[Windows] Fix driver version detection of AMD RDNA+ GPU on Windows 10
[xbmc.git] / xbmc / network / Socket.h
blobb94553398e8a2b9cb93e8e66f9461bbb775aa955
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
7 * SPDX-License-Identifier: GPL-2.0-or-later
8 * See LICENSES/README.md for more information.
9 */
11 #pragma once
13 #include <map>
14 #include <memory>
15 #include <string.h>
16 #include <vector>
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>
25 #include "PlatformDefs.h"
26 #ifdef TARGET_POSIX
27 typedef int SOCKET;
28 #endif
30 namespace SOCKETS
32 // types of sockets
33 enum SocketType
35 ST_TCP,
36 ST_UDP,
37 ST_UNIX
40 /**********************************************************************/
41 /* IP address abstraction class */
42 /**********************************************************************/
43 class CAddress
45 public:
46 union
48 sockaddr_in saddr4;
49 sockaddr_in6 saddr6;
50 sockaddr saddr_generic;
51 } saddr;
52 socklen_t size;
54 public:
55 CAddress()
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);
63 explicit CAddress(const char *address)
65 SetAddress(address);
68 void SetAddress(const char *address)
70 in6_addr addr6;
71 memset(&saddr, 0, sizeof(saddr));
72 if (inet_pton(AF_INET6, address, &addr6) == 1)
74 saddr.saddr6.sin6_family = AF_INET6;
75 saddr.saddr6.sin6_addr = addr6;
76 size = sizeof(saddr.saddr6);
78 else
80 saddr.saddr4.sin_family = AF_INET;
81 saddr.saddr4.sin_addr.s_addr = inet_addr(address);
82 size = sizeof(saddr.saddr4);
86 // returns statically alloced buffer, do not free
87 const char *Address()
89 if (saddr.saddr_generic.sa_family == AF_INET6)
91 static char buf[INET6_ADDRSTRLEN];
92 return inet_ntop(AF_INET6, &saddr.saddr6.sin6_addr, buf, size);
94 else
95 return inet_ntoa(saddr.saddr4.sin_addr);
98 unsigned long ULong()
100 if (saddr.saddr_generic.sa_family == AF_INET6)
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)
109 hash = hash * 33 + saddr.saddr6.sin6_addr.s6_addr[i];
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);
118 else
119 return (unsigned long)saddr.saddr4.sin_addr.s_addr;
123 /**********************************************************************/
124 /* Base class for all sockets */
125 /**********************************************************************/
126 class CBaseSocket
128 public:
129 CBaseSocket()
131 m_Type = ST_TCP;
132 m_bReady = false;
133 m_bBound = false;
134 m_iPort = 0;
136 virtual ~CBaseSocket() { Close(); }
138 // socket functions
139 virtual bool Bind(bool localOnly, int port, int range=0) = 0;
140 virtual bool Connect() = 0;
141 virtual void Close() {}
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;
150 protected:
151 virtual void SetBound(bool set=true) { m_bBound = set; }
152 virtual void SetReady(bool set=true) { m_bReady = set; }
154 protected:
155 SocketType m_Type;
156 bool m_bReady;
157 bool m_bBound;
158 int m_iPort;
161 /**********************************************************************/
162 /* Base class for UDP socket implementations */
163 /**********************************************************************/
164 class CUDPSocket : public CBaseSocket
166 public:
167 CUDPSocket()
169 m_Type = ST_UDP;
171 // I/O functions
172 virtual int SendTo(const CAddress& addr, const int bufferlength,
173 const void* buffer) = 0;
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;
181 // Implementation specific classes
183 /**********************************************************************/
184 /* POSIX based UDP socket implementation */
185 /**********************************************************************/
186 class CPosixUDPSocket : public CUDPSocket
188 public:
189 CPosixUDPSocket()
191 m_iSock = INVALID_SOCKET;
192 m_ipv6Socket = false;
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
202 //! @todo implement
203 return false;
205 SOCKET Socket() override { return m_iSock; }
206 void Close() override;
208 protected:
209 SOCKET m_iSock;
210 CAddress m_addr;
212 private:
213 bool CheckIPv6(int port, int range);
215 bool m_ipv6Socket;
218 /**********************************************************************/
219 /* Create and return platform dependent sockets */
220 /**********************************************************************/
221 class CSocketFactory
223 public:
224 static std::unique_ptr<CUDPSocket> CreateUDPSocket();
227 /**********************************************************************/
228 /* Listens on multiple sockets for reads */
229 /**********************************************************************/
231 #define LISTENERROR 1
232 #define LISTENEMPTY 2
234 class CSocketListener
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();
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;