- Added daytime and quote of the day services

- Use universal header and remove needless seperate dirs
- Many bugfixes
- Added to build, not yet included in install as it's still in the early stages

Tested in WinXP using both Windows and Linux clients. Not yet tried in ROS,

svn path=/trunk/; revision=18142
This commit is contained in:
Ged Murphy 2005-09-28 22:33:55 +00:00
parent a3ff770ebd
commit 708722cfd9
17 changed files with 267 additions and 125 deletions

View file

@ -1,30 +1,33 @@
<directory name="arp">
<xi:include href="arp/arp.xml" />
<xi:include href="arp/arp.xml" />
</directory>
<directory name="finger">
<xi:include href="finger/finger.xml" />
<xi:include href="finger/finger.xml" />
</directory>
<directory name="ftp">
<xi:include href="ftp/ftp.xml" />
<xi:include href="ftp/ftp.xml" />
</directory>
<directory name="ipconfig">
<xi:include href="ipconfig/ipconfig.xml" />
<xi:include href="ipconfig/ipconfig.xml" />
</directory>
<directory name="netstat">
<xi:include href="netstat/netstat.xml" />
<xi:include href="netstat/netstat.xml" />
</directory>
<directory name="ping">
<xi:include href="ping/ping.xml" />
<xi:include href="ping/ping.xml" />
</directory>
<directory name="route">
<xi:include href="route/route.xml" />
<xi:include href="route/route.xml" />
</directory>
<directory name="tcpsvcs">
<xi:include href="tcpsvcs/tcpsvcs.xml" />
</directory>
<directory name="telnet">
<xi:include href="telnet/telnet.xml" />
<xi:include href="telnet/telnet.xml" />
</directory>
<directory name="tracert">
<xi:include href="tracert/tracert.xml" />
<xi:include href="tracert/tracert.xml" />
</directory>
<directory name="whois">
<xi:include href="whois/whois.xml" />
<xi:include href="whois/whois.xml" />
</directory>

View file

@ -1,8 +1,7 @@
#include <stdio.h>
#include <winsock2.h>
#include <tchar.h>
#include "chargen.h"
#include "../skelserver/skelserver.h"
#include "tcpsvcs.h"
DWORD WINAPI ChargenHandler(VOID* Sock_)
{
@ -10,12 +9,12 @@ DWORD WINAPI ChargenHandler(VOID* Sock_)
SOCKET Sock = (SOCKET)Sock_;
if (!GenerateChars(Sock)) {
_tprintf(_T("Echo incoming packets failed\n"));
_tprintf(_T("Char generation failed\n"));
Retval = 3;
}
_tprintf(_T("Shutting connection down...\n"));
if (ShutdownConnection(Sock)) {
if (ShutdownConnection(Sock, FALSE)) {
_tprintf(_T("Connection is down.\n"));
}
else
@ -23,6 +22,8 @@ DWORD WINAPI ChargenHandler(VOID* Sock_)
_tprintf(_T("Connection shutdown failed\n"));
Retval = 3;
}
_tprintf(_T("Terminating thread\n"));
ExitThread(0);
return Retval;
}
@ -35,6 +36,7 @@ BOOL GenerateChars(SOCKET Sock)
loopIndex; /* line loop */
char ring[END-START];
char *endring;
BOOL bLoop = TRUE;
/* fill ring with printable characters */
for (charIndex=0, i=START; i<=END; charIndex++, i++)
@ -45,7 +47,7 @@ BOOL GenerateChars(SOCKET Sock)
/* where we will start output from */
loopIndex = 0;
while (1)
while (bLoop)
{
/* if the loop index is equal to number of chars previously
* printed, start the loop from the beginning */
@ -56,21 +58,29 @@ BOOL GenerateChars(SOCKET Sock)
charIndex = loopIndex;
for (i=0; i<LINESIZ; i++)
{
SendChar(Sock, ring[charIndex]);
/* FIXME: Should send lines instead of chars to improve efficiency
* TCP will wait until it fills a packet anway before putting on
* the wire, so it's pointless to keep polling send */
if (!SendChar(Sock, ring[charIndex]))
{
return FALSE;
}
/* if current char equal last char, reset */
if (ring[charIndex] == *endring)
charIndex = 0;
else
charIndex++;
}
SendChar(Sock, L'\r');
SendChar(Sock, L'\n');
if (bLoop)
if ((!SendChar(Sock, L'\r')) || (!SendChar(Sock, L'\n')))
return FALSE;
/* increment loop index to start printing from next char in ring */
loopIndex++;
}
return 0;
return TRUE;
}
BOOL SendChar(SOCKET Sock, TCHAR c)
@ -80,25 +90,22 @@ BOOL SendChar(SOCKET Sock, TCHAR c)
SentBytes = 0;
RetVal = send(Sock, &c, sizeof(TCHAR), 0);
if (RetVal > 0) {
/*FIXME: need to establish if peer closes connection,
not just report a socket error */
if (RetVal > 0)
{
SentBytes += RetVal;
return TRUE;
}
else if (RetVal == SOCKET_ERROR) {
else if (RetVal == SOCKET_ERROR)
{
_tprintf(("Socket error\n"));
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;
}
_tprintf(("unknown error\n"));
//WSAGetLastError()
_tprintf(("Connection closed by peer.\n"));
return TRUE;
}

View file

@ -1,8 +0,0 @@
#define START 32
#define END 126
#define LINESIZ 72
#define BUF 1024
DWORD WINAPI ChargenHandler(VOID* Sock_);
BOOL GenerateChars(SOCKET Sock);
BOOL SendChar(SOCKET Sock, CHAR c);

View file

@ -1,9 +0,0 @@
<module name="chargen" type="win32cui" installbase="system32" installname="chargen.exe">
<include base="arp">.</include>
<define name="__USE_W32API" />
<library>kernel32</library>
<library>iphlpapi</library>
<library>ws2_32</library>
<file>chargen/chargen.c</file>
</module>

View file

@ -0,0 +1,46 @@
#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 = 3;
}
_tprintf(_T("Terminating thread\n"));
ExitThread(0);
return 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

