Esempio n. 1
0
int SocketLayer::RecvFrom( const SOCKET s, RakPeer *rakPeer, int *errorCode )
{
    int len;
    char data[ MAXIMUM_MTU_SIZE ];
    sockaddr_in sa;

    const socklen_t len2 = sizeof( struct sockaddr_in );
    sa.sin_family = AF_INET;

#ifdef _DEBUG
    data[ 0 ] = 0;
    len = 0;
    sa.sin_addr.s_addr = 0;
#endif

    if ( s == INVALID_SOCKET )
    {
        *errorCode = SOCKET_ERROR;
        return SOCKET_ERROR;
    }

    len = recvfrom( s, data, MAXIMUM_MTU_SIZE, COMPATIBILITY_2_RECV_FROM_FLAGS, ( sockaddr* ) & sa, ( socklen_t* ) & len2 );

    // if (len>0)
    //  printf("Got packet on port %i\n",ntohs(sa.sin_port));

    if ( len == 0 )
    {
#ifdef _DEBUG
        printf( "Error: recvfrom returned 0 on a connectionless blocking call\non port %i.  This is a bug with Zone Alarm.  Please turn off Zone Alarm.\n", ntohs( sa.sin_port ) );
        assert( 0 );
#endif

        *errorCode = SOCKET_ERROR;
        return SOCKET_ERROR;
    }

    if ( len != SOCKET_ERROR )
    {
        unsigned short portnum;
        portnum = ntohs( sa.sin_port );

        ProcessNetworkPacket( sa.sin_addr.s_addr, portnum, data, len, rakPeer );

        return 1;
    }
    else
    {
        *errorCode = 0;

#if defined(_WIN32) && !defined(_COMPATIBILITY_1) && defined(_DEBUG)

        DWORD dwIOError = WSAGetLastError();

        if ( dwIOError == WSAEWOULDBLOCK )
        {
            return SOCKET_ERROR;
        }
        if ( dwIOError == WSAECONNRESET )
        {
#if defined(_DEBUG)
//			printf( "A previous send operation resulted in an ICMP Port Unreachable message.\n" );
#endif


            unsigned short portnum=0;
            ProcessPortUnreachable(sa.sin_addr.s_addr, portnum, rakPeer);
            // *errorCode = dwIOError;
            return SOCKET_ERROR;
        }
        else
        {
#if defined(_DEBUG)
            if ( dwIOError != WSAEINTR )
            {
                LPVOID messageBuffer;
                FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
                               NULL, dwIOError, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ),  // Default language
                               ( LPTSTR ) & messageBuffer, 0, NULL );
                // something has gone wrong here...
                printf( "recvfrom failed:Error code - %d\n%s", dwIOError, messageBuffer );

                //Free the buffer.
                LocalFree( messageBuffer );
            }
#endif
        }
