mirror of
				https://github.com/f4exb/sdrangel.git
				synced 2025-10-31 04:50:29 -04:00 
			
		
		
		
	
		
			
	
	
		
			340 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			340 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
|  | ///////////////////////////////////////////////////////////////////////////////////
 | ||
|  | // SDRdaemon - send I/Q samples read from a SDR device over the network via UDP. //
 | ||
|  | //                                                                               //
 | ||
|  | // 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                  //
 | ||
|  | //                                                                               //
 | ||
|  | // 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 | ||
|  |      *          is in posession of the \c Exception object. Callers \a must | ||
|  |      *          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 | ||
|  |    */ | ||
|  | 
 | ||
|  |     string GetLocalAddress() throw(CSocketException); | ||
|  | 
 | ||
|  |     /**
 | ||
|  |    *   Get the local port | ||
|  |    *   @return local port of socket | ||
|  |    *   @exception CSocketException thrown if fetch fails | ||
|  |    */ | ||
|  | 
 | ||
|  |     unsigned short GetLocalPort() throw(CSocketException); | ||
|  | 
 | ||
|  | 
 | ||
|  |     /**
 | ||
|  |    *   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 | ||
|  |    */ | ||
|  | 
 | ||
|  |     void BindLocalPort(unsigned short localPort) throw(CSocketException); | ||
|  | 
 | ||
|  |     /**
 | ||
|  |    *   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 | ||
|  |    */ | ||
|  | 
 | ||
|  |     void BindLocalAddressAndPort(const string &localAddress, unsigned short localPort = 0) throw(CSocketException); | ||
|  | 
 | ||
|  |     /**
 | ||
|  |     *   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. | ||
|  |     */ | ||
|  |     void SetReadBufferSize(unsigned int nSize) throw(CSocketException); | ||
|  | 
 | ||
|  |     /**
 | ||
|  |     *   Sets the socket to Blocking/Non blocking state. | ||
|  |     *   @param Bool flag for Non blocking status. | ||
|  |     */ | ||
|  |     void SetNonBlocking(bool bBlocking) throw(CSocketException); | ||
|  | 
 | ||
|  |     /**
 | ||
|  |    *   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 | ||
|  |    */ | ||
|  |     void ConnectToHost(const string &foreignAddress, unsigned short foreignPort) throw(CSocketException); | ||
|  | 
 | ||
|  |     /**
 | ||
|  |      *   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 | ||
|  |      */ | ||
|  |     void Send(const void *buffer, int bufferLen) throw(CSocketException); | ||
|  | 
 | ||
|  |   /**
 | ||
|  |    *   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 | ||
|  |    */ | ||
|  |     int Recv(void *buffer, int bufferLen) throw(CSocketException); | ||
|  | 
 | ||
|  |     /**
 | ||
|  |      *   Get the foreign address.  Call connect() before calling recv() | ||
|  |      *   @return foreign address | ||
|  |      *   @exception SocketException thrown if unable to fetch foreign address | ||
|  |      */ | ||
|  |     string GetPeerAddress() throw(CSocketException); | ||
|  | 
 | ||
|  |     /**
 | ||
|  |      *   Get the foreign port.  Call connect() before calling recv() | ||
|  |      *   @return foreign port | ||
|  |      *   @exception SocketException thrown if unable to fetch foreign port | ||
|  |      */ | ||
|  |     unsigned short GetPeerPort() throw(CSocketException); | ||
|  | 
 | ||
|  |     /**
 | ||
|  |      *   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 | ||
|  |      */ | ||
|  |     void SetBindToDevice(const string& sInterface) throw(CSocketException); | ||
|  | 
 | ||
|  | protected: | ||
|  |     /**
 | ||
|  |      *   Internal Socket descriptor | ||
|  |      **/ | ||
|  |     int m_sockDesc; | ||
|  | 
 | ||
|  |     CSocket(SocketType type, NetworkLayerProtocol protocol) throw(CSocketException); | ||
|  |     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 | ||
|  |    */ | ||
|  |     UDPSocket() throw(CSocketException); | ||
|  |   /**
 | ||
|  |    *   Construct a UDP socket with the given local port | ||
|  |    *   @param localPort local port | ||
|  |    *   @exception SocketException thrown if unable to create UDP socket | ||
|  |    */ | ||
|  |     UDPSocket(unsigned short localPort) throw(CSocketException); | ||
|  | 
 | ||
|  |   /**
 | ||
|  |    *   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 | ||
|  |    */ | ||
|  |     UDPSocket(const string &localAddress, unsigned short localPort) throw(CSocketException); | ||
|  | 
 | ||
|  |   /**
 | ||
|  |    *   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 | ||
|  |    */ | ||
|  |     void DisconnectFromHost() throw(CSocketException); | ||
|  | 
 | ||
|  |   /**
 | ||
|  |    *   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, | ||
|  |         unsigned short foreignPort) throw(CSocketException); | ||
|  | 
 | ||
|  |     /**
 | ||
|  |      *   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, | ||
|  |                unsigned short &sourcePort) throw(CSocketException); | ||
|  | 
 | ||
|  |     /**
 | ||
|  |     *   Set the multicast TTL | ||
|  |     *   @param multicastTTL multicast TTL | ||
|  |     *   @exception SocketException thrown if unable to set TTL | ||
|  |     */ | ||
|  |     void SetMulticastTTL(unsigned char multicastTTL) throw(CSocketException); | ||
|  | 
 | ||
|  |     /**
 | ||
|  |      *   Join the specified multicast group | ||
|  |      *   @param multicastGroup multicast group address to join | ||
|  |      *   @exception SocketException thrown if unable to join group | ||
|  |      */ | ||
|  |     void JoinGroup(const string &multicastGroup) throw(CSocketException); | ||
|  | 
 | ||
|  |     /**
 | ||
|  |      *   Leave the specified multicast group | ||
|  |      *   @param multicastGroup multicast group address to leave | ||
|  |      *   @exception SocketException thrown if unable to leave group | ||
|  |      */ | ||
|  |     void LeaveGroup(const string &multicastGroup) throw(CSocketException); | ||
|  | 
 | ||
|  | private: | ||
|  |     void SetBroadcast(); | ||
|  | 
 | ||
|  | }; | ||
|  | 
 | ||
|  | 
 | ||
|  | #endif /* INCLUDE_UDPSOCKET_H_ */
 |