/*! \reimp Closes the socket and sets the socket identifier to -1 (invalid). (This function ignores errors; if there are any then a file descriptor leakage might result. As far as we know, the only error that can arise is EBADF, and that would of course not cause leakage. There may be OS-specific errors that we haven't come across, however.) \sa open() */ void MSocketDevice::close() { if ( fd == -1 || !isOpen() ) // already closed return; setOpenMode(NotOpen); ::close( fd ); VERBOSE(VB_SOCKET|VB_EXTRA, QString("MSocketDevice::close: Closed socket %1").arg(fd)); fd = -1; fetchConnectionParameters(); QIODevice::close(); }
void MSocketDevice::close() { if ( fd == -1 || !isOpen() ) // already closed return; setOpenMode(NotOpen); ::closesocket( fd ); #if defined(QSOCKETDEVICE_DEBUG) qDebug( "MSocketDevice::close: Closed socket %x", fd ); #endif fd = -1; fetchConnectionParameters(); QIODevice::close(); }
/*! Sets the socket device to operate on the existing socket \a socket. The \a type argument must match the actual socket type; use \c Q3SocketDevice::Stream for a reliable, connection-oriented TCP socket, or Q3SocketDevice::Datagram for an unreliable, connectionless UDP socket. Any existing socket is closed. \sa isValid(), close() */ void Q3SocketDevice::setSocket( int socket, Type type ) { if ( fd != -1 ) // close any open socket close(); #if defined(Q3SOCKETDEVICE_DEBUG) qDebug( "Q3SocketDevice::setSocket: socket %x, type %d", socket, type ); #endif t = type; fd = socket; d->protocol = Unknown; e = NoError; resetStatus(); open( ReadWrite ); fetchConnectionParameters(); }
/*! Assigns a name to an unnamed socket. The name is the host address \a address and the port number \a port. If the operation succeeds, bind() returns true; otherwise it returns false without changing what port() and address() return. bind() is used by servers for setting up incoming connections. Call bind() before listen(). */ bool MSocketDevice::bind( const QHostAddress &address, quint16 port ) { if ( !isValid() ) return false; int r; struct sockaddr_in a4; #if !defined(QT_NO_IPV6) struct sockaddr_in6 a6; if ( address.protocol() == QAbstractSocket::IPv6Protocol ) { memset( &a6, 0, sizeof(a6) ); a6.sin6_family = AF_INET6; a6.sin6_port = htons( port ); Q_IPV6ADDR tmp = address.toIPv6Address(); memcpy( &a6.sin6_addr.s6_addr, &tmp, sizeof(tmp) ); r = QT_SOCKET_BIND( fd, (struct sockaddr *)&a6, sizeof(a6) ); } else #endif if ( address.protocol() == QAbstractSocket::IPv4Protocol ) { memset( &a4, 0, sizeof(a4) ); a4.sin_family = AF_INET; a4.sin_port = htons( port ); a4.sin_addr.s_addr = htonl( address.toIPv4Address() ); r = QT_SOCKET_BIND( fd, (struct sockaddr*)&a4, sizeof(a4) ); } else { e = Impossible; return false; } if ( r < 0 ) { switch( errno ) { case EINVAL: e = AlreadyBound; break; case EACCES: e = Inaccessible; break; case ENOMEM: e = NoResources; break; case EFAULT: // a was illegal case ENAMETOOLONG: // sz was wrong e = InternalError; break; case EBADF: // AF_UNIX only case ENOTSOCK: // AF_UNIX only case EROFS: // AF_UNIX only case ENOENT: // AF_UNIX only case ENOTDIR: // AF_UNIX only case ELOOP: // AF_UNIX only e = Impossible; break; default: e = UnknownError; break; } return false; } fetchConnectionParameters(); return true; }
/*! Connects to the IP address and port specified by \a addr and \a port. Returns true if it establishes a connection; otherwise returns false. If it returns false, error() explains why. Note that error() commonly returns NoError for non-blocking sockets; this just means that you can call connect() again in a little while and it'll probably succeed. */ bool MSocketDevice::connect( const QHostAddress &addr, quint16 port ) { if ( !isValid() ) { #if !defined(QT_NO_IPV6) if ( addr.protocol() == QAbstractSocket::IPv6Protocol ) { setProtocol(IPv6); VERBOSE(VB_SOCKET, "MSocketDevice::connect: setting Protocol to IPv6"); } else #endif if ( addr.protocol() == QAbstractSocket::IPv4Protocol ) { setProtocol(IPv4); VERBOSE(VB_SOCKET, "MSocketDevice::connect: setting Protocol to IPv4"); } VERBOSE(VB_SOCKET, "MSocketDevice::connect: attempting to create new socket"); MSocketDevice::setSocket( createNewSocket(), t); // If still not valid, give up. if ( !isValid() ) return false; } pa = addr; pp = port; struct sockaddr_in a4; struct sockaddr *aa; QT_SOCKLEN_T aalen; #if !defined(QT_NO_IPV6) struct sockaddr_in6 a6; if ( addr.protocol() == QAbstractSocket::IPv6Protocol ) { memset( &a6, 0, sizeof(a6) ); a6.sin6_family = AF_INET6; a6.sin6_port = htons( port ); Q_IPV6ADDR ip6 = addr.toIPv6Address(); memcpy( &a6.sin6_addr.s6_addr, &ip6, sizeof(ip6) ); aalen = sizeof( a6 ); aa = (struct sockaddr *)&a6; } else #endif if ( addr.protocol() == QAbstractSocket::IPv4Protocol ) { memset( &a4, 0, sizeof(a4) ); a4.sin_family = AF_INET; a4.sin_port = htons( port ); a4.sin_addr.s_addr = htonl( addr.toIPv4Address() ); aalen = sizeof(a4); aa = (struct sockaddr *)&a4; } else { e = Impossible; return false; } int r = QT_SOCKET_CONNECT( fd, aa, aalen ); if ( r == 0 ) { fetchConnectionParameters(); return true; } if ( errno == EISCONN || errno == EALREADY || errno == EINPROGRESS ) { fetchConnectionParameters(); return true; } if ( e != NoError || errno == EAGAIN || errno == EWOULDBLOCK ) { return false; } switch( errno ) { case EBADF: case ENOTSOCK: e = Impossible; break; case EFAULT: case EAFNOSUPPORT: e = InternalError; break; case ECONNREFUSED: e = ConnectionRefused; break; case ETIMEDOUT: case ENETUNREACH: e = NetworkFailure; break; case EADDRINUSE: e = NoResources; break; case EACCES: case EPERM: e = Inaccessible; break; default: e = UnknownError; break; } return false; }
bool Q3SocketDevice::connect( const QHostAddress &addr, Q_UINT16 port ) { if ( !isValid() ) return false; pa = addr; pp = port; struct sockaddr_in a4; struct sockaddr *aa; QT_SOCKLEN_T aalen; #if !defined(QT_NO_IPV6) struct sockaddr_in6 a6; if ( addr.isIPv6Address() ) { memset( &a6, 0, sizeof(a6) ); a6.sin6_family = AF_INET6; a6.sin6_port = htons( port ); Q_IPV6ADDR ip6 = addr.toIPv6Address(); memcpy( &a6.sin6_addr.s6_addr, &ip6, sizeof(ip6) ); aalen = sizeof( a6 ); aa = (struct sockaddr *)&a6; } else #endif if ( addr.isIPv4Address() ) { memset( &a4, 0, sizeof(a4) ); a4.sin_family = AF_INET; a4.sin_port = htons( port ); a4.sin_addr.s_addr = htonl( addr.toIPv4Address() ); aalen = sizeof(a4); aa = (struct sockaddr *)&a4; } else { e = Impossible; return false; } int r = QT_SOCKET_CONNECT( fd, aa, aalen ); if ( r == 0 ) { fetchConnectionParameters(); return true; } if ( errno == EISCONN || errno == EALREADY || errno == EINPROGRESS ) { fetchConnectionParameters(); return true; } if ( e != NoError || errno == EAGAIN || errno == EWOULDBLOCK ) { return false; } switch( errno ) { case EBADF: case ENOTSOCK: e = Impossible; break; case EFAULT: case EAFNOSUPPORT: e = InternalError; break; case ECONNREFUSED: e = ConnectionRefused; break; case ETIMEDOUT: case ENETUNREACH: e = NetworkFailure; break; case EADDRINUSE: e = NoResources; break; case EACCES: case EPERM: e = Inaccessible; break; default: e = UnknownError; break; } return false; }
bool Q3SocketDevice::bind( const QHostAddress &address, quint16 port ) { if ( !isValid() ) return false; int r; struct sockaddr_in a4; #if !defined(QT_NO_IPV6) qt_sockaddr_in6 a6; if ( initialized >= 0x20 && address.isIPv6Address() ) { memset( &a6, 0, sizeof(a6) ); a6.sin6_family = AF_INET6; a6.sin6_port = htons( port ); Q_IPV6ADDR tmp = address.toIPv6Address(); memcpy( &a6.sin6_addr.qt_s6_addr, &tmp, sizeof(tmp) ); r = ::bind( fd, (struct sockaddr *)&a6, sizeof(struct qt_sockaddr_storage) ); } else #endif if ( address.isIPv4Address() ) { memset( &a4, 0, sizeof(a4) ); a4.sin_family = AF_INET; a4.sin_port = htons( port ); a4.sin_addr.s_addr = htonl( address.toIPv4Address() ); r = ::bind( fd, (struct sockaddr*)&a4, sizeof(struct sockaddr_in) ); } else { e = Impossible; return false; } if ( r == SOCKET_ERROR ) { switch( WSAGetLastError() ) { case WSANOTINITIALISED: e = Impossible; break; case WSAENETDOWN: e = NetworkFailure; break; case WSAEACCES: e = Inaccessible; break; case WSAEADDRNOTAVAIL: e = Inaccessible; break; case WSAEFAULT: e = InternalError; break; case WSAEINPROGRESS: case WSAENOBUFS: e = NoResources; break; case WSAEADDRINUSE: case WSAEINVAL: e = AlreadyBound; break; case WSAENOTSOCK: e = Impossible; break; default: e = UnknownError; break; } return false; } fetchConnectionParameters(); return true; }
bool Q3SocketDevice::connect( const QHostAddress &addr, quint16 port ) { if ( !isValid() ) return false; pa = addr; pp = port; struct sockaddr_in a4; struct sockaddr *aa; SOCKLEN_T aalen; #if !defined(QT_NO_IPV6) qt_sockaddr_in6 a6; if ( initialized >= 0x20 && addr.isIPv6Address() ) { memset(&a6, 0, sizeof(a6)); a6.sin6_family = AF_INET6; a6.sin6_port = htons( port ); Q_IPV6ADDR ip6 = addr.toIPv6Address(); memcpy( &a6.sin6_addr.qt_s6_addr, &ip6, sizeof(ip6) ); aalen = sizeof( a6 ); aa = (struct sockaddr *)&a6; } else #endif if ( addr.isIPv4Address() ) { memset(&a4, 0, sizeof(a4)); a4.sin_family = AF_INET; a4.sin_port = htons(port); a4.sin_addr.s_addr = htonl(addr.toIPv4Address()); aalen = sizeof(a4); aa = (struct sockaddr *)&a4; } else { e = Impossible; return false; } int r = ::connect( fd, aa, aalen ); if ( r == SOCKET_ERROR ) { switch( WSAGetLastError() ) { case WSANOTINITIALISED: e = Impossible; break; case WSAENETDOWN: e = NetworkFailure; break; case WSAEADDRINUSE: case WSAEINPROGRESS: case WSAENOBUFS: e = NoResources; break; case WSAEINTR: e = UnknownError; // ### ? break; case WSAEALREADY: // ### ? break; case WSAEADDRNOTAVAIL: e = ConnectionRefused; // ### ? break; case WSAEAFNOSUPPORT: case WSAEFAULT: e = InternalError; break; case WSAEINVAL: break; case WSAECONNREFUSED: e = ConnectionRefused; break; case WSAEISCONN: goto successful; case WSAENETUNREACH: case WSAETIMEDOUT: e = NetworkFailure; break; case WSAENOTSOCK: e = Impossible; break; case WSAEWOULDBLOCK: break; case WSAEACCES: e = Inaccessible; break; case 10107: // Workaround for a problem with the WinSock Proxy Server. See // also support/arc-12/25557 for details on the problem. goto successful; default: e = UnknownError; break; } return false; } successful: fetchConnectionParameters(); return true; }