#endif
    }

    return 0; // no data
}
Esempio n. 2
0
int SocketLayer::RecvFrom( const SOCKET s, RakPeer *rakPeer, int *errorCode, RakNetSmartPtr<RakNetSocket> rakNetSocket, unsigned short remotePortRakNetWasStartedOn_PS3 )
{
	int len=0;
#if (defined(_XBOX) || defined(_X360)) && defined(RAKNET_USE_VDP)
	char dataAndVoice[ MAXIMUM_MTU_SIZE*2 ];
	char *data=&dataAndVoice[sizeof(unsigned short)]; // 2 bytes in
#else
	char data[ MAXIMUM_MTU_SIZE ];
#endif

	if (slo)
	{
		SystemAddress sender;
		len = slo->RakNetRecvFrom(s,rakPeer,data,&sender,true);
		if (len>0)
		{
			ProcessNetworkPacket( sender, data, len, rakPeer, rakNetSocket, RakNet::GetTimeUS() );
			return 1;
		}
	}

	if ( s == (SOCKET) -1 )
	{
		*errorCode = -1;
		return -1;
	}

#if defined (_WIN32) || !defined(MSG_DONTWAIT)
	const int flag=0;
#else
	const int flag=MSG_DONTWAIT;
#endif

	sockaddr_in sa;
	socklen_t len2;
	unsigned short portnum=0;
	if (remotePortRakNetWasStartedOn_PS3!=0)
	{
#if defined(_PS3) || defined(__PS3__) || defined(SN_TARGET_PS3)
                                                                                                                                                                                                                                                                           
#endif
	}
	else
	{
		len2 = sizeof( sa );
		sa.sin_family = AF_INET;
		sa.sin_port=0;

#if (defined(_XBOX) || defined(_X360)) && defined(RAKNET_USE_VDP)

		/*
		DWORD zero=0;
		WSABUF wsaBuf;
		DWORD lenDword=0;
		wsaBuf.buf=dataAndVoice;
		wsaBuf.len=sizeof(dataAndVoice);
		int result = WSARecvFrom( s, 
			&wsaBuf,
			1,
			&lenDword,
			&zero,
			( sockaddr* ) & sa, ( socklen_t* ) & len2,
			0,0	);
		len=lenDword;
		*/

		len = recvfrom( s, dataAndVoice, sizeof(dataAndVoice), flag, ( sockaddr* ) & sa, ( socklen_t* ) & len2 );
		if (len>2)
		{
			// Skip first two bytes
			len-=2;
		}
#else
		len = recvfrom( s, data, MAXIMUM_MTU_SIZE, flag, ( sockaddr* ) & sa, ( socklen_t* ) & len2 );
#endif

		portnum = ntohs( sa.sin_port );
	}

	if ( len == 0 )
	{
#ifdef _DEBUG
		RAKNET_DEBUG_PRINTF( "Error: recvfrom returned 0 on a connectionless blocking call\non port %i.  This is a bug with Zone Alarm.  Please turn off Zone Alarm.\n", portnum );
		RakAssert( 0 );
#endif

		// 4/13/09 Changed from returning -1 to 0, to prevent attackers from sending 0 byte messages to shutdown the server
		*errorCode = 0;
		return 0;
	}

	if ( len > 0 )
	{
		ProcessNetworkPacket( SystemAddress(sa.sin_addr.s_addr, portnum), data, len, rakPeer, rakNetSocket, RakNet::GetTimeUS() );

		return 1;
	}
	else
	{
		*errorCode = 0;


#if defined(_WIN32) && defined(_DEBUG)

		DWORD dwIOError = WSAGetLastError();

		if ( dwIOError == WSAEWOULDBLOCK )
		{
			return SOCKET_ERROR;
		}
		if ( dwIOError == WSAECONNRESET )
		{
#if defined(_DEBUG)
//			RAKNET_DEBUG_PRINTF( "A previous send operation resulted in an ICMP Port Unreachable message.\n" );
#endif


			unsigned short portnum=0;
			ProcessPortUnreachable(sa.sin_addr.s_addr, portnum, rakPeer);
			// *errorCode = dwIOError;
			return -1;
		}
		else
		{
#if defined(_DEBUG) && !defined(_XBOX) && !defined(X360)
			if ( dwIOError != WSAEINTR && dwIOError != WSAETIMEDOUT)
			{
				LPVOID messageBuffer;
				FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
					NULL, dwIOError, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ),  // Default language
					( LPTSTR ) & messageBuffer, 0, NULL );
				// something has gone wrong here...
				RAKNET_DEBUG_PRINTF( "recvfrom failed:Error code - %d\n%s", dwIOError, messageBuffer );

				//Free the buffer.
				LocalFree( messageBuffer );
			}
#endif
		}
#endif
	}

	return 0; // no data
}
int SocketLayer::RecvFrom( const SOCKET s, RakPeer *rakPeer, int *errorCode, unsigned connectionSocketIndex )
{
	int len;
	char data[ MAXIMUM_MTU_SIZE ];

#if defined(_PS3) && defined (_PS3_LOBBY)
	sockaddr_in_p2p sa;
#else
	sockaddr_in sa;
#endif


	socklen_t len2 = sizeof( sa );
	sa.sin_family = AF_INET;

#ifdef _DEBUG
	data[ 0 ] = 0;
	len = 0;
	sa.sin_addr.s_addr = 0;
#endif

	if ( s == (SOCKET) -1 )
	{
		*errorCode = -1;
		return -1;
	}

#if defined (_WIN32) || !defined(MSG_DONTWAIT)
	const int flag=0;
#else
	const int flag=MSG_DONTWAIT;
#endif

	len = recvfrom( s, data, MAXIMUM_MTU_SIZE, flag, ( sockaddr* ) & sa, ( socklen_t* ) & len2 );

	// if (len>0)
	//  printf("Got packet on port %i\n",ntohs(sa.sin_port));

	if ( len == 0 )
	{
#ifdef _DEBUG
		printf( "Error: recvfrom returned 0 on a connectionless blocking call\non port %i.  This is a bug with Zone Alarm.  Please turn off Zone Alarm.\n", ntohs( sa.sin_port ) );
		assert( 0 );
#endif

		*errorCode = -1;
		return -1;
	}

	if ( len > 0 )
	// if ( len != SOCKET_ERROR )
	{
		unsigned short portnum;
//#if defined(_PS3) && defined (_PS3_LOBBY)
//		portnum = ntohs( sa.sin_vport );
//#else
		portnum = ntohs( sa.sin_port );
//#endif
		//strcpy(ip, inet_ntoa(sa.sin_addr));
		//if (strcmp(ip, "0.0.0.0")==0)
		// strcpy(ip, "127.0.0.1");
		ProcessNetworkPacket( sa.sin_addr.s_addr, portnum, data, len, rakPeer, connectionSocketIndex );

		return 1;
	}
	else
	{
		*errorCode = 0;


#if defined(_WIN32) && !defined(_XBOX360) && defined(_DEBUG)

		DWORD dwIOError = WSAGetLastError();

		if ( dwIOError == WSAEWOULDBLOCK )
		{
			return SOCKET_ERROR;
		}
		if ( dwIOError == WSAECONNRESET )
		{
#if defined(_DEBUG)
//			printf( "A previous send operation resulted in an ICMP Port Unreachable message.\n" );
#endif


			unsigned short portnum=0;
			ProcessPortUnreachable(sa.sin_addr.s_addr, portnum, rakPeer);
			// *errorCode = dwIOError;
			return -1;
		}
		else
		{
#if defined(_DEBUG)
			if ( dwIOError != WSAEINTR )
			{
				LPVOID messageBuffer;
				FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
					NULL, dwIOError, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ),  // Default language
					( LPTSTR ) & messageBuffer, 0, NULL );
				// something has gone wrong here...
				printf( "recvfrom failed:Error code - %d\n%s", dwIOError, messageBuffer );

				//Free the buffer.
				LocalFree( messageBuffer );
			}
#endif
		}
