- Rewrite the service handler and parts of the main control thread. The rest will be rewritten bit by bit.

- tcpsvcs now cleanly starts serves and stops in Windows.

svn path=/trunk/; revision=27552
This commit is contained in:
Ged Murphy 2007-07-09 23:13:09 +00:00
parent 2c13c59b51
commit 4216adf631
8 changed files with 343 additions and 376 deletions

View file

@ -11,84 +11,6 @@
extern BOOL bShutDown; extern BOOL bShutDown;
DWORD WINAPI ChargenHandler(VOID* Sock_)
{
INT RetVal = 0;
SOCKET Sock = (SOCKET)Sock_;
if (!GenerateChars(Sock))
{
LogEvent(_T("Chargen: Char generation failed\n"), 0, FALSE);
RetVal = 1;
}
LogEvent(_T("Chargen: Shutting connection down...\n"), 0, FALSE);
if (ShutdownConnection(Sock, FALSE))
LogEvent(_T("Chargen: Connection is down.\n"), 0, FALSE);
else
{
LogEvent(_T("Chargen: Connection shutdown failed\n"), 0, FALSE);
RetVal = 1;
}
LogEvent(_T("Chargen: Terminating thread\n"), 0, FALSE);
ExitThread(RetVal);
}
BOOL GenerateChars(SOCKET Sock)
{
int i;
int charIndex; /* internal loop */
int loopIndex; /* line loop */
char ring[END-START];
char *endring;
char Line[LINESIZ];
/* fill ring with printable characters */
for (charIndex=0, i=START; i<=END; charIndex++, i++)
ring[charIndex] = (char)i;
/* save the address of the end character in the ring */
endring = &ring[charIndex];
/* where we will start output from */
loopIndex = 0;
while (! bShutDown)
{
/* if the loop index is equal to the last char,
* start the loop again from the beginning */
if (loopIndex == END-START)
loopIndex = 0;
/* start printing from char controled by loopIndex */
charIndex = loopIndex;
for (i=0; i < LINESIZ - 2; i++)
{
Line[i] = ring[charIndex];
if (ring[charIndex] == *endring)
charIndex = 0;
else
charIndex++;
}
Line[LINESIZ - 2] = '\r';
Line[LINESIZ - 1] = '\n';
if (! SendLine(Sock, Line))
break;
/* increment loop index to start printing from next char in ring */
loopIndex++;
}
if (bShutDown)
return FALSE;
else
return TRUE;
}
BOOL SendLine(SOCKET Sock, char* Line) BOOL SendLine(SOCKET Sock, char* Line)
{ {
INT RetVal; INT RetVal;
@ -123,3 +45,79 @@ BOOL SendLine(SOCKET Sock, char* Line)
LogEvent(_T("Chargen: Connection closed by peer.\n"), 0, FALSE); LogEvent(_T("Chargen: Connection closed by peer.\n"), 0, FALSE);
return TRUE; return TRUE;
} }
BOOL GenerateChars(SOCKET Sock)
{
int i;
int charIndex; /* internal loop */
int loopIndex; /* line loop */
char ring[ASCII_END - ASCII_START];
char *endring;
char Line[LINESIZ];
/* fill ring with printable characters */
for (charIndex=0, i=ASCII_START; i<=ASCII_END; charIndex++, i++)
ring[charIndex] = (char)i;
/* save the address of the end character in the ring */
endring = &ring[charIndex];
/* where we will start output from */
loopIndex = 0;
while (! bShutDown)
{
/* if the loop index is equal to the last char,
* start the loop again from the beginning */
if (loopIndex == ASCII_END-ASCII_START)
loopIndex = 0;
/* start printing from char controled by loopIndex */
charIndex = loopIndex;
for (i=0; i < LINESIZ - 2; i++)
{
Line[i] = ring[charIndex];
if (ring[charIndex] == *endring)
charIndex = 0;
else
charIndex++;
}
Line[LINESIZ - 2] = '\r';
Line[LINESIZ - 1] = '\n';
if (! SendLine(Sock, Line))
break;
/* increment loop index to start printing from next char in ring */
loopIndex++;
}
if (bShutDown)
return FALSE;
else
return TRUE;
}
DWORD WINAPI ChargenHandler(VOID* Sock_)
{
INT RetVal = 0;
SOCKET Sock = (SOCKET)Sock_;
if (!GenerateChars(Sock))
{
LogEvent(_T("Chargen: Char generation failed\n"), 0, FALSE);
RetVal = 1;
}
LogEvent(_T("Chargen: Shutting connection down...\n"), 0, FALSE);
if (ShutdownConnection(Sock, FALSE))
LogEvent(_T("Chargen: Connection is down.\n"), 0, FALSE);
else
{
LogEvent(_T("Chargen: Connection shutdown failed\n"), 0, FALSE);
RetVal = 1;
}
LogEvent(_T("Chargen: Terminating thread\n"), 0, FALSE);
ExitThread(RetVal);
}

