2 * PROJECT: ReactOS simple TCP/IP services
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: /base/services/tcpsvcs/skelserver.c
5 * PURPOSE: Sets up a server and listens for connections
6 * COPYRIGHT: Copyright 2005 - 2008 Ged Murphy <gedmurphy@gmail.com>
15 SetUpListener(USHORT Port
)
21 sock
= socket(AF_INET
, SOCK_STREAM
, 0);
22 if (sock
!= INVALID_SOCKET
)
24 server
.sin_family
= AF_INET
;
25 server
.sin_addr
.s_addr
= htonl(INADDR_ANY
);
26 server
.sin_port
= Port
;
28 if (bind(sock
, (SOCKADDR
*)&server
, sizeof(SOCKADDR_IN
)) != SOCKET_ERROR
)
30 if (listen(sock
, SOMAXCONN
) != SOCKET_ERROR
)
36 LogEvent(L
"listen() failed", WSAGetLastError(), 0, LOG_ERROR
);
41 LogEvent(L
"bind() failed", WSAGetLastError(), 0, LOG_ERROR
);
46 LogEvent(L
"socket() failed", WSAGetLastError(), 0, LOG_ERROR
);
49 return bSetup
? sock
: INVALID_SOCKET
;
54 AcceptConnections(SOCKET listeningSocket
,
55 LPTHREAD_START_ROUTINE lpService
,
66 timeVal
.tv_sec
= timeOut
/ 1000;
67 timeVal
.tv_usec
= timeOut
% 1000;
74 FD_SET(listeningSocket
, &readFD
);
76 selRet
= select(0, &readFD
, NULL
, NULL
, &timeVal
);
79 if (!bShutdown
|| FD_ISSET(listeningSocket
, &readFD
))
81 INT addrSize
= sizeof(SOCKADDR_IN
);
83 sock
= accept(listeningSocket
, (SOCKADDR
*)&client
, &addrSize
);
84 if (sock
!= INVALID_SOCKET
)
87 L
"Accepted connection to %s server from %S:%d",
89 inet_ntoa(client
.sin_addr
),
90 ntohs(client
.sin_port
));
91 LogEvent(logBuf
, 0, 0, LOG_FILE
);
93 _swprintf(logBuf
, L
"Creating worker thread for %s", lpName
);
94 LogEvent(logBuf
, 0, 0, LOG_FILE
);
98 hThread
= CreateThread(0, 0, lpService
, (void*)sock
, 0, NULL
);
101 CloseHandle(hThread
);
105 _swprintf(logBuf
, L
"Failed to start worker thread for the %s server",
107 LogEvent(logBuf
, 0, 0, LOG_FILE
);
113 LogEvent(L
"accept failed", WSAGetLastError(), 0, LOG_ERROR
);
117 else if (selRet
== SOCKET_ERROR
)
119 LogEvent(L
"select failed", WSAGetLastError(), 0, LOG_ERROR
);
125 ShutdownConnection(SOCKET sock
,
130 /* Disallow any further data sends. This will tell the other side
131 that we want to go away now. If we skip this step, we don't
132 shut the connection down nicely. */
133 if (shutdown(sock
, SD_SEND
) == SOCKET_ERROR
)
135 LogEvent(L
"Error in shutdown()", WSAGetLastError(), 0, LOG_ERROR
);
139 /* Receive any extra data still sitting on the socket
140 before we close it */
143 CHAR readBuffer
[BUF
];
148 ret
= recv(sock
, readBuffer
, BUF
, 0);
151 _swprintf(logBuf
, L
"FYI, received %d unexpected bytes during shutdown", ret
);
152 LogEvent(logBuf
, 0, 0, LOG_FILE
);
164 StartServer(LPVOID lpParam
)
166 SOCKET listeningSocket
;
170 pServices
= (PSERVICES
)lpParam
;
172 _swprintf(logBuf
, L
"Starting %s server", pServices
->lpName
);
173 LogEvent(logBuf
, 0, 0, LOG_FILE
);
177 listeningSocket
= SetUpListener(htons(pServices
->Port
));
178 if (!bShutdown
&& listeningSocket
!= INVALID_SOCKET
)
181 L
"%s is waiting for connections on port %d",
184 LogEvent(logBuf
, 0, 0, LOG_FILE
);
186 AcceptConnections(listeningSocket
, pServices
->lpService
, pServices
->lpName
);
190 LogEvent(L
"Socket error when setting up listener", 0, 0, LOG_FILE
);
195 L
"Exiting %s thread",
197 LogEvent(logBuf
, 0, 0, LOG_FILE
);