2019-12-27 21:52:45 +00:00
# include "cwCommon.h"
# include "cwLog.h"
# include "cwCommonImpl.h"
# include "cwMem.h"
2020-02-01 15:12:51 +00:00
# include <sys/socket.h>
# include <sys/ioctl.h>
# include <net/if.h>
2019-12-27 21:52:45 +00:00
# include <netinet/in.h>
# include <arpa/inet.h>
# include <fcntl.h>
# include <unistd.h> // close
# include "cwTcpSocket.h"
# define cwSOCKET_SYS_ERR (-1)
# define cwSOCKET_NULL_SOCK (-1)
# ifndef HOST_NAME_MAX
# define HOST_NAME_MAX _POSIX_HOST_NAME_MAX
# endif
namespace cw
{
namespace net
{
namespace socket
{
enum
{
kIsConnectedFl = 0x01 ,
kIsBlockingFl = 0x02
} ;
typedef struct socket_str
{
int sockH ;
2020-01-27 22:52:53 +00:00
int fdH ;
2020-02-12 18:25:13 +00:00
unsigned createFlags ;
2019-12-27 21:52:45 +00:00
unsigned flags ;
struct sockaddr_in sockaddr ;
char ntopBuf [ INET_ADDRSTRLEN + 1 ] ; // use INET6_ADDRSTRLEN for IPv6
char hnameBuf [ HOST_NAME_MAX + 1 ] ;
} socket_t ;
2020-03-17 02:52:21 +00:00
inline socket_t * _handleToPtr ( handle_t h )
{ return handleToPtr < handle_t , socket_t > ( h ) ; }
2019-12-27 21:52:45 +00:00
rc_t _destroy ( socket_t * p )
{
2020-01-27 22:52:53 +00:00
// close the fdH
if ( p - > fdH ! = cwSOCKET_NULL_SOCK )
{
errno = 0 ;
if ( : : close ( p - > fdH ) ! = 0 )
cwLogSysError ( kOpFailRC , errno , " The socket fd close failed. " ) ;
p - > fdH = cwSOCKET_NULL_SOCK ;
}
2019-12-27 21:52:45 +00:00
// close the socket
if ( p - > sockH ! = cwSOCKET_NULL_SOCK )
{
errno = 0 ;
if ( : : close ( p - > sockH ) ! = 0 )
cwLogSysError ( kOpFailRC , errno , " The socket close failed. " ) ;
2020-01-27 22:52:53 +00:00
2019-12-27 21:52:45 +00:00
p - > sockH = cwSOCKET_NULL_SOCK ;
}
2019-12-28 02:51:28 +00:00
mem : : release ( p ) ;
2019-12-27 21:52:45 +00:00
return kOkRC ;
}
2020-03-17 02:52:21 +00:00
rc_t _initAddr ( const char * addrStr , portNumber_t portNumber , struct sockaddr_in * retAddrPtr )
2019-12-27 21:52:45 +00:00
{
memset ( retAddrPtr , 0 , sizeof ( struct sockaddr_in ) ) ;
2020-01-27 22:52:53 +00:00
//if( portNumber == kInvalidPortNumber )
// return cwLogError(kInvalidArgRC,"The port number %i cannot be used.",kInvalidPortNumber);
2019-12-27 21:52:45 +00:00
if ( addrStr = = NULL )
retAddrPtr - > sin_addr . s_addr = htonl ( INADDR_ANY ) ;
else
{
errno = 0 ;
if ( inet_pton ( AF_INET , addrStr , & retAddrPtr - > sin_addr ) = = 0 )
return cwLogSysError ( kOpFailRC , errno , " The network address string '%s' could not be converted to a netword address structure. " , cwStringNullGuard ( addrStr ) ) ;
}
//retAddrPtr->sin_len = sizeof(struct sockaddr_in);
retAddrPtr - > sin_family = AF_INET ;
2020-01-27 22:52:53 +00:00
if ( portNumber ! = kInvalidPortNumber )
retAddrPtr - > sin_port = htons ( portNumber ) ;
2019-12-27 21:52:45 +00:00
return kOkRC ;
}
rc_t _connect ( socket_t * p , const char * remoteAddr , portNumber_t remotePort )
{
struct sockaddr_in addr ;
rc_t rc ;
// create the remote address
2020-03-17 02:52:21 +00:00
if ( ( rc = _initAddr ( remoteAddr , remotePort , & addr ) ) ! = kOkRC )
2019-12-27 21:52:45 +00:00
return rc ;
errno = 0 ;
// ... and connect this socket to the remote address/port
if ( connect ( p - > sockH , ( struct sockaddr * ) & addr , sizeof ( addr ) ) = = cwSOCKET_SYS_ERR )
return cwLogSysError ( kOpFailRC , errno , " Socket connect failed. " ) ;
p - > flags = cwSetFlag ( p - > flags , kIsConnectedFl ) ;
return rc ;
}
2020-01-27 22:52:53 +00:00
rc_t _setTimeOutMs ( socket_t * p , unsigned timeOutMs )
{
rc_t rc = kOkRC ;
struct timeval timeOut ;
// set the socket time out
timeOut . tv_sec = timeOutMs / 1000 ;
timeOut . tv_usec = ( timeOutMs - ( timeOut . tv_sec * 1000 ) ) * 1000 ;
if ( setsockopt ( p - > sockH , SOL_SOCKET , SO_RCVTIMEO , & timeOut , sizeof ( timeOut ) ) = = cwSOCKET_SYS_ERR )
{
rc = cwLogSysError ( kOpFailRC , errno , " Attempt to set the socket timeout failed. " ) ;
goto errLabel ;
}
errLabel :
return rc ;
2020-02-12 18:25:13 +00:00
}
rc_t _get_info ( int sockH , unsigned char outBuf [ 6 ] , struct sockaddr_in * addr , const char * interfaceName )
{
cw : : rc_t rc = kOkRC ;
struct ifreq ifr ;
struct ifconf ifc ;
char buf [ 1024 ] ;
ifc . ifc_len = sizeof ( buf ) ;
ifc . ifc_buf = buf ;
if ( ioctl ( sockH , SIOCGIFCONF , & ifc ) = = - 1 )
{
rc = cwLogSysError ( kOpFailRC , errno , " ioctl(SIOCGIFCONF) failed. " ) ;
return rc ;
}
struct ifreq * it = ifc . ifc_req ;
const struct ifreq * const end = it + ( ifc . ifc_len / sizeof ( struct ifreq ) ) ;
for ( ; it ! = end ; + + it )
{
if ( strcmp ( it - > ifr_name , interfaceName ) = = 0 )
{
strcpy ( ifr . ifr_name , it - > ifr_name ) ;
if ( ioctl ( sockH , SIOCGIFFLAGS , & ifr ) ! = 0 )
{
rc = cwLogSysError ( kOpFailRC , errno , " ioctl(SIOCGIFCONF) failed. " ) ;
}
else
{
if ( ! ( ifr . ifr_flags & IFF_LOOPBACK ) )
{
// don't count loopback
if ( ioctl ( sockH , SIOCGIFHWADDR , & ifr ) = = 0 )
{
memcpy ( outBuf , ifr . ifr_hwaddr . sa_data , 6 ) ;
if ( addr ! = nullptr & & ioctl ( sockH , SIOCGIFADDR , & ifr ) = = 0 )
{
addr - > sin_addr = ( ( struct sockaddr_in * ) & ifr . ifr_addr ) - > sin_addr ;
}
return kOkRC ;
}
}
}
}
}
return cwLogError ( kInvalidArgRC , " The network interface information for '%s' could not be found. " , interfaceName ) ;
}
2019-12-27 21:52:45 +00:00
}
}
}
cw : : rc_t cw : : net : : socket : : create (
handle_t & hRef ,
portNumber_t port ,
unsigned flags ,
unsigned timeOutMs ,
const char * remoteAddr ,
2020-02-12 18:25:13 +00:00
portNumber_t remotePort ,
const char * localAddr )
2019-12-27 21:52:45 +00:00
{
rc_t rc ;
if ( ( rc = destroy ( hRef ) ) ! = kOkRC )
return rc ;
2019-12-28 02:51:28 +00:00
socket_t * p = mem : : allocZ < socket_t > ( ) ;
2020-02-12 18:25:13 +00:00
p - > sockH = cwSOCKET_NULL_SOCK ;
p - > fdH = cwSOCKET_NULL_SOCK ;
p - > createFlags = flags ;
2020-01-27 22:52:53 +00:00
int type = cwIsFlag ( flags , kStreamFl ) ? SOCK_STREAM : SOCK_DGRAM ;
int protocol = cwIsFlag ( flags , kTcpFl ) ? 0 : IPPROTO_UDP ;
2019-12-27 21:52:45 +00:00
// get a handle to the socket
2020-01-27 22:52:53 +00:00
if ( ( p - > sockH = : : socket ( AF_INET , type , protocol ) ) = = cwSOCKET_SYS_ERR )
2019-12-27 21:52:45 +00:00
return cwLogSysError ( kOpFailRC , errno , " Socket create failed. " ) ;
// if this socket should block
2020-01-27 22:52:53 +00:00
if ( cwIsFlag ( flags , kBlockingFl ) )
2019-12-27 21:52:45 +00:00
{
2020-01-27 22:52:53 +00:00
if ( timeOutMs > 0 )
2019-12-27 21:52:45 +00:00
{
2020-01-27 22:52:53 +00:00
_setTimeOutMs ( p , timeOutMs ) ;
2019-12-27 21:52:45 +00:00
}
2020-01-27 22:52:53 +00:00
2019-12-27 21:52:45 +00:00
p - > flags = cwSetFlag ( p - > flags , kIsBlockingFl ) ;
2020-01-27 22:52:53 +00:00
2019-12-27 21:52:45 +00:00
}
else
{
int opts ;
// get the socket options flags
if ( ( opts = fcntl ( p - > sockH , F_GETFL ) ) < 0 )
{
rc = cwLogSysError ( kOpFailRC , errno , " Attempt to get the socket options flags failed. " ) ;
goto errLabel ;
}
opts = ( opts | O_NONBLOCK ) ;
// set the socket options flags
if ( fcntl ( p - > sockH , F_SETFL , opts ) < 0 )
{
rc = cwLogSysError ( kOpFailRC , errno , " Attempt to set the socket to non-blocking failed. " ) ;
goto errLabel ;
}
}
2020-01-27 22:52:53 +00:00
if ( cwIsFlag ( flags , kReuseAddrFl ) )
{
unsigned int reuseaddr = 1 ;
if ( setsockopt ( p - > sockH , SOL_SOCKET , SO_REUSEADDR , ( const char * ) & reuseaddr , sizeof ( reuseaddr ) ) = = cwSOCKET_SYS_ERR )
{
rc = cwLogSysError ( kOpFailRC , errno , " Attempt to set the socket 'reuse address' attribute failed. " ) ;
goto errLabel ;
}
}
# ifdef SO_REUSEPORT
if ( cwIsFlag ( flags , kReusePortFl ) )
{
unsigned int reuseaddr = 1 ;
if ( setsockopt ( p - > sockH , SOL_SOCKET , SO_REUSEPORT , ( const char * ) & reuseaddr , sizeof ( reuseaddr ) ) = = cwSOCKET_SYS_ERR )
{
rc = cwLogSysError ( kOpFailRC , errno , " Attempt to set the socket 'reuse port' attribute failed. " ) ;
goto errLabel ;
}
}
# endif
if ( cwIsFlag ( flags , kMultiCastTtlFl ) )
{
unsigned char ttl = 1 ;
if ( setsockopt ( p - > sockH , IPPROTO_IP , IP_MULTICAST_TTL , ( const char * ) & ttl , sizeof ( ttl ) ) = = cwSOCKET_SYS_ERR )
{
rc = cwLogSysError ( kOpFailRC , errno , " Attempt to set the socket 'multicast TTL' attribute failed. " ) ;
goto errLabel ;
}
}
if ( cwIsFlag ( flags , kMultiCastLoopFl ) )
{
unsigned char loopback = 1 ;
if ( setsockopt ( p - > sockH , IPPROTO_IP , IP_MULTICAST_LOOP , ( const char * ) & loopback , sizeof ( loopback ) ) = = cwSOCKET_SYS_ERR )
{
rc = cwLogSysError ( kOpFailRC , errno , " Attempt to set the socket 'reuse port' attribute failed. " ) ;
goto errLabel ;
}
}
2019-12-27 21:52:45 +00:00
// if broadcast option was requested.
if ( cwIsFlag ( flags , kBroadcastFl ) )
{
2020-01-27 22:52:53 +00:00
int bcastFl = 1 ;
2019-12-27 21:52:45 +00:00
if ( setsockopt ( p - > sockH , SOL_SOCKET , SO_BROADCAST , & bcastFl , sizeof ( bcastFl ) ) = = cwSOCKET_SYS_ERR )
{
rc = cwLogSysError ( kOpFailRC , errno , " Attempt to set the socket broadcast attribute failed. " ) ;
goto errLabel ;
}
}
2020-01-27 22:52:53 +00:00
2020-02-12 18:25:13 +00:00
// create the 32 bit local address
2020-03-17 02:52:21 +00:00
if ( ( rc = _initAddr ( localAddr , port , & p - > sockaddr ) ) ! = kOkRC )
2020-01-27 22:52:53 +00:00
goto errLabel ;
2020-02-12 18:25:13 +00:00
2020-01-27 22:52:53 +00:00
// bind the socket to a local address/port
if ( ( bind ( p - > sockH , ( struct sockaddr * ) & p - > sockaddr , sizeof ( p - > sockaddr ) ) ) = = cwSOCKET_SYS_ERR )
{
rc = cwLogSysError ( kOpFailRC , errno , " Socket bind failed. " ) ;
goto errLabel ;
}
2020-02-12 18:25:13 +00:00
// get the local address as a string
if ( ( rc = addrToString ( & p - > sockaddr , p - > ntopBuf , sizeof ( p - > ntopBuf ) ) ) ! = kOkRC )
goto errLabel ;
2020-01-27 22:52:53 +00:00
// if a remote addr was given connect this socket to it
if ( remoteAddr ! = NULL )
if ( ( rc = _connect ( p , remoteAddr , remotePort ) ) ! = kOkRC )
goto errLabel ;
2019-12-27 21:52:45 +00:00
2020-01-27 22:52:53 +00:00
// if the socket should be marked for listening
if ( cwIsFlag ( flags , kListenFl ) )
{
if ( : : listen ( p - > sockH , 10 ) ! = 0 )
{
rc = cwLogSysError ( kOpFailRC , errno , " Socket listen() failed. " ) ;
goto errLabel ;
}
}
2019-12-27 21:52:45 +00:00
errLabel :
if ( rc ! = kOkRC )
_destroy ( p ) ;
else
hRef . set ( p ) ;
return rc ;
}
2020-01-27 22:52:53 +00:00
2019-12-27 21:52:45 +00:00
cw : : rc_t cw : : net : : socket : : destroy ( handle_t & hRef )
{
rc_t rc = kOkRC ;
if ( ! hRef . isValid ( ) )
return rc ;
socket_t * p = _handleToPtr ( hRef ) ;
if ( ( rc = _destroy ( p ) ) ! = kOkRC )
return rc ;
hRef . clear ( ) ;
return rc ;
}
2020-02-12 18:25:13 +00:00
unsigned cw : : net : : socket : : flags ( handle_t h )
{
socket_t * p = _handleToPtr ( h ) ;
return p - > createFlags ;
}
2020-01-29 16:42:41 +00:00
cw : : rc_t cw : : net : : socket : : set_multicast_time_to_live ( handle_t h , unsigned seconds )
{
rc_t rc = kOkRC ;
socket_t * p = _handleToPtr ( h ) ;
if ( setsockopt ( p - > sockH , IPPROTO_IP , IP_MULTICAST_TTL , & seconds , sizeof ( seconds ) ) = = cwSOCKET_SYS_ERR )
{
rc = cwLogSysError ( kOpFailRC , errno , " Attempt to set the socket multicast TTLfailed. " ) ;
}
return rc ;
}
2020-01-27 22:52:53 +00:00
cw : : rc_t cw : : net : : socket : : join_multicast_group ( handle_t h , const char * addrStr )
{
rc_t rc = kOkRC ;
socket_t * p = _handleToPtr ( h ) ;
struct ip_mreq req ;
memset ( & req , 0 , sizeof ( req ) ) ;
if ( inet_pton ( AF_INET , addrStr , & req . imr_multiaddr . s_addr ) = = 0 )
{
rc = cwLogSysError ( kOpFailRC , errno , " The network address string '%s' could not be converted to a netword address structure. " , cwStringNullGuard ( addrStr ) ) ;
goto errLabel ;
}
req . imr_interface . s_addr = INADDR_ANY ;
if ( setsockopt ( p - > sockH , IPPROTO_IP , IP_ADD_MEMBERSHIP , ( char * ) & req , sizeof ( req ) ) = = cwSOCKET_SYS_ERR )
{
rc = cwLogSysError ( kOpFailRC , errno , " Attempt to add socket to multicast group on '%s' failed. " , cwStringNullGuard ( addrStr ) ) ;
goto errLabel ;
}
errLabel :
return rc ;
}
cw : : rc_t cw : : net : : socket : : setTimeOutMs ( handle_t h , unsigned timeOutMs )
{
socket_t * p = _handleToPtr ( h ) ;
return _setTimeOutMs ( p , timeOutMs ) ;
}
cw : : rc_t cw : : net : : socket : : accept ( handle_t h )
{
struct sockaddr_storage remoteAddr ; // connector's address information
socklen_t sin_size = sizeof ( remoteAddr ) ;
rc_t rc = kOkRC ;
int fd = cwSOCKET_NULL_SOCK ;
socket_t * p = _handleToPtr ( h ) ;
if ( ( fd = accept ( p - > sockH , ( struct sockaddr * ) & remoteAddr , & sin_size ) ) < 0 )
{
if ( errno = = EAGAIN | | errno = = EWOULDBLOCK )
rc = kTimeOutRC ;
else
{
rc = cwLogSysError ( kOpFailRC , errno , " Socket accept() failed. " ) ;
goto errLabel ;
}
}
else
{
char s [ INET_ADDRSTRLEN + 1 ] ;
addrToString ( ( struct sockaddr_in * ) & remoteAddr , s , INET_ADDRSTRLEN ) ;
if ( p - > fdH ! = cwSOCKET_NULL_SOCK )
{
close ( p - > fdH ) ;
p - > fdH = cwSOCKET_NULL_SOCK ;
}
p - > fdH = fd ;
2020-01-29 16:42:41 +00:00
p - > flags = cwSetFlag ( p - > flags , kIsConnectedFl ) ;
2020-02-12 18:25:13 +00:00
/*
if ( false )
{
struct sockaddr_in addr ;
char aBuf [ INET_ADDRSTRLEN + 1 ] ;
peername ( h , & addr ) ;
addrToString ( & addr , aBuf , INET_ADDRSTRLEN ) ;
printf ( " DNS-SD PEER: %i %s \n " , addr . sin_port , aBuf ) ;
}
*/
cwLogInfo ( " Connect:%s \n " , s ) ;
2020-01-27 22:52:53 +00:00
}
errLabel :
return rc ;
}
2019-12-27 21:52:45 +00:00
cw : : rc_t cw : : net : : socket : : connect ( handle_t h , const char * remoteAddr , portNumber_t remotePort )
{
socket_t * p = _handleToPtr ( h ) ;
return _connect ( p , remoteAddr , remotePort ) ;
}
2020-01-29 16:42:41 +00:00
bool cw : : net : : socket : : isConnected ( handle_t h )
{
socket_t * p = _handleToPtr ( h ) ;
return cwIsFlag ( p - > flags , kIsConnectedFl ) ;
}
2019-12-27 21:52:45 +00:00
cw : : rc_t cw : : net : : socket : : send ( handle_t h , const void * data , unsigned dataByteCnt )
{
socket_t * p = _handleToPtr ( h ) ;
errno = 0 ;
if ( cwIsFlag ( p - > flags , kIsConnectedFl ) = = false )
2020-01-27 22:52:53 +00:00
return cwLogError ( kInvalidOpRC , " socket::send() only works with connected sockets . " ) ;
2019-12-27 21:52:45 +00:00
2020-01-29 16:42:41 +00:00
int fd = p - > fdH ! = cwSOCKET_NULL_SOCK ? p - > fdH : p - > sockH ;
if ( : : send ( fd , data , dataByteCnt , 0 ) = = cwSOCKET_SYS_ERR )
2019-12-27 21:52:45 +00:00
return cwLogSysError ( kOpFailRC , errno , " Send failed. " ) ;
return kOkRC ;
}
cw : : rc_t cw : : net : : socket : : send ( handle_t h , const void * data , unsigned dataByteCnt , const struct sockaddr_in * remoteAddr )
{
socket_t * p = _handleToPtr ( h ) ;
errno = 0 ;
2020-01-27 22:52:53 +00:00
if ( : : sendto ( p - > sockH , data , dataByteCnt , 0 , ( struct sockaddr * ) remoteAddr , sizeof ( * remoteAddr ) ) = = cwSOCKET_SYS_ERR )
2019-12-27 21:52:45 +00:00
return cwLogSysError ( kOpFailRC , errno , " Send to remote addr. failed. " ) ;
return kOkRC ;
}
cw : : rc_t cw : : net : : socket : : send ( handle_t h , const void * data , unsigned dataByteCnt , const char * remoteAddr , portNumber_t remotePort )
{
rc_t rc ;
struct sockaddr_in addr ;
2020-03-17 02:52:21 +00:00
if ( ( rc = _initAddr ( remoteAddr , remotePort , & addr ) ) ! = kOkRC )
2019-12-27 21:52:45 +00:00
return rc ;
return send ( h , data , dataByteCnt , & addr ) ;
}
2020-02-12 18:25:13 +00:00
cw : : rc_t cw : : net : : socket : : receive ( handle_t h , char * data , unsigned dataByteCnt , unsigned * recvByteCntRef , struct sockaddr_in * fromAddr )
2019-12-27 21:52:45 +00:00
{
socket_t * p = _handleToPtr ( h ) ;
rc_t rc = kOkRC ;
ssize_t retVal = 0 ;
socklen_t sizeOfRemoteAddr = fromAddr = = NULL ? 0 : sizeof ( struct sockaddr_in ) ;
2020-01-29 16:42:41 +00:00
2019-12-27 21:52:45 +00:00
errno = 0 ;
if ( recvByteCntRef ! = NULL )
* recvByteCntRef = 0 ;
2020-01-27 22:52:53 +00:00
int fd = p - > fdH ! = cwSOCKET_NULL_SOCK ? p - > fdH : p - > sockH ;
if ( ( retVal = recvfrom ( fd , data , dataByteCnt , 0 , ( struct sockaddr * ) fromAddr , & sizeOfRemoteAddr ) ) = = cwSOCKET_SYS_ERR )
2020-02-01 15:12:51 +00:00
{
2020-02-12 18:25:13 +00:00
switch ( errno )
{
case EAGAIN :
return kTimeOutRC ;
case ENOTCONN :
if ( cwIsFlag ( p - > flags , kIsConnectedFl ) )
cwLogWarning ( " Socket Disconnected. " ) ;
p - > flags = cwClrFlag ( p - > flags , kIsConnectedFl ) ;
}
return cwLogSysError ( kOpFailRC , errno , " recvfrom() failed . " ) ;
2020-02-01 15:12:51 +00:00
}
2020-02-12 18:25:13 +00:00
2019-12-27 21:52:45 +00:00
if ( recvByteCntRef ! = NULL )
* recvByteCntRef = retVal ;
return rc ;
}
2020-02-12 18:25:13 +00:00
cw : : rc_t cw : : net : : socket : : select_receive ( handle_t h , char * buf , unsigned bufByteCnt , unsigned timeOutMs , unsigned * recvByteCntRef , struct sockaddr_in * fromAddr )
2019-12-27 21:52:45 +00:00
{
rc_t rc = kOkRC ;
socket_t * p = _handleToPtr ( h ) ;
fd_set rdSet ;
struct timeval timeOut ;
2020-03-23 20:46:04 +00:00
int fd = p - > fdH ! = cwSOCKET_NULL_SOCK ? p - > fdH : p - > sockH ;
2019-12-27 21:52:45 +00:00
// setup the select() call
FD_ZERO ( & rdSet ) ;
2020-03-23 20:46:04 +00:00
FD_SET ( fd , & rdSet ) ;
2019-12-27 21:52:45 +00:00
timeOut . tv_sec = timeOutMs / 1000 ;
timeOut . tv_usec = ( timeOutMs - ( timeOut . tv_sec * 1000 ) ) * 1000 ;
if ( recvByteCntRef ! = nullptr )
* recvByteCntRef = 0 ;
// NOTE; select() takes the highest socket value plus one of all the sockets in all the sets.
2020-03-23 20:46:04 +00:00
switch ( select ( fd + 1 , & rdSet , NULL , NULL , & timeOut ) )
2019-12-27 21:52:45 +00:00
{
case - 1 : // error
if ( errno ! = EINTR )
cwLogSysError ( kOpFailRC , errno , " Select failed. " ) ;
break ;
2020-02-12 18:25:13 +00:00
case 0 : // select() timed out
rc = kTimeOutRC ;
2019-12-27 21:52:45 +00:00
break ;
case 1 : // (> 0) count of ready descripters
2020-03-23 20:46:04 +00:00
if ( FD_ISSET ( fd , & rdSet ) )
2019-12-27 21:52:45 +00:00
{
socklen_t addrByteCnt = fromAddr = = nullptr ? 0 : sizeof ( * fromAddr ) ;
ssize_t retByteCnt ;
errno = 0 ;
// recv the incoming msg into buf[]
2020-03-23 20:46:04 +00:00
if ( ( retByteCnt = recvfrom ( fd , buf , bufByteCnt , 0 , ( struct sockaddr * ) fromAddr , & addrByteCnt ) ) = = cwSOCKET_SYS_ERR )
2020-02-12 18:25:13 +00:00
{
switch ( errno )
{
case ECONNRESET :
if ( cwIsFlag ( p - > flags , kIsConnectedFl ) )
cwLogWarning ( " Socket Disconnected. " ) ;
p - > flags = cwClrFlag ( p - > flags , kIsConnectedFl ) ;
}
2019-12-27 21:52:45 +00:00
rc = cwLogSysError ( kOpFailRC , errno , " recvfrom() failed. " ) ;
2020-02-12 18:25:13 +00:00
}
2019-12-27 21:52:45 +00:00
else
{
// check for overflow
2020-04-16 15:11:09 +00:00
if ( retByteCnt = = ( ssize_t ) bufByteCnt )
2019-12-27 21:52:45 +00:00
rc = cwLogError ( kBufTooSmallRC , " The receive buffer requires more than %i bytes. " , bufByteCnt ) ;
if ( recvByteCntRef ! = nullptr )
* recvByteCntRef = retByteCnt ;
}
}
break ;
default :
{ cwAssert ( 0 ) ; }
} // switch
return rc ;
}
2020-01-27 22:52:53 +00:00
cw : : rc_t cw : : net : : socket : : recv_from ( handle_t h , char * buf , unsigned bufByteCnt , unsigned * recvByteCntRef , struct sockaddr_in * fromAddr )
{
rc_t rc = kOkRC ;
socket_t * p = _handleToPtr ( h ) ;
socklen_t addrlen = 0 ;
int bytesN = 0 ;
if ( recvByteCntRef ! = nullptr )
* recvByteCntRef = 0 ;
if ( fromAddr ! = nullptr )
{
addrlen = sizeof ( * fromAddr ) ;
memset ( fromAddr , 0 , sizeof ( * fromAddr ) ) ;
}
int fd = p - > fdH ! = cwSOCKET_NULL_SOCK ? p - > fdH : p - > sockH ;
if ( ( bytesN = recvfrom ( fd , buf , bufByteCnt , 0 , ( struct sockaddr * ) fromAddr , & addrlen ) ) < 0 )
{
// if this is a non-blocking socket then return value -1 indicates that no data is available.
if ( cwIsNotFlag ( p - > flags , kBlockingFl ) & & bytesN = = - 1 )
bytesN = 0 ;
else
{
rc = cwLogSysError ( kReadFailRC , errno , " recvfrom() failed. " ) ;
goto errLabel ;
}
}
if ( recvByteCntRef ! = nullptr )
* recvByteCntRef = bytesN ;
errLabel :
return rc ;
}
2020-02-12 18:25:13 +00:00
cw : : rc_t cw : : net : : socket : : get_mac ( handle_t h , unsigned char outBuf [ 6 ] , struct sockaddr_in * addr , const char * netInterfaceName )
2020-02-01 15:12:51 +00:00
{
2020-02-12 18:25:13 +00:00
socket_t * p = _handleToPtr ( h ) ;
return _get_info ( p - > sockH , outBuf , addr , netInterfaceName ) ;
2020-02-01 15:12:51 +00:00
}
2019-12-27 21:52:45 +00:00
2020-03-17 02:52:21 +00:00
cw : : rc_t cw : : net : : socket : : initAddr ( const char * addrStr , portNumber_t portNumber , struct sockaddr_in * retAddrPtr )
2019-12-27 21:52:45 +00:00
{
2020-03-17 02:52:21 +00:00
return _initAddr ( addrStr , portNumber , retAddrPtr ) ;
2019-12-27 21:52:45 +00:00
}
2020-02-12 18:25:13 +00:00
cw : : rc_t cw : : net : : socket : : addrToString ( const struct sockaddr_in * addr , char * buf , unsigned bufN )
2019-12-27 21:52:45 +00:00
{
2020-02-12 18:25:13 +00:00
rc_t rc = kOkRC ;
2019-12-27 21:52:45 +00:00
errno = 0 ;
if ( inet_ntop ( AF_INET , & ( addr - > sin_addr ) , buf , bufN ) = = NULL )
{
2020-02-12 18:25:13 +00:00
rc = cwLogSysError ( kOpFailRC , errno , " Network address to string conversion failed. " ) ;
goto errLabel ;
2019-12-27 21:52:45 +00:00
}
buf [ bufN - 1 ] = 0 ;
2020-02-12 18:25:13 +00:00
errLabel :
return rc ;
2019-12-27 21:52:45 +00:00
}
bool cw : : net : : socket : : addrIsEqual ( const struct sockaddr_in * a0 , const struct sockaddr_in * a1 )
{
return a0 - > sin_family = = a1 - > sin_family
& & a0 - > sin_port = = a1 - > sin_port
& & memcmp ( & a0 - > sin_addr , & a1 - > sin_addr , sizeof ( a0 - > sin_addr ) ) = = 0 ;
}
const char * cw : : net : : socket : : hostName ( handle_t h )
{
socket_t * p = _handleToPtr ( h ) ;
errno = 0 ;
if ( gethostname ( p - > hnameBuf , HOST_NAME_MAX ) ! = 0 )
{
2020-02-12 18:25:13 +00:00
cwLogSysError ( kOpFailRC , errno , " gethostname() failed. " ) ;
return NULL ;
2019-12-27 21:52:45 +00:00
}
p - > hnameBuf [ HOST_NAME_MAX ] = 0 ;
return p - > hnameBuf ;
}
2020-02-12 18:25:13 +00:00
const char * cw : : net : : socket : : ipAddress ( handle_t h )
{
socket_t * p = _handleToPtr ( h ) ;
return p - > ntopBuf ;
}
unsigned cw : : net : : socket : : inetAddress ( handle_t h )
{
socket_t * p = _handleToPtr ( h ) ;
return p - > sockaddr . sin_addr . s_addr ;
}
cw : : net : : socket : : portNumber_t cw : : net : : socket : : port ( handle_t h )
{
socket_t * p = _handleToPtr ( h ) ;
return ntohs ( p - > sockaddr . sin_port ) ;
}
cw : : rc_t cw : : net : : socket : : peername ( handle_t h , struct sockaddr_in * addr )
{
rc_t rc = kOkRC ;
socklen_t n = sizeof ( struct sockaddr_in ) ;
socket_t * p = _handleToPtr ( h ) ;
if ( getpeername ( p - > sockH , ( struct sockaddr * ) addr , & n ) = = cwSOCKET_SYS_ERR )
return cwLogSysError ( kOpFailRC , errno , " Get peer name failed. " ) ;
addr - > sin_port = ntohs ( addr - > sin_port ) ;
return rc ;
}
cw : : rc_t cw : : net : : socket : : get_info ( const char * netInterfaceName , unsigned char mac [ 6 ] , char * host , unsigned hostN , struct sockaddr_in * addr )
{
rc_t rc = kOkRC ;
int sockH ;
if ( host ! = nullptr )
if ( gethostname ( host , hostN ) ! = 0 )
return cwLogSysError ( kOpFailRC , errno , " Unable to get the local host name. " ) ;
// get a handle to the socket
if ( ( sockH = : : socket ( AF_INET , SOCK_DGRAM , 0 ) ) = = cwSOCKET_SYS_ERR )
return cwLogSysError ( kOpFailRC , errno , " Unable to create temporary socket. " ) ;
if ( ( rc = _get_info ( sockH , mac , addr , netInterfaceName ) ) ! = kOkRC )
goto errLabel ;
errLabel :
close ( sockH ) ;
return rc ;
}