summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Kalnischkies <david@kalnischkies.de>2016-07-06 14:49:39 +0200
committerDavid Kalnischkies <david@kalnischkies.de>2016-07-06 15:53:59 +0200
commit3af3ac2f5ec007badeded46a94be2bd06b9917a2 (patch)
tree38513401fbf38cbb9d3836ddb0c0cb4b873e35cc
parentb50dfa6b2dd2d459e0c2746ac9367982b96ffac0 (diff)
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.
-rw-r--r--methods/connect.cc30
1 files 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;
}