Exemplo n.º 1
0
int TcpTransport::Connect(const std::string &strServerURL)
{
	if (m_state == CLIENT_STATE_UNINIT)
	{
		return CLIENT_ERROR_INIT;
	}

	if (IsConnected())
	{
		if (strServerURL.compare(m_serverURL) == 0)
		{
			return CLIENT_ERROR_SUCCESS;
		}
		else
		{
			Close();
		}
	}

	short port;
	std::string strAddr;

	if (!SplitURL(strServerURL, strAddr, port))
	{
		return CLIENT_ERROR_INVALID_URL;
	}

	struct sockaddr_in sa;
	sa.sin_family = AF_INET;
	sa.sin_port = htons(port);

	sa.sin_addr.s_addr = inet_addr(strAddr.c_str());




	m_sfd = (int)socket(AF_INET, SOCK_STREAM, 0);

	if (SetTcpNoDelay(m_sfd) == -1)
	{
		closesocket(m_sfd);
		return CLIENT_ERROR_CONNECT;
	}

	// handshake SSL.


	if (MakeSocketNonblocking(m_sfd) == -1)
	{
		return CLIENT_ERROR_CONNECT;
	}
	
	if (!enableSSL && connect(m_sfd,(struct sockaddr*)&sa, sizeof(sockaddr)) == -1)
	{
		int err = NET_ERROR;
		if (err == WSAEWOULDBLOCK || err == WSAEINPROGRESS)
		{
			fd_set wfd;
			fd_set exceptfds;

			FD_ZERO(&wfd);
			FD_ZERO(&exceptfds);
			FD_SET(m_sfd,&wfd);
			FD_SET(m_sfd, &exceptfds);

			struct timeval tv = {5, 0};

			if (select(FD_SETSIZE, NULL, &wfd, &exceptfds, &tv) == -1)
			{
				closesocket(m_sfd);
				return CLIENT_ERROR_CONNECT;
			}

			if (!FD_ISSET(m_sfd,&wfd))
			{
				closesocket(m_sfd);
				return CLIENT_ERROR_CONNECT;
			}

#ifndef WIN32

			int opterr = 0;
			socklen_t errlen = sizeof(opterr);
			if (getsockopt(m_sfd,SOL_SOCKET, SO_ERROR, &opterr, &errlen) == -1)
			{
				closesocket(m_sfd);
				return CLIENT_ERROR_CONNECT;
			}

			if (opterr)
			{
				closesocket(m_sfd);
				return CLIENT_ERROR_CONNECT;
			}
#endif
		}
		else
		{
			return CLIENT_ERROR_CONNECT;
		}
	}

	m_serverURL = strServerURL;
    m_state = CLIENT_STATE_CONNECTED;
	m_recvBufUsed = 0;

	return CLIENT_ERROR_SUCCESS;
}
Exemplo n.º 2
0
bool_t XPlat_SocketUtils_AcceptConnection( XPlat_Socket listen_sock, 
                                           XPlat_Socket* connected_sock,
                                           int timeout_sec,
                                           bool_t nonblock )
{
    int err, maxfd, retval;
    XPlat_Socket connection;
    const char* err_str;
    fd_set readfds;
    struct timeval tv;

    xplat_dbg( 3, xplat_printf(FLF, stderr,
                          "listening on socket=%d\n", listen_sock) );

    *connected_sock = InvalidSocket;

    if( nonblock && (0 == timeout_sec) )
        timeout_sec = 1;

    do {
        if( timeout_sec > 0 ) {
            // use select with timeout
            FD_ZERO( &readfds );
            FD_SET( listen_sock, &readfds );
            
            tv.tv_sec = timeout_sec;
            tv.tv_usec = 0;
        
            maxfd = listen_sock + 1;
            retval = select( maxfd, &readfds, NULL, NULL, &tv );
            err = XPlat_NetUtils_GetLastError();
            if( retval == 0 ) { // timed-out
                return false; // let caller decide what's next
            }
            else if( retval < 0 ) {
                err_str = XPlat_Error_GetErrorString(err);
                xplat_dbg( 1, xplat_printf(FLF, stderr,
                                      "select() failed with '%s'\n", err_str) );
                return false;
            }
        }

        // now try to accept a connection
        connection = accept( listen_sock, NULL, NULL );
        if( -1 == connection ) {
            err = XPlat_NetUtils_GetLastError();
            if( nonblock && (EWOULDBLOCK == err) )
                return false; // let caller decide what's next
	    if( EWOULDBLOCK != err ) {
                err_str = XPlat_Error_GetErrorString(err);
                xplat_dbg( 1, xplat_printf(FLF, stderr,
                                      "accept() failed with '%s'\n", err_str) );
	    } 
            if( EINTR != err )
                return false;
        }
    } while( -1 == connection );

    // Set the socket to be blocking
    if( ! XPlat_SocketUtils_SetBlockingMode(connection, true) )
        xplat_dbg( 1, xplat_printf(FLF, stderr,
                              "failed to set blocking\n") );

    // Close socket on exec
    if( ! SetCloseOnExec(connection) ) {
        xplat_dbg( 1, xplat_printf(FLF, stderr,
                              "failed to set close-on-exec\n") );     
    }
    
    // Turn off Nagle algorithm
    if( ! SetTcpNoDelay(connection) ) {
        xplat_dbg( 1, xplat_printf(FLF, stderr, 
                              "failed to set TCP_NODELAY\n") );
    }

    xplat_dbg( 3, xplat_printf(FLF, stderr,
                          "returning socket=%d\n", connection) );
    *connected_sock = connection;
    return true;
}
Exemplo n.º 3
0
bool_t XPlat_SocketUtils_Connect( const char* host,
                                  const XPlat_Port port,
                                  XPlat_Socket* sock,
                                  unsigned num_retry )
{
    unsigned nConnectTries = 0;
    int err, cret = -1;
    XPlat_Socket _sock = *sock;
    const char* err_str = NULL;
    struct hostent *server_hostent = NULL;
    struct sockaddr_in server_addr;

    xplat_dbg( 3, xplat_printf(FLF, stderr,
                          "host=%s port=%hu sock=%d\n",
                          host, port, _sock) );

    if( InvalidSocket == _sock ) {
        _sock = socket( AF_INET, SOCK_STREAM, 0 );
        if ( InvalidSocket == _sock ) {
            err = XPlat_NetUtils_GetLastError();
            err_str = XPlat_Error_GetErrorString(err);
            xplat_dbg( 1, xplat_printf(FLF, stderr,
                                  "socket() failed with '%s'\n", err_str) );
            return false;
        }
        xplat_dbg( 5, xplat_printf(FLF, stderr,
                              "socket() => %d\n", _sock) );
    }

    server_hostent = gethostbyname( host ); 
    if ( NULL == server_hostent ) {
        err = XPlat_NetUtils_GetLastError();
        err_str = XPlat_Error_GetErrorString(err);
        xplat_dbg( 1, xplat_printf(FLF, stderr,
                              "gethostbyname() failed with '%s'\n", err_str) );
        return false;
    } 

    memset( &server_addr, 0, sizeof(server_addr) );
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons( port );
    memcpy( &server_addr.sin_addr, server_hostent->h_addr_list[0],
            sizeof(struct in_addr) );

    do {
        cret = connect( _sock, (struct sockaddr *) &server_addr, 
                        (socklen_t) sizeof(server_addr) );
        if( -1 == cret ) {
            err = XPlat_NetUtils_GetLastError();
            err_str = XPlat_Error_GetErrorString(err);
            xplat_dbg( 5, xplat_printf(FLF, stderr,
                                  "connect() failed with '%s'\n", err_str) );
            if( ! (XPlat_Error_ETimedOut(err) || 
                   XPlat_Error_EConnRefused(err)) ) {
                xplat_dbg(1, xplat_printf(FLF, stderr,
                                     "connect() to %s:%hu failed with '%s'\n", 
                                      host, port, err_str));
                return false;
            }

            nConnectTries++;
            xplat_dbg( 3, xplat_printf(FLF, stderr,
                                  "timed out %d times\n", nConnectTries) );
            if( (num_retry > 0) && (nConnectTries >= num_retry) )
                break;

            // delay before trying again (more each time)
            sleep( nConnectTries );
        }
    } while( -1 == cret );

    if( -1 == cret ) {
        err_str = XPlat_Error_GetErrorString(err);
        xplat_dbg( 1, xplat_printf(FLF, stderr,
                              "connect() to %s:%d failed with '%s'\n", 
                              host, port, err_str) );
        return false;
    }

    xplat_dbg( 5, xplat_printf(FLF, stderr,
                          "connected to %s:%d \n", host, port) );

    // Close socket on exec
    if( ! SetCloseOnExec(_sock) ) {
        xplat_dbg( 1, xplat_printf(FLF, stderr, "XPlat_SocketUtils_Connect - " 
                              "failed to set close-on-exec\n") );
    }

    // Turn off Nagle algorithm
    if( ! SetTcpNoDelay(_sock) ) {
        xplat_dbg( 1, xplat_printf(FLF, stderr, 
                              "failed to set TCP_NODELAY\n") );
    }

    xplat_dbg( 3, xplat_printf(FLF, stderr,             
                          "returning socket=%d\n", _sock) );
    *sock = _sock;
    return true;
}
Exemplo n.º 4
0
bool_t XPlat_SocketUtils_CreateListening( XPlat_Socket* sock, 
                                          XPlat_Port* port, 
                                          bool_t nonblock )
{
    static int backlog = 128;
    int err, optval;
    bool_t soret, success;
    XPlat_Socket _sock;
    XPlat_Port _port = *port;
    const char* err_str = NULL;
    struct sockaddr_in local_addr;

    if( InvalidPort == _port )
        _port = 0;

    _sock = socket( AF_INET, SOCK_STREAM, 0 );
    if( -1 == _sock ) {
        err = XPlat_NetUtils_GetLastError();
        err_str = XPlat_Error_GetErrorString(err);
        xplat_dbg( 1, xplat_printf(FLF, stderr,
                              "socket() failed with '%s'\n", err_str) );
        return false;
    }

    xplat_dbg( 3, xplat_printf(FLF, stderr,
                          "sock:%d, port:%d\n",
                          _sock, _port) );

    // Close socket on exec
    if( ! SetCloseOnExec(_sock) ) {
        xplat_dbg( 1, xplat_printf(FLF, stderr,
                              "failed to set close-on-exec\n") );     
    }

    // Set listening socket to non-blocking if requested
    if( nonblock ) {
        if( ! XPlat_SocketUtils_SetBlockingMode(_sock, false) )
            xplat_dbg( 1, xplat_printf(FLF, stderr,
                                  "failed to set non-blocking\n") );
    }

#ifndef os_windows
    /* Set the socket so that it does not hold onto its port after
     * the process exits (needed because on at least some platforms we
     * use well-known ports when connecting sockets) */
    optval = 1;
    soret = XPlat_SocketUtils_SetOption( _sock, SOL_SOCKET, SO_REUSEADDR, 
                                         (void*) &optval, 
                                         (socklen_t) sizeof(optval) );
    if( ! soret ) {
        err = XPlat_NetUtils_GetLastError();
        err_str = XPlat_Error_GetErrorString(err);
        xplat_dbg( 1, xplat_printf(FLF, stderr,
                              "setsockopt() failed with '%s'\n", err_str) );
    }
#endif

    memset( &local_addr, 0, sizeof(local_addr) );
    local_addr.sin_family = AF_INET;
    local_addr.sin_addr.s_addr = htonl( INADDR_ANY );

    if( 0 != _port ) {
        // try to bind and listen using the supplied port
        local_addr.sin_port = htons( _port );
        if( -1 == bind(_sock, (struct sockaddr*)&local_addr, sizeof(local_addr)) ) {
            err = XPlat_NetUtils_GetLastError();
            err_str = XPlat_Error_GetErrorString(err);
            xplat_dbg( 1, xplat_printf(FLF, stderr,
                                  "bind() to static port %d failed with '%s'\n",
                                   _port, err_str) );
            XPlat_SocketUtils_Close( _sock );
            return false;
        }
    }

#ifndef os_windows
    // else, the system will assign a port for us in listen
    if( -1 == listen(_sock, backlog) ) {
        err = XPlat_NetUtils_GetLastError();
        err_str = XPlat_Error_GetErrorString(err);
        xplat_dbg( 1, xplat_printf(FLF, stderr,
                              "listen() failed with '%s'\n", err_str) );
        XPlat_SocketUtils_Close( _sock );
        return false;
    }
    // determine which port we were actually assigned to
    if( ! XPlat_SocketUtils_GetPort(_sock, &_port) ) {
        xplat_dbg( 1, xplat_printf(FLF, stderr,
                              "failed to obtain port from socket\n" ) );
        XPlat_SocketUtils_Close( _sock );
        return false;
    }
#else
    // try binding ports, starting from 1st dynamic port
    _port = 49152;
    success = false;
    do {
        local_addr.sin_port = htons( _port );
        if( -1 == bind(_sock, (struct sockaddr*)&local_addr, sizeof(local_addr)) ) {
            err = XPlat_NetUtils_GetLastError();
            if( XPlat_Error_EAddrInUse( err ) ) {
                ++_port;
                continue;
            }
            else {
                err_str = XPlat_Error_GetErrorString(err);
                xplat_dbg( 1, xplat_printf(FLF, stderr,
                                      "bind() to dynamic port %d failed with '%s'\n",
                                      _port, err_str) );
                XPlat_SocketUtils_Close( _sock );
                return false;
            }
        }
        else {
            if( -1 == listen(_sock, backlog) ) {
                err = XPlat_NetUtils_GetLastError();
                if( XPlat_Error_EAddrInUse( err ) ) {
                    ++_port;
                    continue;
                }
                else {
                    err_str = XPlat_Error_GetErrorString(err);
                    xplat_dbg( 1, xplat_printf(FLF, stderr,
                                          "listen() failed with '%s'\n", err_str) );
                    XPlat_SocketUtils_Close( _sock );
                    return false;
                }
            }
            success = true;
        }
    } while( ! success );
#endif

    // Turn off Nagle algorithm
    if( ! SetTcpNoDelay(_sock) ) {
        xplat_dbg( 1, xplat_printf(FLF, stderr,
                              "failed to set TCP_NODELAY\n") );
    }

    *port = _port;
    *sock = _sock;
    xplat_dbg( 3, xplat_printf(FLF, stderr,
                          "returning socket=%d, port=%hu\n", _sock, _port) );
 
    return true;
}