@ -1,8 +1,7 @@
#include <stdio.h>
#include <winsock2.h>
#include <tchar.h>
#include "echo.h"
#include "../skelserver/skelserver.h"
#include "tcpsvcs.h"
DWORD WINAPI EchoHandler(VOID* Sock_)
{
@ -15,7 +14,7 @@ DWORD WINAPI EchoHandler(VOID* Sock_)
}
_tprintf(_T("Shutting connection down...\n"));
if (ShutdownConnection(Sock)) {
if (ShutdownConnection(Sock, TRUE)) {
_tprintf(_T("Connection is down.\n"));
}
else
@ -23,6 +22,8 @@ DWORD WINAPI EchoHandler(VOID* Sock_)
_tprintf(_T("Connection shutdown failed\n"));
Retval = 3;
}
_tprintf(_T("Terminating thread\n"));
ExitThread(0);
return Retval;
}
@ -68,4 +69,3 @@ BOOL EchoIncomingPackets(SOCKET Sock)
_tprintf(("Connection closed by peer.\n"));
return TRUE;
}

View file

@ -1,4 +0,0 @@
#define BUF 1024
DWORD WINAPI EchoHandler(VOID* Sock_);
BOOL EchoIncomingPackets(SOCKET Sock);

View file

@ -0,0 +1,56 @@
#include <stdio.h>
#include <winsock2.h>
#include <tchar.h>
#include <time.h>
#include "tcpsvcs.h"
//these need putting in an RC file.
TCHAR Quotes[][MAX_QUOTE_BUF] = {
_T("\"I have a penchant for mischief, property damage, stalking and cheesecake, of course\" - kjk hyperion"),
_T("\"Wow! I fixed a setmenu bug.\" - jimtabor"),
_T("\"if the code is broken though, your free to call it ur own\" - Alex Ionescu"),
_T("\"i don't know about any bug; none exist; ReactOS is prefect\" - filip2307"),
_T("\"if you were kernel code, cutler would rewrite you.\" - Alex Ionescu"),
_T("\"Looks like Hartmut is cleaning out his WC. working copy, that is\" - WaxDragon")
};
DWORD WINAPI QotdHandler(VOID* Sock_)
{
DWORD Retval = 0;
SOCKET Sock;
INT NumOfQuotes;
Sock = (SOCKET)Sock_;
NumOfQuotes = sizeof(Quotes) / MAX_QUOTE_BUF;
SendQuote(Sock, Quotes[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 = 3;
}
_tprintf(_T("Terminating 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

@ -1,8 +1,7 @@
#include <stdio.h>
#include <winsock2.h>
#include <tchar.h>
#include "../tcpsvcs.h"
#include "skelserver.h"
#include "tcpsvcs.h"
DWORD WINAPI StartServer(LPVOID lpParam)
@ -10,9 +9,9 @@ DWORD WINAPI StartServer(LPVOID lpParam)
const TCHAR* HostIP = "127.0.0.1";
DWORD RetVal;
WSADATA wsaData;
PMYDATA pData;
PSERVICES pServices;
pData = (PMYDATA)lpParam;
pServices = (PSERVICES)lpParam;
if ((RetVal = WSAStartup(MAKEWORD(2, 2), &wsaData)) != 0)
{
@ -20,20 +19,22 @@ DWORD WINAPI StartServer(LPVOID lpParam)
return -1;
}
SOCKET ListeningSocket = SetUpListener(HostIP, htons(pData->Port));
SOCKET ListeningSocket = SetUpListener(HostIP, htons(pServices->Port));
if (ListeningSocket == INVALID_SOCKET)
{
_tprintf(_T("error setting up socket\n"));
return 3;
}
printf("Waiting for connections...\n");
_tprintf(_T("Waiting for connections...\n"));
while (1)
{
AcceptConnections(ListeningSocket, pData->Service);
AcceptConnections(ListeningSocket, pServices->Service);
printf("Acceptor restarting...\n");
}
/* won't see this yet as we kill the service */
_tprintf(_T("Detaching Winsock2...\n"));
WSACleanup();
return 0;
}
@ -43,25 +44,21 @@ SOCKET SetUpListener(const char* ServAddr, int Port)
{
SOCKET Sock;
SOCKADDR_IN Server;
DWORD InterfaceAddr = inet_addr(ServAddr);
if (InterfaceAddr != INADDR_NONE)
Sock = socket(AF_INET, SOCK_STREAM, 0);
if (Sock != INVALID_SOCKET)
{
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)
{
Server.sin_family = AF_INET;
Server.sin_addr.s_addr = InterfaceAddr;
Server.sin_port = Port;
if (bind(Sock, (SOCKADDR*)&Server, sizeof(SOCKADDR_IN)) != SOCKET_ERROR)
{
listen(Sock, SOMAXCONN);
return Sock;
}
else
printf("bind() failed\n");
listen(Sock, SOMAXCONN);
return Sock;
}
else
printf("bind() failed\n");
}
return INVALID_SOCKET;
}
@ -83,7 +80,7 @@ VOID AcceptConnections(SOCKET ListeningSocket, LPTHREAD_START_ROUTINE Service)
{
_tprintf(_T("Accepted connection from %s:%d\n"),
inet_ntoa(Client.sin_addr), ntohs(Client.sin_port));
_tprintf(_T("About to create thread\n"));
CreateThread(0, 0, Service, (void*)Sock, 0, &ThreadID);
}
else
@ -94,20 +91,23 @@ VOID AcceptConnections(SOCKET ListeningSocket, LPTHREAD_START_ROUTINE Service)
}
}
BOOL ShutdownConnection(SOCKET Sock)
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. */
while (1)
if (bRec)
{
char ReadBuffer[BUF];
int NewBytes = recv(Sock, ReadBuffer, BUF, 0);
@ -115,8 +115,6 @@ BOOL ShutdownConnection(SOCKET Sock)
return FALSE;
else if (NewBytes != 0)
_tprintf(_T("FYI, received %d unexpected bytes during shutdown\n"), NewBytes);
else
break;
}
/* Close the socket. */

