PageRenderTime 44ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/addons/pvr.mediaportal.tvserver/src/Socket.cpp

https://github.com/xhaggi/xbmc-pvr-addons
C++ | 725 lines | 569 code | 120 blank | 36 comment | 71 complexity | 5e694a5dbc91a4e233e01463a719bc22 MD5 | raw file
Possible License(s): GPL-3.0, AGPL-1.0, GPL-2.0, LGPL-2.1, MIT
  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 "utils.h"
  21. #include <string>
  22. #include "platform/os.h"
  23. #include "client.h"
  24. #include "Socket.h"
  25. using namespace std;
  26. using namespace ADDON;
  27. using namespace MPTV;
  28. namespace MPTV
  29. {
  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. }
  41. Socket::Socket()
  42. {
  43. // Default constructor, default settings
  44. _sd = INVALID_SOCKET;
  45. _family = af_inet;
  46. _domain = pf_inet;
  47. _type = sock_stream;
  48. _protocol = tcp;
  49. memset (&_sockaddr, 0, sizeof( _sockaddr ) );
  50. }
  51. Socket::~Socket()
  52. {
  53. close();
  54. }
  55. bool Socket::setHostname ( const std::string& host )
  56. {
  57. if (isalpha(host.c_str()[0]))
  58. {
  59. // host address is a name
  60. struct hostent *he = NULL;
  61. if ((he = gethostbyname( host.c_str() )) == 0)
  62. {
  63. errormessage( getLastError(), "Socket::setHostname");
  64. return false;
  65. }
  66. _sockaddr.sin_addr = *((in_addr *) he->h_addr);
  67. }
  68. else
  69. {
  70. _sockaddr.sin_addr.s_addr = inet_addr(host.c_str());
  71. }
  72. return true;
  73. }
  74. bool Socket::close()
  75. {
  76. if (is_valid())
  77. {
  78. if (_sd != SOCKET_ERROR)
  79. #ifdef TARGET_WINDOWS
  80. closesocket(_sd);
  81. #else
  82. ::close(_sd);
  83. #endif
  84. _sd = INVALID_SOCKET;
  85. osCleanup();
  86. return true;
  87. }
  88. return false;
  89. }
  90. bool Socket::create()
  91. {
  92. if( is_valid() )
  93. {
  94. close();
  95. }
  96. if(!osInit())
  97. {
  98. return false;
  99. }
  100. _sd = socket(_family, _type, _protocol );
  101. //0 indicates that the default protocol for the type selected is to be used.
  102. //For example, IPPROTO_TCP is chosen for the protocol if the type was set to
  103. //SOCK_STREAM and the address family is AF_INET.
  104. if (_sd == INVALID_SOCKET)
  105. {
  106. errormessage( getLastError(), "Socket::create" );
  107. return false;
  108. }
  109. return true;
  110. }
  111. bool Socket::bind ( const unsigned short port )
  112. {
  113. if (!is_valid())
  114. {
  115. return false;
  116. }
  117. _sockaddr.sin_family = (sa_family_t) _family;
  118. _sockaddr.sin_addr.s_addr = INADDR_ANY; //listen to all
  119. _sockaddr.sin_port = htons( port );
  120. int bind_return = ::bind(_sd, (sockaddr*)(&_sockaddr), sizeof(_sockaddr));
  121. if ( bind_return == -1 )
  122. {
  123. errormessage( getLastError(), "Socket::bind" );
  124. return false;
  125. }
  126. return true;
  127. }
  128. bool Socket::listen() const
  129. {
  130. if (!is_valid())
  131. {
  132. return false;
  133. }
  134. int listen_return = ::listen (_sd, SOMAXCONN);
  135. //This is defined as 5 in winsock.h, and 0x7FFFFFFF in winsock2.h.
  136. //linux 128//MAXCONNECTIONS =1
  137. if (listen_return == -1)
  138. {
  139. errormessage( getLastError(), "Socket::listen" );
  140. return false;
  141. }
  142. return true;
  143. }
  144. bool Socket::accept ( Socket& new_socket ) const
  145. {
  146. if (!is_valid())
  147. {
  148. return false;
  149. }
  150. socklen_t addr_length = sizeof( _sockaddr );
  151. new_socket._sd = ::accept(_sd, const_cast<sockaddr*>( (const sockaddr*) &_sockaddr), &addr_length );
  152. if (new_socket._sd <= 0)
  153. {
  154. errormessage( getLastError(), "Socket::accept" );
  155. return false;
  156. }
  157. return true;
  158. }
  159. int Socket::send ( const std::string& data )
  160. {
  161. return Socket::send( (const char*) data.c_str(), (const unsigned int) data.size());
  162. }
  163. int Socket::send ( const char* data, const unsigned int len )
  164. {
  165. fd_set set_w, set_e;
  166. struct timeval tv;
  167. int result;
  168. if (!is_valid())
  169. {
  170. return 0;
  171. }
  172. // fill with new data
  173. tv.tv_sec = 0;
  174. tv.tv_usec = 0;
  175. FD_ZERO(&set_w);
  176. FD_ZERO(&set_e);
  177. FD_SET(_sd, &set_w);
  178. FD_SET(_sd, &set_e);
  179. result = select(FD_SETSIZE, &set_w, NULL, &set_e, &tv);
  180. if (result < 0)
  181. {
  182. XBMC->Log(LOG_ERROR, "Socket::send - select failed");
  183. _sd = INVALID_SOCKET;
  184. return 0;
  185. }
  186. if (FD_ISSET(_sd, &set_w))
  187. {
  188. XBMC->Log(LOG_ERROR, "Socket::send - failed to send data");
  189. _sd = INVALID_SOCKET;
  190. return 0;
  191. }
  192. int status = ::send(_sd, data, len, 0 );
  193. if (status == -1)
  194. {
  195. errormessage( getLastError(), "Socket::send");
  196. XBMC->Log(LOG_ERROR, "Socket::send - failed to send data");
  197. _sd = INVALID_SOCKET;
  198. return 0;
  199. }
  200. return status;
  201. }
  202. int Socket::sendto ( const char* data, unsigned int size, bool sendcompletebuffer)
  203. {
  204. int sentbytes = 0;
  205. int i;
  206. do
  207. {
  208. i = ::sendto(_sd, data, size, 0, (const struct sockaddr*) &_sockaddr, sizeof( _sockaddr ) );
  209. if (i <= 0)
  210. {
  211. errormessage( getLastError(), "Socket::sendto");
  212. osCleanup();
  213. return i;
  214. }
  215. sentbytes += i;
  216. } while ( (sentbytes < (int) size) && (sendcompletebuffer == true));
  217. return i;
  218. }
  219. int Socket::receive ( std::string& data, unsigned int minpacketsize ) const
  220. {
  221. char * buf = NULL;
  222. int status = 0;
  223. if (!is_valid())
  224. {
  225. return 0;
  226. }
  227. buf = new char [ minpacketsize + 1 ];
  228. memset ( buf, 0, minpacketsize + 1 );
  229. status = receive( buf, minpacketsize, minpacketsize );
  230. data = buf;
  231. delete[] buf;
  232. return status;
  233. }
  234. //Receive until error or \n
  235. bool Socket::ReadLine (string& line)
  236. {
  237. fd_set set_r, set_e;
  238. timeval timeout;
  239. int result;
  240. int retries = 6;
  241. char buffer[2048];
  242. size_t pos1 = 0;
  243. if (!is_valid())
  244. return false;
  245. while (true)
  246. {
  247. if ((pos1 = line.find("\r\n", 0)) != std::string::npos)
  248. {
  249. line.erase(pos1, string::npos);
  250. return true;
  251. }
  252. timeout.tv_sec = RECEIVE_TIMEOUT;
  253. timeout.tv_usec = 0;
  254. // fill with new data
  255. FD_ZERO(&set_r);
  256. FD_ZERO(&set_e);
  257. FD_SET(_sd, &set_r);
  258. FD_SET(_sd, &set_e);
  259. result = select(FD_SETSIZE, &set_r, NULL, &set_e, &timeout);
  260. if (result < 0)
  261. {
  262. XBMC->Log(LOG_DEBUG, "%s: select failed", __FUNCTION__);
  263. errormessage(getLastError(), __FUNCTION__);
  264. _sd = INVALID_SOCKET;
  265. return false;
  266. }
  267. if (result == 0)
  268. {
  269. if (retries != 0)
  270. {
  271. XBMC->Log(LOG_DEBUG, "%s: timeout waiting for response, retrying... (%i)", __FUNCTION__, retries);
  272. retries--;
  273. continue;
  274. } else {
  275. XBMC->Log(LOG_DEBUG, "%s: timeout waiting for response. Aborting after 10 retries.", __FUNCTION__);
  276. return false;
  277. }
  278. }
  279. result = recv(_sd, buffer, sizeof(buffer) - 1, 0);
  280. if (result < 0)
  281. {
  282. XBMC->Log(LOG_DEBUG, "%s: recv failed", __FUNCTION__);
  283. errormessage(getLastError(), __FUNCTION__);
  284. _sd = INVALID_SOCKET;
  285. return false;
  286. }
  287. buffer[result] = 0;
  288. line.append(buffer);
  289. }
  290. return true;
  291. }
  292. int Socket::receive ( std::string& data) const
  293. {
  294. char buf[MAXRECV + 1];
  295. int status = 0;
  296. if ( !is_valid() )
  297. {
  298. return 0;
  299. }
  300. memset ( buf, 0, MAXRECV + 1 );
  301. status = receive( buf, MAXRECV, 0 );
  302. data = buf;
  303. return status;
  304. }
  305. int Socket::receive ( char* data, const unsigned int buffersize, const unsigned int minpacketsize ) const
  306. {
  307. unsigned int receivedsize = 0;
  308. int status = 0;
  309. if ( !is_valid() )
  310. {
  311. return 0;
  312. }
  313. while ( (receivedsize <= minpacketsize) && (receivedsize < buffersize) )
  314. {
  315. status = ::recv(_sd, data+receivedsize, (buffersize - receivedsize), 0 );
  316. if ( status == SOCKET_ERROR )
  317. {
  318. errormessage( getLastError(), "Socket::receive" );
  319. return status;
  320. }
  321. receivedsize += status;
  322. }
  323. return receivedsize;
  324. }
  325. int Socket::recvfrom ( char* data, const int buffersize, const int minpacketsize, struct sockaddr* from, socklen_t* fromlen) const
  326. {
  327. int status = ::recvfrom(_sd, data, buffersize, 0, from, fromlen);
  328. return status;
  329. }
  330. bool Socket::connect ( const std::string& host, const unsigned short port )
  331. {
  332. if ( !is_valid() )
  333. {
  334. return false;
  335. }
  336. _sockaddr.sin_family = (sa_family_t) _family;
  337. _sockaddr.sin_port = htons ( port );
  338. if ( !setHostname( host ) )
  339. {
  340. XBMC->Log(LOG_ERROR, "Socket::setHostname(%s) failed.\n", host.c_str());
  341. return false;
  342. }
  343. int status = ::connect ( _sd, reinterpret_cast<sockaddr*>(&_sockaddr), sizeof ( _sockaddr ) );
  344. if ( status == SOCKET_ERROR )
  345. {
  346. XBMC->Log(LOG_ERROR, "Socket::connect %s:%u\n", host.c_str(), port);
  347. errormessage( getLastError(), "Socket::connect" );
  348. return false;
  349. }
  350. return true;
  351. }
  352. bool Socket::reconnect()
  353. {
  354. if ( _sd != INVALID_SOCKET )
  355. {
  356. return true;
  357. }
  358. if( !create() )
  359. return false;
  360. int status = ::connect ( _sd, reinterpret_cast<sockaddr*>(&_sockaddr), sizeof ( _sockaddr ) );
  361. if ( status == SOCKET_ERROR )
  362. {
  363. errormessage( getLastError(), "Socket::connect" );
  364. return false;
  365. }
  366. return true;
  367. }
  368. bool Socket::is_valid() const
  369. {
  370. return (_sd != INVALID_SOCKET);
  371. }
  372. #if defined(TARGET_WINDOWS)
  373. bool Socket::set_non_blocking ( const bool b )
  374. {
  375. u_long iMode;
  376. if ( b )
  377. iMode = 1; // enable non_blocking
  378. else
  379. iMode = 0; // disable non_blocking
  380. if (ioctlsocket(_sd, FIONBIO, &iMode) == -1)
  381. {
  382. XBMC->Log(LOG_ERROR, "Socket::set_non_blocking - Can't set socket condition to: %i", iMode);
  383. return false;
  384. }
  385. return true;
  386. }
  387. void Socket::errormessage( int errnum, const char* functionname) const
  388. {
  389. const char* errmsg = NULL;
  390. switch (errnum)
  391. {
  392. case WSANOTINITIALISED:
  393. errmsg = "A successful WSAStartup call must occur before using this function.";
  394. break;
  395. case WSAENETDOWN:
  396. errmsg = "The network subsystem or the associated service provider has failed";
  397. break;
  398. case WSA_NOT_ENOUGH_MEMORY:
  399. errmsg = "Insufficient memory available";
  400. break;
  401. case WSA_INVALID_PARAMETER:
  402. errmsg = "One or more parameters are invalid";
  403. break;
  404. case WSA_OPERATION_ABORTED:
  405. errmsg = "Overlapped operation aborted";
  406. break;
  407. case WSAEINTR:
  408. errmsg = "Interrupted function call";
  409. break;
  410. case WSAEBADF:
  411. errmsg = "File handle is not valid";
  412. break;
  413. case WSAEACCES:
  414. errmsg = "Permission denied";
  415. break;
  416. case WSAEFAULT:
  417. errmsg = "Bad address";
  418. break;
  419. case WSAEINVAL:
  420. errmsg = "Invalid argument";
  421. break;
  422. case WSAENOTSOCK:
  423. errmsg = "Socket operation on nonsocket";
  424. break;
  425. case WSAEDESTADDRREQ:
  426. errmsg = "Destination address required";
  427. break;
  428. case WSAEMSGSIZE:
  429. errmsg = "Message too long";
  430. break;
  431. case WSAEPROTOTYPE:
  432. errmsg = "Protocol wrong type for socket";
  433. break;
  434. case WSAENOPROTOOPT:
  435. errmsg = "Bad protocol option";
  436. break;
  437. case WSAEPFNOSUPPORT:
  438. errmsg = "Protocol family not supported";
  439. break;
  440. case WSAEAFNOSUPPORT:
  441. errmsg = "Address family not supported by protocol family";
  442. break;
  443. case WSAEADDRINUSE:
  444. errmsg = "Address already in use";
  445. break;
  446. case WSAECONNRESET:
  447. errmsg = "Connection reset by peer";
  448. break;
  449. case WSAHOST_NOT_FOUND:
  450. errmsg = "Authoritative answer host not found";
  451. break;
  452. case WSATRY_AGAIN:
  453. errmsg = "Nonauthoritative host not found, or server failure";
  454. break;
  455. case WSAEISCONN:
  456. errmsg = "Socket is already connected";
  457. break;
  458. case WSAETIMEDOUT:
  459. errmsg = "Connection timed out";
  460. break;
  461. case WSAECONNREFUSED:
  462. errmsg = "Connection refused";
  463. break;
  464. case WSANO_DATA:
  465. errmsg = "Valid name, no data record of requested type";
  466. break;
  467. default:
  468. errmsg = "WSA Error";
  469. }
  470. XBMC->Log(LOG_ERROR, "%s: (Winsock error=%i) %s\n", functionname, errnum, errmsg);
  471. }
  472. int Socket::getLastError() const
  473. {
  474. return WSAGetLastError();
  475. }
  476. int Socket::win_usage_count = 0; //Declared static in Socket class
  477. bool Socket::osInit()
  478. {
  479. win_usage_count++;
  480. // initialize winsock:
  481. if (WSAStartup(MAKEWORD(2,2),&_wsaData) != 0)
  482. {
  483. return false;
  484. }
  485. WORD wVersionRequested = MAKEWORD(2,2);
  486. // check version
  487. if (_wsaData.wVersion != wVersionRequested)
  488. {
  489. return false;
  490. }
  491. return true;
  492. }
  493. void Socket::osCleanup()
  494. {
  495. win_usage_count--;
  496. if(win_usage_count == 0)
  497. {
  498. WSACleanup();
  499. }
  500. }
  501. #elif defined TARGET_LINUX || defined TARGET_DARWIN
  502. bool Socket::set_non_blocking ( const bool b )
  503. {
  504. int opts;
  505. opts = fcntl(_sd, F_GETFL);
  506. if ( opts < 0 )
  507. {
  508. return false;
  509. }
  510. if ( b )
  511. opts = ( opts | O_NONBLOCK );
  512. else
  513. opts = ( opts & ~O_NONBLOCK );
  514. if(fcntl (_sd , F_SETFL, opts) == -1)
  515. {
  516. XBMC->Log(LOG_ERROR, "Socket::set_non_blocking - Can't set socket flags to: %i", opts);
  517. return false;
  518. }
  519. return true;
  520. }
  521. void Socket::errormessage( int errnum, const char* functionname) const
  522. {
  523. const char* errmsg = NULL;
  524. switch ( errnum )
  525. {
  526. case EAGAIN: //same as EWOULDBLOCK
  527. errmsg = "EAGAIN: The socket is marked non-blocking and the requested operation would block";
  528. break;
  529. case EBADF:
  530. errmsg = "EBADF: An invalid descriptor was specified";
  531. break;
  532. case ECONNRESET:
  533. errmsg = "ECONNRESET: Connection reset by peer";
  534. break;
  535. case EDESTADDRREQ:
  536. errmsg = "EDESTADDRREQ: The socket is not in connection mode and no peer address is set";
  537. break;
  538. case EFAULT:
  539. errmsg = "EFAULT: An invalid userspace address was specified for a parameter";
  540. break;
  541. case EINTR:
  542. errmsg = "EINTR: A signal occurred before data was transmitted";
  543. break;
  544. case EINVAL:
  545. errmsg = "EINVAL: Invalid argument passed";
  546. break;
  547. case ENOTSOCK:
  548. errmsg = "ENOTSOCK: The argument is not a valid socket";
  549. break;
  550. case EMSGSIZE:
  551. errmsg = "EMSGSIZE: The socket requires that message be sent atomically, and the size of the message to be sent made this impossible";
  552. break;
  553. case ENOBUFS:
  554. errmsg = "ENOBUFS: The output queue for a network interface was full";
  555. break;
  556. case ENOMEM:
  557. errmsg = "ENOMEM: No memory available";
  558. break;
  559. case EPIPE:
  560. errmsg = "EPIPE: The local end has been shut down on a connection oriented socket";
  561. break;
  562. case EPROTONOSUPPORT:
  563. errmsg = "EPROTONOSUPPORT: The protocol type or the specified protocol is not supported within this domain";
  564. break;
  565. case EAFNOSUPPORT:
  566. errmsg = "EAFNOSUPPORT: The implementation does not support the specified address family";
  567. break;
  568. case ENFILE:
  569. errmsg = "ENFILE: Not enough kernel memory to allocate a new socket structure";
  570. break;
  571. case EMFILE:
  572. errmsg = "EMFILE: Process file table overflow";
  573. break;
  574. case EACCES:
  575. errmsg = "EACCES: Permission to create a socket of the specified type and/or protocol is denied";
  576. break;
  577. case ECONNREFUSED:
  578. errmsg = "ECONNREFUSED: A remote host refused to allow the network connection (typically because it is not running the requested service)";
  579. break;
  580. case ENOTCONN:
  581. errmsg = "ENOTCONN: The socket is associated with a connection-oriented protocol and has not been connected";
  582. break;
  583. //case E:
  584. // errmsg = "";
  585. // break;
  586. default:
  587. break;
  588. }
  589. XBMC->Log(LOG_ERROR, "%s: (errno=%i) %s\n", functionname, errnum, errmsg);
  590. }
  591. int Socket::getLastError() const
  592. {
  593. return errno;
  594. }
  595. bool Socket::osInit()
  596. {
  597. // Not needed for Linux
  598. return true;
  599. }
  600. void Socket::osCleanup()
  601. {
  602. // Not needed for Linux
  603. }
  604. #endif //TARGET_WINDOWS || TARGET_LINUX || TARGET_DARWIN
  605. } //namespace MPTV