mirror of
				https://github.com/f4exb/sdrangel.git
				synced 2025-10-26 02:20:26 -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();
 | |
| 
 | |
|     /**
 | |
|    *   Get the local port
 | |
|    *   @return local port of socket
 | |
|    *   @exception CSocketException thrown if fetch fails
 | |
|    */
 | |
| 
 | |
|     unsigned short GetLocalPort();
 | |
| 
 | |
| 
 | |
|     /**
 | |
|    *   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);
 | |
| 
 | |
|     /**
 | |
|    *   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);
 | |
| 
 | |
|     /**
 | |
|     *   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);
 | |
| 
 | |
|     /**
 | |
|     *   Sets the socket to Blocking/Non blocking state.
 | |
|     *   @param Bool flag for Non blocking status.
 | |
|     */
 | |
|     void SetNonBlocking(bool bBlocking);
 | |
| 
 | |
|     /**
 | |
|    *   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);
 | |
| 
 | |
|     /**
 | |
|      *   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);
 | |
| 
 | |
|   /**
 | |
|    *   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);
 | |
| 
 | |
|     /**
 | |
|      *   Get the foreign address.  Call connect() before calling recv()
 | |
|      *   @return foreign address
 | |
|      *   @exception SocketException thrown if unable to fetch foreign address
 | |
|      */
 | |
|     string GetPeerAddress();
 | |
| 
 | |
|     /**
 | |
|      *   Get the foreign port.  Call connect() before calling recv()
 | |
|      *   @return foreign port
 | |
|      *   @exception SocketException thrown if unable to fetch foreign port
 | |
|      */
 | |
|     unsigned short GetPeerPort();
 | |
| 
 | |
|     /**
 | |
|      *   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);
 | |
| 
 | |
| protected:
 | |
|     /**
 | |
|      *   Internal Socket descriptor
 | |
|      **/
 | |
|     int m_sockDesc;
 | |
| 
 | |
|     CSocket(SocketType type, NetworkLayerProtocol protocol);
 | |
|     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();
 | |
|   /**
 | |
|    *   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);
 | |
| 
 | |
|   /**
 | |
|    *   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);
 | |
| 
 | |
|   /**
 | |
|    *   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();
 | |
| 
 | |
|   /**
 | |
|    *   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);
 | |
| 
 | |
|     /**
 | |
|      *   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);
 | |
| 
 | |
|     /**
 | |
|     *   Set the multicast TTL
 | |
|     *   @param multicastTTL multicast TTL
 | |
|     *   @exception SocketException thrown if unable to set TTL
 | |
|     */
 | |
|     void SetMulticastTTL(unsigned char multicastTTL);
 | |
| 
 | |
|     /**
 | |
|      *   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);
 | |
| 
 | |
|     /**
 | |
|      *   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);
 | |
| 
 | |
| private:
 | |
|     void SetBroadcast();
 | |
| 
 | |
| };
 | |
| 
 | |
| 
 | |
| #endif /* INCLUDE_UDPSOCKET_H_ */
 |