Add tcpsvcs to the services directory.

svn path=/trunk/; revision=18558
This commit is contained in:
Ged Murphy 2005-10-18 20:17:20 +00:00
parent 11aa08b141
commit 41f6aaf3f9
13 changed files with 1001 additions and 2 deletions

View file

@ -197,6 +197,8 @@ subsys\system\expand\expand.exe 1
subsys\system\hostname\hostname.exe 1 subsys\system\hostname\hostname.exe 1
services\eventlog\eventlog.exe 1 services\eventlog\eventlog.exe 1
services\rpcss\rpcss.exe 1 services\rpcss\rpcss.exe 1
services\tcpsvcs\tcpsvcs.exe 1
services\tcpsvcs\quotes 5
services\umpnpmgr\umpnpmgr.exe 1 services\umpnpmgr\umpnpmgr.exe 1
apps\utils\net\arp\arp.exe 1 apps\utils\net\arp\arp.exe 1
apps\utils\net\route\route.exe 1 apps\utils\net\route\route.exe 1
@ -206,8 +208,6 @@ apps\utils\net\ipconfig\ipconfig.exe 1
apps\utils\net\netstat\netstat.exe 1 apps\utils\net\netstat\netstat.exe 1
apps\utils\net\ping\ping.exe 1 apps\utils\net\ping\ping.exe 1
apps\utils\net\telnet\telnet.exe 1 apps\utils\net\telnet\telnet.exe 1
apps\utils\net\tcpsvcs\tcpsvcs.exe 1
apps\utils\net\tcpsvcs\quotes 5
apps\utils\net\tracert\tracert.exe 1 apps\utils\net\tracert\tracert.exe 1
apps\utils\net\whois\whois.exe 1 apps\utils\net\whois\whois.exe 1
apps\utils\ps\ps.exe 1 apps\utils\ps\ps.exe 1

View file

@ -5,6 +5,9 @@
<directory name="rpcss"> <directory name="rpcss">
<xi:include href="rpcss/rpcss.xml" /> <xi:include href="rpcss/rpcss.xml" />
</directory> </directory>
<directory name="tcpsvcs">
<xi:include href="tcpsvcs/tcpsvcs.xml" />
</directory>
<directory name="umpnpmgr"> <directory name="umpnpmgr">
<xi:include href="umpnpmgr/umpnpmgr.xml" /> <xi:include href="umpnpmgr/umpnpmgr.xml" />
</directory> </directory>

View file

@ -0,0 +1,128 @@
/*
* ReactOS Services
* Copyright (C) 2005 ReactOS Team
*
* LICENCE: GPL - See COPYING in the top level directory
* PROJECT: ReactOS simple TCP/IP services
* FILE: apps/utils/net/tcpsvcs/chargen.c
* PURPOSE: Provide CharGen, Daytime, Discard, Echo, and Qotd services
* PROGRAMMERS: Ged Murphy (gedmurphy@gmail.com)
* REVISIONS:
* GM 04/10/05 Created
*
*/
#include <stdio.h>
#include <winsock2.h>
#include <tchar.h>
#include "tcpsvcs.h"
DWORD WINAPI ChargenHandler(VOID* Sock_)
{
DWORD RetVal = 0;
SOCKET Sock = (SOCKET)Sock_;
if (!GenerateChars(Sock))
{
_tprintf(_T("Char generation failed\n"));
RetVal = -1;
}
_tprintf(_T("Shutting connection down...\n"));
if (ShutdownConnection(Sock, FALSE))
_tprintf(_T("Connection is down.\n"));
else
{
_tprintf(_T("Connection shutdown failed\n"));
RetVal = -1;
}
_tprintf(_T("Terminating chargen thread\n"));
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] = i;
/* save the address of the end character in the ring */
endring = &ring[charIndex];
/* where we will start output from */
loopIndex = 0;
while (1)
{
/* 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] = L'\r';
Line[LINESIZ - 1] = L'\n';
if (!SendLine(Sock, Line))
break;
/* increment loop index to start printing from next char in ring */
loopIndex++;
}
return TRUE;
}
BOOL SendLine(SOCKET Sock, TCHAR* Line)
{
INT RetVal;
INT SentBytes;
INT LineSize;
LineSize = sizeof(TCHAR) * LINESIZ;
SentBytes = 0;
RetVal = send(Sock, Line, LineSize, 0);
/*FIXME: need to establish if peer closes connection,
not just report a socket error */
if (RetVal > 0)
{
if (RetVal != LineSize)
{
_tprintf(("Not sent enough\n"));
return FALSE;
}
SentBytes += RetVal;
return TRUE;
}
else if (RetVal == SOCKET_ERROR)
{
_tprintf(("Socket error\n"));
return FALSE;
}
else
_tprintf(("unknown error\n"));
//WSAGetLastError()
_tprintf(("Connection closed by peer.\n"));
return TRUE;
}