View file

@ -9,6 +9,19 @@
#include "tcpsvcs.h" #include "tcpsvcs.h"
BOOL SendTime(SOCKET Sock, CHAR *time)
{
INT StringSize = (INT)strlen(time);
INT RetVal = send(Sock, time, sizeof(CHAR) * StringSize, 0);
if (RetVal == SOCKET_ERROR)
return FALSE;
LogEvent(_T("DayTime: Connection closed by peer.\n"), 0, FALSE);
return TRUE;
}
DWORD WINAPI DaytimeHandler(VOID* Sock_) DWORD WINAPI DaytimeHandler(VOID* Sock_)
{ {
struct tm *newtime; struct tm *newtime;
@ -35,16 +48,3 @@ DWORD WINAPI DaytimeHandler(VOID* Sock_)
LogEvent(_T("DayTime: Terminating thread\n"), 0, FALSE); LogEvent(_T("DayTime: Terminating thread\n"), 0, FALSE);
ExitThread(RetVal); ExitThread(RetVal);
} }
BOOL SendTime(SOCKET Sock, CHAR *time)
{
INT StringSize = (INT)strlen(time);
INT RetVal = send(Sock, time, sizeof(CHAR) * StringSize, 0);
if (RetVal == SOCKET_ERROR)
return FALSE;
LogEvent(_T("DayTime: Connection closed by peer.\n"), 0, FALSE);
return TRUE;
}

View file

@ -11,32 +11,6 @@
extern BOOL bShutDown; extern BOOL bShutDown;
DWORD WINAPI DiscardHandler(VOID* Sock_)
{
DWORD RetVal = 0;
SOCKET Sock = (SOCKET)Sock_;
if (!RecieveIncomingPackets(Sock))
{
LogEvent(_T("Discard: RecieveIncomingPackets failed\n"), 0, FALSE);
RetVal = 1;
}
LogEvent(_T("Discard: Shutting connection down...\n"), 0, FALSE);
if (ShutdownConnection(Sock, TRUE))
LogEvent(_T("Discard: Connection is down.\n"), 0, FALSE);
else
{
LogEvent(_T("Discard: Connection shutdown failed\n"), 0, FALSE);
RetVal = 1;
}
LogEvent(_T("Discard: Terminating thread\n"), 0, FALSE);
ExitThread(RetVal);
}
BOOL RecieveIncomingPackets(SOCKET Sock) BOOL RecieveIncomingPackets(SOCKET Sock)
{ {
char ReadBuffer[BUF]; char ReadBuffer[BUF];
@ -64,3 +38,27 @@ BOOL RecieveIncomingPackets(SOCKET Sock)
return TRUE; return TRUE;
} }
DWORD WINAPI DiscardHandler(VOID* Sock_)
{
DWORD RetVal = 0;
SOCKET Sock = (SOCKET)Sock_;
if (!RecieveIncomingPackets(Sock))
{
LogEvent(_T("Discard: RecieveIncomingPackets failed\n"), 0, FALSE);
RetVal = 1;
}
LogEvent(_T("Discard: Shutting connection down...\n"), 0, FALSE);
if (ShutdownConnection(Sock, TRUE))
LogEvent(_T("Discard: Connection is down.\n"), 0, FALSE);
else
{
LogEvent(_T("Discard: Connection shutdown failed\n"), 0, FALSE);
RetVal = 1;
}
LogEvent(_T("Discard: Terminating thread\n"), 0, FALSE);
ExitThread(RetVal);
}

View file

