mirror of
https://github.com/reactos/reactos.git
synced 2024-08-28 06:08:23 +00:00
Start to implement the beginneings of tcpsvcs.exe. Just ideas at the moment, subject to change.
Working code for basic echo and chargen included. Tested in Windows from both Windows and Linux clients Run from cmd, not incorporated into services.exe at the moment Builds ok, but not included into build system just yet. svn path=/trunk/; revision=18129
This commit is contained in:
parent
1d982cb8e9
commit
6c01ff3c32
104
reactos/apps/utils/net/tcpsvcs/chargen/chargen.c
Normal file
104
reactos/apps/utils/net/tcpsvcs/chargen/chargen.c
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <winsock2.h>
|
||||||
|
#include <tchar.h>
|
||||||
|
#include "chargen.h"
|
||||||
|
#include "../skelserver/skelserver.h"
|
||||||
|
|
||||||
|
DWORD WINAPI ChargenHandler(VOID* Sock_)
|
||||||
|
{
|
||||||
|
DWORD Retval = 0;
|
||||||
|
SOCKET Sock = (SOCKET)Sock_;
|
||||||
|
|
||||||
|
if (!GenerateChars(Sock)) {
|
||||||
|
_tprintf(_T("Echo incoming packets failed\n"));
|
||||||
|
Retval = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
_tprintf(_T("Shutting connection down...\n"));
|
||||||
|
if (ShutdownConnection(Sock)) {
|
||||||
|
_tprintf(_T("Connection is down.\n"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_tprintf(_T("Connection shutdown failed\n"));
|
||||||
|
Retval = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BOOL GenerateChars(SOCKET Sock)
|
||||||
|
{
|
||||||
|
int i,
|
||||||
|
charIndex, /* internal loop */
|
||||||
|
loopIndex; /* line loop */
|
||||||
|
char ring[END-START];
|
||||||
|
char *endring;
|
||||||
|
|
||||||
|
/* fill ring with printable characters */
|
||||||
|
for (charIndex=0, i=START; i<=END; charIndex++, i++)
|
||||||
|
ring[charIndex] = i;
|
||||||
|
/* establish 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 number of chars previously
|
||||||
|
* printed, start the loop from the beginning */
|
||||||
|
if (loopIndex == END-START)
|
||||||
|
loopIndex = 0;
|
||||||
|
|
||||||
|
/* start printing from char controled by loopIndex */
|
||||||
|
charIndex = loopIndex;
|
||||||
|
for (i=0; i<LINESIZ; i++)
|
||||||
|
{
|
||||||
|
SendChar(Sock, ring[charIndex]);
|
||||||
|
/* if current char equal last char, reset */
|
||||||
|
if (ring[charIndex] == *endring)
|
||||||
|
charIndex = 0;
|
||||||
|
else
|
||||||
|
charIndex++;
|
||||||
|
}
|
||||||
|
SendChar(Sock, L'\r');
|
||||||
|
SendChar(Sock, L'\n');
|
||||||
|
|
||||||
|
/* increment loop index to start printing from next char in ring */
|
||||||
|
loopIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL SendChar(SOCKET Sock, TCHAR c)
|
||||||
|
{
|
||||||
|
INT Temp;
|
||||||
|
INT SentBytes;
|
||||||
|
|
||||||
|
SentBytes = 0;
|
||||||
|
Temp = send(Sock, &c, sizeof(TCHAR), 0);
|
||||||
|
if (Temp > 0) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
_tprintf(("Connection closed by peer.\n"));
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
8
reactos/apps/utils/net/tcpsvcs/chargen/chargen.h
Normal file
8
reactos/apps/utils/net/tcpsvcs/chargen/chargen.h
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#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);
|
9
reactos/apps/utils/net/tcpsvcs/chargen/chargen.xml
Normal file
9
reactos/apps/utils/net/tcpsvcs/chargen/chargen.xml
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
<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>
|
||||||
|
|
0
reactos/apps/utils/net/tcpsvcs/daytime/.gitignore
vendored
Normal file
0
reactos/apps/utils/net/tcpsvcs/daytime/.gitignore
vendored
Normal file
0
reactos/apps/utils/net/tcpsvcs/discard/.gitignore
vendored
Normal file
0
reactos/apps/utils/net/tcpsvcs/discard/.gitignore
vendored
Normal file
72
reactos/apps/utils/net/tcpsvcs/echo/echo.c
Normal file
72
reactos/apps/utils/net/tcpsvcs/echo/echo.c
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <winsock2.h>
|
||||||
|
#include <tchar.h>
|
||||||
|
#include "echo.h"
|
||||||
|
#include "../skelserver/skelserver.h"
|
||||||
|
|
||||||
|
// Handles the incoming data by reflecting it back to the sender.
|
||||||
|
DWORD WINAPI EchoHandler(VOID* Sock_)
|
||||||
|
{
|
||||||
|
DWORD Retval = 0;
|
||||||
|
SOCKET Sock = (SOCKET)Sock_;
|
||||||
|
|
||||||
|
if (!EchoIncomingPackets(Sock)) {
|
||||||
|
_tprintf(_T("Echo incoming packets failed\n"));
|
||||||
|
Retval = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
_tprintf(_T("Shutting connection down...\n"));
|
||||||
|
if (ShutdownConnection(Sock)) {
|
||||||
|
_tprintf(_T("Connection is down.\n"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_tprintf(_T("Connection shutdown failed\n"));
|
||||||
|
Retval = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 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;
|
||||||
|
}
|
||||||
|
|
4
reactos/apps/utils/net/tcpsvcs/echo/echo.h
Normal file
4
reactos/apps/utils/net/tcpsvcs/echo/echo.h
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
#define BUF 1024
|
||||||
|
|
||||||
|
DWORD WINAPI EchoHandler(VOID* Sock_);
|
||||||
|
BOOL EchoIncomingPackets(SOCKET Sock);
|
0
reactos/apps/utils/net/tcpsvcs/qotd/.gitignore
vendored
Normal file
0
reactos/apps/utils/net/tcpsvcs/qotd/.gitignore
vendored
Normal file
127
reactos/apps/utils/net/tcpsvcs/skelserver/skelserver.c
Normal file
127
reactos/apps/utils/net/tcpsvcs/skelserver/skelserver.c
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <winsock2.h>
|
||||||
|
#include <tchar.h>
|
||||||
|
#include "../tcpsvcs.h"
|
||||||
|
#include "skelserver.h"
|
||||||
|
|
||||||
|
|
||||||
|
DWORD WINAPI StartServer(LPVOID lpParam)
|
||||||
|
{
|
||||||
|
const TCHAR* HostIP = "127.0.0.1";
|
||||||
|
DWORD RetVal;
|
||||||
|
WSADATA wsaData;
|
||||||
|
PMYDATA pData;
|
||||||
|
|
||||||
|
pData = (PMYDATA)lpParam;
|
||||||
|
|
||||||
|
if ((RetVal = WSAStartup(MAKEWORD(2, 2), &wsaData)) != 0)
|
||||||
|
{
|
||||||
|
_tprintf(_T("WSAStartup() failed : %lu\n"), RetVal);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
SOCKET ListeningSocket = SetUpListener(HostIP, htons(pData->Port));
|
||||||
|
if (ListeningSocket == INVALID_SOCKET)
|
||||||
|
{
|
||||||
|
_tprintf(_T("error setting up socket\n"));
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Waiting for connections...\n");
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
AcceptConnections(ListeningSocket, pData->Service);
|
||||||
|
printf("Acceptor restarting...\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
WSACleanup();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
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");
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return INVALID_SOCKET;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
VOID AcceptConnections(SOCKET ListeningSocket, LPTHREAD_START_ROUTINE Service)
|
||||||
|
{
|
||||||
|
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 from %s:%d\n"),
|
||||||
|
inet_ntoa(Client.sin_addr), ntohs(Client.sin_port));
|
||||||
|
|
||||||
|
CreateThread(0, 0, Service, (void*)Sock, 0, &ThreadID);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_tprintf(_T("accept() failed\n"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL ShutdownConnection(SOCKET Sock)
|
||||||
|
{
|
||||||
|
/* 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)
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Close the socket. */
|
||||||
|
if (closesocket(Sock) == SOCKET_ERROR)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
7
reactos/apps/utils/net/tcpsvcs/skelserver/skelserver.h
Normal file
7
reactos/apps/utils/net/tcpsvcs/skelserver/skelserver.h
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
#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);
|
57
reactos/apps/utils/net/tcpsvcs/tcpsvcs.c
Normal file
57
reactos/apps/utils/net/tcpsvcs/tcpsvcs.c
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <winsock2.h>
|
||||||
|
#include <tchar.h>
|
||||||
|
#include "tcpsvcs.h"
|
||||||
|
#include "skelserver/skelserver.h"
|
||||||
|
#include "echo/echo.h"
|
||||||
|
#include "chargen/chargen.h"
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
PMYDATA pData[MAX_THREADS];
|
||||||
|
DWORD dwThreadId[MAX_THREADS];
|
||||||
|
HANDLE hThread[MAX_THREADS];
|
||||||
|
INT i;
|
||||||
|
|
||||||
|
/* Create MAX_THREADS worker threads. */
|
||||||
|
for( i=0; i<MAX_THREADS; i++ )
|
||||||
|
{
|
||||||
|
/* Allocate memory for thread data. */
|
||||||
|
pData[i] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MYDATA));
|
||||||
|
|
||||||
|
if( pData == 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;
|
||||||
|
|
||||||
|
hThread[i] = CreateThread(
|
||||||
|
NULL, // default security attributes
|
||||||
|
0, // use default stack size
|
||||||
|
StartServer, // thread function
|
||||||
|
pData[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)
|
||||||
|
{
|
||||||
|
ExitProcess(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wait until all threads have terminated. */
|
||||||
|
WaitForMultipleObjects(MAX_THREADS, hThread, TRUE, INFINITE);
|
||||||
|
|
||||||
|
/* Close all thread handles upon completion. */
|
||||||
|
for(i=0; i<MAX_THREADS; i++)
|
||||||
|
{
|
||||||
|
CloseHandle(hThread[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
13
reactos/apps/utils/net/tcpsvcs/tcpsvcs.h
Normal file
13
reactos/apps/utils/net/tcpsvcs/tcpsvcs.h
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
#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 BUF_SIZE 255
|
||||||
|
|
||||||
|
typedef struct _MyData {
|
||||||
|
INT Port;
|
||||||
|
LPTHREAD_START_ROUTINE Service;
|
||||||
|
} MYDATA, *PMYDATA;
|
13
reactos/apps/utils/net/tcpsvcs/tcpsvcs.xml
Normal file
13
reactos/apps/utils/net/tcpsvcs/tcpsvcs.xml
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<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>
|
||||||
|
|
Loading…
Reference in a new issue