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.
18 #include <arpa/inet.h>
19 #include <netinet/in.h>
20 #include <sys/socket.h>
22 #include <sys/types.h>
25 #include "PlatformDefs.h"
40 /**********************************************************************/
41 /* IP address abstraction class */
42 /**********************************************************************/
50 sockaddr saddr_generic
;
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
)
68 void SetAddress(const char *address
)
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
);
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
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
);
95 return inet_ntoa(saddr
.saddr4
.sin_addr
);
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.
114 if (hash
== 0xffffffffu
)
116 return (unsigned long)htonl(hash
);
119 return (unsigned long)saddr
.saddr4
.sin_addr
.s_addr
;
123 /**********************************************************************/
124 /* Base class for all sockets */
125 /**********************************************************************/
136 virtual ~CBaseSocket() { Close(); }
139 virtual bool Bind(bool localOnly
, int port
, int range
=0) = 0;
140 virtual bool Connect() = 0;
141 virtual void Close() {}
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;
151 virtual void SetBound(bool set
=true) { m_bBound
= set
; }
152 virtual void SetReady(bool set
=true) { m_bReady
= set
; }
161 /**********************************************************************/
162 /* Base class for UDP socket implementations */
163 /**********************************************************************/
164 class CUDPSocket
: public CBaseSocket
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
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
205 SOCKET
Socket() override
{ return m_iSock
; }
206 void Close() override
;
213 bool CheckIPv6(int port
, int range
);
218 /**********************************************************************/
219 /* Create and return platform dependent sockets */
220 /**********************************************************************/
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
238 void AddSocket(CBaseSocket
*);
239 bool Listen(int timeoutMs
); // in ms, -1=>never timeout, 0=>poll
241 CBaseSocket
* GetFirstReadySocket();
242 CBaseSocket
* GetNextReadySocket();
245 std::vector
<CBaseSocket
*> m_sockets
;
248 int m_iCurrentSocket
;