bool CSocket::DoPulse()
{
    // Make sure the socket exists before taking action
    if (m_pSocket != ERR_INVALID_SOCKET)
    {
        // Wait for connect to complete before proceeding
        if (!m_bConnected)
        {
            struct timeval tv = { 0, 0 };
            fd_set wfds;
            FD_ZERO(&wfds);
            FD_SET(m_pSocket, &wfds);
            // See if socket it writable
            int ret = select(m_pSocket+1, NULL, &wfds, NULL, &tv);
            if (ret == 0)
               return true;     // Not writable yet
            if (ret == -1)
               return false;    // select error
        }

        // Create a buffer for catching received data
        // (1 byte larger than receive limit, because another character has to be added)
        char chBuffer[SOCK_RECV_LIMIT + 1];

        // Receive the data
        int iLength = recv(m_pSocket, chBuffer, SOCK_RECV_LIMIT, 0);

        // Check if there were any errors
        int iError = GetLastSocketError();

        // Check if the socket just connected. If connection failed, return false
        if (!m_bConnected && (HandleConnection(iError) == ERR_CONNECT_FAILURE))
            return false;

        // If connected, handle data processing
        if (m_bConnected)
        {
            // Process data if there is any
            if (iLength > 0)
            {
                // Add a NULL at the end of the data, or the data will appear corrupted
                chBuffer[iLength] = '\0';

                TriggerEvent("onSockData",chBuffer);
            }
            else if (iError != ERR_NO_ERROR && iError != ERR_WOULD_BLOCK)
            {
                // An error has occured, so time to kill the socket
                m_bConnected = false;
                return false;
            }
        }
    }
    else
        // If the socket doesn't exist, well, error?
        return false;

    // If the call makes it up till here, it has been a huge success! Cake and true as a reward!
    return true;
}
Example #2
0
// if timeout occurs, nbytes=-1, nresult=1
// if socket error, nbyte=-1, nresult=-1
// if the other side has disconnected in either block mode or nonblock mode, nbytes=0, nresult=-1
void SocketRecv(HSocket hs, char* ptr, int nbytes, transresult_t& rt)
{
    rt.nbytes = 0;
    rt.nresult = 0;

    if(!ptr|| nbytes<1)
    {
        return;
    }

    rt.nbytes = recv(hs, ptr, nbytes, BLOCKREADWRITE);

    if(rt.nbytes>0)
    {
        return;
    }
    else if(rt.nbytes==0)
    {
        rt.nresult=-1;
    }
    else
    {
        rt.nresult = GetLastSocketError();
        rt.nresult = ETRYAGAIN(rt.nresult)? 1:-1;
    }

}
Example #3
0
//
// if timeout occurs, nbytes=-1, nresult=1
// if socket error, nbyte=-1, nresult=-1
// if the other side has disconnected in either block mode or nonblock mode, nbytes=0, nresult=-1
// otherwise nbytes= the count of bytes sent , nresult=0
void SocketSend(HSocket hs, const char* ptr, int nbytes, transresult_t& rt)
{
    rt.nbytes = 0;
    rt.nresult = 0;

    if(!ptr|| nbytes<1)
    {
        return;
    }

    //Linux: flag can be MSG_DONTWAIT, MSG_WAITALL, 使用MSG_WAITALL的时候, socket 必须是处于阻塞模式下,否则WAITALL不能起作用
    rt.nbytes = send(hs, ptr, nbytes, BLOCKREADWRITE|SENDNOSIGNAL);

    if(rt.nbytes>0)
    {
        rt.nresult = (rt.nbytes == nbytes)?0:1;
    }
    else if(rt.nbytes==0)
    {
        rt.nresult=-1;
    }
    else
    {
        rt.nresult = GetLastSocketError();
        rt.nresult = ETRYAGAIN(rt.nresult)? 1:-1;
    }
}
Example #4
0
void SocketTrySend(HSocket hs, const char* ptr, int nbytes, int milliseconds, transresult_t& rt)
{
    rt.nbytes = 0;
    rt.nresult = 0;

    if(!ptr|| nbytes<1)
    {
        return;
    }


    int n;
    CMyTimeSpan start;

    while(1)
    {
        n = send(hs, ptr+rt.nbytes, nbytes, NONBLOCKREADWRITE|SENDNOSIGNAL);

        if(n>0)
        {
            rt.nbytes += n;
            nbytes -= n;

            if(rt.nbytes >= nbytes)
            {
                rt.nresult = 0;
                break;
            }
        }
        else if( n==0)
        {
            rt.nresult= -2;
            break;
        }
        else
        {
            n = GetLastSocketError();

            if(ETRYAGAIN(n))
            {
                // CLightThread::DiscardTimeSlice();
                int  dwSleep=20;
                std::this_thread::sleep_for(std::chrono::milliseconds(dwSleep*1000));
            }
            else
            {
                rt.nresult = -1;
                break;
            }
        }

        if(start.GetSpaninMilliseconds() > (unsigned int)milliseconds)
        {
            rt.nresult= 1;
            break;
        }
    }
}
Example #5
0
bool 
ServerSocket::Connect(
    unsigned long   a_nIpAddress, 
    int             a_nPort, 
    int             a_nTimeout
    )
{
    Disconnect();

    struct sockaddr_in server;
    server.sin_family = AF_INET;
    server.sin_port = htons((short)a_nPort);
    server.sin_addr.s_addr = a_nIpAddress;

    SOCKET s = socket(AF_INET, SOCK_STREAM, 0);
    if (s == INVALID_SOCKET) return false;

    try {
        // non-blocking for connect
        u_long value = 1;
        int rc = ioctlsocket(s, FIONBIO, &value);
        if (rc != 0) throw rc;

        rc = connect(s, (struct sockaddr *) &server, sizeof(server));
        if (rc != 0) {
            if (rc != SOCKET_ERROR || GetLastSocketError() != EWOULDBLOCK) throw rc;

            // non-blocking wait
            struct timeval timeout;
            timeout.tv_sec  =  a_nTimeout / 1000;
            timeout.tv_usec = (a_nTimeout % 1000) * 1000;
            fd_set wr; FD_ZERO(&wr); FD_SET(s, &wr);
            fd_set ex; FD_ZERO(&ex); FD_SET(s, &ex);
            rc = select(0, NULL, &wr, &ex, &timeout);
            if (rc == 0 || rc == SOCKET_ERROR || FD_ISSET(s, &ex)) throw rc;
        }

        // blocking
        value = 0;
        rc = ioctlsocket(s, FIONBIO, &value);
        if (rc != 0) throw rc;

        rc = setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, 
            (const char*) &a_nTimeout, sizeof(a_nTimeout));
        if (rc != 0) throw rc;

        rc = setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, 
            (const char*) &a_nTimeout, sizeof(a_nTimeout));
        if (rc != 0) throw rc;

        mSocket = s;
        return true;
    }
    catch (int) {
        closesocket(s);
        return false;
    }
}
Example #6
0
// if timeout occurs, nbytes=-1, nresult=1
// if socket error, nbyte=-1, nresult=-1
// if the other side has disconnected in either block mode or nonblock mode, nbytes=0, nresult=-1
void SocketTryRecv(HSocket hs, char* ptr, int nbytes, int milliseconds, transresult_t& rt)
{
    rt.nbytes = 0;
    rt.nresult = 0;

    if(!ptr|| nbytes<1)
    {
        return;
    }

    if(milliseconds>2)
    {
        CMyTimeSpan start;

        while(1)
        {
            rt.nbytes = recv(hs, ptr, nbytes, NONBLOCKREADWRITE);

            if(rt.nbytes>0)
            {
                break;
            }
            else if(rt.nbytes==0)
            {
                rt.nresult = -1;
                break;
            }
            else
            {
                rt.nresult = GetLastSocketError();

                if( ETRYAGAIN(rt.nresult))
                {
                    if(start.GetSpaninMilliseconds() > (unsigned int)milliseconds)
                    {
                        rt.nresult= 1;
                        break;
                    }

                    //CLightThread::DiscardTimeSlice();
                    int  dwSleep=20;
                    std::this_thread::sleep_for(std::chrono::milliseconds(dwSleep*1000));
                }
                else
                {
                    rt.nresult = -1;
                    break;
                }
            }

        }
    }
    else
    {
        SocketRecv(hs, ptr, nbytes, rt);
    }
}
Example #7
0
//
// UDPsocket
//
int UDPsocket (void)
{
	int	s;

	// allocate a socket
	s = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
	if ( !IsValidSocket( s ) ) {
		int err = GetLastSocketError();
		I_Error( "can't create socket, error %d", err );
	}

	return s;
}
CSocket::CSocket(lua_State *luaVM, const string& strHost, const unsigned short& usPort)
{
    // Prepare variables
    m_bConnected = false;
    m_strHost    = strHost;
    m_usPort     = usPort;
    m_pLuaVM     = luaVM;
    m_pUserdata  = NULL;
    m_pSocket    = ERR_INVALID_SOCKET;
    
    // Prepare data for connection (cancel on failure)
    if (!ProcessTargetLocation(strHost, usPort))
        return;
    
    // Create the socket, and put it in non-blocking mode
    m_pSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

    // Exit if the socket failed to create
    if (m_pSocket == ERR_INVALID_SOCKET)
        return;

    ms_iTotalOpenSocketCount++;

    // Set the socket to non-blocking mode
    SetNonBlocking();

    // Make the socket connect
    if (connect(m_pSocket, (sockaddr*)&m_sSockAddr, sizeof(m_sSockAddr)) != ERR_CONNECT_SUCCESS)
    {
        // If the connection failed, check why
        int iError = GetLastSocketError();

        // If the error is ERR_WOULD_BLOCK (meaning it's in progress) then ignore
        if (iError != ERR_CONNECT_IN_PROGRESS)
        {
            // Error, so unload the socket and exit the function
            CloseSocket();
            return;
        }
    }

    // Create userdata, for identification
    m_pUserdata  = lua_newuserdata(luaVM, 128);
}
Example #9
0
int EHSConnection::TrySend ( const char * ipMessage, size_t inLength, int inFlags )
{

    int iWouldBlockCount = 0;
lp1:
    {
        int iCount = 0;
        UpdateLastActivity ( );
        while( !m_poNetworkAbstraction->IsWritable(1000) && !m_poNetworkAbstraction->IsAtError(0) )
        {
            iCount++;
            if ( iCount == 10 )
            {
                break;
            }
        } 
    }

	int ret = m_poNetworkAbstraction->Send ( ipMessage, inLength, inFlags );

    if ( ret == SOCKET_ERROR )
    {
        int err = GetLastSocketError ();
        if ( err == E_WOULDBLOCK )
        {
            Sleep(20);
            iWouldBlockCount++;
            if ( iWouldBlockCount < 2 )
                goto lp1;
            m_poNetworkAbstraction->Close();
        }
    }
    else
    if ( ret != inLength )
    {
        ipMessage += ret;
        inLength -= ret;
        Sleep(1);
        goto lp1;
    }

    return ret;
}
Example #10
0
// if timeout occurs, nbytes=-1, nresult=1
// if socket error, nbyte=-1, nresult=-1
// if the other side has disconnected in either block mode or nonblock mode, nbytes=0, nresult=-1
void SocketTryRecv(HSocket hs, char *ptr, int nbytes, int milliseconds, transresult_t &rt)
{
    rt.nbytes = 0;
    rt.nresult = 0;
    if(!ptr|| nbytes<1) return;

    if(milliseconds>2)
    {
        CMyTimeSpan start;
        while(1)
        {
            rt.nbytes = recv(hs, ptr, nbytes, NONBLOCKREADWRITE);
            if(rt.nbytes>0)
            {
               break;
            }
            else if(rt.nbytes==0)
            {
                rt.nresult = -1;
                break;
            }
            else
            {
                rt.nresult = GetLastSocketError();
                if( ETRYAGAIN(rt.nresult))
                {
                   if(start.GetSpaninMilliseconds()>milliseconds)  { rt.nresult= 1; break;}
                   CLightThread::DiscardTimeSlice();
                }
                else
                {
                    rt.nresult = -1;
                    break;
                }
            }

        }
    }
    else
    {
        SocketRecv(hs, ptr, nbytes, rt);
    }
}
Example #11
0
//  nbytes= the count of bytes sent
// if timeout occurs, nresult=1
// if socket error,  nresult=-1,
// if the other side has disconnected in either block mode or nonblock mode, nresult=-2
void SocketTrySend(HSocket hs, const char *ptr, int nbytes, int milliseconds, transresult_t &rt)
{
    rt.nbytes = 0;
    rt.nresult = 0;
    if(!ptr|| nbytes<1) return;


    int n;
    CMyTimeSpan start;
    while(1)
    {
        n = send(hs, ptr+rt.nbytes, nbytes, NONBLOCKREADWRITE|SENDNOSIGNAL);
        if(n>0)
        {
            rt.nbytes += n;
            nbytes -= n;
            if(rt.nbytes >= nbytes) {    rt.nresult = 0;  break; }
        }
        else if( n==0)
        {
            rt.nresult= -2;
            break;
        }
        else
        {
            n = GetLastSocketError();
            if(ETRYAGAIN(n))
            {
                CLightThread::DiscardTimeSlice();
            }
            else
            {
                rt.nresult = -1;
                break;
            }
        }
        if(start.GetSpaninMilliseconds()>milliseconds)  { rt.nresult= 1; break;}
    }
}
Example #12
0
                int TcpSocketClient::WaitOnSocket(int32_t timeout, bool rd)
                {
                    int ready = 0;
                    int lastError = 0;

                    fd_set fds;

                    do {
                        struct timeval tv = { 0 };
                        tv.tv_sec = timeout;

                        FD_ZERO(&fds);
                        FD_SET(socketHandle, &fds);

                        fd_set* readFds = 0;
                        fd_set* writeFds = 0;

                        if (rd)
                            readFds = &fds;
                        else
                            writeFds = &fds;

                        ready = select(static_cast<int>((socketHandle) + 1),
                            readFds, writeFds, NULL, (timeout == 0 ? NULL : &tv));

                        if (ready == SOCKET_ERROR)
                            lastError = GetLastSocketError();

                    } while (ready == SOCKET_ERROR && IsSocketOperationInterrupted(lastError));

                    if (ready == SOCKET_ERROR)
                        return -lastError;

                    if (ready == 0)
                        return WaitResult::TIMEOUT;

                    return WaitResult::SUCCESS;
                }