View file

@ -1,7 +0,0 @@
#define BUF 1024
DWORD WINAPI StartServer(LPVOID lpParam);
SOCKET SetUpListener(const char* ServAddr, int Port);
VOID AcceptConnections(SOCKET ListeningSocket, LPTHREAD_START_ROUTINE Service);
BOOL EchoIncomingPackets(SOCKET sd);
BOOL ShutdownConnection(SOCKET Sock);

View file

@ -2,37 +2,49 @@
#include <winsock2.h>
#include <tchar.h>
#include "tcpsvcs.h"
#include "skelserver/skelserver.h"
#include "echo/echo.h"
#include "chargen/chargen.h"
LPTHREAD_START_ROUTINE
ServiceHandler[NUM_SERVICES] = {
EchoHandler,
ChargenHandler,
DaytimeHandler,
NULL,
QotdHandler
};
INT ServicePort[NUM_SERVICES] = {
ECHO_PORT,
CHARGEN_PORT,
DAYTIME_PORT,
DISCARD_PORT,
QOTD_PORT
};
int main(int argc, char *argv[])
{
PMYDATA pData[MAX_THREADS];
DWORD dwThreadId[MAX_THREADS];
HANDLE hThread[MAX_THREADS];
PSERVICES pServices[NUM_SERVICES];
DWORD dwThreadId[NUM_SERVICES];
HANDLE hThread[NUM_SERVICES];
INT i;
/* Create MAX_THREADS worker threads. */
for( i=0; i<MAX_THREADS; i++ )
for( i=0; i<NUM_SERVICES; i++ )
{
/* Allocate memory for thread data. */
pData[i] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MYDATA));
if( pData == NULL )
pServices[i] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SERVICES));
if( pServices[i] == NULL )
ExitProcess(2);
/* Generate unique data for each thread. */
pData[0]->Port = ECHO_PORT;
pData[0]->Service = EchoHandler;
pData[1]->Port = CHARGEN_PORT;
pData[1]->Service = ChargenHandler;
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
pData[i], // argument to thread function
pServices[i], // argument to thread function
0, // use default creation flags
&dwThreadId[i]); // returns the thread identifier
@ -44,14 +56,13 @@ int main(int argc, char *argv[])
}
/* Wait until all threads have terminated. */
WaitForMultipleObjects(MAX_THREADS, hThread, TRUE, INFINITE);
WaitForMultipleObjects(NUM_SERVICES, hThread, TRUE, INFINITE);
/* Close all thread handles upon completion. */
for(i=0; i<MAX_THREADS; i++)
for(i=0; i<NUM_SERVICES; i++)
{
CloseHandle(hThread[i]);
}
return 0;
}

