only call IPlayerCallback::OnPlayBackSpeedChanged if the speed has actually changed
[vuplus_xbmc] / xbmc / network / TCPServer.cpp
1 #include "TCPServer.h"
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <memory.h>
5 #include <netinet/in.h>
6 #include <arpa/inet.h>
7
8 #include "settings/AdvancedSettings.h"
9 #include "interfaces/json-rpc/JSONRPC.h"
10 #include "interfaces/AnnouncementManager.h"
11 #include "utils/log.h"
12 #include "utils/Variant.h"
13 #include "threads/SingleLock.h"
14
15 static const char     bt_service_name[] = "XBMC JSON-RPC";
16 static const char     bt_service_desc[] = "Interface for XBMC remote control over bluetooth";
17 static const char     bt_service_prov[] = "XBMC JSON-RPC Provider";
18 static const uint32_t bt_service_guid[] = {0x65AE4CC0, 0x775D11E0, 0xBE16CE28, 0x4824019B};
19
20 #ifdef HAVE_LIBBLUETOOTH
21 #include <bluetooth/bluetooth.h>
22 #include <bluetooth/rfcomm.h>
23 #include <bluetooth/sdp.h>
24 #include <bluetooth/sdp_lib.h>
25
26  /* The defines BDADDR_ANY and BDADDR_LOCAL are broken so use our own structs */
27 static const bdaddr_t bt_bdaddr_any   = {{0, 0, 0, 0, 0, 0}};
28 static const bdaddr_t bt_bdaddr_local = {{0, 0, 0, 0xff, 0xff, 0xff}};
29
30 #endif
31
32 using namespace JSONRPC;
33 using namespace ANNOUNCEMENT;
34 //using namespace std; On VS2010, bind conflicts with std::bind
35
36 #define RECEIVEBUFFER 1024
37
38 CTCPServer *CTCPServer::ServerInstance = NULL;
39
40 bool CTCPServer::StartServer(int port, bool nonlocal)
41 {
42   StopServer(true);
43
44   ServerInstance = new CTCPServer(port, nonlocal);
45   if (ServerInstance->Initialize())
46   {
47     ServerInstance->Create();
48     return true;
49   }
50   else
51     return false;
52 }
53
54 void CTCPServer::StopServer(bool bWait)
55 {
56   if (ServerInstance)
57   {
58     ServerInstance->StopThread(bWait);
59     if (bWait)
60     {
61       delete ServerInstance;
62       ServerInstance = NULL;
63     }
64   }
65 }
66
67 CTCPServer::CTCPServer(int port, bool nonlocal)
68 {
69   m_port = port;
70   m_nonlocal = nonlocal;
71   m_sdpd = NULL;
72 }
73
74 void CTCPServer::Process()
75 {
76   m_bStop = false;
77
78   while (!m_bStop)
79   {
80     SOCKET          max_fd = 0;
81     fd_set          rfds;
82     struct timeval  to     = {1, 0};
83     FD_ZERO(&rfds);
84
85     for (std::vector<SOCKET>::iterator it = m_servers.begin(); it != m_servers.end(); it++)
86     {
87       FD_SET(*it, &rfds);
88       if ((intptr_t)*it > (intptr_t)max_fd)
89         max_fd = *it;
90     }
91
92     for (unsigned int i = 0; i < m_connections.size(); i++)
93     {
94       FD_SET(m_connections[i].m_socket, &rfds);
95       if ((intptr_t)m_connections[i].m_socket > (intptr_t)max_fd)
96         max_fd = m_connections[i].m_socket;
97     }
98
99     int res = select((intptr_t)max_fd+1, &rfds, NULL, NULL, &to);
100     if (res < 0)
101     {
102       CLog::Log(LOGERROR, "JSONRPC Server: Select failed");
103       Sleep(1000);
104       Initialize();
105     }
106     else if (res > 0)
107     {
108       for (int i = m_connections.size() - 1; i >= 0; i--)
109       {
110         int socket = m_connections[i].m_socket;
111         if (FD_ISSET(socket, &rfds))
112         {
113           char buffer[RECEIVEBUFFER] = {};
114           int  nread = 0;
115           nread = recv(socket, (char*)&buffer, RECEIVEBUFFER, 0);
116           if (nread > 0)
117           {
118             m_connections[i].PushBuffer(this, buffer, nread);
119           }
120           if (nread <= 0)
121           {
122             CLog::Log(LOGINFO, "JSONRPC Server: Disconnection detected");
123             m_connections[i].Disconnect();
124             m_connections.erase(m_connections.begin() + i);
125           }
126         }
127       }
128
129       for (std::vector<SOCKET>::iterator it = m_servers.begin(); it != m_servers.end(); it++)
130       {
131         if (FD_ISSET(*it, &rfds))
132         {
133           CLog::Log(LOGDEBUG, "JSONRPC Server: New connection detected");
134           CTCPClient newconnection;
135           newconnection.m_socket = accept(*it, (sockaddr*)&newconnection.m_cliaddr, &newconnection.m_addrlen);
136
137           if (newconnection.m_socket == INVALID_SOCKET)
138             CLog::Log(LOGERROR, "JSONRPC Server: Accept of new connection failed");
139           else
140           {
141             CLog::Log(LOGINFO, "JSONRPC Server: New connection added");
142             m_connections.push_back(newconnection);
143           }
144         }
145       }
146     }
147   }
148
149   Deinitialize();
150 }
151
152 bool CTCPServer::Download(const char *path, CVariant &result)
153 {
154   return false;
155 }
156
157 int CTCPServer::GetCapabilities()
158 {
159   return Response | Announcing;
160 }
161
162 void CTCPServer::Announce(EAnnouncementFlag flag, const char *sender, const char *message, const CVariant &data)
163 {
164   std::string str = AnnouncementToJSON(flag, sender, message, data, g_advancedSettings.m_jsonOutputCompact);
165
166   for (unsigned int i = 0; i < m_connections.size(); i++)
167   {
168     {
169       CSingleLock lock (m_connections[i].m_critSection);
170       if ((m_connections[i].GetAnnouncementFlags() & flag) == 0)
171         continue;
172     }
173
174     unsigned int sent = 0;
175     do
176     {
177       CSingleLock lock (m_connections[i].m_critSection);
178       sent += send(m_connections[i].m_socket, str.c_str(), str.size() - sent, sent);
179     } while (sent < str.size());
180   }
181 }
182
183 bool CTCPServer::Initialize()
184 {
185   Deinitialize();
186
187   bool started = false;
188
189   started |= InitializeBlue();
190   started |= InitializeTCP();
191
192   if(started)
193   {
194     CAnnouncementManager::AddAnnouncer(this);
195     CLog::Log(LOGINFO, "JSONRPC Server: Successfully initialized");
196     return true;
197   }
198   return false;
199 }
200
201 bool CTCPServer::InitializeBlue()
202 {
203   if(!m_nonlocal)
204     return false;
205
206 #ifdef _WIN32
207
208   SOCKET fd = socket (AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM);
209   if(fd == INVALID_SOCKET)
210   {
211     CLog::Log(LOGINFO, "JSONRPC Server: Unable to get bluetooth socket");
212     return false;
213   }
214   SOCKADDR_BTH sa  = {};
215   sa.addressFamily = AF_BTH;
216   sa.port          = BT_PORT_ANY;
217
218   if(bind(fd, (SOCKADDR*)&sa, sizeof(sa)) < 0)
219   {
220     CLog::Log(LOGINFO, "JSONRPC Server: Unable to bind to bluetooth socket");
221     closesocket(fd);
222     return false;
223   }
224
225   ULONG optval = TRUE;
226   if(setsockopt(fd, SOL_RFCOMM, SO_BTH_AUTHENTICATE, (const char*)&optval, sizeof(optval)) == SOCKET_ERROR)
227   {
228     CLog::Log(LOGERROR, "JSONRPC Server: Failed to force authentication for bluetooth socket");
229     closesocket(fd);
230     return false;
231   }
232
233   int len = sizeof(sa);
234   if(getsockname(fd, (SOCKADDR*)&sa, &len) < 0)
235     CLog::Log(LOGERROR, "JSONRPC Server: Failed to get bluetooth port");
236
237   if (listen(fd, 10) < 0)
238   {
239     CLog::Log(LOGERROR, "JSONRPC Server: Failed to listen to bluetooth port");
240     closesocket(fd);
241     return false;
242   }
243
244   m_servers.push_back(fd);
245
246   CSADDR_INFO addrinfo;
247   addrinfo.iProtocol   = BTHPROTO_RFCOMM;
248   addrinfo.iSocketType = SOCK_STREAM;
249   addrinfo.LocalAddr.lpSockaddr       = (SOCKADDR*)&sa;
250   addrinfo.LocalAddr.iSockaddrLength  = sizeof(sa);
251   addrinfo.RemoteAddr.lpSockaddr      = (SOCKADDR*)&sa;
252   addrinfo.RemoteAddr.iSockaddrLength = sizeof(sa);
253
254   WSAQUERYSET service = {};
255   service.dwSize = sizeof(service);
256   service.lpszServiceInstanceName = (LPSTR)bt_service_name;
257   service.lpServiceClassId        = (LPGUID)&bt_service_guid;
258   service.lpszComment             = (LPSTR)bt_service_desc;
259   service.dwNameSpace             = NS_BTH;
260   service.lpNSProviderId          = NULL; /* RFCOMM? */
261   service.lpcsaBuffer             = &addrinfo;
262   service.dwNumberOfCsAddrs       = 1;
263
264   if(WSASetService(&service, RNRSERVICE_REGISTER, 0) == SOCKET_ERROR)
265     CLog::Log(LOGERROR, "JSONRPC Server: failed to register bluetooth service error %d",  WSAGetLastError());
266
267   return true;
268 #endif
269
270 #ifdef HAVE_LIBBLUETOOTH
271
272   SOCKET fd = socket (AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
273   if(fd == INVALID_SOCKET)
274   {
275     CLog::Log(LOGINFO, "JSONRPC Server: Unable to get bluetooth socket");
276     return false;
277   }
278   struct sockaddr_rc sa  = {0};
279   sa.rc_family  = AF_BLUETOOTH;
280   sa.rc_bdaddr  = bt_bdaddr_any;
281   sa.rc_channel = 0;
282
283   if(bind(fd, (struct sockaddr*)&sa, sizeof(sa)) < 0)
284   {
285     CLog::Log(LOGINFO, "JSONRPC Server: Unable to bind to bluetooth socket");
286     closesocket(fd);
287     return false;
288   }
289
290   socklen_t len = sizeof(sa);
291   if(getsockname(fd, (struct sockaddr*)&sa, &len) < 0)
292     CLog::Log(LOGERROR, "JSONRPC Server: Failed to get bluetooth port");
293
294   if (listen(fd, 10) < 0)
295   {
296     CLog::Log(LOGERROR, "JSONRPC Server: Failed to listen to bluetooth port %d", sa.rc_channel);
297     closesocket(fd);
298     return false;
299   }
300
301   uint8_t rfcomm_channel = sa.rc_channel;
302
303   uuid_t root_uuid, l2cap_uuid, rfcomm_uuid, svc_uuid;
304   sdp_list_t *l2cap_list = 0,
305              *rfcomm_list = 0,
306              *root_list = 0,
307              *proto_list = 0,
308              *access_proto_list = 0,
309              *service_class = 0;
310
311   sdp_data_t *channel = 0;
312
313   sdp_record_t *record = sdp_record_alloc();
314
315   // set the general service ID
316   sdp_uuid128_create( &svc_uuid, &bt_service_guid );
317   sdp_set_service_id( record, svc_uuid );
318
319   // make the service record publicly browsable
320   sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
321   root_list = sdp_list_append(0, &root_uuid);
322   sdp_set_browse_groups( record, root_list );
323
324   // set l2cap information
325   sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
326   l2cap_list = sdp_list_append( 0, &l2cap_uuid );
327   proto_list = sdp_list_append( 0, l2cap_list );
328
329   // set rfcomm information
330   sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
331   channel = sdp_data_alloc(SDP_UINT8, &rfcomm_channel);
332   rfcomm_list = sdp_list_append( 0, &rfcomm_uuid );
333   sdp_list_append( rfcomm_list, channel );
334   sdp_list_append( proto_list, rfcomm_list );
335
336   // attach protocol information to service record
337   access_proto_list = sdp_list_append( 0, proto_list );
338   sdp_set_access_protos( record, access_proto_list );
339
340   // set the name, provider, and description
341   sdp_set_info_attr(record, bt_service_name, bt_service_prov, bt_service_desc);
342
343   // set the Service class ID
344   service_class = sdp_list_append(0, &svc_uuid);
345   sdp_set_service_classes( record, service_class);
346
347   // cleanup
348   sdp_data_free( channel );
349   sdp_list_free( l2cap_list, 0 );
350   sdp_list_free( rfcomm_list, 0 );
351   sdp_list_free( root_list, 0 );
352   sdp_list_free( access_proto_list, 0 );
353   sdp_list_free( service_class, 0 );
354
355   // connect to the local SDP server, register the service record
356   sdp_session_t *session = sdp_connect( &bt_bdaddr_any, &bt_bdaddr_local, SDP_RETRY_IF_BUSY );
357   if(session == NULL)
358   {
359     CLog::Log(LOGERROR, "JSONRPC Server: Failed to connect to sdpd");
360     closesocket(fd);
361     sdp_record_free(record);
362     return false;
363   }
364
365   if(sdp_record_register(session, record, 0) < 0)
366   {
367     CLog::Log(LOGERROR, "JSONRPC Server: Failed to register record with error %d", errno);
368     closesocket(fd);
369     sdp_close(session);
370     sdp_record_free(record);
371     return false;
372   }
373
374   m_sdpd = session;
375   m_servers.push_back(fd);
376
377   return true;
378 #endif
379   return false;
380 }
381
382 bool CTCPServer::InitializeTCP()
383 {
384
385   struct sockaddr_in myaddr;
386   memset(&myaddr, 0, sizeof(myaddr));
387
388   myaddr.sin_family = AF_INET;
389   myaddr.sin_port = htons(m_port);
390
391   if (m_nonlocal)
392     myaddr.sin_addr.s_addr = INADDR_ANY;
393   else
394     inet_pton(AF_INET, "127.0.0.1", &myaddr.sin_addr.s_addr);
395
396   SOCKET fd = socket(PF_INET, SOCK_STREAM, 0);
397
398   if (fd == INVALID_SOCKET)
399   {
400     CLog::Log(LOGERROR, "JSONRPC Server: Failed to create serversocket");
401     return false;
402   }
403
404   if (bind(fd, (struct sockaddr*)&myaddr, sizeof myaddr) < 0)
405   {
406     CLog::Log(LOGERROR, "JSONRPC Server: Failed to bind serversocket");
407     closesocket(fd);
408     return false;
409   }
410
411   if (listen(fd, 10) < 0)
412   {
413     CLog::Log(LOGERROR, "JSONRPC Server: Failed to set listen");
414     closesocket(fd);
415     return false;
416   }
417   m_servers.push_back(fd);
418   return true;
419 }
420
421 void CTCPServer::Deinitialize()
422 {
423   for (unsigned int i = 0; i < m_connections.size(); i++)
424     m_connections[i].Disconnect();
425
426   m_connections.clear();
427
428   for (unsigned int i = 0; i < m_servers.size(); i++)
429     closesocket(m_servers[i]);
430
431   m_servers.clear();
432
433 #ifdef HAVE_LIBBLUETOOTH
434   if(m_sdpd)
435     sdp_close( (sdp_session_t*)m_sdpd );
436   m_sdpd = NULL;
437 #endif
438
439   CAnnouncementManager::RemoveAnnouncer(this);
440 }
441
442 CTCPServer::CTCPClient::CTCPClient()
443 {
444   m_announcementflags = ANNOUNCE_ALL;
445   m_socket = INVALID_SOCKET;
446   m_beginBrackets = 0;
447   m_endBrackets = 0;
448   m_beginChar = 0;
449   m_endChar = 0;
450
451   m_addrlen = sizeof(m_cliaddr);
452 }
453
454 CTCPServer::CTCPClient::CTCPClient(const CTCPClient& client)
455 {
456   Copy(client);
457 }
458
459 CTCPServer::CTCPClient& CTCPServer::CTCPClient::operator=(const CTCPClient& client)
460 {
461   Copy(client);
462   return *this;
463 }
464
465 int CTCPServer::CTCPClient::GetPermissionFlags()
466 {
467   return OPERATION_PERMISSION_ALL;
468 }
469
470 int CTCPServer::CTCPClient::GetAnnouncementFlags()
471 {
472   return m_announcementflags;
473 }
474
475 bool CTCPServer::CTCPClient::SetAnnouncementFlags(int flags)
476 {
477   m_announcementflags = flags;
478   return true;
479 }
480
481 void CTCPServer::CTCPClient::PushBuffer(CTCPServer *host, const char *buffer, int length)
482 {
483   for (int i = 0; i < length; i++)
484   {
485     char c = buffer[i];
486
487     if (m_beginChar == 0 && c == '{')
488     {
489       m_beginChar = '{';
490       m_endChar = '}';
491     }
492     else if (m_beginChar == 0 && c == '[')
493     {
494       m_beginChar = '[';
495       m_endChar = ']';
496     }
497
498     if (m_beginChar != 0)
499     {
500       m_buffer.push_back(c);
501       if (c == m_beginChar)
502         m_beginBrackets++;
503       else if (c == m_endChar)
504         m_endBrackets++;
505       if (m_beginBrackets > 0 && m_endBrackets > 0 && m_beginBrackets == m_endBrackets)
506       {
507         std::string line = CJSONRPC::MethodCall(m_buffer, host, this);
508         CSingleLock lock (m_critSection);
509         send(m_socket, line.c_str(), line.size(), 0);
510         m_beginChar = m_beginBrackets = m_endBrackets = 0;
511         m_buffer.clear();
512       }
513     }
514   }
515 }
516
517 void CTCPServer::CTCPClient::Disconnect()
518 {
519   if (m_socket > 0)
520   {
521     CSingleLock lock (m_critSection);
522     shutdown(m_socket, SHUT_RDWR);
523     closesocket(m_socket);
524     m_socket = INVALID_SOCKET;
525   }
526 }
527
528 void CTCPServer::CTCPClient::Copy(const CTCPClient& client)
529 {
530   m_socket            = client.m_socket;
531   m_cliaddr           = client.m_cliaddr;
532   m_addrlen           = client.m_addrlen;
533   m_announcementflags = client.m_announcementflags;
534   m_beginBrackets     = client.m_beginBrackets;
535   m_endBrackets       = client.m_endBrackets;
536   m_beginChar         = client.m_beginChar;
537   m_endChar           = client.m_endChar;
538   m_buffer            = client.m_buffer;
539 }
540