2022-01-07 06:39:55 -08:00
/*************************************************************************
* Copyright (c) 2016-2022, NVIDIA CORPORATION. All rights reserved.
*
* See LICENSE.txt for license information
************************************************************************/
#include "socket.h"
#include "utils.h"
#include <stdlib.h>
#include <unistd.h>
#include <ifaddrs.h>
#include <net/if.h>
/* Format a string representation of a (union ncclSocketAddress *) socket address using getnameinfo()
*
* Output: "IPv4/IPv6 address<port>"
*/
2022-03-30 02:25:49 -07:00
const char * ncclSocketToString ( union ncclSocketAddress * addr , char * buf , const int numericHostForm /*= 1*/ ) {
2022-01-07 06:39:55 -08:00
if ( buf == NULL || addr == NULL ) return NULL ;
struct sockaddr * saddr = & addr -> sa ;
if ( saddr -> sa_family != AF_INET && saddr -> sa_family != AF_INET6 ) { buf [ 0 ] = '\0' ; return buf ; }
char host [ NI_MAXHOST ], service [ NI_MAXSERV ];
2022-03-30 02:25:49 -07:00
/* NI_NUMERICHOST: If set, then the numeric form of the hostname is returned.
* (When not set, this will still happen in case the node's name cannot be determined.)
*/
int flag = NI_NUMERICSERV | ( numericHostForm ? NI_NUMERICHOST : 0 );
( void ) getnameinfo ( saddr , sizeof ( union ncclSocketAddress ), host , NI_MAXHOST , service , NI_MAXSERV , flag );
2022-01-07 06:39:55 -08:00
sprintf ( buf , "%s<%s>" , host , service );
return buf ;
}
static uint16_t socketToPort ( union ncclSocketAddress * addr ) {
struct sockaddr * saddr = & addr -> sa ;
return ntohs ( saddr -> sa_family == AF_INET ? addr -> sin . sin_port : addr -> sin6 . sin6_port );
}
/* Allow the user to force the IPv4/IPv6 interface selection */
static int envSocketFamily ( void ) {
int family = - 1 ; // Family selection is not forced, will use first one found
char * env = getenv ( "NCCL_SOCKET_FAMILY" );
if ( env == NULL )
return family ;
INFO ( NCCL_ENV , "NCCL_SOCKET_FAMILY set by environment to %s" , env );
if ( strcmp ( env , "AF_INET" ) == 0 )
family = AF_INET ; // IPv4
else if ( strcmp ( env , "AF_INET6" ) == 0 )
family = AF_INET6 ; // IPv6
return family ;
}
static int findInterfaces ( const char * prefixList , char * names , union ncclSocketAddress * addrs , int sock_family , int maxIfNameSize , int maxIfs ) {
#ifdef ENABLE_TRACE
char line [ SOCKET_NAME_MAXLEN + 1 ];
#endif
struct netIf userIfs [ MAX_IFS ];
bool searchNot = prefixList && prefixList [ 0 ] == '^' ;
if ( searchNot ) prefixList ++ ;
bool searchExact = prefixList && prefixList [ 0 ] == '=' ;
if ( searchExact ) prefixList ++ ;
int nUserIfs = parseStringList ( prefixList , userIfs , MAX_IFS );
int found = 0 ;
struct ifaddrs * interfaces , * interface ;
getifaddrs ( & interfaces );
for ( interface = interfaces ; interface && found < maxIfs ; interface = interface -> ifa_next ) {
if ( interface -> ifa_addr == NULL ) continue ;
/* We only support IPv4 & IPv6 */
int family = interface -> ifa_addr -> sa_family ;
if ( family != AF_INET && family != AF_INET6 )
continue ;
TRACE ( NCCL_INIT | NCCL_NET , "Found interface %s:%s" , interface -> ifa_name , ncclSocketToString (( union ncclSocketAddress * ) interface -> ifa_addr , line ));
/* Allow the caller to force the socket family type */
if ( sock_family != - 1 && family != sock_family )
continue ;
/* We also need to skip IPv6 loopback interfaces */
if ( family == AF_INET6 ) {
struct sockaddr_in6 * sa = ( struct sockaddr_in6 * )( interface -> ifa_addr );
if ( IN6_IS_ADDR_LOOPBACK ( & sa -> sin6_addr )) continue ;
}
// check against user specified interfaces
if ( ! ( matchIfList ( interface -> ifa_name , - 1 , userIfs , nUserIfs , searchExact ) ^ searchNot )) {
continue ;
}
// Check that this interface has not already been saved
// getifaddrs() normal order appears to be; IPv4, IPv6 Global, IPv6 Link
bool duplicate = false ;
for ( int i = 0 ; i < found ; i ++ ) {
if ( strcmp ( interface -> ifa_name , names + i * maxIfNameSize ) == 0 ) { duplicate = true ; break ; }
}
if ( ! duplicate ) {
// Store the interface name
strncpy ( names + found * maxIfNameSize , interface -> ifa_name , maxIfNameSize );
// Store the IP address
int salen = ( family == AF_INET ) ? sizeof ( struct sockaddr_in ) : sizeof ( struct sockaddr_in6 );
memcpy ( addrs + found , interface -> ifa_addr , salen );
found ++ ;
}
}
freeifaddrs ( interfaces );
return found ;
}
static bool matchSubnet ( struct ifaddrs local_if , union ncclSocketAddress * remote ) {
/* Check family first */
int family = local_if . ifa_addr -> sa_family ;
if ( family != remote -> sa . sa_family ) {
return false ;
}
if ( family == AF_INET ) {
struct sockaddr_in * local_addr = ( struct sockaddr_in * )( local_if . ifa_addr );
struct sockaddr_in * mask = ( struct sockaddr_in * )( local_if . ifa_netmask );
struct sockaddr_in & remote_addr = remote -> sin ;
struct in_addr local_subnet , remote_subnet ;
local_subnet . s_addr = local_addr -> sin_addr . s_addr & mask -> sin_addr . s_addr ;
remote_subnet . s_addr = remote_addr . sin_addr . s_addr & mask -> sin_addr . s_addr ;
return ( local_subnet . s_addr ^ remote_subnet . s_addr ) ? false : true ;
} else if ( family == AF_INET6 ) {
struct sockaddr_in6 * local_addr = ( struct sockaddr_in6 * )( local_if . ifa_addr );
struct sockaddr_in6 * mask = ( struct sockaddr_in6 * )( local_if . ifa_netmask );
struct sockaddr_in6 & remote_addr = remote -> sin6 ;
struct in6_addr & local_in6 = local_addr -> sin6_addr ;
struct in6_addr & mask_in6 = mask -> sin6_addr ;
struct in6_addr & remote_in6 = remote_addr . sin6_addr ;
bool same = true ;
int len = 16 ; //IPv6 address is 16 unsigned char
for ( int c = 0 ; c < len ; c ++ ) { //Network byte order is big-endian
char c1 = local_in6 . s6_addr [ c ] & mask_in6 . s6_addr [ c ];
char c2 = remote_in6 . s6_addr [ c ] & mask_in6 . s6_addr [ c ];
if ( c1 ^ c2 ) {
same = false ;
break ;
}
}
// At last, we need to compare scope id
// Two Link-type addresses can have the same subnet address even though they are not in the same scope
// For Global type, this field is 0, so a comparison wouldn't matter
same &= ( local_addr -> sin6_scope_id == remote_addr . sin6_scope_id );
return same ;
} else {
WARN ( "Net : Unsupported address family type" );
return false ;
}
}
int ncclFindInterfaceMatchSubnet ( char * ifNames , union ncclSocketAddress * localAddrs , union ncclSocketAddress * remoteAddr , int ifNameMaxSize , int maxIfs ) {
#ifdef ENABLE_TRACE
char line [ SOCKET_NAME_MAXLEN + 1 ];
#endif
char line_a [ SOCKET_NAME_MAXLEN + 1 ];
int found = 0 ;
struct ifaddrs * interfaces , * interface ;
getifaddrs ( & interfaces );
for ( interface = interfaces ; interface && ! found ; interface = interface -> ifa_next ) {
if ( interface -> ifa_addr == NULL ) continue ;
/* We only support IPv4 & IPv6 */
int family = interface -> ifa_addr -> sa_family ;
if ( family != AF_INET && family != AF_INET6 )
continue ;
// check against user specified interfaces
if ( ! matchSubnet ( * interface , remoteAddr )) {
continue ;
}
// Store the local IP address
int salen = ( family == AF_INET ) ? sizeof ( struct sockaddr_in ) : sizeof ( struct sockaddr_in6 );
memcpy ( localAddrs + found , interface -> ifa_addr , salen );
// Store the interface name
strncpy ( ifNames + found * ifNameMaxSize , interface -> ifa_name , ifNameMaxSize );
TRACE ( NCCL_INIT | NCCL_NET , "NET : Found interface %s:%s in the same subnet as remote address %s" , interface -> ifa_name , ncclSocketToString ( localAddrs + found , line ), ncclSocketToString ( remoteAddr , line_a ));
found ++ ;
if ( found == maxIfs ) break ;
}
if ( found == 0 ) {
WARN ( "Net : No interface found in the same subnet as remote address %s" , ncclSocketToString ( remoteAddr , line_a ));
}
freeifaddrs ( interfaces );
return found ;
}
ncclResult_t ncclGetSocketAddrFromString ( union ncclSocketAddress * ua , const char * ip_port_pair ) {
if ( ! ( ip_port_pair && strlen ( ip_port_pair ) > 1 )) {
WARN ( "Net : string is null" );
return ncclInvalidArgument ;
}
bool ipv6 = ip_port_pair [ 0 ] == '[' ;
/* Construct the sockaddress structure */
if ( ! ipv6 ) {
struct netIf ni ;
// parse <ip_or_hostname>:<port> string, expect one pair
if ( parseStringList ( ip_port_pair , & ni , 1 ) != 1 ) {
WARN ( "Net : No valid <IPv4_or_hostname>:<port> pair found" );
return ncclInvalidArgument ;
}
struct addrinfo hints , * p ;
int rv ;
memset ( & hints , 0 , sizeof ( hints ));
hints . ai_family = AF_UNSPEC ;
hints . ai_socktype = SOCK_STREAM ;
if ( ( rv = getaddrinfo ( ni . prefix , NULL , & hints , & p )) != 0 ) {
WARN ( "Net : error encountered when getting address info : %s" , gai_strerror ( rv ));
return ncclInvalidArgument ;
}
// use the first
if ( p -> ai_family == AF_INET ) {
struct sockaddr_in & sin = ua -> sin ;
memcpy ( & sin , p -> ai_addr , sizeof ( struct sockaddr_in ));
sin . sin_family = AF_INET ; // IPv4
//inet_pton(AF_INET, ni.prefix, &(sin.sin_addr)); // IP address
sin . sin_port = htons ( ni . port ); // port
} else if ( p -> ai_family == AF_INET6 ) {
struct sockaddr_in6 & sin6 = ua -> sin6 ;
memcpy ( & sin6 , p -> ai_addr , sizeof ( struct sockaddr_in6 ));
sin6 . sin6_family = AF_INET6 ; // IPv6
sin6 . sin6_port = htons ( ni . port ); // port
sin6 . sin6_flowinfo = 0 ; // needed by IPv6, but possibly obsolete
sin6 . sin6_scope_id = 0 ; // should be global scope, set to 0
} else {
WARN ( "Net : unsupported IP family" );
return ncclInvalidArgument ;
}
freeaddrinfo ( p ); // all done with this structure
} else {
int i , j = - 1 , len = strlen ( ip_port_pair );
for ( i = 1 ; i < len ; i ++ ) {
if ( ip_port_pair [ i ] == '%' ) j = i ;
if ( ip_port_pair [ i ] == ']' ) break ;
}
if ( i == len ) {
WARN ( "Net : No valid [IPv6]:port pair found" );
return ncclInvalidArgument ;
}
bool global_scope = ( j == - 1 ? true : false ); // If no % found, global scope; otherwise, link scope
char ip_str [ NI_MAXHOST ], port_str [ NI_MAXSERV ], if_name [ IFNAMSIZ ];
memset ( ip_str , '\0' , sizeof ( ip_str ));
memset ( port_str , '\0' , sizeof ( port_str ));
memset ( if_name , '\0' , sizeof ( if_name ));
strncpy ( ip_str , ip_port_pair + 1 , global_scope ? i - 1 : j - 1 );
strncpy ( port_str , ip_port_pair + i + 2 , len - i - 1 );
int port = atoi ( port_str );
if ( ! global_scope ) strncpy ( if_name , ip_port_pair + j + 1 , i - j - 1 ); // If not global scope, we need the intf name
struct sockaddr_in6 & sin6 = ua -> sin6 ;
sin6 . sin6_family = AF_INET6 ; // IPv6
inet_pton ( AF_INET6 , ip_str , & ( sin6 . sin6_addr )); // IP address
sin6 . sin6_port = htons ( port ); // port
sin6 . sin6_flowinfo = 0 ; // needed by IPv6, but possibly obsolete
sin6 . sin6_scope_id = global_scope ? 0 : if_nametoindex ( if_name ); // 0 if global scope; intf index if link scope
}
return ncclSuccess ;
}
int ncclFindInterfaces ( char * ifNames , union ncclSocketAddress * ifAddrs , int ifNameMaxSize , int maxIfs ) {
static int shownIfName = 0 ;
int nIfs = 0 ;
// Allow user to force the INET socket family selection
int sock_family = envSocketFamily ();
// User specified interface
char * env = getenv ( "NCCL_SOCKET_IFNAME" );
if ( env && strlen ( env ) > 1 ) {
INFO ( NCCL_ENV , "NCCL_SOCKET_IFNAME set by environment to %s" , env );
// Specified by user : find or fail
if ( shownIfName ++ == 0 ) INFO ( NCCL_NET , "NCCL_SOCKET_IFNAME set to %s" , env );
nIfs = findInterfaces ( env , ifNames , ifAddrs , sock_family , ifNameMaxSize , maxIfs );
} else {
// Try to automatically pick the right one
// Start with IB
nIfs = findInterfaces ( "ib" , ifNames , ifAddrs , sock_family , ifNameMaxSize , maxIfs );
// else see if we can get some hint from COMM ID
if ( nIfs == 0 ) {
char * commId = getenv ( "NCCL_COMM_ID" );
if ( commId && strlen ( commId ) > 1 ) {
INFO ( NCCL_ENV , "NCCL_COMM_ID set by environment to %s" , commId );
// Try to find interface that is in the same subnet as the IP in comm id
union ncclSocketAddress idAddr ;
ncclGetSocketAddrFromString ( & idAddr , commId );
nIfs = ncclFindInterfaceMatchSubnet ( ifNames , ifAddrs , & idAddr , ifNameMaxSize , maxIfs );
}
}
// Then look for anything else (but not docker or lo)
if ( nIfs == 0 ) nIfs = findInterfaces ( "^docker,lo" , ifNames , ifAddrs , sock_family , ifNameMaxSize , maxIfs );
// Finally look for docker, then lo.
if ( nIfs == 0 ) nIfs = findInterfaces ( "docker" , ifNames , ifAddrs , sock_family , ifNameMaxSize , maxIfs );
if ( nIfs == 0 ) nIfs = findInterfaces ( "lo" , ifNames , ifAddrs , sock_family , ifNameMaxSize , maxIfs );
}
return nIfs ;
}
ncclResult_t ncclSocketListen ( struct ncclSocket * sock ) {
/* IPv4/IPv6 support */
int family = sock -> addr . sa . sa_family ;
int salen = ( family == AF_INET ) ? sizeof ( struct sockaddr_in ) : sizeof ( struct sockaddr_in6 );
int flags ;
/* Create socket and bind it to a port */
int fd = socket ( family , SOCK_STREAM , 0 );
if ( fd == - 1 ) {
WARN ( "Net : Socket creation failed : %s" , strerror ( errno ));
return ncclSystemError ;
}
if ( socketToPort ( & sock -> addr )) {
// Port is forced by env. Make sure we get the port.
int opt = 1 ;
#if defined(SO_REUSEPORT)
SYSCHECK ( setsockopt ( fd , SOL_SOCKET , SO_REUSEADDR | SO_REUSEPORT , & opt , sizeof ( opt )), "setsockopt" );
#else
SYSCHECK ( setsockopt ( fd , SOL_SOCKET , SO_REUSEADDR , & opt , sizeof ( opt )), "setsockopt" );
#endif
}
/* make all new sockets non-blocking */
EQCHECK ( flags = fcntl ( fd , F_GETFL ), - 1 );
SYSCHECK ( fcntl ( fd , F_SETFL , flags | O_NONBLOCK ), "fcntl" );
// addr port should be 0 (Any port)
SYSCHECK ( bind ( fd , & sock -> addr . sa , salen ), "bind" );
/* Get the assigned Port */
socklen_t size = salen ;
SYSCHECK ( getsockname ( fd , & sock -> addr . sa , & size ), "getsockname" );
#ifdef ENABLE_TRACE
char line [ SOCKET_NAME_MAXLEN + 1 ];
TRACE ( NCCL_INIT | NCCL_NET , "Listening on socket %s" , ncclSocketToString ( & sock -> addr , line ));
#endif
/* Put the socket in listen mode
* NB: The backlog will be silently truncated to the value in /proc/sys/net/core/somaxconn
*/
SYSCHECK ( listen ( fd , 16384 ), "listen" );
sock -> fd = fd ;
return ncclSuccess ;
}
static ncclResult_t getFdState ( int fd , enum ncclSocketState * state ) {
struct pollfd pfd ;
int timeout = 1 , ret ;
socklen_t rlen = sizeof ( int );
memset ( & pfd , 0 , sizeof ( struct pollfd ));
pfd . fd = fd ;
pfd . events = POLLOUT ;
SYSCHECK ( ret = poll ( & pfd , 1 , timeout ), "poll" );
if ( ret == 0 ) {
ret = EINPROGRESS ;
} else {
/* check socket status */
EQCHECK ( ret == 1 && ( pfd . revents & POLLOUT ), 0 );
SYSCHECK ( getsockopt ( fd , SOL_SOCKET , SO_ERROR , ( void * ) & ret , & rlen ), "getsockopt" );
}
if ( ret == EINPROGRESS )
* state = ncclSocketConnecting ;
else if ( ret == 0 )
* state = ncclSocketConnected ;
else
* state = ncclSocketError ;
return ncclSuccess ;
}
ncclResult_t ncclGetSocketState ( struct ncclSocket * sock , enum ncclSocketState * state ) {
NCCLCHECK ( getFdState ( sock -> fd , state ));
sock -> state = * state ;
return ncclSuccess ;
}
ncclResult_t ncclSocketConnect ( struct ncclSocket * sock ) {
char line [ SOCKET_NAME_MAXLEN + 1 ];
/* IPv4/IPv6 support */
int family = sock -> addr . sa . sa_family ;
if ( family != AF_INET && family != AF_INET6 ) {
WARN ( "Net : connecting to address %s with family %d is neither AF_INET(%d) nor AF_INET6(%d)" ,
ncclSocketToString ( & sock -> addr , line ), family , AF_INET , AF_INET6 );
return ncclInternalError ;
}
int salen = ( family == AF_INET ) ? sizeof ( struct sockaddr_in ) : sizeof ( struct sockaddr_in6 );
int flags ;
/* Connect to a hostname / port */
int fd = socket ( family , SOCK_STREAM , 0 );
if ( fd == - 1 ) {
WARN ( "Net : Socket creation failed : %s" , strerror ( errno ));
return ncclSystemError ;
}
const int one = 1 ;
SYSCHECK ( setsockopt ( fd , IPPROTO_TCP , TCP_NODELAY , ( char * ) & one , sizeof ( int )), "setsockopt" );
/* support non-blocking socket; by default, the socket is non-blocking */
EQCHECK ( flags = fcntl ( fd , F_GETFL ), - 1 );
SYSCHECK ( fcntl ( fd , F_SETFL , flags | O_NONBLOCK ), "fcntl" );
/* const int bufsize = 128*1024;
SYSCHECK(setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char*)&bufsize, sizeof(int)), "setsockopt");
SYSCHECK(setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char*)&bufsize, sizeof(int)), "setsockopt");*/
TRACE ( NCCL_INIT | NCCL_NET , "Connecting to socket %s" , ncclSocketToString ( & sock -> addr , line ));
int ret ;
int timedout_retries = 0 ;
int refused_retries = 0 ;
retry :
/* async connect; abort when error happens and abortFlag is present. */
ret = connect ( fd , & sock -> addr . sa , salen );
if ( errno == EAGAIN || ( errno == ECONNREFUSED && ++ refused_retries < RETRY_REFUSED_TIMES ) ||
( errno == ETIMEDOUT && ++ timedout_retries < RETRY_TIMEDOUT_TIMES )) {
if ( refused_retries % 1000 == 0 ) INFO ( NCCL_ALL , "Call to connect returned %s, retrying" , strerror ( errno ));
usleep ( SLEEP_INT );
goto retry ;
} else if ( errno == EINPROGRESS && ! sock -> asyncFlag ) {
enum ncclSocketState state ;
do {
if ( sock -> abortFlag ) NEQCHECK ( * sock -> abortFlag , 0 );
NCCLCHECK ( getFdState ( fd , & state ));
} while ( state == ncclSocketConnecting );
EQCHECK ( state , ncclSocketError );
ret = 0 ;
}
if ( ret == 0 || ( errno == EINPROGRESS && sock -> asyncFlag )) {
sock -> fd = fd ;
return ncclSuccess ;
}
WARN ( "Net : Connect to %s failed : %s" , ncclSocketToString ( & sock -> addr , line ), strerror ( errno ));
return ncclSystemError ;
}
ncclResult_t ncclSocketAccept ( struct ncclSocket * sock , struct ncclSocket * listenSocket ) {
socklen_t socklen = sizeof ( union ncclSocketAddress );
int tmpFd = sock -> fd = - 1 ;
do {
if ( listenSocket -> abortFlag ) NEQCHECK ( * listenSocket -> abortFlag , 0 );
tmpFd = accept ( listenSocket -> fd , & sock -> addr . sa , & socklen );
} while (( errno == EAGAIN || errno == EWOULDBLOCK ) && tmpFd == - 1 && ! listenSocket -> asyncFlag );
if ( ! listenSocket -> asyncFlag ) {
EQCHECK ( tmpFd , - 1 );
} else if ( tmpFd == - 1 && errno != EAGAIN && errno != EWOULDBLOCK ) {
return ncclSystemError ;
}
sock -> fd = tmpFd ;
return ncclSuccess ;
}
ncclResult_t ncclSocketInit ( struct ncclSocket * sock , union ncclSocketAddress * addr , volatile uint32_t * abortFlag , int asyncFlag ) {
if ( sock == NULL )
return ncclSuccess ;
sock -> fd = - 1 ;
if ( addr ) {
memcpy ( & sock -> addr , addr , sizeof ( union ncclSocketAddress ));
} else {
memset ( & sock -> addr , 0 , sizeof ( union ncclSocketAddress ));
}
sock -> abortFlag = abortFlag ;
sock -> asyncFlag = asyncFlag ;
sock -> state = ncclSocketStateNum ;
return ncclSuccess ;
}
static ncclResult_t ncclSocketProgressOpt ( int op , struct ncclSocket * sock , void * ptr , int size , int * offset , int block , int * closed ) {
int bytes = 0 ;
* closed = 0 ;
char * data = ( char * ) ptr ;
char line [ SOCKET_NAME_MAXLEN + 1 ];
do {
if ( op == NCCL_SOCKET_RECV ) bytes = recv ( sock -> fd , data + ( * offset ), size - ( * offset ), block ? 0 : MSG_DONTWAIT );
if ( op == NCCL_SOCKET_SEND ) bytes = send ( sock -> fd , data + ( * offset ), size - ( * offset ), block ? 0 : MSG_DONTWAIT );
if ( op == NCCL_SOCKET_RECV && bytes == 0 ) {
* closed = 1 ;
return ncclSuccess ;
}
if ( bytes == - 1 ) {
if ( errno != EINTR && errno != EWOULDBLOCK && errno != EAGAIN ) {
WARN ( "Net : Call to recv from %s failed : %s" , ncclSocketToString ( & sock -> addr , line ), strerror ( errno ));
return ncclSystemError ;
} else {
bytes = 0 ;
}
}
( * offset ) += bytes ;
if ( sock -> abortFlag && * sock -> abortFlag != 0 ) {
INFO ( NCCL_NET , "Socket progress: abort called" );
return ncclSystemError ;
}
} while ( bytes > 0 && ( * offset ) < size );
return ncclSuccess ;
}
ncclResult_t ncclSocketProgress ( int op , struct ncclSocket * sock , void * ptr , int size , int * offset ) {
int closed ;
NCCLCHECK ( ncclSocketProgressOpt ( op , sock , ptr , size , offset , 0 , & closed ));
if ( closed ) {
char line [ SOCKET_NAME_MAXLEN + 1 ];
2022-03-30 02:25:49 -07:00
WARN ( "Net : Connection closed by remote peer %s" , ncclSocketToString ( & sock -> addr , line , 0 ));
2022-01-07 06:39:55 -08:00
return ncclSystemError ;
}
return ncclSuccess ;
}
ncclResult_t ncclSocketWait ( int op , struct ncclSocket * sock , void * ptr , int size , int * offset ) {
while ( * offset < size )
NCCLCHECK ( ncclSocketProgress ( op , sock , ptr , size , offset ));
return ncclSuccess ;
}
ncclResult_t ncclSocketSend ( struct ncclSocket * sock , void * ptr , int size ) {
int offset = 0 ;
NCCLCHECK ( ncclSocketWait ( NCCL_SOCKET_SEND , sock , ptr , size , & offset ));
return ncclSuccess ;
}
ncclResult_t ncclSocketRecv ( struct ncclSocket * sock , void * ptr , int size ) {
int offset = 0 ;
NCCLCHECK ( ncclSocketWait ( NCCL_SOCKET_RECV , sock , ptr , size , & offset ));
return ncclSuccess ;
}
// Receive or detect connection closed
ncclResult_t ncclSocketTryRecv ( struct ncclSocket * sock , void * ptr , int size , int * closed ) {
int offset = 0 ;
* closed = 0 ;
while ( offset < size ) {
NCCLCHECK ( ncclSocketProgressOpt ( NCCL_SOCKET_RECV , sock , ptr , size , & offset , 0 , closed ));
if ( * closed ) return ncclSuccess ;
}
return ncclSuccess ;
}