2012-10-30 03:52:39 +00:00
# include "cmPrefix.h"
# include "cmGlobal.h"
# include "cmRpt.h"
# include "cmErr.h"
# include "cmCtx.h"
# include "cmMem.h"
# include "cmMallocDebug.h"
# include "cmThread.h"
# include <sys/socket.h>
# include <netinet/in.h>
# include <arpa/inet.h>
# include <fcntl.h>
# include <unistd.h> // close
# include "cmUdpPort.h"
# define cmUdp_SYS_ERR (-1)
# define cmUdp_NULL_SOCK (-1)
2013-05-01 22:08:58 +00:00
# ifndef HOST_NAME_MAX
# define HOST_NAME_MAX _POSIX_HOST_NAME_MAX
# endif
2012-10-30 03:52:39 +00:00
enum
{
kIsConnectedUdpFl = 0x01 ,
kIsBlockingUdpFl = 0x02 ,
kQueueingUdpFl = 0x04
} ;
typedef struct
{
cmErr_t err ;
int sockH ;
cmUdpCallback_t cbFunc ;
void * cbArg ;
unsigned timeOutMs ;
unsigned flags ;
cmThreadH_t thH ;
cmTs1p1cH_t qH ;
unsigned recvBufByteCnt ;
char * tempBuf ;
unsigned timeOutCnt ;
unsigned recvCnt ;
unsigned queCbCnt ;
unsigned errCnt ;
2013-04-27 19:13:38 +00:00
struct sockaddr_in sockaddr ;
2013-04-12 20:07:50 +00:00
cmChar_t ntopBuf [ INET_ADDRSTRLEN + 1 ] ; // use INET6_ADDRSTRLEN for IPv6
2013-04-27 19:13:38 +00:00
cmChar_t hnameBuf [ HOST_NAME_MAX + 1 ] ;
2012-10-30 03:52:39 +00:00
} cmUdp_t ;
cmUdpH_t cmUdpNullHandle = cmSTATIC_NULL_HANDLE ;
# define _cmUdpClear_errno() errno = 0
cmUdp_t * _cmUdpHandleToPtr ( cmUdpH_t h )
{
cmUdp_t * p = ( cmUdp_t * ) h . h ;
assert ( p ! = NULL ) ;
return p ;
}
cmUdpRC_t _cmUdpFinal ( cmUdp_t * p )
{
cmUdpRC_t rc = kOkUdpRC ;
if ( cmThreadIsValid ( p - > thH ) )
if ( cmThreadDestroy ( & p - > thH ) ! = kOkThRC )
return cmErrMsg ( & p - > err , kThreadFailUdpRC , " Listener thread destroy failed. " ) ;
if ( cmTs1p1cIsValid ( p - > qH ) )
if ( cmTs1p1cDestroy ( & p - > qH ) ! = kOkThRC )
cmErrMsg ( & p - > err , kQueueFailUdpRC , " Receive data queue destroy failed. " ) ;
cmMemPtrFree ( & p - > tempBuf ) ;
// close the socket
if ( p - > sockH ! = cmUdp_NULL_SOCK )
{
_cmUdpClear_errno ( ) ;
if ( close ( p - > sockH ) ! = 0 )
cmErrSysMsg ( & p - > err , kSockCloseFailUdpRC , errno , " The socket close failed. " ) ;
p - > sockH = cmUdp_NULL_SOCK ;
}
return rc ;
}
cmUdpRC_t _cmUdpFree ( cmUdp_t * p )
{
cmUdpRC_t rc ;
if ( ( rc = _cmUdpFinal ( p ) ) ! = kOkUdpRC )
return rc ;
cmMemFree ( p ) ;
return rc ;
}
cmUdpRC_t _cmUdpInitAddr ( cmUdp_t * p , const char * addrStr , cmUdpPort_t portNumber , struct sockaddr_in * retAddrPtr )
{
memset ( retAddrPtr , 0 , sizeof ( struct sockaddr_in ) ) ;
2013-05-01 22:08:58 +00:00
if ( portNumber = = kInvalidUdpPortNumber )
return cmErrMsg ( & p - > err , kInvalidPortNumbUdpRC , " The port number %i cannot be used. " , kInvalidUdpPortNumber ) ;
2012-10-30 03:52:39 +00:00
if ( addrStr = = NULL )
retAddrPtr - > sin_addr . s_addr = htonl ( INADDR_ANY ) ;
else
{
_cmUdpClear_errno ( ) ;
if ( inet_pton ( AF_INET , addrStr , & retAddrPtr - > sin_addr ) = = 0 )
//if(( retAddrPtr->sin_addr.s_addr = inet_addr(addrStr)) == INADDR_NONE )
return cmErrSysMsg ( & p - > err , kPtoNFailUdpRC , errno , " The network address string '%s' could not be converted to a netword address structure. " , cmStringNullGuard ( addrStr ) ) ;
}
//retAddrPtr->sin_len = sizeof(struct sockaddr_in);
retAddrPtr - > sin_family = AF_INET ;
retAddrPtr - > sin_port = htons ( portNumber ) ;
return kOkUdpRC ;
}
cmUdpRC_t _cmUdpConnect ( cmUdp_t * p , const char * remoteAddr , cmUdpPort_t remotePort )
{
struct sockaddr_in addr ;
cmUdpRC_t rc ;
// create the remote address
if ( ( rc = _cmUdpInitAddr ( p , remoteAddr , remotePort , & addr ) ) ! = kOkUdpRC )
return rc ;
_cmUdpClear_errno ( ) ;
// ... and connect this socket to the remote address/port
if ( connect ( p - > sockH , ( struct sockaddr * ) & addr , sizeof ( addr ) ) = = cmUdp_SYS_ERR )
return cmErrSysMsg ( & p - > err , kSockConnectFailUdpRC , errno , " Socket connect failed. " ) ;
p - > flags = cmSetFlag ( p - > flags , kIsConnectedUdpFl ) ;
return rc ;
}
cmUdpRC_t cmUdpAlloc ( cmCtx_t * ctx , cmUdpH_t * hp )
{
cmUdpRC_t rc ;
if ( ( rc = cmUdpFree ( hp ) ) ! = kOkUdpRC )
return rc ;
cmUdp_t * p = cmMemAllocZ ( cmUdp_t , 1 ) ;
cmErrSetup ( & p - > err , & ctx - > rpt , " UDP Port " ) ;
p - > sockH = cmUdp_NULL_SOCK ;
hp - > h = p ;
return rc ;
}
cmUdpRC_t cmUdpFree ( cmUdpH_t * hp )
{
cmUdpRC_t rc = kOkUdpRC ;
if ( hp = = NULL | | cmUdpIsValid ( * hp ) = = false )
return rc ;
cmUdp_t * p = _cmUdpHandleToPtr ( * hp ) ;
if ( ( rc = _cmUdpFree ( p ) ) ! = kOkUdpRC )
return rc ;
hp - > h = NULL ;
return rc ;
}
cmUdpRC_t cmUdpInit (
cmUdpH_t h ,
cmUdpPort_t port ,
unsigned flags ,
cmUdpCallback_t cbFunc ,
void * cbArg ,
const char * remoteAddr ,
cmUdpPort_t remotePort ,
unsigned recvBufByteCnt ,
unsigned timeOutMs )
{
cmUdpRC_t rc ;
cmUdp_t * p = _cmUdpHandleToPtr ( h ) ;
if ( ( rc = _cmUdpFinal ( p ) ) ! = kOkUdpRC )
return rc ;
_cmUdpClear_errno ( ) ;
// get a handle to the socket
if ( ( p - > sockH = socket ( AF_INET , SOCK_DGRAM , IPPROTO_UDP ) ) = = cmUdp_SYS_ERR )
return cmErrSysMsg ( & p - > err , kSockCreateFailUdpRC , errno , " Socket create failed. " ) ;
// create the local address
2013-04-27 19:13:38 +00:00
if ( ( rc = _cmUdpInitAddr ( p , NULL , port , & p - > sockaddr ) ) ! = kOkUdpRC )
2012-10-30 03:52:39 +00:00
goto errLabel ;
// bind the socket to a local address/port
2013-04-27 19:13:38 +00:00
if ( ( bind ( p - > sockH , ( struct sockaddr * ) & p - > sockaddr , sizeof ( p - > sockaddr ) ) ) = = cmUdp_SYS_ERR )
2012-10-30 03:52:39 +00:00
{
rc = cmErrSysMsg ( & p - > err , kSockBindFailUdpRC , errno , " Socket bind failed. " ) ;
goto errLabel ;
}
// if a remote addr was given connect this socket to it
if ( remoteAddr ! = NULL )
if ( ( rc = _cmUdpConnect ( p , remoteAddr , remotePort ) ) ! = kOkUdpRC )
goto errLabel ;
// if this socket should block
if ( cmIsFlag ( flags , kBlockingUdpFl ) )
{
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 ) ) = = cmUdp_SYS_ERR )
{
rc = cmErrSysMsg ( & p - > err , kSockOptSetFailUdpRC , errno , " Attempt to set the socket timeout failed. " ) ;
goto errLabel ;
}
p - > flags = cmSetFlag ( p - > flags , kIsBlockingUdpFl ) ;
}
else
{
int opts ;
// get the socket options flags
if ( ( opts = fcntl ( p - > sockH , F_GETFL ) ) < 0 )
{
rc = cmErrSysMsg ( & p - > err , kSockOptSetFailUdpRC , 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 = cmErrSysMsg ( & p - > err , kSockOptSetFailUdpRC , errno , " Attempt to set the socket to non-blocking failed. " ) ;
goto errLabel ;
}
}
2013-04-27 22:51:58 +00:00
// if broadcast option was requested.
if ( cmIsFlag ( flags , kBroadcastUdpFl ) )
{
int bcastFl = 1 ;
if ( setsockopt ( p - > sockH , SOL_SOCKET , SO_BROADCAST , & bcastFl , sizeof ( bcastFl ) ) = = cmUdp_SYS_ERR )
{
rc = cmErrSysMsg ( & p - > err , kSockOptSetFailUdpRC , errno , " Attempt to set the socket broadcast attribute failed. " ) ;
goto errLabel ;
}
}
2012-10-30 03:52:39 +00:00
if ( recvBufByteCnt ! = 0 )
p - > tempBuf = cmMemAlloc ( char , recvBufByteCnt ) ;
p - > timeOutMs = timeOutMs ;
p - > cbFunc = cbFunc ;
p - > cbArg = cbArg ;
p - > recvBufByteCnt = recvBufByteCnt ;
p - > timeOutCnt = 0 ;
p - > recvCnt = 0 ;
p - > queCbCnt = 0 ;
p - > errCnt = 0 ;
if ( cmIsFlag ( flags , kNoQueueUdpFl ) = = false )
p - > flags = cmSetFlag ( p - > flags , kQueueingUdpFl ) ;
errLabel :
if ( rc ! = kOkUdpRC )
_cmUdpFree ( p ) ;
return rc ;
}
cmUdpRC_t cmUdpFinal ( cmUdpH_t h )
{
cmUdp_t * p = _cmUdpHandleToPtr ( h ) ;
return _cmUdpFinal ( p ) ;
}
bool cmUdpIsValid ( cmUdpH_t h )
{ return h . h ! = NULL ; }
2013-04-27 19:13:38 +00:00
const struct sockaddr_in * cmUdpLocalAddr ( cmUdpH_t h )
{
cmUdp_t * p = _cmUdpHandleToPtr ( h ) ;
return & p - > sockaddr ;
}
2012-10-30 03:52:39 +00:00
cmUdpRC_t cmUdpConnect ( cmUdpH_t h , const char * remoteAddr , cmUdpPort_t remotePort )
{
cmUdp_t * p = _cmUdpHandleToPtr ( h ) ;
return _cmUdpConnect ( p , remoteAddr , remotePort ) ;
}
cmUdpRC_t cmUdpSend ( cmUdpH_t h , const char * data , unsigned dataByteCnt )
{
cmUdp_t * p = _cmUdpHandleToPtr ( h ) ;
_cmUdpClear_errno ( ) ;
if ( cmIsFlag ( p - > flags , kIsConnectedUdpFl ) = = false )
return cmErrMsg ( & p - > err , kNotConnectedUdpRC , " cmUdpSend() only works with connected sockets . " ) ;
if ( send ( p - > sockH , data , dataByteCnt , 0 ) = = cmUdp_SYS_ERR )
return cmErrSysMsg ( & p - > err , kSockSendFailUdpRC , errno , " Send failed. " ) ;
return kOkUdpRC ;
}
cmUdpRC_t cmUdpSendTo ( cmUdpH_t h , const char * data , unsigned dataByteCnt , const struct sockaddr_in * remoteAddr )
{
cmUdp_t * p = _cmUdpHandleToPtr ( h ) ;
_cmUdpClear_errno ( ) ;
if ( sendto ( p - > sockH , data , dataByteCnt , 0 , ( struct sockaddr * ) remoteAddr , sizeof ( * remoteAddr ) ) = = cmUdp_SYS_ERR )
return cmErrSysMsg ( & p - > err , kSockSendFailUdpRC , errno , " SendTo failed. " ) ;
return kOkUdpRC ;
}
cmUdpRC_t cmUdpSend2 ( cmUdpH_t h , const char * data , unsigned dataByteCnt , const char * remoteAddr , cmUdpPort_t remotePort )
{
cmUdpRC_t rc ;
cmUdp_t * p = _cmUdpHandleToPtr ( h ) ;
struct sockaddr_in addr ;
if ( ( rc = _cmUdpInitAddr ( p , remoteAddr , remotePort , & addr ) ) ! = kOkUdpRC )
return rc ;
return cmUdpSendTo ( h , data , dataByteCnt , & addr ) ;
}
cmUdpRC_t cmUdpRecv ( cmUdpH_t h , char * data , unsigned dataByteCnt , struct sockaddr_in * fromAddr , unsigned * recvByteCntPtr )
{
cmUdp_t * p = _cmUdpHandleToPtr ( h ) ;
cmUdpRC_t rc = kOkUdpRC ;
ssize_t retVal = 0 ;
socklen_t sizeOfRemoteAddr = fromAddr = = NULL ? 0 : sizeof ( struct sockaddr_in ) ;
_cmUdpClear_errno ( ) ;
if ( recvByteCntPtr ! = NULL )
* recvByteCntPtr = 0 ;
if ( ( retVal = recvfrom ( p - > sockH , data , dataByteCnt , 0 , ( struct sockaddr * ) fromAddr , & sizeOfRemoteAddr ) ) = = cmUdp_SYS_ERR )
return cmErrSysMsg ( & p - > err , kSockRecvFailUdpRC , errno , " recvFrom() failed . " ) ;
if ( recvByteCntPtr ! = NULL )
* recvByteCntPtr = retVal ;
return rc ;
}
bool _cmUdpThreadCb ( void * param )
{
cmUdp_t * p = ( cmUdp_t * ) param ;
fd_set rdSet ;
struct timeval timeOut ;
// setup the select() call
FD_ZERO ( & rdSet ) ;
FD_SET ( p - > sockH , & rdSet ) ;
timeOut . tv_sec = p - > timeOutMs / 1000 ;
timeOut . tv_usec = ( p - > timeOutMs - ( timeOut . tv_sec * 1000 ) ) * 1000 ;
// NOTE; select() takes the highest socket value plus one of all the sockets in all the sets.
switch ( select ( p - > sockH + 1 , & rdSet , NULL , NULL , & timeOut ) )
{
case - 1 : // error
if ( errno ! = EINTR )
cmErrSysMsg ( & p - > err , kSockSelectFailUdpRC , errno , " Select failed. " ) ;
+ + p - > errCnt ;
break ;
case 0 : // select() timed out
+ + p - > timeOutCnt ;
break ;
case 1 : // (> 0) count of ready descripters
if ( FD_ISSET ( p - > sockH , & rdSet ) )
{
struct sockaddr_in remoteAddr ;
socklen_t addrByteCnt = sizeof ( remoteAddr ) ;
ssize_t retByteCnt ;
_cmUdpClear_errno ( ) ;
+ + p - > recvCnt ;
// recv the incoming msg into p->tempBuf[]
if ( ( retByteCnt = recvfrom ( p - > sockH , p - > tempBuf , p - > recvBufByteCnt , 0 , ( struct sockaddr * ) & remoteAddr , & addrByteCnt ) ) = = cmUdp_SYS_ERR )
cmErrSysMsg ( & p - > err , kSockRecvFailUdpRC , errno , " recvfrom() failed. " ) ;
else
{
// check for overflow
if ( retByteCnt = = p - > recvBufByteCnt )
cmErrMsg ( & p - > err , kRecvBufOverflowUdpRC , " The receive buffer requires more than %i bytes. " , p - > recvBufByteCnt ) ;
else
{
// if queueing is enabled
if ( cmIsFlag ( p - > flags , kQueueingUdpFl ) )
{
// enqueue the msg - with the source address appended after the data
const void * msgPtrArray [ ] = { p - > tempBuf , & remoteAddr , p - > tempBuf } ;
unsigned msgByteCntArray [ ] = { retByteCnt , sizeof ( remoteAddr ) } ;
if ( cmTs1p1cEnqueueSegMsg ( p - > qH , msgPtrArray , msgByteCntArray , 2 ) ! = kOkThRC )
cmErrMsg ( & p - > err , kQueueFailUdpRC , " A received msg containing %i bytes was not queued. " , retByteCnt ) ;
}
else // if queueing is not enabled - transmit the data directly via the callback
if ( p - > cbFunc ! = NULL )
{
p - > cbFunc ( p - > cbArg , p - > tempBuf , retByteCnt , & remoteAddr ) ;
}
}
}
}
break ;
default :
{ assert ( 0 ) ; }
} // switch
return true ;
}
cmRC_t _cmUdpQueueCb ( void * userCbPtr , unsigned msgByteCnt , const void * msgDataPtr )
{
cmUdp_t * p = ( cmUdp_t * ) userCbPtr ;
if ( p - > cbFunc ! = NULL )
{
struct sockaddr_in addr ;
assert ( msgByteCnt > = sizeof ( addr ) ) ;
const char * dataPtr = ( const char * ) msgDataPtr ;
// the address of the data source is apppended to the data bytes.
const char * addrPtr = dataPtr + msgByteCnt - sizeof ( addr ) ;
memcpy ( & addr , addrPtr , sizeof ( addr ) ) ;
// make the receive callback
p - > cbFunc ( p - > cbArg , dataPtr , msgByteCnt - sizeof ( addr ) , & addr ) ;
+ + p - > queCbCnt ;
}
return cmOkRC ;
}
cmUdpRC_t cmUdpEnableListen ( cmUdpH_t h , bool enableFl )
{
cmUdp_t * p = _cmUdpHandleToPtr ( h ) ;
if ( cmThreadIsValid ( p - > thH ) = = false & & enableFl = = true )
{
if ( cmThreadCreate ( & p - > thH , _cmUdpThreadCb , p , p - > err . rpt ) ! = kOkThRC )
return cmErrMsg ( & p - > err , kThreadFailUdpRC , " Listener thread create failed. " ) ;
if ( cmTs1p1cCreate ( & p - > qH , p - > recvBufByteCnt , _cmUdpQueueCb , p , p - > err . rpt ) ! = kOkThRC )
return cmErrMsg ( & p - > err , kQueueFailUdpRC , " Listener data queue create failed. " ) ;
}
if ( cmThreadIsValid ( p - > thH ) )
if ( cmThreadPause ( p - > thH , enableFl ? 0 : kPauseThFl ) ! = kOkThRC )
return cmErrMsg ( & p - > err , kThreadFailUdpRC , " The listener thread failed to %s. " , enableFl ? " pause " : " un-pause " ) ;
return kOkUdpRC ;
}
bool cmUdpIsQueueEnabled ( cmUdpH_t h )
{
cmUdp_t * p = _cmUdpHandleToPtr ( h ) ;
return cmIsFlag ( p - > flags , kQueueingUdpFl ) ;
}
void cmUdpQueueEnable ( cmUdpH_t h , bool enableFl )
{
cmUdp_t * p = _cmUdpHandleToPtr ( h ) ;
p - > flags = cmSetFlag ( p - > flags , kQueueingUdpFl ) ;
}
unsigned cmUdpAvailDataByteCount ( cmUdpH_t h )
{
cmUdp_t * p = _cmUdpHandleToPtr ( h ) ;
return cmTs1p1cIsValid ( p - > qH ) ? cmTs1p1cDequeueMsgByteCount ( p - > qH ) : 0 ;
}
cmUdpRC_t cmUdpGetAvailData ( cmUdpH_t h , char * data , unsigned * dataByteCntPtr , struct sockaddr_in * fromAddr )
{
cmUdp_t * p = _cmUdpHandleToPtr ( h ) ;
unsigned availByteCnt ;
// if a received msg is queued
if ( ( availByteCnt = cmTs1p1cAvailByteCount ( p - > qH ) ) > 0 )
{
// all msg's must have at least a source address
assert ( availByteCnt > = sizeof ( * fromAddr ) ) ;
// get the size of the return buffer (or 0 if there is no return buffer)
unsigned dataByteCnt = ( data ! = NULL & & dataByteCntPtr ! = NULL ) ? * dataByteCntPtr : 0 ;
if ( dataByteCnt = = 0 )
data = NULL ;
// dequeue the msg - if data==NULL then the data will be returned by
// a call to the callback function provided in cmUdpAlloc().
if ( cmTs1p1cDequeueMsg ( p - > qH , data , dataByteCnt ) ! = kOkThRC )
return cmErrMsg ( & p - > err , kQueueFailUdpRC , " Data dequeue failed. " ) ;
// if a return buffer was given
if ( data ! = NULL )
{
assert ( dataByteCntPtr ! = NULL ) ;
// the source address is appended to the end of the data
const char * addrPtr = data + availByteCnt - sizeof ( * fromAddr ) ;
// copy out the source address
if ( fromAddr ! = NULL )
memcpy ( fromAddr , addrPtr , sizeof ( * fromAddr ) ) ;
// subtract the address size from the total msg size
* dataByteCntPtr = availByteCnt - sizeof ( * fromAddr ) ;
}
}
return kOkUdpRC ;
}
void cmUdpReport ( cmUdpH_t h , cmRpt_t * rpt )
{
cmUdp_t * p = _cmUdpHandleToPtr ( h ) ;
cmRptPrintf ( rpt , " time-out:%i recv:%i queue cb:%i \n " , p - > timeOutCnt , p - > recvCnt , p - > queCbCnt ) ;
}
cmUdpRC_t cmUdpInitAddr ( cmUdpH_t h , const char * addrStr , cmUdpPort_t portNumber , struct sockaddr_in * retAddrPtr )
{
cmUdp_t * p = _cmUdpHandleToPtr ( h ) ;
return _cmUdpInitAddr ( p , addrStr , portNumber , retAddrPtr ) ;
}
2013-04-12 20:07:50 +00:00
const cmChar_t * cmUdpAddrToString ( cmUdpH_t h , const struct sockaddr_in * addr )
{
cmUdp_t * p = _cmUdpHandleToPtr ( h ) ;
_cmUdpClear_errno ( ) ;
2013-04-27 18:17:46 +00:00
if ( inet_ntop ( AF_INET , & ( addr - > sin_addr ) , p - > ntopBuf , INET_ADDRSTRLEN ) = = NULL )
2013-04-12 20:07:50 +00:00
{
cmErrSysMsg ( & p - > err , kNtoPFailUdpRC , errno , " Network address to string conversion failed. " ) ;
return NULL ;
}
p - > ntopBuf [ INET_ADDRSTRLEN ] = 0 ;
return p - > ntopBuf ;
}
2013-04-26 22:33:13 +00:00
2014-06-16 05:17:31 +00:00
bool cmUdpAddrIsEqual ( 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 ;
}
2013-04-27 19:13:38 +00:00
const cmChar_t * cmUdpHostName ( cmUdpH_t h )
2013-04-26 22:33:13 +00:00
{
2013-04-27 19:13:38 +00:00
cmUdp_t * p = _cmUdpHandleToPtr ( h ) ;
2013-04-26 22:33:13 +00:00
2013-04-27 19:13:38 +00:00
_cmUdpClear_errno ( ) ;
2013-04-26 22:33:13 +00:00
2013-04-27 19:13:38 +00:00
if ( gethostname ( p - > hnameBuf , HOST_NAME_MAX ) ! = 0 )
{
cmErrSysMsg ( & p - > err , kHostNameFailUdpRC , errno , " gethostname() failed. " ) ;
return NULL ;
}
p - > hnameBuf [ HOST_NAME_MAX ] = 0 ;
return p - > hnameBuf ;
2013-04-26 22:33:13 +00:00
}
2014-12-06 22:24:48 +00:00
//=======================================================================================
void cmUdpCallbackTest ( void * cbArg , const char * data , unsigned dataByteCnt , const struct sockaddr_in * fromAddr )
{
printf ( " %s \n " , data ) ;
}
cmUdpRC_t cmUdpTest ( cmCtx_t * ctx , const char * remoteIpAddr , cmUdpPort_t port )
{
cmUdpRC_t rc = kOkUdpRC ;
cmUdpH_t h = cmUdpNullHandle ;
cmErr_t * err = & ctx - > err ;
unsigned recvBufByteCnt = 4096 ;
unsigned recvTimeOutMs = 50 ;
unsigned udpFlags = kNonBlockingUdpFl | kBroadcastUdpFl | kNoQueueUdpFl ;
unsigned strN = 1024 ;
char str [ strN ] ;
struct sockaddr_in addr ;
// allocate the UDP port
if ( ( rc = cmUdpAlloc ( ctx , & h ) ) ! = kOkUdpRC )
return cmErrMsg ( err , rc , " UDP port allocate failed. " ) ;
// initialize the UDP port
if ( ( rc = cmUdpInit ( h , port , udpFlags , cmUdpCallbackTest , NULL , NULL , 0 , recvBufByteCnt , recvTimeOutMs ) ) ! = kOkUdpRC )
{
rc = cmErrMsg ( err , rc , " UPD port initialzation failed. " ) ;
goto errLabel ;
}
// convert the IP address to a sockaddr_in
if ( ( rc = cmUdpInitAddr ( h , remoteIpAddr , port , & addr ) ) ! = kOkUdpRC )
{
rc = cmErrMsg ( err , rc , " IP address conversion failed. " ) ;
goto errLabel ;
}
// start up the UDP port listening thread
if ( ( rc = cmUdpEnableListen ( h , true ) ) ! = kOkUdpRC )
{
rc = cmErrMsg ( err , rc , " UDP port switch to listen mode failed. " ) ;
goto errLabel ;
}
printf ( " q=quit " ) ;
while ( 1 )
{
printf ( " $ " ) ;
fflush ( stdout ) ;
scanf ( " %s " , str ) ;
if ( strlen ( str ) > 0 )
{
if ( strcmp ( str , " q " ) = = 0 )
break ;
if ( ( rc = cmUdpSendTo ( h , str , strlen ( str ) + 1 , & addr ) ) ! = kOkUdpRC )
{
rc = cmErrMsg ( err , rc , " UDP send failed. " ) ;
goto errLabel ;
}
}
}
errLabel :
if ( ( rc = cmUdpFree ( & h ) ) ! = kOkUdpRC )
rc = cmErrMsg ( err , rc , " UDP port free failed. " ) ;
return rc ;
}
cmUdpRC_t cmUdpTestV ( cmCtx_t * ctx , unsigned argc , const char * argv [ ] )
{
if ( argc < 3 )
return cmErrMsg ( & ctx - > err , kTestFailUdpRC , " cmUdpTestV usage: argv[1]=<IP Addr> argv[2]=<Socket Port Number> " ) ;
const char * ipAddr = argv [ 1 ] ;
cmUdpPort_t port = atoi ( argv [ 2 ] ) ;
cmRptPrintf ( & ctx - > rpt , " UDP Test Sending To: %s port:%i \n " , ipAddr , port ) ;
return cmUdpTest ( ctx , ipAddr , port ) ;
}