Exemplo n.º 1
0
// caller: application
bool UDTConnection::connect( )
{
    struct sockaddr address;
    CCC *cc = NULL;
    int len;

    ConstConnectionDescriptionPtr description = getDescription();
    LBASSERT( CONNECTIONTYPE_UDT == description->type );
    if( !isClosed( ))
        return false;

    _setState( STATE_CONNECTING );

    if( !_parseAddress( description, address, false ))
        goto err;

    LBASSERT( UDT::INVALID_SOCK == _udt );
    _udt = UDT::socket( AF_INET, SOCK_STREAM, 0 );
    if( UDT::INVALID_SOCK == _udt )
    {
        LBERROR << UDTLASTERROR( "UDT::socket" ) << std::endl;
        goto err;
    }

    if( !tuneSocket( ))
        goto err;

    if( UDT::ERROR == UDT::connect( _udt, &address, sizeof( address )))
    {
        LBERROR << UDTLASTERROR( "UDT::connect" ) << std::endl;
        goto err;
    }

    // Do this after connect, otherwise connect itself becomes non-blocking
    static const bool OFF = false;
    if( !setSockOpt( UDT_RCVSYN,
        static_cast<const void *>( &OFF ), sizeof(OFF) ))
        goto err;

    if( UDT::ERROR != UDT::getsockopt( _udt, 0, UDT_CC, &cc, &len ))
    {
        if( NULL != cc )
        {
            CUDPBlast *ccblast = dynamic_cast<CUDPBlast *>( cc );
            if( NULL != ccblast )
                ccblast->setRate( description->bandwidth / 1000. );
        }
    }

    if( initialize( ))
    {
        _setState( STATE_CONNECTED );
        return true;
    }
err:
    return false;
}
Exemplo n.º 2
0
// caller: application
bool UDTConnection::listen( )
{
    struct sockaddr address;

    ConstConnectionDescriptionPtr description = getDescription();
    LBASSERT( CONNECTIONTYPE_UDT == description->type );
    if( !isClosed( ))
        return false;

    _setState( STATE_CONNECTING );

    if( !_parseAddress( description, address, true ))
        goto err;

    LBASSERT( UDT::INVALID_SOCK == _udt );
    _udt = UDT::socket( AF_INET, SOCK_STREAM, 0 );
    if( UDT::INVALID_SOCK == _udt )
    {
        LBERROR << UDTLASTERROR( "UDT::socket" ) << std::endl;
        goto err;
    }

    if( !tuneSocket( ))
        goto err;

    if( UDT::ERROR == UDT::bind( _udt, &address, sizeof( address )))
    {
        LBERROR << UDTLASTERROR( "UDT::bind" ) << std::endl;
        goto err;
    }

    if( UDT::ERROR == UDT::listen( _udt, SOMAXCONN ))
    {
        LBERROR << UDTLASTERROR( "UDT::listen" ) << std::endl;
        goto err;
    }

    if( initialize( ))
    {
        _setState( STATE_LISTENING );
        return true;
    }
err:
    return false;
}
Exemplo n.º 3
0
//----------------------------------------------------------------------
// listen
//----------------------------------------------------------------------
bool SocketConnection::listen()
{
    ConnectionDescriptionPtr description = _getDescription();
    LBASSERT( description->type == CONNECTIONTYPE_TCPIP );

    if( !isClosed( ))
        return false;

    _setState( STATE_CONNECTING );

    sockaddr_in address;
    const size_t size = sizeof( sockaddr_in );

    if( !_parseAddress( description, address ))
    {
        LBWARN << "Can't parse connection parameters" << std::endl;
        return false;
    }

    if( !_createSocket())
        return false;

    const bool bound = (::bind( _readFD, (sockaddr *)&address, size ) == 0);

    if( !bound )
    {
        LBWARN << "Could not bind socket " << _readFD << ": "
               << lunchbox::sysError << " to " << getHostName( address )
               << ":" << ntohs( address.sin_port ) << " AF "
               << (int)address.sin_family << std::endl;

        close();
        return false;
    }

    if( ::listen( _readFD, SOMAXCONN ) != 0 )
    {
        LBWARN << "Could not listen on socket: " << lunchbox::sysError
               << std::endl;
        close();
        return false;
    }

    // get socket parameters
    socklen_t used = size;
    getsockname( _readFD, (struct sockaddr *)&address, &used );
    description->port = ntohs( address.sin_port );

    std::string hostname = description->getHostname();
    if( hostname.empty( ))
    {
        if( address.sin_addr.s_addr == INADDR_ANY )
        {
            char cHostname[256] = {0};
            gethostname( cHostname, 256 );
            hostname = cHostname;

            description->setHostname( hostname );
        }
        else
            description->setHostname( getHostName( address ));
    }

    _initAIOAccept();
    _setState( STATE_LISTENING );

    LBDEBUG << "Listening on " << description->getHostname() << "["
           << getHostName( address ) << "]:" << description->port
           << " (" << description->toString() << ")" << std::endl;

    return true;
}
Exemplo n.º 4
0
//----------------------------------------------------------------------
// connect
//----------------------------------------------------------------------
bool SocketConnection::connect()
{
    ConnectionDescriptionPtr description = _getDescription();
    LBASSERT( description->type == CONNECTIONTYPE_TCPIP );
    if( !isClosed( ))
        return false;

    if( description->port == 0 )
        return false;

    if( description->getHostname().empty( ))
        description->setHostname( "127.0.0.1" );

    sockaddr_in address;
    if( !_parseAddress( description, address ))
    {
        LBWARN << "Can't parse connection parameters" << std::endl;
        return false;
    }

    _setState( STATE_CONNECTING );

    if( !_createSocket( ))
        return false;

    if( address.sin_addr.s_addr == 0 )
    {
        LBWARN << "Refuse to connect to 0.0.0.0" << std::endl;
        close();
        return false;
    }

#ifdef _WIN32
    const bool connected = WSAConnect( _readFD, (sockaddr*)&address,
                                       sizeof( address ), 0, 0, 0, 0 ) == 0;
#else
    int nTries = 10;
    while( nTries-- )
    {
        const bool connected = (::connect( _readFD, (sockaddr*)&address,
                                           sizeof( address )) == 0);
        if( connected )
            break;

        switch( errno )
        {
          case EINTR: // Happens sometimes, but looks harmless
              LBDEBUG << "connect: " << lunchbox::sysError << ", retrying"
                     << std::endl;
              lunchbox::sleep( 5 /*ms*/ );
              break;

          default:
              nTries = 0;
              break;
        }
    }
    const bool connected = nTries > 0;
#endif

    if( !connected )
    {
        LBDEBUG << "Could not connect to '" << description->getHostname() << ":"
                << description->port << "': " << lunchbox::sysError << std::endl;
        close();
        return false;
    }

    _initAIORead();
    _setState( STATE_CONNECTED );
    LBDEBUG << "Connected " << description->toString() << std::endl;
    return true;
}
Exemplo n.º 5
0
//----------------------------------------------------------------------
// listen
//----------------------------------------------------------------------
bool PGMConnection::listen()
{
    EQASSERT( _description->type == CONNECTIONTYPE_PGM );

    if( _state != STATE_CLOSED )
        return false;

    _state = STATE_CONNECTING;
    _fireStateChanged();

    sockaddr_in address;
    const size_t size = sizeof( sockaddr_in ); 

    if( !_parseAddress( address ))
    {
        EQWARN << "Can't parse connection parameters" << std::endl;
        return false;
    }

    //-- create a 'listening' read socket
    _readFD = _initSocket( address );
    
    if( _readFD == INVALID_SOCKET || !_setupReadSocket( ))
    {
        close();
        return false;
    }

    const bool listening = (::listen( _readFD, 10 ) == 0);
        
    if( !listening )
    {
        EQWARN << "Could not listen on socket: " << base::sysError 
               << std::endl;
        close();
        return false;
    }

    // get listening socket parameters
    socklen_t used = size;
    getsockname( _readFD, (struct sockaddr *)&address, &used ); 

    _description->port = ntohs( address.sin_port );

    const std::string& hostname = _description->getHostname();
    if( hostname.empty( ))
    {
        if( address.sin_addr.s_addr == INADDR_ANY )
        {
            char cHostname[256];
            gethostname( cHostname, 256 );
            _description->setHostname( cHostname );
        }
        else
            _description->setHostname( inet_ntoa( address.sin_addr ));
    }
    
    _initAIOAccept();

    
    //-- create a connected 'write' socket
    address.sin_family      = AF_INET;
    address.sin_addr.s_addr = htonl( INADDR_ANY );
    address.sin_port        = htons( 0 );
    memset( &(address.sin_zero), 0, 8 ); // zero the rest

    _writeFD = _initSocket( address );

    if( _writeFD == INVALID_SOCKET || !_setupSendSocket( ))
    {
        close();
        return false;
    }

    _parseAddress( address );
    
#ifdef _WIN32
    const bool connected = WSAConnect( _writeFD, (sockaddr*)&address, 
                                       size, 0, 0, 0, 0 ) == 0;
#else
    const bool connected = (::connect( _readFD, (sockaddr*)&address, 
                                       size ) == 0);
#endif

    if( !connected )
    {
        EQWARN << "Could not connect to '" << _description->getHostname() << ":"
               << _description->port << "': " << base::sysError 
               << std::endl;
        close();
        return false;
    }

    _state = STATE_LISTENING;
    _fireStateChanged();

    EQINFO << "Listening on " << _description->getHostname() << "["
           << inet_ntoa( address.sin_addr ) << "]:" << _description->port
           << " (" << _description->toString() << ")" << std::endl;
    
    return true;
}
static AthenaTransportLink *
_ETHOpen(AthenaTransportLinkModule *athenaTransportLinkModule, PARCURI *connectionURI)
{
    AthenaTransportLink *result = 0;
    char device[NI_MAXHOST];

    const char *authorityString = parcURI_GetAuthority(connectionURI);
    if (authorityString == NULL) {
        parcLog_Error(athenaTransportLinkModule_GetLogger(athenaTransportLinkModule),
                      "Unable to parse connection authority %s", authorityString);
        errno = EINVAL;
        return NULL;
    }
    PARCURIAuthority *authority = parcURIAuthority_Parse(authorityString);
    const char *URIHostname = parcURIAuthority_GetHostName(authority);
    strcpy(device, URIHostname);

    bool srcMACSpecified = false;
    struct ether_addr srcMAC = { { 0 } };
    struct ether_addr destMAC = { { 0 } };
    if (_parseAddress(authorityString, &destMAC) != 0) {
        parcURIAuthority_Release(&authority);
        errno = EINVAL;
        return NULL;
    }
    parcURIAuthority_Release(&authority);

    bool isListener = false;
    char *linkName = NULL;
    char specifiedLinkName[MAXPATHLEN] = { 0 };
    size_t mtu = 0;
    int forceLocal = 0;

    PARCURIPath *remainder = parcURI_GetPath(connectionURI);
    size_t segments = parcURIPath_Count(remainder);
    for (int i = 0; i < segments; i++) {
        PARCURISegment *segment = parcURIPath_Get(remainder, i);
        const char *token = parcURISegment_ToString(segment);

        if (strcasecmp(token, ETH_LISTENER_FLAG) == 0) {
            // Packet source for listener is destination parameter, unless told otherwise
            if (srcMACSpecified == false) {
                memcpy(&srcMAC, &destMAC, sizeof(struct ether_addr));
            }
            isListener = true;
            parcMemory_Deallocate(&token);
            continue;
        }

        if (strncasecmp(token, SRC_LINK_SPECIFIER, strlen(SRC_LINK_SPECIFIER)) == 0) {
            if (_parseSrc(athenaTransportLinkModule, token, &srcMAC) != 0) {
                parcLog_Error(athenaTransportLinkModule_GetLogger(athenaTransportLinkModule),
                              "Improper connection source specification (%s)", token);
                parcMemory_Deallocate(&token);
                return NULL;
            }
            srcMACSpecified = true;
            parcMemory_Deallocate(&token);
            continue;
        }

        if (strncasecmp(token, LINK_MTU_SIZE, strlen(LINK_MTU_SIZE)) == 0) {
            if (_parseMTU(token, &mtu) == -1) {
                parcLog_Error(athenaTransportLinkModule_GetLogger(athenaTransportLinkModule),
                              "Improper MTU specification (%s)", token);
                parcMemory_Deallocate(&token);
                errno = EINVAL;
                return NULL;
            }
            parcMemory_Deallocate(&token);
            continue;
        }

        if (strncasecmp(token, LINK_NAME_SPECIFIER, strlen(LINK_NAME_SPECIFIER)) == 0) {
            if (_parseLinkName(token, specifiedLinkName) != 0) {
                parcLog_Error(athenaTransportLinkModule_GetLogger(athenaTransportLinkModule),
                              "Improper connection name specification (%s)", token);
                parcMemory_Deallocate(&token);
                errno = EINVAL;
                return NULL;
            }
            linkName = specifiedLinkName;
            parcMemory_Deallocate(&token);
            continue;
        }

        if (strncasecmp(token, LOCAL_LINK_FLAG, strlen(LOCAL_LINK_FLAG)) == 0) {
            forceLocal = _parseLocalFlag(token);
            if (forceLocal == 0) {
                parcLog_Error(athenaTransportLinkModule_GetLogger(athenaTransportLinkModule),
                              "Improper local specification (%s)", token);
                parcMemory_Deallocate(&token);
                errno = EINVAL;
                return NULL;
            }
            parcMemory_Deallocate(&token);
            continue;
        }

        parcLog_Error(athenaTransportLinkModule_GetLogger(athenaTransportLinkModule),
                      "Unknown connection parameter (%s)", token);
        parcMemory_Deallocate(&token);
        errno = EINVAL;
        return NULL;
    }

    if (isListener) {
        result = _ETHOpenListener(athenaTransportLinkModule, linkName, device, &srcMAC, mtu);
    } else {
        if (srcMACSpecified) {
            result = _ETHOpenConnection(athenaTransportLinkModule, linkName, device, &srcMAC, &destMAC, mtu);
        } else {
            result = _ETHOpenConnection(athenaTransportLinkModule, linkName, device, NULL, &destMAC, mtu);
        }
    }

    // forced IsLocal/IsNotLocal, mainly for testing
    if (result && forceLocal) {
        athenaTransportLink_ForceLocal(result, forceLocal);
    }

    return result;
}