Many changes and additions to cwTcpSocket* to support MDNS and DNS-SD operations.
This commit is contained in:
parent
be439a8331
commit
b53383f6c3
245
cwTcpSocket.cpp
245
cwTcpSocket.cpp
@ -37,6 +37,7 @@ namespace cw
|
|||||||
{
|
{
|
||||||
int sockH;
|
int sockH;
|
||||||
int fdH;
|
int fdH;
|
||||||
|
unsigned createFlags;
|
||||||
unsigned flags;
|
unsigned flags;
|
||||||
unsigned recvBufByteCnt;
|
unsigned recvBufByteCnt;
|
||||||
struct sockaddr_in sockaddr;
|
struct sockaddr_in sockaddr;
|
||||||
@ -141,6 +142,60 @@ namespace cw
|
|||||||
errLabel:
|
errLabel:
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -152,15 +207,17 @@ cw::rc_t cw::net::socket::create(
|
|||||||
unsigned flags,
|
unsigned flags,
|
||||||
unsigned timeOutMs,
|
unsigned timeOutMs,
|
||||||
const char* remoteAddr,
|
const char* remoteAddr,
|
||||||
portNumber_t remotePort )
|
portNumber_t remotePort,
|
||||||
|
const char* localAddr)
|
||||||
{
|
{
|
||||||
rc_t rc;
|
rc_t rc;
|
||||||
if((rc = destroy(hRef)) != kOkRC )
|
if((rc = destroy(hRef)) != kOkRC )
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
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;
|
p->fdH = cwSOCKET_NULL_SOCK;
|
||||||
|
p->createFlags = flags;
|
||||||
|
|
||||||
int type = cwIsFlag(flags,kStreamFl) ? SOCK_STREAM : SOCK_DGRAM;
|
int type = cwIsFlag(flags,kStreamFl) ? SOCK_STREAM : SOCK_DGRAM;
|
||||||
int protocol = cwIsFlag(flags,kTcpFl) ? 0 : IPPROTO_UDP;
|
int protocol = cwIsFlag(flags,kTcpFl) ? 0 : IPPROTO_UDP;
|
||||||
@ -259,11 +316,10 @@ cw::rc_t cw::net::socket::create(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// create the local address
|
// create the 32 bit local address
|
||||||
if((rc = _initAddr(p, NULL, port, &p->sockaddr )) != kOkRC )
|
if((rc = _initAddr(p, localAddr, port, &p->sockaddr )) != kOkRC )
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
|
|
||||||
|
|
||||||
// bind the socket to a local address/port
|
// bind the socket to a local address/port
|
||||||
if( (bind( p->sockH, (struct sockaddr*)&p->sockaddr, sizeof(p->sockaddr))) == cwSOCKET_SYS_ERR )
|
if( (bind( p->sockH, (struct sockaddr*)&p->sockaddr, sizeof(p->sockaddr))) == cwSOCKET_SYS_ERR )
|
||||||
{
|
{
|
||||||
@ -271,6 +327,11 @@ cw::rc_t cw::net::socket::create(
|
|||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get the local address as a string
|
||||||
|
if((rc = addrToString( &p->sockaddr, p->ntopBuf, sizeof(p->ntopBuf) )) != kOkRC )
|
||||||
|
goto errLabel;
|
||||||
|
|
||||||
|
|
||||||
// if a remote addr was given connect this socket to it
|
// if a remote addr was given connect this socket to it
|
||||||
if( remoteAddr != NULL )
|
if( remoteAddr != NULL )
|
||||||
if((rc = _connect(p,remoteAddr,remotePort)) != kOkRC )
|
if((rc = _connect(p,remoteAddr,remotePort)) != kOkRC )
|
||||||
@ -310,6 +371,12 @@ cw::rc_t cw::net::socket::destroy( handle_t& hRef )
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned cw::net::socket::flags( handle_t h )
|
||||||
|
{
|
||||||
|
socket_t* p = _handleToPtr(h);
|
||||||
|
return p->createFlags;
|
||||||
|
}
|
||||||
|
|
||||||
cw::rc_t cw::net::socket::set_multicast_time_to_live( handle_t h, unsigned seconds )
|
cw::rc_t cw::net::socket::set_multicast_time_to_live( handle_t h, unsigned seconds )
|
||||||
{
|
{
|
||||||
rc_t rc = kOkRC;
|
rc_t rc = kOkRC;
|
||||||
@ -392,8 +459,19 @@ cw::rc_t cw::net::socket::accept( handle_t h )
|
|||||||
|
|
||||||
p->flags = cwSetFlag(p->flags,kIsConnectedFl);
|
p->flags = cwSetFlag(p->flags,kIsConnectedFl);
|
||||||
|
|
||||||
printf("Connect:%s\n",s);
|
/*
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
errLabel:
|
errLabel:
|
||||||
@ -453,7 +531,7 @@ cw::rc_t cw::net::socket::send( handle_t h, const void* data, unsigned dataByteC
|
|||||||
return send( h, data, dataByteCnt, &addr );
|
return send( h, data, dataByteCnt, &addr );
|
||||||
}
|
}
|
||||||
|
|
||||||
cw::rc_t cw::net::socket::recieve( handle_t h, char* data, unsigned dataByteCnt, unsigned* recvByteCntRef, struct sockaddr_in* fromAddr )
|
cw::rc_t cw::net::socket::receive( handle_t h, char* data, unsigned dataByteCnt, unsigned* recvByteCntRef, struct sockaddr_in* fromAddr )
|
||||||
{
|
{
|
||||||
socket_t* p = _handleToPtr(h);
|
socket_t* p = _handleToPtr(h);
|
||||||
rc_t rc = kOkRC;
|
rc_t rc = kOkRC;
|
||||||
@ -468,13 +546,20 @@ cw::rc_t cw::net::socket::recieve( handle_t h, char* data, unsigned dataByteCnt,
|
|||||||
int fd = p->fdH != cwSOCKET_NULL_SOCK ? p->fdH : p->sockH;
|
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 )
|
if((retVal = recvfrom(fd, data, dataByteCnt, 0, (struct sockaddr*)fromAddr, &sizeOfRemoteAddr )) == cwSOCKET_SYS_ERR )
|
||||||
return errno == EAGAIN ? kTimeOutRC : cwLogSysError(kOpFailRC,errno,"recvfrom() failed.");
|
|
||||||
|
|
||||||
|
|
||||||
// if the read 0 bytes but did not time out this probably means that it was disconnected
|
|
||||||
if( retVal == 0 )
|
|
||||||
{
|
{
|
||||||
//p->flags = cwClrFlag(p->flags,kIsConnectedFl);
|
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.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if( recvByteCntRef != NULL )
|
if( recvByteCntRef != NULL )
|
||||||
@ -483,7 +568,7 @@ cw::rc_t cw::net::socket::recieve( handle_t h, char* data, unsigned dataByteCnt,
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
cw::rc_t cw::net::socket::select_recieve(handle_t h, char* buf, unsigned bufByteCnt, unsigned timeOutMs, unsigned* recvByteCntRef, struct sockaddr_in* fromAddr )
|
cw::rc_t cw::net::socket::select_receive(handle_t h, char* buf, unsigned bufByteCnt, unsigned timeOutMs, unsigned* recvByteCntRef, struct sockaddr_in* fromAddr )
|
||||||
{
|
{
|
||||||
rc_t rc = kOkRC;
|
rc_t rc = kOkRC;
|
||||||
socket_t* p = _handleToPtr(h);
|
socket_t* p = _handleToPtr(h);
|
||||||
@ -510,6 +595,7 @@ cw::rc_t cw::net::socket::select_recieve(handle_t h, char* buf, unsigned bufByte
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 0: // select() timed out
|
case 0: // select() timed out
|
||||||
|
rc = kTimeOutRC;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1: // (> 0) count of ready descripters
|
case 1: // (> 0) count of ready descripters
|
||||||
@ -522,7 +608,19 @@ cw::rc_t cw::net::socket::select_recieve(handle_t h, char* buf, unsigned bufByte
|
|||||||
|
|
||||||
// recv the incoming msg into buf[]
|
// recv the incoming msg into buf[]
|
||||||
if(( retByteCnt = recvfrom( p->sockH, buf, bufByteCnt, 0, (struct sockaddr*)fromAddr, &addrByteCnt )) == cwSOCKET_SYS_ERR )
|
if(( retByteCnt = recvfrom( p->sockH, buf, bufByteCnt, 0, (struct sockaddr*)fromAddr, &addrByteCnt )) == cwSOCKET_SYS_ERR )
|
||||||
|
{
|
||||||
|
switch( errno )
|
||||||
|
{
|
||||||
|
case ECONNRESET:
|
||||||
|
if( cwIsFlag(p->flags,kIsConnectedFl) )
|
||||||
|
cwLogWarning("Socket Disconnected.");
|
||||||
|
p->flags = cwClrFlag(p->flags,kIsConnectedFl);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
rc = cwLogSysError(kOpFailRC,errno,"recvfrom() failed.");
|
rc = cwLogSysError(kOpFailRC,errno,"recvfrom() failed.");
|
||||||
|
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// check for overflow
|
// check for overflow
|
||||||
@ -579,52 +677,10 @@ cw::rc_t cw::net::socket::recv_from(handle_t h, char* buf, unsigned bufByteCnt,
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
cw::rc_t cw::net::socket::get_mac( handle_t h, unsigned char outBuf[6], const char* interfaceName )
|
cw::rc_t cw::net::socket::get_mac( handle_t h, unsigned char outBuf[6], struct sockaddr_in* addr, const char* netInterfaceName )
|
||||||
{
|
{
|
||||||
cw::rc_t rc = kOkRC;
|
socket_t* p = _handleToPtr(h);
|
||||||
socket_t* p = _handleToPtr(h);
|
return _get_info(p->sockH, outBuf, addr, netInterfaceName );
|
||||||
struct ifreq ifr;
|
|
||||||
struct ifconf ifc;
|
|
||||||
char buf[1024];
|
|
||||||
|
|
||||||
ifc.ifc_len = sizeof(buf);
|
|
||||||
ifc.ifc_buf = buf;
|
|
||||||
|
|
||||||
if (ioctl(p->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(p->sockH, SIOCGIFFLAGS, &ifr) != 0)
|
|
||||||
{
|
|
||||||
rc = cwLogSysError(kOpFailRC,errno,"ioctl(SIOCGIFCONF) failed.");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (! (ifr.ifr_flags & IFF_LOOPBACK))
|
|
||||||
{
|
|
||||||
// don't count loopback
|
|
||||||
if (ioctl(p->sockH, SIOCGIFHWADDR, &ifr) == 0)
|
|
||||||
{
|
|
||||||
memcpy(outBuf, ifr.ifr_hwaddr.sa_data, 6);
|
|
||||||
return kOkRC;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return cwLogError(kInvalidArgRC,"The MAC address of interface '%s' could not be found.", interfaceName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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 )
|
||||||
@ -633,18 +689,21 @@ cw::rc_t cw::net::socket::initAddr( handle_t h, const char* addrStr, portNumber_
|
|||||||
return _initAddr(p,addrStr,portNumber,retAddrPtr);
|
return _initAddr(p,addrStr,portNumber,retAddrPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* cw::net::socket::addrToString( const struct sockaddr_in* addr, char* buf, unsigned bufN )
|
cw::rc_t cw::net::socket::addrToString( const struct sockaddr_in* addr, char* buf, unsigned bufN )
|
||||||
{
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
|
||||||
if( inet_ntop(AF_INET, &(addr->sin_addr), buf, bufN) == NULL)
|
if( inet_ntop(AF_INET, &(addr->sin_addr), buf, bufN) == NULL)
|
||||||
{
|
{
|
||||||
cwLogSysError(kOpFailRC,errno, "Network address to string conversion failed." );
|
rc = cwLogSysError(kOpFailRC,errno, "Network address to string conversion failed." );
|
||||||
return NULL;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
buf[bufN-1]=0;
|
buf[bufN-1]=0;
|
||||||
return buf;
|
errLabel:
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cw::net::socket::addrIsEqual( const struct sockaddr_in* a0, const struct sockaddr_in* a1 )
|
bool cw::net::socket::addrIsEqual( const struct sockaddr_in* a0, const struct sockaddr_in* a1 )
|
||||||
@ -662,10 +721,64 @@ const char* cw::net::socket::hostName( handle_t h )
|
|||||||
|
|
||||||
if( gethostname(p->hnameBuf,HOST_NAME_MAX) != 0 )
|
if( gethostname(p->hnameBuf,HOST_NAME_MAX) != 0 )
|
||||||
{
|
{
|
||||||
cwLogSysError(kOpFailRC,errno, "gethostname() failed." );
|
cwLogSysError(kOpFailRC,errno, "gethostname() failed." );
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
p->hnameBuf[HOST_NAME_MAX] = 0;
|
p->hnameBuf[HOST_NAME_MAX] = 0;
|
||||||
return p->hnameBuf;
|
return p->hnameBuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
@ -23,7 +23,7 @@ namespace cw
|
|||||||
kMultiCastTtlFl = 0x020,
|
kMultiCastTtlFl = 0x020,
|
||||||
kMultiCastLoopFl = 0x040,
|
kMultiCastLoopFl = 0x040,
|
||||||
kListenFl = 0x080,
|
kListenFl = 0x080,
|
||||||
kStreamFl = 0x100
|
kStreamFl = 0x100, // connected stream (not Datagram)
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
enum
|
||||||
@ -38,10 +38,13 @@ namespace cw
|
|||||||
unsigned flags,
|
unsigned flags,
|
||||||
unsigned timeOutMs = 100, // time out to use with recv() on blocking sockets
|
unsigned timeOutMs = 100, // time out to use with recv() on blocking sockets
|
||||||
const char* remoteAddr = NULL,
|
const char* remoteAddr = NULL,
|
||||||
portNumber_t remotePort = socket::kInvalidPortNumber );
|
portNumber_t remotePort = socket::kInvalidPortNumber,
|
||||||
|
const char* localAddr = NULL );
|
||||||
|
|
||||||
rc_t destroy( handle_t& hRef );
|
rc_t destroy( handle_t& hRef );
|
||||||
|
|
||||||
|
unsigned flags( handle_t h );
|
||||||
|
|
||||||
rc_t set_multicast_time_to_live( handle_t h, unsigned seconds );
|
rc_t set_multicast_time_to_live( handle_t h, unsigned seconds );
|
||||||
|
|
||||||
rc_t join_multicast_group( handle_t h, const char* addr );
|
rc_t join_multicast_group( handle_t h, const char* addr );
|
||||||
@ -77,26 +80,31 @@ namespace cw
|
|||||||
// return immediately if no incoming messages are waiting. If
|
// return immediately if no incoming messages are waiting. If
|
||||||
// recvByteCntRef is valid (non-NULL) then it is set to the
|
// recvByteCntRef is valid (non-NULL) then it is set to the
|
||||||
// length of the received message or 0 if no msg was received.
|
// length of the received message or 0 if no msg was received.
|
||||||
rc_t recieve(handle_t h, char* data, unsigned dataByteCnt, unsigned* recvByteCntRef=nullptr, struct sockaddr_in* fromAddr=nullptr );
|
rc_t receive(handle_t h, char* data, unsigned dataByteCnt, 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 select_receive(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 );
|
rc_t recv_from(handle_t h, char* buf, unsigned bufByteCnt, unsigned* recvByteCntRef=nullptr, struct sockaddr_in* fromAddr=nullptr );
|
||||||
|
|
||||||
// Note that
|
// Note that
|
||||||
rc_t get_mac( handle_t h, unsigned char buf[6], const char* interfaceName=nullptr );
|
rc_t get_mac( handle_t h, unsigned char buf[6], struct sockaddr_in* addr=nullptr, const char* netInterfaceName=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 );
|
||||||
|
|
||||||
const char* addrToString( const struct sockaddr_in* addr, char* buf, unsigned bufN=INET_ADDRSTRLEN );
|
rc_t addrToString( const struct sockaddr_in* addr, char* buf, unsigned bufN=INET_ADDRSTRLEN );
|
||||||
|
|
||||||
bool addrIsEqual( const struct sockaddr_in* addr0, const struct sockaddr_in* addr1 );
|
bool addrIsEqual( const struct sockaddr_in* addr0, const struct sockaddr_in* addr1 );
|
||||||
|
|
||||||
const char* hostName( handle_t h );
|
const char* hostName( handle_t h );
|
||||||
|
const char* ipAddress( handle_t h );
|
||||||
|
unsigned inetAddress( handle_t h );
|
||||||
|
portNumber_t port( handle_t h );
|
||||||
|
rc_t peername( handle_t h, struct sockaddr_in* addr );
|
||||||
|
|
||||||
|
rc_t get_info( const char* netInterfaceName, unsigned char mac[6], char* hostBuf=nullptr, unsigned hostBufN=_POSIX_HOST_NAME_MAX, struct sockaddr_in* addr=nullptr );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@ namespace cw
|
|||||||
unsigned timeOutMs;
|
unsigned timeOutMs;
|
||||||
char* recvBuf;
|
char* recvBuf;
|
||||||
unsigned recvBufByteCnt;
|
unsigned recvBufByteCnt;
|
||||||
|
unsigned flags;
|
||||||
} socksrv_t;
|
} socksrv_t;
|
||||||
|
|
||||||
inline socksrv_t* _handleToPtr( handle_t h ) { return handleToPtr<handle_t,socksrv_t>(h); }
|
inline socksrv_t* _handleToPtr( handle_t h ) { return handleToPtr<handle_t,socksrv_t>(h); }
|
||||||
@ -43,23 +44,44 @@ namespace cw
|
|||||||
|
|
||||||
bool _threadFunc( void* arg )
|
bool _threadFunc( void* arg )
|
||||||
{
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
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( p->timeOutMs == 0 )
|
|
||||||
|
if( cwIsFlag(p->flags,kUseAcceptFl) && socket::isConnected(p->sockH)==false )
|
||||||
{
|
{
|
||||||
rc = recv_from(p->sockH, p->recvBuf, p->recvBufByteCnt, &rcvByteCnt, &fromAddr );
|
rc = socket::accept( p->sockH );
|
||||||
sleepMs(100);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
rc = select_recieve(p->sockH, p->recvBuf, p->recvBufByteCnt, p->timeOutMs, &rcvByteCnt, &fromAddr );
|
{
|
||||||
|
// if this is a TCP socket that is not connected
|
||||||
if( rc == kOkRC )
|
if( cwIsFlag(socket::flags( p->sockH),socket::kTcpFl) && socket::isConnected(p->sockH) == false )
|
||||||
if( rcvByteCnt>0 && p->cbFunc != nullptr )
|
{
|
||||||
p->cbFunc( p->cbArg, p->recvBuf, rcvByteCnt, &fromAddr );
|
sleepMs(p->timeOutMs);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// this is a connected TCP socket or UDP socket
|
||||||
|
if( cwIsFlag(p->flags,kUseRecvFromFl) )
|
||||||
|
{
|
||||||
|
rc = recv_from(p->sockH, p->recvBuf, p->recvBufByteCnt, &rcvByteCnt, &fromAddr );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rc = select_receive(p->sockH, p->recvBuf, p->recvBufByteCnt, p->timeOutMs, &rcvByteCnt, &fromAddr );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( (p->cbFunc != nullptr) && ((rc == kOkRC && rcvByteCnt>0) || (cwIsFlag(p->flags,kRecvTimeOutFl) && rc == kTimeOutRC)))
|
||||||
|
{
|
||||||
|
void* buf = rc == kTimeOutRC ? nullptr : p->recvBuf;
|
||||||
|
unsigned n = rc == kTimeOutRC ? 0 : rcvByteCnt;
|
||||||
|
struct sockaddr_in* addr = rc == kTimeOutRC ? nullptr : &fromAddr;
|
||||||
|
p->cbFunc( p->cbArg, buf, n, addr );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -70,12 +92,14 @@ cw::rc_t cw::net::srv::create(
|
|||||||
handle_t& hRef,
|
handle_t& hRef,
|
||||||
socket::portNumber_t port,
|
socket::portNumber_t port,
|
||||||
unsigned flags,
|
unsigned flags,
|
||||||
|
unsigned srvFlags,
|
||||||
cbFunc_t cbFunc,
|
cbFunc_t cbFunc,
|
||||||
void* cbArg,
|
void* cbArg,
|
||||||
unsigned recvBufByteCnt,
|
unsigned recvBufByteCnt,
|
||||||
unsigned timeOutMs,
|
unsigned timeOutMs,
|
||||||
const char* remoteAddr,
|
const char* remoteAddr,
|
||||||
socket::portNumber_t remotePort )
|
socket::portNumber_t remotePort,
|
||||||
|
const char* localAddr)
|
||||||
{
|
{
|
||||||
rc_t rc;
|
rc_t rc;
|
||||||
if((rc = destroy(hRef)) != kOkRC )
|
if((rc = destroy(hRef)) != kOkRC )
|
||||||
@ -83,16 +107,18 @@ 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, flags, timeOutMs, remoteAddr, remotePort )) != kOkRC )
|
if((rc = socket::create( p->sockH, port, flags, timeOutMs, remoteAddr, remotePort, localAddr )) != kOkRC )
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
|
|
||||||
if((rc = thread::create( p->threadH, _threadFunc, p )) != kOkRC )
|
if((rc = thread::create( p->threadH, _threadFunc, p )) != kOkRC )
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
|
|
||||||
|
p->flags = srvFlags;
|
||||||
p->recvBuf = mem::allocZ<char>( recvBufByteCnt );
|
p->recvBuf = mem::allocZ<char>( recvBufByteCnt );
|
||||||
p->recvBufByteCnt = recvBufByteCnt;
|
p->recvBufByteCnt = recvBufByteCnt;
|
||||||
p->cbFunc = cbFunc;
|
p->cbFunc = cbFunc;
|
||||||
p->cbArg = cbArg;
|
p->cbArg = cbArg;
|
||||||
|
p->timeOutMs = timeOutMs;
|
||||||
|
|
||||||
errLabel:
|
errLabel:
|
||||||
if( rc == kOkRC )
|
if( rc == kOkRC )
|
||||||
|
@ -10,15 +10,24 @@ namespace cw
|
|||||||
typedef void (*cbFunc_t)( void* cbArg, const void* 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;
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
kUseAcceptFl = 0x01, // wait for a connection
|
||||||
|
kUseRecvFromFl = 0x02, // use socket::recv_from
|
||||||
|
kRecvTimeOutFl = 0x04, // Generate empty receive callbacks on receive timeouts
|
||||||
|
};
|
||||||
|
|
||||||
rc_t create( handle_t& hRef, //
|
rc_t create( handle_t& hRef, //
|
||||||
socket::portNumber_t port, // local port number
|
socket::portNumber_t port, // local port number
|
||||||
unsigned flags, // see socket::flags
|
unsigned flags, // see socket::flags
|
||||||
|
unsigned srvFlags, //
|
||||||
cbFunc_t cbFunc, // callback for received messages
|
cbFunc_t cbFunc, // callback for received messages
|
||||||
void* cbArg, // callback arg
|
void* cbArg, // callback arg
|
||||||
unsigned recvBufByteCnt = 1024,// recieve buffer size
|
unsigned recvBufByteCnt = 1024,// recieve buffer size
|
||||||
unsigned timeOutMs = 100, // time out to use with recv() on thread select()
|
unsigned timeOutMs = 100, // time out to use with recv() on thread select()
|
||||||
const char* remoteAddr = NULL,
|
const char* remoteAddr = NULL,
|
||||||
socket::portNumber_t remotePort = socket::kInvalidPortNumber );
|
socket::portNumber_t remotePort = socket::kInvalidPortNumber,
|
||||||
|
const char* localAddr = NULL);
|
||||||
|
|
||||||
rc_t destroy( handle_t& hRef );
|
rc_t destroy( handle_t& hRef );
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ namespace cw
|
|||||||
char buf[ app->recvBufByteN ];
|
char buf[ app->recvBufByteN ];
|
||||||
unsigned recvBufByteN = 0;
|
unsigned recvBufByteN = 0;
|
||||||
|
|
||||||
if((rc = recieve( app->sockH, buf, app->recvBufByteN, &recvBufByteN, &fromAddr )) == kOkRC )
|
if((rc = receive( app->sockH, buf, app->recvBufByteN, &recvBufByteN, &fromAddr )) == kOkRC )
|
||||||
{
|
{
|
||||||
addrToString( &fromAddr, addrBuf );
|
addrToString( &fromAddr, addrBuf );
|
||||||
printf("%i %s from %s\n", recvBufByteN, buf, addrBuf );
|
printf("%i %s from %s\n", recvBufByteN, buf, addrBuf );
|
||||||
@ -77,7 +77,7 @@ namespace cw
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if((rc = recieve( app->sockH, buf, app->recvBufByteN, &recvBufByteN, nullptr )) == kOkRC )
|
if((rc = receive( app->sockH, buf, app->recvBufByteN, &recvBufByteN, nullptr )) == kOkRC )
|
||||||
{
|
{
|
||||||
// if the server disconnects then recvBufByteN
|
// if the server disconnects then recvBufByteN
|
||||||
if( !isConnected( app->sockH) )
|
if( !isConnected( app->sockH) )
|
||||||
@ -238,19 +238,19 @@ namespace cw
|
|||||||
unsigned cbN;
|
unsigned cbN;
|
||||||
} app_t;
|
} app_t;
|
||||||
|
|
||||||
void srvRecieveCallback( void* arg, const void* data, unsigned dataByteCnt, const struct sockaddr_in* fromAddr )
|
void srvReceiveCallback( 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, (const char*)data );
|
printf("%i %s %s\n", p->cbN, addrBuf, (const char*)data );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cw::rc_t cw::net::srv::test( socket::portNumber_t localPort, const char* remoteAddr, socket::portNumber_t remotePort )
|
cw::rc_t cw::net::srv::test_udp_srv( socket::portNumber_t localPort, const char* remoteAddr, socket::portNumber_t remotePort )
|
||||||
{
|
{
|
||||||
rc_t rc;
|
rc_t rc;
|
||||||
unsigned recvBufByteCnt = 1024;
|
unsigned recvBufByteCnt = 1024;
|
||||||
@ -260,7 +260,17 @@ cw::rc_t cw::net::srv::test( socket::portNumber_t localPort, const char* remoteA
|
|||||||
app_t app;
|
app_t app;
|
||||||
app.cbN = 0;
|
app.cbN = 0;
|
||||||
|
|
||||||
if((rc = srv::create(app.srvH, localPort, socket::kBlockingFl, srvRecieveCallback, &app, recvBufByteCnt, timeOutMs, NULL, socket::kInvalidPortNumber )) != kOkRC )
|
if((rc = srv::create(app.srvH,
|
||||||
|
localPort,
|
||||||
|
socket::kBlockingFl,
|
||||||
|
0,
|
||||||
|
srvReceiveCallback,
|
||||||
|
&app,
|
||||||
|
recvBufByteCnt,
|
||||||
|
timeOutMs,
|
||||||
|
nullptr,
|
||||||
|
socket::kInvalidPortNumber )) != kOkRC )
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
if((rc = srv::start( app.srvH )) != kOkRC )
|
if((rc = srv::start( app.srvH )) != kOkRC )
|
||||||
@ -285,5 +295,50 @@ cw::rc_t cw::net::srv::test( socket::portNumber_t localPort, const char* remoteA
|
|||||||
return rcSelect(rc,rc0);
|
return rcSelect(rc,rc0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cw::rc_t cw::net::srv::test_tcp_srv( socket::portNumber_t localPort, const char* remoteAddr, socket::portNumber_t remotePort )
|
||||||
|
{
|
||||||
|
rc_t rc;
|
||||||
|
unsigned recvBufByteCnt = 1024;
|
||||||
|
unsigned timeOutMs = 100;
|
||||||
|
const unsigned sbufN = 31;
|
||||||
|
char sbuf[ sbufN+1 ];
|
||||||
|
app_t app;
|
||||||
|
app.cbN = 0;
|
||||||
|
|
||||||
|
if((rc = srv::create(app.srvH,
|
||||||
|
localPort,
|
||||||
|
socket::kBlockingFl | socket::kTcpFl | socket::kStreamFl,
|
||||||
|
0,
|
||||||
|
srvReceiveCallback,
|
||||||
|
&app,
|
||||||
|
recvBufByteCnt,
|
||||||
|
timeOutMs,
|
||||||
|
remoteAddr,
|
||||||
|
remotePort )) != kOkRC )
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
if((rc = srv::start( app.srvH )) != kOkRC )
|
||||||
|
goto errLabel;
|
||||||
|
|
||||||
|
while( true )
|
||||||
|
{
|
||||||
|
printf("? ");
|
||||||
|
if( std::fgets(sbuf,sbufN,stdin) == sbuf )
|
||||||
|
{
|
||||||
|
printf("Sending:%s",sbuf);
|
||||||
|
send(app.srvH, sbuf, strlen(sbuf)+1 );
|
||||||
|
|
||||||
|
if( strcmp(sbuf,"quit\n") == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
errLabel:
|
||||||
|
rc_t rc0 = destroy(app.srvH);
|
||||||
|
|
||||||
|
return rcSelect(rc,rc0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -13,7 +13,8 @@ namespace cw
|
|||||||
|
|
||||||
namespace srv
|
namespace srv
|
||||||
{
|
{
|
||||||
rc_t test( socket::portNumber_t localPort, const char* remoteAddr, socket::portNumber_t remotePort );
|
rc_t test_udp_srv( socket::portNumber_t localPort, const char* remoteAddr, socket::portNumber_t remotePort );
|
||||||
|
rc_t test_tcp_srv( socket::portNumber_t localPort, const char* remoteAddr, socket::portNumber_t remotePort );
|
||||||
rc_t mdns_test();
|
rc_t mdns_test();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user