Copyright (C) Kevin Larke 2009-2020

This file is part of libcm.

libcm is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

libcm is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

See the GNU General Public License distributed with the libcm package or look here: .


cmUdpPort : UDP socket interface class.

  #include <netinet/in.h>

enum
{
  kOkUdpRC = cmOkRC,
  kSockCreateFailUdpRC,
  kSockCloseFailUdpRC,
  kSockBindFailUdpRC,
  kSockConnectFailUdpRC,
  kSockOptSetFailUdpRC,
  kSockSendFailUdpRC,
  kSockRecvFailUdpRC,
  kSockSelectFailUdpRC,
  kPtoNFailUdpRC,
  kNtoPFailUdpRC,
  kNotConnectedUdpRC,
  kThreadFailUdpRC,
  kQueueFailUdpRC,
  kRecvBufOverflowUdpRC,
  kBufTooSmallUdpRC,
  kHostNameFailUdpRC,
  kInvalidPortNumbUdpRC,
  kTimeOutUdpRC,
  kTestFailUdpRC
};

typedef cmRC_t         cmUdpRC_t;
typedef cmHandle_t     cmUdpH_t;
typedef unsigned short cmUdpPort_t;

extern cmUdpH_t cmUdpNullHandle;

typedef void (*cmUdpCallback_t)( void* cbArg, const char* data, unsigned dataByteCnt, const struct sockaddr_in* fromAddr ); 

enum
{
  kNonBlockingUdpFl = 0x00,
  kBlockingUdpFl    = 0x01,
  kNoQueueUdpFl     = 0x02,
  kBroadcastUdpFl   = 0x04
  
};

enum
{
  // port 0 is reserved by and is therefore a convenient invalid port number
  kInvalidUdpPortNumber = 0 
};

cmUdpRC_t cmUdpAlloc( cmCtx_t* ctx, cmUdpH_t* hp );
cmUdpRC_t cmUdpFree(  cmUdpH_t* hp );

cmUdpRC_t cmUdpInit( 
cmUdpH_t        h, 
cmUdpPort_t     port,             // this sockets port
unsigned        flags,            // see kXXXUdpFl 
cmUdpCallback_t cbFunc,           // Callback for use w/ cmUdpGetAvailData()
void*           cbArg,            // First arg to cbFunc().
const char*     remoteAddr,       // Remote addr to bind this socket to (or NULL).
cmUdpPort_t     remotePort,       // Remote port to use with remoteAddr.
unsigned        recvBufByteCnt,   // Size of the internal receive buffer in bytes. Size of the internal queue and msg receive buffer. No single msg can exceed this size. 
unsigned        timeOutMs );      // Receive time-out in milliseconds

cmUdpRC_t cmUdpFinal( cmUdpH_t h );
bool      cmUdpIsValid( cmUdpH_t h );

// This function may not return a useful value until the 
// socket has gone into 'listen' mode.
const struct sockaddr_in* cmUdpLocalAddr( cmUdpH_t h );

// Set a destination address for this socket. Once a destination address is set
// the caller may use cmUdpSend() to communicate with the specified remote socket
// without having to specify an destination address on each call.
cmUdpRC_t cmUdpConnect( cmUdpH_t h, const char* remoteAddr, cmUdpPort_t remotePort );

// Send a message to a remote UDP socket. Use the function cmUdpInitAddr() to setup 
// the 'sockaddr_in' arg. for cmUdpSendTo().
cmUdpRC_t cmUdpSend(    cmUdpH_t h, const char* data, unsigned dataByteCnt );
cmUdpRC_t cmUdpSendTo(  cmUdpH_t h, const char* data, unsigned dataByteCnt, const struct sockaddr_in* remoteAddr );
cmUdpRC_t cmUdpSend2(   cmUdpH_t h, const char* data, unsigned dataByteCnt, const char* remoteAddr, cmUdpPort_t remotePort );

// Receive incoming messages by directly checking the internal
// socket for waiting data.  This function is used to receive
// incoming data when the internal listening thread is not used.
// Note that if kBlockingUdpFl was set
// in cmUdpInit() that this call will block for available data
// or for 'timeOutMs' milliseconds, whichever comes first.
// If kNonBlockingUdpFl was set in cmUdpInit() then the function
// will return immediately if no incoming messages are waiting.
// If non-NULL *recvByteCntPtr is set to the length of the received
// message or 0 if no msg was received. 
cmUdpRC_t cmUdpRecv(    cmUdpH_t h, char* data, unsigned dataByteCnt, struct sockaddr_in* fromAddr, unsigned* recvByteCntPtr );

// Start a listening thread. If the queue is enabled then incoming 
// messages are received as they arrive and stored in an internal 
// queue until the client requests them using cmUdpGetAvailData().
// If the queue is disabled the messages are transmitted immediately
// to the client in the context of the internal listening thread.
cmUdpRC_t cmUdpEnableListen( cmUdpH_t h, bool enableFl );

// Enable/disable the internal queue.  If the queue is disabled then
// the receive callback function will be called immediately upon reception
// of the incoming message in the context of the internal listening thread.  
// If the queue is enabled then incoming
// messages will be queued until they are transmitted by calling
// cmUdpGetAvailData().
bool      cmUdpIsQueueEnabled( cmUdpH_t h );
void      cmUdpQueueEnable( cmUdpH_t h, bool enableFl );

// Return the size of the next available message waiting in the
// internal data queue.
unsigned  cmUdpAvailDataByteCount( cmUdpH_t h );

// The Call this function to receieve any data waiting in the internal queue.
// Set 'data' to NULL to receive the data via the callback provided
// in cmUdpAlloc().
// On input *dataByteCntPtr must be set to the number of bytes in data[].
// On return *dataByteCntPtr is set to the actual number of bytes copied into data[].
// If fromAddr is non-NULL it is set to the data source address.
cmUdpRC_t cmUdpGetAvailData( cmUdpH_t h, char* data, unsigned* dataByteCntPtr, struct sockaddr_in* fromAddr );

void      cmUdpReport( cmUdpH_t h, cmRpt_t* rpt );

// Prepare a struct sockadddr_in for use with cmUdpSendTo()
cmUdpRC_t cmUdpInitAddr( cmUdpH_t h, const char* addrStr, cmUdpPort_t portNumber, struct sockaddr_in* retAddrPtr );

const cmChar_t*  cmUdpAddrToString( cmUdpH_t h, const struct sockaddr_in* addr );

bool             cmUdpAddrIsEqual( const struct sockaddr_in* a0, const struct sockaddr_in* a1 );

const cmChar_t* cmUdpHostName( cmUdpH_t h );

cmUdpRC_t cmUdpTest( cmCtx_t* ctx, const char* remoteIpAddr, cmUdpPort_t port );
cmUdpRC_t cmUdpTestV( cmCtx_t* ctx, unsigned argc, const char* argv[]);