- 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);