@ -11,32 +11,6 @@
extern BOOL bShutDown; extern BOOL bShutDown;
DWORD WINAPI EchoHandler(VOID* Sock_)
{
DWORD RetVal = 0;
SOCKET Sock = (SOCKET)Sock_;
if (!EchoIncomingPackets(Sock)) {
LogEvent(_T("Echo: EchoIncomingPackets failed\n"), 0, FALSE);
RetVal = 1;
}
LogEvent(_T("Echo: Shutting connection down...\n"), 0, FALSE);
if (ShutdownConnection(Sock, TRUE))
LogEvent(_T("Echo: Connection is down\n"), 0, FALSE);
else
{
LogEvent(_T("Echo: Connection shutdown failed\n"), 0, FALSE);
RetVal = 1;
}
LogEvent(_T("Echo: Terminating thread\n"), 0, FALSE);
ExitThread(RetVal);
}
BOOL EchoIncomingPackets(SOCKET Sock) BOOL EchoIncomingPackets(SOCKET Sock)
{ {
char ReadBuffer[BUF]; char ReadBuffer[BUF];
@ -88,3 +62,27 @@ BOOL EchoIncomingPackets(SOCKET Sock)
return TRUE; return TRUE;
} }
DWORD WINAPI EchoHandler(VOID* Sock_)
{
DWORD RetVal = 0;
SOCKET Sock = (SOCKET)Sock_;
if (!EchoIncomingPackets(Sock)) {
LogEvent(_T("Echo: EchoIncomingPackets failed\n"), 0, FALSE);
RetVal = 1;
}
LogEvent(_T("Echo: Shutting connection down...\n"), 0, FALSE);
if (ShutdownConnection(Sock, TRUE))
LogEvent(_T("Echo: Connection is down\n"), 0, FALSE);
else
{
LogEvent(_T("Echo: Connection shutdown failed\n"), 0, FALSE);
RetVal = 1;
}
LogEvent(_T("Echo: Terminating thread\n"), 0, FALSE);
ExitThread(RetVal);
}

View file

@ -13,6 +13,22 @@
LPCTSTR FilePath = _T("\\drivers\\etc\\quotes"); /* 19 chars */ LPCTSTR FilePath = _T("\\drivers\\etc\\quotes"); /* 19 chars */
BOOL SendQuote(SOCKET Sock, char* Quote)
{
INT StringSize;
INT RetVal;
StringSize = (INT)strlen(Quote);
RetVal = send(Sock, Quote, sizeof(char) * StringSize, 0);
if (RetVal == SOCKET_ERROR)
return FALSE;
LogEvent(_T("QOTD: Connection closed by peer\n"), 0, FALSE);
return TRUE;
}
DWORD WINAPI QotdHandler(VOID* Sock_) DWORD WINAPI QotdHandler(VOID* Sock_)
{ {
FILE *fp; FILE *fp;
@ -74,19 +90,3 @@ DWORD WINAPI QotdHandler(VOID* Sock_)
ExitThread(0); ExitThread(0);
} }
BOOL SendQuote(SOCKET Sock, char* Quote)
{
INT StringSize;
INT RetVal;
StringSize = (INT)strlen(Quote);
RetVal = send(Sock, Quote, sizeof(char) * StringSize, 0);
if (RetVal == SOCKET_ERROR)
return FALSE;
LogEvent(_T("QOTD: Connection closed by peer\n"), 0, FALSE);
return TRUE;
}

View file

