Something went wrong. Try again.
Reactos
Something went wrong. Try again.
C++
at master
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS HTTP Daemon * FILE: socket.cpp * PURPOSE: Socket classes * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) * REVISIONS: * CSH 01/09/2000 Created */#include <socket.h>#include <string.h>#include <error.h>#include <iterator.h>
// ***************************** CSocket *****************************
// Default constructorCSocket::CSocket(){ Active = FALSE; Event = WSA_INVALID_EVENT; Events = 0; Socket = INVALID_SOCKET;
// INET address family SockAddrIn.sin_family = AF_INET;
// Any address will do SockAddrIn.sin_addr.s_addr = INADDR_ANY;
// Convert to network ordering SockAddrIn.sin_port = htons(0);}
// Default destructorCSocket::~CSocket(){}
// Return winsock socket handleSOCKET CSocket::GetSocket(){ return Socket;}
// Set winsock socket handleVOID CSocket::SetSocket(SOCKET socket){ Socket = socket;}
// Return socket addressSOCKADDR_IN CSocket::GetSockAddrIn(){ return SockAddrIn;}
// Set socket addressVOID CSocket::SetSockAddrIn(SOCKADDR_IN sockaddrin){ SockAddrIn = sockaddrin;}
// Associate winsock events with socketVOID CSocket::SetEvents(LONG lEvents){ if (Event == WSA_INVALID_EVENT) { // Create socket event Event = WSACreateEvent(); if (Event == WSA_INVALID_EVENT) throw ESocketOpen(TS("Unable to create event.")); }
if (lEvents != Events) { // Associate network events with socket if (WSAEventSelect(Socket, Event, lEvents) == SOCKET_ERROR) throw ESocketOpen(TS("Unable to select socket events.")); Events = lEvents; }}
// Return associated winsock eventsLONG CSocket::GetEvents(){ return Events;}
// Open socketVOID CSocket::Open(){}
// Close socketVOID CSocket::Close(){}
// *********************** CServerClientSocket ***********************
// Constructor with serversocket as parameterCServerClientSocket::CServerClientSocket(LPCServerSocket lpServerSocket){ ServerSocket = lpServerSocket;}
// Transmit data to socketINT CServerClientSocket::Transmit( LPCSTR lpsBuffer, UINT nLength){ return send(Socket, lpsBuffer, nLength, 0);}
// Send a string to socketINT CServerClientSocket::SendText( LPCSTR lpsText){ static CHAR crlf[3] = {0x0D, 0x0A, 0x00}; INT nCount;
nCount = Transmit(lpsText, strlen(lpsText)); nCount += Transmit(crlf, strlen(crlf)); return nCount;}
// Receive data from socketINT CServerClientSocket::Receive(LPSTR lpsBuffer, UINT nLength){ return recv(Socket, lpsBuffer, nLength, 0);}
// Process winsock messages if anyVOID CServerClientSocket::MessageLoop(){ UINT nStatus; WSANETWORKEVENTS NetworkEvents;
nStatus = WSAWaitForMultipleEvents(1, &Event, FALSE, 0, FALSE); if ((nStatus == 0) && (WSAEnumNetworkEvents(Socket, Event, &NetworkEvents) != SOCKET_ERROR)) { if ((NetworkEvents.lNetworkEvents & FD_READ) != 0) { OnRead(); } if ((NetworkEvents.lNetworkEvents & FD_CLOSE) != 0) { OnClose(); } }}
// Return server socket that own this socketLPCServerSocket CServerClientSocket::GetServerSocket(){ return ServerSocket;}
// *********************** CServerClientThread ***********************
CServerClientThread::CServerClientThread(LPCServerClientSocket lpSocket){ ClientSocket = lpSocket;}
CServerClientThread::~CServerClientThread(){ ClientSocket->GetServerSocket()->RemoveClient((LPCServerClientThread) this);}
// ************************** CServerSocket **************************
// Default constructorCServerSocket::CServerSocket(){}
// Default destructorCServerSocket::~CServerSocket(){ if (Active) Close();}
// Open server socket so clients can connectVOID CServerSocket::Open(){ assert(!Active);
// Convert to network ordering SockAddrIn.sin_port = htons(Port);
if (Socket == INVALID_SOCKET) { // Create socket Socket = socket(AF_INET, SOCK_STREAM, 0); if (Socket == INVALID_SOCKET) throw ESocketOpen(TS("Unable to allocate a socket.")); }
// Associate an address with server socket if (bind(Socket, (struct sockaddr FAR *) &SockAddrIn, sizeof(SockAddrIn)) == SOCKET_ERROR) throw ESocketOpen(TS("Unable to associate address with socket."));
// Listen for incoming connections if (listen(Socket, MAX_PENDING_CONNECTS) != 0) throw ESocketOpen(TS("Unable to listen on socket."));
// Associate network events with socket SetEvents(FD_ACCEPT | FD_CONNECT | FD_CLOSE);
Active = TRUE;}
// Close server socket and all current connectionsVOID CServerSocket::Close(){ assert(Active);
if (Event != WSA_INVALID_EVENT) { // Tell winsock not to notify us about any events if (WSAEventSelect(Socket, Event, 0) == SOCKET_ERROR) throw ESocketClose(TS("Unable to select socket events."));
if (!WSACloseEvent(Event)) throw ESocketClose(TS("Unable to close socket event.")); Event = WSA_INVALID_EVENT; }
CIterator<LPCServerClientThread> *i = Connections.CreateIterator();
// Terminate and free all client threads for (i->First(); !i->IsDone(); i->Next()) { //i->CurrentItem()->Terminate(); delete i->CurrentItem(); } delete i; Connections.RemoveAll();
closesocket(Socket); Socket = INVALID_SOCKET;
Active = FALSE;}
// Set port number to listen onVOID CServerSocket::SetPort(UINT nPort){ assert(!Active);
Port = nPort;}
// Process messages from winsock if anyVOID CServerSocket::MessageLoop(){ UINT nStatus; INT nAddrLen; SOCKET ClientSocket; SOCKADDR_IN SockAddrIn; WSANETWORKEVENTS NetworkEvents; LPCServerClientSocket lpClient; LPCServerClientThread lpThread;
nStatus = WSAWaitForMultipleEvents(1, &Event, FALSE, 0, FALSE); if ((nStatus == 0) && (WSAEnumNetworkEvents(Socket, Event, &NetworkEvents) != SOCKET_ERROR)) { if ((NetworkEvents.lNetworkEvents & FD_ACCEPT) != 0) { lpClient = OnGetSocket(this); nAddrLen = sizeof(SockAddrIn); ClientSocket = accept(Socket, (SOCKADDR *) &SockAddrIn, &nAddrLen); if (ClientSocket != INVALID_SOCKET) { // Set socket handle lpClient->SetSocket(ClientSocket); // Set socket address lpClient->SetSockAddrIn(SockAddrIn); // Set winsock events lpClient->SetEvents(FD_READ | FD_CLOSE); // Create client connection thread lpThread = OnGetThread(lpClient); // Add client thread to connection list InsertClient(lpThread); // Call OnAccept event handler OnAccept(lpThread); } else { delete lpClient; lpClient = NULL; throw ESocketOpen(TS("No more sockets available.")); } } /*if ((NetworkEvents.lNetworkEvents & FD_CONNECT) != 0) { } if ((NetworkEvents.lNetworkEvents & FD_CLOSE) != 0) { }*/ }}
// Insert client into connection listVOID CServerSocket::InsertClient(LPCServerClientThread lpClient){ Connections.Insert(lpClient);}
// Remove client from connection listVOID CServerSocket::RemoveClient(LPCServerClientThread lpClient){ Connections.Remove(lpClient);}
// OnGetSocket event handlerLPCServerClientSocket CServerSocket::OnGetSocket(LPCServerSocket lpServerSocket){ return NULL;}
// OnGetThread event handlerLPCServerClientThread CServerSocket::OnGetThread(LPCServerClientSocket lpSocket){ return NULL;}
// Initialize WinSock DLLVOID InitWinsock(){ WORD wVersionRequested; WSADATA wsaData;
wVersionRequested = MAKEWORD(2, 0);
if (WSAStartup(wVersionRequested, &wsaData) != 0) // Return FALSE as we couldn't find a usable WinSock DLL throw ESocketWinsock(TS("Unable to initialize winsock dll."));
/* Confirm that the WinSock DLL supports 2.0 */
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 0) { // We couldn't find a usable winsock dll WSACleanup(); throw ESocketDll(TS("Winsock dll version is not 2.0 or higher.")); }}
// Deinitialize WinSock DLLVOID DeinitWinsock(){ if (WSACleanup() != 0) throw ESocketWinsock(TS("Unable to deinitialize winsock dll."));}