2017-05-22 19:41:30 -04:00
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
2019-02-02 16:58:42 -05:00
|
|
|
// Remote - send I/Q samples read from a SDR device over the network via UDP. //
|
2017-05-22 19:41:30 -04:00
|
|
|
// //
|
|
|
|
// Copyright (C) 2015 Edouard Griffiths, F4EXB //
|
|
|
|
// //
|
|
|
|
// This program 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 as version 3 of the License, or //
|
2019-04-11 00:39:30 -04:00
|
|
|
// (at your option) any later version. //
|
2017-05-22 19:41:30 -04:00
|
|
|
// //
|
|
|
|
// This program 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 V3 for more details. //
|
|
|
|
// //
|
|
|
|
// You should have received a copy of the GNU General Public License //
|
|
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
// Original code is posted at: https://cppcodetips.wordpress.com/2014/01/29/udp-socket-class-in-c/
|
|
|
|
|
|
|
|
#ifndef INCLUDE_UDPSOCKET_H_
|
|
|
|
#define INCLUDE_UDPSOCKET_H_
|
|
|
|
|
|
|
|
#include <cstring> // For string
|
|
|
|
#include <exception> // For exception class
|
|
|
|
#include <string>
|
|
|
|
#include <sys/types.h> // For data types
|
|
|
|
#include <sys/socket.h> // For socket(), connect(), send(), and recv()
|
|
|
|
#include <netdb.h> // For gethostbyname()
|
|
|
|
#include <arpa/inet.h> // For inet_addr()
|
|
|
|
#include <unistd.h> // For close()
|
|
|
|
#include <netinet/in.h> // For sockaddr_in
|
|
|
|
#include <errno.h>
|
|
|
|
#include <climits>
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Signals a problem with the execution of a socket call.
|
|
|
|
*/
|
|
|
|
|
|
|
|
class CSocketException: public std::exception
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
/**
|
|
|
|
* Construct a SocketException with a explanatory message.
|
|
|
|
* @param message explanatory message
|
|
|
|
* @param bSysMsg true if system message (from strerror(errno))
|
|
|
|
* should be postfixed to the user provided message
|
|
|
|
*/
|
|
|
|
CSocketException(const string &message, bool bSysMsg = false) throw();
|
|
|
|
|
|
|
|
|
|
|
|
/** Destructor.
|
|
|
|
* Virtual to allow for subclassing.
|
|
|
|
*/
|
|
|
|
virtual ~CSocketException() throw ();
|
|
|
|
|
|
|
|
/** Returns a pointer to the (constant) error description.
|
|
|
|
* @return A pointer to a \c const \c char*. The underlying memory
|
2019-07-22 17:14:23 -04:00
|
|
|
* is in possession of the \c Exception object. Callers \a must
|
2017-05-22 19:41:30 -04:00
|
|
|
* not attempt to free the memory.
|
|
|
|
*/
|
|
|
|
virtual const char* what() const throw (){ return m_sMsg.c_str(); }
|
|
|
|
|
|
|
|
protected:
|
|
|
|
/** Error message.
|
|
|
|
*/
|
|
|
|
std::string m_sMsg;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Base class representing basic communication endpoint.
|
|
|
|
*/
|
|
|
|
|
|
|
|
class CSocket
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
virtual ~CSocket();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Enum to represent type of socket(UDP or TCP)
|
|
|
|
*/
|
|
|
|
enum SocketType
|
|
|
|
{
|
|
|
|
TcpSocket = SOCK_STREAM,
|
|
|
|
UdpSocket = SOCK_DGRAM,
|
|
|
|
UnknownSocketType =-1
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Enum to represent type network layer protocol used for socket
|
|
|
|
*/
|
|
|
|
enum NetworkLayerProtocol
|
|
|
|
{
|
|
|
|
IPv4Protocol = AF_INET,
|
|
|
|
IPv6Protocol = AF_INET6,
|
|
|
|
UnknownNetworkLayerProtocol = -1
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Enum to represent Wait Result when reading data from a socket
|
|
|
|
*/
|
|
|
|
enum ReadResult
|
|
|
|
{
|
|
|
|
DATA_ARRIVED = 0,
|
|
|
|
DATA_TIMED_OUT = ETIMEDOUT,
|
|
|
|
DATA_EXCEPTION = 255
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the local address
|
|
|
|
* @return local address of socket
|
|
|
|
* @exception CSocketException thrown if fetch fails
|
|
|
|
*/
|
|
|
|
|
2017-12-30 20:46:03 -05:00
|
|
|
string GetLocalAddress();
|
2017-05-22 19:41:30 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the local port
|
|
|
|
* @return local port of socket
|
|
|
|
* @exception CSocketException thrown if fetch fails
|
|
|
|
*/
|
|
|
|
|
2017-12-30 20:46:03 -05:00
|
|
|
unsigned short GetLocalPort();
|
2017-05-22 19:41:30 -04:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set the local port to the specified port and the local address
|
|
|
|
* to any interface
|
|
|
|
* @param localPort local port
|
|
|
|
* @exception CSocketException thrown if setting local port fails
|
|
|
|
*/
|
|
|
|
|
2017-12-30 20:46:03 -05:00
|
|
|
void BindLocalPort(unsigned short localPort);
|
2017-05-22 19:41:30 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Set the local port to the specified port and the local address
|
|
|
|
* to the specified address. If you omit the port, a random port
|
|
|
|
* will be selected.
|
|
|
|
* @param localAddress local address
|
|
|
|
* @param localPort local port
|
|
|
|
* @exception CSocketException thrown if setting local port or address fails
|
|
|
|
*/
|
|
|
|
|
2017-12-30 20:46:03 -05:00
|
|
|
void BindLocalAddressAndPort(const string &localAddress, unsigned short localPort = 0);
|
2017-05-22 19:41:30 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the size of the internal read buffer. This limits the amount of data that the client
|
|
|
|
* can receive before you call
|
|
|
|
*/
|
|
|
|
unsigned long int GetReadBufferSize ();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sets the read buffer size of the socket.
|
|
|
|
* @param Size of the buffer.
|
|
|
|
*/
|
2017-12-30 20:46:03 -05:00
|
|
|
void SetReadBufferSize(unsigned int nSize);
|
2017-05-22 19:41:30 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Sets the socket to Blocking/Non blocking state.
|
|
|
|
* @param Bool flag for Non blocking status.
|
|
|
|
*/
|
2017-12-30 20:46:03 -05:00
|
|
|
void SetNonBlocking(bool bBlocking);
|
2017-05-22 19:41:30 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Establish a socket connection with the given foreign
|
|
|
|
* address and port
|
|
|
|
* @param foreignAddress foreign address (IP address or name)
|
|
|
|
* @param foreignPort foreign port
|
|
|
|
* @exception SocketException thrown if unable to establish connection
|
|
|
|
*/
|
2017-12-30 20:46:03 -05:00
|
|
|
void ConnectToHost(const string &foreignAddress, unsigned short foreignPort);
|
2017-05-22 19:41:30 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Write the given buffer to this socket. Call connect() before
|
|
|
|
* calling send()
|
|
|
|
* @param buffer buffer to be written
|
|
|
|
* @param bufferLen number of bytes from buffer to be written
|
|
|
|
* @exception SocketException thrown if unable to send data
|
|
|
|
*/
|
2017-12-30 20:46:03 -05:00
|
|
|
void Send(const void *buffer, int bufferLen);
|
2017-05-22 19:41:30 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Read into the given buffer up to bufferLen bytes data from this
|
|
|
|
* socket. Call connect() before calling recv()
|
|
|
|
* @param buffer buffer to receive the data
|
|
|
|
* @param bufferLen maximum number of bytes to read into buffer
|
|
|
|
* @return number of bytes read, 0 for EOF, and -1 for error
|
|
|
|
* @exception SocketException thrown if unable to receive data
|
|
|
|
*/
|
2017-12-30 20:46:03 -05:00
|
|
|
int Recv(void *buffer, int bufferLen);
|
2017-05-22 19:41:30 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the foreign address. Call connect() before calling recv()
|
|
|
|
* @return foreign address
|
|
|
|
* @exception SocketException thrown if unable to fetch foreign address
|
|
|
|
*/
|
2017-12-30 20:46:03 -05:00
|
|
|
string GetPeerAddress();
|
2017-05-22 19:41:30 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the foreign port. Call connect() before calling recv()
|
|
|
|
* @return foreign port
|
|
|
|
* @exception SocketException thrown if unable to fetch foreign port
|
|
|
|
*/
|
2017-12-30 20:46:03 -05:00
|
|
|
unsigned short GetPeerPort();
|
2017-05-22 19:41:30 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Writing sStr to socket
|
|
|
|
*/
|
|
|
|
CSocket& operator<<(const string& sStr );
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Reading data to sStr from socket
|
|
|
|
*/
|
|
|
|
CSocket& operator>>(string& sStr);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Blocking function to check whether data arrived in socket for reading.
|
|
|
|
* @param timeToWait waits for 'timeToWait' seconds.
|
|
|
|
*/
|
|
|
|
virtual int OnDataRead(unsigned long timeToWait = ULONG_MAX);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* To Bind socket to a symbolic device name like eth0
|
|
|
|
* @param sInterface NIC device name
|
|
|
|
*/
|
2017-12-30 20:46:03 -05:00
|
|
|
void SetBindToDevice(const string& sInterface);
|
2017-05-22 19:41:30 -04:00
|
|
|
|
|
|
|
protected:
|
|
|
|
/**
|
|
|
|
* Internal Socket descriptor
|
|
|
|
**/
|
|
|
|
int m_sockDesc;
|
|
|
|
|
2017-12-30 20:46:03 -05:00
|
|
|
CSocket(SocketType type, NetworkLayerProtocol protocol);
|
2017-05-22 19:41:30 -04:00
|
|
|
CSocket(int sockDesc);
|
|
|
|
static void FillAddr( const string & localAddress, unsigned short localPort, sockaddr_in& localAddr );
|
|
|
|
|
|
|
|
private:
|
|
|
|
// Prevent the user from trying to use Exact copy of this object
|
|
|
|
CSocket(const CSocket &sock);
|
|
|
|
void operator=(const CSocket &sock);
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* UDP Socket class.
|
|
|
|
*/
|
|
|
|
|
|
|
|
class UDPSocket : public CSocket
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
/**
|
|
|
|
* Construct a UDP socket
|
|
|
|
* @exception SocketException thrown if unable to create UDP socket
|
|
|
|
*/
|
2017-12-30 20:46:03 -05:00
|
|
|
UDPSocket();
|
2017-05-22 19:41:30 -04:00
|
|
|
/**
|
|
|
|
* Construct a UDP socket with the given local port
|
|
|
|
* @param localPort local port
|
|
|
|
* @exception SocketException thrown if unable to create UDP socket
|
|
|
|
*/
|
2017-12-30 20:46:03 -05:00
|
|
|
UDPSocket(unsigned short localPort);
|
2017-05-22 19:41:30 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Construct a UDP socket with the given local port and address
|
|
|
|
* @param localAddress local address
|
|
|
|
* @param localPort local port
|
|
|
|
* @exception SocketException thrown if unable to create UDP socket
|
|
|
|
*/
|
2017-12-30 20:46:03 -05:00
|
|
|
UDPSocket(const string &localAddress, unsigned short localPort);
|
2017-05-22 19:41:30 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Unset foreign address and port
|
|
|
|
* @return true if disassociation is successful
|
|
|
|
* @exception SocketException thrown if unable to disconnect UDP socket
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Unset foreign address and port
|
|
|
|
* @return true if disassociation is successful
|
|
|
|
* @exception SocketException thrown if unable to disconnect UDP socket
|
|
|
|
*/
|
2017-12-30 20:46:03 -05:00
|
|
|
void DisconnectFromHost();
|
2017-05-22 19:41:30 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Send the given buffer as a UDP datagram to the
|
|
|
|
* specified address/port
|
|
|
|
* @param buffer buffer to be written
|
|
|
|
* @param bufferLen number of bytes to write
|
|
|
|
* @param foreignAddress address (IP address or name) to send to
|
|
|
|
* @param foreignPort port number to send to
|
|
|
|
* @return true if send is successful
|
|
|
|
* @exception SocketException thrown if unable to send datagram
|
|
|
|
*/
|
|
|
|
void SendDataGram(const void *buffer, int bufferLen, const string &foreignAddress,
|
2017-12-30 20:46:03 -05:00
|
|
|
unsigned short foreignPort);
|
2017-05-22 19:41:30 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Read read up to bufferLen bytes data from this socket. The given buffer
|
|
|
|
* is where the data will be placed
|
|
|
|
* @param buffer buffer to receive data
|
|
|
|
* @param bufferLen maximum number of bytes to receive
|
|
|
|
* @param sourceAddress address of datagram source
|
|
|
|
* @param sourcePort port of data source
|
|
|
|
* @return number of bytes received and -1 for error
|
|
|
|
* @exception SocketException thrown if unable to receive datagram
|
|
|
|
*/
|
|
|
|
int RecvDataGram(void *buffer, int bufferLen, string &sourceAddress,
|
2017-12-30 20:46:03 -05:00
|
|
|
unsigned short &sourcePort);
|
2017-05-22 19:41:30 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Set the multicast TTL
|
|
|
|
* @param multicastTTL multicast TTL
|
|
|
|
* @exception SocketException thrown if unable to set TTL
|
|
|
|
*/
|
2017-12-30 20:46:03 -05:00
|
|
|
void SetMulticastTTL(unsigned char multicastTTL);
|
2017-05-22 19:41:30 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Join the specified multicast group
|
|
|
|
* @param multicastGroup multicast group address to join
|
|
|
|
* @exception SocketException thrown if unable to join group
|
|
|
|
*/
|
2017-12-30 20:46:03 -05:00
|
|
|
void JoinGroup(const string &multicastGroup);
|
2017-05-22 19:41:30 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Leave the specified multicast group
|
|
|
|
* @param multicastGroup multicast group address to leave
|
|
|
|
* @exception SocketException thrown if unable to leave group
|
|
|
|
*/
|
2017-12-30 20:46:03 -05:00
|
|
|
void LeaveGroup(const string &multicastGroup);
|
2017-05-22 19:41:30 -04:00
|
|
|
|
|
|
|
private:
|
|
|
|
void SetBroadcast();
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
#endif /* INCLUDE_UDPSOCKET_H_ */
|