source: trunk/src/qt3support/network/q3socketdevice_unix.cpp@ 802

Last change on this file since 802 was 651, checked in by Dmitry A. Kuminov, 16 years ago

trunk: Merged in qt 4.6.2 sources.

File size: 20.2 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the Qt3Support module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qplatformdefs.h"
43
44// Almost always the same. If not, specify in qplatformdefs.h.
45#if !defined(QT_SOCKOPTLEN_T)
46# define QT_SOCKOPTLEN_T QT_SOCKLEN_T
47#endif
48
49// Tru64 redefines accept -> _accept with _XOPEN_SOURCE_EXTENDED
50static inline int qt_socket_accept(int s, struct sockaddr *addr, QT_SOCKLEN_T *addrlen)
51{ return ::accept(s, addr, addrlen); }
52#if defined(accept)
53# undef accept
54#endif
55
56// UnixWare 7 redefines listen -> _listen
57static inline int qt_socket_listen(int s, int backlog)
58{ return ::listen(s, backlog); }
59#if defined(listen)
60# undef listen
61#endif
62
63// UnixWare 7 redefines socket -> _socket
64static inline int qt_socket_socket(int domain, int type, int protocol)
65{ return ::socket(domain, type, protocol); }
66#if defined(socket)
67# undef socket
68#endif
69
70#include "q3socketdevice.h"
71
72#ifndef QT_NO_NETWORK
73
74#include "qwindowdefs.h"
75
76#include <errno.h>
77#include <sys/types.h>
78
79QT_BEGIN_NAMESPACE
80
81static inline void qt_socket_getportaddr( struct sockaddr *sa,
82 Q_UINT16 *port, QHostAddress *addr )
83{
84#if !defined(QT_NO_IPV6)
85 if ( sa->sa_family == AF_INET6 ) {
86 struct sockaddr_in6 *sa6 = ( struct sockaddr_in6 * )sa;
87 Q_IPV6ADDR tmp;
88 memcpy( &tmp, &sa6->sin6_addr.s6_addr, sizeof(tmp) );
89 QHostAddress a( tmp );
90 *addr = a;
91 *port = ntohs( sa6->sin6_port );
92 return;
93 }
94#endif
95 struct sockaddr_in *sa4 = (struct sockaddr_in *)sa;
96 QHostAddress a( ntohl( sa4->sin_addr.s_addr ) );
97 *port = ntohs( sa4->sin_port );
98 *addr = QHostAddress( ntohl( sa4->sin_addr.s_addr ) );
99 return;
100}
101
102
103//#define QSOCKETDEVICE_DEBUG
104
105// internal
106void Q3SocketDevice::init()
107{
108}
109
110
111Q3SocketDevice::Protocol Q3SocketDevice::getProtocol() const
112{
113 if ( isValid() ) {
114#if !defined (QT_NO_IPV6)
115 struct sockaddr_storage sa;
116#else
117 struct sockaddr sa;
118#endif
119 memset( &sa, 0, sizeof(sa) );
120 QT_SOCKLEN_T sz = sizeof( sa );
121#if !defined (QT_NO_IPV6)
122 struct sockaddr *sap = reinterpret_cast<struct sockaddr *>(&sa);
123 if ( !::getsockname(fd, sap, &sz) ) {
124 switch ( sap->sa_family ) {
125 case AF_INET:
126 return IPv4;
127 case AF_INET6:
128 return IPv6;
129 default:
130 return Unknown;
131 }
132 }
133#else
134 if ( !::getsockname(fd, &sa, &sz) ) {
135 switch ( sa.sa_family ) {
136 case AF_INET:
137 return IPv4;
138 default:
139 return Unknown;
140 }
141 }
142#endif
143 }
144 return Unknown;
145}
146
147
148int Q3SocketDevice::createNewSocket()
149{
150#if !defined(QT_NO_IPV6)
151 int s = qt_socket_socket( protocol() == IPv6 ? AF_INET6 : AF_INET,
152 t == Datagram ? SOCK_DGRAM : SOCK_STREAM, 0 );
153#else
154 int s = qt_socket_socket( AF_INET, t==Datagram?SOCK_DGRAM:SOCK_STREAM, 0 );
155#endif
156 if ( s < 0 ) {
157 switch( errno ) {
158 case EPROTONOSUPPORT:
159 e = InternalError; // 0 is supposed to work for both types
160 break;
161 case ENFILE:
162 e = NoFiles; // special case for this
163 break;
164 case EACCES:
165 e = Inaccessible;
166 break;
167 case ENOBUFS:
168 case ENOMEM:
169 e = NoResources;
170 break;
171 case EINVAL:
172 e = Impossible;
173 break;
174 default:
175 e = UnknownError;
176 break;
177 }
178 } else {
179 return s;
180 }
181 return -1;
182}
183
184void Q3SocketDevice::close()
185{
186 if ( fd == -1 || !isOpen() ) // already closed
187 return;
188 resetStatus();
189 setOpenMode(NotOpen);
190 ::close( fd );
191#if defined(QSOCKETDEVICE_DEBUG)
192 qDebug( "Q3SocketDevice::close: Closed socket %x", fd );
193#endif
194 fd = -1;
195 fetchConnectionParameters();
196 QIODevice::close();
197}
198
199
200bool Q3SocketDevice::blocking() const
201{
202 if ( !isValid() )
203 return true;
204 int s = fcntl(fd, F_GETFL, 0);
205 return !(s >= 0 && ((s & O_NDELAY) != 0));
206}
207
208
209void Q3SocketDevice::setBlocking( bool enable )
210{
211#if defined(QSOCKETDEVICE_DEBUG)
212 qDebug( "Q3SocketDevice::setBlocking( %d )", enable );
213#endif
214 if ( !isValid() )
215 return;
216 int tmp = ::fcntl(fd, F_GETFL, 0);
217 if ( tmp >= 0 )
218 tmp = ::fcntl( fd, F_SETFL, enable ? (tmp&~O_NDELAY) : (tmp|O_NDELAY) );
219 if ( tmp >= 0 )
220 return;
221 if ( e )
222 return;
223 switch( errno ) {
224 case EACCES:
225 case EBADF:
226 e = Impossible;
227 break;
228 case EFAULT:
229 case EAGAIN:
230#if EAGAIN != EWOULDBLOCK
231 case EWOULDBLOCK:
232#endif
233 case EDEADLK:
234 case EINTR:
235 case EINVAL:
236 case EMFILE:
237 case ENOLCK:
238 case EPERM:
239 default:
240 e = UnknownError;
241 }
242}
243
244
245int Q3SocketDevice::option( Option opt ) const
246{
247 if ( !isValid() )
248 return -1;
249 int n = -1;
250 int v = -1;
251 switch ( opt ) {
252 case Broadcast:
253 n = SO_BROADCAST;
254 break;
255 case ReceiveBuffer:
256 n = SO_RCVBUF;
257 break;
258 case ReuseAddress:
259 n = SO_REUSEADDR;
260 break;
261 case SendBuffer:
262 n = SO_SNDBUF;
263 break;
264 }
265 if ( n != -1 ) {
266 QT_SOCKOPTLEN_T len;
267 len = sizeof(v);
268 int r = ::getsockopt( fd, SOL_SOCKET, n, (char*)&v, &len );
269 if ( r >= 0 )
270 return v;
271 if ( !e ) {
272 Q3SocketDevice *that = (Q3SocketDevice*)this; // mutable function
273 switch( errno ) {
274 case EBADF:
275 case ENOTSOCK:
276 that->e = Impossible;
277 break;
278 case EFAULT:
279 that->e = InternalError;
280 break;
281 default:
282 that->e = UnknownError;
283 break;
284 }
285 }
286 return -1;
287 }
288 return v;
289}
290
291
292void Q3SocketDevice::setOption( Option opt, int v )
293{
294 if ( !isValid() )
295 return;
296 int n = -1; // for really, really bad compilers
297 switch ( opt ) {
298 case Broadcast:
299 n = SO_BROADCAST;
300 break;
301 case ReceiveBuffer:
302 n = SO_RCVBUF;
303 break;
304 case ReuseAddress:
305 n = SO_REUSEADDR;
306 break;
307 case SendBuffer:
308 n = SO_SNDBUF;
309 break;
310 default:
311 return;
312 }
313 if ( ::setsockopt( fd, SOL_SOCKET, n, (char*)&v, sizeof(v)) < 0 &&
314 e == NoError ) {
315 switch( errno ) {
316 case EBADF:
317 case ENOTSOCK:
318 e = Impossible;
319 break;
320 case EFAULT:
321 e = InternalError;
322 break;
323 default:
324 e = UnknownError;
325 break;
326 }
327 }
328}
329
330
331bool Q3SocketDevice::connect( const QHostAddress &addr, Q_UINT16 port )
332{
333 if ( !isValid() )
334 return false;
335
336 pa = addr;
337 pp = port;
338
339 struct sockaddr_in a4;
340 struct sockaddr *aa;
341 QT_SOCKLEN_T aalen;
342
343#if !defined(QT_NO_IPV6)
344 struct sockaddr_in6 a6;
345
346 if ( addr.isIPv6Address() ) {
347 memset( &a6, 0, sizeof(a6) );
348 a6.sin6_family = AF_INET6;
349 a6.sin6_port = htons( port );
350 Q_IPV6ADDR ip6 = addr.toIPv6Address();
351 memcpy( &a6.sin6_addr.s6_addr, &ip6, sizeof(ip6) );
352
353 aalen = sizeof( a6 );
354 aa = (struct sockaddr *)&a6;
355 } else
356#endif
357 if ( addr.isIPv4Address() ) {
358 memset( &a4, 0, sizeof(a4) );
359 a4.sin_family = AF_INET;
360 a4.sin_port = htons( port );
361 a4.sin_addr.s_addr = htonl( addr.toIPv4Address() );
362
363 aalen = sizeof(a4);
364 aa = (struct sockaddr *)&a4;
365 } else {
366 e = Impossible;
367 return false;
368 }
369
370 int r = QT_SOCKET_CONNECT( fd, aa, aalen );
371 if ( r == 0 ) {
372 fetchConnectionParameters();
373 return true;
374 }
375 if ( errno == EISCONN || errno == EALREADY || errno == EINPROGRESS ) {
376 fetchConnectionParameters();
377 return true;
378 }
379 if ( e != NoError || errno == EAGAIN || errno == EWOULDBLOCK ) {
380 return false;
381 }
382 switch( errno ) {
383 case EBADF:
384 case ENOTSOCK:
385 e = Impossible;
386 break;
387 case EFAULT:
388 case EAFNOSUPPORT:
389 e = InternalError;
390 break;
391 case ECONNREFUSED:
392 e = ConnectionRefused;
393 break;
394 case ETIMEDOUT:
395 case ENETUNREACH:
396 e = NetworkFailure;
397 break;
398 case EADDRINUSE:
399 e = NoResources;
400 break;
401 case EACCES:
402 case EPERM:
403 e = Inaccessible;
404 break;
405 default:
406 e = UnknownError;
407 break;
408 }
409 return false;
410}
411
412
413bool Q3SocketDevice::bind( const QHostAddress &address, Q_UINT16 port )
414{
415 if ( !isValid() )
416 return false;
417 int r;
418 struct sockaddr_in a4;
419#if !defined(QT_NO_IPV6)
420 struct sockaddr_in6 a6;
421
422 if ( address.isIPv6Address() ) {
423 memset( &a6, 0, sizeof(a6) );
424 a6.sin6_family = AF_INET6;
425 a6.sin6_port = htons( port );
426 Q_IPV6ADDR tmp = address.toIPv6Address();
427 memcpy( &a6.sin6_addr.s6_addr, &tmp, sizeof(tmp) );
428
429 r = QT_SOCKET_BIND( fd, (struct sockaddr *)&a6, sizeof(a6) );
430 } else
431#endif
432 if ( address.isIPv4Address() ) {
433 memset( &a4, 0, sizeof(a4) );
434 a4.sin_family = AF_INET;
435 a4.sin_port = htons( port );
436 a4.sin_addr.s_addr = htonl( address.toIPv4Address() );
437
438 r = QT_SOCKET_BIND( fd, (struct sockaddr*)&a4, sizeof(a4) );
439 } else {
440 e = Impossible;
441 return false;
442 }
443
444 if ( r < 0 ) {
445 switch( errno ) {
446 case EINVAL:
447 e = AlreadyBound;
448 break;
449 case EACCES:
450 e = Inaccessible;
451 break;
452 case ENOMEM:
453 e = NoResources;
454 break;
455 case EFAULT: // a was illegal
456 case ENAMETOOLONG: // sz was wrong
457 e = InternalError;
458 break;
459 case EBADF: // AF_UNIX only
460 case ENOTSOCK: // AF_UNIX only
461 case EROFS: // AF_UNIX only
462 case ENOENT: // AF_UNIX only
463 case ENOTDIR: // AF_UNIX only
464 case ELOOP: // AF_UNIX only
465 e = Impossible;
466 break;
467 default:
468 e = UnknownError;
469 break;
470 }
471 return false;
472 }
473 fetchConnectionParameters();
474 return true;
475}
476
477
478bool Q3SocketDevice::listen( int backlog )
479{
480 if ( !isValid() )
481 return false;
482 if ( qt_socket_listen( fd, backlog ) >= 0 )
483 return true;
484 if ( !e )
485 e = Impossible;
486 return false;
487}
488
489
490int Q3SocketDevice::accept()
491{
492 if ( !isValid() )
493 return -1;
494
495#if !defined (QT_NO_IPV6)
496 struct sockaddr_storage aa;
497#else
498 struct sockaddr aa;
499#endif
500 QT_SOCKLEN_T l = sizeof( aa );
501 bool done;
502 int s;
503 do {
504 s = qt_socket_accept( fd, (struct sockaddr*)&aa, &l );
505 // we'll blithely throw away the stuff accept() wrote to aa
506 done = true;
507 if ( s < 0 && e == NoError ) {
508 switch( errno ) {
509 case EINTR:
510 done = false;
511 break;
512#if defined(EPROTO)
513 case EPROTO:
514#endif
515#if defined(ENONET)
516 case ENONET:
517#endif
518 case ENOPROTOOPT:
519 case EHOSTDOWN:
520 case EOPNOTSUPP:
521 case EHOSTUNREACH:
522 case ENETDOWN:
523 case ENETUNREACH:
524 case ETIMEDOUT:
525 // in all these cases, an error happened during connection
526 // setup. we're not interested in what happened, so we
527 // just treat it like the client-closed-quickly case.
528 case EPERM:
529 // firewalling wouldn't let us accept. we treat it like
530 // the client-closed-quickly case.
531 case EAGAIN:
532#if EAGAIN != EWOULDBLOCK
533 case EWOULDBLOCK:
534#endif
535 // the client closed the connection before we got around
536 // to accept()ing it.
537 break;
538 case EBADF:
539 case ENOTSOCK:
540 e = Impossible;
541 break;
542 case EFAULT:
543 e = InternalError;
544 break;
545 case ENOMEM:
546 case ENOBUFS:
547 e = NoResources;
548 break;
549 default:
550 e = UnknownError;
551 break;
552 }
553 }
554 } while (!done);
555 return s;
556}
557
558
559qint64 Q3SocketDevice::bytesAvailable() const
560{
561 if ( !isValid() )
562 return -1;
563
564 /*
565 Apparently, there is not consistency among different operating
566 systems on how to use FIONREAD.
567
568 FreeBSD, Linux and Solaris all expect the 3rd argument to
569 ioctl() to be an int, which is normally 32-bit even on 64-bit
570 machines.
571
572 IRIX, on the other hand, expects a size_t, which is 64-bit on
573 64-bit machines.
574
575 So, the solution is to use size_t initialized to zero to make
576 sure all bits are set to zero, preventing underflow with the
577 FreeBSD/Linux/Solaris ioctls.
578 */
579 size_t nbytes = 0;
580 // gives shorter than true amounts on Unix domain sockets.
581 if ( ::ioctl(fd, FIONREAD, (char*)&nbytes) < 0 )
582 return -1;
583 return (Q_LONG) *((int *) &nbytes) + QIODevice::bytesAvailable();
584}
585
586
587Q_LONG Q3SocketDevice::waitForMore( int msecs, bool *timeout ) const
588{
589 if ( !isValid() )
590 return -1;
591 if ( fd >= FD_SETSIZE )
592 return -1;
593
594 fd_set fds;
595 struct timeval tv;
596
597 FD_ZERO( &fds );
598 FD_SET( fd, &fds );
599
600 tv.tv_sec = msecs / 1000;
601 tv.tv_usec = (msecs % 1000) * 1000;
602
603 int rv = select( fd+1, &fds, 0, 0, msecs < 0 ? 0 : &tv );
604
605 if ( rv < 0 )
606 return -1;
607
608 if ( timeout ) {
609 if ( rv == 0 )
610 *timeout = true;
611 else
612 *timeout = false;
613 }
614
615 return bytesAvailable();
616}
617
618
619qint64 Q3SocketDevice::readData( char *data, qint64 maxlen )
620{
621#if defined(QT_CHECK_NULL)
622 if ( data == 0 && maxlen != 0 ) {
623 qWarning( "Q3SocketDevice::readBlock: Null pointer error" );
624 }
625#endif
626#if defined(QT_CHECK_STATE)
627 if ( !isValid() ) {
628 qWarning( "Q3SocketDevice::readBlock: Invalid socket" );
629 return -1;
630 }
631 if ( !isOpen() ) {
632 qWarning( "Q3SocketDevice::readBlock: Device is not open" );
633 return -1;
634 }
635 if ( !isReadable() ) {
636 qWarning( "Q3SocketDevice::readBlock: Read operation not permitted" );
637 return -1;
638 }
639#endif
640 bool done = false;
641 int r = 0;
642 while ( done == false ) {
643 if ( t == Datagram ) {
644#if !defined(QT_NO_IPV6)
645 struct sockaddr_storage aa;
646#else
647 struct sockaddr_in aa;
648#endif
649 memset( &aa, 0, sizeof(aa) );
650 QT_SOCKLEN_T sz;
651 sz = sizeof( aa );
652 r = ::recvfrom( fd, data, maxlen, 0,
653 (struct sockaddr *)&aa, &sz );
654
655 qt_socket_getportaddr( (struct sockaddr *)&aa, &pp, &pa);
656
657 } else {
658 r = ::read( fd, data, maxlen );
659 }
660 done = true;
661 if ( r == 0 && t == Stream && maxlen > 0 ) {
662 // connection closed
663 close();
664 } else if ( r >= 0 || errno == EAGAIN || errno == EWOULDBLOCK ) {
665 // nothing
666 } else if ( errno == EINTR ) {
667 done = false;
668 } else if ( e == NoError ) {
669 switch( errno ) {
670 case EIO:
671 case EISDIR:
672 case EBADF:
673 case EINVAL:
674 case EFAULT:
675 case ENOTCONN:
676 case ENOTSOCK:
677 e = Impossible;
678 break;
679#if defined(ENONET)
680 case ENONET:
681#endif
682 case EHOSTUNREACH:
683 case ENETDOWN:
684 case ENETUNREACH:
685 case ETIMEDOUT:
686 e = NetworkFailure;
687 break;
688 case EPIPE:
689 case ECONNRESET:
690 // connection closed
691 close();
692 r = 0;
693 break;
694 default:
695 e = UnknownError;
696 break;
697 }
698 }
699 }
700 return r;
701}
702
703
704qint64 Q3SocketDevice::writeData( const char *data, qint64 len )
705{
706 if ( data == 0 && len != 0 ) {
707#if defined(QT_CHECK_NULL) || defined(QSOCKETDEVICE_DEBUG)
708 qWarning( "Q3SocketDevice::writeBlock: Null pointer error" );
709#endif
710 return -1;
711 }
712 if ( !isValid() ) {
713#if defined(QT_CHECK_STATE) || defined(QSOCKETDEVICE_DEBUG)
714 qWarning( "Q3SocketDevice::writeBlock: Invalid socket" );
715#endif
716 return -1;
717 }
718 if ( !isOpen() ) {
719#if defined(QT_CHECK_STATE) || defined(QSOCKETDEVICE_DEBUG)
720 qWarning( "Q3SocketDevice::writeBlock: Device is not open" );
721#endif
722 return -1;
723 }
724 if ( !isWritable() ) {
725#if defined(QT_CHECK_STATE) || defined(QSOCKETDEVICE_DEBUG)
726 qWarning( "Q3SocketDevice::writeBlock: Write operation not permitted" );
727#endif
728 return -1;
729 }
730 bool done = false;
731 int r = 0;
732 bool timeout;
733 while ( !done ) {
734 r = ::write( fd, data, len );
735 done = true;
736 if ( r < 0 && e == NoError &&
737 errno != EAGAIN && errno != EWOULDBLOCK ) {
738 switch( errno ) {
739 case EINTR: // signal - call read() or whatever again
740 done = false;
741 break;
742 case EPIPE:
743 case ECONNRESET:
744 // connection closed
745 close();
746 r = 0;
747 break;
748 case ENOSPC:
749 case EIO:
750 case EISDIR:
751 case EBADF:
752 case EINVAL:
753 case EFAULT:
754 case ENOTCONN:
755 case ENOTSOCK:
756 e = Impossible;
757 break;
758#if defined(ENONET)
759 case ENONET:
760#endif
761 case EHOSTUNREACH:
762 case ENETDOWN:
763 case ENETUNREACH:
764 case ETIMEDOUT:
765 e = NetworkFailure;
766 break;
767 default:
768 e = UnknownError;
769 break;
770 }
771 } else if ( waitForMore( 0, &timeout ) == 0 ) {
772 if ( !timeout ) {
773 // connection closed
774 close();
775 }
776 }
777 }
778 return r;
779}
780
781
782Q_LONG Q3SocketDevice::writeBlock( const char * data, Q_ULONG len,
783 const QHostAddress & host, Q_UINT16 port )
784{
785 if ( t != Datagram ) {
786#if defined(QT_CHECK_STATE) || defined(QSOCKETDEVICE_DEBUG)
787 qWarning( "Q3SocketDevice::sendBlock: Not datagram" );
788#endif
789 return -1; // for now - later we can do t/tcp
790 }
791
792 if ( data == 0 && len != 0 ) {
793#if defined(QT_CHECK_NULL) || defined(QSOCKETDEVICE_DEBUG)
794 qWarning( "Q3SocketDevice::sendBlock: Null pointer error" );
795#endif
796 return -1;
797 }
798 if ( !isValid() ) {
799#if defined(QT_CHECK_STATE) || defined(QSOCKETDEVICE_DEBUG)
800 qWarning( "Q3SocketDevice::sendBlock: Invalid socket" );
801#endif
802 return -1;
803 }
804 if ( !isOpen() ) {
805#if defined(QT_CHECK_STATE) || defined(QSOCKETDEVICE_DEBUG)
806 qWarning( "Q3SocketDevice::sendBlock: Device is not open" );
807#endif
808 return -1;
809 }
810 if ( !isWritable() ) {
811#if defined(QT_CHECK_STATE) || defined(QSOCKETDEVICE_DEBUG)
812 qWarning( "Q3SocketDevice::sendBlock: Write operation not permitted" );
813#endif
814 return -1;
815 }
816 struct sockaddr_in a4;
817 struct sockaddr *aa;
818 QT_SOCKLEN_T slen;
819#if !defined(QT_NO_IPV6)
820 struct sockaddr_in6 a6;
821 if ( host.isIPv6Address() ) {
822 memset( &a6, 0, sizeof(a6) );
823 a6.sin6_family = AF_INET6;
824 a6.sin6_port = htons( port );
825
826 Q_IPV6ADDR tmp = host.toIPv6Address();
827 memcpy( &a6.sin6_addr.s6_addr, &tmp, sizeof(tmp) );
828 slen = sizeof( a6 );
829 aa = (struct sockaddr *)&a6;
830 } else
831#endif
832 if ( host.isIPv4Address() ) {
833 memset( &a4, 0, sizeof(a4) );
834 a4.sin_family = AF_INET;
835 a4.sin_port = htons( port );
836 a4.sin_addr.s_addr = htonl( host.toIPv4Address() );
837 slen = sizeof(a4);
838 aa = (struct sockaddr *)&a4;
839 } else {
840 e = Impossible;
841 return -1;
842 }
843
844 // we'd use MSG_DONTWAIT + MSG_NOSIGNAL if Stevens were right.
845 // but apparently Stevens and most implementors disagree
846 bool done = false;
847 int r = 0;
848 while ( !done ) {
849 r = ::sendto( fd, data, len, 0, aa, slen);
850 done = true;
851 if ( r < 0 && e == NoError &&
852 errno != EAGAIN && errno != EWOULDBLOCK ) {
853 switch( errno ) {
854 case EINTR: // signal - call read() or whatever again
855 done = false;
856 break;
857 case ENOSPC:
858 case EPIPE:
859 case EIO:
860 case EISDIR:
861 case EBADF:
862 case EINVAL:
863 case EFAULT:
864 case ENOTCONN:
865 case ENOTSOCK:
866 e = Impossible;
867 break;
868#if defined(ENONET)
869 case ENONET:
870#endif
871 case EHOSTUNREACH:
872 case ENETDOWN:
873 case ENETUNREACH:
874 case ETIMEDOUT:
875 e = NetworkFailure;
876 break;
877 default:
878 e = UnknownError;
879 break;
880 }
881 }
882 }
883 return r;
884}
885
886
887void Q3SocketDevice::fetchConnectionParameters()
888{
889 if ( !isValid() ) {
890 p = 0;
891 a = QHostAddress();
892 pp = 0;
893 pa = QHostAddress();
894 return;
895 }
896#if !defined(QT_NO_IPV6)
897 struct sockaddr_storage sa;
898#else
899 struct sockaddr_in sa;
900#endif
901 memset( &sa, 0, sizeof(sa) );
902 QT_SOCKLEN_T sz;
903 sz = sizeof( sa );
904 if ( !::getsockname( fd, (struct sockaddr *)(&sa), &sz ) )
905 qt_socket_getportaddr( (struct sockaddr *)&sa, &p, &a );
906
907 sz = sizeof( sa );
908 if ( !::getpeername( fd, (struct sockaddr *)(&sa), &sz ) )
909 qt_socket_getportaddr( (struct sockaddr *)&sa, &pp, &pa );
910}
911
912
913Q_UINT16 Q3SocketDevice::peerPort() const
914{
915 return pp;
916}
917
918
919QHostAddress Q3SocketDevice::peerAddress() const
920{
921 return pa;
922}
923
924QT_END_NAMESPACE
925
926#endif //QT_NO_NETWORK
Note: See TracBrowser for help on using the repository browser.