MythTV  0.28pre
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Groups Pages
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 
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 (maxlen == 0)
987  return 0;
988 
989  if (data == 0)
990  {
991  LOG(VB_SOCKET, LOG_DEBUG,
992  "MSocketDevice::readBlock: Null pointer error");
993  return -1;
994  }
995 
996  if (!isValid())
997  {
998  LOG(VB_SOCKET, LOG_DEBUG,
999  "MSocketDevice::readBlock: Invalid socket");
1000  return -1;
1001  }
1002 
1003  if (!isOpen())
1004  {
1005  LOG(VB_SOCKET, LOG_DEBUG,
1006  "MSocketDevice::readBlock: Device is not open");
1007  return -1;
1008  }
1009 
1010  if (!isReadable())
1011  {
1012  LOG(VB_SOCKET, LOG_DEBUG,
1013  "MSocketDevice::readBlock: Read operation not permitted");
1014  return -1;
1015  }
1016 
1017  bool done = false;
1018 
1019  int r = 0;
1020 
1021  while (done == false)
1022  {
1023  if (t == Datagram)
1024  {
1025 #if !defined(QT_NO_IPV6)
1026 
1027  struct sockaddr_storage aa;
1028 #else
1029 
1030  struct sockaddr_in aa;
1031 #endif
1032  memset(&aa, 0, sizeof(aa));
1033  QT_SOCKLEN_T sz;
1034  sz = sizeof(aa);
1035  r = ::recvfrom(fd, data, maxlen, 0,
1036  (struct sockaddr *) & aa, &sz);
1037 
1038  qt_socket_getportaddr((struct sockaddr *)&aa, &pp, &pa);
1039 
1040  }
1041  else
1042  {
1043  r = ::read(fd, data, maxlen);
1044  }
1045 
1046  done = true;
1047 
1048  if (r == 0 && t == Stream && maxlen > 0)
1049  {
1050  // connection closed
1051  close();
1052  }
1053  else if (r >= 0 || errno == EAGAIN || errno == EWOULDBLOCK)
1054  {
1055  // nothing
1056  }
1057  else if (errno == EINTR)
1058  {
1059  done = false;
1060  }
1061  else if (e == NoError)
1062  {
1063  switch (errno)
1064  {
1065 
1066  case EIO:
1067 
1068  case EISDIR:
1069 
1070  case EBADF:
1071 
1072  case EINVAL:
1073 
1074  case EFAULT:
1075 
1076  case ENOTCONN:
1077 
1078  case ENOTSOCK:
1079  e = Impossible;
1080  break;
1081 #if defined(ENONET)
1082 
1083  case ENONET:
1084 #endif
1085 
1086  case EHOSTUNREACH:
1087 
1088  case ENETDOWN:
1089 
1090  case ENETUNREACH:
1091 
1092  case ETIMEDOUT:
1093  e = NetworkFailure;
1094  break;
1095 
1096  case EPIPE:
1097 
1098  case ECONNRESET:
1099  // connection closed
1100  close();
1101  r = 0;
1102  break;
1103 
1104  default:
1105  e = UnknownError;
1106  break;
1107  }
1108  }
1109  }
1110 
1111  return r;
1112 }
1113 
1114 
1121 qint64 MSocketDevice::writeData(const char *data, qint64 len)
1122 {
1123  if (len == 0)
1124  return 0;
1125 
1126  if (data == 0)
1127  {
1128  LOG(VB_SOCKET, LOG_DEBUG,
1129  "MSocketDevice::writeBlock: Null pointer error");
1130  return -1;
1131  }
1132 
1133  if (!isValid())
1134  {
1135  LOG(VB_SOCKET, LOG_DEBUG,
1136  "MSocketDevice::writeBlock: Invalid socket");
1137  return -1;
1138  }
1139 
1140  if (!isOpen())
1141  {
1142  LOG(VB_SOCKET, LOG_DEBUG,
1143  "MSocketDevice::writeBlock: Device is not open");
1144  return -1;
1145  }
1146 
1147  if (!isWritable())
1148  {
1149  LOG(VB_SOCKET, LOG_DEBUG,
1150  "MSocketDevice::writeBlock: Write operation not permitted");
1151  return -1;
1152  }
1153 
1154  bool done = false;
1155 
1156  int r = 0;
1157  bool timeout;
1158 
1159  while (!done)
1160  {
1161  r = ::write(fd, data, len);
1162  done = true;
1163 
1164  if (r < 0 && e == NoError &&
1165  errno != EAGAIN && errno != EWOULDBLOCK)
1166  {
1167  switch (errno)
1168  {
1169 
1170  case EINTR: // signal - call read() or whatever again
1171  done = false;
1172  break;
1173 
1174  case EPIPE:
1175 
1176  case ECONNRESET:
1177  // connection closed
1178  close();
1179  r = 0;
1180  break;
1181 
1182  case ENOSPC:
1183 
1184  case EIO:
1185 
1186  case EISDIR:
1187 
1188  case EBADF:
1189 
1190  case EINVAL:
1191 
1192  case EFAULT:
1193 
1194  case ENOTCONN:
1195 
1196  case ENOTSOCK:
1197  e = Impossible;
1198  break;
1199 #if defined(ENONET)
1200 
1201  case ENONET:
1202 #endif
1203 
1204  case EHOSTUNREACH:
1205 
1206  case ENETDOWN:
1207 
1208  case ENETUNREACH:
1209 
1210  case ETIMEDOUT:
1211  e = NetworkFailure;
1212  break;
1213 
1214  default:
1215  e = UnknownError;
1216  break;
1217  }
1218  }
1219  else if (waitForMore(0, &timeout) == 0)
1220  {
1221  if (!timeout)
1222  {
1223  // connection closed
1224  close();
1225  }
1226  }
1227  }
1228 
1229  return r;
1230 }
1231 
1232 
1242 qint64 MSocketDevice::writeBlock(const char * data, quint64 len,
1243  const QHostAddress & host, quint16 port)
1244 {
1245  if (len == 0)
1246  return 0;
1247 
1248  if (t != Datagram)
1249  {
1250  LOG(VB_SOCKET, LOG_DEBUG,
1251  "MSocketDevice::sendBlock: Not datagram");
1252  return -1; // for now - later we can do t/tcp
1253  }
1254 
1255  if (data == 0)
1256  {
1257  LOG(VB_SOCKET, LOG_DEBUG,
1258  "MSocketDevice::sendBlock: Null pointer error");
1259  return -1;
1260  }
1261 
1262  if (!isValid())
1263  {
1264  LOG(VB_SOCKET, LOG_DEBUG,
1265  "MSocketDevice::sendBlock: Invalid socket");
1266  return -1;
1267  }
1268 
1269  if (!isOpen())
1270  {
1271  LOG(VB_SOCKET, LOG_DEBUG,
1272  "MSocketDevice::sendBlock: Device is not open");
1273  return -1;
1274  }
1275 
1276  if (!isWritable())
1277  {
1278  LOG(VB_SOCKET, LOG_DEBUG,
1279  "MSocketDevice::sendBlock: Write operation not permitted");
1280  return -1;
1281  }
1282 
1283  struct sockaddr_in a4;
1284 
1285  struct sockaddr *aa;
1286 
1287  QT_SOCKLEN_T slen;
1288 
1289 #if !defined(QT_NO_IPV6)
1290 
1291  struct sockaddr_in6 a6;
1292 
1293  if (host.protocol() == QAbstractSocket::IPv6Protocol)
1294  {
1295  memset(&a6, 0, sizeof(a6));
1296  a6.sin6_family = AF_INET6;
1297  a6.sin6_port = htons(port);
1298 
1299  Q_IPV6ADDR tmp = host.toIPv6Address();
1300  memcpy(&a6.sin6_addr.s6_addr, &tmp, sizeof(tmp));
1301  slen = sizeof(a6);
1302  aa = (struct sockaddr *) & a6;
1303  }
1304  else
1305 #endif
1306  if (host.protocol() == QAbstractSocket::IPv4Protocol)
1307  {
1308  memset(&a4, 0, sizeof(a4));
1309  a4.sin_family = AF_INET;
1310  a4.sin_port = htons(port);
1311  a4.sin_addr.s_addr = htonl(host.toIPv4Address());
1312  slen = sizeof(a4);
1313  aa = (struct sockaddr *) & a4;
1314  }
1315  else
1316  {
1317  e = Impossible;
1318  return -1;
1319  }
1320 
1321  // we'd use MSG_DONTWAIT + MSG_NOSIGNAL if Stevens were right.
1322  // but apparently Stevens and most implementors disagree
1323  bool done = false;
1324 
1325  int r = 0;
1326 
1327  while (!done)
1328  {
1329  r = ::sendto(fd, data, len, 0, aa, slen);
1330  done = true;
1331 
1332  if (r < 0 && e == NoError &&
1333  errno != EAGAIN && errno != EWOULDBLOCK)
1334  {
1335  switch (errno)
1336  {
1337 
1338  case EINTR: // signal - call read() or whatever again
1339  done = false;
1340  break;
1341 
1342  case ENOSPC:
1343 
1344  case EPIPE:
1345 
1346  case EIO:
1347 
1348  case EISDIR:
1349 
1350  case EBADF:
1351 
1352  case EINVAL:
1353 
1354  case EFAULT:
1355 
1356  case ENOTCONN:
1357 
1358  case ENOTSOCK:
1359  e = Impossible;
1360  break;
1361 #if defined(ENONET)
1362 
1363  case ENONET:
1364 #endif
1365 
1366  case EHOSTUNREACH:
1367 
1368  case ENETDOWN:
1369 
1370  case ENETUNREACH:
1371 
1372  case ETIMEDOUT:
1373  e = NetworkFailure;
1374  break;
1375 
1376  default:
1377  e = UnknownError;
1378  break;
1379  }
1380  }
1381  }
1382 
1383  return r;
1384 }
1385 
1386 
1392 {
1393  if (!isValid())
1394  {
1395  p = 0;
1396  a = QHostAddress();
1397  pp = 0;
1398  pa = QHostAddress();
1399  return;
1400  }
1401 
1402 #if !defined(QT_NO_IPV6)
1403 
1404  struct sockaddr_storage sa;
1405 
1406 #else
1407 
1408  struct sockaddr_in sa;
1409 
1410 #endif
1411  memset(&sa, 0, sizeof(sa));
1412 
1413  QT_SOCKLEN_T sz;
1414 
1415  sz = sizeof(sa);
1416 
1417  if (!::getsockname(fd, (struct sockaddr *)(&sa), &sz))
1418  qt_socket_getportaddr((struct sockaddr *)&sa, &p, &a);
1419 
1420  sz = sizeof(sa);
1421 
1422  if (!::getpeername(fd, (struct sockaddr *)(&sa), &sz))
1423  qt_socket_getportaddr((struct sockaddr *)&sa, &pp, &pa);
1424 }
1425 
1426 
1436 {
1437  return pp;
1438 }
1439 
1440 
1449 QHostAddress MSocketDevice::peerAddress() const
1450 {
1451  return pa;
1452 }
1453 
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)
my tmp
Definition: twit.tv.pl:144
bool isValid() const
QHostAddress pa
return memcpy(dest, src, len)
GLenum GLsizei len
virtual void setBlocking(bool)
GLint GLenum GLsizei GLint GLenum GLenum type
virtual void setSocket(int socket, Type type)
void setProtocol(Protocol protocol)
bool blocking() const
static int qt_socket_socket(int domain, int type, int protocol)
return memset(s, c, len)
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)
return s
Definition: minilzo.cpp:2409
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)
unsigned char r
Definition: ParseText.cpp:339
def write
Definition: mythburn.py:279
close(CACHE)
virtual bool listen(int backlog)
QHostAddress a