Exemple #1
0
bool_t AsyncAcceptor::GetPeerInfomation(char_t *buffer, uint32_t size, AsyncSession *sess)
{
	bool_t ret = FALSE;

	#ifdef OS_WINDOWS
	sockaddr_in *local_addr		= 0;
	sockaddr_in *remote_addr	= 0;
	int32_t local_addr_len		= 0;
	int32_t remote_addr_len		= 0;

	GetAcceptExSockaddrs(buffer,
						0,
						sizeof(sockaddr_in) + 16,
						sizeof(sockaddr_in) + 16,
						(sockaddr **)&local_addr,
						&local_addr_len,
						(sockaddr **)&remote_addr,
						&remote_addr_len);

	Socket *sock = (Socket *)sess->Handle();
	if(!sock) { ECILA_TRACE(); return FALSE; }

	IPAddrs *ipaddr = sock->GetIpAddrs();
	if(!ipaddr) { ECILA_TRACE(); return FALSE; }

	ret = ipaddr->Init(remote_addr);
	if(!ret) { ECILA_TRACE(); return FALSE; }

	#endif


	return TRUE;
}
ConnectionPtr SocketConnection::acceptSync()
{
    LB_TS_THREAD( _recvThread );
    if( !isListening( ))
        return 0;

    LBASSERT( _overlappedAcceptData );
    LBASSERT( _overlappedSocket != INVALID_SOCKET );
    if( _overlappedSocket == INVALID_SOCKET )
        return 0;

    // complete accept
    DWORD got   = 0;
    DWORD flags = 0;

    if( !WSAGetOverlappedResult( _readFD, &_overlappedRead, &got, TRUE,
                                 &flags ))
    {
        LBWARN << "Accept completion failed: " << lunchbox::sysError
               << ", closing socket" << std::endl;
        close();
        return 0;
    }

    sockaddr_in* local     = 0;
    sockaddr_in* remote    = 0;
    int          localLen  = 0;
    int          remoteLen = 0;
    GetAcceptExSockaddrs( _overlappedAcceptData, 0, sizeof( sockaddr_in ) + 16,
                          sizeof( sockaddr_in ) + 16, (sockaddr**)&local,
                          &localLen, (sockaddr**)&remote, &remoteLen );
    _tuneSocket( _overlappedSocket );

    ConstConnectionDescriptionPtr description = getDescription();
    SocketConnection* newConnection = new SocketConnection;
    ConnectionPtr connection( newConnection ); // to keep ref-counting correct

    newConnection->_readFD  = _overlappedSocket;
    newConnection->_writeFD = _overlappedSocket;

#ifndef _WIN32
    //fcntl( _overlappedSocket, F_SETFL, O_NONBLOCK );
#endif

    newConnection->_initAIORead();
    _overlappedSocket       = INVALID_SOCKET;

    newConnection->_setState( STATE_CONNECTED );
    ConnectionDescriptionPtr newDescription = newConnection->_getDescription();
    newDescription->bandwidth = description->bandwidth;
    newDescription->port = ntohs( remote->sin_port );
    newDescription->setHostname( getHostName( *remote ));

    LBDEBUG << "accepted connection from " << newDescription->getHostname()
           << ":" << newDescription->port << std::endl;
    return connection;
}
/*
 * Process the socket when the overlapped accept() completed.
 */