View file

@ -1,13 +1,53 @@
/* default port numbers */
#define ECHO_PORT 7
#define CHARGEN_PORT 19
#define DAYTIME_PORT 13
#define DISCARD_PORT 9
#define QOTD_PORT 17
#define MAX_THREADS 2
#define NUM_SERVICES 6
#define BUF_SIZE 255
#define BUF 1024
typedef struct _MyData {
/* 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 72
/* data structure to pass to threads */
typedef struct _Services {
INT Port;
LPTHREAD_START_ROUTINE Service;
} MYDATA, *PMYDATA;
} SERVICES, *PSERVICES;
/* skelserver functions */
DWORD WINAPI StartServer(LPVOID lpParam);
SOCKET SetUpListener(const char* ServAddr, int Port);
VOID AcceptConnections(SOCKET ListeningSocket, LPTHREAD_START_ROUTINE Service);
BOOL EchoIncomingPackets(SOCKET sd);
BOOL ShutdownConnection(SOCKET Sock, BOOL bRec);
/* chargen functions */
DWORD WINAPI ChargenHandler(VOID* Sock_);
BOOL GenerateChars(SOCKET Sock);
BOOL SendChar(SOCKET Sock, CHAR c);
/* 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 */
/* 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

@ -1,13 +1,15 @@
<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/skelserver.c</file>
<file>echo/echo.c</file>
<file>chargen/chargen.c</file>
</module>
<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>chargen.c</file>
<file>daytime.c</file>
<file>qotd.c</file>
</module>