MythTV  master
msocketdevice_unix.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
4 **
5 ** This file is part of the Qt3Support module of the Qt Toolkit.
6 **
7 ** This file may be used under the terms of the GNU General Public
8 ** License versions 2.0 or 3.0 as published by the Free Software
9 ** Foundation and appearing in the files LICENSE.GPL2 and LICENSE.GPL3
10 ** included in the packaging of this file. Alternatively you may (at
11 ** your option) use any later version of the GNU General Public
12 ** License if such license has been publicly approved by Trolltech ASA
13 ** (or its successors, if any) and the KDE Free Qt Foundation. In
14 ** addition, as a special exception, Trolltech gives you certain
15 ** additional rights. These rights are described in the Trolltech GPL
16 ** Exception version 1.2, which can be found at
17 ** http://www.trolltech.com/products/qt/gplexception/ and in the file
18 ** GPL_EXCEPTION.txt in this package.
19 **
20 ** Please review the following information to ensure GNU General
21 ** Public Licensing requirements will be met:
22 ** http://trolltech.com/products/qt/licenses/licensing/opensource/. If
23 ** you are unsure which license is appropriate for your use, please
24 ** review the following information:
25 ** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
26 ** or contact the sales department at sales@trolltech.com.
27 **
28 ** In addition, as a special exception, Trolltech, as the sole
29 ** copyright holder for Qt Designer, grants users of the Qt/Eclipse
30 ** Integration plug-in the right for the Qt/Eclipse Integration to
31 ** link to functionality provided by Qt Designer and its related
32 ** libraries.
33 **
34 ** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
35 ** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
36 ** A PARTICULAR PURPOSE. Trolltech reserves all rights not expressly
37 ** granted herein.
38 **
39 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
40 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
41 **
42 ****************************************************************************/
43 
44 #include "qplatformdefs.h"
45 #include "mythlogging.h"
46 
47 #ifdef Q_OS_ANDROID
48 #include <sys/socket.h>
49 #include <linux/in.h>
50 #include <linux/in6.h>
51 #endif
52 
53 // Almost always the same. If not, specify in qplatformdefs.h.
54 #if !defined(QT_SOCKOPTLEN_T)
55 # define QT_SOCKOPTLEN_T QT_SOCKLEN_T
56 #endif
57 
58 // Tru64 redefines accept -> _accept with _XOPEN_SOURCE_EXTENDED
59 static inline int qt_socket_accept(int s, struct sockaddr *addr, QT_SOCKLEN_T *addrlen)
60 {
61  return ::accept(s, addr, addrlen);
62 }
63 
64 #if defined(accept)
65 # undef accept
66 #endif
67 
68 // UnixWare 7 redefines listen -> _listen
69 static inline int qt_socket_listen(int s, int backlog)
70 {
71  return ::listen(s, backlog);
72 }
73 
74 #if defined(listen)
75 # undef listen
76 #endif
77 
78 // UnixWare 7 redefines socket -> _socket
79 static inline int qt_socket_socket(int domain, int type, int protocol)
80 {
81  return ::socket(domain, type, protocol);
82 }
83 
84 #if defined(socket)
85 # undef socket
86 #endif
87 
88 #include "msocketdevice.h"
89 
90 #include "qwindowdefs.h"
91 
92 #include <errno.h>
93 #include <sys/types.h>
94 
95 static inline void qt_socket_getportaddr(struct sockaddr *sa,
96  quint16 *port, QHostAddress *addr)
97 {
98 
99  if (sa->sa_family == AF_INET6)
100  {
101 
102  struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa;
103  Q_IPV6ADDR tmp;
104  memcpy(&tmp, &sa6->sin6_addr.s6_addr, sizeof(tmp));
105  QHostAddress a(tmp);
106  *addr = a;
107  *port = ntohs(sa6->sin6_port);
108  return;
109  }
110 
111 
112  struct sockaddr_in *sa4 = (struct sockaddr_in *)sa;
113 
114  QHostAddress a(ntohl(sa4->sin_addr.s_addr));
115 
116  *port = ntohs(sa4->sin_port);
117 
118  *addr = QHostAddress(ntohl(sa4->sin_addr.s_addr));
119 
120  return;
121 }
122 
123 // internal
125 {
126 }
127 
128 
130 {
131  if (isValid())
132  {
133 
134  struct sockaddr_storage sa;
135  memset(&sa, 0, sizeof(sa));
136  QT_SOCKLEN_T sz = sizeof(sa);
137 
138  struct sockaddr *sap = reinterpret_cast<struct sockaddr *>(&sa);
139 
140  if (!::getsockname(fd, sap, &sz))
141  {
142  switch (sap->sa_family)
143  {
144 
145  case AF_INET:
146  return IPv4;
147 
148  case AF_INET6:
149  return IPv6;
150 
151  default:
152  return Unknown;
153  }
154  }
155 
156  }
157 
158  return Unknown;
159 }
160 
169 {
170  int s = qt_socket_socket(protocol() == IPv6 ? AF_INET6 : AF_INET,
171  t == Datagram ? SOCK_DGRAM : SOCK_STREAM, 0);
172 
173  if (s < 0)
174  {
175  switch (errno)
176  {
177 
178  case EPROTONOSUPPORT:
179  e = InternalError; // 0 is supposed to work for both types
180  break;
181 
182  case ENFILE:
183  e = NoFiles; // special case for this
184  break;
185 
186  case EACCES:
187  e = Inaccessible;
188  break;
189 
190  case ENOBUFS:
191 
192  case ENOMEM:
193  e = NoResources;
194  break;
195 
196  case EINVAL:
197  e = Impossible;
198  break;
199 
200  default:
201  e = UnknownError;
202  break;
203  }
204  }
205  else
206  {
207  return s;
208  }
209 
210  return -1;
211 }
212 
227 {
228  if (fd == -1 || !isOpen()) // already closed
229  return;
230 
231  setOpenMode(NotOpen);
232 
233  ::close(fd);
234 
235  LOG(VB_SOCKET, LOG_DEBUG,
236  QString("MSocketDevice::close: Closed socket %1").arg(fd));
237 
238  fd = -1;
239 
241 
242  QIODevice::close();
243 }
244 
245 
258 {
259  if (!isValid())
260  return true;
261 
262  int s = fcntl(fd, F_GETFL, 0);
263 
264  return !(s >= 0 && ((s & O_NDELAY) != 0));
265 }
266 
267 
282 void MSocketDevice::setBlocking(bool enable)
283 {
284  LOG(VB_SOCKET, LOG_DEBUG, QString("MSocketDevice::setBlocking(%1)")
285  .arg((enable) ? "true" : "false"));
286 
287  if (!isValid())
288  return;
289 
290  int tmp = ::fcntl(fd, F_GETFL, 0);
291 
292  if (tmp >= 0)
293  tmp = ::fcntl(fd, F_SETFL, enable ? (tmp & ~O_NDELAY) : (tmp | O_NDELAY));
294 
295  if (tmp >= 0)
296  return;
297 
298  if (e)
299  return;
300 
301  switch (errno)
302  {
303 
304  case EACCES:
305 
306  case EBADF:
307  e = Impossible;
308  break;
309 
310  case EFAULT:
311 
312  case EAGAIN:
313 #if EAGAIN != EWOULDBLOCK
314 
315  case EWOULDBLOCK:
316 #endif
317 
318  case EDEADLK:
319 
320  case EINTR:
321 
322  case EINVAL:
323 
324  case EMFILE:
325 
326  case ENOLCK:
327 
328  case EPERM:
329 
330  default:
331  e = UnknownError;
332  }
333 }
334 
335 
340 {
341  if (!isValid())
342  return -1;
343 
344  int n = -1;
345 
346  int v = -1;
347 
348  switch (opt)
349  {
350 
351  case Broadcast:
352  n = SO_BROADCAST;
353  break;
354 
355  case ReceiveBuffer:
356  n = SO_RCVBUF;
357  break;
358 
359  case ReuseAddress:
360  n = SO_REUSEADDR;
361  break;
362 
363  case SendBuffer:
364  n = SO_SNDBUF;
365  break;
366 
367  case Keepalive:
368  n = SO_KEEPALIVE;
369  break;
370  }
371 
372  if (n != -1)
373  {
374  QT_SOCKOPTLEN_T len;
375  len = sizeof(v);
376  int r = ::getsockopt(fd, SOL_SOCKET, n, (char*) & v, &len);
377 
378  if (r >= 0)
379  return v;
380 
381  if (!e)
382  {
383  MSocketDevice *that = (MSocketDevice*)this; // mutable function
384 
385  switch (errno)
386  {
387 
388  case EBADF:
389 
390  case ENOTSOCK:
391  that->e = Impossible;
392  break;
393 
394  case EFAULT:
395  that->e = InternalError;
396  break;
397 
398  default:
399  that->e = UnknownError;
400  break;
401  }
402  }
403 
404  return -1;
405  }
406 
407  return v;
408 }
409 
410 
415 {
416  if (!isValid())
417  return;
418 
419  int n = -1; // for really, really bad compilers
420 
421  switch (opt)
422  {
423 
424  case Broadcast:
425  n = SO_BROADCAST;
426  break;
427 
428  case ReceiveBuffer:
429  n = SO_RCVBUF;
430  break;
431 
432  case ReuseAddress:
433  n = SO_REUSEADDR;
434  break;
435 
436  case SendBuffer:
437  n = SO_SNDBUF;
438  break;
439 
440  case Keepalive:
441  n = SO_KEEPALIVE;
442  break;
443 
444  default:
445  return;
446  }
447 
448  if (::setsockopt(fd, SOL_SOCKET, n, (char*)&v, sizeof(v)) < 0 &&
449  e == NoError)
450  {
451  switch (errno)
452  {
453 
454  case EBADF:
455 
456  case ENOTSOCK:
457  e = Impossible;
458  break;
459 
460  case EFAULT:
461  e = InternalError;
462  break;
463 
464  default:
465  e = UnknownError;
466  break;
467  }
468  }
469 }
470 
471 
481 bool MSocketDevice::connect(const QHostAddress &addr, quint16 port)
482 {
483  if (isValid() && addr.protocol() != pa.protocol())
484  {
485  close();
486  fd = -1;
487  }
488 
489  if (!isValid())
490  {
491 
492  if (addr.protocol() == QAbstractSocket::IPv6Protocol)
493  {
494  setProtocol(IPv6);
495  LOG(VB_SOCKET, LOG_INFO,
496  "MSocketDevice::connect: setting Protocol to IPv6");
497  }
498  else
499  if (addr.protocol() == QAbstractSocket::IPv4Protocol)
500  {
501  setProtocol(IPv4);
502  LOG(VB_SOCKET, LOG_INFO,
503  "MSocketDevice::connect: setting Protocol to IPv4");
504  }
505 
506  LOG(VB_SOCKET, LOG_INFO,
507 
508  "MSocketDevice::connect: attempting to create new socket");
510 
511  // If still not valid, give up.
512 
513  if (!isValid())
514  return false;
515  }
516 
517  pa = addr;
518 
519  pp = port;
520 
521  struct sockaddr_in a4;
522 
523  struct sockaddr *aa;
524  QT_SOCKLEN_T aalen;
525 
526 
527  struct sockaddr_in6 a6;
528 
529  if (addr.protocol() == QAbstractSocket::IPv6Protocol)
530  {
531  memset(&a6, 0, sizeof(a6));
532  a6.sin6_family = AF_INET6;
533  a6.sin6_port = htons(port);
534  Q_IPV6ADDR ip6 = addr.toIPv6Address();
535  memcpy(&a6.sin6_addr.s6_addr, &ip6, sizeof(ip6));
536 
537  aalen = sizeof(a6);
538  aa = (struct sockaddr *) & a6;
539  }
540  else
541  if (addr.protocol() == QAbstractSocket::IPv4Protocol)
542  {
543  memset(&a4, 0, sizeof(a4));
544  a4.sin_family = AF_INET;
545  a4.sin_port = htons(port);
546  a4.sin_addr.s_addr = htonl(addr.toIPv4Address());
547 
548  aalen = sizeof(a4);
549  aa = (struct sockaddr *) & a4;
550  }
551  else
552  {
553  e = Impossible;
554  return false;
555  }
556 
557  int r = QT_SOCKET_CONNECT(fd, aa, aalen);
558 
559  if (r == 0)
560  {
562  return true;
563  }
564 
565  if (errno == EISCONN || errno == EALREADY || errno == EINPROGRESS)
566  {
568  return true;
569  }
570 
571  if (e != NoError || errno == EAGAIN || errno == EWOULDBLOCK)
572  {
573  return false;
574  }
575 
576  switch (errno)
577  {
578 
579  case EBADF:
580 
581  case ENOTSOCK:
582  e = Impossible;
583  break;
584 
585  case EFAULT:
586 
587  case EAFNOSUPPORT:
588  e = InternalError;
589  break;
590 
591  case ECONNREFUSED:
593  break;
594 
595  case ETIMEDOUT:
596 
597  case ENETUNREACH:
598  e = NetworkFailure;
599  break;
600 
601  case EADDRINUSE:
602  e = NoResources;
603  break;
604 
605  case EACCES:
606 
607  case EPERM:
608  e = Inaccessible;
609  break;
610 
611  default:
612  e = UnknownError;
613  break;
614  }
615 
616  return false;
617 }
618 
619 
629 bool MSocketDevice::bind(const QHostAddress &address, quint16 port)
630 {
631  if (!isValid())
632  return false;
633 
634  int r;
635 
636  struct sockaddr_in a4;
637 
638 
639  struct sockaddr_in6 a6;
640 
641  if (address.protocol() == QAbstractSocket::IPv6Protocol)
642  {
643  memset(&a6, 0, sizeof(a6));
644  a6.sin6_family = AF_INET6;
645  a6.sin6_port = htons(port);
646  Q_IPV6ADDR tmp = address.toIPv6Address();
647  memcpy(&a6.sin6_addr.s6_addr, &tmp, sizeof(tmp));
648 
649  r = QT_SOCKET_BIND(fd, (struct sockaddr *) & a6, sizeof(a6));
650  }
651  else
652  if (address.protocol() == QAbstractSocket::IPv4Protocol)
653  {
654  memset(&a4, 0, sizeof(a4));
655  a4.sin_family = AF_INET;
656  a4.sin_port = htons(port);
657  a4.sin_addr.s_addr = htonl(address.toIPv4Address());
658 
659  r = QT_SOCKET_BIND(fd, (struct sockaddr*) & a4, sizeof(a4));
660  }
661  else
662  {
663  e = Impossible;
664  return false;
665  }
666 
667  if (r < 0)
668  {
669  switch (errno)
670  {
671 
672  case EINVAL:
673  e = AlreadyBound;
674  break;
675 
676  case EACCES:
677  e = Inaccessible;
678  break;
679 
680  case ENOMEM:
681  e = NoResources;
682  break;
683 
684  case EFAULT: // a was illegal
685 
686  case ENAMETOOLONG: // sz was wrong
687  e = InternalError;
688  break;
689 
690  case EBADF: // AF_UNIX only
691 
692  case ENOTSOCK: // AF_UNIX only
693 
694  case EROFS: // AF_UNIX only
695 
696  case ENOENT: // AF_UNIX only
697 
698  case ENOTDIR: // AF_UNIX only
699 
700  case ELOOP: // AF_UNIX only
701  e = Impossible;
702  break;
703 
704  default:
705  e = UnknownError;
706  break;
707  }
708 
709  return false;
710  }
711 
713 
714  return true;
715 }
716 
717 
729 bool MSocketDevice::listen(int backlog)
730 {
731  if (!isValid())
732  return false;
733 
734  if (qt_socket_listen(fd, backlog) >= 0)
735  return true;
736 
737  if (!e)
738  e = Impossible;
739 
740  return false;
741 }
742 
743 
752 {
753  if (!isValid())
754  return -1;
755 
756  struct sockaddr_storage aa;
757 
758  QT_SOCKLEN_T l = sizeof(aa);
759 
760  bool done;
761 
762  int s;
763 
764  do
765  {
766  s = qt_socket_accept(fd, (struct sockaddr*) & aa, &l);
767  // we'll blithely throw away the stuff accept() wrote to aa
768  done = true;
769 
770  if (s < 0 && e == NoError)
771  {
772  switch (errno)
773  {
774 
775  case EINTR:
776  done = false;
777  break;
778 #if defined(EPROTO)
779 
780  case EPROTO:
781 #endif
782 #if defined(ENONET)
783 
784  case ENONET:
785 #endif
786 
787  case ENOPROTOOPT:
788 
789  case EHOSTDOWN:
790 
791  case EOPNOTSUPP:
792 
793  case EHOSTUNREACH:
794 
795  case ENETDOWN:
796 
797  case ENETUNREACH:
798 
799  case ETIMEDOUT:
800  // in all these cases, an error happened during connection
801  // setup. we're not interested in what happened, so we
802  // just treat it like the client-closed-quickly case.
803 
804  case EPERM:
805  // firewalling wouldn't let us accept. we treat it like
806  // the client-closed-quickly case.
807 
808  case EAGAIN:
809 #if EAGAIN != EWOULDBLOCK
810 
811  case EWOULDBLOCK:
812 #endif
813  // the client closed the connection before we got around
814  // to accept()ing it.
815  break;
816 
817  case EBADF:
818 
819  case ENOTSOCK:
820  e = Impossible;
821  break;
822 
823  case EFAULT:
824  e = InternalError;
825  break;
826 
827  case ENOMEM:
828 
829  case ENOBUFS:
830  e = NoResources;
831  break;
832 
833  default:
834  e = UnknownError;
835  break;
836  }
837  }
838  }
839  while (!done);
840 
841  return s;
842 }
843 
844 
857 {
858  if (!isValid())
859  return -1;
860 
861  /*
862  Apparently, there is not consistency among different operating
863  systems on how to use FIONREAD.
864 
865  FreeBSD, Linux and Solaris all expect the 3rd argument to
866  ioctl() to be an int, which is normally 32-bit even on 64-bit
867  machines.
868 
869  IRIX, on the other hand, expects a size_t, which is 64-bit on
870  64-bit machines.
871 
872  So, the solution is to use size_t initialized to zero to make
873  sure all bits are set to zero, preventing underflow with the
874  FreeBSD/Linux/Solaris ioctls.
875  */
876  union { size_t st;
877  int i;
878  } nbytes;
879 
880  nbytes.st = 0;
881 
882  // gives shorter than true amounts on Unix domain sockets.
883 
884  if (::ioctl(fd, FIONREAD, (char*)&nbytes.i) < 0)
885  return -1;
886 
887  return (qint64) nbytes.i + QIODevice::bytesAvailable();
888 }
889 
890 
909 qint64 MSocketDevice::waitForMore(int msecs, bool *timeout) const
910 {
911  if (!isValid())
912  return -1;
913 
914  if (fd >= static_cast<int>(FD_SETSIZE))
915  return -1;
916 
917  fd_set fds;
918 
919  struct timeval tv;
920 
921  FD_ZERO(&fds);
922 
923  FD_SET(fd, &fds);
924 
925  tv.tv_sec = msecs / 1000;
926 
927  tv.tv_usec = (msecs % 1000) * 1000;
928 
929  int rv = select(fd + 1, &fds, 0, 0, msecs < 0 ? 0 : &tv);
930 
931  if (rv < 0)
932  return -1;
933 
934  if (timeout)
935  {
936  if (rv == 0)
937  *timeout = true;
938  else
939  *timeout = false;
940  }
941 
942  return bytesAvailable();
943 }
944 
945 
950 qint64 MSocketDevice::readData(char *data, qint64 maxlen)
951 {
952 
953  struct sockaddr_storage aa;
954 
955  if (maxlen == 0)
956  {
957  // Cannot short circuit on zero bytes for datagram because zero-
958  // byte datagrams are a real thing and if you don't issue a read
959  // then select() will keep falling through
960  if (t == Datagram)
961  {
962  QT_SOCKLEN_T sz;
963  sz = sizeof(aa);
964  ::recvfrom(fd, data, 0, 0, (struct sockaddr *) & aa, &sz);
965  qt_socket_getportaddr((struct sockaddr *)&aa, &pp, &pa);
966  }
967  return 0;
968  }
969 
970  if (data == 0)
971  {
972  LOG(VB_SOCKET, LOG_DEBUG,
973  "MSocketDevice::readBlock: Null pointer error");
974  return -1;
975  }
976 
977  if (!isValid())
978  {
979  LOG(VB_SOCKET, LOG_DEBUG,
980  "MSocketDevice::readBlock: Invalid socket");
981  return -1;
982  }
983 
984  if (!isOpen())
985  {
986  LOG(VB_SOCKET, LOG_DEBUG,
987  "MSocketDevice::readBlock: Device is not open");
988  return -1;
989  }
990 
991  if (!isReadable())
992  {
993  LOG(VB_SOCKET, LOG_DEBUG,
994  "MSocketDevice::readBlock: Read operation not permitted");
995  return -1;
996  }
997 
998  bool done = false;
999 
1000  int r = 0;
1001 
1002  while (done == false)
1003  {
1004  if (t == Datagram)
1005  {
1006  memset(&aa, 0, sizeof(aa));
1007  QT_SOCKLEN_T sz;
1008  sz = sizeof(aa);
1009  r = ::recvfrom(fd, data, maxlen, 0,
1010  (struct sockaddr *) & aa, &sz);
1011 
1012  qt_socket_getportaddr((struct sockaddr *)&aa, &pp, &pa);
1013 
1014  }
1015  else
1016  {
1017  r = ::read(fd, data, maxlen);
1018  }
1019 
1020  done = true;
1021 
1022  if (r == 0 && t == Stream && maxlen > 0)
1023  {
1024  // connection closed
1025  close();
1026  }
1027  else if (r >= 0 || errno == EAGAIN || errno == EWOULDBLOCK)
1028  {
1029  // nothing
1030  }
1031  else if (errno == EINTR)
1032  {
1033  done = false;
1034  }
1035  else if (e == NoError)
1036  {
1037  switch (errno)
1038  {
1039 
1040  case EIO:
1041 
1042  case EISDIR:
1043 
1044  case EBADF:
1045 
1046  case EINVAL:
1047 
1048  case EFAULT:
1049 
1050  case ENOTCONN:
1051 
1052  case ENOTSOCK:
1053  e = Impossible;
1054  break;
1055 #if defined(ENONET)
1056 
1057  case ENONET:
1058 #endif
1059 
1060  case EHOSTUNREACH:
1061 
1062  case ENETDOWN:
1063 
1064  case ENETUNREACH:
1065 
1066  case ETIMEDOUT:
1067  e = NetworkFailure;
1068  break;
1069 
1070  case EPIPE:
1071 
1072  case ECONNRESET:
1073  // connection closed
1074  close();
1075  r = 0;
1076  break;
1077 
1078  default:
1079  e = UnknownError;
1080  break;
1081  }
1082  }
1083  }
1084 
1085  return r;
1086 }
1087 
1088 
1095 qint64 MSocketDevice::writeData(const char *data, qint64 len)
1096 {
1097  if (len == 0)
1098  return 0;
1099 
1100  if (data == 0)
1101  {
1102  LOG(VB_SOCKET, LOG_DEBUG,
1103  "MSocketDevice::writeBlock: Null pointer error");
1104  return -1;
1105  }
1106 
1107  if (!isValid())
1108  {
1109  LOG(VB_SOCKET, LOG_DEBUG,
1110  "MSocketDevice::writeBlock: Invalid socket");
1111  return -1;
1112  }
1113 
1114  if (!isOpen())
1115  {
1116  LOG(VB_SOCKET, LOG_DEBUG,
1117  "MSocketDevice::writeBlock: Device is not open");
1118  return -1;
1119  }
1120 
1121  if (!isWritable())
1122  {
1123  LOG(VB_SOCKET, LOG_DEBUG,
1124  "MSocketDevice::writeBlock: Write operation not permitted");
1125  return -1;
1126  }
1127 
1128  bool done = false;
1129 
1130  int r = 0;
1131  bool timeout;
1132 
1133  while (!done)
1134  {
1135  r = ::write(fd, data, len);
1136  done = true;
1137 
1138  if (r < 0 && e == NoError &&
1139  errno != EAGAIN && errno != EWOULDBLOCK)
1140  {
1141  switch (errno)
1142  {
1143 
1144  case EINTR: // signal - call read() or whatever again
1145  done = false;
1146  break;
1147 
1148  case EPIPE:
1149 
1150  case ECONNRESET:
1151  // connection closed
1152  close();
1153  r = 0;
1154  break;
1155 
1156  case ENOSPC:
1157 
1158  case EIO:
1159 
1160  case EISDIR:
1161 
1162  case EBADF:
1163 
1164  case EINVAL:
1165 
1166  case EFAULT:
1167 
1168  case ENOTCONN:
1169 
1170  case ENOTSOCK:
1171  e = Impossible;
1172  break;
1173 #if defined(ENONET)
1174 
1175  case ENONET:
1176 #endif
1177 
1178  case EHOSTUNREACH:
1179 
1180  case ENETDOWN:
1181 
1182  case ENETUNREACH:
1183 
1184  case ETIMEDOUT:
1185  e = NetworkFailure;
1186  break;
1187 
1188  default:
1189  e = UnknownError;
1190  break;
1191  }
1192  }
1193  else if (waitForMore(0, &timeout) == 0)
1194  {
1195  if (!timeout)
1196  {
1197  // connection closed
1198  close();
1199  }
1200  }
1201  }
1202 
1203  return r;
1204 }
1205 
1206 
1216 qint64 MSocketDevice::writeBlock(const char * data, quint64 len,
1217  const QHostAddress & host, quint16 port)
1218 {
1219  if (len == 0)
1220  return 0;
1221 
1222  if (t != Datagram)
1223  {
1224  LOG(VB_SOCKET, LOG_DEBUG,
1225  "MSocketDevice::sendBlock: Not datagram");
1226  return -1; // for now - later we can do t/tcp
1227  }
1228 
1229  if (data == 0)
1230  {
1231  LOG(VB_SOCKET, LOG_DEBUG,
1232  "MSocketDevice::sendBlock: Null pointer error");
1233  return -1;
1234  }
1235 
1236  if (!isValid())
1237  {
1238  LOG(VB_SOCKET, LOG_DEBUG,
1239  "MSocketDevice::sendBlock: Invalid socket");
1240  return -1;
1241  }
1242 
1243  if (!isOpen())
1244  {
1245  LOG(VB_SOCKET, LOG_DEBUG,
1246  "MSocketDevice::sendBlock: Device is not open");
1247  return -1;
1248  }
1249 
1250  if (!isWritable())
1251  {
1252  LOG(VB_SOCKET, LOG_DEBUG,
1253  "MSocketDevice::sendBlock: Write operation not permitted");
1254  return -1;
1255  }
1256 
1257  struct sockaddr_in a4;
1258 
1259  struct sockaddr *aa;
1260 
1261  QT_SOCKLEN_T slen;
1262 
1263 
1264  struct sockaddr_in6 a6;
1265 
1266  if (host.protocol() == QAbstractSocket::IPv6Protocol)
1267  {
1268  memset(&a6, 0, sizeof(a6));
1269  a6.sin6_family = AF_INET6;
1270  a6.sin6_port = htons(port);
1271 
1272  Q_IPV6ADDR tmp = host.toIPv6Address();
1273  memcpy(&a6.sin6_addr.s6_addr, &tmp, sizeof(tmp));
1274  slen = sizeof(a6);
1275  aa = (struct sockaddr *) & a6;
1276  }
1277  else
1278  if (host.protocol() == QAbstractSocket::IPv4Protocol)
1279  {
1280  memset(&a4, 0, sizeof(a4));
1281  a4.sin_family = AF_INET;
1282  a4.sin_port = htons(port);
1283  a4.sin_addr.s_addr = htonl(host.toIPv4Address());
1284  slen = sizeof(a4);
1285  aa = (struct sockaddr *) & a4;
1286  }
1287  else
1288  {
1289  e = Impossible;
1290  return -1;
1291  }
1292 
1293  // we'd use MSG_DONTWAIT + MSG_NOSIGNAL if Stevens were right.
1294  // but apparently Stevens and most implementors disagree
1295  bool done = false;
1296 
1297  int r = 0;
1298 
1299  while (!done)
1300  {
1301  r = ::sendto(fd, data, len, 0, aa, slen);
1302  done = true;
1303 
1304  if (r < 0 && e == NoError &&
1305  errno != EAGAIN && errno != EWOULDBLOCK)
1306  {
1307  switch (errno)
1308  {
1309 
1310  case EINTR: // signal - call read() or whatever again
1311  done = false;
1312  break;
1313 
1314  case ENOSPC:
1315 
1316  case EPIPE:
1317 
1318  case EIO:
1319 
1320  case EISDIR:
1321 
1322  case EBADF:
1323 
1324  case EINVAL:
1325 
1326  case EFAULT:
1327 
1328  case ENOTCONN:
1329 
1330  case ENOTSOCK:
1331  e = Impossible;
1332  break;
1333 #if defined(ENONET)
1334 
1335  case ENONET:
1336 #endif
1337 
1338  case EHOSTUNREACH:
1339 
1340  case ENETDOWN:
1341 
1342  case ENETUNREACH:
1343 
1344  case ETIMEDOUT:
1345  e = NetworkFailure;
1346  break;
1347 
1348  default:
1349  e = UnknownError;
1350  break;
1351  }
1352  }
1353  }
1354 
1355  return r;
1356 }
1357 
1358 
1364 {
1365  if (!isValid())
1366  {
1367  p = 0;
1368  a = QHostAddress();
1369  pp = 0;
1370  pa = QHostAddress();
1371  return;
1372  }
1373 
1374  struct sockaddr_storage sa;
1375 
1376  memset(&sa, 0, sizeof(sa));
1377 
1378  QT_SOCKLEN_T sz;
1379 
1380  sz = sizeof(sa);
1381 
1382  if (!::getsockname(fd, (struct sockaddr *)(&sa), &sz))
1383  qt_socket_getportaddr((struct sockaddr *)&sa, &p, &a);
1384 
1385  sz = sizeof(sa);
1386 
1387  if (!::getpeername(fd, (struct sockaddr *)(&sa), &sz))
1388  qt_socket_getportaddr((struct sockaddr *)&sa, &pp, &pa);
1389 }
1390 
1391 
1401 {
1402  return pp;
1403 }
1404 
1405 
1414 QHostAddress MSocketDevice::peerAddress() const
1415 {
1416  return pa;
1417 }
1418 
def write(text, progress=True)
Definition: mythburn.py:279
uint64_t l
Definition: alpha_asm.h:68
virtual quint16 peerPort() const
virtual QHostAddress peerAddress() const
virtual quint16 port() const
virtual void setOption(Option, int)
int option(Option) const
QHostAddress pa
virtual void setBlocking(bool)
virtual void setSocket(int socket, Type type)
void setProtocol(Protocol protocol)
__u8 data[42]
Definition: videodev2.h:1039
Protocol getProtocol() const
__u32 type
Definition: videodev2.h:1038
unsigned char r
Definition: ParseText.cpp:339
static int qt_socket_socket(int domain, int type, int protocol)
def read(device=None, features=[])
Definition: disc.py:35
qint64 readData(char *data, qint64 maxlen)
__u32 addr
Definition: videodev2.h:1040
The MSocketDevice class provides a platform-independent low-level socket API.
Definition: msocketdevice.h:54
MSocketDevice::Error e
int errno
virtual qint64 writeBlock(const char *data, quint64 len, const QHostAddress &host, quint16 port)
static void init()
qint64 writeData(const char *data, qint64 len)
qint64 waitForMore(int msecs, bool *timeout=0) const
virtual int accept()
bool blocking() const
bool isValid() const
static void qt_socket_getportaddr(struct sockaddr *sa, quint16 *port, QHostAddress *addr)
qint64 bytesAvailable() const
Protocol protocol() const
static int qt_socket_listen(int s, int backlog)
virtual bool bind(const QHostAddress &, quint16)
static int qt_socket_accept(int s, struct sockaddr *addr, QT_SOCKLEN_T *addrlen)
virtual QHostAddress address() const
virtual bool connect(const QHostAddress &, quint16)
virtual bool listen(int backlog)
QHostAddress a