00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044 #include "qplatformdefs.h"
00045 #include "mythlogging.h"
00046
00047
00048 #if !defined(QT_SOCKOPTLEN_T)
00049 # define QT_SOCKOPTLEN_T QT_SOCKLEN_T
00050 #endif
00051
00052
00053 static inline int qt_socket_accept(int s, struct sockaddr *addr, QT_SOCKLEN_T *addrlen)
00054 {
00055 return ::accept(s, addr, addrlen);
00056 }
00057
00058 #if defined(accept)
00059 # undef accept
00060 #endif
00061
00062
00063 static inline int qt_socket_listen(int s, int backlog)
00064 {
00065 return ::listen(s, backlog);
00066 }
00067
00068 #if defined(listen)
00069 # undef listen
00070 #endif
00071
00072
00073 static inline int qt_socket_socket(int domain, int type, int protocol)
00074 {
00075 return ::socket(domain, type, protocol);
00076 }
00077
00078 #if defined(socket)
00079 # undef socket
00080 #endif
00081
00082 #include "msocketdevice.h"
00083
00084 #include "qwindowdefs.h"
00085
00086 #include <errno.h>
00087 #include <sys/types.h>
00088
00089 static inline void qt_socket_getportaddr(struct sockaddr *sa,
00090 quint16 *port, QHostAddress *addr)
00091 {
00092 #if !defined(QT_NO_IPV6)
00093
00094 if (sa->sa_family == AF_INET6)
00095 {
00096
00097 struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa;
00098 Q_IPV6ADDR tmp;
00099 memcpy(&tmp, &sa6->sin6_addr.s6_addr, sizeof(tmp));
00100 QHostAddress a(tmp);
00101 *addr = a;
00102 *port = ntohs(sa6->sin6_port);
00103 return;
00104 }
00105
00106 #endif
00107
00108 struct sockaddr_in *sa4 = (struct sockaddr_in *)sa;
00109
00110 QHostAddress a(ntohl(sa4->sin_addr.s_addr));
00111
00112 *port = ntohs(sa4->sin_port);
00113
00114 *addr = QHostAddress(ntohl(sa4->sin_addr.s_addr));
00115
00116 return;
00117 }
00118
00119
00120 void MSocketDevice::init()
00121 {
00122 }
00123
00124
00125 MSocketDevice::Protocol MSocketDevice::getProtocol() const
00126 {
00127 if (isValid())
00128 {
00129 #if !defined (QT_NO_IPV6)
00130
00131 struct sockaddr_storage sa;
00132 #else
00133
00134 struct sockaddr sa;
00135 #endif
00136 memset(&sa, 0, sizeof(sa));
00137 QT_SOCKLEN_T sz = sizeof(sa);
00138 #if !defined (QT_NO_IPV6)
00139
00140 struct sockaddr *sap = reinterpret_cast<struct sockaddr *>(&sa);
00141
00142 if (!::getsockname(fd, sap, &sz))
00143 {
00144 switch (sap->sa_family)
00145 {
00146
00147 case AF_INET:
00148 return IPv4;
00149
00150 case AF_INET6:
00151 return IPv6;
00152
00153 default:
00154 return Unknown;
00155 }
00156 }
00157
00158 #else
00159 if (!::getsockname(fd, &sa, &sz))
00160 {
00161 switch (sa.sa_family)
00162 {
00163
00164 case AF_INET:
00165 return IPv4;
00166
00167 default:
00168 return Unknown;
00169 }
00170 }
00171
00172 #endif
00173 }
00174
00175 return Unknown;
00176 }
00177
00185 int MSocketDevice::createNewSocket()
00186 {
00187 #if !defined(QT_NO_IPV6)
00188 int s = qt_socket_socket(protocol() == IPv6 ? AF_INET6 : AF_INET,
00189 t == Datagram ? SOCK_DGRAM : SOCK_STREAM, 0);
00190 #else
00191 int s = qt_socket_socket(AF_INET, t == Datagram ? SOCK_DGRAM : SOCK_STREAM, 0);
00192 #endif
00193
00194 if (s < 0)
00195 {
00196 switch (errno)
00197 {
00198
00199 case EPROTONOSUPPORT:
00200 e = InternalError;
00201 break;
00202
00203 case ENFILE:
00204 e = NoFiles;
00205 break;
00206
00207 case EACCES:
00208 e = Inaccessible;
00209 break;
00210
00211 case ENOBUFS:
00212
00213 case ENOMEM:
00214 e = NoResources;
00215 break;
00216
00217 case EINVAL:
00218 e = Impossible;
00219 break;
00220
00221 default:
00222 e = UnknownError;
00223 break;
00224 }
00225 }
00226 else
00227 {
00228 return s;
00229 }
00230
00231 return -1;
00232 }
00233
00247 void MSocketDevice::close()
00248 {
00249 if (fd == -1 || !isOpen())
00250 return;
00251
00252 setOpenMode(NotOpen);
00253
00254 ::close(fd);
00255
00256 LOG(VB_SOCKET, LOG_DEBUG,
00257 QString("MSocketDevice::close: Closed socket %1").arg(fd));
00258
00259 fd = -1;
00260
00261 fetchConnectionParameters();
00262
00263 QIODevice::close();
00264 }
00265
00266
00278 bool MSocketDevice::blocking() const
00279 {
00280 if (!isValid())
00281 return true;
00282
00283 int s = fcntl(fd, F_GETFL, 0);
00284
00285 return !(s >= 0 && ((s & O_NDELAY) != 0));
00286 }
00287
00288
00303 void MSocketDevice::setBlocking(bool enable)
00304 {
00305 LOG(VB_SOCKET, LOG_DEBUG, QString("MSocketDevice::setBlocking(%1)")
00306 .arg((enable) ? "true" : "false"));
00307
00308 if (!isValid())
00309 return;
00310
00311 int tmp = ::fcntl(fd, F_GETFL, 0);
00312
00313 if (tmp >= 0)
00314 tmp = ::fcntl(fd, F_SETFL, enable ? (tmp & ~O_NDELAY) : (tmp | O_NDELAY));
00315
00316 if (tmp >= 0)
00317 return;
00318
00319 if (e)
00320 return;
00321
00322 switch (errno)
00323 {
00324
00325 case EACCES:
00326
00327 case EBADF:
00328 e = Impossible;
00329 break;
00330
00331 case EFAULT:
00332
00333 case EAGAIN:
00334 #if EAGAIN != EWOULDBLOCK
00335
00336 case EWOULDBLOCK:
00337 #endif
00338
00339 case EDEADLK:
00340
00341 case EINTR:
00342
00343 case EINVAL:
00344
00345 case EMFILE:
00346
00347 case ENOLCK:
00348
00349 case EPERM:
00350
00351 default:
00352 e = UnknownError;
00353 }
00354 }
00355
00356
00360 int MSocketDevice::option(Option opt) const
00361 {
00362 if (!isValid())
00363 return -1;
00364
00365 int n = -1;
00366
00367 int v = -1;
00368
00369 switch (opt)
00370 {
00371
00372 case Broadcast:
00373 n = SO_BROADCAST;
00374 break;
00375
00376 case ReceiveBuffer:
00377 n = SO_RCVBUF;
00378 break;
00379
00380 case ReuseAddress:
00381 n = SO_REUSEADDR;
00382 break;
00383
00384 case SendBuffer:
00385 n = SO_SNDBUF;
00386 break;
00387
00388 case Keepalive:
00389 n = SO_KEEPALIVE;
00390 break;
00391 }
00392
00393 if (n != -1)
00394 {
00395 QT_SOCKOPTLEN_T len;
00396 len = sizeof(v);
00397 int r = ::getsockopt(fd, SOL_SOCKET, n, (char*) & v, &len);
00398
00399 if (r >= 0)
00400 return v;
00401
00402 if (!e)
00403 {
00404 MSocketDevice *that = (MSocketDevice*)this;
00405
00406 switch (errno)
00407 {
00408
00409 case EBADF:
00410
00411 case ENOTSOCK:
00412 that->e = Impossible;
00413 break;
00414
00415 case EFAULT:
00416 that->e = InternalError;
00417 break;
00418
00419 default:
00420 that->e = UnknownError;
00421 break;
00422 }
00423 }
00424
00425 return -1;
00426 }
00427
00428 return v;
00429 }
00430
00431
00435 void MSocketDevice::setOption(Option opt, int v)
00436 {
00437 if (!isValid())
00438 return;
00439
00440 int n = -1;
00441
00442 switch (opt)
00443 {
00444
00445 case Broadcast:
00446 n = SO_BROADCAST;
00447 break;
00448
00449 case ReceiveBuffer:
00450 n = SO_RCVBUF;
00451 break;
00452
00453 case ReuseAddress:
00454 n = SO_REUSEADDR;
00455 break;
00456
00457 case SendBuffer:
00458 n = SO_SNDBUF;
00459 break;
00460
00461 case Keepalive:
00462 n = SO_KEEPALIVE;
00463 break;
00464
00465 default:
00466 return;
00467 }
00468
00469 if (::setsockopt(fd, SOL_SOCKET, n, (char*)&v, sizeof(v)) < 0 &&
00470 e == NoError)
00471 {
00472 switch (errno)
00473 {
00474
00475 case EBADF:
00476
00477 case ENOTSOCK:
00478 e = Impossible;
00479 break;
00480
00481 case EFAULT:
00482 e = InternalError;
00483 break;
00484
00485 default:
00486 e = UnknownError;
00487 break;
00488 }
00489 }
00490 }
00491
00492
00502 bool MSocketDevice::connect(const QHostAddress &addr, quint16 port)
00503 {
00504 if (isValid() && addr.protocol() != pa.protocol())
00505 {
00506 close();
00507 fd = -1;
00508 }
00509
00510 if (!isValid())
00511 {
00512 #if !defined(QT_NO_IPV6)
00513
00514 if (addr.protocol() == QAbstractSocket::IPv6Protocol)
00515 {
00516 setProtocol(IPv6);
00517 LOG(VB_SOCKET, LOG_INFO,
00518 "MSocketDevice::connect: setting Protocol to IPv6");
00519 }
00520 else
00521 #endif
00522 if (addr.protocol() == QAbstractSocket::IPv4Protocol)
00523 {
00524 setProtocol(IPv4);
00525 LOG(VB_SOCKET, LOG_INFO,
00526 "MSocketDevice::connect: setting Protocol to IPv4");
00527 }
00528
00529 LOG(VB_SOCKET, LOG_INFO,
00530
00531 "MSocketDevice::connect: attempting to create new socket");
00532 MSocketDevice::setSocket(createNewSocket(), t);
00533
00534
00535
00536 if (!isValid())
00537 return false;
00538 }
00539
00540 pa = addr;
00541
00542 pp = port;
00543
00544 struct sockaddr_in a4;
00545
00546 struct sockaddr *aa;
00547 QT_SOCKLEN_T aalen;
00548
00549 #if !defined(QT_NO_IPV6)
00550
00551 struct sockaddr_in6 a6;
00552
00553 if (addr.protocol() == QAbstractSocket::IPv6Protocol)
00554 {
00555 memset(&a6, 0, sizeof(a6));
00556 a6.sin6_family = AF_INET6;
00557 a6.sin6_port = htons(port);
00558 Q_IPV6ADDR ip6 = addr.toIPv6Address();
00559 memcpy(&a6.sin6_addr.s6_addr, &ip6, sizeof(ip6));
00560
00561 aalen = sizeof(a6);
00562 aa = (struct sockaddr *) & a6;
00563 }
00564 else
00565 #endif
00566 if (addr.protocol() == QAbstractSocket::IPv4Protocol)
00567 {
00568 memset(&a4, 0, sizeof(a4));
00569 a4.sin_family = AF_INET;
00570 a4.sin_port = htons(port);
00571 a4.sin_addr.s_addr = htonl(addr.toIPv4Address());
00572
00573 aalen = sizeof(a4);
00574 aa = (struct sockaddr *) & a4;
00575 }
00576 else
00577 {
00578 e = Impossible;
00579 return false;
00580 }
00581
00582 int r = QT_SOCKET_CONNECT(fd, aa, aalen);
00583
00584 if (r == 0)
00585 {
00586 fetchConnectionParameters();
00587 return true;
00588 }
00589
00590 if (errno == EISCONN || errno == EALREADY || errno == EINPROGRESS)
00591 {
00592 fetchConnectionParameters();
00593 return true;
00594 }
00595
00596 if (e != NoError || errno == EAGAIN || errno == EWOULDBLOCK)
00597 {
00598 return false;
00599 }
00600
00601 switch (errno)
00602 {
00603
00604 case EBADF:
00605
00606 case ENOTSOCK:
00607 e = Impossible;
00608 break;
00609
00610 case EFAULT:
00611
00612 case EAFNOSUPPORT:
00613 e = InternalError;
00614 break;
00615
00616 case ECONNREFUSED:
00617 e = ConnectionRefused;
00618 break;
00619
00620 case ETIMEDOUT:
00621
00622 case ENETUNREACH:
00623 e = NetworkFailure;
00624 break;
00625
00626 case EADDRINUSE:
00627 e = NoResources;
00628 break;
00629
00630 case EACCES:
00631
00632 case EPERM:
00633 e = Inaccessible;
00634 break;
00635
00636 default:
00637 e = UnknownError;
00638 break;
00639 }
00640
00641 return false;
00642 }
00643
00644
00654 bool MSocketDevice::bind(const QHostAddress &address, quint16 port)
00655 {
00656 if (!isValid())
00657 return false;
00658
00659 int r;
00660
00661 struct sockaddr_in a4;
00662
00663 #if !defined(QT_NO_IPV6)
00664
00665 struct sockaddr_in6 a6;
00666
00667 if (address.protocol() == QAbstractSocket::IPv6Protocol)
00668 {
00669 memset(&a6, 0, sizeof(a6));
00670 a6.sin6_family = AF_INET6;
00671 a6.sin6_port = htons(port);
00672 Q_IPV6ADDR tmp = address.toIPv6Address();
00673 memcpy(&a6.sin6_addr.s6_addr, &tmp, sizeof(tmp));
00674
00675 r = QT_SOCKET_BIND(fd, (struct sockaddr *) & a6, sizeof(a6));
00676 }
00677 else
00678 #endif
00679 if (address.protocol() == QAbstractSocket::IPv4Protocol)
00680 {
00681 memset(&a4, 0, sizeof(a4));
00682 a4.sin_family = AF_INET;
00683 a4.sin_port = htons(port);
00684 a4.sin_addr.s_addr = htonl(address.toIPv4Address());
00685
00686 r = QT_SOCKET_BIND(fd, (struct sockaddr*) & a4, sizeof(a4));
00687 }
00688 else
00689 {
00690 e = Impossible;
00691 return false;
00692 }
00693
00694 if (r < 0)
00695 {
00696 switch (errno)
00697 {
00698
00699 case EINVAL:
00700 e = AlreadyBound;
00701 break;
00702
00703 case EACCES:
00704 e = Inaccessible;
00705 break;
00706
00707 case ENOMEM:
00708 e = NoResources;
00709 break;
00710
00711 case EFAULT:
00712
00713 case ENAMETOOLONG:
00714 e = InternalError;
00715 break;
00716
00717 case EBADF:
00718
00719 case ENOTSOCK:
00720
00721 case EROFS:
00722
00723 case ENOENT:
00724
00725 case ENOTDIR:
00726
00727 case ELOOP:
00728 e = Impossible;
00729 break;
00730
00731 default:
00732 e = UnknownError;
00733 break;
00734 }
00735
00736 return false;
00737 }
00738
00739 fetchConnectionParameters();
00740
00741 return true;
00742 }
00743
00744
00756 bool MSocketDevice::listen(int backlog)
00757 {
00758 if (!isValid())
00759 return false;
00760
00761 if (qt_socket_listen(fd, backlog) >= 0)
00762 return true;
00763
00764 if (!e)
00765 e = Impossible;
00766
00767 return false;
00768 }
00769
00770
00778 int MSocketDevice::accept()
00779 {
00780 if (!isValid())
00781 return -1;
00782
00783 #if !defined (QT_NO_IPV6)
00784
00785 struct sockaddr_storage aa;
00786
00787 #else
00788
00789 struct sockaddr aa;
00790
00791 #endif
00792 QT_SOCKLEN_T l = sizeof(aa);
00793
00794 bool done;
00795
00796 int s;
00797
00798 do
00799 {
00800 s = qt_socket_accept(fd, (struct sockaddr*) & aa, &l);
00801
00802 done = true;
00803
00804 if (s < 0 && e == NoError)
00805 {
00806 switch (errno)
00807 {
00808
00809 case EINTR:
00810 done = false;
00811 break;
00812 #if defined(EPROTO)
00813
00814 case EPROTO:
00815 #endif
00816 #if defined(ENONET)
00817
00818 case ENONET:
00819 #endif
00820
00821 case ENOPROTOOPT:
00822
00823 case EHOSTDOWN:
00824
00825 case EOPNOTSUPP:
00826
00827 case EHOSTUNREACH:
00828
00829 case ENETDOWN:
00830
00831 case ENETUNREACH:
00832
00833 case ETIMEDOUT:
00834
00835
00836
00837
00838 case EPERM:
00839
00840
00841
00842 case EAGAIN:
00843 #if EAGAIN != EWOULDBLOCK
00844
00845 case EWOULDBLOCK:
00846 #endif
00847
00848
00849 break;
00850
00851 case EBADF:
00852
00853 case ENOTSOCK:
00854 e = Impossible;
00855 break;
00856
00857 case EFAULT:
00858 e = InternalError;
00859 break;
00860
00861 case ENOMEM:
00862
00863 case ENOBUFS:
00864 e = NoResources;
00865 break;
00866
00867 default:
00868 e = UnknownError;
00869 break;
00870 }
00871 }
00872 }
00873 while (!done);
00874
00875 return s;
00876 }
00877
00878
00890 qint64 MSocketDevice::bytesAvailable() const
00891 {
00892 if (!isValid())
00893 return -1;
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910 union { size_t st;
00911 int i;
00912 } nbytes;
00913
00914 nbytes.st = 0;
00915
00916
00917
00918 if (::ioctl(fd, FIONREAD, (char*)&nbytes.i) < 0)
00919 return -1;
00920
00921 return (qint64) nbytes.i + QIODevice::bytesAvailable();
00922 }
00923
00924
00943 qint64 MSocketDevice::waitForMore(int msecs, bool *timeout) const
00944 {
00945 if (!isValid())
00946 return -1;
00947
00948 if (fd >= FD_SETSIZE)
00949 return -1;
00950
00951 fd_set fds;
00952
00953 struct timeval tv;
00954
00955 FD_ZERO(&fds);
00956
00957 FD_SET(fd, &fds);
00958
00959 tv.tv_sec = msecs / 1000;
00960
00961 tv.tv_usec = (msecs % 1000) * 1000;
00962
00963 int rv = select(fd + 1, &fds, 0, 0, msecs < 0 ? 0 : &tv);
00964
00965 if (rv < 0)
00966 return -1;
00967
00968 if (timeout)
00969 {
00970 if (rv == 0)
00971 *timeout = true;
00972 else
00973 *timeout = false;
00974 }
00975
00976 return bytesAvailable();
00977 }
00978
00979
00984 qint64 MSocketDevice::readData(char *data, qint64 maxlen)
00985 {
00986 if (maxlen == 0)
00987 return 0;
00988
00989 if (data == 0)
00990 {
00991 LOG(VB_SOCKET, LOG_DEBUG,
00992 "MSocketDevice::readBlock: Null pointer error");
00993 return -1;
00994 }
00995
00996 if (!isValid())
00997 {
00998 LOG(VB_SOCKET, LOG_DEBUG,
00999 "MSocketDevice::readBlock: Invalid socket");
01000 return -1;
01001 }
01002
01003 if (!isOpen())
01004 {
01005 LOG(VB_SOCKET, LOG_DEBUG,
01006 "MSocketDevice::readBlock: Device is not open");
01007 return -1;
01008 }
01009
01010 if (!isReadable())
01011 {
01012 LOG(VB_SOCKET, LOG_DEBUG,
01013 "MSocketDevice::readBlock: Read operation not permitted");
01014 return -1;
01015 }
01016
01017 bool done = false;
01018
01019 int r = 0;
01020
01021 while (done == false)
01022 {
01023 if (t == Datagram)
01024 {
01025 #if !defined(QT_NO_IPV6)
01026
01027 struct sockaddr_storage aa;
01028 #else
01029
01030 struct sockaddr_in aa;
01031 #endif
01032 memset(&aa, 0, sizeof(aa));
01033 QT_SOCKLEN_T sz;
01034 sz = sizeof(aa);
01035 r = ::recvfrom(fd, data, maxlen, 0,
01036 (struct sockaddr *) & aa, &sz);
01037
01038 qt_socket_getportaddr((struct sockaddr *)&aa, &pp, &pa);
01039
01040 }
01041 else
01042 {
01043 r = ::read(fd, data, maxlen);
01044 }
01045
01046 done = true;
01047
01048 if (r == 0 && t == Stream && maxlen > 0)
01049 {
01050
01051 close();
01052 }
01053 else if (r >= 0 || errno == EAGAIN || errno == EWOULDBLOCK)
01054 {
01055
01056 }
01057 else if (errno == EINTR)
01058 {
01059 done = false;
01060 }
01061 else if (e == NoError)
01062 {
01063 switch (errno)
01064 {
01065
01066 case EIO:
01067
01068 case EISDIR:
01069
01070 case EBADF:
01071
01072 case EINVAL:
01073
01074 case EFAULT:
01075
01076 case ENOTCONN:
01077
01078 case ENOTSOCK:
01079 e = Impossible;
01080 break;
01081 #if defined(ENONET)
01082
01083 case ENONET:
01084 #endif
01085
01086 case EHOSTUNREACH:
01087
01088 case ENETDOWN:
01089
01090 case ENETUNREACH:
01091
01092 case ETIMEDOUT:
01093 e = NetworkFailure;
01094 break;
01095
01096 case EPIPE:
01097
01098 case ECONNRESET:
01099
01100 close();
01101 r = 0;
01102 break;
01103
01104 default:
01105 e = UnknownError;
01106 break;
01107 }
01108 }
01109 }
01110
01111 return r;
01112 }
01113
01114
01121 qint64 MSocketDevice::writeData(const char *data, qint64 len)
01122 {
01123 if (len == 0)
01124 return 0;
01125
01126 if (data == 0)
01127 {
01128 LOG(VB_SOCKET, LOG_DEBUG,
01129 "MSocketDevice::writeBlock: Null pointer error");
01130 return -1;
01131 }
01132
01133 if (!isValid())
01134 {
01135 LOG(VB_SOCKET, LOG_DEBUG,
01136 "MSocketDevice::writeBlock: Invalid socket");
01137 return -1;
01138 }
01139
01140 if (!isOpen())
01141 {
01142 LOG(VB_SOCKET, LOG_DEBUG,
01143 "MSocketDevice::writeBlock: Device is not open");
01144 return -1;
01145 }
01146
01147 if (!isWritable())
01148 {
01149 LOG(VB_SOCKET, LOG_DEBUG,
01150 "MSocketDevice::writeBlock: Write operation not permitted");
01151 return -1;
01152 }
01153
01154 bool done = false;
01155
01156 int r = 0;
01157 bool timeout;
01158
01159 while (!done)
01160 {
01161 r = ::write(fd, data, len);
01162 done = true;
01163
01164 if (r < 0 && e == NoError &&
01165 errno != EAGAIN && errno != EWOULDBLOCK)
01166 {
01167 switch (errno)
01168 {
01169
01170 case EINTR:
01171 done = false;
01172 break;
01173
01174 case EPIPE:
01175
01176 case ECONNRESET:
01177
01178 close();
01179 r = 0;
01180 break;
01181
01182 case ENOSPC:
01183
01184 case EIO:
01185
01186 case EISDIR:
01187
01188 case EBADF:
01189
01190 case EINVAL:
01191
01192 case EFAULT:
01193
01194 case ENOTCONN:
01195
01196 case ENOTSOCK:
01197 e = Impossible;
01198 break;
01199 #if defined(ENONET)
01200
01201 case ENONET:
01202 #endif
01203
01204 case EHOSTUNREACH:
01205
01206 case ENETDOWN:
01207
01208 case ENETUNREACH:
01209
01210 case ETIMEDOUT:
01211 e = NetworkFailure;
01212 break;
01213
01214 default:
01215 e = UnknownError;
01216 break;
01217 }
01218 }
01219 else if (waitForMore(0, &timeout) == 0)
01220 {
01221 if (!timeout)
01222 {
01223
01224 close();
01225 }
01226 }
01227 }
01228
01229 return r;
01230 }
01231
01232
01242 qint64 MSocketDevice::writeBlock(const char * data, quint64 len,
01243 const QHostAddress & host, quint16 port)
01244 {
01245 if (len == 0)
01246 return 0;
01247
01248 if (t != Datagram)
01249 {
01250 LOG(VB_SOCKET, LOG_DEBUG,
01251 "MSocketDevice::sendBlock: Not datagram");
01252 return -1;
01253 }
01254
01255 if (data == 0)
01256 {
01257 LOG(VB_SOCKET, LOG_DEBUG,
01258 "MSocketDevice::sendBlock: Null pointer error");
01259 return -1;
01260 }
01261
01262 if (!isValid())
01263 {
01264 LOG(VB_SOCKET, LOG_DEBUG,
01265 "MSocketDevice::sendBlock: Invalid socket");
01266 return -1;
01267 }
01268
01269 if (!isOpen())
01270 {
01271 LOG(VB_SOCKET, LOG_DEBUG,
01272 "MSocketDevice::sendBlock: Device is not open");
01273 return -1;
01274 }
01275
01276 if (!isWritable())
01277 {
01278 LOG(VB_SOCKET, LOG_DEBUG,
01279 "MSocketDevice::sendBlock: Write operation not permitted");
01280 return -1;
01281 }
01282
01283 struct sockaddr_in a4;
01284
01285 struct sockaddr *aa;
01286
01287 QT_SOCKLEN_T slen;
01288
01289 #if !defined(QT_NO_IPV6)
01290
01291 struct sockaddr_in6 a6;
01292
01293 if (host.protocol() == QAbstractSocket::IPv6Protocol)
01294 {
01295 memset(&a6, 0, sizeof(a6));
01296 a6.sin6_family = AF_INET6;
01297 a6.sin6_port = htons(port);
01298
01299 Q_IPV6ADDR tmp = host.toIPv6Address();
01300 memcpy(&a6.sin6_addr.s6_addr, &tmp, sizeof(tmp));
01301 slen = sizeof(a6);
01302 aa = (struct sockaddr *) & a6;
01303 }
01304 else
01305 #endif
01306 if (host.protocol() == QAbstractSocket::IPv4Protocol)
01307 {
01308 memset(&a4, 0, sizeof(a4));
01309 a4.sin_family = AF_INET;
01310 a4.sin_port = htons(port);
01311 a4.sin_addr.s_addr = htonl(host.toIPv4Address());
01312 slen = sizeof(a4);
01313 aa = (struct sockaddr *) & a4;
01314 }
01315 else
01316 {
01317 e = Impossible;
01318 return -1;
01319 }
01320
01321
01322
01323 bool done = false;
01324
01325 int r = 0;
01326
01327 while (!done)
01328 {
01329 r = ::sendto(fd, data, len, 0, aa, slen);
01330 done = true;
01331
01332 if (r < 0 && e == NoError &&
01333 errno != EAGAIN && errno != EWOULDBLOCK)
01334 {
01335 switch (errno)
01336 {
01337
01338 case EINTR:
01339 done = false;
01340 break;
01341
01342 case ENOSPC:
01343
01344 case EPIPE:
01345
01346 case EIO:
01347
01348 case EISDIR:
01349
01350 case EBADF:
01351
01352 case EINVAL:
01353
01354 case EFAULT:
01355
01356 case ENOTCONN:
01357
01358 case ENOTSOCK:
01359 e = Impossible;
01360 break;
01361 #if defined(ENONET)
01362
01363 case ENONET:
01364 #endif
01365
01366 case EHOSTUNREACH:
01367
01368 case ENETDOWN:
01369
01370 case ENETUNREACH:
01371
01372 case ETIMEDOUT:
01373 e = NetworkFailure;
01374 break;
01375
01376 default:
01377 e = UnknownError;
01378 break;
01379 }
01380 }
01381 }
01382
01383 return r;
01384 }
01385
01386
01391 void MSocketDevice::fetchConnectionParameters()
01392 {
01393 if (!isValid())
01394 {
01395 p = 0;
01396 a = QHostAddress();
01397 pp = 0;
01398 pa = QHostAddress();
01399 return;
01400 }
01401
01402 #if !defined(QT_NO_IPV6)
01403
01404 struct sockaddr_storage sa;
01405
01406 #else
01407
01408 struct sockaddr_in sa;
01409
01410 #endif
01411 memset(&sa, 0, sizeof(sa));
01412
01413 QT_SOCKLEN_T sz;
01414
01415 sz = sizeof(sa);
01416
01417 if (!::getsockname(fd, (struct sockaddr *)(&sa), &sz))
01418 qt_socket_getportaddr((struct sockaddr *)&sa, &p, &a);
01419
01420 sz = sizeof(sa);
01421
01422 if (!::getpeername(fd, (struct sockaddr *)(&sa), &sz))
01423 qt_socket_getportaddr((struct sockaddr *)&sa, &pp, &pa);
01424 }
01425
01426
01435 quint16 MSocketDevice::peerPort() const
01436 {
01437 return pp;
01438 }
01439
01440
01449 QHostAddress MSocketDevice::peerAddress() const
01450 {
01451 return pa;
01452 }
01453