@ -12,34 +12,8 @@
extern BOOL bShutDown; extern BOOL bShutDown;
extern BOOL bPause; extern BOOL bPause;
DWORD WINAPI StartServer(LPVOID lpParam) static SOCKET
{ SetUpListener(USHORT Port)
SOCKET ListeningSocket;
PSERVICES pServices;
TCHAR buf[256];
pServices = (PSERVICES)lpParam;
//DebugBreak();
ListeningSocket = SetUpListener(htons(pServices->Port));
if (ListeningSocket == INVALID_SOCKET)
{
LogEvent(_T("Socket error when setting up listener\n"), 0, TRUE);
return 3;
}
_stprintf(buf, _T("%s is waiting for connections on port %d...\n"),
pServices->Name, pServices->Port);
LogEvent(buf, 0, FALSE);
if (! bShutDown)
AcceptConnections(ListeningSocket, pServices->Service, pServices->Name);
ExitThread(0);
}
SOCKET SetUpListener(USHORT Port)
{ {
SOCKET Sock; SOCKET Sock;
SOCKADDR_IN Server; SOCKADDR_IN Server;
@ -59,6 +33,7 @@ SOCKET SetUpListener(USHORT Port)
LogEvent(_T("bind() failed\n"), 0, TRUE); LogEvent(_T("bind() failed\n"), 0, TRUE);
} }
return INVALID_SOCKET; return INVALID_SOCKET;
} }
@ -74,8 +49,10 @@ typedef struct _WORKER_THREAD {
*/ */
VOID AcceptConnections(SOCKET ListeningSocket, static VOID
LPTHREAD_START_ROUTINE Service, TCHAR *Name) AcceptConnections(SOCKET ListeningSocket,
LPTHREAD_START_ROUTINE Service,
TCHAR *Name)
{ {
SOCKADDR_IN Client; SOCKADDR_IN Client;
SOCKET Sock; SOCKET Sock;
@ -87,8 +64,6 @@ VOID AcceptConnections(SOCKET ListeningSocket,
TCHAR buf[256]; TCHAR buf[256];
INT TimeOut = 2000; // 2 seconds INT TimeOut = 2000; // 2 seconds
//DebugBreak();
/* set timeout values */ /* set timeout values */
TimeVal.tv_sec = TimeOut / 1000; TimeVal.tv_sec = TimeOut / 1000;
TimeVal.tv_usec = TimeOut % 1000; TimeVal.tv_usec = TimeOut % 1000;
@ -144,7 +119,9 @@ VOID AcceptConnections(SOCKET ListeningSocket,
} }
} }
BOOL ShutdownConnection(SOCKET Sock, BOOL bRec) BOOL
ShutdownConnection(SOCKET Sock,
BOOL bRec)
{ {
TCHAR buf[256]; TCHAR buf[256];
@ -181,3 +158,36 @@ BOOL ShutdownConnection(SOCKET Sock, BOOL bRec)
return TRUE; return TRUE;
} }
DWORD WINAPI
StartServer(LPVOID lpParam)
{
SOCKET ListeningSocket;
PSERVICES pServices;
TCHAR buf[256];
pServices = (PSERVICES)lpParam;
ListeningSocket = SetUpListener(htons(pServices->Port));
if (ListeningSocket == INVALID_SOCKET)
{
LogEvent(_T("Socket error when setting up listener"), 0, TRUE);
return 3;
}
_stprintf(buf,
_T("%s is waiting for connections on port %d"),
pServices->Name,
pServices->Port);
LogEvent(buf, 0, FALSE);
if (!bShutDown)
AcceptConnections(ListeningSocket, pServices->Service, pServices->Name);
_stprintf(buf,
_T("Exiting %s thread"),
pServices->Name);
LogEvent(buf, 0, FALSE);
ExitThread(0);
}

View file

@ -3,37 +3,22 @@
* LICENSE: GPL - See COPYING in the top level directory * LICENSE: GPL - See COPYING in the top level directory
* FILE: /base/services/tcpsvcs/tcpsvcs.c * FILE: /base/services/tcpsvcs/tcpsvcs.c
* PURPOSE: Provide CharGen, Daytime, Discard, Echo, and Qotd services * PURPOSE: Provide CharGen, Daytime, Discard, Echo, and Qotd services
* COPYRIGHT: Copyright 2005 - 2006 Ged Murphy <gedmurphy@gmail.com> * COPYRIGHT: Copyright 2005 - 2007 Ged Murphy <gedmurphy@reactos.org>
* *
*/ */
/*
* TODO:
* - fix bug when terminating chargen server
* - log info in the event logger (when it's implemented)
*/
#include "tcpsvcs.h" #include "tcpsvcs.h"
//#define NDEBUG #define DEBUG
//#include <debug.h>
volatile BOOL bShutDown = FALSE;
/* volatile BOOL bPause = FALSE;
* globals
*/
VOID WINAPI ServiceMain(DWORD argc, LPTSTR argv[]);
static SERVICE_STATUS hServStatus; static SERVICE_STATUS hServStatus;
static SERVICE_STATUS_HANDLE hSStat; static SERVICE_STATUS_HANDLE hSStat;
FILE *hLogFile; LPCTSTR LogFileName = _T("C:\\tcpsvcs_log.log");
BOOL bShutDown = FALSE;
BOOL bPause = FALSE;
LPCTSTR LogFileName = _T("\\tcpsvcs_log.log");
LPTSTR ServiceName = _T("Simp Tcp"); LPTSTR ServiceName = _T("Simp Tcp");
//LPTSTR DisplayName = _T("Simple TCP/IP Services");
static SERVICES static SERVICES
Services[NUM_SERVICES] = Services[NUM_SERVICES] =
@ -45,86 +30,121 @@ Services[NUM_SERVICES] =
{CHARGEN_PORT, _T("Chargen"), ChargenHandler} {CHARGEN_PORT, _T("Chargen"), ChargenHandler}
}; };
VOID
int LogEvent(LPCTSTR UserMessage,
main(void) DWORD ExitCode,
BOOL PrintErrorMsg)
{ {
SERVICE_TABLE_ENTRY ServiceTable[] = #ifdef DEBUG
DWORD eMsgLen;
DWORD ErrNum = GetLastError();
LPTSTR lpvSysMsg;
TCHAR MessageBuffer[512];
FILE *hLogFile = NULL;
hLogFile = _tfopen(LogFileName, _T("a"));
if (hLogFile == NULL) return;
if (PrintErrorMsg)
{ {
{ServiceName, ServiceMain}, eMsgLen = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
{NULL, NULL} NULL,
}; ErrNum,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpvSysMsg,
0,
NULL);
//DPRINT("Starting tcpsvcs service. See \system32%s for logs\n", LogFileName); _stprintf(MessageBuffer,
_T("\n%s %s ErrNum = %lu ExitCode = %lu"),
UserMessage,
lpvSysMsg,
ErrNum,
ExitCode);
if (! StartServiceCtrlDispatcher(ServiceTable)) HeapFree(GetProcessHeap(),
LogEvent(_T("failed to start the service control dispatcher\n"), -1, TRUE); 0,
lpvSysMsg);
//DPRINT("Shutdown tcpsvcs service\n");
return 0;
} }
else
{
_stprintf(MessageBuffer,
_T("\n%s"),
UserMessage);
}
_fputts(MessageBuffer, hLogFile);
fclose(hLogFile);
#endif
if (ExitCode > 0)
ExitProcess(ExitCode);
else
return;
}
VOID
UpdateStatus(DWORD NewStatus,
DWORD Check)
{
TCHAR szSet[50];
if (Check > 0)
hServStatus.dwCheckPoint += Check;
else
hServStatus.dwCheckPoint = Check;
if (NewStatus > 0)
hServStatus.dwCurrentState = NewStatus;
_sntprintf(szSet, 49, _T("setting service to 0x%lu, CheckPoint %lu"), NewStatus, hServStatus.dwCheckPoint);
LogEvent(szSet, 0, FALSE);
if (!SetServiceStatus(hSStat, &hServStatus))
LogEvent(_T("Cannot set service status"), 101, TRUE);
return;
}
VOID WINAPI VOID WINAPI
ServiceMain(DWORD argc, LPTSTR argv[]) ServiceMain(DWORD argc, LPTSTR argv[])
{ {
TCHAR LogFilePath[MAX_PATH + 17]; LogEvent(_T("Starting service. First log entry."), 0, FALSE);
LogEvent (_T("Entering ServiceMain."), 0, FALSE);
if(! GetSystemDirectory(LogFilePath, MAX_PATH))
return;
_tcsncat(LogFilePath, LogFileName, 17);
hLogFile = _tfopen(LogFilePath, _T("a+"));
if (hLogFile == NULL)
{
TCHAR buf[300];
_sntprintf(buf, 300, _T("Could not open log file: %s\n"), LogFilePath);
MessageBox(NULL, buf, NULL, MB_OK);
return;
}
LogEvent(_T("Entering ServiceMain\n"), 0, FALSE);
hServStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; hServStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
hServStatus.dwCurrentState = SERVICE_START_PENDING; hServStatus.dwCurrentState = SERVICE_STOPPED;
hServStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | hServStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_PAUSE_CONTINUE;
SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_PAUSE_CONTINUE;
hServStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR; hServStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
hServStatus.dwServiceSpecificExitCode = NO_ERROR; hServStatus.dwServiceSpecificExitCode = 0;
hServStatus.dwCheckPoint = 0; hServStatus.dwCheckPoint = 0;
hServStatus.dwWaitHint = 2 * CS_TIMEOUT; hServStatus.dwWaitHint = 2 * CS_TIMEOUT;
hSStat = RegisterServiceCtrlHandler(ServiceName, ServerCtrlHandler); hSStat = RegisterServiceCtrlHandler(ServiceName, ServerCtrlHandler);
if (hSStat == 0) if (hSStat == 0)
LogEvent(_T("Failed to register service\n"), -1, TRUE); LogEvent(_T("Failed to register service\n"), 100, TRUE);
LogEvent(_T("Control handler registered successfully\n"), 0, FALSE); LogEvent(_T("Control handler registered successfully"), 0, FALSE);
SetServiceStatus (hSStat, &hServStatus); UpdateStatus(SERVICE_START_PENDING, 1);
LogEvent(_T("Service status set to SERVICE_START_PENDING\n"), 0, FALSE); LogEvent(_T("Service status set to SERVICE_START_PENDING"), 0, FALSE);
if (CreateServers() != 0) if (CreateServers() != 0)
{ {
hServStatus.dwCurrentState = SERVICE_STOPPED;
hServStatus.dwServiceSpecificExitCode = 1; hServStatus.dwServiceSpecificExitCode = 1;
SetServiceStatus(hSStat, &hServStatus); UpdateStatus(SERVICE_STOPPED, 0);
return; return;
} }
LogEvent(_T("Service threads shut down. Set SERVICE_STOPPED status\n"), 0, FALSE); 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); UpdateStatus(SERVICE_STOPPED, 0);
LogEvent(_T("Service status set to SERVICE_STOPPED\n"), 0, FALSE); LogEvent(_T("Service status set to SERVICE_STOPPED\n"), 0, FALSE);
LogEvent(_T("Leaving ServiceMain\n"), 0, FALSE); LogEvent(_T("Leaving ServiceMain\n"), 0, FALSE);
fclose(hLogFile);
return; return;
} }
VOID WINAPI VOID WINAPI
@ -132,48 +152,39 @@ ServerCtrlHandler(DWORD Control)
{ {
switch (Control) switch (Control)
{ {
case SERVICE_CONTROL_SHUTDOWN: /* fall through */ case SERVICE_CONTROL_SHUTDOWN:
case SERVICE_CONTROL_STOP: case SERVICE_CONTROL_STOP:
LogEvent(_T("stopping service\n"), 0, FALSE); LogEvent(_T("\nSetting the service to SERVICE_STOP_PENDING"), 0, FALSE);
InterlockedExchange((LONG *)&bShutDown, TRUE); InterlockedExchange((LONG *)&bShutDown, TRUE);
UpdateStatus(SERVICE_STOP_PENDING, -1); hServStatus.dwWin32ExitCode = 0;
hServStatus.dwWaitHint = 0;
UpdateStatus(SERVICE_STOP_PENDING, 1);
break; break;
case SERVICE_CONTROL_PAUSE: /* not yet implemented */ case SERVICE_CONTROL_PAUSE: /* not yet implemented */
LogEvent(_T("pausing service\n"), 0, FALSE); LogEvent(_T("Setting the service to SERVICE_PAUSED"), 0, FALSE);
InterlockedExchange((LONG *)&bPause, TRUE); InterlockedExchange((LONG *)&bPause, TRUE);
UpdateStatus(SERVICE_PAUSED, 0);
break; break;
case SERVICE_CONTROL_CONTINUE: case SERVICE_CONTROL_CONTINUE:
LogEvent(_T("continuing service\n"), 0, FALSE); LogEvent(_T("Setting the service to SERVICE_RUNNING"), 0, FALSE);
InterlockedExchange((LONG *)&bPause, FALSE); InterlockedExchange((LONG *)&bPause, FALSE);
UpdateStatus(SERVICE_RUNNING, 0);
break; break;
case SERVICE_CONTROL_INTERROGATE: case SERVICE_CONTROL_INTERROGATE:
break; break;
default: default:
if (Control > 127 && Control < 256) /* user defined */ if (Control > 127 && Control < 256) /* user defined */
break; 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\n"), -1, TRUE);
return; return;
} }
INT INT
CreateServers() CreateServers()
{ {
@ -191,86 +202,64 @@ CreateServers()
return -1; return -1;
} }
UpdateStatus(-1, -1); /* increment checkpoint */ UpdateStatus(0, 1); /* increment checkpoint */
LogEvent(_T("Creating server Threads\n"), 0, FALSE); LogEvent(_T("\nCreating server Threads"), 0, FALSE);
/* Create MAX_THREADS worker threads. */ /* Create worker threads. */
for(i = 0; i < NUM_SERVICES; i++) for(i = 0; i < NUM_SERVICES; i++)
{ {
_stprintf(buf, _T("Starting %s server....\n"), Services[i].Name); _stprintf(buf, _T("Starting %s server"), Services[i].Name);
LogEvent(buf, 0, FALSE); LogEvent(buf, 0, FALSE);
hThread[i] = CreateThread( hThread[i] = CreateThread(NULL, // default security attributes
NULL, // default security attributes
0, // use default stack size 0, // use default stack size
StartServer, // thread function StartServer, // thread function
&Services[i], // argument to thread function &Services[i], // argument to thread function
0, // use default creation flags 0, // use default creation flags
&dwThreadId[i]); // returns the thread identifier &dwThreadId[i]); // returns the thread identifier
/* Check the return value for success. */
if (hThread[i] == NULL) if (hThread[i] == NULL)
{ {
_stprintf(buf, _T("Failed to start %s server....\n"), Services[i].Name); _stprintf(buf, _T("\nFailed to start %s server\n"), Services[i].Name);
/* don't exit process via LogEvent. We want to exit via the server /* don't exit process via LogEvent. We want to exit via the server
* which failed to start, which could mean i=0 */ * which failed to start, which could mean i=0 */
LogEvent(buf, 0, TRUE); LogEvent(buf, 0, TRUE);
ExitProcess(i);
}
} }
LogEvent(_T("setting service status to running\n"), 0, FALSE); UpdateStatus(0, 1); /* increment checkpoint */
}
LogEvent(_T("setting service status to running"), 0, FALSE);
UpdateStatus(SERVICE_RUNNING, 0); UpdateStatus(SERVICE_RUNNING, 0);
/* Wait until all threads have terminated. */ /* Wait until all threads have terminated. */
WaitForMultipleObjects(NUM_SERVICES, hThread, TRUE, INFINITE); WaitForMultipleObjects(NUM_SERVICES, hThread, TRUE, INFINITE);
/* Close all thread handles upon completion. */
for(i = 0; i < NUM_SERVICES; i++) for(i = 0; i < NUM_SERVICES; i++)
{ {
CloseHandle(hThread[i]); CloseHandle(hThread[i]);
} }
LogEvent(_T("Detaching Winsock2...\n"), 0, FALSE); LogEvent(_T("Detaching Winsock2"), 0, FALSE);
WSACleanup(); WSACleanup();
return 0; return 0;
} }
int _tmain (int argc, LPTSTR argv [])
/* This is a temperary log system until our eventlog is in place */
VOID
LogEvent (LPCTSTR UserMessage, INT ExitCode, BOOL PrintErrorMsg)
{ {
DWORD eMsgLen, ErrNum = GetLastError (); SERVICE_TABLE_ENTRY ServiceTable[] =
LPTSTR lpvSysMsg;
TCHAR MessageBuffer[1024];
if (PrintErrorMsg)
{ {
eMsgLen = FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | {ServiceName, ServiceMain},
FORMAT_MESSAGE_FROM_SYSTEM, NULL, {NULL, NULL }
ErrNum, MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), };
(LPTSTR)&lpvSysMsg, 0, NULL);
_sntprintf(MessageBuffer, 1024, _T("%s %s ErrNum = %lu. ExitCode = %d."), remove(LogFileName);
UserMessage, lpvSysMsg, ErrNum, ExitCode);
HeapFree(GetProcessHeap (), 0, lpvSysMsg);
}
else
{
_sntprintf(MessageBuffer, 1024, _T("%s"), UserMessage);
}
_fputts(MessageBuffer, hLogFile); if (!StartServiceCtrlDispatcher(ServiceTable))
LogEvent(_T("failed to start the service control dispatcher\n"), 100, TRUE);
if (ExitCode != 0) return 0;
ExitProcess(ExitCode);
else
return;
} }

