5 * Copyright (c) 2008 d4rk
6 * Copyright (C) 2008-2015 Team Kodi
9 * This Program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2, or (at your option)
14 * This Program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with Kodi; see the file COPYING. If not, see
21 * <http://www.gnu.org/licenses/>.
28 #include <sys/socket.h>
29 #include <netinet/in.h>
30 #include <arpa/inet.h>
32 #include <sys/types.h>
48 /**********************************************************************/
49 /* IP address abstraction class */
50 /**********************************************************************/
58 sockaddr saddr_generic
;
65 memset(&saddr
, 0, sizeof(saddr
));
66 saddr
.saddr4
.sin_family
= AF_INET
;
67 saddr
.saddr4
.sin_addr
.s_addr
= htonl(INADDR_ANY
);
68 size
= sizeof(saddr
.saddr4
);
71 CAddress(const char *address
)
76 void SetAddress(const char *address
)
79 memset(&saddr
, 0, sizeof(saddr
));
80 if (inet_pton(AF_INET6
, address
, &addr6
) == 1)
82 saddr
.saddr6
.sin6_family
= AF_INET6
;
83 saddr
.saddr6
.sin6_addr
= addr6
;
84 size
= sizeof(saddr
.saddr6
);
88 saddr
.saddr4
.sin_family
= AF_INET
;
89 saddr
.saddr4
.sin_addr
.s_addr
= inet_addr(address
);
90 size
= sizeof(saddr
.saddr4
);
94 // returns statically alloced buffer, do not free
97 if (saddr
.saddr_generic
.sa_family
== AF_INET6
)
99 static char buf
[INET6_ADDRSTRLEN
];
100 return inet_ntop(AF_INET6
, &saddr
.saddr6
.sin6_addr
, buf
, size
);
103 return inet_ntoa(saddr
.saddr4
.sin_addr
);
106 unsigned long ULong()
108 if (saddr
.saddr_generic
.sa_family
== AF_INET6
)
110 // IPv4 coercion (see http://home.samfundet.no/~sesse/ipv6-porting.pdf).
111 // We hash the entire IPv6 address because XBMC might conceivably need to
112 // distinguish between different hosts in the same subnet.
113 // This hash function (djbhash) is not too strong, but good enough.
114 uint32_t hash
= 5381;
115 for (int i
= 0; i
< 16; ++i
)
117 hash
= hash
* 33 + saddr
.saddr6
.sin6_addr
.s6_addr
[i
];
119 // Move into 224.0.0.0/3. As a special safeguard, make sure we don't
120 // end up with the the special broadcast address 255.255.255.255.
122 if (hash
== 0xffffffffu
)
124 return (unsigned long)htonl(hash
);
127 return (unsigned long)saddr
.saddr4
.sin_addr
.s_addr
;
131 /**********************************************************************/
132 /* Base class for all sockets */
133 /**********************************************************************/
144 virtual ~CBaseSocket() { Close(); }
147 virtual bool Bind(bool localOnly
, int port
, int range
=0) = 0;
148 virtual bool Connect() = 0;
149 virtual void Close() {};
152 bool Ready() { return m_bReady
; }
153 bool Bound() { return m_bBound
; }
154 SocketType
Type() { return m_Type
; }
155 int Port() { return m_iPort
; }
156 virtual SOCKET
Socket() = 0;
159 virtual void SetBound(bool set
=true) { m_bBound
= set
; }
160 virtual void SetReady(bool set
=true) { m_bReady
= set
; }
169 /**********************************************************************/
170 /* Base class for UDP socket implementations */
171 /**********************************************************************/
172 class CUDPSocket
: public CBaseSocket
180 virtual int SendTo(const CAddress
& addr
, const int bufferlength
,
181 const void* buffer
) = 0;
183 // read datagrams, return no. of bytes read or -1 or error
184 virtual int Read(CAddress
& addr
, const int buffersize
, void *buffer
) = 0;
185 virtual bool Broadcast(const CAddress
& addr
, const int datasize
,
186 const void* data
) = 0;
189 // Implementation specific classes
191 /**********************************************************************/
192 /* POSIX based UDP socket implementation */
193 /**********************************************************************/
194 class CPosixUDPSocket
: public CUDPSocket
199 m_iSock
= INVALID_SOCKET
;
200 m_ipv6Socket
= false;
203 bool Bind(bool localOnly
, int port
, int range
=0);
204 bool Connect() { return false; }
205 bool Listen(int timeout
);
206 int SendTo(const CAddress
& addr
, const int datasize
, const void* data
);
207 int Read(CAddress
& addr
, const int buffersize
, void *buffer
);
208 bool Broadcast(const CAddress
& addr
, const int datasize
, const void* data
)
213 SOCKET
Socket() { return m_iSock
; }
224 /**********************************************************************/
225 /* Create and return platform dependent sockets */
226 /**********************************************************************/
230 static CUDPSocket
* CreateUDPSocket();
233 /**********************************************************************/
234 /* Listens on multiple sockets for reads */
235 /**********************************************************************/
237 #define LISTENERROR 1
238 #define LISTENEMPTY 2
240 class CSocketListener
244 void AddSocket(CBaseSocket
*);
245 bool Listen(int timeoutMs
); // in ms, -1=>never timeout, 0=>poll
247 CBaseSocket
* GetFirstReadySocket();
248 CBaseSocket
* GetNextReadySocket();
251 std::vector
<CBaseSocket
*> m_sockets
;
254 int m_iCurrentSocket
;