1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS HTTP Daemon 4 * FILE: socket.cpp 5 * PURPOSE: Socket classes 6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) 7 * REVISIONS: 8 * CSH 01/09/2000 Created 9 */ 10 #include <socket.h> 11 #include <string.h> 12 #include <error.h> 13 #include <iterator.h> 14 15 // ***************************** CSocket ***************************** 16 17 // Default constructor 18 CSocket::CSocket() 19 { 20 Active = FALSE; 21 Event = WSA_INVALID_EVENT; 22 Events = 0; 23 Socket = INVALID_SOCKET; 24 25 // INET address family 26 SockAddrIn.sin_family = AF_INET; 27 28 // Any address will do 29 SockAddrIn.sin_addr.s_addr = INADDR_ANY; 30 31 // Convert to network ordering 32 SockAddrIn.sin_port = htons(0); 33 } 34 35 // Default destructor 36 CSocket::~CSocket() 37 { 38 } 39 40 // Return winsock socket handle 41 SOCKET CSocket::GetSocket() 42 { 43 return Socket; 44 } 45 46 // Set winsock socket handle 47 VOID CSocket::SetSocket(SOCKET socket) 48 { 49 Socket = socket; 50 } 51 52 53 // Return socket address 54 SOCKADDR_IN CSocket::GetSockAddrIn() 55 { 56 return SockAddrIn; 57 } 58 59 // Set socket address 60 VOID CSocket::SetSockAddrIn(SOCKADDR_IN sockaddrin) 61 { 62 SockAddrIn = sockaddrin; 63 } 64 65 // Associate winsock events with socket 66 VOID CSocket::SetEvents(LONG lEvents) 67 { 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.")); 73 } 74 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.")); 79 Events = lEvents; 80 } 81 } 82 83 // Return associated winsock events 84 LONG CSocket::GetEvents() 85 { 86 return Events; 87 } 88 89 // Open socket 90 VOID CSocket::Open() 91 { 92 } 93 94 // Close socket 95 VOID CSocket::Close() 96 { 97 } 98 99 100 // *********************** CServerClientSocket *********************** 101 102 // Constructor with serversocket as parameter 103 CServerClientSocket::CServerClientSocket(LPCServerSocket lpServerSocket) 104 { 105 ServerSocket = lpServerSocket; 106 } 107 108 // Transmit data to socket 109 INT CServerClientSocket::Transmit( LPCSTR lpsBuffer, UINT nLength) 110 { 111 return send(Socket, lpsBuffer, nLength, 0); 112 } 113 114 // Send a string to socket 115 INT CServerClientSocket::SendText( LPCSTR lpsText) 116 { 117 static CHAR crlf[3] = {0x0D, 0x0A, 0x00}; 118 INT nCount; 119 120 nCount = Transmit(lpsText, strlen(lpsText)); 121 nCount += Transmit(crlf, strlen(crlf)); 122 return nCount; 123 } 124 125 // Receive data from socket 126 INT CServerClientSocket::Receive(LPSTR lpsBuffer, UINT nLength) 127 { 128 return recv(Socket, lpsBuffer, nLength, 0); 129 } 130 131 // Process winsock messages if any 132 VOID CServerClientSocket::MessageLoop() 133 { 134 UINT nStatus; 135 WSANETWORKEVENTS NetworkEvents; 136 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) { 140 OnRead(); 141 } 142 if ((NetworkEvents.lNetworkEvents & FD_CLOSE) != 0) { 143 OnClose(); 144 } 145 } 146 } 147 148 // Return server socket that own this socket 149 LPCServerSocket CServerClientSocket::GetServerSocket() 150 { 151 return ServerSocket; 152 } 153 154 155 // *********************** CServerClientThread *********************** 156 157 CServerClientThread::CServerClientThread(LPCServerClientSocket lpSocket) 158 { 159 ClientSocket = lpSocket; 160 } 161 162 CServerClientThread::~CServerClientThread() 163 { 164 ClientSocket->GetServerSocket()->RemoveClient((LPCServerClientThread) this); 165 } 166 167 168 // ************************** CServerSocket ************************** 169 170 // Default constructor 171 CServerSocket::CServerSocket() 172 { 173 } 174 175 // Default destructor 176 CServerSocket::~CServerSocket() 177 { 178 if (Active) 179 Close(); 180 } 181 182 // Open server socket so clients can connect 183 VOID CServerSocket::Open() 184 { 185 assert(!Active); 186 187 // Convert to network ordering 188 SockAddrIn.sin_port = htons(Port); 189 190 if (Socket == INVALID_SOCKET) { 191 // Create socket 192 Socket = socket(AF_INET, SOCK_STREAM, 0); 193 if (Socket == INVALID_SOCKET) 194 throw ESocketOpen(TS("Unable to allocate a socket.")); 195 } 196 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.")); 200 201 // Listen for incoming connections 202 if (listen(Socket, MAX_PENDING_CONNECTS) != 0) 203 throw ESocketOpen(TS("Unable to listen on socket.")); 204 205 // Associate network events with socket 206 SetEvents(FD_ACCEPT | FD_CONNECT | FD_CLOSE); 207 208 Active = TRUE; 209 } 210 211 // Close server socket and all current connections 212 VOID CServerSocket::Close() 213 { 214 assert(Active); 215 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.")); 220 221 if (!WSACloseEvent(Event)) 222 throw ESocketClose(TS("Unable to close socket event.")); 223 Event = WSA_INVALID_EVENT; 224 } 225 226 CIterator<LPCServerClientThread> *i = Connections.CreateIterator(); 227 228 // Terminate and free all client threads 229 for (i->First(); !i->IsDone(); i->Next()) { 230 //i->CurrentItem()->Terminate(); 231 delete i->CurrentItem(); 232 } 233 delete i; 234 Connections.RemoveAll(); 235 236 closesocket(Socket); 237 Socket = INVALID_SOCKET; 238 239 Active = FALSE; 240 } 241 242 // Set port number to listen on 243 VOID CServerSocket::SetPort(UINT nPort) 244 { 245 assert(!Active); 246 247 Port = nPort; 248 } 249 250 // Process messages from winsock if any 251 VOID CServerSocket::MessageLoop() 252 { 253 UINT nStatus; 254 INT nAddrLen; 255 SOCKET ClientSocket; 256 SOCKADDR_IN SockAddrIn; 257 WSANETWORKEVENTS NetworkEvents; 258 LPCServerClientSocket lpClient; 259 LPCServerClientThread lpThread; 260 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) { 268 // Set socket handle 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 279 OnAccept(lpThread); 280 } else { 281 delete lpClient; 282 lpClient = NULL; 283 throw ESocketOpen(TS("No more sockets available.")); 284 } 285 } 286 /*if ((NetworkEvents.lNetworkEvents & FD_CONNECT) != 0) { 287 } 288 if ((NetworkEvents.lNetworkEvents & FD_CLOSE) != 0) { 289 }*/ 290 } 291 } 292 293 // Insert client into connection list 294 VOID CServerSocket::InsertClient(LPCServerClientThread lpClient) 295 { 296 Connections.Insert(lpClient); 297 } 298 299 // Remove client from connection list 300 VOID CServerSocket::RemoveClient(LPCServerClientThread lpClient) 301 { 302 Connections.Remove(lpClient); 303 } 304 305 // OnGetSocket event handler 306 LPCServerClientSocket CServerSocket::OnGetSocket(LPCServerSocket lpServerSocket) 307 { 308 return NULL; 309 } 310 311 // OnGetThread event handler 312 LPCServerClientThread CServerSocket::OnGetThread(LPCServerClientSocket lpSocket) 313 { 314 return NULL; 315 } 316 317 318 // Initialize WinSock DLL 319 VOID InitWinsock() 320 { 321 WORD wVersionRequested; 322 WSADATA wsaData; 323 324 wVersionRequested = MAKEWORD(2, 0); 325 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.")); 329 330 /* Confirm that the WinSock DLL supports 2.0 */ 331 332 if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 0) { 333 // We couldn't find a usable winsock dll 334 WSACleanup(); 335 throw ESocketDll(TS("Winsock dll version is not 2.0 or higher.")); 336 } 337 } 338 339 // Deinitialize WinSock DLL 340 VOID DeinitWinsock() 341 { 342 if (WSACleanup() != 0) 343 throw ESocketWinsock(TS("Unable to deinitialize winsock dll.")); 344 } 345