static void ioqueue_on_accept_complete(pj_ioqueue_key_t *key,
                                       ioqueue_accept_rec *accept_overlapped)
{
    struct sockaddr *local;
    struct sockaddr *remote;
    int locallen, remotelen;
    pj_status_t status;

    PJ_CHECK_STACK();

    /* On WinXP or later, use SO_UPDATE_ACCEPT_CONTEXT so that socket 
     * addresses can be obtained with getsockname() and getpeername().
     */
    status = setsockopt(accept_overlapped->newsock, 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.
     */

    /* Operation complete immediately. */
    if (accept_overlapped->addrlen) {
	GetAcceptExSockaddrs( accept_overlapped->accept_buf,
			      0, 
			      ACCEPT_ADDR_LEN,
			      ACCEPT_ADDR_LEN,
			      &local,
			      &locallen,
			      &remote,
			      &remotelen);
	if (*accept_overlapped->addrlen >= locallen) {
	    if (accept_overlapped->local)
		pj_memcpy(accept_overlapped->local, local, locallen);
	    if (accept_overlapped->remote)
		pj_memcpy(accept_overlapped->remote, remote, locallen);
	} else {
	    if (accept_overlapped->local)
		pj_bzero(accept_overlapped->local, 
			 *accept_overlapped->addrlen);
	    if (accept_overlapped->remote)
		pj_bzero(accept_overlapped->remote, 
			 *accept_overlapped->addrlen);
	}

	*accept_overlapped->addrlen = locallen;
    }
    if (accept_overlapped->newsock_ptr)
        *accept_overlapped->newsock_ptr = accept_overlapped->newsock;
    accept_overlapped->operation = 0;
}
Exemple #4
0
ConnectionPtr PGMConnection::acceptSync()
{
    EQ_TS_THREAD( _recvThread );
    if( _state != STATE_LISTENING )
        return 0;

    EQASSERT( _overlappedAcceptData );
    EQASSERT( _overlappedSocket != INVALID_SOCKET );
    if( _overlappedSocket == INVALID_SOCKET )
        return 0;

    // complete accept
    DWORD got   = 0;
    DWORD flags = 0;
    if( !WSAGetOverlappedResult( _readFD, &_overlapped, &got, TRUE, &flags ))
    {
        EQWARN << "Accept completion failed: " << base::sysError 
               << ", closing connection" << std::endl;
        close();
        return 0;
    }

    sockaddr_in* local     = 0;
    sockaddr_in* remote    = 0;
    int          localLen  = 0;
    int          remoteLen = 0;
    GetAcceptExSockaddrs( _overlappedAcceptData, 0, sizeof( sockaddr_in ) + 16,
                          sizeof( sockaddr_in ) + 16, (sockaddr**)&local, 
                          &localLen, (sockaddr**)&remote, &remoteLen );

    PGMConnection* newConnection = new PGMConnection;
    ConnectionPtr connection( newConnection ); // to keep ref-counting correct

    newConnection->_readFD  = _overlappedSocket;
    _overlappedSocket       = INVALID_SOCKET;

    newConnection->_setupReadSocket();
    newConnection->_writeFD = _writeFD;
    newConnection->_initAIORead();
    newConnection->_state       = STATE_CONNECTED;
    newConnection->_description = _description;

    EQINFO << "accepted connection " << (void*)newConnection << " from " 
           << inet_ntoa( remote->sin_addr ) << ":" << ntohs( remote->sin_port )
           << std::endl;
    return connection;
}
	void IOCPConnection::OnConnect( void* pBuf )
	{
		struct sockaddr_in* pMyAddr = NULL;
		struct sockaddr_in* pPeerAddr = NULL;
		int myLen, peerLen;

		GetAcceptExSockaddrs( pBuf, 0, sizeof(sockaddr_in)+16, sizeof(sockaddr_in)+16,
							reinterpret_cast<sockaddr**>(&pMyAddr), &myLen, 
							reinterpret_cast<sockaddr**>(&pPeerAddr), &peerLen );

		m_myAddr.SetAddr( inet_ntoa(pMyAddr->sin_addr) );
		m_myAddr.SetPort( ntohs(pMyAddr->sin_port) );
		m_peerAddr.SetAddr( inet_ntoa(pPeerAddr->sin_addr) );
		m_peerAddr.SetPort( ntohs(pPeerAddr->sin_port) );
		
		m_bConnected = true;
	}
//클라이언트의ㅡ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;
}
Exemple #7
0
bool CClient::PostConnect(NetData* pData)
{
	CLock lock(&m_criticalSection);
	m_status = NETSTATUS_Connected;
	SOCKADDR* localAddr = NULL;
	SOCKADDR* remoteAddr = NULL;
	int localAddrLen = 0;
	int remoteAddrLen = 0;
	GetAcceptExSockaddrs(pData->buffer.buf, 0,
		sizeof(SOCKADDR_IN)+16, sizeof(SOCKADDR_IN)+16, 
		&localAddr, &localAddrLen, &remoteAddr, &remoteAddrLen);

	SOCKET listenSocket = m_pServer->GetListenSocket();
	if (setsockopt(m_socket, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, (const char*)&listenSocket, sizeof(listenSocket)) == SOCKET_ERROR)
	{
		LOGNET("Client[%d] fail to update accept context.", GetID());
		return false;
	}

	if (!m_completePort)
	{
		if (CreateIoCompletionPort((HANDLE)m_socket, m_pManager->GetIOCompletePort(), (ULONG_PTR)this, 0) == NULL)
		{
			LOG("Fail to associate client[%d] socket with completion port.", GetID());
			return false;
		}
		m_completePort = true;
	}
	m_send.Clean();
	m_recv.Clean();
	m_discon.Clean();
	m_accept.Clean();
	m_lastActionTime = 0;
	m_status = NETSTATUS_CompletionNotify;
	return true;
}
Exemple #8
0
DWORD ThreadProcess(LPVOID pParam)
{
	ThreadInfo* pThreadInfo = (ThreadInfo*)pParam;

	HANDLE hIOCP = pThreadInfo->hIOCP;
	SOCKET sListenConn = pThreadInfo->Conn;
	NetMsg* pReadMsg = pThreadInfo->ReadMsg;
	NetMsg* pWriteMsg = pThreadInfo->WriteMsg;
	OverLapped* pOver = NULL;
	SOCKET* pConn	  = NULL;
	DWORD	dwBytes;
	DWORD	dwFlag;	

	for (;;)
	{

		GetQueuedCompletionStatus(hIOCP, &dwBytes, (PULONG_PTR)&pConn, (LPOVERLAPPED*)&pOver, INFINITE);
		
		if (!pConn && !pOver)
			return 0;

		
		if ((dwBytes == 0 && (pOver->opType == OverLapped::OLOpType::EOLOT_Send || pOver->opType == OverLapped::OLOpType::EOLOT_Recv)) || (pOver->opType == OverLapped::OLOpType::EOLOT_Accept && WSAGetLastError() == WSA_OPERATION_ABORTED))
		{
			closesocket((SOCKET)pOver->sysBuffer.len);
			delete pOver;
		}
		else
		{
			switch (pOver->opType)
			{
				case OverLapped::OLOpType::EOLOT_Accept:
				{
					SOCKET sAcceptConn = (SOCKET)pOver->sysBuffer.len;					
					int iLocalAddr, iRemoteAddr, iError;
					LPSOCKADDR pLocalAddr;
					sockaddr_in* pRemoteAddr = NULL;
					GetAcceptExSockaddrs(pOver->sysBuffer.buf, 0, AcceptExSockAddrInLen, AcceptExSockAddrInLen, 
										(PSOCKADDR*)&pLocalAddr, &iLocalAddr, (PSOCKADDR*)&pRemoteAddr, &iRemoteAddr);

					printf("new connect: %d.%d.%d.%d\n", pRemoteAddr->sin_addr.s_net, pRemoteAddr->sin_addr.s_host, pRemoteAddr->sin_addr.s_lh, pRemoteAddr->sin_addr.s_impno);
					
					// 更新连接进来的Socket,希望ClientSocket具有和ListenSocket相同的属性,对ClientSocket调用SO_UPDATE_ACCEPT_CONTEXT
					// git snap (00e097d): WSAEFAULT 参数4应该指针
					if (setsockopt(sAcceptConn, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, (char*)&sListenConn, sizeof(sListenConn)) == SOCKET_ERROR)
					{
						Log("EOLOT_Accept [%d] setsockopt Error[%d].\n", sAcceptConn, WSAGetLastError());
						closesocket(sAcceptConn);
						delete pOver;
						break;
					}

					// IOCP管理连接 
					// 参数4:指针
					if (!CreateIoCompletionPort((HANDLE)sAcceptConn, hIOCP, (DWORD_PTR)&sAcceptConn, 0))
					{
						Log("EOLOT_Accept [%d] CreateIoCompletionPort Error [%d].\n", sAcceptConn, WSAGetLastError());
						closesocket(sAcceptConn);
						delete pOver;
						break;
					}

					delete pOver;

					OverLapped* pRecvOver = new OverLapped;
					pRecvOver->opType = OverLapped::EOLOT_Recv;
					pRecvOver->sysBuffer.len = OverLappedBufferLen;
					ZeroMemory(pRecvOver->dataBuffer, OverLappedBufferLen);
					// 等待接受数据
					// git snap(6fa835e): Error = WSAEOPNOTSUPP(10045 Operation not supported), 参数5:flag错误
					DWORD dwTemp[2] = {0, 0}; 
					int nResult = WSARecv(sAcceptConn, &pRecvOver->sysBuffer, 1, &dwTemp[0], &dwTemp[1], &pRecvOver->sysOverLapped, NULL);
					if (nResult == SOCKET_ERROR && ((iError = WSAGetLastError()) != ERROR_IO_PENDING))
					{
						Log("EOLOT_Accept [%d] WSARecv Error[%d].\n", sAcceptConn, iError);
						closesocket(sAcceptConn);
						delete pRecvOver;
						break;
					}
					Log("EOLOT_Accept [%d] WSARecv OK.\n", sAcceptConn);

					// 发送第一个数据
					// git snap(): Erro = 
					OverLapped* pSendOver = new OverLapped;
					pSendOver->opType = OverLapped::OLOpType::EOLOT_Send;
					ZeroMemory(pSendOver->dataBuffer, OverLappedBufferLen);
					GetSendMsg(pSendOver->dataBuffer, pSendOver->sysBuffer.len);
					//sprintf_s(pSendOver->dataBuffer, "server new send time %d", GetTickCount());
					//pSendOver->sysBuffer.len = strlen(pSendOver->dataBuffer);					
					int nResult2 = WSASend(sAcceptConn, &pSendOver->sysBuffer, 1, &dwBytes, 0, &pSendOver->sysOverLapped, 0);
					if (nResult2 == SOCKET_ERROR && ((iError = WSAGetLastError()) != ERROR_IO_PENDING))
					{
						Log("EOLOT_Accept [%d] WSASend Error[%d].\n", sAcceptConn, iError);				
						closesocket(sAcceptConn);
						delete pSendOver;
						break;
					}

					Log("EOLOT_Accept WSASend OK");
				}break; // OverLapped::OLOpType::EOLOT_Accept

				case OverLapped::OLOpType::EOLOT_Send:
				{
					delete pOver;
				}break; // OverLapped::OLOpType::EOLOT_Send
				
				case OverLapped::OLOpType::EOLOT_Recv:
				{
					Log("EOLOT_Recv New Msg");
					char* pData = pOver->dataBuffer;
					SOCKET sAcceptConn = *pConn;
					pReadMsg->AddNewMsg((void*)pData, (size_t)dwBytes, sAcceptConn);

					// 等待接受下一组数据
					ZeroMemory(pOver->dataBuffer, OverLappedBufferLen);
					DWORD dwTemp[2] = { 0, 0 };
					int nResult = WSARecv(sAcceptConn, &pOver->sysBuffer, 1, &dwTemp[0], &dwTemp[1], &pOver->sysOverLapped, 0);
					if (nResult == SOCKET_ERROR && WSAGetLastError() != ERROR_IO_PENDING)
					{
						closesocket(sAcceptConn);
						delete pOver;
						break;
					}

					//// 模拟发送测试数据
					//OverLapped* pSendOver = new OverLapped;
					//pSendOver->opType = OverLapped::OLOpType::EOLOT_Send;
					//ZeroMemory(pSendOver->dataBuffer, OverLappedBufferLen);
					//sprintf_s(pSendOver->dataBuffer, "server new send time %d", GetTickCount());
					//pSendOver->sysBuffer.len = strlen(pSendOver->dataBuffer);
					//int nResult2 = WSASend(sAcceptConn, &pSendOver->sysBuffer, 1, &dwBytes, 0, &pSendOver->sysOverLapped, 0);
					//if (nResult2 == SOCKET_ERROR && WSAGetLastError() != ERROR_IO_PENDING)
					//{
					//	closesocket(sAcceptConn);
					//	delete pOver;
					//	break;
					//}
				}break; // OverLapped::OLOpType::EOLOT_Recv
			}
		}
	}
}
Exemple #9
0
void
gas_accept_completed (GAS_POLLER_INFO *pi, gas_client_info *accept_ci, BOOL resultOk, DWORD size)
{
	DWORD addr_buffer_size = sizeof(struct sockaddr_in) + 16;
	struct sockaddr *LocalSockaddr, *RemoteSockaddr;
	int LocalSockaddrLen=0, RemoteSockaddrLen=0;

	if (resultOk) {
		gas_debug_message (GAS_IO, "New connection created\n");

		GetAcceptExSockaddrs (gas_get_buffer_data(pi->accept_ci->rb), 0, addr_buffer_size, addr_buffer_size,
				&LocalSockaddr, &LocalSockaddrLen, &RemoteSockaddr, &RemoteSockaddrLen);

		if (pi->networks_info != NULL) {
			char address_string[30];
			if (!gas_validate_network (pi, RemoteSockaddr, address_string)) {
				gas_error_message ("Forbidden user: %s\n", address_string);
				closesocket(accept_ci->socket);
				// starts waiting for another connection request
				gas_start_accepting(pi);
				return;
			}
		}

		// "updates the context" (whatever that is...)
		setsockopt(accept_ci->socket, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT,
				(char *)&pi->server_socket, sizeof(pi->server_socket));

		// associates new socket with completion port
		gas_client_info* ci = gas_create_client (pi, accept_ci->socket);

		struct sockaddr_in * client_addr_in;
		client_addr_in = (struct sockaddr_in *) &RemoteSockaddr;
		memcpy (&ci->remote_addr, &client_addr_in->sin_addr, sizeof(struct in_addr));	// keep client address for reference
		ci->remote_port = ntohs (client_addr_in->sin_port);								// and remote port
		client_addr_in = (struct sockaddr_in *) &LocalSockaddr;
		memcpy (&ci->local_addr, &client_addr_in->sin_addr, sizeof(struct in_addr));	// keep server address for reference
		ci->local_port = ntohs (client_addr_in->sin_port);								// and local port

		gas_do_callback (ci, GAS_CLIENT_CREATE);

		if (CreateIoCompletionPort((HANDLE)ci->socket, pi->cpl_port, (ULONG_PTR)ci, 0) != pi->cpl_port) {
			int err = WSAGetLastError();
			gas_error_message ("Error %d in CreateIoCompletionPort\n", err);
		}
		else {
			// starts receiving from the new connection
			ci->overlapped = gas_create_overlapped(pi);
			gas_start_reading(ci);
		}
		// starts waiting for another connection request
		gas_start_accepting(pi);
	}

	else {		// !resultOk
		int err = GetLastError();
		gas_debug_message (GAS_IO, "Error (%d,%d) in accept, cleaning up and retrying!!!", err, (int)size);
		closesocket(accept_ci->socket);
		gas_start_accepting(pi);
	}
}
Exemple #10
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;
}
unsigned int __stdcall CEgTcpDriver::WorkerThread(void * pThisClass)
{
	CEgTcpDriver * pThis = (CEgTcpDriver*)pThisClass;

    BOOL            bSuccess = FALSE;
    int             nRet;
    DWORD           dwIoSize;
	DWORD			dwRes = 0;

    LPOVERLAPPED    lpOverlapped = NULL;
	PPER_SOCKET_CONTEXT lpPerSocketContext = NULL;
    PPER_IO_CONTEXT lpIOContext = NULL; 

	CoInitializeEx(NULL, pThis->m_ThreadingModel);

    while (TRUE) 
    {

        // continually loop to service io completion packets
        bSuccess = GetQueuedCompletionStatus(
                       pThis->m_hIocp,
                       &dwIoSize,
                       (PDWORD_PTR)&lpPerSocketContext,
                       &lpOverlapped,
                       INFINITE 
                       );

		// exit condition
        if (lpPerSocketContext == NULL)
			break;

		lpIOContext = (PPER_IO_CONTEXT)&lpPerSocketContext->m_pIOContext;

        //We should never skip the loop and not post another AcceptEx if the current
        //completion packet is for previous AcceptEx
        if (lpIOContext->m_IoOperation != ClientIoAccept)
        {
            if (!bSuccess || (bSuccess && (0 == dwIoSize)) )
            {

#ifdef _DEBUG
				DWORD dwErr = GetLastError();
#endif
                // client connection dropped
				pThis->m_SocketContextsLock.Lock();
                pThis->CloseClient(*lpPerSocketContext); 
				pThis->m_SocketContextsLock.Unlock();
                continue;
            }
        }


         switch (lpIOContext->m_IoOperation)
         {
            case ClientIoAccept:
			{
				SOCKADDR_IN *LocalSockaddr, *RemoteSockaddr;
				INT		 LocalSockaddrLength, RemoteSockaddrLength;

				assert(dwIoSize == 0);

				GetAcceptExSockaddrs(	lpPerSocketContext->m_pIOContext.m_ReceiveBuffer.buf,
										0,  
										sizeof(SOCKADDR_IN) + 16,  
										sizeof(SOCKADDR_IN) + 16,  
										(SOCKADDR**)&LocalSockaddr,  
										&LocalSockaddrLength,  
										(SOCKADDR**)&RemoteSockaddr,  
										&RemoteSockaddrLength  
									);

				PER_SOCKET_CONTEXT AcceptSocketContext;
				AcceptSocketContext.m_ConnectioID.m_LocalAddr = *LocalSockaddr;
				AcceptSocketContext.m_ConnectioID.m_RemoteAddr = *RemoteSockaddr;
				AcceptSocketContext.m_pIOContext.m_IoOperation = ClientIoRead;
				AcceptSocketContext.m_ConnectioID.m_Socket = lpPerSocketContext->m_pIOContext.m_SocketAccept;

				pair<set<PER_SOCKET_CONTEXT>::iterator, bool> InsIt;

				pThis->m_SocketContextsLock.Lock();

				while(true)
				{
					InsIt = pThis->m_SocketContexts.insert(AcceptSocketContext);
					if (InsIt.second == true)
						break;
					
					SwitchToThread();
				}
				
				nRet = setsockopt(lpPerSocketContext->m_pIOContext.m_SocketAccept, 
								  SOL_SOCKET,
								  SO_UPDATE_ACCEPT_CONTEXT,
								  (char *)&(pThis->m_ListenSocket),
								  sizeof(pThis->m_ListenSocket)
								 );

                if (nRet == SOCKET_ERROR)
				{
#ifdef _DEBUG
					DWORD e = WSAGetLastError();
#endif
					pThis->CloseClient(AcceptSocketContext);
					pThis->m_SocketContextsLock.Unlock();
					break;
				}


				PER_SOCKET_CONTEXT & SocketContext = *(InsIt.first);

				dwRes = pThis->BindCompletionPort(SocketContext);
				if (dwRes != 0)
				{
					pThis->CloseClient(AcceptSocketContext);
					pThis->m_SocketContextsLock.Unlock();
					break;
				}

				// while Send method is not called we are waiting for client's data
				
				BOOL bConnectionEnabled = 
						m_bInited ?
						pThis->m_pEvents->OnConnect(SocketContext.m_ConnectioID, TRUE) :
						FALSE;

				if (bConnectionEnabled)
				{
					pThis->QueueReceiveOperation(SocketContext, DEFAULT_BUFFER_SIZE);
				}
				else
				{
					pThis->CloseClient(SocketContext, CONNECTION_DISCARDED);
				}

				pThis->m_SocketContextsLock.Unlock();

				// pending for another connection
				dwRes = pThis->CreateAcceptSocket(FALSE);
			}
			break;

			case ClientIoRead:
			case ClientIoWrite:

				DWORD cbTransferReceive;
				DWORD cbTransferSend;
				DWORD dwFlags;
				BOOL  bRes;

				bRes = WSAGetOverlappedResult(lpPerSocketContext->m_ConnectioID.m_Socket,
									&lpPerSocketContext->m_pIOContext.m_SendOverlapped,
									&cbTransferSend,FALSE, &dwFlags);

				if (bRes == TRUE && cbTransferSend == dwIoSize)
				{
				}
#ifdef _DEBUG
				if (bRes == FALSE)
				{
					DWORD dwErr = WSAGetLastError();
				}
#endif
				bRes = WSAGetOverlappedResult(lpPerSocketContext->m_ConnectioID.m_Socket,
									&lpPerSocketContext->m_pIOContext.m_ReceiveOverlapped,
									&cbTransferReceive,FALSE, &dwFlags);

				if (bRes == TRUE && cbTransferReceive == dwIoSize)
				{

					if (pThis->m_bInited)
						pThis->m_pEvents->OnReceive(lpPerSocketContext->m_ConnectioID, 
							lpPerSocketContext->m_pIOContext.m_ReceiveBuffer.m_pData, 
							dwIoSize);

					lpPerSocketContext->m_pIOContext.m_ReceiveBuffer.m_dwTransferred = 0;

					pThis->QueueReceiveOperation(*lpPerSocketContext, DEFAULT_BUFFER_SIZE);
				}
#ifdef _DEBUG
				if (bRes == FALSE)
				{
					DWORD dwErr = WSAGetLastError();
				}
#endif
				break;
		 }

	}

	CoUninitialize();
    return(0);
}
Exemple #12
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;
}
Exemple #13
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;
}
Exemple #14
0
bool CServerSocket::AcceptCompleted( CSocketBuffer * pBuffer, DWORD dwReceiveByte )
{

	bool bRet ;
	// Accept 가 완료되면.
	if( pBuffer && pBuffer->IsConnected() )
	{
		pool_lock() ;
		try{
			pBuffer->m_bAccepted = true ;
		}
		catch (...) {
			::PrintConsole("[exception] %s, %d \n", __FILE__, __LINE__ ) ;
		}		
		pool_unlock() ;

		
		::InterlockedDecrement( &m_nCurPendingAccept ) ;
	
		//SetEvent( m_hAcceptPostEvent ) ;

		int nEstablishedSeconds = 0;		
		int bytes = sizeof(nEstablishedSeconds);		
		int err = ::getsockopt(pBuffer->socket, SOL_SOCKET, SO_CONNECT_TIME, (char*)&nEstablishedSeconds, &bytes);
		if (nEstablishedSeconds == 0xffffffff)
		{			
			//  현재 연결되지 않은 넘
			::PrintConsole( "[ERROR] Dissconnected socket \n") ;
			return false ;
		}		
		else			
		{
			// nEstablishedSeconds --> 커넥션 이루어진 때로부터 현재까지 경과한 초단위 시간			
		}


		if( SOCKET_ERROR == ::setsockopt( pBuffer->socket, SOL_SOCKET, 
			SO_UPDATE_ACCEPT_CONTEXT, (char*)&m_listensocket, sizeof(m_listensocket) ) ) 
		{
			::PrintConsole( "CServerSocket::AcceptCompleted setsockopt failed - Code %d\n", ::WSAGetLastError() ) ;
		}
		

		// 주소를 채우고, 
		//
		int sizeofLocal=0, sizeofRemote = 0 ;
		SOCKADDR * pLocal = NULL, * pRemote = NULL ;

		GetAcceptExSockaddrs( pBuffer->m_buf, 0, m_sizeofaddr, m_sizeofaddr, 
			&pLocal, &sizeofLocal, &pRemote, &sizeofRemote ) ;

		if( pRemote )
		{
			::CopyMemory( &pBuffer->addr, pRemote, sizeof(SOCKADDR) ) ;

			//printf( "Ip = %s\n", inet_ntoa( pBuffer->addr.sin_addr ) ) ;
		}

		tcp_keepalive keepAlive, outKeepAlive = {0};
		DWORD	outByte ;
		
		keepAlive.onoff = 1 ;
		keepAlive.keepaliveinterval = _KEEPALIVE_INTERVAL_ ;
		keepAlive.keepalivetime = _KEEPALIVE_TIME_ ;
		WSAIoctl( pBuffer->socket, SIO_KEEPALIVE_VALS, &keepAlive, sizeof(keepAlive), &outKeepAlive, sizeof(outKeepAlive), &outByte, NULL, NULL ) ;

		


		// completion port 와 연결한다..
		/*
		if( m_iocp.AssociateSocket( pBuffer ) == false )
		{
			int iError = WSAGetLastError() ;
			::PrintConsole( " m_iocp.AssociateSocket( pBuf ) == false (err_code :%d)\n", iError ) ;			
		}
		*/

		//OnConnectionEstablished( pBuffer ) ;
		bRet = true ;
	
	}
	else
	{
		::PrintConsole("[ERROR] if( pBuffer && pBuffer->IsConnected() == false ) \n" ) ;
		bRet = false ;
		
	}

	return bRet ;
}