View file

@ -1,12 +1,6 @@
/* #ifdef _MSC_VER
* PROJECT: ReactOS simple TCP/IP services #define _CRT_SECURE_NO_DEPRECATE 1
* LICENSE: GPL - See COPYING in the top level directory #endif
* FILE: /base/services/tcpsvcs/tcpsvcs.h
* PURPOSE: Provide CharGen, Daytime, Discard, Echo, and Qotd services
* COPYRIGHT: Copyright 2005 - 2006 Ged Murphy <gedmurphy@gmail.com>
*
*/
#include <stdio.h> #include <stdio.h>
#include <winsock2.h> #include <winsock2.h>
#include <tchar.h> #include <tchar.h>
@ -28,8 +22,8 @@
#define MAX_QUOTE_BUF 512 #define MAX_QUOTE_BUF 512
/* printable ASCII's characters for chargen */ /* printable ASCII's characters for chargen */
#define START 32 #define ASCII_START 32
#define END 126 #define ASCII_END 126
/* number of chars to put on a line */ /* number of chars to put on a line */
#define LINESIZ 74 // 72 + /r and /n #define LINESIZ 74 // 72 + /r and /n
@ -42,38 +36,18 @@ typedef struct _Services {
} SERVICES, *PSERVICES; } SERVICES, *PSERVICES;
/* tcpsvcs functions */ /* tcpsvcs functions */
//static VOID WINAPI ServiceMain(DWORD argc, LPTSTR argv[]);
VOID WINAPI ServerCtrlHandler(DWORD control); VOID WINAPI ServerCtrlHandler(DWORD control);
INT CreateServers(VOID); INT CreateServers(VOID);
VOID LogEvent (LPCTSTR UserMessage, INT ExitCode, BOOL PrintErrorMsg); VOID LogEvent(LPCTSTR UserMessage, DWORD ExitCode, BOOL PrintErrorMsg);
void UpdateStatus (int NewStatus, int Check); void UpdateStatus(DWORD NewStatus, DWORD Check);
/* skelserver functions */ /* skelserver functions */
DWORD WINAPI StartServer(LPVOID lpParam); DWORD WINAPI StartServer(LPVOID lpParam);
SOCKET SetUpListener(USHORT Port);
VOID AcceptConnections(SOCKET ListeningSocket,
LPTHREAD_START_ROUTINE Service, TCHAR *Name);
BOOL EchoIncomingPackets(SOCKET sd);
BOOL ShutdownConnection(SOCKET Sock, BOOL bRec); BOOL ShutdownConnection(SOCKET Sock, BOOL bRec);
/* chargen functions */ /* server thread handlers */
DWORD WINAPI ChargenHandler(VOID* Sock_); DWORD WINAPI ChargenHandler(VOID* Sock_);
BOOL GenerateChars(SOCKET Sock);
BOOL SendLine(SOCKET Sock, char* Line);
/* daytime functions */
DWORD WINAPI DaytimeHandler(VOID* Sock_); DWORD WINAPI DaytimeHandler(VOID* Sock_);
BOOL SendTime(SOCKET Sock, char *time);
/* echo functions */
DWORD WINAPI EchoHandler(VOID* Sock_); DWORD WINAPI EchoHandler(VOID* Sock_);
BOOL EchoIncomingPackets(SOCKET Sock);
/* discard functions */
DWORD WINAPI DiscardHandler(VOID* Sock_); DWORD WINAPI DiscardHandler(VOID* Sock_);
BOOL RecieveIncomingPackets(SOCKET Sock);
/* qotd functions */
DWORD WINAPI QotdHandler(VOID* Sock_); DWORD WINAPI QotdHandler(VOID* Sock_);
BOOL SendQuote(SOCKET Sock, char* Quote);