/*! Fetches information about both ends of the connection: whatever is available. */ void MSocketDevice::fetchConnectionParameters() { if (!isValid()) { p = 0; a = QHostAddress(); pp = 0; pa = QHostAddress(); return; } #if !defined(QT_NO_IPV6) struct sockaddr_storage sa; #else struct sockaddr_in sa; #endif memset(&sa, 0, sizeof(sa)); QT_SOCKLEN_T sz; sz = sizeof(sa); if (!::getsockname(fd, (struct sockaddr *)(&sa), &sz)) qt_socket_getportaddr((struct sockaddr *)&sa, &p, &a); sz = sizeof(sa); if (!::getpeername(fd, (struct sockaddr *)(&sa), &sz)) qt_socket_getportaddr((struct sockaddr *)&sa, &pp, &pa); }
void Q3SocketDevice::fetchPeerConnectionParameters() { // do the getpeername() lazy on Windows (sales/arc-18/37759 claims that // there will be problems otherwise if you use MS Proxy server) #if !defined (QT_NO_IPV6) struct qt_sockaddr_storage sa; #else struct sockaddr_in sa; #endif memset( &sa, 0, sizeof(sa) ); SOCKLEN_T sz; sz = sizeof( sa ); if ( !::getpeername( fd, (struct sockaddr *)(&sa), &sz ) ) qt_socket_getportaddr( (struct sockaddr *)(&sa), &pp, &pa ); }
/*! Reads \a maxlen bytes from the socket into \a data and returns the number of bytes read. Returns -1 if an error occurred. */ qint64 MSocketDevice::readData( char *data, qint64 maxlen ) { if ( maxlen == 0 ) return 0; if ( data == 0 ) { VERBOSE(VB_SOCKET|VB_EXTRA, "MSocketDevice::readBlock: Null pointer error"); return -1; } if ( !isValid() ) { VERBOSE(VB_SOCKET|VB_EXTRA, "MSocketDevice::readBlock: Invalid socket"); return -1; } if ( !isOpen() ) { VERBOSE(VB_SOCKET|VB_EXTRA, "MSocketDevice::readBlock: Device is not open"); return -1; } if ( !isReadable() ) { VERBOSE(VB_SOCKET|VB_EXTRA, "MSocketDevice::readBlock: Read operation not permitted"); return -1; } bool done = false; int r = 0; while ( done == false ) { if ( t == Datagram ) { #if !defined(QT_NO_IPV6) struct sockaddr_storage aa; #else struct sockaddr_in aa; #endif memset( &aa, 0, sizeof(aa) ); QT_SOCKLEN_T sz; sz = sizeof( aa ); r = ::recvfrom( fd, data, maxlen, 0, (struct sockaddr *)&aa, &sz ); qt_socket_getportaddr( (struct sockaddr *)&aa, &pp, &pa); } else { r = ::read( fd, data, maxlen ); } done = true; if ( r == 0 && t == Stream && maxlen > 0 ) { // connection closed close(); } else if ( r >= 0 || errno == EAGAIN || errno == EWOULDBLOCK ) { // nothing } else if ( errno == EINTR ) { done = false; } else if ( e == NoError ) { switch( errno ) { case EIO: case EISDIR: case EBADF: case EINVAL: case EFAULT: case ENOTCONN: case ENOTSOCK: e = Impossible; break; #if defined(ENONET) case ENONET: #endif case EHOSTUNREACH: case ENETDOWN: case ENETUNREACH: case ETIMEDOUT: e = NetworkFailure; break; case EPIPE: case ECONNRESET: // connection closed close(); r = 0; break; default: e = UnknownError; break; } } } return r; }
qint64 Q3SocketDevice::readData( char *data, qint64 maxlen ) { #if defined(QT_CHECK_NULL) if ( data == 0 && maxlen != 0 ) { qWarning( "Q3SocketDevice::readBlock: Null pointer error" ); } #endif #if defined(QT_CHECK_STATE) if ( !isValid() ) { qWarning( "Q3SocketDevice::readBlock: Invalid socket" ); return -1; } if ( !isOpen() ) { qWarning( "Q3SocketDevice::readBlock: Device is not open" ); return -1; } if ( !isReadable() ) { qWarning( "Q3SocketDevice::readBlock: Read operation not permitted" ); return -1; } #endif qint64 r = 0; if ( t == Datagram ) { #if !defined(QT_NO_IPV6) // With IPv6 support, we must be prepared to receive both IPv4 // and IPv6 packets. The generic SOCKADDR_STORAGE (struct // sockaddr_storage on unix) replaces struct sockaddr. struct qt_sockaddr_storage a; #else struct sockaddr_in a; #endif memset( &a, 0, sizeof(a) ); SOCKLEN_T sz; sz = sizeof( a ); r = ::recvfrom( fd, data, maxlen, 0, (struct sockaddr *)&a, &sz ); qt_socket_getportaddr( (struct sockaddr *)(&a), &pp, &pa ); } else { r = ::recv( fd, data, maxlen, 0 ); } if ( r == 0 && t == Stream && maxlen > 0 ) { if ( WSAGetLastError() != WSAEWOULDBLOCK ) { // connection closed close(); } } else if ( r == SOCKET_ERROR && e == NoError ) { switch( WSAGetLastError() ) { case WSANOTINITIALISED: e = Impossible; break; case WSAECONNABORTED: close(); r = 0; break; case WSAETIMEDOUT: case WSAECONNRESET: /* From msdn doc: On a UDP datagram socket this error would indicate that a previous send operation resulted in an ICMP "Port Unreachable" message. So we should not close this socket just because one sendto failed. */ if ( t != Datagram ) close(); // connection closed r = 0; break; case WSAENETDOWN: case WSAENETRESET: e = NetworkFailure; break; case WSAEFAULT: case WSAENOTCONN: case WSAESHUTDOWN: case WSAEINVAL: e = Impossible; break; case WSAEINTR: // ### ? r = 0; break; case WSAEINPROGRESS: e = NoResources; break; case WSAENOTSOCK: e = Impossible; break; case WSAEOPNOTSUPP: e = InternalError; // ### ? break; case WSAEWOULDBLOCK: break; case WSAEMSGSIZE: e = NoResources; // ### ? break; case WSAEISCONN: // ### ? r = 0; break; default: e = UnknownError; break; } } return r; }