bool CAcceptor::Register(CLoginSocket &loginSocket, int size) { if (CDisconnected::Instance() != loginSocket.stateMachine.CurrentState()) { MYERRORPRINTF("loginSocket's state is not CDisconnected !!!"); return false; } DWORD byteTransferred; BOOL result = AcceptEx( listenSocket->sock, loginSocket.sock, loginSocket.acceptBuf, size, sizeof(SOCKADDR_IN)+16, sizeof(SOCKADDR_IN)+16, &byteTransferred, static_cast<OVERLAPPED*>(&loginSocket.acts[CLoginSocket::ACT_TYPE::ACCEPT]) ); int error = WSAGetLastError(); if (!result) { if (WSA_IO_PENDING != error) { MYERRORPRINTF("AcceptEx"); return false; } } return true; }
static void enable_listen(EVENT_KERNEL *ev, ACL_EVENT_FDTABLE *fdp) { const char *myname = "enable_listen"; ACL_SOCKET sock; DWORD ReceiveLen = 0; sock = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, 0, 0, WSA_FLAG_OVERLAPPED); memset(&fdp->event_read->overlapped, 0, sizeof(fdp->event_read->overlapped)); fdp->stream->type |= ACL_VSTREAM_TYPE_LISTEN_IOCP; fdp->stream->iocp_sock = sock; if (AcceptEx(ACL_VSTREAM_SOCK(fdp->stream), sock, fdp->event_read->myAddrBlock, 0, ACCEPT_ADDRESS_LENGTH, ACCEPT_ADDRESS_LENGTH, &ReceiveLen, &fdp->event_read->overlapped) == FALSE && acl_last_error() !=ERROR_IO_PENDING) { acl_msg_warn("%s(%d): AcceptEx error(%s)", myname, __LINE__, acl_last_serror()); } }
DWORD CEgTcpDriver::CreateAcceptSocket(BOOL bBindIocp) { DWORD dwRecvNumBytes = 0; DWORD dwRes; if (bBindIocp) { m_ListenSocketContext.m_ConnectioID.m_Socket = m_ListenSocket; m_ListenSocketContext.m_pIOContext.m_IoOperation = ClientIoAccept; dwRes = BindCompletionPort(m_ListenSocketContext); if (dwRes != 0) return dwRes; } m_ListenSocketContext.m_pIOContext.m_SocketAccept = CreateSocket(); if (INVALID_SOCKET == m_ListenSocketContext.m_pIOContext.m_SocketAccept) return WSAGetLastError(); int nRet = AcceptEx( m_ListenSocket, m_ListenSocketContext.m_pIOContext.m_SocketAccept, (LPVOID)(m_ListenSocketContext.m_pIOContext.m_ReceiveBuffer.buf), 0, sizeof(SOCKADDR_IN) + 16, sizeof(SOCKADDR_IN) + 16, &dwRecvNumBytes, (LPOVERLAPPED) &(m_ListenSocketContext.m_pIOContext.m_SendOverlapped) ); if (nRet == SOCKET_ERROR && (ERROR_IO_PENDING != WSAGetLastError())) return WSAGetLastError(); return 0; }
void AddWaitingAcceptConn(SOCKET sListenConn, LPFN_ACCEPTEX lpfnAcceptEx) { for (int a = 0; a < WaitingAcceptCon; a++) { SOCKET sAcceptConn = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_IP, 0, 0, WSA_FLAG_OVERLAPPED); //SOCKET sAcceptConn = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_IP, 0, 0, WSA_FLAG_OVERLAPPED); if (sAcceptConn == INVALID_SOCKET) return; Log("WSASocket new AccepteConn [%d].", sAcceptConn); OverLapped* pAcceptExOverLapped = new OverLapped; pAcceptExOverLapped->opType = OverLapped::OLOpType::EOLOT_Accept; pAcceptExOverLapped->sysBuffer.len = (DWORD)sAcceptConn; // git snap(0342d1d): 调用 AcceptEx 返回错误 (WSA_IO_PENDING) // git snap(6234b13): 增加测试代码(BOOL bRet = AcceptEx, 并打印错误码), 返回错误(WSAEINVAL), 因为sAcceptConn被AcceptEx两次 DWORD dwBytes; BOOL bRet = AcceptEx(sListenConn, sAcceptConn, pAcceptExOverLapped->sysBuffer.buf, 0, AcceptExSockAddrInLen, AcceptExSockAddrInLen, &dwBytes, &pAcceptExOverLapped->sysOverLapped); if (!bRet && WSAGetLastError() != WSA_IO_PENDING) { printf("WSAGetLastError = [%d].\n", WSAGetLastError()); delete pAcceptExOverLapped; return; } } MustPrint("AddWaitingAcceptConn OK.\n"); }
sp_thread_result_t SP_THREAD_CALL SP_IocpServer :: acceptThread( void * arg ) { DWORD recvBytes = 0; SP_IocpAcceptArg_t * acceptArg = (SP_IocpAcceptArg_t*)arg; for( ; ; ) { acceptArg->mClientSocket = (HANDLE)WSASocket( AF_INET, SOCK_STREAM, IPPROTO_IP, NULL, 0, WSA_FLAG_OVERLAPPED ); if( INVALID_SOCKET == (int)acceptArg->mClientSocket ) { sp_syslog( LOG_ERR, "WSASocket fail, errno %d", WSAGetLastError() ); Sleep( 50 ); continue; } SP_IOUtils::setNonblock( (int)acceptArg->mClientSocket ); memset( &( acceptArg->mOverlapped ), 0, sizeof( OVERLAPPED ) ); BOOL ret = AcceptEx( (SOCKET)acceptArg->mListenSocket, (SOCKET)acceptArg->mClientSocket, acceptArg->mBuffer, 0, sizeof(struct sockaddr_in) + 16, sizeof(struct sockaddr_in) + 16, &recvBytes, &( acceptArg->mOverlapped ) ); int lastError = WSAGetLastError(); if( FALSE == ret && (ERROR_IO_PENDING != lastError) ) { sp_syslog( LOG_ERR, "AcceptEx() fail, errno %d", lastError ); closesocket( (int)acceptArg->mClientSocket ); if( WSAENOBUFS == lastError ) Sleep( 50 ); } else { WaitForSingleObject( acceptArg->mAcceptEvent, INFINITE ); ResetEvent( acceptArg->mAcceptEvent ); } } return 0; }
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); } } }
bool CSocket::initSocket(int index, SOCKET sockListener){ int dummy; DWORD dwReceived; ZeroMemory(this, sizeof(CSocket)); //zeromemory 안하면 overlapped 구조체 에러 _eovSendTcp.mode = SENDEOVTCP; _eovRecvTcp.mode = RECVEOVTCP; _index = index; _iSTRestCnt = 0; _iFixedQ = DEFAULTQUEUE; //처음 로직큐 _iChannel = DEFAULTCHANNEL; //처음 채널 //링버퍼 초기화 _cpSTBegin = _cpSTEnd = _cSendTcpRingBuf; _cpRTMark = _cpRTBegin = _cpRTEnd = _cRecvTcpRingBuf; _sockTcp = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED); if (_sockTcp == INVALID_SOCKET){ printf("invlaid_socket/n"); return 0; } //1새로운 연결 받기 2 지역 주소 원격 주소 반환 3 첫 데이터 블럭 수신 dummy = AcceptEx(sockListener, _sockTcp, //소켓, 버퍼, 오버랩 구조체, 니주소, 내주소 _cpRTEnd, //ipOutputBuffer MAXRECVPACKETSIZE, //실제 데이터 수신 바이트 수 최대 크기 처음에 안받으면 0 sizeof(sockaddr_in) + 16, //localaddress length tcp is 16 + 원격 까지 16 sizeof(sockaddr_in) + 16, //remoteaddress length &dwReceived, // 연결되자마자 받은 데이터의 크기이다. (OVERLAPPED *)&_eovRecvTcp); //plOverlapped os가 생성해서 리턴해줌 이놈만 쓰라고 특별히 할당해줌 if (dummy == FALSE && GetLastError() != ERROR_IO_PENDING) { printf("duummy is %d accept fail is %d/n",dummy,GetLastError()); return 0; } InitializeCriticalSection(&_csSTcp); return true; }
CHANNEL accept(ACCEPTOR ap){ channelimpl * ch = pool::objpool<channelimpl>::allocator(1); new (ch)channelimpl(((acceptorimlp*)((handle*)ap))->que, ((acceptorimlp*)((handle*)ap))->sa); setsockopt(ch->s, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, (char *)&((acceptorimlp*)((handle*)ap))->sl, sizeof(((acceptorimlp*)((handle*)ap))->sl)); unsigned long ul = 1; if (ioctlsocket(ch->s, FIONBIO, (unsigned long *)&ul) == SOCKET_ERROR){ } CreateIoCompletionPort((HANDLE)ch->s, ((queueimpl*)((handle*)ch->que))->iocp, 0, 0); { WSABUF * wsabuf = pool::objpool<WSABUF>::allocator(1); wsabuf->buf = ch->buf; wsabuf->len = ch->buflen; DWORD bytes = 0; DWORD flags = 0; overlappedex * ovp = pool::objpool<overlappedex>::allocator(1); new (ovp)overlappedex(); ovp->h = (handle*)ch; ovp->com_type = iocp_type_ipv4_tcp; ovp->event_type = type_recv; OVERLAPPED * ovp_ = static_cast<OVERLAPPED *>(ovp); memset(ovp_, 0, sizeof(OVERLAPPED)); WSARecv(ch->s, wsabuf, 1, &bytes, &flags, ovp_, 0); } { ((acceptorimlp*)((handle*)ap))->sa = socket(AF_INET, SOCK_STREAM, 0); memset(((acceptorimlp*)((handle*)ap))->outbuf, 0, sizeof(((acceptorimlp*)((handle*)ap))->outbuf)); overlappedex * ovlp = pool::objpool<overlappedex>::allocator(1); new (ovlp)overlappedex(); ovlp->h = (handle*)ap; ovlp->com_type = iocp_type_ipv4_tcp; ovlp->event_type = type_accept; OVERLAPPED * ovp_ = static_cast<OVERLAPPED *>(ovlp); memset(ovp_, 0, sizeof(OVERLAPPED)); AcceptEx(((acceptorimlp*)((handle*)ap))->sl, ((acceptorimlp*)((handle*)ap))->sa, ((acceptorimlp*)((handle*)ap))->outbuf, 0, sizeof(SOCKADDR_IN) + 16, sizeof(SOCKADDR_IN) + 16, 0, ovp_); } return (CHANNEL)((handle*)ch); }
//클라이언트의ㅡaccept를 담당할 쓰레드 UINT AcceptThread( LPVOID lParam ){ SERVER_INFO* serverInfo = (SERVER_INFO*)lParam; OVERLAPPED ov; while(TRUE) { //SOCKET clientSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);//이렇게 프로토콜만 결정된상태 SOCKET clientSocket = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED); char temp[1024]; DWORD dwRecv; //이건사실안나온다. 억셉트ex는 비동기함수라 바로 밑으로 빠져나간다. 그래서 dwRecv에 값이 들어갈수가없다. 형식적인거. memset(&ov, 0, sizeof(ov)); AcceptEx(*serverInfo->hServSock, clientSocket, temp, 0, sizeof(SOCKADDR_IN)+16, sizeof(SOCKADDR_IN)+16, &dwRecv, &ov); //첫번째 listensocket, 서버소켓만들고바인드하고리슨까지한거,그다음은 acceptsocket //그럼 이제 시스템이 내부적으로 클라이언트가 connect할때까지 기다린다. //우리는 클라이언트가 커넥트하면 clientSocket가지고 링크드리스트에 집어넣고 이런작업해야한다. //근데 얘는 언제끝날지 모른다. 그래서 WaitForSingleObject((HANDLE)*serverInfo->hServSock, INFINITE); //이렇게 클라이언트가 connect할때까지 기다리는거다. //SOCKADDR_IN의 더블포인터가 필요하다. SOCKADDR_IN * pLocal; SOCKADDR_IN * pAddr; int iLocalLen = sizeof(SOCKADDR_IN); int iRemoteLen = sizeof(SOCKADDR_IN); GetAcceptExSockaddrs(temp, 0, sizeof(SOCKADDR_IN)+16, sizeof(SOCKADDR_IN)+16, (sockaddr **)&pLocal, &iLocalLen, (sockaddr **)&pAddr, &iRemoteLen); //이 temp에 정보가 다 들어있다. CreateIoCompletionPort((HANDLE)clientSocket, *serverInfo->hComPort, (DWORD)clientSocket, 0); //세번째 파라미터가 RecvFunc에 dwCompKey로 간다. //이렇게 하면 소켓이 아까 만든 껍데기에 등록이 된다. 처음에 한명이 접근해서 하나가 등록이 된다. EnterCriticalSection(&myCS2); //client 등록 serverInfo->mCToonVasServerDlg->AddClient(clientSocket, *pAddr); LeaveCriticalSection(&myCS2); } return 0; }
void gas_start_accepting (GAS_POLLER_INFO *pi) { DWORD addr_buffer_size = sizeof(struct sockaddr_in) + 16; pi->accept_ci->socket = gas_create_socket(GAS_FALSE); memset(pi->accept_ci->overlapped, 0, sizeof(WSAOVERLAPPED)); gas_debug_message (GAS_IO, "Started accepting connections...\n"); // uses listener's completion key and overlapped structure // starts asynchronous accept if (!AcceptEx(pi->server_socket, pi->accept_ci->socket, gas_get_buffer_data(pi->accept_ci->rb), 0 /* no recv */, addr_buffer_size, addr_buffer_size, NULL, (WSAOVERLAPPED *)pi->accept_ci->overlapped)) { int err = WSAGetLastError(); if (err != ERROR_IO_PENDING) gas_error_message("Error %d in AcceptEx\n", err); } }
acceptorimlp::acceptorimlp(QUEUE _que, ENDPOINT ep){ _handle_type = handle_ipv4_tcp_acceptor_type; que = _que; sl = socket(AF_INET, SOCK_STREAM, 0); sa = socket(AF_INET, SOCK_STREAM, 0); outbuf = new char[1024]; if (bind(sl, (sockaddr*)(&((endpointimpl*)((handle*)ep))->addr), sizeof(SOCKADDR_IN)) != 0){ throw std::exception("bind error"); } if (listen(sl, 10) != 0){ throw std::exception("listen error"); } int corenum = 8; SYSTEM_INFO info; GetSystemInfo(&info); corenum = info.dwNumberOfProcessors; if (CreateIoCompletionPort((HANDLE)sl, ((queueimpl*)((handle*)_que))->iocp, 0, corenum) != ((queueimpl*)((handle*)_que))->iocp){ throw std::exception("CreateIoCompletionPort error", WSAGetLastError()); } memset(outbuf, 0, sizeof(outbuf)); overlappedex * ovlp = pool::objpool<overlappedex>::allocator(1); new (ovlp) overlappedex(); ovlp->h = (handle*)this; ovlp->com_type = iocp_type_ipv4_tcp; ovlp->event_type = type_accept; OVERLAPPED * ovp = static_cast<OVERLAPPED *>(ovlp); memset(ovp, 0, sizeof(OVERLAPPED)); if (!AcceptEx(sl, sa, outbuf, 0, sizeof(SOCKADDR_IN) + 16, sizeof(SOCKADDR_IN) + 16, 0, ovp)){ int error = WSAGetLastError(); if (error != WSA_IO_PENDING){ throw std::exception("acceptorimlp", error); } } }
void SockSpring::__HandleRead(void) { bool to_handle = true; RefLock(); if(shutdown_already_) to_handle = false; RefUnlock(); if(!to_handle) return; SockPad skpad; #if defined(LNE_WIN32) SOCKET listen_socket = skpad_.socket(); setsockopt(iocp_data_.child, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, (char *)&listen_socket, sizeof(listen_socket)); skpad.Attach(skpad_.family(), iocp_data_.child); iocp_data_.child = socket(skpad_.family(), SOCK_STREAM, IPPROTO_TCP); if(iocp_data_.child != INVALID_SOCKET) { DWORD bytes; if(!AcceptEx(skpad_.socket(), iocp_data_.child, &iocp_data_.address, 0, 0, sizeof(iocp_data_.address), &bytes, &iocp_data_) && WSAGetLastError() != ERROR_IO_PENDING) { closesocket(iocp_data_.child); iocp_data_.child = INVALID_SOCKET; } } handler_->HandleClient(this, skpad); #else SOCKET sock; do { RefLock(); if(skpad_) sock = accept(skpad_.socket(), NULL, NULL); else { sock = SOCKET_ERROR; errno = EBADF; } RefUnlock(); if(sock != SOCKET_ERROR) { skpad.Attach(skpad_.family(), sock); handler_->HandleClient(this, skpad); } } while(sock != SOCKET_ERROR || errno == EINTR); #endif }
void ntpAddAcceptSocket(SOCKET sListen) { BOOL success; SOCKET sAccept=WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED); if(INVALID_SOCKET==sAccept){ DebugBreak(); } DWORD nBufSize=max(4096, (sizeof(sockaddr_in)+16)*2); LPOVERLAPPED_ACCEPT ola=(LPOVERLAPPED_ACCEPT)HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS|HEAP_ZERO_MEMORY, sizeof(OVERLAPPED_ACCEPT)+nBufSize); ola->tp=CreateThreadpoolIo((HANDLE)sAccept, workerIoThreadProc, 0, &tEnvrion); ola->acceptBuf=(UINT8*)ola+sizeof(OVERLAPPED_ACCEPT); ola->s=sAccept; ola->bufSize=nBufSize; DWORD acceptBufSize=max(0, ola->bufSize-sizeof(sockaddr_in)-16-sizeof(sockaddr_in)-16); acceptBufSize=0; StartThreadpoolIo(pListen); success=AcceptEx(sListen, ola->s, ola->acceptBuf, acceptBufSize, sizeof(sockaddr_in)+16, sizeof(sockaddr_in)+16, 0, &ola->overlapped); if(!success && WSAGetLastError()!=ERROR_IO_PENDING){ DebugBreak(); } }
VOID CALLBACK workerIoThreadProc(PTP_CALLBACK_INSTANCE Instance, PVOID Context, PVOID Overlapped, ULONG IoResult, ULONG_PTR NumberOfBytesTransferred, PTP_IO Io) { ods("workerIoThreadProc start\n"); BOOL success; LPOVERLAPPED_ACCEPT ola=(LPOVERLAPPED_ACCEPT)Overlapped; if(OAS_RECV==ola->oas){ ods("OAS_RECV\n"); DWORD numWritten=0; SecureZeroMemory(Overlapped, sizeof(OVERLAPPED)); DWORD sizeofSend=sizeof(status200HelloWorld)-1; CopyMemory(ola->acceptBuf, status200HelloWorld, sizeofSend); ola->oas=OAS_SEND; StartThreadpoolIo(Io); success=WriteFile((HANDLE)ola->s, ola->acceptBuf, sizeofSend, &numWritten, &ola->overlapped); if(!success && GetLastError()!=ERROR_IO_PENDING){ int wsaError=WSAGetLastError(); DebugBreak(); } }else if(OAS_SEND==ola->oas){ ods("OAS_SEND\n"); SecureZeroMemory(Overlapped, sizeof(OVERLAPPED)); ola->oas=OAS_CLOSE; StartThreadpoolIo(Io); success=DisconnectEx(ola->s, &ola->overlapped, TF_REUSE_SOCKET, 0); if(!success && GetLastError()!=ERROR_IO_PENDING){ int wsaError=WSAGetLastError(); DebugBreak(); } }else if(OAS_CLOSE==ola->oas){ ods("OAS_CLOSE\n"); DWORD acceptBufSize=max(0, ola->bufSize-sizeof(sockaddr_in)-16-sizeof(sockaddr_in)-16); acceptBufSize=0; StartThreadpoolIo(pListen); success=AcceptEx(sListen, ola->s, ola->acceptBuf, acceptBufSize, sizeof(sockaddr_in)+16, sizeof(sockaddr_in)+16, 0, &ola->overlapped); if(!success && WSAGetLastError()!=ERROR_IO_PENDING){ DebugBreak(); } }else{ DebugBreak(); } ods("workerIoThreadProc return\n"); }
static bool StartAsyncAccept(IOOperation* ioop) { DWORD numBytes; BOOL trueval = TRUE; IODesc* iod; int ret; iod = GetIODesc(ioop->fd); if (iod->read || iod->write) ASSERT_FAIL(); // create an accepting socket with WSA_FLAG_OVERLAPPED to support async operations iod->acceptFd.sock = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED); if (iod->acceptFd.sock == INVALID_SOCKET) return false; if (setsockopt(iod->acceptFd.sock, SOL_SOCKET, SO_REUSEADDR, (char *)&trueval, sizeof(BOOL))) { closesocket(iod->acceptFd.sock); return false; } memset(&iod->ovlRead, 0, sizeof(OVERLAPPED)); if (!AcceptEx(ioop->fd.sock, iod->acceptFd.sock, iod->acceptData, 0, ACCEPT_ADDR_LEN, ACCEPT_ADDR_LEN, &numBytes, &iod->ovlRead)) { ret = WSAGetLastError(); if (ret != WSA_IO_PENDING) { Log_Errno(); closesocket(iod->acceptFd.sock); return false; } } iod->read = ioop; ioop->active = true; return true; }
void SocketConnection::acceptNB() { LBASSERT( isListening() ); // Create new accept socket const DWORD flags = getDescription()->type == CONNECTIONTYPE_SDP ? WSA_FLAG_OVERLAPPED | WSA_FLAG_SDP : WSA_FLAG_OVERLAPPED; LBASSERT( _overlappedAcceptData ); LBASSERT( _overlappedSocket == INVALID_SOCKET ); _overlappedSocket = WSASocket( AF_INET, SOCK_STREAM, IPPROTO_TCP, 0, 0, flags ); if( _overlappedSocket == INVALID_SOCKET ) { LBERROR << "Could not create accept socket: " << lunchbox::sysError << ", closing listening socket" << std::endl; close(); return; } const int on = 1; setsockopt( _overlappedSocket, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, reinterpret_cast<const char*>( &on ), sizeof( on )); // Start accept ResetEvent( _overlappedRead.hEvent ); DWORD got; if( !AcceptEx( _readFD, _overlappedSocket, _overlappedAcceptData, 0, sizeof( sockaddr_in ) + 16, sizeof( sockaddr_in ) + 16, &got, &_overlappedRead ) && GetLastError() != WSA_IO_PENDING ) { LBERROR << "Could not start accept operation: " << lunchbox::sysError << ", closing connection" << std::endl; close(); } }
bool SockSpring::HandleBind(SockPoller *binder) { bool result = false; #if defined(LNE_WIN32) iocp_data_.child = socket(skpad_.family(), SOCK_STREAM, IPPROTO_TCP); if(iocp_data_.child != INVALID_SOCKET) { #else int flags = fcntl(skpad_.socket(), F_GETFL); if(flags >= 0 && fcntl(skpad_.socket(), F_SETFL, flags | O_NONBLOCK) == 0) { #endif set_poller(binder); #if defined(LNE_WIN32) if(CreateIoCompletionPort(reinterpret_cast<HANDLE>(skpad_.socket()), poller()->Handle(), static_cast<ULONG_PTR>(skpad_.socket()), 0) != NULL) { DWORD bytes; if(AcceptEx(skpad_.socket(), iocp_data_.child, iocp_data_.address, 0, 0, sizeof(iocp_data_.address), &bytes, &iocp_data_) || WSAGetLastError() == ERROR_IO_PENDING) result = true; } #elif defined(LNE_LINUX) if(epoll_ctl(poller()->Handle(), EPOLL_CTL_ADD, skpad_.socket(), &epoll_data_) == 0) result = true; #elif defined(LNE_FREEBSD) struct kevent kev[1]; EV_SET(&kev[0], skpad_.socket(), EVFILT_READ, EV_ADD, 0, 0, static_cast<SockEventer *>(this)); if(kevent(poller()->Handle(), kev, 1, NULL, 0, NULL) == 0) result = true; #endif } if(!result) Clean(); return result; } void SockSpring::HandleRead(void) { AddRef(); __HandleRead(); Release(); }
static void create_iocp_accept(void) { BOOL bRet; memset(&ac, 0, sizeof(ac)); /* Create simple socket for acceptance */ ac.sockfd = socket(PF_INET, SOCK_STREAM, 0); DIE(ac.sockfd == INVALID_SOCKET, "socket"); /* Launch overlapped connection accept through AcceptEx. */ bRet = AcceptEx( listenfd, ac.sockfd, ac.buffer, 0, 128, 128, &ac.len, &ac.ov); DIE(bRet == FALSE && WSAGetLastError() != ERROR_IO_PENDING, "AcceptEx"); }
int post_listen(struct net_service* service, struct net_session* session, struct accept_session* asession) { NET_SOCKET accept_socket; int err; accept_socket = create_socket(); if(NET_INVALID_SOCKET == accept_socket) { return -1; } CreateIoCompletionPort((HANDLE)accept_socket, service->net_service_fd, (ULONG_PTR)accept_socket, sizeof(NET_SOCKET)); memset(asession, 0, sizeof(struct accept_session)); asession->id = session->id; asession->accept_socket = accept_socket; asession->op = OP_NET_ACCEPT; if(!AcceptEx( session->fd, accept_socket, asession->data_buf, 0, sizeof(struct sockaddr_in) + 32, sizeof(struct sockaddr_in) + 32, &asession->recv_bytes, &asession->overlapped )) { err = net_get_error(); if(ERROR_IO_PENDING != err) { net_close_fd(accept_socket); return err; } } return NO_ERROR; }
void PGMConnection::acceptNB() { EQASSERT( _state == STATE_LISTENING ); // Create new accept socket const DWORD flags = WSA_FLAG_OVERLAPPED; EQASSERT( _overlappedAcceptData ); EQASSERT( _overlappedSocket == INVALID_SOCKET ); _overlappedSocket = WSASocket( AF_INET, SOCK_STREAM, IPPROTO_RM, 0, 0, flags ); if( _overlappedSocket == INVALID_SOCKET ) { EQERROR << "Could not create accept socket: " << base::sysError << ", closing connection" << std::endl; close(); return; } const int on = 1; setsockopt( _overlappedSocket, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, reinterpret_cast<const char*>( &on ), sizeof( on )); // Start accept ResetEvent( _overlapped.hEvent ); DWORD got; if( !AcceptEx( _readFD, _overlappedSocket, _overlappedAcceptData, 0, sizeof( sockaddr_in ) + 16, sizeof( sockaddr_in ) + 16, &got, &_overlapped ) && GetLastError() != WSA_IO_PENDING ) { EQERROR << "Could not start accept operation: " << base::sysError << ", closing connection" << std::endl; close(); } }
bool IOCPMonitor::AddAccept( SOCKET listenSocket ) { #ifdef WIN32 if ( SOCKET_ERROR == listenSocket ) return false; //创建参数 IOCP_OVERLAPPED *pOverlapped = new (m_iocpDataPool.Alloc())IOCP_OVERLAPPED; if ( NULL == pOverlapped ) return false; memset( &pOverlapped->m_overlapped, 0, sizeof(OVERLAPPED) ); pOverlapped->m_dwLocalAddressLength = sizeof(SOCKADDR_IN) + 16;//客户端局域网IP pOverlapped->m_dwRemoteAddressLength = sizeof(SOCKADDR_IN) + 16;//客户端外网IP memset( pOverlapped->m_outPutBuf, 0, sizeof(SOCKADDR_IN)*2+32 ); Socket client; client.Init( Socket::tcp ); pOverlapped->sock = client.GetSocket(); pOverlapped->completiontype = IOCPMonitor::connect; //投递接受连接操作 if ( !AcceptEx( listenSocket, client.GetSocket(), pOverlapped->m_outPutBuf, 0, pOverlapped->m_dwLocalAddressLength, pOverlapped->m_dwRemoteAddressLength, NULL, &pOverlapped->m_overlapped ) ) { int nErrCode = WSAGetLastError(); if ( ERROR_IO_PENDING != nErrCode ) { m_iocpDataPool.Free(pOverlapped); pOverlapped = NULL; return false; } } return true; #endif return true; }
void IOCPEngine::PostAcceptEvent(EventHandler * eh) { if (!eh) return; int on = 1; u_long arg = 1; struct linger linger = { 0 }; int fd = WSASocket(AF_INET, SOCK_STREAM, 0, 0, 0, WSA_FLAG_OVERLAPPED); setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&on, sizeof(on)); /* This is BSD compatible, setting l_onoff to 0 is *NOT* http://web.irc.org/mla/ircd-dev/msg02259.html */ linger.l_onoff = 1; linger.l_linger = 1; setsockopt(fd, SOL_SOCKET, SO_LINGER, (char*)&linger,sizeof(linger)); ioctlsocket(fd, FIONBIO, &arg); int len = sizeof(sockaddr_in) + 16; DWORD dwBytes; accept_overlap* ao = new accept_overlap; memset(ao->buf, 0, 1024); ao->socket = fd; Overlapped* ov = new Overlapped(SOCKET_IO_EVENT_ACCEPT, (int)ao); eh->Extend("windows_acceptevent", ov); if(AcceptEx(eh->GetFd(), fd, ao->buf, 0, len, len, &dwBytes, &ov->m_overlap) == FALSE) { int err = WSAGetLastError(); if(err != WSA_IO_PENDING) { printf("PostAcceptEvent err: %d\n", err); } } }
bool ClientSession::PostAccept() { CRASH_ASSERT(LThreadType == THREAD_MAIN); OverlappedAcceptContext* acceptContext = new OverlappedAcceptContext(this); DWORD bytes = 0; DWORD flags = 0; acceptContext->mWsaBuf.len = 0; acceptContext->mWsaBuf.buf = nullptr; if (FALSE == AcceptEx(*GIocpManager->GetListenSocket(), mSocket, GIocpManager->mAcceptBuf, 0, sizeof(SOCKADDR_IN)+16, sizeof(SOCKADDR_IN)+16, &bytes, (LPOVERLAPPED)acceptContext)) { if (WSAGetLastError() != WSA_IO_PENDING) { DeleteIoContext(acceptContext); printf_s("AcceptEx Error : %d\n", GetLastError()); return false; } } return true; }
// // Begin accepting a connection to an existing port. Used by server. // For synchronous port, blocks until a connection is made (returns TRUE) or an error occurs (returns FALSE). // For asynchronous port, returns immediately. Returns TRUE for success or FALSE if any error occurs. // Call IsAcceptComplete() to determine if it has completed, and GetAcceptResult() to get result. // BOOL PortTCP::Accept() { // // Listen to socket. // #if PORT_DETAILS || _DETAILS cout << "Listening to socket " << name << "." << endl; WSASetLastError(0); #endif if (listen(server_socket, 0) != 0) // allow at most one connection at a time { *errmsg << "===> ERROR: Listening to socket " << name << " failed." << endl << " [PortTCP::Accept() in " << __FILE__ << " line " << __LINE__ << "]" << endl << " errno = " << WSAGetLastError() << ends; OutputErrMsg(); return FALSE; } // // Accept connections to socket. // #if PORT_DETAILS || _DETAILS cout << "Accepting connections to socket " << name << "." << endl; WSASetLastError(0); #endif if (synchronous) { // don't need any info about who we're talking to client_socket = accept(server_socket, NULL, NULL); if (client_socket == (int)INVALID_SOCKET) { *errmsg << "===> ERROR: Accepting connection to socket " << name << " failed." << endl << " [PortTCP::Accept() in " << __FILE__ << " line " << __LINE__ << "]" << endl << " errno = " << WSAGetLastError() << ends; OutputErrMsg(); return FALSE; } else { return TRUE; } } #if defined(IOMTR_OS_WIN32) || defined(IOMTR_OS_WIN64) else { DWORD bytes_received; if (!InitOverlapped(&accept_overlapped)) { *errmsg << "===> ERROR: Creating OVERLAPPED structure for socket " << name << " failed." << endl << " [PortTCP::Accept() in " << __FILE__ << " line " << __LINE__ << "]" << ends; OutputErrMsg(); return FALSE; } // // Create client socket. // #if PORT_DETAILS || _DETAILS cout << "Creating client socket for " << name << "." << endl; WSASetLastError(0); #endif client_socket = WSASocket(AF_INET, SOCK_STREAM, PF_UNSPEC, NULL, 0, WSA_FLAG_OVERLAPPED); if (client_socket == INVALID_SOCKET) { *errmsg << "===> ERROR: Creating client socket for " << name << " failed." << endl << " [PortTCP::Accept() in " << __FILE__ << " line " << __LINE__ << "]" << endl << " errno = " << WSAGetLastError() << ends; OutputErrMsg(); return FALSE; } // // Accept connections to socket. // if (AcceptEx(server_socket, client_socket, accept_ex_buffer, 0, // read no data, only the two addresses, into accept_ex_buffer sizeof(struct sockaddr_in) + 16, sizeof(struct sockaddr_in) + 16, &bytes_received, &accept_overlapped)) { #if PORT_DETAILS || _DETAILS cout << "Connection accepted." << endl; #endif return TRUE; } else { if (WSAGetLastError() == WSA_IO_PENDING) // Read started OK... { return TRUE; } else { *errmsg << "===> ERROR: AcceptEx() failed." << endl << " [PortTCP::Accept() in " << __FILE__ << " line " << __LINE__ << "]" << ends; OutputErrMsg(); return FALSE; } } } #elif defined(IOMTR_OS_LINUX) || defined(IOMTR_OS_NETWARE) || defined(IOMTR_OS_OSX) || defined(IOMTR_OS_SOLARIS) else {
void CServerSocket::Accept() { CSocketBuffer * pBuffer = NULL ; pool_lock() ; try{ if( m_UsingPool.empty() == false ) { pBuffer = m_UsingPool.front() ; m_UsingPool.pop() ; } } catch (...) { ::PrintConsole("[exception] %s, %d \n", __FILE__, __LINE__ ) ; } pool_unlock() ; if( pBuffer ) { pBuffer->release() ; //pBuffer->InitSocket() ; pBuffer->SetMode( mode_accept_complete ) ; int nEstablishedSeconds = 0; int bytes = sizeof(nEstablishedSeconds); int err = ::getsockopt(pBuffer->socket, SOL_SOCKET, SO_CONNECT_TIME, (char*)&nEstablishedSeconds, &bytes); if (nEstablishedSeconds == 0xffffffff) { } else { // nEstablishedSeconds --> 커넥션 이루어진 때로부터 현재까지 경과한 초단위 시간 ::PrintConsole( "[ERROR] Already connected socket \n") ; pBuffer->Shutdown( SD_BOTH ) ; pool_lock() ; try{ pBuffer->release() ; m_UsingPool.push( pBuffer ) ; } catch (...) { printf("[exception] %s, %d \n", __FILE__, __LINE__ ) ; } pool_unlock() ; return ; } if( FALSE == AcceptEx( pBuffer ) ) { int err = WSAGetLastError() ; if( err != WSA_IO_PENDING ) { ::PrintConsole( "AcceptEx : Error %d\n", err ) ; return ; } } else { m_iocp.PostStatus( (DWORD)pBuffer, 0, static_cast<LPOVERLAPPED>(pBuffer) ) ; } ::InterlockedIncrement( &m_nCurPendingAccept ) ; } else { ::PrintConsole( "pop failed\n" ) ; } }
void main(void) { DWORD EventTotal = 0; WSAEVENT EventArray[WSA_MAXIMUM_WAIT_EVENTS]; LPSOCKET_INFORMATION SocketArray[WSA_MAXIMUM_WAIT_EVENTS]; CHAR AcceptBuffer[2 * (sizeof(SOCKADDR_IN) + 16)]; WSAOVERLAPPED ListenOverlapped; DWORD Bytes; DWORD Index; DWORD Flags; DWORD BytesTransferred; LPSOCKET_INFORMATION SI; WSADATA wsaData; SOCKET ListenSocket, AcceptSocket; SOCKADDR_IN InternetAddr; DWORD RecvBytes, SendBytes; DWORD i; INT Ret; if ((Ret = WSAStartup(0x0202,&wsaData)) != 0) { printf("WSAStartup failed with error %d\n", Ret); WSACleanup(); return; } if ((ListenSocket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET) { printf("Failed to get a socket %d\n", WSAGetLastError()); return; } InternetAddr.sin_family = AF_INET; InternetAddr.sin_addr.s_addr = htonl(INADDR_ANY); InternetAddr.sin_port = htons(PORT); if (bind(ListenSocket, (PSOCKADDR) &InternetAddr, sizeof(InternetAddr)) == SOCKET_ERROR) { printf("bind() failed with error %d\n", WSAGetLastError()); return; } if (listen(ListenSocket, 5)) { printf("listen() failed with error %d\n", WSAGetLastError()); return; } // Setup the listening socket for connections. if ((AcceptSocket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET) { printf("Failed to get a socket %d\n", WSAGetLastError()); return; } ZeroMemory(&ListenOverlapped, sizeof(OVERLAPPED)); if ((EventArray[0] = ListenOverlapped.hEvent = WSACreateEvent()) == WSA_INVALID_EVENT) { printf("WSACreateEvent failed with error %d\n", WSAGetLastError()); return; } EventTotal = 1; if (AcceptEx(ListenSocket, AcceptSocket, (PVOID) AcceptBuffer, 0, sizeof(SOCKADDR_IN) + 16, sizeof(SOCKADDR_IN) + 16, &Bytes, &ListenOverlapped) == FALSE) if (WSAGetLastError() != ERROR_IO_PENDING) { printf("AcceptEx failed with error %d\n", WSAGetLastError()); return; } // Process asynchronous AcceptEx, WSASend, WSARecv requests. while(TRUE) { if ((Index = WSAWaitForMultipleEvents(EventTotal, EventArray, FALSE, WSA_INFINITE, FALSE)) == WSA_WAIT_FAILED) { printf("WSAWaitForMultipleEvents failed %d\n", WSAGetLastError()); return; } // If the event triggered was zero then a connection attempt was made // on our listening socket. if ((Index - WSA_WAIT_EVENT_0) == 0) { // Check the returns from the overlapped I/O operation on the listening // socket. if (WSAGetOverlappedResult(ListenSocket, &(ListenOverlapped), &BytesTransferred, FALSE, &Flags) == FALSE) { printf("WSAGetOverlappedResult failed with error %d\n", WSAGetLastError()); return; } printf("Socket %d connected\n", AcceptSocket); if (EventTotal > WSA_MAXIMUM_WAIT_EVENTS) { printf("Too many connections - closing socket.\n"); closesocket(AcceptSocket); continue; } else { // Create a socket information structure to associate with the accepted socket. if ((SocketArray[EventTotal] = (LPSOCKET_INFORMATION) GlobalAlloc(GPTR, sizeof(SOCKET_INFORMATION))) == NULL) { printf("GlobalAlloc() failed with error %d\n", GetLastError()); return; } // Fill in the details of our accepted socket. SocketArray[EventTotal]->Socket = AcceptSocket; ZeroMemory(&(SocketArray[EventTotal]->Overlapped), sizeof(OVERLAPPED)); SocketArray[EventTotal]->BytesSEND = 0; SocketArray[EventTotal]->BytesRECV = 0; SocketArray[EventTotal]->DataBuf.len = DATA_BUFSIZE; SocketArray[EventTotal]->DataBuf.buf = SocketArray[EventTotal]->Buffer; if ((SocketArray[EventTotal]->Overlapped.hEvent = EventArray[EventTotal] = WSACreateEvent()) == WSA_INVALID_EVENT) { printf("WSACreateEvent() failed with error %d\n", WSAGetLastError()); return; } // Post a WSARecv request to to begin receiving data on the socket if (WSARecv(SocketArray[EventTotal]->Socket, &(SocketArray[EventTotal]->DataBuf), 1, &RecvBytes, &Flags, &(SocketArray[EventTotal]->Overlapped), NULL) == SOCKET_ERROR) { if (WSAGetLastError() != ERROR_IO_PENDING) { printf("WSARecv() failed with error %d\n", WSAGetLastError()); return; } } EventTotal++; } // Make a new socket for accepting future connections and post another // AcceptEx call. if ((AcceptSocket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET) { printf("Failed to get a socket %d\n", WSAGetLastError()); return; } WSAResetEvent(EventArray[0]); ZeroMemory(&ListenOverlapped, sizeof(OVERLAPPED)); ListenOverlapped.hEvent = EventArray[0]; if (AcceptEx(ListenSocket, AcceptSocket, (PVOID) AcceptBuffer, 0, sizeof(SOCKADDR_IN) + 16, sizeof(SOCKADDR_IN) + 16, &Bytes, &ListenOverlapped) == FALSE) if (WSAGetLastError() != ERROR_IO_PENDING) { printf("AcceptEx failed with error %d\n", WSAGetLastError()); return; } continue; } SI = SocketArray[Index - WSA_WAIT_EVENT_0]; WSAResetEvent(EventArray[Index - WSA_WAIT_EVENT_0]); if (WSAGetOverlappedResult(SI->Socket, &(SI->Overlapped), &BytesTransferred, FALSE, &Flags) == FALSE) { printf("WSAGetOverlappedResult failed with error %d\n", WSAGetLastError()); return; } // First check to see if the peer has closed the connection and if so // then close the socket and cleanup the SOCKET_INFORMATION structure // associated with the socket. if (BytesTransferred == 0) { printf("Closing socket %d\n", SI->Socket); if (closesocket(SI->Socket) == SOCKET_ERROR) { printf("closesocket() failed with error %d\n", WSAGetLastError()); } GlobalFree(SI); WSACloseEvent(EventArray[Index - WSA_WAIT_EVENT_0]); // Cleanup SocketArray and EventArray by removing the socket event handle // and socket information structure if they are not at the end of the // arrays. if ((Index - WSA_WAIT_EVENT_0) + 1 != EventTotal) for (i = Index - WSA_WAIT_EVENT_0; i < EventTotal; i++) { EventArray[i] = EventArray[i + 1]; SocketArray[i] = SocketArray[i + 1]; } EventTotal--; continue; } // Check to see if the BytesRECV field equals zero. If this is so, then // this means a WSARecv call just completed so update the BytesRECV field // with the BytesTransferred value from the completed WSARecv() call. if (SI->BytesRECV == 0) { SI->BytesRECV = BytesTransferred; SI->BytesSEND = 0; } else { SI->BytesSEND += BytesTransferred; } if (SI->BytesRECV > SI->BytesSEND) { // Post another WSASend() request. // Since WSASend() is not gauranteed to send all of the bytes requested, // continue posting WSASend() calls until all received bytes are sent. ZeroMemory(&(SI->Overlapped), sizeof(WSAOVERLAPPED)); SI->Overlapped.hEvent = EventArray[Index - WSA_WAIT_EVENT_0]; SI->DataBuf.buf = SI->Buffer + SI->BytesSEND; SI->DataBuf.len = SI->BytesRECV - SI->BytesSEND; if (WSASend(SI->Socket, &(SI->DataBuf), 1, &SendBytes, 0, &(SI->Overlapped), NULL) == SOCKET_ERROR) { if (WSAGetLastError() != ERROR_IO_PENDING) { printf("WSASend() failed with error %d\n", WSAGetLastError()); return; } } } else { SI->BytesRECV = 0; // Now that there are no more bytes to send post another WSARecv() request. Flags = 0; ZeroMemory(&(SI->Overlapped), sizeof(WSAOVERLAPPED)); SI->Overlapped.hEvent = EventArray[Index - WSA_WAIT_EVENT_0]; SI->DataBuf.len = DATA_BUFSIZE; SI->DataBuf.buf = SI->Buffer; if (WSARecv(SI->Socket, &(SI->DataBuf), 1, &RecvBytes, &Flags, &(SI->Overlapped), NULL) == SOCKET_ERROR) { if (WSAGetLastError() != ERROR_IO_PENDING) { printf("WSARecv() failed with error %d\n", WSAGetLastError()); return; } } } } }
/* * pj_ioqueue_accept() * * Initiate overlapped accept() operation. */ PJ_DEF(pj_status_t) pj_ioqueue_accept( pj_ioqueue_key_t *key, pj_ioqueue_op_key_t *op_key, pj_sock_t *new_sock, pj_sockaddr_t *local, pj_sockaddr_t *remote, int *addrlen) { BOOL rc; DWORD bytesReceived; pj_status_t status; union operation_key *op_key_rec; SOCKET sock; PJ_CHECK_STACK(); PJ_ASSERT_RETURN(key && op_key && new_sock, PJ_EINVAL); #if PJ_IOQUEUE_HAS_SAFE_UNREG /* Check key is not closing */ if (key->closing) return PJ_ECANCELLED; #endif /* * See if there is a new connection immediately available. */ sock = WSAAccept((SOCKET)key->hnd, remote, addrlen, NULL, 0); if (sock != INVALID_SOCKET) { /* Yes! New socket is available! */ if (local && addrlen) { int status; /* On WinXP or later, use SO_UPDATE_ACCEPT_CONTEXT so that socket * addresses can be obtained with getsockname() and getpeername(). */ status = setsockopt(sock, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, (char*)&key->hnd, sizeof(SOCKET)); /* SO_UPDATE_ACCEPT_CONTEXT is for WinXP or later. * So ignore the error status. */ status = getsockname(sock, local, addrlen); if (status != 0) { DWORD dwError = WSAGetLastError(); closesocket(sock); return PJ_RETURN_OS_ERROR(dwError); } } *new_sock = sock; return PJ_SUCCESS; } else { DWORD dwError = WSAGetLastError(); if (dwError != WSAEWOULDBLOCK) { return PJ_RETURN_OS_ERROR(dwError); } } /* * No connection is immediately available. * Must schedule an asynchronous operation. */ op_key_rec = (union operation_key*)op_key->internal__; status = pj_sock_socket(pj_AF_INET(), pj_SOCK_STREAM(), 0, &op_key_rec->accept.newsock); if (status != PJ_SUCCESS) return status; op_key_rec->accept.operation = PJ_IOQUEUE_OP_ACCEPT; op_key_rec->accept.addrlen = addrlen; op_key_rec->accept.local = local; op_key_rec->accept.remote = remote; op_key_rec->accept.newsock_ptr = new_sock; pj_bzero( &op_key_rec->accept.overlapped, sizeof(op_key_rec->accept.overlapped)); rc = AcceptEx( (SOCKET)key->hnd, (SOCKET)op_key_rec->accept.newsock, op_key_rec->accept.accept_buf, 0, ACCEPT_ADDR_LEN, ACCEPT_ADDR_LEN, &bytesReceived, &op_key_rec->accept.overlapped ); if (rc == TRUE) { ioqueue_on_accept_complete(key, &op_key_rec->accept); return PJ_SUCCESS; } else { DWORD dwStatus = WSAGetLastError(); if (dwStatus!=WSA_IO_PENDING) return PJ_STATUS_FROM_OS(dwStatus); } /* Asynchronous Accept() has been submitted. */ return PJ_EPENDING; }
int socket_accept4(int s,char *ip,uint16 *port) { struct sockaddr_in si; socklen_t len = sizeof si; int fd; #ifdef __MINGW32__ io_entry* e=array_get(&io_fds,sizeof(io_entry),s); if (e && e->inuse) { int sa2len; fd=-1; if (e->acceptqueued==1) { errno=EAGAIN; return -1; } if (e->acceptqueued==2) { incoming: /* incoming! */ { struct sockaddr* x,* y; GetAcceptExSockaddrs(e->inbuf,0,200,200,&x,&sa2len,&y,&len); if (len>sizeof(si)) len=sizeof(si); memcpy(&si,y,len); } fd=e->next_accept; e->next_accept=0; if (e->nonblock) { if (io_fd(fd)) { io_entry* f=array_get(&io_fds,sizeof(io_entry),fd); if (f) { f->nonblock=1; /* printf("setting fd %lu to non-blocking\n",(int)fd);*/ } } } } /* no accept queued, queue one now. */ if (e->next_accept==0) { e->next_accept=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); if (e==-1) return winsock2errno(-1); } if (AcceptEx(s,e->next_accept,e->inbuf,0,200,200,&e->errorcode,&e->or)) goto incoming; if (WSAGetLastError() != ERROR_IO_PENDING) return winsock2errno(-1); e->acceptqueued=1; if (fd==-1) { errno=EAGAIN; return fd; } } else { #endif if ((fd=accept(s,(void*) &si,&len))==-1) return winsock2errno(-1); #ifdef __MINGW32__ } #endif if (ip) *(uint32*)ip = *(uint32*)&si.sin_addr; if (port) uint16_unpack_big((char *) &si.sin_port,port); return fd; }
static unsigned int __stdcall winnt_accept(void *lr_) { ap_listen_rec *lr = (ap_listen_rec *)lr_; apr_os_sock_info_t sockinfo; winnt_conn_ctx_t *context = NULL; DWORD BytesRead; SOCKET nlsd; core_server_config *core_sconf; const char *accf_name; int rv; int accf; int err_count = 0; HANDLE events[3]; #if APR_HAVE_IPV6 SOCKADDR_STORAGE ss_listen; int namelen = sizeof(ss_listen); #endif u_long zero = 0; core_sconf = ap_get_core_module_config(ap_server_conf->module_config); accf_name = apr_table_get(core_sconf->accf_map, lr->protocol); if (strcmp(accf_name, "data") == 0) accf = 2; else if (strcmp(accf_name, "connect") == 0) accf = 1; else if (strcmp(accf_name, "none") == 0) accf = 0; else { accf = 0; accf_name = "none"; ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ap_server_conf, APLOGNO(00331) "winnt_accept: unrecognized AcceptFilter '%s', " "only 'data', 'connect' or 'none' are valid. " "Using 'none' instead", accf_name); } apr_os_sock_get(&nlsd, lr->sd); #if APR_HAVE_IPV6 if (getsockname(nlsd, (struct sockaddr *)&ss_listen, &namelen) == SOCKET_ERROR) { ap_log_error(APLOG_MARK, APLOG_ERR, apr_get_netos_error(), ap_server_conf, APLOGNO(00332) "winnt_accept: getsockname error on listening socket, " "is IPv6 available?"); return 1; } #endif if (accf > 0) /* 'data' or 'connect' */ { /* first, high priority event is an already accepted connection */ events[1] = exit_event; events[2] = max_requests_per_child_event; } else /* accf == 0, 'none' */ { reinit: /* target of data or connect upon too many AcceptEx failures */ /* last, low priority event is a not yet accepted connection */ events[0] = exit_event; events[1] = max_requests_per_child_event; events[2] = CreateEvent(NULL, FALSE, FALSE, NULL); /* The event needs to be removed from the accepted socket, * if not removed from the listen socket prior to accept(), */ rv = WSAEventSelect(nlsd, events[2], FD_ACCEPT); if (rv) { ap_log_error(APLOG_MARK, APLOG_ERR, apr_get_netos_error(), ap_server_conf, APLOGNO(00333) "WSAEventSelect() failed."); CloseHandle(events[2]); return 1; } } ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(00334) "Child: Accept thread listening on %pI using AcceptFilter %s", lr->bind_addr, accf_name); while (!shutdown_in_progress) { if (!context) { int timeout; context = mpm_get_completion_context(&timeout); if (!context) { if (!timeout) { /* Hopefully a temporary condition in the provider? */ ++err_count; if (err_count > MAX_ACCEPTEX_ERR_COUNT) { ap_log_error(APLOG_MARK, APLOG_CRIT, 0, ap_server_conf, APLOGNO(00335) "winnt_accept: Too many failures grabbing a " "connection ctx. Aborting."); break; } } Sleep(100); continue; } } if (accf > 0) /* Either 'connect' or 'data' */ { DWORD len; char *buf; /* Create and initialize the accept socket */ #if APR_HAVE_IPV6 if (context->accept_socket == INVALID_SOCKET) { context->accept_socket = socket(ss_listen.ss_family, SOCK_STREAM, IPPROTO_TCP); context->socket_family = ss_listen.ss_family; } else if (context->socket_family != ss_listen.ss_family) { closesocket(context->accept_socket); context->accept_socket = socket(ss_listen.ss_family, SOCK_STREAM, IPPROTO_TCP); context->socket_family = ss_listen.ss_family; } #else if (context->accept_socket == INVALID_SOCKET) context->accept_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); #endif if (context->accept_socket == INVALID_SOCKET) { ap_log_error(APLOG_MARK, APLOG_WARNING, apr_get_netos_error(), ap_server_conf, APLOGNO(00336) "winnt_accept: Failed to allocate an accept socket. " "Temporary resource constraint? Try again."); Sleep(100); continue; } if (accf == 2) { /* 'data' */ len = APR_BUCKET_BUFF_SIZE; buf = apr_bucket_alloc(len, context->ba); len -= PADDED_ADDR_SIZE * 2; } else /* (accf == 1) 'connect' */ { len = 0; buf = context->buff; } /* AcceptEx on the completion context. The completion context will be * signaled when a connection is accepted. */ if (!AcceptEx(nlsd, context->accept_socket, buf, len, PADDED_ADDR_SIZE, PADDED_ADDR_SIZE, &BytesRead, &context->overlapped)) { rv = apr_get_netos_error(); if ((rv == APR_FROM_OS_ERROR(WSAECONNRESET)) || (rv == APR_FROM_OS_ERROR(WSAEACCES))) { /* We can get here when: * 1) the client disconnects early * 2) handshake was incomplete */ if (accf == 2) apr_bucket_free(buf); closesocket(context->accept_socket); context->accept_socket = INVALID_SOCKET; continue; } else if ((rv == APR_FROM_OS_ERROR(WSAEINVAL)) || (rv == APR_FROM_OS_ERROR(WSAENOTSOCK))) { /* We can get here when: * 1) TransmitFile does not properly recycle the accept socket (typically * because the client disconnected) * 2) there is VPN or Firewall software installed with * buggy WSAAccept or WSADuplicateSocket implementation * 3) the dynamic address / adapter has changed * Give five chances, then fall back on AcceptFilter 'none' */ if (accf == 2) apr_bucket_free(buf); closesocket(context->accept_socket); context->accept_socket = INVALID_SOCKET; ++err_count; if (err_count > MAX_ACCEPTEX_ERR_COUNT) { ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf, APLOGNO(00337) "Child: Encountered too many AcceptEx " "faults accepting client connections. " "Possible causes: dynamic address renewal, " "or incompatible VPN or firewall software. "); ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, ap_server_conf, APLOGNO(00338) "winnt_mpm: falling back to " "'AcceptFilter none'."); err_count = 0; accf = 0; } continue; } else if ((rv != APR_FROM_OS_ERROR(ERROR_IO_PENDING)) && (rv != APR_FROM_OS_ERROR(WSA_IO_PENDING))) { if (accf == 2) apr_bucket_free(buf); closesocket(context->accept_socket); context->accept_socket = INVALID_SOCKET; ++err_count; if (err_count > MAX_ACCEPTEX_ERR_COUNT) { ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf, APLOGNO(00339) "Child: Encountered too many AcceptEx " "faults accepting client connections."); ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, ap_server_conf, APLOGNO(00340) "winnt_mpm: falling back to " "'AcceptFilter none'."); err_count = 0; accf = 0; goto reinit; } continue; } err_count = 0; events[0] = context->overlapped.hEvent; do { rv = WaitForMultipleObjectsEx(3, events, FALSE, INFINITE, TRUE); } while (rv == WAIT_IO_COMPLETION); if (rv == WAIT_OBJECT_0) { if ((context->accept_socket != INVALID_SOCKET) && !GetOverlappedResult((HANDLE)context->accept_socket, &context->overlapped, &BytesRead, FALSE)) { ap_log_error(APLOG_MARK, APLOG_WARNING, apr_get_os_error(), ap_server_conf, APLOGNO(00341) "winnt_accept: Asynchronous AcceptEx failed."); closesocket(context->accept_socket); context->accept_socket = INVALID_SOCKET; } } else { /* exit_event triggered or event handle was closed */ closesocket(context->accept_socket); context->accept_socket = INVALID_SOCKET; if (accf == 2) apr_bucket_free(buf); break; } if (context->accept_socket == INVALID_SOCKET) { if (accf == 2) apr_bucket_free(buf); continue; } } err_count = 0; /* Potential optimization; consider handing off to the worker */ /* Inherit the listen socket settings. Required for * shutdown() to work */ if (setsockopt(context->accept_socket, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, (char *)&nlsd, sizeof(nlsd))) { ap_log_error(APLOG_MARK, APLOG_WARNING, apr_get_netos_error(), ap_server_conf, APLOGNO(00342) "setsockopt(SO_UPDATE_ACCEPT_CONTEXT) failed."); /* Not a failure condition. Keep running. */ } /* Get the local & remote address * TODO; error check */ GetAcceptExSockaddrs(buf, len, PADDED_ADDR_SIZE, PADDED_ADDR_SIZE, &context->sa_server, &context->sa_server_len, &context->sa_client, &context->sa_client_len); /* For 'data', craft a bucket for our data result * and pass to worker_main as context->overlapped.Pointer */ if (accf == 2 && BytesRead) { apr_bucket *b; b = apr_bucket_heap_create(buf, APR_BUCKET_BUFF_SIZE, apr_bucket_free, context->ba); /* Adjust the bucket to refer to the actual bytes read */ b->length = BytesRead; context->overlapped.Pointer = b; } else context->overlapped.Pointer = NULL; } else /* (accf = 0) e.g. 'none' */ { /* There is no socket reuse without AcceptEx() */ if (context->accept_socket != INVALID_SOCKET) closesocket(context->accept_socket); /* This could be a persistent event per-listener rather than * per-accept. However, the event needs to be removed from * the target socket if not removed from the listen socket * prior to accept(), or the event select is inherited. * and must be removed from the accepted socket. */ do { rv = WaitForMultipleObjectsEx(3, events, FALSE, INFINITE, TRUE); } while (rv == WAIT_IO_COMPLETION); if (rv != WAIT_OBJECT_0 + 2) { /* not FD_ACCEPT; * exit_event triggered or event handle was closed */ break; } context->sa_server = (void *) context->buff; context->sa_server_len = sizeof(context->buff) / 2; context->sa_client_len = context->sa_server_len; context->sa_client = (void *) (context->buff + context->sa_server_len); context->accept_socket = accept(nlsd, context->sa_server, &context->sa_server_len); if (context->accept_socket == INVALID_SOCKET) { rv = apr_get_netos_error(); if ( rv == APR_FROM_OS_ERROR(WSAECONNRESET) || rv == APR_FROM_OS_ERROR(WSAEINPROGRESS) || rv == APR_FROM_OS_ERROR(WSAEWOULDBLOCK) ) { ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, ap_server_conf, APLOGNO(00343) "accept() failed, retrying."); continue; } /* A more serious error than 'retry', log it */ ap_log_error(APLOG_MARK, APLOG_WARNING, rv, ap_server_conf, APLOGNO(00344) "accept() failed."); if ( rv == APR_FROM_OS_ERROR(WSAEMFILE) || rv == APR_FROM_OS_ERROR(WSAENOBUFS) ) { /* Hopefully a temporary condition in the provider? */ Sleep(100); ++err_count; if (err_count > MAX_ACCEPTEX_ERR_COUNT) { ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf, APLOGNO(00345) "Child: Encountered too many accept() " "resource faults, aborting."); break; } continue; } break; } /* Per MSDN, cancel the inherited association of this socket * to the WSAEventSelect API, and restore the state corresponding * to apr_os_sock_make's default assumptions (really, a flaw within * os_sock_make and os_sock_put that it does not query). */ WSAEventSelect(context->accept_socket, 0, 0); context->overlapped.Pointer = NULL; err_count = 0; context->sa_server_len = sizeof(context->buff) / 2; if (getsockname(context->accept_socket, context->sa_server, &context->sa_server_len) == SOCKET_ERROR) { ap_log_error(APLOG_MARK, APLOG_WARNING, apr_get_netos_error(), ap_server_conf, APLOGNO(00346) "getsockname failed"); continue; } if ((getpeername(context->accept_socket, context->sa_client, &context->sa_client_len)) == SOCKET_ERROR) { ap_log_error(APLOG_MARK, APLOG_WARNING, apr_get_netos_error(), ap_server_conf, APLOGNO(00347) "getpeername failed"); memset(&context->sa_client, '\0', sizeof(context->sa_client)); } } sockinfo.os_sock = &context->accept_socket; sockinfo.local = context->sa_server; sockinfo.remote = context->sa_client; sockinfo.family = context->sa_server->sa_family; sockinfo.type = SOCK_STREAM; sockinfo.protocol = IPPROTO_TCP; /* Restore the state corresponding to apr_os_sock_make's default * assumption of timeout -1 (really, a flaw of os_sock_make and * os_sock_put that it does not query to determine ->timeout). * XXX: Upon a fix to APR, these three statements should disappear. */ ioctlsocket(context->accept_socket, FIONBIO, &zero); setsockopt(context->accept_socket, SOL_SOCKET, SO_RCVTIMEO, (char *) &zero, sizeof(zero)); setsockopt(context->accept_socket, SOL_SOCKET, SO_SNDTIMEO, (char *) &zero, sizeof(zero)); apr_os_sock_make(&context->sock, &sockinfo, context->ptrans); /* When a connection is received, send an io completion notification * to the ThreadDispatchIOCP. */ PostQueuedCompletionStatus(ThreadDispatchIOCP, BytesRead, IOCP_CONNECTION_ACCEPTED, &context->overlapped); context = NULL; } if (!accf) CloseHandle(events[2]); if (!shutdown_in_progress) { /* Yow, hit an irrecoverable error! Tell the child to die. */ SetEvent(exit_event); } ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, ap_server_conf, APLOGNO(00348) "Child: Accept thread exiting."); return 0; }
static unsigned int __stdcall winnt_accept(void *lr_) { ap_listen_rec *lr = (ap_listen_rec *)lr_; apr_os_sock_info_t sockinfo; PCOMP_CONTEXT context = NULL; DWORD BytesRead; SOCKET nlsd; int rv, err_count = 0; #if APR_HAVE_IPV6 SOCKADDR_STORAGE ss_listen; int namelen = sizeof(ss_listen); #endif apr_os_sock_get(&nlsd, lr->sd); #if APR_HAVE_IPV6 if (getsockname(nlsd, (struct sockaddr *)&ss_listen, &namelen) == SOCKET_ERROR) { ap_log_error(APLOG_MARK,APLOG_ERR, apr_get_netos_error(), ap_server_conf, "winnt_accept: getsockname error on listening socket, is IPv6 available?"); return 1; } #endif ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, "Child %lu: Starting thread to listen on port %d.", my_pid, lr->bind_addr->port); while (!shutdown_in_progress) { if (!context) { context = mpm_get_completion_context(); if (!context) { /* Temporary resource constraint? */ Sleep(0); continue; } } /* Create and initialize the accept socket */ #if APR_HAVE_IPV6 if (context->accept_socket == INVALID_SOCKET) { context->accept_socket = socket(ss_listen.ss_family, SOCK_STREAM, IPPROTO_TCP); context->socket_family = ss_listen.ss_family; } else if (context->socket_family != ss_listen.ss_family) { closesocket(context->accept_socket); context->accept_socket = socket(ss_listen.ss_family, SOCK_STREAM, IPPROTO_TCP); context->socket_family = ss_listen.ss_family; } if (context->accept_socket == INVALID_SOCKET) { ap_log_error(APLOG_MARK,APLOG_WARNING, apr_get_netos_error(), ap_server_conf, "winnt_accept: Failed to allocate an accept socket. " "Temporary resource constraint? Try again."); Sleep(100); continue; } #else if (context->accept_socket == INVALID_SOCKET) { context->accept_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (context->accept_socket == INVALID_SOCKET) { /* Another temporary condition? */ ap_log_error(APLOG_MARK,APLOG_WARNING, apr_get_netos_error(), ap_server_conf, "winnt_accept: Failed to allocate an accept socket. " "Temporary resource constraint? Try again."); Sleep(100); continue; } } #endif /* AcceptEx on the completion context. The completion context will be * signaled when a connection is accepted. */ if (!AcceptEx(nlsd, context->accept_socket, context->buff, 0, PADDED_ADDR_SIZE, PADDED_ADDR_SIZE, &BytesRead, &context->Overlapped)) { rv = apr_get_netos_error(); if ((rv == APR_FROM_OS_ERROR(WSAEINVAL)) || (rv == APR_FROM_OS_ERROR(WSAENOTSOCK))) { /* We can get here when: * 1) the client disconnects early * 2) TransmitFile does not properly recycle the accept socket (typically * because the client disconnected) * 3) there is VPN or Firewall software installed with buggy AcceptEx implementation * 4) the webserver is using a dynamic address that has changed */ ++err_count; closesocket(context->accept_socket); context->accept_socket = INVALID_SOCKET; if (err_count > MAX_ACCEPTEX_ERR_COUNT) { ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf, "Child %lu: Encountered too many errors accepting client connections. " "Possible causes: dynamic address renewal, or incompatible VPN or firewall software. " "Try using the Win32DisableAcceptEx directive.", my_pid); err_count = 0; } continue; } else if ((rv != APR_FROM_OS_ERROR(ERROR_IO_PENDING)) && (rv != APR_FROM_OS_ERROR(WSA_IO_PENDING))) { ++err_count; if (err_count > MAX_ACCEPTEX_ERR_COUNT) { ap_log_error(APLOG_MARK,APLOG_ERR, rv, ap_server_conf, "Child %lu: Encountered too many errors accepting client connections. " "Possible causes: Unknown. " "Try using the Win32DisableAcceptEx directive.", my_pid); err_count = 0; } closesocket(context->accept_socket); context->accept_socket = INVALID_SOCKET; continue; } err_count = 0; /* Wait for pending i/o. * Wake up once per second to check for shutdown . * XXX: We should be waiting on exit_event instead of polling */ while (1) { rv = WaitForSingleObject(context->Overlapped.hEvent, 1000); if (rv == WAIT_OBJECT_0) { if (context->accept_socket == INVALID_SOCKET) { /* socket already closed */ break; } if (!GetOverlappedResult((HANDLE)context->accept_socket, &context->Overlapped, &BytesRead, FALSE)) { ap_log_error(APLOG_MARK, APLOG_WARNING, apr_get_os_error(), ap_server_conf, "winnt_accept: Asynchronous AcceptEx failed."); closesocket(context->accept_socket); context->accept_socket = INVALID_SOCKET; } break; } /* WAIT_TIMEOUT */ if (shutdown_in_progress) { closesocket(context->accept_socket); context->accept_socket = INVALID_SOCKET; break; } } if (context->accept_socket == INVALID_SOCKET) { continue; } } err_count = 0; /* Inherit the listen socket settings. Required for * shutdown() to work */ if (setsockopt(context->accept_socket, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, (char *)&nlsd, sizeof(nlsd))) { ap_log_error(APLOG_MARK, APLOG_WARNING, apr_get_netos_error(), ap_server_conf, "setsockopt(SO_UPDATE_ACCEPT_CONTEXT) failed."); /* Not a failure condition. Keep running. */ } /* Get the local & remote address */ GetAcceptExSockaddrs(context->buff, 0, PADDED_ADDR_SIZE, PADDED_ADDR_SIZE, &context->sa_server, &context->sa_server_len, &context->sa_client, &context->sa_client_len); sockinfo.os_sock = &context->accept_socket; sockinfo.local = context->sa_server; sockinfo.remote = context->sa_client; sockinfo.family = context->sa_server->sa_family; sockinfo.type = SOCK_STREAM; apr_os_sock_make(&context->sock, &sockinfo, context->ptrans); /* When a connection is received, send an io completion notification to * the ThreadDispatchIOCP. This function could be replaced by * mpm_post_completion_context(), but why do an extra function call... */ PostQueuedCompletionStatus(ThreadDispatchIOCP, 0, IOCP_CONNECTION_ACCEPTED, &context->Overlapped); context = NULL; } if (!shutdown_in_progress) { /* Yow, hit an irrecoverable error! Tell the child to die. */ SetEvent(exit_event); } ap_log_error(APLOG_MARK, APLOG_INFO, APR_SUCCESS, ap_server_conf, "Child %lu: Accept thread exiting.", my_pid); return 0; }