/* static */ void CALLBACK Server::IoCompletionCallback(PTP_CALLBACK_INSTANCE /* Instance */, PVOID /* Context */, PVOID Overlapped, ULONG IoResult, ULONG_PTR NumberOfBytesTransferred, PTP_IO /* Io */) { IOEvent* event = CONTAINING_RECORD(Overlapped, IOEvent, GetOverlapped()); assert(event); if (IoResult != ERROR_SUCCESS) { ERROR_CODE(IoResult, "I/O operation failed. type[%d]", event->GetType()); switch (event->GetType()) { case IOEvent::SEND: Server::Instance()->OnSend(event, NumberOfBytesTransferred); break; } Server::Instance()->OnClose(event); } else { switch (event->GetType()) { case IOEvent::ACCEPT: Server::Instance()->OnAccept(event); break; case IOEvent::RECV: if (NumberOfBytesTransferred > 0) { Server::Instance()->OnRecv(event, NumberOfBytesTransferred); } else { Server::Instance()->OnClose(event); } break; case IOEvent::SEND: Server::Instance()->OnSend(event, NumberOfBytesTransferred); break; default: assert(false); break; } } IOEvent::Destroy(event); }
void aysnc_accept(SOCKET sl, SOCKET sa, char * recvbuff, boost::function<void() > acceptcallback){ DWORD bytes = 0; overlappedaccept * poverlappedaccept = static_cast<overlappedaccept*>(GetOverlapped(event_accept)); poverlappedaccept->fncallback = acceptcallback; BOOL bret = AcceptEx(sl, sa, recvbuff, 0, sizeof(SOCKADDR_IN6), sizeof(SOCKADDR_IN6), &bytes, &(poverlappedaccept->ovlap)); if (!bret){ int err = WSAGetLastError(); if (err != ERROR_IO_PENDING){ throw exception::AcceptException("AcceptEx fail", err); } } }
void async_disconnect(SOCKET s){ LPFN_DISCONNECTEX DisConnectEx; DWORD bytes = 0; GUID guid = WSAID_DISCONNECTEX; if (WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, &guid, sizeof(guid), &DisConnectEx, sizeof(DisConnectEx), &bytes, 0, 0) != 0){ throw exception::DisConnectException("Get LPFN_DISCONNECTEX fail", GetLastError()); } overlappeddisconnect * poverlappeddisconnect = static_cast<overlappeddisconnect*>(GetOverlapped(event_disconnect)); poverlappeddisconnect->s = s; if (!DisConnectEx(s, &poverlappeddisconnect->ovlap, 0, 0)){ throw exception::DisConnectException("DisConnectEx fail", GetLastError()); } }
void async_recvfrom(SOCKET s, char * buff, const uint32_t buflen, boost::function<void(char * buff, uint32_t len, const address & addr) > recvfromcallback){ WSABUF * pWSABUF = GetWSABUF(1); pWSABUF->buf = buff; pWSABUF->len = buflen; overlappedrecvfrom * poverlappedrecvfrom = static_cast<overlappedrecvfrom*>(GetOverlapped(event_recv)); poverlappedrecvfrom->fncallback = boost::bind(recvfromcallback, buff, _1, _2); DWORD bytes = 0; if (SOCKET_ERROR == WSARecvFrom(s, pWSABUF, 1, &bytes, 0, (sockaddr*)&poverlappedrecvfrom->remoteaddr, &poverlappedrecvfrom->addrlen, &poverlappedrecvfrom->ovlap, 0)){ int err = WSAGetLastError(); if (err != ERROR_IO_PENDING){ throw exception::RecvfromException("Recvfrom fail", err); } } }
void async_recv(SOCKET s, char * buff, const uint32_t buflen, boost::function<void(char * buff, uint32_t recvlen) > recvcallback){ WSABUF * pWSABUF = GetWSABUF(1); pWSABUF->buf = buff; pWSABUF->len = buflen; overlappedrecv * poverlappedrecv = static_cast<overlappedrecv*>(GetOverlapped(event_recv)); poverlappedrecv->fncallback = boost::bind(recvcallback, buff, _1); DWORD bytes = 0; if (SOCKET_ERROR == WSARecv(s, pWSABUF, 1, &bytes, 0, &(poverlappedrecv->ovlap), 0)){ int err = WSAGetLastError(); if (err != ERROR_IO_PENDING){ throw exception::RecvException("Recv fail", err); } } }
void async_connect(SOCKET s, const sockaddr * addr, boost::function<void() > connectcallback){ LPFN_CONNECTEX ConnectEx; DWORD bytes = 0; GUID guid = WSAID_CONNECTEX; if (WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, &guid, sizeof(guid), &ConnectEx, sizeof(ConnectEx), &bytes, 0, 0) != 0){ throw exception::ConnectException("Get LPFN_CONNECTEX fail", GetLastError()); } overlappedconnect * poverlappedconnect = static_cast<overlappedconnect*>(GetOverlapped(event_connect)); poverlappedconnect->fncallback = connectcallback; if (!ConnectEx(s, addr, sizeof(addr), 0, 0, &bytes, &(poverlappedconnect->ovlap))){ int err = WSAGetLastError(); if (err != ERROR_IO_PENDING){ throw exception::ConnectException("ConnectEx fail", err); } } }
void async_send(SOCKET s, const std::vector<buffstruct> & buff, boost::function<void() > sendcallback){ overlappedsend * poverlapped = static_cast<overlappedsend*>(GetOverlapped(event_send)); WSABUF * pWSABUF = GetWSABUF(buff.size()); for(uint32_t i = 0; i < buff.size(); i++){ pWSABUF[i].buf = buff[i].buff; pWSABUF[i].len = buff[i].len; } poverlapped->vectbuff.assign(buff.begin(), buff.end()); poverlapped->fncallback = sendcallback; DWORD bytes; if (SOCKET_ERROR == WSASend(s, pWSABUF, buff.size(), &bytes, 0, &poverlapped->ovlap, 0)){ int err = WSAGetLastError(); if (err != ERROR_IO_PENDING){ throw exception::SendException("Send fail", err); } } }
/// Accepts an incoming connection on a server pipe. /// /// @param[in] timeout maximum time to wait for a client in milliseconds /// @return this end of a pipe connected to the client, or NULL if none was available CNamedPipe *CNamedPipe::Accept (unsigned long timeout) { assert (IsServer ()); #ifdef _WIN32 if (!ConnectNamedPipe (GetFile (), GetOverlapped ())) { if (GetLastError () != ERROR_PIPE_CONNECTED) { if (!WaitOnOverlapped (timeout)) { DWORD dwError = GetLastError (); LOGWARN (TEXT ("Overlapped result not available, error ") << dwError); SetLastError (dwError); return NULL; } } } HANDLE handle = _CreatePipe (GetName (), IsServer (), false, IsReader ()); if (!handle) { DWORD dwError = GetLastError (); LOGWARN (TEXT ("Couldn't create replacement pipe for server, error ") << dwError); SetLastError (dwError); return NULL; } CNamedPipe *poClient = new CNamedPipe (GetFile (), GetName (), false, IsReader ()); SetFile (handle); return poClient; #else failedOperation: struct sockaddr_un addr; bool bLazyWait = false; unsigned long lLazy = IsLazyClosing (); if (lLazy) { bLazyWait = true; timeout = lLazy; } timeoutOperation: int sock; if (BeginOverlapped (timeout, true)) { socklen_t len = sizeof (addr); sock = accept (GetFile (), (struct sockaddr*)&addr, &len); EndOverlapped (); } else { sock = -1; } if (sock < 0) { int ec = GetLastError (); if (ec == EINTR) { LOGDEBUG (TEXT ("Accept interrupted")); lLazy = IsLazyClosing (); if (lLazy) { if (bLazyWait) { LOGINFO (TEXT ("Closing file on idle timeout")); Close (); } } if (!IsClosed () && !bLazyWait) { bLazyWait = true; timeout = lLazy; LOGDEBUG (TEXT ("Resuming operation with idle timeout of ") << timeout << TEXT ("ms")); goto timeoutOperation; } } LOGWARN (TEXT ("Couldn't accept client, error ") << ec); SetLastError (ec); return NULL; } LOGINFO (TEXT ("Connection accepted on ") << GetName ()); if (!_SetDefaultSocketOptions (sock)) { int ec = GetLastError (); close (sock); LOGWARN (TEXT ("Couldn't set default socket options, error ") << ec); SetLastError (ec); return NULL; } if ((send (sock, "!", 1, 0) != 1) || fcntl (sock, F_SETFL, O_NONBLOCK)) { int ec = GetLastError (); close (sock); if (ec == EPIPE) { LOGWARN (TEXT ("Client disconnected before receiving handshake")); goto failedOperation; } LOGWARN (TEXT ("Couldn't send handshake message, error ") << ec); SetLastError (ec); return NULL; } else { LOGDEBUG (TEXT ("Handshake message written")); } return new CNamedPipe (sock, GetName (), false, IsReader ()); #endif }