From 6d7db5da6129ea012e7f5dff4466a0bf624e1b71 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Wed, 6 Jul 2016 14:49:39 +0200 Subject: keep trying with next if connection to a SRV host failed Instead of only trying the first host we get via SRV, we try them all as we are supposed to and if that isn't working we try to connect to the host itself as if we hadn't seen any SRV records. This was already the intend of the old code, but it failed to hide earlier problems for the next call, which would unconditionally fail then resulting in an all around failure to connect. With proper stacking we can also keep the error messages of each call around (and in the order tried) so if the entire connection fails we can report all the things we have tried while we discard the entire stack if something works out in the end. (cherry picked from commit 3af3ac2f5ec007badeded46a94be2bd06b9917a2) --- methods/connect.cc | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/methods/connect.cc b/methods/connect.cc index 07a730b88..f768169d1 100644 --- a/methods/connect.cc +++ b/methods/connect.cc @@ -280,19 +280,35 @@ bool Connect(std::string Host,int Port,const char *Service, if (_config->FindB("Acquire::EnableSrvRecords", true) == true) GetSrvRecords(Host, DefPort, SrvRecords); } - // we have no SrvRecords for this host, connect right away - if(SrvRecords.size() == 0) - return ConnectToHostname(Host, Port, Service, DefPort, Fd, - TimeOut, Owner); + size_t stackSize = 0; // try to connect in the priority order of the srv records - while(SrvRecords.size() > 0) + std::string initialHost{std::move(Host)}; + while(SrvRecords.empty() == false) { + _error->PushToStack(); + ++stackSize; // PopFromSrvRecs will also remove the server Host = PopFromSrvRecs(SrvRecords).target; - if(ConnectToHostname(Host, Port, Service, DefPort, Fd, TimeOut, Owner)) + auto const ret = ConnectToHostname(Host, Port, Service, DefPort, Fd, TimeOut, Owner); + if (ret) + { + while(stackSize--) + _error->RevertToStack(); return true; + } } + Host = std::move(initialHost); - return false; + // we have no (good) SrvRecords for this host, connect right away + _error->PushToStack(); + ++stackSize; + auto const ret = ConnectToHostname(Host, Port, Service, DefPort, Fd, + TimeOut, Owner); + while(stackSize--) + if (ret) + _error->RevertToStack(); + else + _error->MergeWithStack(); + return ret; } -- cgit v1.2.3