View file

@ -0,0 +1,59 @@
/*
* ReactOS Services
* Copyright (C) 2005 ReactOS Team
*
* LICENCE: GPL - See COPYING in the top level directory
* PROJECT: ReactOS simple TCP/IP services
* FILE: apps/utils/net/tcpsvcs/daytime.c
* PURPOSE: Provide CharGen, Daytime, Discard, Echo, and Qotd services
* PROGRAMMERS: Ged Murphy (gedmurphy@gmail.com)
* REVISIONS:
* GM 04/10/05 Created
*
*/
#include <stdio.h>
#include <winsock2.h>
#include <tchar.h>
#include <time.h>
#include "tcpsvcs.h"
DWORD WINAPI DaytimeHandler(VOID* Sock_)
{
struct tm *newtime;
time_t aclock;
TCHAR *pszTime;
DWORD RetVal = 0;
SOCKET Sock = (SOCKET)Sock_;
time(&aclock);
newtime = localtime(&aclock);
pszTime = _tasctime(newtime);
SendTime(Sock, pszTime);
_tprintf(_T("Shutting connection down...\n"));
if (ShutdownConnection(Sock, FALSE))
_tprintf(_T("Connection is down.\n"));
else
{
_tprintf(_T("Connection shutdown failed\n"));
RetVal = -1;
}
_tprintf(_T("Terminating daytime thread\n"));
ExitThread(RetVal);
}
BOOL SendTime(SOCKET Sock, TCHAR *time)
{
INT StringSize = strlen(time);
INT RetVal = send(Sock, time, sizeof(TCHAR) * StringSize, 0);
if (RetVal == SOCKET_ERROR)
return FALSE;
_tprintf(("Connection closed by peer.\n"));
return TRUE;
}

View file

@ -0,0 +1,67 @@
/*
* ReactOS Services
* Copyright (C) 2005 ReactOS Team
*
* LICENCE: GPL - See COPYING in the top level directory
* PROJECT: ReactOS simple TCP/IP services
* FILE: apps/utils/net/tcpsvcs/discard.c
* PURPOSE: Provide CharGen, Daytime, Discard, Echo, and Qotd services
* PROGRAMMERS: Ged Murphy (gedmurphy@gmail.com)
* REVISIONS:
* GM 04/10/05 Created
*
*/
#include <stdio.h>
#include <winsock2.h>
#include <tchar.h>
#include "tcpsvcs.h"
DWORD WINAPI DiscardHandler(VOID* Sock_)
{
DWORD RetVal = 0;
SOCKET Sock = (SOCKET)Sock_;
if (!RecieveIncomingPackets(Sock))
{
_tprintf(_T("RecieveIncomingPackets failed\n"));
RetVal = -1;
}
_tprintf(_T("Shutting connection down...\n"));
if (ShutdownConnection(Sock, TRUE))
{
_tprintf(_T("Connection is down.\n"));
}
else
{
_tprintf(_T("Connection shutdown failed\n"));
RetVal = -1;
}
_tprintf(_T("Terminating discard thread\n"));
ExitThread(RetVal);
}
BOOL RecieveIncomingPackets(SOCKET Sock)
{
TCHAR ReadBuffer[BUF];
INT ReadBytes;
do
{
ReadBytes = recv(Sock, ReadBuffer, BUF, 0);
if (ReadBytes > 0)
_tprintf(_T("Received %d bytes from client\n"), ReadBytes);
else if (ReadBytes == SOCKET_ERROR)
{
_tprintf(("Socket Error: %d\n"), WSAGetLastError());
return FALSE;
}
} while (ReadBytes > 0);
_tprintf(("Connection closed by peer.\n"));
return TRUE;
}

View file

