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