kodi
Socket.h
1 /*
2  * Socket classes
3  * Copyright (c) 2008 d4rk
4  * Copyright (C) 2008-2018 Team Kodi
5  * This file is part of Kodi - https://kodi.tv
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  * See LICENSES/README.md for more information.
9  */
10 
11 #pragma once
12 
13 #include <map>
14 #include <memory>
15 #include <string.h>
16 #include <vector>
17 
18 #include <arpa/inet.h>
19 #include <netinet/in.h>
20 #include <sys/socket.h>
21 #include <sys/time.h>
22 #include <sys/types.h>
23 #include <unistd.h>
24 
25 #include "PlatformDefs.h"
26 #ifdef TARGET_POSIX
27 typedef int SOCKET;
28 #endif
29 
30 namespace SOCKETS
31 {
32  // types of sockets
33  enum SocketType
34  {
35  ST_TCP,
36  ST_UDP,
37  ST_UNIX
38  };
39 
40  /**********************************************************************/
41  /* IP address abstraction class */
42  /**********************************************************************/
43  class CAddress
44  {
45  public:
46  union
47  {
48  sockaddr_in saddr4;
49  sockaddr_in6 saddr6;
50  sockaddr saddr_generic;
51  } saddr;
52  socklen_t size;
53 
54  public:
55  CAddress()
56  {
57  memset(&saddr, 0, sizeof(saddr));
58  saddr.saddr4.sin_family = AF_INET;
59  saddr.saddr4.sin_addr.s_addr = htonl(INADDR_ANY);
60  size = sizeof(saddr.saddr4);
61  }
62 
63  explicit CAddress(const char *address)
64  {
65  SetAddress(address);
66  }
67 
68  void SetAddress(const char *address)
69  {
70  in6_addr addr6;
71  memset(&saddr, 0, sizeof(saddr));
72  if (inet_pton(AF_INET6, address, &addr6) == 1)
73  {
74  saddr.saddr6.sin6_family = AF_INET6;
75  saddr.saddr6.sin6_addr = addr6;
76  size = sizeof(saddr.saddr6);
77  }
78  else
79  {
80  saddr.saddr4.sin_family = AF_INET;
81  saddr.saddr4.sin_addr.s_addr = inet_addr(address);
82  size = sizeof(saddr.saddr4);
83  }
84  }
85 
86  // returns statically alloced buffer, do not free
87  const char *Address()
88  {
89  if (saddr.saddr_generic.sa_family == AF_INET6)
90  {
91  static char buf[INET6_ADDRSTRLEN];
92  return inet_ntop(AF_INET6, &saddr.saddr6.sin6_addr, buf, size);
93  }
94  else
95  return inet_ntoa(saddr.saddr4.sin_addr);
96  }
97 
98  unsigned long ULong()
99  {
100  if (saddr.saddr_generic.sa_family == AF_INET6)
101  {
102  // IPv4 coercion (see http://home.samfundet.no/~sesse/ipv6-porting.pdf).
103  // We hash the entire IPv6 address because XBMC might conceivably need to
104  // distinguish between different hosts in the same subnet.
105  // This hash function (djbhash) is not too strong, but good enough.
106  uint32_t hash = 5381;
107  for (int i = 0; i < 16; ++i)
108  {
109  hash = hash * 33 + saddr.saddr6.sin6_addr.s6_addr[i];
110  }
111  // Move into 224.0.0.0/3. As a special safeguard, make sure we don't
112  // end up with the the special broadcast address 255.255.255.255.
113  hash |= 0xe0000000u;
114  if (hash == 0xffffffffu)
115  hash = 0xfffffffeu;
116  return (unsigned long)htonl(hash);
117  }
118  else
119  return (unsigned long)saddr.saddr4.sin_addr.s_addr;
120  }
121  };
122 
123  /**********************************************************************/
124  /* Base class for all sockets */
125  /**********************************************************************/
127  {
128  public:
129  CBaseSocket()
130  {
131  m_Type = ST_TCP;
132  m_bReady = false;
133  m_bBound = false;
134  m_iPort = 0;
135  }
136  virtual ~CBaseSocket() { Close(); }
137 
138  // socket functions
139  virtual bool Bind(bool localOnly, int port, int range=0) = 0;
140  virtual bool Connect() = 0;
141  virtual void Close() {}
142 
143  // state functions
144  bool Ready() { return m_bReady; }
145  bool Bound() { return m_bBound; }
146  SocketType Type() { return m_Type; }
147  int Port() { return m_iPort; }
148  virtual SOCKET Socket() = 0;
149 
150  protected:
151  virtual void SetBound(bool set=true) { m_bBound = set; }
152  virtual void SetReady(bool set=true) { m_bReady = set; }
153 
154  protected:
155  SocketType m_Type;
156  bool m_bReady;
157  bool m_bBound;
158  int m_iPort;
159  };
160 
161  /**********************************************************************/
162  /* Base class for UDP socket implementations */
163  /**********************************************************************/
164  class CUDPSocket : public CBaseSocket
165  {
166  public:
167  CUDPSocket()
168  {
169  m_Type = ST_UDP;
170  }
171  // I/O functions
172  virtual int SendTo(const CAddress& addr, const int bufferlength,
173  const void* buffer) = 0;
174 
175  // read datagrams, return no. of bytes read or -1 or error
176  virtual int Read(CAddress& addr, const int buffersize, void *buffer) = 0;
177  virtual bool Broadcast(const CAddress& addr, const int datasize,
178  const void* data) = 0;
179  };
180 
181  // Implementation specific classes
182 
183  /**********************************************************************/
184  /* POSIX based UDP socket implementation */
185  /**********************************************************************/
187  {
188  public:
190  {
191  m_iSock = INVALID_SOCKET;
192  m_ipv6Socket = false;
193  }
194 
195  bool Bind(bool localOnly, int port, int range=0) override;
196  bool Connect() override { return false; }
197  bool Listen(int timeout);
198  int SendTo(const CAddress& addr, const int datasize, const void* data) override;
199  int Read(CAddress& addr, const int buffersize, void *buffer) override;
200  bool Broadcast(const CAddress& addr, const int datasize, const void* data) override
201  {
203  return false;
204  }
205  SOCKET Socket() override { return m_iSock; }
206  void Close() override;
207 
208  protected:
209  SOCKET m_iSock;
210  CAddress m_addr;
211 
212  private:
213  bool CheckIPv6(int port, int range);
214 
215  bool m_ipv6Socket;
216  };
217 
218  /**********************************************************************/
219  /* Create and return platform dependent sockets */
220  /**********************************************************************/
222  {
223  public:
224  static std::unique_ptr<CUDPSocket> CreateUDPSocket();
225  };
226 
227  /**********************************************************************/
228  /* Listens on multiple sockets for reads */
229  /**********************************************************************/
230 
231 #define LISTENERROR 1
232 #define LISTENEMPTY 2
233 
235  {
236  public:
237  CSocketListener();
238  void AddSocket(CBaseSocket *);
239  bool Listen(int timeoutMs); // in ms, -1=>never timeout, 0=>poll
240  void Clear();
241  CBaseSocket* GetFirstReadySocket();
242  CBaseSocket* GetNextReadySocket();
243 
244  protected:
245  std::vector<CBaseSocket*> m_sockets;
246  int m_iReadyCount;
247  int m_iMaxSockets;
248  int m_iCurrentSocket;
249  fd_set m_fdset;
250  };
251 
252 }
253 
Definition: Socket.h:186
Definition: Socket.h:221
Definition: Socket.h:30
Definition: Socket.h:126
Definition: Socket.h:164
Definition: Socket.h:234
Definition: Socket.h:43
bool Broadcast(const CAddress &addr, const int datasize, const void *data) override
Definition: Socket.h:200