///////////////////////////////////////////////////////
| 838 | |
| 839 | //////////////////////////////////////////////////////////// |
| 840 | Socket::Status TcpSocket::connect(IpAddress remoteAddress, unsigned short remotePort, Time timeout) |
| 841 | { |
| 842 | // Disconnect the socket if it is already connected |
| 843 | disconnect(); |
| 844 | |
| 845 | // Create the remote address |
| 846 | sockaddr_in addressV4{}; |
| 847 | sockaddr_in6 addressV6{}; |
| 848 | sockaddr* sockaddrPtr{}; |
| 849 | priv::SocketImpl::AddrLength sockaddrSize{}; |
| 850 | |
| 851 | if (remoteAddress.isV4()) |
| 852 | { |
| 853 | addressV4 = priv::SocketImpl::createAddress(remoteAddress.toInteger(), remotePort); |
| 854 | sockaddrPtr = reinterpret_cast<sockaddr*>(&addressV4); |
| 855 | sockaddrSize = sizeof(addressV4); |
| 856 | |
| 857 | // Create the internal socket if it doesn't exist |
| 858 | create(IpAddress::Type::IpV4); |
| 859 | } |
| 860 | else if (remoteAddress.isV6()) |
| 861 | { |
| 862 | addressV6 = priv::SocketImpl::createAddress(remoteAddress.toBytes(), remotePort); |
| 863 | sockaddrPtr = reinterpret_cast<sockaddr*>(&addressV6); |
| 864 | sockaddrSize = sizeof(addressV6); |
| 865 | |
| 866 | // Create the internal socket if it doesn't exist |
| 867 | create(IpAddress::Type::IpV6); |
| 868 | } |
| 869 | |
| 870 | assert(sockaddrPtr && sockaddrSize); |
| 871 | |
| 872 | if (timeout <= Time::Zero) |
| 873 | { |
| 874 | // ----- We're not using a timeout: just try to connect ----- |
| 875 | |
| 876 | // Connect the socket |
| 877 | if (::connect(getNativeHandle(), sockaddrPtr, sockaddrSize) == -1) |
| 878 | return priv::SocketImpl::getErrorStatus(); |
| 879 | |
| 880 | // Connection succeeded |
| 881 | return Status::Done; |
| 882 | } |
| 883 | |
| 884 | // ----- We're using a timeout: we'll need a few tricks to make it work ----- |
| 885 | |
| 886 | // Save the previous blocking state |
| 887 | const bool blocking = isBlocking(); |
| 888 | |
| 889 | // Switch to non-blocking to enable our connection timeout |
| 890 | if (blocking) |
| 891 | setBlocking(false); |
| 892 | |
| 893 | // Try to connect to the remote address |
| 894 | if (::connect(getNativeHandle(), sockaddrPtr, sockaddrSize) >= 0) |
| 895 | { |
| 896 | // We got instantly connected! (it may no happen a lot...) |
| 897 | setBlocking(blocking); |