MythTV  0.28pre
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 #if !defined(QT_NO_IPV6)
99 
100  if (sa->sa_family == AF_INET6)
101  {
102 
103  struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa;
104  Q_IPV6ADDR tmp;
105  memcpy(&tmp, &sa6->sin6_addr.s6_addr, sizeof(tmp));
106  QHostAddress a(tmp);
107  *addr = a;
108  *port = ntohs(sa6->sin6_port);
109  return;
110  }
111 
112 #endif
113 
114  struct sockaddr_in *sa4 = (struct sockaddr_in *)sa;
115 
116  QHostAddress a(ntohl(sa4->sin_addr.s_addr));
117 
118  *port = ntohs(sa4->sin_port);
119 
120  *addr = QHostAddress(ntohl(sa4->sin_addr.s_addr));
121 
122  return;
123 }
124 
125 // internal
127 {
128 }
129 
130 
132 {
133  if (isValid())
134  {
135 #if !defined (QT_NO_IPV6)
136 
137  struct sockaddr_storage sa;
138 #else
139 
140  struct sockaddr sa;
141 #endif
142  memset(&sa, 0, sizeof(sa));
143  QT_SOCKLEN_T sz = sizeof(sa);
144 #if !defined (QT_NO_IPV6)
145 
146  struct sockaddr *sap = reinterpret_cast<struct sockaddr *>(&sa);
147 
148  if (!::getsockname(fd, sap, &sz))
149  {
150  switch (sap->sa_family)
151  {
152 
153  case AF_INET:
154  return IPv4;
155 
156  case AF_INET6:
157  return IPv6;
158 
159  default:
160  return Unknown;
161  }
162  }
163 
164 #else
165  if (!::getsockname(fd, &sa, &sz))
166  {
167  switch (sa.sa_family)
168  {
169 
170  case AF_INET:
171  return IPv4;
172 
173  default:
174  return Unknown;
175  }
176  }
177 
178 #endif
179  }
180 
181  return Unknown;
182 }
183 
192 {
193 #if !defined(QT_NO_IPV6)
194  int s = qt_socket_socket(protocol() == IPv6 ? AF_INET6 : AF_INET,
195  t == Datagram ? SOCK_DGRAM : SOCK_STREAM, 0);
196 #else
197  int s = qt_socket_socket(AF_INET, t == Datagram ? SOCK_DGRAM : SOCK_STREAM, 0);
198 #endif
199 
200  if (s < 0)
201  {
202  switch (errno)
203  {
204 
205  case EPROTONOSUPPORT:
206  e = InternalError; // 0 is supposed to work for both types
207  break;
208 
209  case ENFILE:
210  e = NoFiles; // special case for this
211  break;
212 
213  case EACCES:
214  e = Inaccessible;
215  break;
216 
217  case ENOBUFS:
218 
219  case ENOMEM:
220  e = NoResources;
221  break;
222 
223  case EINVAL:
224  e = Impossible;
225  break;
226 
227  default:
228  e = UnknownError;
229  break;
230  }
231  }
232  else
233  {
234  return s;
235  }
236 
237  return -1;
238 }
239 
254 {
255  if (fd == -1 || !isOpen()) // already closed
256  return;
257 
258  setOpenMode(NotOpen);
259 
260  ::close(fd);
261 
262  LOG(VB_SOCKET, LOG_DEBUG,
263  QString("MSocketDevice::close: Closed socket %1").arg(fd));
264 
265  fd = -1;
266 
268 
269  QIODevice::close();
270 }
271 
272 
285 {
286  if (!isValid())
287  return true;
288 
289  int s = fcntl(fd, F_GETFL, 0);
290 
291  return !(s >= 0 && ((s & O_NDELAY) != 0));
292 }
293 
294 
309 void MSocketDevice::setBlocking(bool enable)
310 {
311  LOG(VB_SOCKET, LOG_DEBUG, QString("MSocketDevice::setBlocking(%1)")
312  .arg((enable) ? "true" : "false"));
313 
314  if (!isValid())
315  return;
316 
317  int tmp = ::fcntl(fd, F_GETFL, 0);
318 
319  if (tmp >= 0)
320  tmp = ::fcntl(fd, F_SETFL, enable ? (tmp & ~O_NDELAY) : (tmp | O_NDELAY));
321 
322  if (tmp >= 0)
323  return;
324 
325  if (e)
326  return;
327 
328  switch (errno)
329  {
330 
331  case EACCES:
332 
333  case EBADF:
334  e = Impossible;
335  break;
336 
337  case EFAULT:
338 
339  case EAGAIN:
340 #if EAGAIN != EWOULDBLOCK
341 
342  case EWOULDBLOCK:
343 #endif
344 
345  case EDEADLK:
346 
347  case EINTR:
348 
349  case EINVAL:
350 
351  case EMFILE:
352 
353  case ENOLCK:
354 
355  case EPERM:
356 
357  default:
358  e = UnknownError;
359  }
360 }
361 
362 
367 {
368  if (!isValid())
369  return -1;
370 
371  int n = -1;
372 
373  int v = -1;
374 
375  switch (opt)
376  {
377 
378  case Broadcast:
379  n = SO_BROADCAST;
380  break;
381 
382  case ReceiveBuffer:
383  n = SO_RCVBUF;
384  break;
385 
386  case ReuseAddress:
387  n = SO_REUSEADDR;
388  break;
389 
390  case SendBuffer:
391  n = SO_SNDBUF;
392  break;
393 
394  case Keepalive:
395  n = SO_KEEPALIVE;
396  break;
397  }
398 
399  if (n != -1)
400  {
401  QT_SOCKOPTLEN_T len;
402  len = sizeof(v);
403  int r = ::getsockopt(fd, SOL_SOCKET, n, (char*) & v, &len);
404 
405  if (r >= 0)
406  return v;
407 
408  if (!e)
409  {
410  MSocketDevice *that = (MSocketDevice*)this; // mutable function
411 
412  switch (errno)
413  {
414 
415  case EBADF:
416 
417  case ENOTSOCK:
418  that->e = Impossible;
419  break;
420 
421  case EFAULT:
422  that->e = InternalError;
423  break;
424 
425  default:
426  that->e = UnknownError;
427  break;
428  }
429  }
430 
431  return -1;
432  }
433 
434  return v;
435 }
436 
437 
442 {
443  if (!isValid())
444  return;
445 
446  int n = -1; // for really, really bad compilers
447 
448  switch (opt)
449  {
450 
451  case Broadcast:
452  n = SO_BROADCAST;
453  break;
454 
455  case ReceiveBuffer:
456  n = SO_RCVBUF;
457  break;
458 
459  case ReuseAddress:
460  n = SO_REUSEADDR;
461  break;
462 
463  case SendBuffer:
464  n = SO_SNDBUF;
465  break;
466 
467  case Keepalive:
468  n = SO_KEEPALIVE;
469  break;
470 
471  default:
472  return;
473  }
474 
475  if (::setsockopt(fd, SOL_SOCKET, n, (char*)&v, sizeof(v)) < 0 &&
476  e == NoError)
477  {
478  switch (errno)
479  {
480 
481  case EBADF:
482 
483  case ENOTSOCK:
484  e = Impossible;
485  break;
486 
487  case EFAULT:
488  e = InternalError;
489  break;
490 
491  default:
492  e = UnknownError;
493  break;
494  }
495  }
496 }
497 
498 
508 bool MSocketDevice::connect(const QHostAddress &addr, quint16 port)
509 {
510  if (isValid() && addr.protocol() != pa.protocol())
511  {
512  close();
513  fd = -1;
514  }
515 
516  if (!isValid())
517  {
518 #if !defined(QT_NO_IPV6)
519 
520  if (addr.protocol() == QAbstractSocket::IPv6Protocol)
521  {
522  setProtocol(IPv6);
523  LOG(VB_SOCKET, LOG_INFO,
524  "MSocketDevice::connect: setting Protocol to IPv6");
525  }
526  else
527 #endif
528  if (addr.protocol() == QAbstractSocket::IPv4Protocol)
529  {
530  setProtocol(IPv4);
531  LOG(VB_SOCKET, LOG_INFO,
532  "MSocketDevice::connect: setting Protocol to IPv4");
533  }
534 
535  LOG(VB_SOCKET, LOG_INFO,
536 
537  "MSocketDevice::connect: attempting to create new socket");
539 
540  // If still not valid, give up.
541 
542  if (!isValid())
543  return false;
544  }
545 
546  pa = addr;
547 
548  pp = port;
549 
550  struct sockaddr_in a4;
551 
552  struct sockaddr *aa;
553  QT_SOCKLEN_T aalen;
554 
555 #if !defined(QT_NO_IPV6)
556 
557  struct sockaddr_in6 a6;
558 
559  if (addr.protocol() == QAbstractSocket::IPv6Protocol)
560  {
561  memset(&a6, 0, sizeof(a6));
562  a6.sin6_family = AF_INET6;
563  a6.sin6_port = htons(port);
564  Q_IPV6ADDR ip6 = addr.toIPv6Address();
565  memcpy(&a6.sin6_addr.s6_addr, &ip6, sizeof(ip6));
566 
567  aalen = sizeof(a6);
568  aa = (struct sockaddr *) & a6;
569  }
570  else
571 #endif
572  if (addr.protocol() == QAbstractSocket::IPv4Protocol)
573  {
574  memset(&a4, 0, sizeof(a4));
575  a4.sin_family = AF_INET;
576  a4.sin_port = htons(port);
577  a4.sin_addr.s_addr = htonl(addr.toIPv4Address());
578 
579  aalen = sizeof(a4);
580  aa = (struct sockaddr *) & a4;
581  }
582  else
583  {
584  e = Impossible;
585  return false;
586  }
587 
588  int r = QT_SOCKET_CONNECT(fd, aa, aalen);
589 
590  if (r == 0)
591  {
593  return true;
594  }
595 
596  if (errno == EISCONN || errno == EALREADY || errno == EINPROGRESS)
597  {
599  return true;
600  }
601 
602  if (e != NoError || errno == EAGAIN || errno == EWOULDBLOCK)
603  {
604  return false;
605  }
606 
607  switch (errno)
608  {
609 
610  case EBADF:
611 
612  case ENOTSOCK:
613  e = Impossible;
614  break;
615 
616  case EFAULT:
617 
618  case EAFNOSUPPORT:
619  e = InternalError;
620  break;
621 
622  case ECONNREFUSED:
624  break;
625 
626  case ETIMEDOUT:
627 
628  case ENETUNREACH:
629  e = NetworkFailure;
630  break;
631 
632  case EADDRINUSE:
633  e = NoResources;
634  break;
635 
636  case EACCES:
637 
638  case EPERM:
639  e = Inaccessible;
640  break;
641 
642  default:
643  e = UnknownError;
644  break;
645  }
646 
647  return false;
648 }
649 
650 
660 bool MSocketDevice::bind(const QHostAddress &address, quint16 port)
661 {
662  if (!isValid())
663  return false;
664 
665  int r;
666 
667  struct sockaddr_in a4;
668 
669 #if !defined(QT_NO_IPV6)
670 
671  struct sockaddr_in6 a6;
672 
673  if (address.protocol() == QAbstractSocket::IPv6Protocol)
674  {
675  memset(&a6, 0, sizeof(a6));
676  a6.sin6_family = AF_INET6;
677  a6.sin6_port = htons(port);
678  Q_IPV6ADDR tmp = address.toIPv6Address();
679  memcpy(&a6.sin6_addr.s6_addr, &tmp, sizeof(tmp));
680 
681  r = QT_SOCKET_BIND(fd, (struct sockaddr *) & a6, sizeof(a6));
682  }
683  else
684 #endif
685  if (address.protocol() == QAbstractSocket::IPv4Protocol)
686  {
687  memset(&a4, 0, sizeof(a4));
688  a4.sin_family = AF_INET;
689  a4.sin_port = htons(port);
690  a4.sin_addr.s_addr = htonl(address.toIPv4Address());
691 
692  r = QT_SOCKET_BIND(fd, (struct sockaddr*) & a4, sizeof(a4));
693  }
694  else
695  {
696  e = Impossible;
697  return false;
698  }
699 
700  if (r < 0)
701  {
702  switch (errno)
703  {
704 
705  case EINVAL:
706  e = AlreadyBound;
707  break;
708 
709  case EACCES:
710  e = Inaccessible;
711  break;
712 
713  case ENOMEM:
714  e = NoResources;
715  break;
716 
717  case EFAULT: // a was illegal
718 
719  case ENAMETOOLONG: // sz was wrong
720  e = InternalError;
721  break;
722 
723  case EBADF: // AF_UNIX only
724 
725  case ENOTSOCK: // AF_UNIX only
726 
727  case EROFS: // AF_UNIX only
728 
729  case ENOENT: // AF_UNIX only
730 
731  case ENOTDIR: // AF_UNIX only
732 
733  case ELOOP: // AF_UNIX only
734  e = Impossible;
735  break;
736 
737  default:
738  e = UnknownError;
739  break;
740  }
741 
742  return false;
743  }
744 
746 
747  return true;
748 }
749 
750 
762 bool MSocketDevice::listen(int backlog)
763 {
764  if (!isValid())
765  return false;
766 
767  if (qt_socket_listen(fd, backlog) >= 0)
768  return true;
769 
770  if (!e)
771  e = Impossible;
772 
773  return false;
774 }
775 
776 
785 {
786  if (!isValid())
787  return -1;
788 
789 #if !defined (QT_NO_IPV6)
790 
791  struct sockaddr_storage aa;
792 
793 #else
794 
795  struct sockaddr aa;
796 
797 #endif
798  QT_SOCKLEN_T l = sizeof(aa);
799 
800  bool done;
801 
802  int s;
803 
804  do
805  {
806  s = qt_socket_accept(fd, (struct sockaddr*) & aa, &l);
807  // we'll blithely throw away the stuff accept() wrote to aa
808  done = true;
809 
810  if (s < 0 && e == NoError)
811  {
812  switch (errno)
813  {
814 
815  case EINTR:
816  done = false;
817  break;
818 #if defined(EPROTO)
819 
820  case EPROTO:
821 #endif
822 #if defined(ENONET)
823 
824  case ENONET:
825 #endif
826 
827  case ENOPROTOOPT:
828 
829  case EHOSTDOWN:
830 
831  case EOPNOTSUPP:
832 
833  case EHOSTUNREACH:
834 
835  case ENETDOWN:
836 
837  case ENETUNREACH:
838 
839  case ETIMEDOUT:
840  // in all these cases, an error happened during connection
841  // setup. we're not interested in what happened, so we
842  // just treat it like the client-closed-quickly case.
843 
844  case EPERM:
845  // firewalling wouldn't let us accept. we treat it like
846  // the client-closed-quickly case.
847 
848  case EAGAIN:
849 #if EAGAIN != EWOULDBLOCK
850 
851  case EWOULDBLOCK:
852 #endif
853  // the client closed the connection before we got around
854  // to accept()ing it.
855  break;
856 
857  case EBADF:
858 
859  case ENOTSOCK:
860  e = Impossible;
861  break;
862 
863  case EFAULT:
864  e = InternalError;
865  break;
866 
867  case ENOMEM:
868 
869  case ENOBUFS:
870  e = NoResources;
871  break;
872 
873  default:
874  e = UnknownError;
875  break;
876  }
877  }
878  }
879  while (!done);
880 
881  return s;
882 }
883 
884 
897 {
898  if (!isValid())
899  return -1;
900 
901  /*
902  Apparently, there is not consistency among different operating
903  systems on how to use FIONREAD.
904 
905  FreeBSD, Linux and Solaris all expect the 3rd argument to
906  ioctl() to be an int, which is normally 32-bit even on 64-bit
907  machines.
908 
909  IRIX, on the other hand, expects a size_t, which is 64-bit on
910  64-bit machines.
911 
912  So, the solution is to use size_t initialized to zero to make
913  sure all bits are set to zero, preventing underflow with the
914  FreeBSD/Linux/Solaris ioctls.
915  */
916  union { size_t st;
917  int i;
918  } nbytes;
919 
920  nbytes.st = 0;
921 
922  // gives shorter than true amounts on Unix domain sockets.
923 
924  if (::ioctl(fd, FIONREAD, (char*)&nbytes.i) < 0)
925  return -1;
926 
927  return (qint64) nbytes.i + QIODevice::bytesAvailable();
928 }
929 
930 
949 qint64 MSocketDevice::waitForMore(int msecs, bool *timeout) const
950 {
951  if (!isValid())
952  return -1;
953 
954  if (fd >= static_cast<int>(FD_SETSIZE))
955  return -1;
956 
957  fd_set fds;
958 
959  struct timeval tv;
960 
961  FD_ZERO(&fds);
962 
963  FD_SET(fd, &fds);
964 
965  tv.tv_sec = msecs / 1000;
966 
967  tv.tv_usec = (msecs % 1000) * 1000;
968 
969  int rv = select(fd + 1, &fds, 0, 0, msecs < 0 ? 0 : &tv);
970 
971  if (rv < 0)
972  return -1;
973 
974  if (timeout)
975  {
976  if (rv == 0)
977  *timeout = true;
978  else
979  *timeout = false;
980  }
981 
982  return bytesAvailable();
983 }
984 
985 
990 qint64 MSocketDevice::readData(char *data, qint64 maxlen)
991 {
992 #if !defined(QT_NO_IPV6)
993 
994  struct sockaddr_storage aa;
995 #else
996 
997  struct sockaddr_in aa;
998 #endif
999 
1000  if (maxlen == 0)
1001  {
1002  // Cannot short circuit on zero bytes for datagram because zero-
1003  // byte datagrams are a real thing and if you don't issue a read
1004  // then select() will keep falling through
1005  if (t == Datagram)
1006  {
1007  QT_SOCKLEN_T sz;
1008  sz = sizeof(aa);
1009  ::recvfrom(fd, data, 0, 0, (struct sockaddr *) & aa, &sz);
1010  qt_socket_getportaddr((struct sockaddr *)&aa, &pp, &pa);
1011  }
1012  return 0;
1013  }
1014 
1015  if (data == 0)
1016  {
1017  LOG(VB_SOCKET, LOG_DEBUG,
1018  "MSocketDevice::readBlock: Null pointer error");
1019  return -1;
1020  }
1021 
1022  if (!isValid())
1023  {
1024  LOG(VB_SOCKET, LOG_DEBUG,
1025  "MSocketDevice::readBlock: Invalid socket");
1026  return -1;
1027  }
1028 
1029  if (!isOpen())
1030  {
1031  LOG(VB_SOCKET, LOG_DEBUG,
1032  "MSocketDevice::readBlock: Device is not open");
1033  return -1;
1034  }
1035 
1036  if (!isReadable())
1037  {
1038  LOG(VB_SOCKET, LOG_DEBUG,
1039  "MSocketDevice::readBlock: Read operation not permitted");
1040  return -1;
1041  }
1042 
1043  bool done = false;
1044 
1045  int r = 0;
1046 
1047  while (done == false)
1048  {
1049  if (t == Datagram)
1050  {
1051  memset(&aa, 0, sizeof(aa));
1052  QT_SOCKLEN_T sz;
1053  sz = sizeof(aa);
1054  r = ::recvfrom(fd, data, maxlen, 0,
1055  (struct sockaddr *) & aa, &sz);
1056 
1057  qt_socket_getportaddr((struct sockaddr *)&aa, &pp, &pa);
1058 
1059  }
1060  else
1061  {
1062  r = ::read(fd, data, maxlen);
1063  }
1064 
1065  done = true;
1066 
1067  if (r == 0 && t == Stream && maxlen > 0)
1068  {
1069  // connection closed
1070  close();
1071  }
1072  else if (r >= 0 || errno == EAGAIN || errno == EWOULDBLOCK)
1073  {
1074  // nothing
1075  }
1076  else if (errno == EINTR)
1077  {
1078  done = false;
1079  }
1080  else if (e == NoError)
1081  {
1082  switch (errno)
1083  {
1084 
1085  case EIO:
1086 
1087  case EISDIR:
1088 
1089  case EBADF:
1090 
1091  case EINVAL:
1092 
1093  case EFAULT:
1094 
1095  case ENOTCONN:
1096 
1097  case ENOTSOCK:
1098  e = Impossible;
1099  break;
1100 #if defined(ENONET)
1101 
1102  case ENONET:
1103 #endif
1104 
1105  case EHOSTUNREACH:
1106 
1107  case ENETDOWN:
1108 
1109  case ENETUNREACH:
1110 
1111  case ETIMEDOUT:
1112  e = NetworkFailure;
1113  break;
1114 
1115  case EPIPE:
1116 
1117  case ECONNRESET:
1118  // connection closed
1119  close();
1120  r = 0;
1121  break;
1122 
1123  default:
1124  e = UnknownError;
1125  break;
1126  }
1127  }
1128  }
1129 
1130  return r;
1131 }
1132 
1133 
1140 qint64 MSocketDevice::writeData(const char *data, qint64 len)
1141 {
1142  if (len == 0)
1143  return 0;
1144 
1145  if (data == 0)
1146  {
1147  LOG(VB_SOCKET, LOG_DEBUG,
1148  "MSocketDevice::writeBlock: Null pointer error");
1149  return -1;
1150  }
1151 
1152  if (!isValid())
1153  {
1154  LOG(VB_SOCKET, LOG_DEBUG,
1155  "MSocketDevice::writeBlock: Invalid socket");
1156  return -1;
1157  }
1158 
1159  if (!isOpen())
1160  {
1161  LOG(VB_SOCKET, LOG_DEBUG,
1162  "MSocketDevice::writeBlock: Device is not open");
1163  return -1;
1164  }
1165 
1166  if (!isWritable())
1167  {
1168  LOG(VB_SOCKET, LOG_DEBUG,
1169  "MSocketDevice::writeBlock: Write operation not permitted");
1170  return -1;
1171  }
1172 
1173  bool done = false;
1174 
1175  int r = 0;
1176  bool timeout;
1177 
1178  while (!done)
1179  {
1180  r = ::write(fd, data, len);
1181  done = true;
1182 
1183  if (r < 0 && e == NoError &&
1184  errno != EAGAIN && errno != EWOULDBLOCK)
1185  {
1186  switch (errno)
1187  {
1188 
1189  case EINTR: // signal - call read() or whatever again
1190  done = false;
1191  break;
1192 
1193  case EPIPE:
1194 
1195  case ECONNRESET:
1196  // connection closed
1197  close();
1198  r = 0;
1199  break;
1200 
1201  case ENOSPC:
1202 
1203  case EIO:
1204 
1205  case EISDIR:
1206 
1207  case EBADF:
1208 
1209  case EINVAL:
1210 
1211  case EFAULT:
1212 
1213  case ENOTCONN:
1214 
1215  case ENOTSOCK:
1216  e = Impossible;
1217  break;
1218 #if defined(ENONET)
1219 
1220  case ENONET:
1221 #endif
1222 
1223  case EHOSTUNREACH:
1224 
1225  case ENETDOWN:
1226 
1227  case ENETUNREACH:
1228 
1229  case ETIMEDOUT:
1230  e = NetworkFailure;
1231  break;
1232 
1233  default:
1234  e = UnknownError;
1235  break;
1236  }
1237  }
1238  else if (waitForMore(0, &timeout) == 0)
1239  {
1240  if (!timeout)
1241  {
1242  // connection closed
1243  close();
1244  }
1245  }
1246  }
1247 
1248  return r;
1249 }
1250 
1251 
1261 qint64 MSocketDevice::writeBlock(const char * data, quint64 len,
1262  const QHostAddress & host, quint16 port)
1263 {
1264  if (len == 0)
1265  return 0;
1266 
1267  if (t != Datagram)
1268  {
1269  LOG(VB_SOCKET, LOG_DEBUG,
1270  "MSocketDevice::sendBlock: Not datagram");
1271  return -1; // for now - later we can do t/tcp
1272  }
1273 
1274  if (data == 0)
1275  {
1276  LOG(VB_SOCKET, LOG_DEBUG,
1277  "MSocketDevice::sendBlock: Null pointer error");
1278  return -1;
1279  }
1280 
1281  if (!isValid())
1282  {
1283  LOG(VB_SOCKET, LOG_DEBUG,
1284  "MSocketDevice::sendBlock: Invalid socket");
1285  return -1;
1286  }
1287 
1288  if (!isOpen())
1289  {
1290  LOG(VB_SOCKET, LOG_DEBUG,
1291  "MSocketDevice::sendBlock: Device is not open");
1292  return -1;
1293  }
1294 
1295  if (!isWritable())
1296  {
1297  LOG(VB_SOCKET, LOG_DEBUG,
1298  "MSocketDevice::sendBlock: Write operation not permitted");
1299  return -1;
1300  }
1301 
1302  struct sockaddr_in a4;
1303 
1304  struct sockaddr *aa;
1305 
1306  QT_SOCKLEN_T slen;
1307 
1308 #if !defined(QT_NO_IPV6)
1309 
1310  struct sockaddr_in6 a6;
1311 
1312  if (host.protocol() == QAbstractSocket::IPv6Protocol)
1313  {
1314  memset(&a6, 0, sizeof(a6));
1315  a6.sin6_family = AF_INET6;
1316  a6.sin6_port = htons(port);
1317 
1318  Q_IPV6ADDR tmp = host.toIPv6Address();
1319  memcpy(&a6.sin6_addr.s6_addr, &tmp, sizeof(tmp));
1320  slen = sizeof(a6);
1321  aa = (struct sockaddr *) & a6;
1322  }
1323  else
1324 #endif
1325  if (host.protocol() == QAbstractSocket::IPv4Protocol)
1326  {
1327  memset(&a4, 0, sizeof(a4));
1328  a4.sin_family = AF_INET;
1329  a4.sin_port = htons(port);
1330  a4.sin_addr.s_addr = htonl(host.toIPv4Address());
1331  slen = sizeof(a4);
1332  aa = (struct sockaddr *) & a4;
1333  }
1334  else
1335  {
1336  e = Impossible;
1337  return -1;
1338  }
1339 
1340  // we'd use MSG_DONTWAIT + MSG_NOSIGNAL if Stevens were right.
1341  // but apparently Stevens and most implementors disagree
1342  bool done = false;
1343 
1344  int r = 0;
1345 
1346  while (!done)
1347  {
1348  r = ::sendto(fd, data, len, 0, aa, slen);
1349  done = true;
1350 
1351  if (r < 0 && e == NoError &&
1352  errno != EAGAIN && errno != EWOULDBLOCK)
1353  {
1354  switch (errno)
1355  {
1356 
1357  case EINTR: // signal - call read() or whatever again
1358  done = false;
1359  break;
1360 
1361  case ENOSPC:
1362 
1363  case EPIPE:
1364 
1365  case EIO:
1366 
1367  case EISDIR:
1368 
1369  case EBADF:
1370 
1371  case EINVAL:
1372 
1373  case EFAULT:
1374 
1375  case ENOTCONN:
1376 
1377  case ENOTSOCK:
1378  e = Impossible;
1379  break;
1380 #if defined(ENONET)
1381 
1382  case ENONET:
1383 #endif
1384 
1385  case EHOSTUNREACH:
1386 
1387  case ENETDOWN:
1388 
1389  case ENETUNREACH:
1390 
1391  case ETIMEDOUT:
1392  e = NetworkFailure;
1393  break;
1394 
1395  default:
1396  e = UnknownError;
1397  break;
1398  }
1399  }
1400  }
1401 
1402  return r;
1403 }
1404 
1405 
1411 {
1412  if (!isValid())
1413  {
1414  p = 0;
1415  a = QHostAddress();
1416  pp = 0;
1417  pa = QHostAddress();
1418  return;
1419  }
1420 
1421 #if !defined(QT_NO_IPV6)
1422 
1423  struct sockaddr_storage sa;
1424 
1425 #else
1426 
1427  struct sockaddr_in sa;
1428 
1429 #endif
1430  memset(&sa, 0, sizeof(sa));
1431 
1432  QT_SOCKLEN_T sz;
1433 
1434  sz = sizeof(sa);
1435 
1436  if (!::getsockname(fd, (struct sockaddr *)(&sa), &sz))
1437  qt_socket_getportaddr((struct sockaddr *)&sa, &p, &a);
1438 
1439  sz = sizeof(sa);
1440 
1441  if (!::getpeername(fd, (struct sockaddr *)(&sa), &sz))
1442  qt_socket_getportaddr((struct sockaddr *)&sa, &pp, &pa);
1443 }
1444 
1445 
1455 {
1456  return pp;
1457 }
1458 
1459 
1468 QHostAddress MSocketDevice::peerAddress() const
1469 {
1470  return pa;
1471 }
1472 
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