| 112 | } |
| 113 | |
| 114 | bool Socket::Connect( const char* addr, uint16_t port ) |
| 115 | { |
| 116 | assert( !IsValid() ); |
| 117 | |
| 118 | if( m_ptr ) |
| 119 | { |
| 120 | const auto c = connect( m_connSock, m_ptr->ai_addr, m_ptr->ai_addrlen ); |
| 121 | if( c == -1 ) |
| 122 | { |
| 123 | #if defined _WIN32 |
| 124 | const auto err = WSAGetLastError(); |
| 125 | if( err == WSAEALREADY || err == WSAEINPROGRESS ) return false; |
| 126 | if( err != WSAEISCONN ) |
| 127 | { |
| 128 | freeaddrinfo( m_res ); |
| 129 | closesocket( m_connSock ); |
| 130 | m_ptr = nullptr; |
| 131 | return false; |
| 132 | } |
| 133 | #else |
| 134 | const auto err = errno; |
| 135 | if( err == EALREADY || err == EINPROGRESS ) return false; |
| 136 | if( err != EISCONN ) |
| 137 | { |
| 138 | freeaddrinfo( m_res ); |
| 139 | close( m_connSock ); |
| 140 | m_ptr = nullptr; |
| 141 | return false; |
| 142 | } |
| 143 | #endif |
| 144 | } |
| 145 | |
| 146 | #if defined _WIN32 |
| 147 | u_long nonblocking = 0; |
| 148 | ioctlsocket( m_connSock, FIONBIO, &nonblocking ); |
| 149 | #else |
| 150 | int flags = fcntl( m_connSock, F_GETFL, 0 ); |
| 151 | fcntl( m_connSock, F_SETFL, flags & ~O_NONBLOCK ); |
| 152 | #endif |
| 153 | m_sock.store( m_connSock, std::memory_order_relaxed ); |
| 154 | freeaddrinfo( m_res ); |
| 155 | m_ptr = nullptr; |
| 156 | return true; |
| 157 | } |
| 158 | |
| 159 | struct addrinfo hints; |
| 160 | struct addrinfo *res, *ptr; |
| 161 | |
| 162 | memset( &hints, 0, sizeof( hints ) ); |
| 163 | hints.ai_family = AF_UNSPEC; |
| 164 | hints.ai_socktype = SOCK_STREAM; |
| 165 | |
| 166 | char portbuf[32]; |
| 167 | sprintf( portbuf, "%" PRIu16, port ); |
| 168 | |
| 169 | if( getaddrinfo( addr, portbuf, &hints, &res ) != 0 ) return false; |
| 170 | int sock = 0; |
| 171 | for( ptr = res; ptr; ptr = ptr->ai_next ) |
no test coverage detected