| 456 | } |
| 457 | |
| 458 | TConnectionRef Connect(TCont* c, const TString& msgAddr, const TResolvedHost& addr, TErrorRef* error) { |
| 459 | if (ExceedHardLimit()) { |
| 460 | if (error) { |
| 461 | *error = new TError("neh::https output connections limit reached", TError::TType::UnknownType); |
| 462 | } |
| 463 | return nullptr; |
| 464 | } |
| 465 | |
| 466 | TConnectionRef res; |
| 467 | TConnList& connList = ConnList(addr); |
| 468 | |
| 469 | while (connList.Dequeue(&res)) { |
| 470 | ActiveConnections.Inc(); |
| 471 | CachedConnections.Dec(); |
| 472 | if (IsNotSocketClosedByOtherSide((*res)->Fd()) && !(*res)->ShutdownReceived()) { |
| 473 | return res; |
| 474 | } |
| 475 | } |
| 476 | |
| 477 | if (!c) { |
| 478 | if (error) { |
| 479 | *error = new TError("directo connection failed"); |
| 480 | } |
| 481 | return nullptr; |
| 482 | } |
| 483 | |
| 484 | const TInstant now(TInstant::Now()); |
| 485 | const TInstant deadline(now + TDuration::Seconds(10)); |
| 486 | TDuration delay = TDuration::MilliSeconds(8); |
| 487 | TInstant checkpoint = Min(deadline, delay.ToDeadLine()); |
| 488 | |
| 489 | TNetworkAddress::TIterator ait = addr.Addr.Begin(); |
| 490 | TSocketRef socket(new TSocketHolder(NCoro::Socket(*ait))); |
| 491 | int ret = NCoro::ConnectD(c, *socket, *ait, deadline); |
| 492 | res.Reset(new TConnectionHolder); |
| 493 | res->Reset(new TConnection(socket, addr)); |
| 494 | |
| 495 | if (ret) { |
| 496 | do { |
| 497 | if ((ret == ETIMEDOUT || ret == EINTR) && checkpoint < deadline) { |
| 498 | delay += delay; |
| 499 | checkpoint = Min(deadline, now + delay); |
| 500 | TConnectionRef res2; |
| 501 | if (connList.Dequeue(&res2)) { |
| 502 | ActiveConnections.Inc(); |
| 503 | CachedConnections.Dec(); |
| 504 | if (IsNotSocketClosedByOtherSide((*res2)->Fd()) && !(*res)->ShutdownReceived()) { |
| 505 | return res2; |
| 506 | } |
| 507 | } |
| 508 | } else { |
| 509 | if (error) { |
| 510 | *error = new TError(TStringBuilder() << TStringBuf("can not connect to ") << msgAddr); |
| 511 | } |
| 512 | return nullptr; |
| 513 | } |
| 514 | } while (ret = NCoro::PollD(c, (*res)->Fd(), CONT_POLL_WRITE, checkpoint)); |
| 515 | } |
no test coverage detected