Add tcpsvcs to the services directory.
[reactos.git] / reactos / services / tcpsvcs / skelserver.c
1 /*
2 * ReactOS Services
3 * Copyright (C) 2005 ReactOS Team
4 *
5 * LICENCE: GPL - See COPYING in the top level directory
6 * PROJECT: ReactOS simple TCP/IP services
7 * FILE: apps/utils/net/tcpsvcs/skelserver.c
8 * PURPOSE: Provide CharGen, Daytime, Discard, Echo, and Qotd services
9 * PROGRAMMERS: Ged Murphy (gedmurphy@gmail.com)
10 * REVISIONS:
11 * GM 04/10/05 Created
12 *
13 */
14
15 #include <stdio.h>
16 #include <winsock2.h>
17 #include <tchar.h>
18 #include "tcpsvcs.h"
19
20 DWORD WINAPI StartServer(LPVOID lpParam)
21 {
22 const TCHAR* HostIP = "127.0.0.1";
23 PSERVICES pServices;
24
25 pServices = (PSERVICES)lpParam;
26
27 SOCKET ListeningSocket = SetUpListener(HostIP, htons(pServices->Port));
28 if (ListeningSocket == INVALID_SOCKET)
29 {
30 _tprintf(_T("error setting up socket\n"));
31 return 3;
32 }
33
34 _tprintf(_T("%s is waiting for connections on port %d...\n"),
35 pServices->Name, pServices->Port);
36 while (1)
37 {
38 AcceptConnections(ListeningSocket, pServices->Service, pServices->Name);
39 printf("Acceptor restarting...\n");
40 }
41
42 /* won't see this yet as we kill the service with ctrl+c */
43 _tprintf(_T("Detaching Winsock2...\n"));
44 WSACleanup();
45 return 0;
46 }
47
48
49 SOCKET SetUpListener(const char* ServAddr, int Port)
50 {
51 SOCKET Sock;
52 SOCKADDR_IN Server;
53
54 Sock = socket(AF_INET, SOCK_STREAM, 0);
55 if (Sock != INVALID_SOCKET)
56 {
57 Server.sin_family = AF_INET;
58 Server.sin_addr.s_addr = htonl(INADDR_ANY);
59 Server.sin_port = Port;
60 if (bind(Sock, (SOCKADDR*)&Server, sizeof(SOCKADDR_IN)) != SOCKET_ERROR)
61 {
62 listen(Sock, SOMAXCONN);
63 return Sock;
64 }
65 else
66 printf("bind() failed\n");
67
68 }
69 return INVALID_SOCKET;
70 }
71
72
73
74
75 VOID AcceptConnections(SOCKET ListeningSocket,
76 LPTHREAD_START_ROUTINE Service, TCHAR *Name)
77 {
78 SOCKADDR_IN Client;
79 SOCKET Sock;
80 INT nAddrSize = sizeof(Client);
81 DWORD ThreadID;
82
83 while (1)
84 {
85 Sock = accept(ListeningSocket, (SOCKADDR*)&Client, &nAddrSize);
86 if (Sock != INVALID_SOCKET)
87 {
88 _tprintf(_T("Accepted connection to %s server from %s:%d\n"),
89 Name, inet_ntoa(Client.sin_addr), ntohs(Client.sin_port));
90 _tprintf(_T("Creating new thread for %s\n"), Name);
91 CreateThread(0, 0, Service, (void*)Sock, 0, &ThreadID);
92 }
93 else
94 {
95 _tprintf(_T("accept() failed\n"));
96 return;
97 }
98 }
99 }
100
101 BOOL ShutdownConnection(SOCKET Sock, BOOL bRec)
102 {
103 /* Disallow any further data sends. This will tell the other side
104 that we want to go away now. If we skip this step, we don't
105 shut the connection down nicely. */
106 if (shutdown(Sock, SD_SEND) == SOCKET_ERROR)
107 {
108 _tprintf(_T("Error in shutdown"));
109 return FALSE;
110 }
111
112 /* Receive any extra data still sitting on the socket. After all
113 data is received, this call will block until the remote host
114 acknowledges the TCP control packet sent by the shutdown above.
115 Then we'll get a 0 back from recv, signalling that the remote
116 host has closed its side of the connection. */
117 if (bRec)
118 {
119 char ReadBuffer[BUF];
120 int NewBytes = recv(Sock, ReadBuffer, BUF, 0);
121 if (NewBytes == SOCKET_ERROR)
122 return FALSE;
123 else if (NewBytes != 0)
124 _tprintf(_T("FYI, received %d unexpected bytes during shutdown\n"), NewBytes);
125 }
126
127 /* Close the socket. */
128 if (closesocket(Sock) == SOCKET_ERROR)
129 return FALSE;
130
131 return TRUE;
132 }