PageRenderTime 7ms CodeModel.GetById 14ms app.highlight 40ms RepoModel.GetById 1ms app.codeStats 1ms

/addons/pvr.nextpvr/src/Socket.cpp

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