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
15 // ***************************** CSocket *****************************
17 // Default constructor
21 Event
= WSA_INVALID_EVENT
;
23 Socket
= INVALID_SOCKET
;
25 // INET address family
26 SockAddrIn
.sin_family
= AF_INET
;
28 // Any address will do
29 SockAddrIn
.sin_addr
.s_addr
= INADDR_ANY
;
31 // Convert to network ordering
32 SockAddrIn
.sin_port
= htons(0);
40 // Return winsock socket handle
41 SOCKET
CSocket::GetSocket()
46 // Set winsock socket handle
47 VOID
CSocket::SetSocket(SOCKET socket
)
53 // Return socket address
54 SOCKADDR_IN
CSocket::GetSockAddrIn()
60 VOID
CSocket::SetSockAddrIn(SOCKADDR_IN sockaddrin
)
62 SockAddrIn
= sockaddrin
;
65 // Associate winsock events with socket
66 VOID
CSocket::SetEvents(LONG lEvents
)
68 if (Event
== WSA_INVALID_EVENT
) {
69 // Create socket event
70 Event
= WSACreateEvent();
71 if (Event
== WSA_INVALID_EVENT
)
72 throw ESocketOpen(TS("Unable to create event."));
75 if (lEvents
!= Events
) {
76 // Associate network events with socket
77 if (WSAEventSelect(Socket
, Event
, lEvents
) == SOCKET_ERROR
)
78 throw ESocketOpen(TS("Unable to select socket events."));
83 // Return associated winsock events
84 LONG
CSocket::GetEvents()
100 // *********************** CServerClientSocket ***********************
102 // Constructor with serversocket as parameter
103 CServerClientSocket::CServerClientSocket(LPCServerSocket lpServerSocket
)
105 ServerSocket
= lpServerSocket
;
108 // Transmit data to socket
109 INT
CServerClientSocket::Transmit( LPSTR lpsBuffer
, UINT nLength
)
111 return send(Socket
, lpsBuffer
, nLength
, 0);
114 // Send a string to socket
115 INT
CServerClientSocket::SendText( LPSTR lpsText
)
117 static CHAR crlf
[3] = {0x0D, 0x0A, 0x00};
120 nCount
= Transmit(lpsText
, strlen(lpsText
));
121 nCount
+= Transmit(crlf
, strlen(crlf
));
125 // Receive data from socket
126 INT
CServerClientSocket::Receive(LPSTR lpsBuffer
, UINT nLength
)
128 return recv(Socket
, lpsBuffer
, nLength
, 0);
131 // Process winsock messages if any
132 VOID
CServerClientSocket::MessageLoop()
135 WSANETWORKEVENTS NetworkEvents
;
137 nStatus
= WSAWaitForMultipleEvents(1, &Event
, FALSE
, 0, FALSE
);
138 if ((nStatus
== 0) && (WSAEnumNetworkEvents(Socket
, Event
, &NetworkEvents
) != SOCKET_ERROR
)) {
139 if ((NetworkEvents
.lNetworkEvents
& FD_READ
) != 0) {
142 if ((NetworkEvents
.lNetworkEvents
& FD_CLOSE
) != 0) {
148 // Return server socket that own this socket
149 LPCServerSocket
CServerClientSocket::GetServerSocket()
155 // *********************** CServerClientThread ***********************
157 CServerClientThread::CServerClientThread(LPCServerClientSocket lpSocket
)
159 ClientSocket
= lpSocket
;
162 CServerClientThread::~CServerClientThread()
164 ClientSocket
->GetServerSocket()->RemoveClient((LPCServerClientThread
) this);
168 // ************************** CServerSocket **************************
170 // Default constructor
171 CServerSocket::CServerSocket()
175 // Default destructor
176 CServerSocket::~CServerSocket()
182 // Open server socket so clients can connect
183 VOID
CServerSocket::Open()
187 // Convert to network ordering
188 SockAddrIn
.sin_port
= htons(Port
);
190 if (Socket
== INVALID_SOCKET
) {
192 Socket
= socket(AF_INET
, SOCK_STREAM
, 0);
193 if (Socket
== INVALID_SOCKET
)
194 throw ESocketOpen(TS("Unable to allocate a socket."));
197 // Associate an address with server socket
198 if (bind(Socket
, (struct sockaddr FAR
*) &SockAddrIn
, sizeof(SockAddrIn
)) == SOCKET_ERROR
)
199 throw ESocketOpen(TS("Unable to associate address with socket."));
201 // Listen for incoming connections
202 if (listen(Socket
, MAX_PENDING_CONNECTS
) != 0)
203 throw ESocketOpen(TS("Unable to listen on socket."));
205 // Associate network events with socket
206 SetEvents(FD_ACCEPT
| FD_CONNECT
| FD_CLOSE
);
211 // Close server socket and all current connections
212 VOID
CServerSocket::Close()
216 if (Event
!= WSA_INVALID_EVENT
) {
217 // Tell winsock not to notify us about any events
218 if (WSAEventSelect(Socket
, Event
, 0) == SOCKET_ERROR
)
219 throw ESocketClose(TS("Unable to select socket events."));
221 if (!WSACloseEvent(Event
))
222 throw ESocketClose(TS("Unable to close socket event."));
223 Event
= WSA_INVALID_EVENT
;
226 CIterator
<LPCServerClientThread
> *i
= Connections
.CreateIterator();
228 // Terminate and free all client threads
229 for (i
->First(); !i
->IsDone(); i
->Next()) {
230 //i->CurrentItem()->Terminate();
231 delete i
->CurrentItem();
234 Connections
.RemoveAll();
237 Socket
= INVALID_SOCKET
;
242 // Set port number to listen on
243 VOID
CServerSocket::SetPort(UINT nPort
)
250 // Process messages from winsock if any
251 VOID
CServerSocket::MessageLoop()
256 SOCKADDR_IN SockAddrIn
;
257 WSANETWORKEVENTS NetworkEvents
;
258 LPCServerClientSocket lpClient
;
259 LPCServerClientThread lpThread
;
261 nStatus
= WSAWaitForMultipleEvents(1, &Event
, FALSE
, 0, FALSE
);
262 if ((nStatus
== 0) && (WSAEnumNetworkEvents(Socket
, Event
, &NetworkEvents
) != SOCKET_ERROR
)) {
263 if ((NetworkEvents
.lNetworkEvents
& FD_ACCEPT
) != 0) {
264 lpClient
= OnGetSocket(this);
265 nAddrLen
= sizeof(SockAddrIn
);
266 ClientSocket
= accept(Socket
, (SOCKADDR
*) &SockAddrIn
, &nAddrLen
);
267 if (ClientSocket
!= INVALID_SOCKET
) {
269 lpClient
->SetSocket(ClientSocket
);
270 // Set socket address
271 lpClient
->SetSockAddrIn(SockAddrIn
);
272 // Set winsock events
273 lpClient
->SetEvents(FD_READ
| FD_CLOSE
);
274 // Create client connection thread
275 lpThread
= OnGetThread(lpClient
);
276 // Add client thread to connection list
277 InsertClient(lpThread
);
278 // Call OnAccept event handler
283 throw ESocketOpen(TS("No more sockets available."));
286 /*if ((NetworkEvents.lNetworkEvents & FD_CONNECT) != 0) {
288 if ((NetworkEvents.lNetworkEvents & FD_CLOSE) != 0) {
293 // Insert client into connection list
294 VOID
CServerSocket::InsertClient(LPCServerClientThread lpClient
)
296 Connections
.Insert(lpClient
);
299 // Remove client from connection list
300 VOID
CServerSocket::RemoveClient(LPCServerClientThread lpClient
)
302 Connections
.Remove(lpClient
);
305 // OnGetSocket event handler
306 LPCServerClientSocket
CServerSocket::OnGetSocket(LPCServerSocket lpServerSocket
)
311 // OnGetThread event handler
312 LPCServerClientThread
CServerSocket::OnGetThread(LPCServerClientSocket lpSocket
)
318 // Initialize WinSock DLL
321 WORD wVersionRequested
;
324 wVersionRequested
= MAKEWORD(2, 0);
326 if (WSAStartup(wVersionRequested
, &wsaData
) != 0)
327 // Return FALSE as we couldn't find a usable WinSock DLL
328 throw ESocketWinsock(TS("Unable to initialize winsock dll."));
330 /* Confirm that the WinSock DLL supports 2.0 */
332 if (LOBYTE(wsaData
.wVersion
) != 2 || HIBYTE(wsaData
.wVersion
) != 0) {
333 // We couldn't find a usable winsock dll
335 throw ESocketDll(TS("Winsock dll version is not 2.0 or higher."));
339 // Deinitialize WinSock DLL
342 if (WSACleanup() != 0)
343 throw ESocketWinsock(TS("Unable to deinitialize winsock dll."));