#endif
	}

	return 0; // no data
}
unsigned __stdcall ThreadPoolFunc( LPVOID arguments )
{
	DWORD dwIoSize;
	ClientContextStruct* lpClientContext;
	ExtendedOverlappedStruct* lpOverlapped;
	LPOVERLAPPED temp;
	BOOL bError;

	HANDLE *completionPort = ( HANDLE * ) arguments;
	AsynchronousFileIO::Instance()->threadCount++;

	while ( 1 )
	{
		// Get a completed IO request.
		BOOL returnValue = GetQueuedCompletionStatus(
			completionPort,
			&dwIoSize,
			( LPDWORD ) & lpClientContext,
			&temp, INFINITE );

		lpOverlapped = ( ExtendedOverlappedStruct* ) temp;

		DWORD dwIOError = GetLastError();

		if ( lpOverlapped == 0 )
			break; // Cancelled thread

		if ( !returnValue && dwIOError != WAIT_TIMEOUT )
		{
			if ( dwIOError != ERROR_OPERATION_ABORTED )
			{
				// Print all but this very common error message
#if defined(_WIN32) && defined(_DEBUG)
				LPVOID messageBuffer;
				FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
					NULL, dwIOError, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ),  // Default language
					( LPTSTR ) & messageBuffer, 0, NULL );
				// something has gone wrong here...
				printf( "GetQueuedCompletionStatus failed:Error code - %d\n%s", dwIOError, messageBuffer );

				//Free the buffer.
				LocalFree( messageBuffer );
#endif

			}

HANDLE_ERROR:
			// Some kind of error. Erase the data for this call
			bError = true;

			// This socket is no longer used

			if ( lpOverlapped )
				delete lpOverlapped;

			if ( lpClientContext )
				delete lpClientContext;

			// If we are killing the threads, then we keep posting fake completion statuses until we get a fake one through the queue (i.e. lpOverlapped==0 as above)
			// This way we delete all the data from the real calls before exiting the thread
			if ( AsynchronousFileIO::Instance()->killThreads )
			{
				PostQueuedCompletionStatus( completionPort, 0, 0, 0 );
			}

		}

		else
			bError = false;

		if ( !bError )
		{
			if ( returnValue && NULL != lpOverlapped && NULL != lpClientContext )
			{
				if ( lpOverlapped->read == true )
				{
					assert( dwIoSize > 0 );

					ProcessNetworkPacket( lpOverlapped->binaryAddress, lpOverlapped->port, lpOverlapped->data, dwIoSize, lpOverlapped->rakPeer );

					// Issue a new read so we always have one outstanding read per socket
					// Finished a read.  Reuse the overlapped pointer
					bError = ReadAsynch( lpClientContext->handle, lpOverlapped );

					if ( !bError )
						goto HANDLE_ERROR; // Windows is super unreliable!
				}

				else
				{
					// AsynchronousFileIO::Instance()->Write(lpClientContext);
					// Finished a write
					ExtendedOverlappedPool::Instance()->ReleasePointer( lpOverlapped );
				}
			}

			else
				assert( 0 );
		}
	}

	AsynchronousFileIO::Instance()->threadCount--;
	return 0;
}