2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS HTTP Daemon
5 * PURPOSE: Socket classes
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
8 * CSH 01/09/2000 Created
14 // ***************************** CSocket *****************************
16 // Default constructor
20 Event = WSA_INVALID_EVENT;
22 Socket = INVALID_SOCKET;
24 // INET address family
25 SockAddrIn.sin_family = AF_INET;
27 // Any address will do
28 SockAddrIn.sin_addr.s_addr = INADDR_ANY;
30 // Convert to network ordering
31 SockAddrIn.sin_port = htons(0);
39 // Return winsock socket handle
40 SOCKET CSocket::GetSocket()
45 // Set winsock socket handle
46 VOID CSocket::SetSocket(SOCKET socket)
52 // Return socket address
53 SOCKADDR_IN CSocket::GetSockAddrIn()
59 VOID CSocket::SetSockAddrIn(SOCKADDR_IN sockaddrin)
61 SockAddrIn = sockaddrin;
64 // Associate winsock events with socket
65 VOID CSocket::SetEvents(LONG lEvents)
67 if (Event == WSA_INVALID_EVENT) {
68 // Create socket event
69 Event = WSACreateEvent();
70 if (Event == WSA_INVALID_EVENT)
71 throw ESocketOpen(TS("Unable to create event."));
74 if (lEvents != Events) {
75 // Associate network events with socket
76 if (WSAEventSelect(Socket, Event, lEvents) == SOCKET_ERROR)
77 throw ESocketOpen(TS("Unable to select socket events."));
82 // Return associated winsock events
83 LONG CSocket::GetEvents()
99 // *********************** CServerClientSocket ***********************
101 // Constructor with serversocket as parameter
102 CServerClientSocket::CServerClientSocket(LPCServerSocket lpServerSocket)
104 ServerSocket = lpServerSocket;
107 // Transmit data to socket
108 INT CServerClientSocket::Transmit( LPSTR lpsBuffer, UINT nLength)
110 return send(Socket, lpsBuffer, nLength, 0);
113 // Send a string to socket
114 INT CServerClientSocket::SendText( LPSTR lpsText)
116 static CHAR crlf[3] = {0x0D, 0x0A, 0x00};
119 nCount = Transmit(lpsText, strlen(lpsText));
120 nCount += Transmit(crlf, strlen(crlf));
124 // Receive data from socket
125 INT CServerClientSocket::Receive(LPSTR lpsBuffer, UINT nLength)
127 return recv(Socket, lpsBuffer, nLength, 0);
130 // Process winsock messages if any
131 VOID CServerClientSocket::MessageLoop()
134 WSANETWORKEVENTS NetworkEvents;
136 nStatus = WSAWaitForMultipleEvents(1, &Event, FALSE, 0, FALSE);
137 if ((nStatus == 0) && (WSAEnumNetworkEvents(Socket, Event, &NetworkEvents) != SOCKET_ERROR)) {
138 if ((NetworkEvents.lNetworkEvents & FD_READ) != 0) {
141 if ((NetworkEvents.lNetworkEvents & FD_CLOSE) != 0) {
147 // Return server socket that own this socket
148 LPCServerSocket CServerClientSocket::GetServerSocket()
154 // *********************** CServerClientThread ***********************
156 CServerClientThread::CServerClientThread(LPCServerClientSocket lpSocket)
158 ClientSocket = lpSocket;
161 CServerClientThread::~CServerClientThread()
163 ClientSocket->GetServerSocket()->RemoveClient((LPCServerClientThread) this);
167 // ************************** CServerSocket **************************
169 // Default constructor
170 CServerSocket::CServerSocket()
174 // Default destructor
175 CServerSocket::~CServerSocket()
181 // Open server socket so clients can connect
182 VOID CServerSocket::Open()
186 // Convert to network ordering
187 SockAddrIn.sin_port = htons(Port);
189 if (Socket == INVALID_SOCKET) {
191 Socket = socket(AF_INET, SOCK_STREAM, 0);
192 if (Socket == INVALID_SOCKET)
193 throw ESocketOpen(TS("Unable to allocate a socket."));
196 // Associate an address with server socket
197 if (bind(Socket, (struct sockaddr FAR *) &SockAddrIn, sizeof(SockAddrIn)) == SOCKET_ERROR)
198 throw ESocketOpen(TS("Unable to associate address with socket."));
200 // Listen for incoming connections
201 if (listen(Socket, MAX_PENDING_CONNECTS) != 0)
202 throw ESocketOpen(TS("Unable to listen on socket."));
204 // Associate network events with socket
205 SetEvents(FD_ACCEPT | FD_CONNECT | FD_CLOSE);
210 // Close server socket and all current connections
211 VOID CServerSocket::Close()
215 if (Event != WSA_INVALID_EVENT) {
216 // Tell winsock not to notify us about any events
217 if (WSAEventSelect(Socket, Event, 0) == SOCKET_ERROR)
218 throw ESocketClose(TS("Unable to select socket events."));
220 if (!WSACloseEvent(Event))
221 throw ESocketClose(TS("Unable to close socket event."));
222 Event = WSA_INVALID_EVENT;
225 CIterator<LPCServerClientThread> *i = Connections.CreateIterator();
227 // Terminate and free all client threads
228 for (i->First(); !i->IsDone(); i->Next()) {
229 //i->CurrentItem()->Terminate();
230 delete i->CurrentItem();
233 Connections.RemoveAll();
236 Socket = INVALID_SOCKET;
241 // Set port number to listen on
242 VOID CServerSocket::SetPort(UINT nPort)
249 // Process messages from winsock if any
250 VOID CServerSocket::MessageLoop()
255 SOCKADDR_IN SockAddrIn;
256 WSANETWORKEVENTS NetworkEvents;
257 LPCServerClientSocket lpClient;
258 LPCServerClientThread lpThread;
260 nStatus = WSAWaitForMultipleEvents(1, &Event, FALSE, 0, FALSE);
261 if ((nStatus == 0) && (WSAEnumNetworkEvents(Socket, Event, &NetworkEvents) != SOCKET_ERROR)) {
262 if ((NetworkEvents.lNetworkEvents & FD_ACCEPT) != 0) {
263 lpClient = OnGetSocket(this);
264 nAddrLen = sizeof(SockAddrIn);
265 ClientSocket = accept(Socket, (SOCKADDR *) &SockAddrIn, &nAddrLen);
266 if (ClientSocket != INVALID_SOCKET) {
268 lpClient->SetSocket(ClientSocket);
269 // Set socket address
270 lpClient->SetSockAddrIn(SockAddrIn);
271 // Set winsock events
272 lpClient->SetEvents(FD_READ | FD_CLOSE);
273 // Create client connection thread
274 lpThread = OnGetThread(lpClient);
275 // Add client thread to connection list
276 InsertClient(lpThread);
277 // Call OnAccept event handler
282 throw ESocketOpen(TS("No more sockets available."));
285 /*if ((NetworkEvents.lNetworkEvents & FD_CONNECT) != 0) {
287 if ((NetworkEvents.lNetworkEvents & FD_CLOSE) != 0) {
292 // Insert client into connection list
293 VOID CServerSocket::InsertClient(LPCServerClientThread lpClient)
295 Connections.Insert(lpClient);
298 // Remove client from connection list
299 VOID CServerSocket::RemoveClient(LPCServerClientThread lpClient)
301 Connections.Remove(lpClient);
304 // OnGetSocket event handler
305 LPCServerClientSocket CServerSocket::OnGetSocket(LPCServerSocket lpServerSocket)
310 // OnGetThread event handler
311 LPCServerClientThread CServerSocket::OnGetThread(LPCServerClientSocket lpSocket)
317 // Initialize WinSock DLL
320 WORD wVersionRequested;
323 wVersionRequested = MAKEWORD(2, 0);
325 if (WSAStartup(wVersionRequested, &wsaData) != 0)
326 // Return FALSE as we couldn't find a usable WinSock DLL
327 throw ESocketWinsock(TS("Unable to initialize winsock dll."));
329 /* Confirm that the WinSock DLL supports 2.0 */
331 if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 0) {
332 // We couldn't find a usable winsock dll
334 throw ESocketDll(TS("Winsock dll version is not 2.0 or higher."));
338 // Deinitialize WinSock DLL
341 if (WSACleanup() != 0)
342 throw ESocketWinsock(TS("Unable to deinitialize winsock dll."));