| 443 | } |
| 444 | |
| 445 | Result DoDial(HPool pool, const char* host, uint16_t port, bool ssl, int timeout, int* cancelflag, HConnection* connection, dmSocket::Result* sock_res, bool ipv4, bool ipv6) |
| 446 | { |
| 447 | if (!pool->m_AllowNewConnections) { |
| 448 | return RESULT_SHUT_DOWN; |
| 449 | } |
| 450 | |
| 451 | // This function would previously not specify ipv4 and/or ipv6 when calling GetHostByName. |
| 452 | // GetHostByName would then assume both ipv4 and ipv6 and always prefer and return an ipv4 |
| 453 | // address. |
| 454 | // Connecting to the returned address would fail when on an ipv6 network. |
| 455 | // This is why when calling DoDial we now have the ability to specify ipv4 and/or ipv6 so |
| 456 | // that the caller can try to connect first to ipv4 and then to ipv6 if ipv4 failed. |
| 457 | dmSocket::Address address; |
| 458 | |
| 459 | uint64_t dial_started = dmTime::GetMonotonicTime(); |
| 460 | bool gethost_did_succeed = dmSocket::GetHostByNameT(host, &address, timeout, cancelflag, ipv4, ipv6) == dmSocket::RESULT_OK; |
| 461 | if (timeout > 0) |
| 462 | { |
| 463 | timeout = timeout - (int)(dmTime::GetMonotonicTime() - dial_started); |
| 464 | if (timeout <= 0) |
| 465 | { |
| 466 | return RESULT_SOCKET_ERROR; |
| 467 | } |
| 468 | } |
| 469 | |
| 470 | dmhash_t conn_id = CalculateConnectionID(address, port, ssl); |
| 471 | |
| 472 | Connection* c = 0; |
| 473 | uint32_t index; |
| 474 | |
| 475 | if (gethost_did_succeed) { |
| 476 | DM_MUTEX_SCOPED_LOCK(pool->m_Mutex); |
| 477 | |
| 478 | PurgeExpired(pool); |
| 479 | |
| 480 | if (!pool->m_AllowNewConnections) { |
| 481 | *sock_res = dmSocket::RESULT_CONNABORTED; |
| 482 | return RESULT_SHUT_DOWN; |
| 483 | } |
| 484 | |
| 485 | if (FindConnection(pool, conn_id, address, port, ssl, connection)) { |
| 486 | return RESULT_OK; |
| 487 | } |
| 488 | |
| 489 | if (!FindSlot(pool, &index, &c)) { |
| 490 | return RESULT_OUT_OF_RESOURCES; |
| 491 | } |
| 492 | c->m_State = STATE_INUSE; // The connection might fail, but we need to reserve this in the meantime |
| 493 | |
| 494 | } else { |
| 495 | *sock_res = dmSocket::RESULT_HOST_NOT_FOUND; // Only error that dmSocket::getHostByName returns |
| 496 | return RESULT_SOCKET_ERROR; |
| 497 | } |
| 498 | |
| 499 | dmSocket::Socket socket = dmSocket::INVALID_SOCKET_HANDLE; |
| 500 | dmSSLSocket::Socket sslsocket = dmSSLSocket::INVALID_SOCKET_HANDLE; |
| 501 | |
| 502 | Result r = Connect(pool, c, host, address, port, timeout, &socket, sock_res); |
no test coverage detected