VTB: release CVBuffer after it actually has been rendered
[xbmc.git] / xbmc / network / Socket.h
blobe5d3c92a0741c3dcb5511147e2b5e47ed8108c67
1 #pragma once
3 /*
4 * Socket classes
5 * Copyright (c) 2008 d4rk
6 * Copyright (C) 2008-2015 Team Kodi
7 * http://kodi.tv
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)
12 * any later version.
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/>.
25 #include <string.h>
26 #include <map>
27 #include <vector>
28 #include <sys/socket.h>
29 #include <netinet/in.h>
30 #include <arpa/inet.h>
31 #include <sys/time.h>
32 #include <sys/types.h>
33 #include <unistd.h>
34 #ifdef TARGET_POSIX
35 typedef int SOCKET;
36 #endif
38 namespace SOCKETS
40 // types of sockets
41 enum SocketType
43 ST_TCP,
44 ST_UDP,
45 ST_UNIX
48 /**********************************************************************/
49 /* IP address abstraction class */
50 /**********************************************************************/
51 class CAddress
53 public:
54 union
56 sockaddr_in saddr4;
57 sockaddr_in6 saddr6;
58 sockaddr saddr_generic;
59 } saddr;
60 socklen_t size;
62 public:
63 CAddress()
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)
73 SetAddress(address);
76 void SetAddress(const char *address)
78 in6_addr addr6;
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);
86 else
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
95 const char *Address()
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);
102 else
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.
121 hash |= 0xe0000000u;
122 if (hash == 0xffffffffu)
123 hash = 0xfffffffeu;
124 return (unsigned long)htonl(hash);
126 else
127 return (unsigned long)saddr.saddr4.sin_addr.s_addr;
131 /**********************************************************************/
132 /* Base class for all sockets */
133 /**********************************************************************/
134 class CBaseSocket
136 public:
137 CBaseSocket()
139 m_Type = ST_TCP;
140 m_bReady = false;
141 m_bBound = false;
142 m_iPort = 0;
144 virtual ~CBaseSocket() { Close(); }
146 // socket functions
147 virtual bool Bind(bool localOnly, int port, int range=0) = 0;
148 virtual bool Connect() = 0;
149 virtual void Close() {};
151 // state functions
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;
158 protected:
159 virtual void SetBound(bool set=true) { m_bBound = set; }
160 virtual void SetReady(bool set=true) { m_bReady = set; }
162 protected:
163 SocketType m_Type;
164 bool m_bReady;
165 bool m_bBound;
166 int m_iPort;
169 /**********************************************************************/
170 /* Base class for UDP socket implementations */
171 /**********************************************************************/
172 class CUDPSocket : public CBaseSocket
174 public:
175 CUDPSocket()
177 m_Type = ST_UDP;
179 // I/O functions
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
196 public:
197 CPosixUDPSocket()
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)
210 //! @todo implement
211 return false;
213 SOCKET Socket() { return m_iSock; }
214 void Close();
216 protected:
217 SOCKET m_iSock;
218 CAddress m_addr;
220 private:
221 bool m_ipv6Socket;
224 /**********************************************************************/
225 /* Create and return platform dependent sockets */
226 /**********************************************************************/
227 class CSocketFactory
229 public:
230 static CUDPSocket* CreateUDPSocket();
233 /**********************************************************************/
234 /* Listens on multiple sockets for reads */
235 /**********************************************************************/
237 #define LISTENERROR 1
238 #define LISTENEMPTY 2
240 class CSocketListener
242 public:
243 CSocketListener();
244 void AddSocket(CBaseSocket *);
245 bool Listen(int timeoutMs); // in ms, -1=>never timeout, 0=>poll
246 void Clear();
247 CBaseSocket* GetFirstReadySocket();
248 CBaseSocket* GetNextReadySocket();
250 protected:
251 std::vector<CBaseSocket*> m_sockets;
252 int m_iReadyCount;
253 int m_iMaxSockets;
254 int m_iCurrentSocket;
255 fd_set m_fdset;