// 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; }
// 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; }
//---------------------------------------------------------------------- // 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; }
//---------------------------------------------------------------------- // 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; }
//---------------------------------------------------------------------- // 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; }