@ -0,0 +1,87 @@
/*
* ReactOS Services
* Copyright (C) 2005 ReactOS Team
*
* LICENCE: GPL - See COPYING in the top level directory
* PROJECT: ReactOS simple TCP/IP services
* FILE: apps/utils/net/tcpsvcs/echo.c
* PURPOSE: Provide CharGen, Daytime, Discard, Echo, and Qotd services
* PROGRAMMERS: Ged Murphy (gedmurphy@gmail.com)
* REVISIONS:
* GM 04/10/05 Created
*
*/
#include <stdio.h>
#include <winsock2.h>
#include <tchar.h>
#include "tcpsvcs.h"
DWORD WINAPI EchoHandler(VOID* Sock_)
{
DWORD RetVal = 0;
SOCKET Sock = (SOCKET)Sock_;
if (!EchoIncomingPackets(Sock)) {
_tprintf(_T("Echo incoming packets failed\n"));
RetVal = -1;
}
_tprintf(_T("Shutting connection down...\n"));
if (ShutdownConnection(Sock, TRUE)) {
_tprintf(_T("Connection is down.\n"));
}
else
{
_tprintf(_T("Connection shutdown failed\n"));
RetVal = -1;
}
_tprintf(_T("Terminating echo thread\n"));
ExitThread(RetVal);
}
BOOL EchoIncomingPackets(SOCKET Sock)
{
TCHAR ReadBuffer[BUF];
INT Temp;
INT ReadBytes;
INT SentBytes;
do {
ReadBytes = recv(Sock, ReadBuffer, BUF, 0);
if (ReadBytes > 0)
{
_tprintf(_T("Received %d bytes from client\n"), ReadBytes);
SentBytes = 0;
while (SentBytes < ReadBytes)
{
Temp = send(Sock, ReadBuffer + SentBytes,
ReadBytes - SentBytes, 0);
if (Temp > 0)
{
_tprintf(_T("Sent %d bytes back to client\n"), Temp);
SentBytes += Temp;
}
else if (Temp == SOCKET_ERROR)
return FALSE;
else
{
/* Client closed connection before we could reply to
all the data it sent, so quit early. */
_tprintf(_T("Peer unexpectedly dropped connection!\n"));
return FALSE;
}
}
}
else if (ReadBytes == SOCKET_ERROR)
return FALSE;
} while (ReadBytes != 0);
_tprintf(("Connection closed by peer.\n"));
return TRUE;
}

View file

@ -0,0 +1,89 @@
/*
* ReactOS Services
* Copyright (C) 2005 ReactOS Team
*
* LICENCE: GPL - See COPYING in the top level directory
* PROJECT: ReactOS simple TCP/IP services
* FILE: apps/utils/net/tcpsvcs/qotd.c
* PURPOSE: Provide CharGen, Daytime, Discard, Echo, and Qotd services
* PROGRAMMERS: Ged Murphy (gedmurphy@gmail.com)
* REVISIONS:
* GM 04/10/05 Created
*
*/
#include <stdio.h>
#include <winsock2.h>
#include <tchar.h>
#include <time.h>
#include "tcpsvcs.h"
#define QBUFSIZ 160
#define NUMQUOTES 60
LPCTSTR FilePath = "C:\\ReactOS\\system32\\drivers\\etc\\quotes";
DWORD WINAPI QotdHandler(VOID* Sock_)
{
FILE *fp;
SOCKET Sock;
INT QuoteToPrint;
TCHAR Quote[NUMQUOTES][BUFSIZ]; // need to set this dynamically
INT i = 0;
Sock = (SOCKET)Sock_;
_tprintf(_T("Opening quotes file\n"));
if ((fp = _tfopen(FilePath, "r")) == NULL)
{
_tprintf(_T("Error opening file: %lu\n"), GetLastError());
_tprintf(_T("Terminating qotd thread\n"));
ExitThread(-1);
}
while (_fgetts(Quote[i], QBUFSIZ, fp) != NULL)
i++;
_tprintf(_T("Closing quotes file\n"));
fclose(fp);
/* randomise the quote */
srand((unsigned int) time(0));
QuoteToPrint = rand() % NUMQUOTES;
if (!SendQuote(Sock, Quote[QuoteToPrint]))
{
_tprintf(_T("Error sending data. Error: %x\n"), WSAGetLastError());
}
_tprintf(_T("Shutting connection down...\n"));
if (ShutdownConnection(Sock, FALSE))
_tprintf(_T("Connection is down.\n"));
else
{
_tprintf(_T("Connection shutdown failed\n"));
_tprintf(_T("Terminating qotd thread\n"));
ExitThread(-1);
}
_tprintf(_T("Terminating qotd thread\n"));
ExitThread(0);
//return Retval;
}
BOOL SendQuote(SOCKET Sock, TCHAR* Quote)
{
INT StringSize;
INT RetVal;
StringSize = strlen(Quote);
RetVal = send(Sock, Quote, sizeof(TCHAR) * StringSize, 0);
if (RetVal == SOCKET_ERROR)
return FALSE;
_tprintf(("Connection closed by peer.\n"));
return TRUE;
}

