Example #1
0
static TCPConnection* TCPConnection_Host_checkNewPeerLink(TCPConnection* tcp,const char*& out_peerName,long& peerPort){
    
#ifdef WIN32 
    typedef int TAcceptSizeType;
#else
    typedef unsigned int TAcceptSizeType;
#endif
    
    struct sockaddr	peer_addr;
    TAcceptSizeType peer_addrLen=(TAcceptSizeType)sizeof(peer_addr);
    memset(&peer_addr,0,peer_addrLen);
    
    TSOCKET peer_sockFD=accept(tcp->sockFD,&peer_addr,&peer_addrLen);
    if (peer_sockFD<0)
        return 0;
    else {
        TCPConnection* peerTCP=TCPConnection_create();
        peerTCP->sockFD=peer_sockFD;
        peerTCP->addr=*(sockaddr_in*)&peer_addr;
        peerTCP->he=gethostbyaddr((const char*)&(peerTCP->addr.sin_addr),sizeof(peerTCP->addr.sin_addr),AF_INET);
        out_peerName=peerTCP->he->h_name;
        //const char* peerName=inet_ntoa(peerTCP->addr.sin_addr);
        //out_peerName=peerName;
        peerPort=peerTCP->addr.sin_port;
        
        return peerTCP;
    }
}
Example #2
0
inline TCPConnection*
TCPConnection_connect (CString host, uint16 port)
{
    const int fd = socket(AF_INET, SOCK_STREAM, 0);

    report_zero_if(ERROR_MESSAGE("socket"), fd == -1);

    // Make it so that we can early-return from this scope using one-liners.
    struct Cleanup
    {
        explicit Cleanup (int fd)
            : ok(false), fd(fd)
        {}

        ~Cleanup ()
        {
            return_if(ok);

            close(fd);
        }

        bool ok;
        int  fd;
    }
    cleanup(fd);

    // FIXME: Use the IPv6-compliant getaddrinfo.
    struct hostent* ip = ::gethostbyname(host);

    report_zero_if(ERROR_MESSAGE("gethostbyname"), ip == NULL);

    sockaddr_in address;
    address.sin_family = AF_INET;
    memcpy(&address.sin_addr, ip->h_addr_list[0], ip->h_length);
    address.sin_port = htons(port);

    {
        // Put the socket into non-blocking mode.

        int flags = fcntl(fd, F_GETFL, 0);
        int status = fcntl(fd, F_SETFL, flags | O_NONBLOCK);

        report_zero_if(ERROR_MESSAGE("fcntl"), status < 0);
    }

    {
        // Perform the non-blocking connection dance.
    
        int status = 0;
        do
        {
            status = ::connect(fd, (sockaddr*) &address, sizeof(address));
            
        }
        while (-1 == status && EINTR == errno); // In the extreme case where connect got interrupted by a signal.

        if (0 != status) // TCPConnection did not immediately succeed.
        {
            switch (errno) // Investigate the error, and take action.
            {
                case EINPROGRESS: // The connection is in progress.
                {
                    static const int connectionTimeoutInMilliseconds = 500;
                
                    // Poll the socket for writing, with a timeout.
                    const int ret = select_single_write(fd, connectionTimeoutInMilliseconds);

                    // Select might actually have returned EINPROGRESS, here.
                    // Currently, we behave as if the connection failed when it times out.
                    // FIXME: Introduce an asynchronous callback connection mechanism in parallel to this blocking one.

                    // Abort if select failed.
                    report_zero_unless(ERROR_MESSAGE("select"), 0 < ret);
                    
                    // Also abort if select returned with a descriptor not ready for writing.
                    report_zero_if("Connection timed out.", 0 == ret);

                    // Make sure that the connection is error-free.
                    int       err = 0;
                    socklen_t len = sizeof(int);
                    report_zero_unless(ERROR_MESSAGE("getsockopt"), 0 == getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &len));
                    report_zero_unless(formatted("connect: %s", strerror(err)).get(), 0 == err);

                    break; // The connection is now established.
                }
                
                default: // The connection failed for other reasons.
                {
                    uplink_log_error(ERROR_MESSAGE("connect"));

                    return 0;
                }
            }
        }
    }

    {
        // Put the socket back into blocking mode.
        
        int flags = fcntl(fd, F_GETFL, 0);
        int status = fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);

        report_zero_if(ERROR_MESSAGE("fcntl"), status < 0);
    }

    cleanup.ok = true;

    return TCPConnection_create(fd);
}
Example #3
0
TNetLinkImportHandle netLink_create(){
    TCPConnection* tcp=TCPConnection_create();
    return tcp;
}