PageRenderTime 48ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/addons/pvr.wmc/src/Socket.cpp

https://github.com/smuehlmann/xbmc-pvr-addons
C++ | 684 lines | 555 code | 92 blank | 37 comment | 56 complexity | 74d938d93d92e4f18320f647f53d8469 MD5 | raw file
Possible License(s): AGPL-1.0, GPL-2.0, LGPL-2.1, MIT, GPL-3.0
  1. /*
  2. * Copyright (C) 2005-2011 Team XBMC
  3. * http://www.xbmc.org
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. *
  18. */
  19. #include "libXBMC_addon.h"
  20. #include <string>
  21. #include "platform/os.h"
  22. #include "client.h"
  23. #include "Socket.h"
  24. #include "utilities.h"
  25. #include "platform/util/timeutils.h"
  26. #include "platform/threads/mutex.h"
  27. using namespace std;
  28. using namespace ADDON;
  29. PLATFORM::CMutex m_mutex;
  30. /* Master defines for client control */
  31. //#define RECEIVE_TIMEOUT 6 //sec
  32. Socket::Socket(const enum SocketFamily family, const enum SocketDomain domain, const enum SocketType type, const enum SocketProtocol protocol)
  33. {
  34. _sd = INVALID_SOCKET;
  35. _family = family;
  36. _domain = domain;
  37. _type = type;
  38. _protocol = protocol;
  39. memset (&_sockaddr, 0, sizeof( _sockaddr ) );
  40. //set_non_blocking(1);
  41. }
  42. Socket::Socket()
  43. {
  44. // Default constructor, default settings
  45. _sd = INVALID_SOCKET;
  46. _family = af_inet;
  47. _domain = pf_inet;
  48. _type = sock_stream;
  49. _protocol = tcp;
  50. memset (&_sockaddr, 0, sizeof( _sockaddr ) );
  51. }
  52. Socket::~Socket()
  53. {
  54. close();
  55. }
  56. bool Socket::setHostname ( const CStdString& host )
  57. {
  58. if (isalpha(host.c_str()[0]))
  59. {
  60. // host address is a name
  61. struct hostent *he = NULL;
  62. if ((he = gethostbyname( host.c_str() )) == 0)
  63. {
  64. errormessage( getLastError(), "Socket::setHostname");
  65. return false;
  66. }
  67. _sockaddr.sin_addr = *((in_addr *) he->h_addr);
  68. }
  69. else
  70. {
  71. _sockaddr.sin_addr.s_addr = inet_addr(host.c_str());
  72. }
  73. return true;
  74. }
  75. bool Socket::close()
  76. {
  77. if (is_valid())
  78. {
  79. if (_sd != SOCKET_ERROR)
  80. #ifdef TARGET_WINDOWS
  81. closesocket(_sd);
  82. #else
  83. ::close(_sd);
  84. #endif
  85. _sd = INVALID_SOCKET;
  86. osCleanup();
  87. return true;
  88. }
  89. return false;
  90. }
  91. int _timeout = 0;
  92. bool Socket::create()
  93. {
  94. if( is_valid() )
  95. {
  96. close();
  97. }
  98. if(!osInit())
  99. {
  100. return false;
  101. }
  102. _sd = socket(_family, _type, _protocol );
  103. //0 indicates that the default protocol for the type selected is to be used.
  104. //For example, IPPROTO_TCP is chosen for the protocol if the type was set to
  105. //SOCK_STREAM and the address family is AF_INET.
  106. if (_sd == INVALID_SOCKET)
  107. {
  108. errormessage( getLastError(), "Socket::create" );
  109. return false;
  110. }
  111. // if requested set a timeout for receiving data
  112. if (_timeout != 0)
  113. {
  114. struct timeval tv;
  115. tv.tv_sec = _timeout; // set the receive timeout desired
  116. tv.tv_usec = 0; // Not init'ing this can cause strange errors
  117. setsockopt(_sd, SOL_SOCKET, SO_RCVTIMEO, (char*)&tv,sizeof(struct timeval)); // set a receive timeout for this new socket
  118. _timeout = 0; // reset to default state of no timeout
  119. }
  120. return true;
  121. }
  122. int Socket::send( const CStdString& data )
  123. {
  124. if (!is_valid())
  125. {
  126. return 0;
  127. }
  128. int status = Socket::send( (const char*) data.c_str(), (const unsigned int) data.size());
  129. return status;
  130. }
  131. int Socket::send ( const char* data, const unsigned int len )
  132. {
  133. fd_set set_w, set_e;
  134. struct timeval tv;
  135. int result;
  136. if (!is_valid())
  137. {
  138. return 0;
  139. }
  140. // fill with new data
  141. tv.tv_sec = 0;
  142. tv.tv_usec = 0;
  143. FD_ZERO(&set_w);
  144. FD_ZERO(&set_e);
  145. FD_SET(_sd, &set_w);
  146. FD_SET(_sd, &set_e);
  147. result = select(FD_SETSIZE, &set_w, NULL, &set_e, &tv);
  148. if (result < 0)
  149. {
  150. XBMC->Log(LOG_ERROR, "Socket::send - select failed");
  151. _sd = INVALID_SOCKET;
  152. return 0;
  153. }
  154. if (FD_ISSET(_sd, &set_w))
  155. {
  156. XBMC->Log(LOG_ERROR, "Socket::send - failed to send data");
  157. _sd = INVALID_SOCKET;
  158. return 0;
  159. }
  160. int status = ::send(_sd, data, len, 0 );
  161. if (status == -1)
  162. {
  163. errormessage( getLastError(), "Socket::send");
  164. XBMC->Log(LOG_ERROR, "Socket::send - failed to send data");
  165. _sd = INVALID_SOCKET;
  166. }
  167. return status;
  168. }
  169. //Receive until error or \n
  170. bool Socket::ReadResponses(int &code, vector<CStdString> &lines)
  171. {
  172. int result;
  173. char buffer[4096]; // this buff size has to be known in server
  174. code = 0;
  175. bool readComplete = false;
  176. CStdString bigString = "";
  177. do
  178. {
  179. result = recv(_sd, buffer, sizeof(buffer) - 1, 0);
  180. if (result < 0) // if result is negative, the socket is bad
  181. {
  182. #ifdef TARGET_WINDOWS
  183. int errorCode = WSAGetLastError();
  184. XBMC->Log(LOG_DEBUG, "ReadResponse ERROR - recv failed, Err: %d", errorCode);
  185. #else
  186. XBMC->Log(LOG_DEBUG, "ReadResponse ERROR - recv failed");
  187. #endif
  188. code = 1;
  189. _sd = INVALID_SOCKET;
  190. return false;
  191. }
  192. if (result > 0) // if we got data from the server in this last pass
  193. {
  194. buffer[result] = 0; // insert end of string marker
  195. bigString.append(buffer); // accumulate all the reads
  196. }
  197. } while (result > 0); // keep reading until result returns '0', meaning server is done sending reponses
  198. if (EndsWith(bigString, "<EOF>"))
  199. {
  200. readComplete = true; // all server data has benn read
  201. lines = split(bigString, "<EOL>", true); // split each reponse by <EOL> delimiters
  202. lines.erase(lines.end() - 1); // erase <EOF> at end
  203. }
  204. else
  205. {
  206. XBMC->Log(LOG_DEBUG, "ReadResponse ERROR - <EOF> in read reponses not found");
  207. _sd = INVALID_SOCKET;
  208. }
  209. return readComplete;
  210. }
  211. bool Socket::connect ( const CStdString& host, const unsigned short port )
  212. {
  213. if ( !is_valid() )
  214. {
  215. return false;
  216. }
  217. _sockaddr.sin_family = (sa_family_t) _family;
  218. _sockaddr.sin_port = htons ( port );
  219. if ( !setHostname( host ) )
  220. {
  221. XBMC->Log(LOG_ERROR, "Socket::setHostname(%s) failed.\n", host.c_str());
  222. return false;
  223. }
  224. int status = ::connect ( _sd, reinterpret_cast<sockaddr*>(&_sockaddr), sizeof ( _sockaddr ) );
  225. if ( status == SOCKET_ERROR )
  226. {
  227. XBMC->Log(LOG_ERROR, "Socket::connect %s:%u\n", host.c_str(), port);
  228. errormessage( getLastError(), "Socket::connect" );
  229. return false;
  230. }
  231. return true;
  232. }
  233. bool Socket::reconnect()
  234. {
  235. if ( _sd != INVALID_SOCKET )
  236. {
  237. return true;
  238. }
  239. if( !create() )
  240. return false;
  241. int status = ::connect ( _sd, reinterpret_cast<sockaddr*>(&_sockaddr), sizeof ( _sockaddr ) );
  242. if ( status == SOCKET_ERROR )
  243. {
  244. errormessage( getLastError(), "Socket::connect" );
  245. return false;
  246. }
  247. return true;
  248. }
  249. bool Socket::is_valid() const
  250. {
  251. return (_sd != INVALID_SOCKET);
  252. }
  253. #if defined(TARGET_WINDOWS)
  254. bool Socket::set_non_blocking ( const bool b )
  255. {
  256. u_long iMode;
  257. if ( b )
  258. iMode = 1; // enable non_blocking
  259. else
  260. iMode = 0; // disable non_blocking
  261. if (ioctlsocket(_sd, FIONBIO, &iMode) == -1)
  262. {
  263. XBMC->Log(LOG_ERROR, "Socket::set_non_blocking - Can't set socket condition to: %i", iMode);
  264. return false;
  265. }
  266. return true;
  267. }
  268. void Socket::errormessage( int errnum, const char* functionname) const
  269. {
  270. const char* errmsg = NULL;
  271. switch (errnum)
  272. {
  273. case WSANOTINITIALISED:
  274. errmsg = "A successful WSAStartup call must occur before using this function.";
  275. break;
  276. case WSAENETDOWN:
  277. errmsg = "The network subsystem or the associated service provider has failed";
  278. break;
  279. case WSA_NOT_ENOUGH_MEMORY:
  280. errmsg = "Insufficient memory available";
  281. break;
  282. case WSA_INVALID_PARAMETER:
  283. errmsg = "One or more parameters are invalid";
  284. break;
  285. case WSA_OPERATION_ABORTED:
  286. errmsg = "Overlapped operation aborted";
  287. break;
  288. case WSAEINTR:
  289. errmsg = "Interrupted function call";
  290. break;
  291. case WSAEBADF:
  292. errmsg = "File handle is not valid";
  293. break;
  294. case WSAEACCES:
  295. errmsg = "Permission denied";
  296. break;
  297. case WSAEFAULT:
  298. errmsg = "Bad address";
  299. break;
  300. case WSAEINVAL:
  301. errmsg = "Invalid argument";
  302. break;
  303. case WSAENOTSOCK:
  304. errmsg = "Socket operation on nonsocket";
  305. break;
  306. case WSAEDESTADDRREQ:
  307. errmsg = "Destination address required";
  308. break;
  309. case WSAEMSGSIZE:
  310. errmsg = "Message too long";
  311. break;
  312. case WSAEPROTOTYPE:
  313. errmsg = "Protocol wrong type for socket";
  314. break;
  315. case WSAENOPROTOOPT:
  316. errmsg = "Bad protocol option";
  317. break;
  318. case WSAEPFNOSUPPORT:
  319. errmsg = "Protocol family not supported";
  320. break;
  321. case WSAEAFNOSUPPORT:
  322. errmsg = "Address family not supported by protocol family";
  323. break;
  324. case WSAEADDRINUSE:
  325. errmsg = "Address already in use";
  326. break;
  327. case WSAECONNRESET:
  328. errmsg = "Connection reset by peer";
  329. break;
  330. case WSAHOST_NOT_FOUND:
  331. errmsg = "Authoritative answer host not found";
  332. break;
  333. case WSATRY_AGAIN:
  334. errmsg = "Nonauthoritative host not found, or server failure";
  335. break;
  336. case WSAEISCONN:
  337. errmsg = "Socket is already connected";
  338. break;
  339. case WSAETIMEDOUT:
  340. errmsg = "Connection timed out";
  341. break;
  342. case WSAECONNREFUSED:
  343. errmsg = "Connection refused";
  344. break;
  345. case WSANO_DATA:
  346. errmsg = "Valid name, no data record of requested type";
  347. break;
  348. default:
  349. errmsg = "WSA Error";
  350. }
  351. XBMC->Log(LOG_ERROR, "%s: (Winsock error=%i) %s\n", functionname, errnum, errmsg);
  352. }
  353. int Socket::getLastError() const
  354. {
  355. return WSAGetLastError();
  356. }
  357. int Socket::win_usage_count = 0; //Declared static in Socket class
  358. bool Socket::osInit()
  359. {
  360. win_usage_count++;
  361. // initialize winsock:
  362. if (WSAStartup(MAKEWORD(2,2),&_wsaData) != 0)
  363. {
  364. return false;
  365. }
  366. WORD wVersionRequested = MAKEWORD(2,2);
  367. // check version
  368. if (_wsaData.wVersion != wVersionRequested)
  369. {
  370. return false;
  371. }
  372. return true;
  373. }
  374. void Socket::osCleanup()
  375. {
  376. win_usage_count--;
  377. if(win_usage_count == 0)
  378. {
  379. WSACleanup();
  380. }
  381. }
  382. #elif defined TARGET_LINUX || defined TARGET_DARWIN || defined TARGET_FREEBSD
  383. bool Socket::set_non_blocking ( const bool b )
  384. {
  385. int opts;
  386. opts = fcntl(_sd, F_GETFL);
  387. if ( opts < 0 )
  388. {
  389. return false;
  390. }
  391. if ( b )
  392. opts = ( opts | O_NONBLOCK );
  393. else
  394. opts = ( opts & ~O_NONBLOCK );
  395. if(fcntl (_sd , F_SETFL, opts) == -1)
  396. {
  397. XBMC->Log(LOG_ERROR, "Socket::set_non_blocking - Can't set socket flags to: %i", opts);
  398. return false;
  399. }
  400. return true;
  401. }
  402. void Socket::errormessage( int errnum, const char* functionname) const
  403. {
  404. const char* errmsg = NULL;
  405. switch ( errnum )
  406. {
  407. case EAGAIN: //same as EWOULDBLOCK
  408. errmsg = "EAGAIN: The socket is marked non-blocking and the requested operation would block";
  409. break;
  410. case EBADF:
  411. errmsg = "EBADF: An invalid descriptor was specified";
  412. break;
  413. case ECONNRESET:
  414. errmsg = "ECONNRESET: Connection reset by peer";
  415. break;
  416. case EDESTADDRREQ:
  417. errmsg = "EDESTADDRREQ: The socket is not in connection mode and no peer address is set";
  418. break;
  419. case EFAULT:
  420. errmsg = "EFAULT: An invalid userspace address was specified for a parameter";
  421. break;
  422. case EINTR:
  423. errmsg = "EINTR: A signal occurred before data was transmitted";
  424. break;
  425. case EINVAL:
  426. errmsg = "EINVAL: Invalid argument passed";
  427. break;
  428. case ENOTSOCK:
  429. errmsg = "ENOTSOCK: The argument is not a valid socket";
  430. break;
  431. case EMSGSIZE:
  432. errmsg = "EMSGSIZE: The socket requires that message be sent atomically, and the size of the message to be sent made this impossible";
  433. break;
  434. case ENOBUFS:
  435. errmsg = "ENOBUFS: The output queue for a network interface was full";
  436. break;
  437. case ENOMEM:
  438. errmsg = "ENOMEM: No memory available";
  439. break;
  440. case EPIPE:
  441. errmsg = "EPIPE: The local end has been shut down on a connection oriented socket";
  442. break;
  443. case EPROTONOSUPPORT:
  444. errmsg = "EPROTONOSUPPORT: The protocol type or the specified protocol is not supported within this domain";
  445. break;
  446. case EAFNOSUPPORT:
  447. errmsg = "EAFNOSUPPORT: The implementation does not support the specified address family";
  448. break;
  449. case ENFILE:
  450. errmsg = "ENFILE: Not enough kernel memory to allocate a new socket structure";
  451. break;
  452. case EMFILE:
  453. errmsg = "EMFILE: Process file table overflow";
  454. break;
  455. case EACCES:
  456. errmsg = "EACCES: Permission to create a socket of the specified type and/or protocol is denied";
  457. break;
  458. case ECONNREFUSED:
  459. errmsg = "ECONNREFUSED: A remote host refused to allow the network connection (typically because it is not running the requested service)";
  460. break;
  461. case ENOTCONN:
  462. errmsg = "ENOTCONN: The socket is associated with a connection-oriented protocol and has not been connected";
  463. break;
  464. //case E:
  465. // errmsg = "";
  466. // break;
  467. default:
  468. break;
  469. }
  470. XBMC->Log(LOG_ERROR, "%s: (errno=%i) %s\n", functionname, errnum, errmsg);
  471. }
  472. int Socket::getLastError() const
  473. {
  474. return errno;
  475. }
  476. bool Socket::osInit()
  477. {
  478. // Not needed for Linux
  479. return true;
  480. }
  481. void Socket::osCleanup()
  482. {
  483. // Not needed for Linux
  484. }
  485. #endif //TARGET_WINDOWS || TARGET_LINUX || TARGET_DARWIN || TARGET_FREEBSD
  486. void Socket::SetServerName(CStdString strServerName)
  487. {
  488. _serverName = strServerName;
  489. }
  490. void Socket::SetClientName(CStdString strClientName)
  491. {
  492. _clientName = strClientName;
  493. }
  494. void Socket::SetServerPort(int port)
  495. {
  496. _port = port;
  497. }
  498. int Socket::SendRequest(CStdString requestStr)
  499. {
  500. CStdString sRequest;
  501. sRequest.Format("%s|%s<Client Quit>", _clientName.c_str(), requestStr.c_str()); // build the request string
  502. int status = send(sRequest);
  503. return status;
  504. }
  505. // set a timeout for the next socket operation called, otherwise no timout is set
  506. void Socket::SetTimeOut(int tSec)
  507. {
  508. _timeout = tSec;
  509. }
  510. std::vector<CStdString> Socket::GetVector(const CStdString &request, bool allowRetry)
  511. {
  512. int maxAttempts = 3;
  513. int sleepAttempts = 1000;
  514. PLATFORM::CLockObject lock(m_mutex); // only process one request at a time
  515. int code;
  516. std::vector<CStdString> reponses;
  517. int cntAttempts = 1;
  518. while (cntAttempts <= maxAttempts)
  519. {
  520. XBMC->Log(LOG_DEBUG, "Socket::GetVector> Send request \"%s\"", request.c_str());
  521. reponses.clear();
  522. if (!create()) // create the socket
  523. {
  524. XBMC->Log(LOG_ERROR, "Socket::GetVector> error could not create socket");
  525. reponses.push_back("SocketError"); // set a SocketError message (not fatal)
  526. }
  527. else // socket created OK
  528. {
  529. if (!connect(_serverName, (unsigned short)_port)) // if this fails, it is likely due to server down
  530. {
  531. XBMC->Log(LOG_ERROR, "Socket::GetVector> Server is down");
  532. reponses.push_back("ServerDown"); // set a server down error message (not fatal)
  533. }
  534. else // connected to server
  535. {
  536. int bytesSent = SendRequest(request.c_str()); // send request to server
  537. if (bytesSent > 0) // if request was sent successfully
  538. {
  539. if (!ReadResponses(code, reponses))
  540. {
  541. XBMC->Log(LOG_ERROR, "Socket::GetVector> error getting responses");
  542. reponses.clear();
  543. reponses.push_back("SocketError");
  544. }
  545. else
  546. {
  547. break;
  548. }
  549. }
  550. else // error sending request
  551. {
  552. XBMC->Log(LOG_ERROR, "Socket::GetVector> error sending server request");
  553. reponses.push_back("SocketError");
  554. }
  555. }
  556. }
  557. if (!allowRetry)
  558. {
  559. break;
  560. }
  561. cntAttempts++;
  562. XBMC->Log(LOG_DEBUG, "Socket::GetVector> Retrying in %ims", sleepAttempts);
  563. usleep(sleepAttempts);
  564. }
  565. close(); // close socket
  566. return reponses; // return responses
  567. }
  568. CStdString Socket::GetString(const CStdString &request, bool allowRetry)
  569. {
  570. std::vector<CStdString> result = GetVector(request, allowRetry);
  571. return result[0];
  572. }
  573. bool Socket::GetBool(const CStdString &request, bool allowRetry)
  574. {
  575. return GetString(request, allowRetry) == "True";
  576. }
  577. int Socket::GetInt(const CStdString &request, bool allowRetry)
  578. {
  579. CStdString valStr = GetString(request, allowRetry);
  580. long val = strtol(valStr, 0, 10);
  581. return val;
  582. }
  583. long long Socket::GetLL(const CStdString &request, bool allowRetry)
  584. {
  585. CStdString valStr = GetString(request, allowRetry);
  586. #ifdef TARGET_WINDOWS
  587. long long val = _strtoi64(valStr, 0, 10);
  588. #else
  589. long long val = strtoll(valStr, NULL, 10);
  590. #endif
  591. return val;
  592. }