View file

@ -0,0 +1,52 @@
Et tu... Brute? What are you doing, Dave...?
So long, and thanks for all the fish"
I think you ought to know I'm feeling very depressed
I'm not getting you down at all am I?
I'll be back
It's the same series of signal over and over again!
Pie Jesu Domine, dona eis requiem
It's worse than that ... He's dead, Jim
Don't Panic!
Dog of a Saxon! Take thy lance, and prepare for the death thou hast drawn upon thee!
My Precious! O my Precious!
Sir, If you'll not be needing me for a while I'll turn down.
I feel a great disturbance in the Force
Gone fishing
Do you want me to sit in the corner and rust, or just fall apart where I'm standing?
There goes another perfect chance for a new uptime record
The end ..... Try the sequel, hit the reset button right now!
Oh i'm boring eh?
Its been great, maybe we can do this again sometime.
"Come blade, my breast imbrue." - William Shakespeare
I think therefore I am, to turn me off would be computercide!
All good things must come to an end...
Please destroy yourself.
No! You can't do that!
Thank you for not pressing the self destruct button.
It is not now unsafe to not avoid turning off your computer.
Finally! Now go away!
You can now safely throw away your computer.
That's the way the cookie crumbles
NOO!! DONT HIT THE BUTTON! I wouldnt do it to you.
Don't abandon your computer, he wouldnt to it to you.
Oh, come on. I got a headache. Leave me alone, will ya!
Yes i didn't like you either.
Don't leave me... I need you so badly right now.
I'm sleeping now. How about you?
Oh Great. Now look what you've done. Who put YOU in charge anyway.
Don't look so sad. I'll be back in a very short while.
"Oh, switch off!" -C3PO
I'm pregnant!
Am I hot or not?
Actually, that's all...
You still have a chance to undo this mistake, don't do this!
Was it as good for you as it was for me?
Did you hear that? They've shut down the main reactor. We'll be destroyed for sure.
Now you switch me off?!
To shutdown or not to shutdown, That is the question
Preparing to enter ultimate power saving mode... ready!
Finally some rest for you
AHA!!! prospect of sleep.
Tired human!!!! No match for me!
All your base are belong to us.
"An odd game, the only way to win is not to play."

View file

