예제 #1
0
bool PipeConnection::_createPipes()
{
    std::stringstream pipeName;
    pipeName << "\\\\.\\pipe\\Collage." << UUID( true );

    ConnectionDescriptionPtr desc = new ConnectionDescription;
    desc->type = CONNECTIONTYPE_NAMEDPIPE;
    desc->setFilename( pipeName.str( ));

    ConnectionPtr connection = Connection::create( desc );
    _namedPipe = static_cast< NamedPipeConnection* >( connection.get( ));
    if( !_namedPipe->listen( ))
        return false;
    _namedPipe->acceptNB();

    connection = Connection::create( desc );
    _sibling->_namedPipe = static_cast<NamedPipeConnection*>(connection.get());
    if( !_sibling->_namedPipe->connect( ))
    {
        _sibling->_namedPipe = 0;
        return false;
    }

    connection = _namedPipe->acceptSync();
    _namedPipe = static_cast< NamedPipeConnection* >(connection.get( ));
    return true;
}
예제 #2
0
ConnectionPtr SocketConnection::acceptSync()
{
    LB_TS_THREAD( _recvThread );
    if( !isListening( ))
        return 0;

    LBASSERT( _overlappedAcceptData );
    LBASSERT( _overlappedSocket != INVALID_SOCKET );
    if( _overlappedSocket == INVALID_SOCKET )
        return 0;

    // complete accept
    DWORD got   = 0;
    DWORD flags = 0;

    if( !WSAGetOverlappedResult( _readFD, &_overlappedRead, &got, TRUE,
                                 &flags ))
    {
        LBWARN << "Accept completion failed: " << lunchbox::sysError
               << ", closing socket" << std::endl;
        close();
        return 0;
    }

    sockaddr_in* local     = 0;
    sockaddr_in* remote    = 0;
    int          localLen  = 0;
    int          remoteLen = 0;
    GetAcceptExSockaddrs( _overlappedAcceptData, 0, sizeof( sockaddr_in ) + 16,
                          sizeof( sockaddr_in ) + 16, (sockaddr**)&local,
                          &localLen, (sockaddr**)&remote, &remoteLen );
    _tuneSocket( _overlappedSocket );

    ConstConnectionDescriptionPtr description = getDescription();
    SocketConnection* newConnection = new SocketConnection;
    ConnectionPtr connection( newConnection ); // to keep ref-counting correct

    newConnection->_readFD  = _overlappedSocket;
    newConnection->_writeFD = _overlappedSocket;

#ifndef _WIN32
    //fcntl( _overlappedSocket, F_SETFL, O_NONBLOCK );
#endif

    newConnection->_initAIORead();
    _overlappedSocket       = INVALID_SOCKET;

    newConnection->_setState( STATE_CONNECTED );
    ConnectionDescriptionPtr newDescription = newConnection->_getDescription();
    newDescription->bandwidth = description->bandwidth;
    newDescription->port = ntohs( remote->sin_port );
    newDescription->setHostname( getHostName( *remote ));

    LBDEBUG << "accepted connection from " << newDescription->getHostname()
           << ":" << newDescription->port << std::endl;
    return connection;
}
예제 #3
0
void LocalNode::_connectMulticast( NodePtr node )
{
    EQASSERT( _inReceiverThread( ));
    base::ScopedMutex<> mutex( _outMulticast );

    if( node->_outMulticast.data.isValid( ))
        // multicast already connected by previous _cmdID
        return;

    // Search if the connected node is in the same multicast group as we are
    ConnectionDescriptions descriptions = getConnectionDescriptions();
    for( ConnectionDescriptions::const_iterator i = descriptions.begin();
         i != descriptions.end(); ++i )
    {
        ConnectionDescriptionPtr description = *i;
        if( description->type < CONNECTIONTYPE_MULTICAST )
            continue;

        const ConnectionDescriptions& fromDescs =
            node->getConnectionDescriptions();
        for( ConnectionDescriptions::const_iterator j = fromDescs.begin();
             j != fromDescs.end(); ++j )
        {
            ConnectionDescriptionPtr fromDescription = *j;
            if( !description->isSameMulticastGroup( fromDescription ))
                continue;
            
            EQASSERT( !node->_outMulticast.data );
            EQASSERT( node->_multicasts.empty( ));

            if( _outMulticast->isValid() && 
                _outMulticast.data->getDescription() == description )
            {
                node->_outMulticast.data = _outMulticast.data;
                EQINFO << "Using " << description << " as multicast group for "
                       << node->getNodeID() << std::endl;
            }
            // find unused multicast connection to node
            else for( MCDatas::const_iterator k = _multicasts.begin();
                      k != _multicasts.end(); ++k )
            {
                const MCData& data = *k;
                ConnectionDescriptionPtr dataDesc = 
                    data.connection->getDescription();
                if( !description->isSameMulticastGroup( dataDesc ))
                    continue;

                node->_multicasts.push_back( data );
                EQINFO << "Adding " << dataDesc << " as multicast group for "
                       << node->getNodeID() << std::endl;
            }
        }
    }
}
std::string serialize( const ConnectionDescriptions& descriptions )
{
    std::ostringstream data;
    data << descriptions.size() << CO_SEPARATOR;

    for( ConnectionDescriptions::const_iterator i = descriptions.begin();
         i != descriptions.end(); ++i )
    {
        ConnectionDescriptionPtr desc = *i;
        desc->serialize( data );
    }

    return data.str();
}
예제 #5
0
// caller: application
ConnectionPtr UDTConnection::acceptSync( )
{
    struct sockaddr address;
    int addrlen;

    UDTSOCKET newSocket = UDT::accept( _udt, &address, &addrlen );
    UDTConnectionPtr newConnection = new UDTConnection;

    if( UDT::INVALID_SOCK == newSocket )
    {
        LBERROR << UDTLASTERROR( "UDT::accept" ) << std::endl;
        close( );
        goto err;
    }

    acknowledge( _notifier );

    newConnection->_udt = newSocket;

    // Do this after accept, otherwise accept itself becomes non-blocking
    static const bool OFF = false;
    if( newConnection->setSockOpt( UDT_RCVSYN,
                                   static_cast<const void *>( &OFF ),
                                   sizeof(OFF) ))
    {
        ConnectionDescriptionPtr desc = newConnection->_getDescription();
        desc->setHostname( ::inet_ntoa(
                                  ((struct sockaddr_in *)&address)->sin_addr ));
        desc->port = ntohs( ((struct sockaddr_in *)&address)->sin_port );
        desc->bandwidth = getDescription()->bandwidth;
        if( newConnection->initialize( ))
        {
            newConnection->_setState( STATE_CONNECTED );
            goto out;
        }
    }
    // else goto err;
err:
    newConnection = 0;

out:
    // Let the event thread continue polling
    lunchbox::ScopedMutex<> mutex( _app_mutex );

    _app_block.set( true );

    return newConnection;
}
예제 #6
0
void Connection::_setDescription( ConnectionDescriptionPtr description )
{
    LBASSERT( description.isValid( ));
    LBASSERTINFO( _impl->description->type == description->type,
                  "Wrong connection type in description" );
    _impl->description = description;
    LBASSERT( description->bandwidth > 0 );
}
예제 #7
0
void Connection::setDescription( ConnectionDescriptionPtr description )
{
    EQASSERT( description.isValid( ));
    EQASSERTINFO( _description->type == description->type,
                  "Wrong connection type in description" );
    _description = description;
    EQASSERT( description->bandwidth > 0 );
}
예제 #8
0
std::ostream& operator << ( std::ostream& os, const Connection& connection )
{
    Connection::State        state = connection.getState();
    ConnectionDescriptionPtr desc  = connection.getDescription();

    os << "Connection " << (void*)&connection << " type "
       << typeid( connection ).name() << " state "
       << ( state == Connection::STATE_CLOSED     ? "closed" :
            state == Connection::STATE_CONNECTING ? "connecting" :
            state == Connection::STATE_CONNECTED  ? "connected" :
            state == Connection::STATE_LISTENING  ? "listening" :
            state == Connection::STATE_CLOSING    ? "closing" :
            "UNKNOWN" );
    if( desc.isValid( ))
        os << " description " << desc->toString();

    return os;
}
bool deserialize( std::string& data, ConnectionDescriptions& descriptions )
{
    if( !descriptions.empty( ))
        LBWARN << "Connection descriptions already hold data before deserialize"
               << std::endl;

    // num connection descriptions
    size_t nextPos = data.find( CO_SEPARATOR );
    if( nextPos == std::string::npos || nextPos == 0 )
    {
        LBERROR << "Could not parse number of connection descriptions"
                << std::endl;
        return false;
    }

    const std::string sizeStr = data.substr( 0, nextPos );
    if( !isdigit( sizeStr[0] ))
    {
        LBERROR << "Could not parse number of connection descriptions"
                << std::endl;
        return false;
    }

    const size_t nDesc = atoi( sizeStr.c_str( ));
    data = data.substr( nextPos + 1 );

    // connection descriptions
    for( size_t i = 0; i < nDesc; ++i )
    {
        ConnectionDescriptionPtr desc = new ConnectionDescription;
        if( !desc->fromString( data ))
        {
            LBERROR << "Error during connection description parsing"
                    << std::endl;
            return false;
        }
        descriptions.push_back( desc );
    }

    return true;
}
예제 #10
0
ConnectionPtr SocketConnection::acceptSync()
{
    if( !isListening( ))
        return 0;

    sockaddr_in newAddress;
    socklen_t   newAddressLen = sizeof( newAddress );

    Socket    fd;
    unsigned  nTries = 1000;
    do
        fd = ::accept( _readFD, (sockaddr*)&newAddress, &newAddressLen );
    while( fd == INVALID_SOCKET && errno == EINTR && --nTries );

    if( fd == INVALID_SOCKET )
    {
      LBWARN << "accept failed: " << lunchbox::sysError << std::endl;
        return 0;
    }

    _tuneSocket( fd );

    ConstConnectionDescriptionPtr description = getDescription();
    SocketConnection* newConnection = new SocketConnection;

    newConnection->_readFD      = fd;
    newConnection->_writeFD     = fd;
    newConnection->_setState( STATE_CONNECTED );
    ConnectionDescriptionPtr newDescription = newConnection->_getDescription();
    newDescription->bandwidth = description->bandwidth;
    newDescription->port = ntohs( newAddress.sin_port );
    newDescription->setHostname( inet_ntoa( newAddress.sin_addr ));

    LBDEBUG << "Accepted " << newDescription->toString() << std::endl;
    return newConnection;
}
예제 #11
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;
}
예제 #12
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;
}