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