Beispiel #1
0
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;
}
Beispiel #2
0
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());
	}
}
Beispiel #3
0
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;
}
Beispiel #4
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");
}
Beispiel #5
0
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;
}
Beispiel #6
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);
		}
	}
}
Beispiel #7
0
	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;

	}
Beispiel #8
0
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;
}
Beispiel #10
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);
	}
}
Beispiel #11
0
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);
		}
	}
}
Beispiel #12
0
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
}
Beispiel #13
0
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();
	}
}
Beispiel #14
0
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");
}
Beispiel #15
0
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;
}
Beispiel #16
0
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();
    }
}
Beispiel #17
0
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();
}
Beispiel #18
0
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");
}
Beispiel #19
0
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;
}
Beispiel #20
0
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;
}
Beispiel #22
0
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 {
Beispiel #25
0
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" ) ;
	}
}
Beispiel #26
0
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;
}
Beispiel #28
0
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;
}
Beispiel #29
0
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;
}
Beispiel #30
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;
}