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