Example #13
0
void EHSServer::CheckClientSockets ( )
{
    MUTEX_LOCK ( m_oMutex );

	// go through all the sockets from which we're still reading
	for ( EHSConnectionList::iterator i = m_oEHSConnectionList.begin ( );
		  i != m_oEHSConnectionList.end ( );
		  i++ ) {

		if ( m_oReadFds.IsSet( (*i)->GetNetworkAbstraction()->GetFd(), POLLIN ) ) {

            if ( MUTEX_TRY_LOCK ( (*i)->m_oConnectionMutex ) == false )
                continue;

			EHS_TRACE ( "$$$$$ Got data on client connection\n" );


			// prepare a buffer for the read
			static const int BYTES_TO_READ_AT_A_TIME = 10240;
			char psReadBuffer [ BYTES_TO_READ_AT_A_TIME + 1 ];
			memset ( psReadBuffer, 0, BYTES_TO_READ_AT_A_TIME + 1 );

			// do the actual read
			int nBytesReceived =
				(*i)->GetNetworkAbstraction ( )->Read ( psReadBuffer,
														BYTES_TO_READ_AT_A_TIME );

            if ( nBytesReceived == SOCKET_ERROR )
            {
                int err = GetLastSocketError ();
                if ( err == E_WOULDBLOCK )
                {
                    MUTEX_UNLOCK ( (*i)->m_oConnectionMutex );
                    continue;
                }
            }
			// if we received a disconnect
			if ( nBytesReceived <= 0 ) {

				// we're done reading and we received a disconnect
				(*i)->DoneReading ( true );

			}
			// otherwise we got data
			else {

				// take the data we got and append to the connection's buffer
				EHSConnection::AddBufferResult nAddBufferResult = 
					(*i)->AddBuffer ( psReadBuffer, nBytesReceived );

				// if add buffer failed, don't read from this connection anymore
				if ( nAddBufferResult == EHSConnection::ADDBUFFER_INVALIDREQUEST ||
					 nAddBufferResult == EHSConnection::ADDBUFFER_TOOBIG ) {

					// done reading but did not receieve disconnect
					EHS_TRACE ( "Done reading because we got a bad request\n" );
					(*i)->DoneReading ( false );

				} // end error with AddBuffer

			} // end nBytesReceived

            MUTEX_UNLOCK ( (*i)->m_oConnectionMutex );
		} // FD_ISSET
		
	} // for loop through connections
    MUTEX_UNLOCK ( m_oMutex );

} 
Example #14
0
// Fills the 'buffer' with maximum of 'count' bytes, explicitly from the remote QRBG Service.
// Actual number of bytes copied into the buffer is returned.
// Upon failure, exceptions are thrown.
// Returns: count of bytes (received) copied into the supplied buffer.
size_t QRBG::AcquireBytesFromService(byte* buffer, size_t count) throw(ConnectError, CommunicationError, ServiceDenied) {
	// connect to the service server,
	// propagate exception to the caller
	Connect();

	//
	// prepare and send the request
	//

	// NOTE: we're using plain authentication.

/*
	Client first (and last) packet:
	Size [B]		Content
	--------------	--------------------------------------------------------
	1				operation, from OperationCodes enum
	if operation == GET_DATA_AUTH_PLAIN, then:
	2				content size (= 1 + username_len + 1 + password_len + 4)
	1				username_len (must be > 0 and <= 100)
	username_len	username (NOT zero padded!)
	1				password_len (must be > 0 and <= 100)
	password_len	password in plain 8-bit ascii text (NOT zero padded!)
	4				bytes of data requested

	Server first (and last) packet:
	Size [B]		Content
	--------------	--------------------------------------------------------
	1				response, from ServerResponseCodes enum
	1				response details - reason, from RefusalReasonCodes
	4				data_len, bytes of data that follow
	data_len		data
*/

	// header structure looks like this:
	// 	struct tClientHeader {
	// 		uint8	eOperation;		// MUST BE eOperation == GET_DATA_AUTH_PLAIN for struct remainder to hold
	// 		uint16	cbContentSize;
	// 		uint8	cbUsername;
	// 		char	szUsername[cbUsername];
	// 		uint8	cbPassword;
	// 		char	szPassword[cbPassword];
	// 		uint32	cbRequested;
	// 	};
	// however, two issues obstruct direct structure usage:
	//	1) we don't know username/password length apriori
	//	2) we must convert all numeric values to network order (big endian)
	// so, we'll fill output buffer byte-by-byte...

	uint8 eOperation = GET_DATA_AUTH_PLAIN;
	uint8 cbUsername = static_cast<uint8>( strlen(szUsername) );
	uint8 cbPassword = static_cast<uint8>( strlen(szPassword) );
	uint32 cbRequested = static_cast<uint32>( count );
	uint16 cbContentSize = sizeof(cbUsername) + cbUsername + sizeof(cbPassword) + cbPassword + sizeof(cbRequested);

	uint32 bytesToSend = sizeof(eOperation) + sizeof(cbContentSize) + cbContentSize;

	ASSERT(outBufferSize >= bytesToSend);
	byte* pRequestBuffer = outBuffer;

	*(uint8*)pRequestBuffer = eOperation, pRequestBuffer += sizeof(eOperation);
	*(uint16*)pRequestBuffer = htons(cbContentSize), pRequestBuffer += sizeof(cbContentSize);
	*(uint8*)pRequestBuffer = cbUsername, pRequestBuffer += sizeof(cbUsername);
	memcpy(pRequestBuffer, szUsername, cbUsername), pRequestBuffer += cbUsername;
	*(uint8*)pRequestBuffer = cbPassword, pRequestBuffer += sizeof(cbPassword);
	memcpy(pRequestBuffer, szPassword, cbPassword), pRequestBuffer += cbPassword;
	*(uint32*)pRequestBuffer = htonl(cbRequested), pRequestBuffer += sizeof(cbRequested);

	int ret = send(hSocket, (const char*)outBuffer, bytesToSend, 0);
	if (ret == -1) {
		// failed to send data request to the server
		Close();
		throw CommunicationError();
	}
	if (ret != bytesToSend) {
		// failed to send complete data request to the server
		Close();
		throw CommunicationError();
	}

	//
	// receive header (assuming GET_DATA_AUTH_PLAIN, as we requested)
	//

	// server response header structure looks like this:
	// 	struct tServerHeader {
	// 		uint8 response;		// actually from enum ServerResponseCodes
	// 		uint8 reason;		// actually from enum RefusalReasonCodes
	// 		uint32 cbDataLen;	// should be equal to cbRequested, but we should not count on it!
	// 	};
	// however, to avoid packing and memory aligning portability issues,
	// we'll read input buffer byte-by-byte...
	ServerResponseCodes eResponse;
	RefusalReasonCodes eReason;
	uint32 cbDataLen = 0;

	const uint32 bytesHeader = sizeof(uint8) + sizeof(uint8) + sizeof(uint32);
	byte header[bytesHeader];

	uint32 bytesReceived = 0;
	uint32 bytesToReceiveTotal = bytesHeader;
	uint32 bytesToReceiveNow = 0;

	// receive header
	while ( (bytesToReceiveNow = bytesToReceiveTotal - bytesReceived) > 0 ) {

		int ret = recv(hSocket, (char*)(header + bytesReceived), bytesToReceiveNow, 0);

		if (ret != -1) {
			if (ret > 0) {
				// data received
				bytesReceived += ret;

				// parse the server response
				if (bytesReceived >= 2*sizeof(uint8)) {
					eResponse = (ServerResponseCodes) header[0];
					eReason = (RefusalReasonCodes) header[1];

					// process server response...
					if (eResponse != OK) {
						Close();
						throw ServiceDenied(eResponse, eReason);
					}

					if (bytesReceived >= bytesToReceiveTotal) {
						cbDataLen = ntohl( *((u_long*)(header + 2*sizeof(uint8))) );
					}
				}

			} else {
				// recv() returns 0 if connection was closed by server
				Close();
				throw CommunicationError();
			}

		} else {
			int nErr = GetLastSocketError();
			if (nErr == EAGAIN) {
				// wait a little bit, and try again
			} else {
				// some socket(network) error occurred; 
				// it doesn't matter what it is, declare failure!
				Close();
				throw CommunicationError();
			}
		}
	}


	//
	// receive data
	//

	bytesReceived = 0;
	bytesToReceiveTotal = cbDataLen;

	while ( (bytesToReceiveNow = bytesToReceiveTotal - bytesReceived) > 0 ) {
		// limit to maximal socket buffer size used
		bytesToReceiveNow = bytesToReceiveNow < INTERNAL_SOCKET_MAX_BUFFER ? 
							bytesToReceiveNow : INTERNAL_SOCKET_MAX_BUFFER;

		int ret = recv(hSocket, (char*)(buffer + bytesReceived), bytesToReceiveNow, 0);

		if (ret != -1) {
			if (ret > 0) {
				// data received
				bytesReceived += ret;
			} else {
				// recv() returns 0 if connection was closed by server
				Close();
				throw CommunicationError();
			}

		} else {
			int nErr = GetLastSocketError();
			if (nErr == EAGAIN) {
				// wait a little bit, and try again
			} else {
				// some socket(network) error occurred; 
				// it doesn't matter what it is, declare failure!
				Close();
				throw CommunicationError();
			}
		}
	}

	Close();

	// we succeeded.
	return bytesReceived;
}