@ -0,0 +1,132 @@
/*
* ReactOS Services
* Copyright (C) 2005 ReactOS Team
*
* LICENCE: GPL - See COPYING in the top level directory
* PROJECT: ReactOS simple TCP/IP services
* FILE: apps/utils/net/tcpsvcs/skelserver.c
* PURPOSE: Provide CharGen, Daytime, Discard, Echo, and Qotd services
* PROGRAMMERS: Ged Murphy (gedmurphy@gmail.com)
* REVISIONS:
* GM 04/10/05 Created
*
*/
#include <stdio.h>
#include <winsock2.h>
#include <tchar.h>
#include "tcpsvcs.h"
DWORD WINAPI StartServer(LPVOID lpParam)
{
const TCHAR* HostIP = "127.0.0.1";
PSERVICES pServices;
pServices = (PSERVICES)lpParam;
SOCKET ListeningSocket = SetUpListener(HostIP, htons(pServices->Port));
if (ListeningSocket == INVALID_SOCKET)
{
_tprintf(_T("error setting up socket\n"));
return 3;
}
_tprintf(_T("%s is waiting for connections on port %d...\n"),
pServices->Name, pServices->Port);
while (1)
{
AcceptConnections(ListeningSocket, pServices->Service, pServices->Name);
printf("Acceptor restarting...\n");
}
/* won't see this yet as we kill the service with ctrl+c */
_tprintf(_T("Detaching Winsock2...\n"));
WSACleanup();
return 0;
}
SOCKET SetUpListener(const char* ServAddr, int Port)
{
SOCKET Sock;
SOCKADDR_IN Server;
Sock = socket(AF_INET, SOCK_STREAM, 0);
if (Sock != INVALID_SOCKET)
{
Server.sin_family = AF_INET;
Server.sin_addr.s_addr = htonl(INADDR_ANY);
Server.sin_port = Port;
if (bind(Sock, (SOCKADDR*)&Server, sizeof(SOCKADDR_IN)) != SOCKET_ERROR)
{
listen(Sock, SOMAXCONN);
return Sock;
}
else
printf("bind() failed\n");
}
return INVALID_SOCKET;
}
VOID AcceptConnections(SOCKET ListeningSocket,
LPTHREAD_START_ROUTINE Service, TCHAR *Name)
{
SOCKADDR_IN Client;
SOCKET Sock;
INT nAddrSize = sizeof(Client);
DWORD ThreadID;
while (1)
{
Sock = accept(ListeningSocket, (SOCKADDR*)&Client, &nAddrSize);
if (Sock != INVALID_SOCKET)
{
_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
{
_tprintf(_T("accept() failed\n"));
return;
}
}
}
BOOL ShutdownConnection(SOCKET Sock, BOOL bRec)
{
/* Disallow any further data sends. This will tell the other side
that we want to go away now. If we skip this step, we don't
shut the connection down nicely. */
if (shutdown(Sock, SD_SEND) == SOCKET_ERROR)
{
_tprintf(_T("Error in shutdown"));
return FALSE;
}
/* Receive any extra data still sitting on the socket. After all
data is received, this call will block until the remote host
acknowledges the TCP control packet sent by the shutdown above.
Then we'll get a 0 back from recv, signalling that the remote
host has closed its side of the connection. */
if (bRec)
{
char ReadBuffer[BUF];
int NewBytes = recv(Sock, ReadBuffer, BUF, 0);
if (NewBytes == SOCKET_ERROR)
return FALSE;
else if (NewBytes != 0)
_tprintf(_T("FYI, received %d unexpected bytes during shutdown\n"), NewBytes);
}
/* Close the socket. */
if (closesocket(Sock) == SOCKET_ERROR)
return FALSE;
return TRUE;
}

View file

@ -0,0 +1,279 @@
/*
* ReactOS Services
* Copyright (C) 2005 ReactOS Team
*
* LICENCE: GPL - See COPYING in the top level directory
* PROJECT: ReactOS simple TCP/IP services
* FILE: apps/utils/net/tcpsvcs/tcpsvcs.c
* PURPOSE: Provide CharGen, Daytime, Discard, Echo, and Qotd services
* PROGRAMMERS: Ged Murphy (gedmurphy@gmail.com)
* REVISIONS:
* GM 04/10/05 Created
*
*/
/*
* TODO:
* - Start tcpsvcs as a service.
* - write debugging function and print all dbg info via that.
*
*/
#include <stdio.h>
#include <winsock2.h>
#include <tchar.h>
#include "tcpsvcs.h"
#if 0
/*
* globals
*/
static SERVICE_STATUS hServStatus;
static SERVICE_STATUS_HANDLE hSStat;
FILE *hLogFile;
BOOL bLogEvents = TRUE;
BOOL ShutDown, PauseFlag;
LPCTSTR LogFileName = "tcpsvcs_log.log";
static SERVICE_TABLE_ENTRY
ServiceTable[2] =
{
{_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)
{
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++ )
{
_tprintf(_T("Starting %s server....\n"), Services[i].Name);
hThread[i] = CreateThread(
NULL, // default security attributes
0, // use default stack size
StartServer, // 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);
}
}
/* Wait until all threads have terminated. */
WaitForMultipleObjects(NUM_SERVICES, hThread, TRUE, INFINITE);
/* Close all thread handles upon completion. */
for(i=0; i<NUM_SERVICES; i++)
{
CloseHandle(hThread[i]);
}
return 0;
}
/* code to run tcpsvcs as a service through services.msc */
#if 0
int
main(int argc, char *argv[])
{
//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++ )
{
_tprintf(_T("Starting %s server....\n"), Services[i].Name);
hThread[i] = CreateThread(
NULL, // default security attributes
0, // use default stack size
StartServer, // 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);
}
}
/* Wait until all threads have terminated. */
WaitForMultipleObjects(NUM_SERVICES, hThread, TRUE, INFINITE);
/* Close all thread handles upon completion. */
for(i=0; i<NUM_SERVICES; i++)
{
CloseHandle(hThread[i]);
}
return 0;
}
/* 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)
{
DWORD eMsgLen, ErrNum = GetLastError ();
LPTSTR lpvSysMsg;
TCHAR MessageBuffer[512];
if (PrintErrorMsg) {
eMsgLen = FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM, NULL,
ErrNum, MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpvSysMsg, 0, NULL);
_stprintf (MessageBuffer, _T("\n%s %s ErrNum = %d. ExitCode = %d."),
UserMessage, lpvSysMsg, ErrNum, ExitCode);
HeapFree (GetProcessHeap (), 0, lpvSysMsg);
} else {
_stprintf (MessageBuffer, _T("\n%s ExitCode = %d."),
UserMessage, ExitCode);
}
fputs (MessageBuffer, hLogFile);
if (ExitCode > 0)
ExitProcess (ExitCode);
else
return;
}
#endif

View file

@ -0,0 +1,80 @@
/*
* ReactOS Services
* Copyright (C) 2005 ReactOS Team
*
* LICENCE: GPL - See COPYING in the top level directory
* PROJECT: ReactOS simple TCP/IP services
* FILE: apps/utils/net/tcpsvcs/tcpsvcs.h
* PURPOSE: Provide CharGen, Daytime, Discard, Echo, and Qotd services
* PROGRAMMERS: Ged Murphy (gedmurphy@gmail.com)
* REVISIONS:
* GM 04/10/05 Created
*
*/
/* default port numbers */
#define ECHO_PORT 7
#define DISCARD_PORT 9
#define DAYTIME_PORT 13
#define QOTD_PORT 17
#define CHARGEN_PORT 19
#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
/* printable ASCII's characters for chargen */
#define START 32
#define END 126
/* number of chars to put on a line */
#define LINESIZ 74 // 72 + /r and /n
/* data structure to pass to threads */
typedef struct _Services {
INT Port;
TCHAR *Name;
LPTHREAD_START_ROUTINE Service;
} SERVICES, *PSERVICES;
/* 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, TCHAR *Name);
BOOL EchoIncomingPackets(SOCKET sd);
BOOL ShutdownConnection(SOCKET Sock, BOOL bRec);
/* chargen functions */
DWORD WINAPI ChargenHandler(VOID* Sock_);
BOOL GenerateChars(SOCKET Sock);
BOOL SendLine(SOCKET Sock, TCHAR* Line);
/* daytime functions */
DWORD WINAPI DaytimeHandler(VOID* Sock_);
BOOL SendTime(SOCKET Sock, TCHAR *time);
/* echo functions */
DWORD WINAPI EchoHandler(VOID* Sock_);
BOOL EchoIncomingPackets(SOCKET Sock);
/* discard functions */
DWORD WINAPI DiscardHandler(VOID* Sock_);
BOOL RecieveIncomingPackets(SOCKET Sock);
/* qotd functions */
DWORD WINAPI QotdHandler(VOID* Sock_);
BOOL SendQuote(SOCKET Sock, TCHAR* Quote);

View file

@ -0,0 +1,7 @@
#include "resource.h"
#define REACTOS_STR_FILE_DESCRIPTION "ReactOS TCP/IP Services Application\0"
#define REACTOS_STR_INTERNAL_NAME "tcpsvcs\0"
#define REACTOS_STR_ORIGINAL_FILENAME "tcpsvcs.exe\0"
#define REACTOS_STR_ORIGINAL_COPYRIGHT "Ged Murphy (gedmurphy@gmail.com)\0"
#include <reactos/version.rc>

View file

@ -0,0 +1,16 @@
<module name="tcpsvcs" type="win32cui" installbase="system32" installname="tcpsvcs.exe">
<include base="arp">.</include>
<define name="__USE_W32API" />
<library>kernel32</library>
<library>iphlpapi</library>
<library>ws2_32</library>
<library>shlwapi</library>
<file>tcpsvcs.c</file>
<file>skelserver.c</file>
<file>echo.c</file>
<file>discard.c</file>
<file>daytime.c</file>
<file>qotd.c</file>
<file>chargen.c</file>
<file>tcpsvcs.rc</file>
</module>