- Don't call winsock initialiser for each seperate server thread - Add more code for tcpsvcs to be controled via services. Still #if 0'd out until fully implemented. - Make server more informative with what is happening. (this info will be output to a log file once implemented as a service. Modified: trunk/reactos/apps/utils/net/tcpsvcs/chargen.c Modified: trunk/reactos/apps/utils/net/tcpsvcs/daytime.c Modified: trunk/reactos/apps/utils/net/tcpsvcs/discard.c Modified: trunk/reactos/apps/utils/net/tcpsvcs/echo.c Modified: trunk/reactos/apps/utils/net/tcpsvcs/qotd.c Modified: trunk/reactos/apps/utils/net/tcpsvcs/skelserver.c Modified: trunk/reactos/apps/utils/net/tcpsvcs/tcpsvcs.c Modified: trunk/reactos/apps/utils/net/tcpsvcs/tcpsvcs.h _____
Modified: trunk/reactos/apps/utils/net/tcpsvcs/chargen.c --- trunk/reactos/apps/utils/net/tcpsvcs/chargen.c 2005-10-03 14:42:34 UTC (rev 18247) +++ trunk/reactos/apps/utils/net/tcpsvcs/chargen.c 2005-10-03 18:32:30 UTC (rev 18248) @@ -22,7 +22,7 @@
_tprintf(_T("Connection shutdown failed\n")); Retval = 3; } - _tprintf(_T("Terminating thread\n")); + _tprintf(_T("Terminating chargen thread\n")); ExitThread(0);
return Retval; _____
Modified: trunk/reactos/apps/utils/net/tcpsvcs/daytime.c --- trunk/reactos/apps/utils/net/tcpsvcs/daytime.c 2005-10-03 14:42:34 UTC (rev 18247) +++ trunk/reactos/apps/utils/net/tcpsvcs/daytime.c 2005-10-03 18:32:30 UTC (rev 18248) @@ -26,7 +26,7 @@
_tprintf(_T("Connection shutdown failed\n")); Retval = 3; } - _tprintf(_T("Terminating thread\n")); + _tprintf(_T("Terminating daytime thread\n")); ExitThread(0);
return Retval; _____
Modified: trunk/reactos/apps/utils/net/tcpsvcs/discard.c --- trunk/reactos/apps/utils/net/tcpsvcs/discard.c 2005-10-03 14:42:34 UTC (rev 18247) +++ trunk/reactos/apps/utils/net/tcpsvcs/discard.c 2005-10-03 18:32:30 UTC (rev 18248) @@ -24,7 +24,7 @@
_tprintf(_T("Connection shutdown failed\n")); Retval = 3; } - _tprintf(_T("Terminating thread\n")); + _tprintf(_T("Terminating discard thread\n")); ExitThread(0);
return Retval; _____
Modified: trunk/reactos/apps/utils/net/tcpsvcs/echo.c --- trunk/reactos/apps/utils/net/tcpsvcs/echo.c 2005-10-03 14:42:34 UTC (rev 18247) +++ trunk/reactos/apps/utils/net/tcpsvcs/echo.c 2005-10-03 18:32:30 UTC (rev 18248) @@ -22,7 +22,7 @@
_tprintf(_T("Connection shutdown failed\n")); Retval = 3; } - _tprintf(_T("Terminating thread\n")); + _tprintf(_T("Terminating echo thread\n")); ExitThread(0);
return Retval; _____
Modified: trunk/reactos/apps/utils/net/tcpsvcs/qotd.c --- trunk/reactos/apps/utils/net/tcpsvcs/qotd.c 2005-10-03 14:42:34 UTC (rev 18247) +++ trunk/reactos/apps/utils/net/tcpsvcs/qotd.c 2005-10-03 18:32:30 UTC (rev 18248) @@ -33,7 +33,7 @@
_tprintf(_T("Connection shutdown failed\n")); Retval = 3; } - _tprintf(_T("Terminating thread\n")); + _tprintf(_T("Terminating qotd thread\n")); ExitThread(0);
return Retval; _____
Modified: trunk/reactos/apps/utils/net/tcpsvcs/skelserver.c --- trunk/reactos/apps/utils/net/tcpsvcs/skelserver.c 2005-10-03 14:42:34 UTC (rev 18247) +++ trunk/reactos/apps/utils/net/tcpsvcs/skelserver.c 2005-10-03 18:32:30 UTC (rev 18248) @@ -7,18 +7,10 @@
DWORD WINAPI StartServer(LPVOID lpParam) { const TCHAR* HostIP = "127.0.0.1"; - DWORD RetVal; - WSADATA wsaData; PSERVICES pServices;
pServices = (PSERVICES)lpParam;
- if ((RetVal = WSAStartup(MAKEWORD(2, 2), &wsaData)) != 0) - { - _tprintf(_T("WSAStartup() failed : %lu\n"), RetVal); - return -1; - } - SOCKET ListeningSocket = SetUpListener(HostIP, htons(pServices->Port)); if (ListeningSocket == INVALID_SOCKET) { @@ -26,10 +18,11 @@ return 3; }
- _tprintf(_T("Waiting for connections...\n")); + _tprintf(_T("%s is waiting for connections on port %d...\n"), + pServices->Name, pServices->Port); while (1) { - AcceptConnections(ListeningSocket, pServices->Service); + AcceptConnections(ListeningSocket, pServices->Service, pServices->Name); printf("Acceptor restarting...\n"); }
@@ -66,7 +59,8 @@
-VOID AcceptConnections(SOCKET ListeningSocket, LPTHREAD_START_ROUTINE Service) +VOID AcceptConnections(SOCKET ListeningSocket, + LPTHREAD_START_ROUTINE Service, TCHAR *Name) { SOCKADDR_IN Client; SOCKET Sock; @@ -78,9 +72,9 @@ Sock = accept(ListeningSocket, (SOCKADDR*)&Client, &nAddrSize); if (Sock != INVALID_SOCKET) { - _tprintf(_T("Accepted connection from %s:%d\n"), - inet_ntoa(Client.sin_addr), ntohs(Client.sin_port)); - _tprintf(_T("About to create thread\n")); + _tprintf(_T("Accepted connection to %s server from %s:%d\n"), + Name, inet_ntoa(Client.sin_addr), ntohs(Client.sin_port)); + _tprintf(_T("Creating new thread for %s\n"), Name); CreateThread(0, 0, Service, (void*)Sock, 0, &ThreadID); } else _____
Modified: trunk/reactos/apps/utils/net/tcpsvcs/tcpsvcs.c --- trunk/reactos/apps/utils/net/tcpsvcs/tcpsvcs.c 2005-10-03 14:42:34 UTC (rev 18247) +++ trunk/reactos/apps/utils/net/tcpsvcs/tcpsvcs.c 2005-10-03 18:32:30 UTC (rev 18248) @@ -3,68 +3,67 @@
#include <tchar.h> #include "tcpsvcs.h"
-static -LPTHREAD_START_ROUTINE -ServiceHandler[NUM_SERVICES] = -{ - EchoHandler, - DiscardHandler, - DaytimeHandler, - QotdHandler, - ChargenHandler -}; +#if 0 +/* + * globals + */ +static SERVICE_STATUS hServStatus; +static SERVICE_STATUS_HANDLE hSStat; +FILE *hLogFile; +BOOL bLogEvents = TRUE; +BOOL ShutDown, PauseFlag; +LPTSTR LogFileName = "tcpsvcs_log.txt";
-static int -ServicePort[NUM_SERVICES] = -{ - ECHO_PORT, - DISCARD_PORT, - DAYTIME_PORT, - QOTD_PORT, - CHARGEN_PORT -}; - -#if 0 -static -SERVICE_TABLE_ENTRY +static SERVICE_TABLE_ENTRY ServiceTable[2] = { - {TEXT("tcpsvcs"), ServiceMain}, + {_T("tcpsvcs"), ServiceMain}, {NULL, NULL} }; #endif
+static SERVICES +Services[NUM_SERVICES] = +{ + {ECHO_PORT, _T("Echo"), EchoHandler}, + {DISCARD_PORT, _T("Discard"), DiscardHandler}, + {DAYTIME_PORT, _T("Daytime"), DaytimeHandler}, + {QOTD_PORT, _T("QOTD"), QotdHandler}, + {CHARGEN_PORT, _T("Chargen"), ChargenHandler} +}; + + int main(void) { - PSERVICES pServices[NUM_SERVICES]; DWORD dwThreadId[NUM_SERVICES]; HANDLE hThread[NUM_SERVICES]; + WSADATA wsaData; + DWORD RetVal; INT i;
+ if ((RetVal = WSAStartup(MAKEWORD(2, 2), &wsaData)) != 0) + { + _tprintf(_T("WSAStartup() failed : %lu\n"), RetVal); + return -1; + } + /* Create MAX_THREADS worker threads. */ for( i=0; i<NUM_SERVICES; i++ ) { - /* Allocate memory for thread data. */ - pServices[i] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SERVICES)); + _tprintf(_T("Starting %s server....\n"), Services[i].Name);
- if( pServices[i] == NULL ) - ExitProcess(2); - - /* Generate unique data for each thread. */ - pServices[i]->Service = ServiceHandler[i]; - pServices[i]->Port = ServicePort[i]; - hThread[i] = CreateThread( NULL, // default security attributes 0, // use default stack size StartServer, // thread function - pServices[i], // argument to thread function + &Services[i], // argument to thread function 0, // use default creation flags &dwThreadId[i]); // returns the thread identifier
/* Check the return value for success. */ if (hThread[i] == NULL) { + _tprintf(_T("Failed to start %s server....\n"), Services[i].Name); ExitProcess(i); } } @@ -80,39 +79,134 @@ return 0; }
+ + +/* code to run tcpsvcs as a service */ #if 0 -static VOID CALLBACK -ServiceMain(DWORD argc, LPTSTR *argv) +int +main(int argc, char *argv[]) { - PSERVICES pServices[NUM_SERVICES]; + //DPRINT("tcpsvcs: main() started. See tcpsvcs_log.txt for info\n"); + + if (!StartServiceCtrlDispatcher(ServiceTable)) + _tprintf(_T("failed to start the service control dispatcher\n")); + + //DPRINT("tcpsvcs: main() done\n"); + + return 0; +} + + +static VOID WINAPI +ServiceMain(DWORD argc, LPTSTR argv[]) +{ + DWORD i; + + hLogFile = fopen(LogFileName, _T("w+")); + if (hLogFile == NULL) + return; + + LogEvent(_T("Entering ServiceMain"), 0, FALSE); + + hServStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; + hServStatus.dwCurrentState = SERVICE_START_PENDING; + hServStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | + SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_PAUSE_CONTINUE; + hServStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR; + hServStatus.dwServiceSpecificExitCode = 0; + hServStatus.dwCheckPoint = 0; + hServStatus.dwWaitHint = 2*CS_TIMEOUT; + + hSStat = RegisterServiceCtrlHandler("tcpsvcs", ServerCtrlHandler); + if (hSStat == 0) + LogEvent(_T("Failed to register service\n"), 100, TRUE); + + LogEvent(_T("Control handler registered successfully"), 0, FALSE); + SetServiceStatus (hSStat, &hServStatus); + LogEvent(_T("Service status set to SERVICE_START_PENDING"), 0, FALSE); + + if (CreateServers() != 0) + { + hServStatus.dwCurrentState = SERVICE_STOPPED; + hServStatus.dwServiceSpecificExitCode = 1; + SetServiceStatus(hSStat, &hServStatus); + return; + } + + LogEvent(_T("Service threads shut down. Set SERVICE_STOPPED status"), 0, FALSE); + /* We will only return here when the ServiceSpecific function + completes, indicating system shutdown. */ + UpdateStatus (SERVICE_STOPPED, 0); + LogEvent(_T("Service status set to SERVICE_STOPPED"), 0, FALSE); + fclose(hLogFile); /* Clean up everything, in general */ + return; + +} + +VOID WINAPI +ServerCtrlHandler(DWORD Control) +{ + switch (Control) + { + case SERVICE_CONTROL_SHUTDOWN: /* fall through */ + case SERVICE_CONTROL_STOP: + ShutDown = TRUE; + UpdateStatus(SERVICE_STOP_PENDING, -1); + break; + case SERVICE_CONTROL_PAUSE: + PauseFlag = TRUE; + break; + case SERVICE_CONTROL_CONTINUE: + PauseFlag = FALSE; + break; + case SERVICE_CONTROL_INTERROGATE: + break; + default: + if (Control > 127 && Control < 256) /* user defined */ + break; + } + UpdateStatus(-1, -1); /* increment checkpoint */ + return; +} + + +void UpdateStatus (int NewStatus, int Check) +/* Set a new service status and checkpoint (either specific value or increment) */ +{ + if (Check < 0 ) hServStatus.dwCheckPoint++; + else hServStatus.dwCheckPoint = Check; + if (NewStatus >= 0) hServStatus.dwCurrentState = NewStatus; + if (!SetServiceStatus (hSStat, &hServStatus)) + LogEvent (_T("Cannot set service status"), 101, TRUE); + return; +} + +INT +CreateServers() +{ DWORD dwThreadId[NUM_SERVICES]; HANDLE hThread[NUM_SERVICES]; INT i;
+ UpdateStatus(-1, -1); /* increment checkpoint */ + /* Create MAX_THREADS worker threads. */ for( i=0; i<NUM_SERVICES; i++ ) { - /* Allocate memory for thread data. */ - pServices[i] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SERVICES)); + _tprintf(_T("Starting %s server....\n"), Services[i].Name);
- if( pServices[i] == NULL ) - ExitProcess(2); - - /* Generate unique data for each thread. */ - pServices[i]->Service = ServiceHandler[i]; - pServices[i]->Port = ServicePort[i]; - hThread[i] = CreateThread( NULL, // default security attributes 0, // use default stack size StartServer, // thread function - pServices[i], // argument to thread function + &Services[i], // argument to thread function 0, // use default creation flags &dwThreadId[i]); // returns the thread identifier
/* Check the return value for success. */ if (hThread[i] == NULL) { + _tprintf(_T("Failed to start %s server....\n"), Services[i].Name); ExitProcess(i); } } @@ -125,20 +219,42 @@ { CloseHandle(hThread[i]); } - + return 0; }
-int -main(int argc, char *argv[]) + +/* LogEvent is similar to the ReportError function used elsewhere + For a service, however, we ReportEvent rather than write to standard + error. Eventually, this function should go into the utility + library. */ +VOID +LogEvent (LPCTSTR UserMessage, DWORD ExitCode, BOOL PrintErrorMsg) { - DPRINT("tcpsvcs: main() started\n"); + DWORD eMsgLen, ErrNum = GetLastError (); + LPTSTR lpvSysMsg; + TCHAR MessageBuffer[512];
- StartServiceCtrlDispatcher(ServiceTable); + if (PrintErrorMsg) { + eMsgLen = FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM, NULL, + ErrNum, MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR)&lpvSysMsg, 0, NULL);
- DPRINT("Umpnpmgr: main() done\n"); + _stprintf (MessageBuffer, _T("\n%s %s ErrNum = %d. ExitCode = %d."), + UserMessage, lpvSysMsg, ErrNum, ExitCode); + HeapFree (GetProcessHeap (), 0, lpvSysMsg); + /* Explained in Chapter 6. */ + } else { + _stprintf (MessageBuffer, _T("\n%s ExitCode = %d."), + UserMessage, ExitCode); + }
- ExitThread(0); + fputs (MessageBuffer, hLogFile);
- return 0; + if (ExitCode > 0) + ExitProcess (ExitCode); + else + return; } + #endif _____
Modified: trunk/reactos/apps/utils/net/tcpsvcs/tcpsvcs.h --- trunk/reactos/apps/utils/net/tcpsvcs/tcpsvcs.h 2005-10-03 14:42:34 UTC (rev 18247) +++ trunk/reactos/apps/utils/net/tcpsvcs/tcpsvcs.h 2005-10-03 18:32:30 UTC (rev 18248) @@ -5,9 +5,10 @@
#define QOTD_PORT 17 #define CHARGEN_PORT 19
-#define NUM_SERVICES 6 +#define NUM_SERVICES 5 #define BUF_SIZE 255 #define BUF 1024 +#define CS_TIMEOUT 1000
/* RFC865 states no more than 512 chars per line */ #define MAX_QUOTE_BUF 512 @@ -22,16 +23,24 @@ /* data structure to pass to threads */ typedef struct _Services { INT Port; + TCHAR *Name; LPTHREAD_START_ROUTINE Service; } SERVICES, *PSERVICES;
-/* tcpsvcs functions */ -//static VOID CALLBACK ServiceMain(DWORD argc, LPTSTR *argv);
+/* tcpsvcs functions * / +static VOID WINAPI ServiceMain(DWORD argc, LPTSTR argv[]); +VOID WINAPI ServerCtrlHandler(DWORD control); +INT CreateServers(VOID); +VOID LogEvent (LPCTSTR UserMessage, DWORD ExitCode, BOOL PrintErrorMsg); +void UpdateStatus (int NewStatus, int Check); +*/ + /* skelserver functions */ DWORD WINAPI StartServer(LPVOID lpParam); SOCKET SetUpListener(const char* ServAddr, int Port); -VOID AcceptConnections(SOCKET ListeningSocket, LPTHREAD_START_ROUTINE Service); +VOID AcceptConnections(SOCKET ListeningSocket, + LPTHREAD_START_ROUTINE Service, TCHAR *Name); BOOL EchoIncomingPackets(SOCKET sd); BOOL ShutdownConnection(SOCKET Sock, BOOL bRec);