cwTcpSocket*.h/cpp : Updated to support more socket options and configurations.
This commit is contained in:
parent
c37595578a
commit
6590d4b181
265
cwTcpSocket.cpp
265
cwTcpSocket.cpp
@ -34,6 +34,7 @@ namespace cw
|
|||||||
typedef struct socket_str
|
typedef struct socket_str
|
||||||
{
|
{
|
||||||
int sockH;
|
int sockH;
|
||||||
|
int fdH;
|
||||||
unsigned flags;
|
unsigned flags;
|
||||||
unsigned recvBufByteCnt;
|
unsigned recvBufByteCnt;
|
||||||
struct sockaddr_in sockaddr;
|
struct sockaddr_in sockaddr;
|
||||||
@ -45,6 +46,18 @@ namespace cw
|
|||||||
|
|
||||||
rc_t _destroy( socket_t* p )
|
rc_t _destroy( socket_t* p )
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
// close the socket
|
// close the socket
|
||||||
if( p->sockH != cwSOCKET_NULL_SOCK )
|
if( p->sockH != cwSOCKET_NULL_SOCK )
|
||||||
{
|
{
|
||||||
@ -65,8 +78,8 @@ namespace cw
|
|||||||
{
|
{
|
||||||
memset(retAddrPtr,0,sizeof(struct sockaddr_in));
|
memset(retAddrPtr,0,sizeof(struct sockaddr_in));
|
||||||
|
|
||||||
if( portNumber == kInvalidPortNumber )
|
//if( portNumber == kInvalidPortNumber )
|
||||||
return cwLogError(kInvalidArgRC,"The port number %i cannot be used.",kInvalidPortNumber);
|
// return cwLogError(kInvalidArgRC,"The port number %i cannot be used.",kInvalidPortNumber);
|
||||||
|
|
||||||
if( addrStr == NULL )
|
if( addrStr == NULL )
|
||||||
retAddrPtr->sin_addr.s_addr = htonl(INADDR_ANY);
|
retAddrPtr->sin_addr.s_addr = htonl(INADDR_ANY);
|
||||||
@ -80,6 +93,7 @@ namespace cw
|
|||||||
|
|
||||||
//retAddrPtr->sin_len = sizeof(struct sockaddr_in);
|
//retAddrPtr->sin_len = sizeof(struct sockaddr_in);
|
||||||
retAddrPtr->sin_family = AF_INET;
|
retAddrPtr->sin_family = AF_INET;
|
||||||
|
if( portNumber != kInvalidPortNumber )
|
||||||
retAddrPtr->sin_port = htons(portNumber);
|
retAddrPtr->sin_port = htons(portNumber);
|
||||||
|
|
||||||
return kOkRC;
|
return kOkRC;
|
||||||
@ -105,6 +119,26 @@ namespace cw
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -124,44 +158,26 @@ cw::rc_t cw::net::socket::create(
|
|||||||
|
|
||||||
socket_t* p = mem::allocZ<socket_t>();
|
socket_t* p = mem::allocZ<socket_t>();
|
||||||
p->sockH = cwSOCKET_NULL_SOCK;
|
p->sockH = cwSOCKET_NULL_SOCK;
|
||||||
|
p->fdH = cwSOCKET_NULL_SOCK;
|
||||||
|
|
||||||
|
int type = cwIsFlag(flags,kStreamFl) ? SOCK_STREAM : SOCK_DGRAM;
|
||||||
|
int protocol = cwIsFlag(flags,kTcpFl) ? 0 : IPPROTO_UDP;
|
||||||
|
|
||||||
// get a handle to the socket
|
// get a handle to the socket
|
||||||
if(( p->sockH = ::socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP ) ) == cwSOCKET_SYS_ERR )
|
if(( p->sockH = ::socket( AF_INET, type, protocol ) ) == cwSOCKET_SYS_ERR )
|
||||||
return cwLogSysError(kOpFailRC, errno, "Socket create failed." );
|
return cwLogSysError(kOpFailRC, errno, "Socket create failed." );
|
||||||
|
|
||||||
// create the local address
|
|
||||||
if((rc = _initAddr(p, NULL, port, &p->sockaddr )) != kOkRC )
|
|
||||||
goto errLabel;
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if a remote addr was given connect this socket to it
|
|
||||||
if( remoteAddr != NULL )
|
|
||||||
if((rc = _connect(p,remoteAddr,remotePort)) != kOkRC )
|
|
||||||
goto errLabel;
|
|
||||||
|
|
||||||
// if this socket should block
|
// if this socket should block
|
||||||
if( cwIsFlag(flags,kBlockingFl))
|
if( cwIsFlag(flags,kBlockingFl))
|
||||||
{
|
{
|
||||||
struct timeval timeOut;
|
if( timeOutMs > 0 )
|
||||||
|
|
||||||
// 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." );
|
_setTimeOutMs(p,timeOutMs);
|
||||||
goto errLabel;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
p->flags = cwSetFlag(p->flags,kIsBlockingFl);
|
p->flags = cwSetFlag(p->flags,kIsBlockingFl);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -185,6 +201,51 @@ cw::rc_t cw::net::socket::create(
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// if broadcast option was requested.
|
// if broadcast option was requested.
|
||||||
if( cwIsFlag(flags,kBroadcastFl) )
|
if( cwIsFlag(flags,kBroadcastFl) )
|
||||||
{
|
{
|
||||||
@ -196,6 +257,33 @@ cw::rc_t cw::net::socket::create(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// create the local address
|
||||||
|
if((rc = _initAddr(p, NULL, port, &p->sockaddr )) != kOkRC )
|
||||||
|
goto errLabel;
|
||||||
|
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if a remote addr was given connect this socket to it
|
||||||
|
if( remoteAddr != NULL )
|
||||||
|
if((rc = _connect(p,remoteAddr,remotePort)) != kOkRC )
|
||||||
|
goto errLabel;
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
errLabel:
|
errLabel:
|
||||||
if(rc != kOkRC )
|
if(rc != kOkRC )
|
||||||
_destroy(p);
|
_destroy(p);
|
||||||
@ -220,6 +308,82 @@ cw::rc_t cw::net::socket::destroy( handle_t& hRef )
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
printf("Connect:%s\n",s);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
errLabel:
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
cw::rc_t cw::net::socket::connect( handle_t h, const char* remoteAddr, portNumber_t remotePort )
|
cw::rc_t cw::net::socket::connect( handle_t h, const char* remoteAddr, portNumber_t remotePort )
|
||||||
{
|
{
|
||||||
socket_t* p = _handleToPtr(h);
|
socket_t* p = _handleToPtr(h);
|
||||||
@ -232,7 +396,7 @@ cw::rc_t cw::net::socket::send( handle_t h, const void* data, unsigned dataByteC
|
|||||||
errno = 0;
|
errno = 0;
|
||||||
|
|
||||||
if( cwIsFlag(p->flags,kIsConnectedFl) == false )
|
if( cwIsFlag(p->flags,kIsConnectedFl) == false )
|
||||||
return cwLogError(kInvalidOpRC,"cmUdpSend() only works with connected sockets.");
|
return cwLogError(kInvalidOpRC,"socket::send() only works with connected sockets.");
|
||||||
|
|
||||||
if( ::send( p->sockH, data, dataByteCnt, 0 ) == cwSOCKET_SYS_ERR )
|
if( ::send( p->sockH, data, dataByteCnt, 0 ) == cwSOCKET_SYS_ERR )
|
||||||
return cwLogSysError(kOpFailRC,errno,"Send failed.");
|
return cwLogSysError(kOpFailRC,errno,"Send failed.");
|
||||||
@ -246,7 +410,7 @@ cw::rc_t cw::net::socket::send( handle_t h, const void* data, unsigned dataByteC
|
|||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
|
||||||
if( sendto(p->sockH, data, dataByteCnt, 0, (struct sockaddr*)remoteAddr, sizeof(*remoteAddr)) == cwSOCKET_SYS_ERR )
|
if( ::sendto(p->sockH, data, dataByteCnt, 0, (struct sockaddr*)remoteAddr, sizeof(*remoteAddr)) == cwSOCKET_SYS_ERR )
|
||||||
return cwLogSysError(kOpFailRC,errno,"Send to remote addr. failed.");
|
return cwLogSysError(kOpFailRC,errno,"Send to remote addr. failed.");
|
||||||
|
|
||||||
return kOkRC;
|
return kOkRC;
|
||||||
@ -276,7 +440,9 @@ cw::rc_t cw::net::socket::recieve( handle_t h, char* data, unsigned dataByteCnt,
|
|||||||
if( recvByteCntRef != NULL )
|
if( recvByteCntRef != NULL )
|
||||||
*recvByteCntRef = 0;
|
*recvByteCntRef = 0;
|
||||||
|
|
||||||
if((retVal = recvfrom(p->sockH, data, dataByteCnt, 0, (struct sockaddr*)fromAddr, &sizeOfRemoteAddr )) == cwSOCKET_SYS_ERR )
|
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 )
|
||||||
return errno == EAGAIN ? kTimeOutRC : cwLogSysError(kOpFailRC,errno,"recvfrom() failed.");
|
return errno == EAGAIN ? kTimeOutRC : cwLogSysError(kOpFailRC,errno,"recvfrom() failed.");
|
||||||
|
|
||||||
if( recvByteCntRef != NULL )
|
if( recvByteCntRef != NULL )
|
||||||
@ -344,6 +510,43 @@ cw::rc_t cw::net::socket::select_recieve(handle_t h, char* buf, unsigned bufByte
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
cw::rc_t cw::net::socket::initAddr( handle_t h, const char* addrStr, portNumber_t portNumber, struct sockaddr_in* retAddrPtr )
|
cw::rc_t cw::net::socket::initAddr( handle_t h, const char* addrStr, portNumber_t portNumber, struct sockaddr_in* retAddrPtr )
|
||||||
{
|
{
|
||||||
|
@ -14,10 +14,16 @@ namespace cw
|
|||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
kNonBlockingFl = 0x00, // create a non-blocking socket
|
kNonBlockingFl = 0x000, // create a non-blocking socket
|
||||||
kBlockingFl = 0x01, // create a blocking socket
|
kBlockingFl = 0x001, // create a blocking socket
|
||||||
kTcpFl = 0x02, // create a TCP socket rather than a UDP socket
|
kTcpFl = 0x002, // create a TCP socket rather than a UDP socket
|
||||||
kBroadcastFl = 0x04
|
kBroadcastFl = 0x004,
|
||||||
|
kReuseAddrFl = 0x008,
|
||||||
|
kReusePortFl = 0x010,
|
||||||
|
kMultiCastTtlFl = 0x020,
|
||||||
|
kMultiCastLoopFl = 0x040,
|
||||||
|
kListenFl = 0x080,
|
||||||
|
kStreamFl = 0x100
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
enum
|
||||||
@ -36,6 +42,13 @@ namespace cw
|
|||||||
|
|
||||||
rc_t destroy( handle_t& hRef );
|
rc_t destroy( handle_t& hRef );
|
||||||
|
|
||||||
|
rc_t join_multicast_group( handle_t h, const char* addr );
|
||||||
|
|
||||||
|
rc_t setTimeOutMs( handle_t h, unsigned timeOutMs );
|
||||||
|
|
||||||
|
// Listen for a connections
|
||||||
|
rc_t accept( handle_t h );
|
||||||
|
|
||||||
// Set a destination address for this socket. Once a destination address is set
|
// Set a destination address for this socket. Once a destination address is set
|
||||||
// the caller may use send() to communicate with the specified remote socket
|
// the caller may use send() to communicate with the specified remote socket
|
||||||
// without having to specify a destination address on each call.
|
// without having to specify a destination address on each call.
|
||||||
@ -64,6 +77,8 @@ namespace cw
|
|||||||
//
|
//
|
||||||
rc_t select_recieve(handle_t h, char* buf, unsigned bufByteCnt, unsigned timeOutMs, unsigned* recvByteCntRef=nullptr, struct sockaddr_in* fromAddr=nullptr );
|
rc_t select_recieve(handle_t h, char* buf, unsigned bufByteCnt, unsigned timeOutMs, unsigned* recvByteCntRef=nullptr, struct sockaddr_in* fromAddr=nullptr );
|
||||||
|
|
||||||
|
//
|
||||||
|
rc_t recv_from(handle_t h, char* buf, unsigned bufByteCnt, unsigned* recvByteCntRef=nullptr, struct sockaddr_in* fromAddr=nullptr );
|
||||||
|
|
||||||
// Prepare a struct sockadddr_in for use with send()
|
// Prepare a struct sockadddr_in for use with send()
|
||||||
rc_t initAddr( handle_t h, const char* addrStr, portNumber_t portNumber, struct sockaddr_in* retAddrPtr );
|
rc_t initAddr( handle_t h, const char* addrStr, portNumber_t portNumber, struct sockaddr_in* retAddrPtr );
|
||||||
|
@ -46,8 +46,17 @@ namespace cw
|
|||||||
socksrv_t* p = static_cast<socksrv_t*>(arg);
|
socksrv_t* p = static_cast<socksrv_t*>(arg);
|
||||||
unsigned rcvByteCnt = 0;
|
unsigned rcvByteCnt = 0;
|
||||||
struct sockaddr_in fromAddr;
|
struct sockaddr_in fromAddr;
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
|
||||||
if( select_recieve(p->sockH, p->recvBuf, p->recvBufByteCnt, p->timeOutMs, &rcvByteCnt, &fromAddr ) == kOkRC )
|
if( p->timeOutMs == 0 )
|
||||||
|
{
|
||||||
|
rc = recv_from(p->sockH, p->recvBuf, p->recvBufByteCnt, &rcvByteCnt, &fromAddr );
|
||||||
|
sleepMs(100);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
rc = select_recieve(p->sockH, p->recvBuf, p->recvBufByteCnt, p->timeOutMs, &rcvByteCnt, &fromAddr );
|
||||||
|
|
||||||
|
if( rc == kOkRC )
|
||||||
if( rcvByteCnt>0 && p->cbFunc != nullptr )
|
if( rcvByteCnt>0 && p->cbFunc != nullptr )
|
||||||
p->cbFunc( p->cbArg, p->recvBuf, rcvByteCnt, &fromAddr );
|
p->cbFunc( p->cbArg, p->recvBuf, rcvByteCnt, &fromAddr );
|
||||||
|
|
||||||
@ -74,7 +83,7 @@ cw::rc_t cw::net::srv::create(
|
|||||||
|
|
||||||
socksrv_t* p = mem::allocZ<socksrv_t>();
|
socksrv_t* p = mem::allocZ<socksrv_t>();
|
||||||
|
|
||||||
if((rc = socket::create( p->sockH, port, socket::kNonBlockingFl, 0, remoteAddr, remotePort )) != kOkRC )
|
if((rc = socket::create( p->sockH, port, flags, timeOutMs, remoteAddr, remotePort )) != kOkRC )
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
|
|
||||||
if((rc = thread::create( p->threadH, _threadFunc, p )) != kOkRC )
|
if((rc = thread::create( p->threadH, _threadFunc, p )) != kOkRC )
|
||||||
|
@ -7,7 +7,7 @@ namespace cw
|
|||||||
{
|
{
|
||||||
namespace srv
|
namespace srv
|
||||||
{
|
{
|
||||||
typedef void (*cbFunc_t)( void* cbArg, const char* data, unsigned dataByteCnt, const struct sockaddr_in* fromAddr );
|
typedef void (*cbFunc_t)( void* cbArg, const void* data, unsigned dataByteCnt, const struct sockaddr_in* fromAddr );
|
||||||
typedef handle< struct socksrv_str > handle_t;
|
typedef handle< struct socksrv_str > handle_t;
|
||||||
|
|
||||||
rc_t create( handle_t& hRef, //
|
rc_t create( handle_t& hRef, //
|
||||||
|
@ -24,9 +24,12 @@ namespace cw
|
|||||||
handle_t sockH;
|
handle_t sockH;
|
||||||
thread::handle_t threadH;
|
thread::handle_t threadH;
|
||||||
unsigned cbN;
|
unsigned cbN;
|
||||||
|
bool serverFl;
|
||||||
|
bool readyFl;
|
||||||
|
bool connectedFl;
|
||||||
} app_t;
|
} app_t;
|
||||||
|
|
||||||
bool _threadFunc( void* arg )
|
bool _dgramThreadFunc( void* arg )
|
||||||
{
|
{
|
||||||
rc_t rc;
|
rc_t rc;
|
||||||
app_t* app = static_cast<app_t*>(arg);
|
app_t* app = static_cast<app_t*>(arg);
|
||||||
@ -50,6 +53,57 @@ namespace cw
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool _tcpStreamThreadFunc( void* arg )
|
||||||
|
{
|
||||||
|
rc_t rc;
|
||||||
|
app_t* app = static_cast<app_t*>(arg);
|
||||||
|
char buf[ app->recvBufByteN ];
|
||||||
|
unsigned recvBufByteN = 0;
|
||||||
|
|
||||||
|
if( !app->serverFl )
|
||||||
|
{
|
||||||
|
// the client node has nothing to do because it does not receive (it only sends)
|
||||||
|
sleepMs(50);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( app->connectedFl == false )
|
||||||
|
{
|
||||||
|
if((rc = accept( app->sockH )) == kOkRC )
|
||||||
|
{
|
||||||
|
app->connectedFl = true;
|
||||||
|
printf("Server connected.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if((rc = recieve( app->sockH, buf, app->recvBufByteN, &recvBufByteN, nullptr )) == kOkRC )
|
||||||
|
{
|
||||||
|
// if the server disconnects then recvBufByteN
|
||||||
|
if( recvBufByteN==0 )
|
||||||
|
{
|
||||||
|
app->connectedFl = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("%i %s\n", recvBufByteN, buf );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// count the number of callbacks
|
||||||
|
app->cbN += 1;
|
||||||
|
if( app->cbN % 10 == 0)
|
||||||
|
{
|
||||||
|
// print '+' when the server is not connected.
|
||||||
|
printf("%s", app->serverFl && app->connectedFl == false ? "+" : ".");
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -68,7 +122,7 @@ cw::rc_t cw::net::socket::test( portNumber_t localPort, const char* remoteAddr,
|
|||||||
if((rc = create(app.sockH,localPort, kBlockingFl,timeOutMs, NULL, kInvalidPortNumber )) != kOkRC )
|
if((rc = create(app.sockH,localPort, kBlockingFl,timeOutMs, NULL, kInvalidPortNumber )) != kOkRC )
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
if((rc = thread::create( app.threadH, _threadFunc, &app )) != kOkRC )
|
if((rc = thread::create( app.threadH, _dgramThreadFunc, &app )) != kOkRC )
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
|
|
||||||
if((rc = thread::unpause( app.threadH )) != kOkRC )
|
if((rc = thread::unpause( app.threadH )) != kOkRC )
|
||||||
@ -95,6 +149,87 @@ cw::rc_t cw::net::socket::test( portNumber_t localPort, const char* remoteAddr,
|
|||||||
return rcSelect(rc,rc0,rc1);
|
return rcSelect(rc,rc0,rc1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
cw::rc_t cw::net::socket::test_tcp( portNumber_t localPort, const char* remoteAddr, portNumber_t remotePort, bool dgramFl, bool serverFl )
|
||||||
|
{
|
||||||
|
rc_t rc;
|
||||||
|
unsigned timeOutMs = 100;
|
||||||
|
const unsigned sbufN = 31;
|
||||||
|
char sbuf[ sbufN+1 ];
|
||||||
|
app_t app;
|
||||||
|
bool streamFl = !dgramFl;
|
||||||
|
bool clientFl = !serverFl;
|
||||||
|
unsigned flags = kTcpFl | kBlockingFl;
|
||||||
|
|
||||||
|
app.cbN = 0;
|
||||||
|
app.recvBufByteN = sbufN+1;
|
||||||
|
app.serverFl = serverFl;
|
||||||
|
app.readyFl = false;
|
||||||
|
app.connectedFl = false;
|
||||||
|
|
||||||
|
if( serverFl && streamFl )
|
||||||
|
flags |= kListenFl;
|
||||||
|
|
||||||
|
if( streamFl )
|
||||||
|
flags |= kStreamFl;
|
||||||
|
|
||||||
|
// create the socket
|
||||||
|
if((rc = create(app.sockH,localPort, flags,timeOutMs, NULL, kInvalidPortNumber )) != kOkRC )
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
// create the listening thread (which is really only used by the server)
|
||||||
|
if((rc = thread::create( app.threadH, streamFl ? _tcpStreamThreadFunc : _dgramThreadFunc, &app )) != kOkRC )
|
||||||
|
goto errLabel;
|
||||||
|
|
||||||
|
// if this is the client then connect to the server (which must have already been started)
|
||||||
|
if( streamFl && clientFl )
|
||||||
|
{
|
||||||
|
if((rc = connect(app.sockH,remoteAddr,remotePort)) != kOkRC )
|
||||||
|
goto errLabel;
|
||||||
|
|
||||||
|
app.connectedFl = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Starting node ....\n");
|
||||||
|
|
||||||
|
// start the thread
|
||||||
|
if((rc = thread::unpause( app.threadH )) != kOkRC )
|
||||||
|
goto errLabel;
|
||||||
|
|
||||||
|
|
||||||
|
while( true )
|
||||||
|
{
|
||||||
|
printf("? ");
|
||||||
|
if( std::fgets(sbuf,sbufN,stdin) == sbuf )
|
||||||
|
{
|
||||||
|
if( strcmp(sbuf,"quit\n") == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// when using streams only the client can send
|
||||||
|
if( streamFl & clientFl )
|
||||||
|
{
|
||||||
|
printf("Sending:%s",sbuf);
|
||||||
|
send(app.sockH, sbuf, strlen(sbuf)+1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
// when using dgrams the dest. address is need to send
|
||||||
|
if( dgramFl )
|
||||||
|
{
|
||||||
|
printf("Sending:%s",sbuf);
|
||||||
|
send(app.sockH, sbuf, strlen(sbuf)+1, remoteAddr, remotePort);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
errLabel:
|
||||||
|
rc_t rc0 = thread::destroy(app.threadH);
|
||||||
|
|
||||||
|
rc_t rc1 = destroy(app.sockH);
|
||||||
|
|
||||||
|
return rcSelect(rc,rc0,rc1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
namespace cw
|
namespace cw
|
||||||
{
|
{
|
||||||
namespace net
|
namespace net
|
||||||
@ -107,13 +242,13 @@ namespace cw
|
|||||||
unsigned cbN;
|
unsigned cbN;
|
||||||
} app_t;
|
} app_t;
|
||||||
|
|
||||||
void srvRecieveCallback( void* arg, const char* data, unsigned dataByteCnt, const struct sockaddr_in* fromAddr )
|
void srvRecieveCallback( void* arg, const void* data, unsigned dataByteCnt, const struct sockaddr_in* fromAddr )
|
||||||
{
|
{
|
||||||
app_t* p = static_cast<app_t*>(arg);
|
app_t* p = static_cast<app_t*>(arg);
|
||||||
char addrBuf[ INET_ADDRSTRLEN ];
|
char addrBuf[ INET_ADDRSTRLEN ];
|
||||||
socket::addrToString( fromAddr, addrBuf, INET_ADDRSTRLEN );
|
socket::addrToString( fromAddr, addrBuf, INET_ADDRSTRLEN );
|
||||||
p->cbN += 1;
|
p->cbN += 1;
|
||||||
printf("%i %s %s", p->cbN, addrBuf, data );
|
printf("%i %s %s", p->cbN, addrBuf, (const char*)data );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -153,3 +288,6 @@ cw::rc_t cw::net::srv::test( socket::portNumber_t localPort, const char* remoteA
|
|||||||
|
|
||||||
return rcSelect(rc,rc0);
|
return rcSelect(rc,rc0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -8,11 +8,13 @@ namespace cw
|
|||||||
namespace socket
|
namespace socket
|
||||||
{
|
{
|
||||||
rc_t test( portNumber_t localPort, const char* remoteAddr, portNumber_t remotePort );
|
rc_t test( portNumber_t localPort, const char* remoteAddr, portNumber_t remotePort );
|
||||||
|
rc_t test_tcp( portNumber_t localPort, const char* remoteAddr, portNumber_t remotePort, bool dgramFl, bool serverFl );
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace srv
|
namespace srv
|
||||||
{
|
{
|
||||||
rc_t test( socket::portNumber_t localPort, const char* remoteAddr, socket::portNumber_t remotePort );
|
rc_t test( socket::portNumber_t localPort, const char* remoteAddr, socket::portNumber_t remotePort );
|
||||||
|
rc_t mdns_test();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user