X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/9b70edba6796ebff3935af1cfb5c9bbc98d020b4..d27daedb6a0bf672508072100f20233d08ccf0e0:/apt-pkg/contrib/srvrec.cc?ds=inline diff --git a/apt-pkg/contrib/srvrec.cc b/apt-pkg/contrib/srvrec.cc index 85241c1d7..be159bad9 100644 --- a/apt-pkg/contrib/srvrec.cc +++ b/apt-pkg/contrib/srvrec.cc @@ -13,18 +13,35 @@ #include <netinet/in.h> #include <arpa/nameser.h> #include <resolv.h> +#include <time.h> #include <algorithm> +#include <tuple> -#include <apt-pkg/strutl.h> +#include <apt-pkg/configuration.h> #include <apt-pkg/error.h> +#include <apt-pkg/strutl.h> + + #include "srvrec.h" + +bool SrvRec::operator==(SrvRec const &other) const +{ + return (std::tie(target, priority, weight, port) == + std::tie(other.target, other.priority, other.weight, other.port)); +} + bool GetSrvRecords(std::string host, int port, std::vector<SrvRec> &Result) { std::string target; - struct servent *s_ent = getservbyport(htons(port), "tcp"); - if (s_ent == NULL) + int res; + struct servent s_ent_buf; + struct servent *s_ent = nullptr; + std::vector<char> buf(1024); + + res = getservbyport_r(htons(port), "tcp", &s_ent_buf, buf.data(), buf.size(), &s_ent); + if (res != 0 || s_ent == nullptr) return false; strprintf(target, "_%s._tcp.%s", s_ent->s_name, host.c_str()); @@ -63,7 +80,6 @@ bool GetSrvRecords(std::string name, std::vector<SrvRec> &Result) unsigned char *pt = answer+sizeof(HEADER)+compressed_name_len+QFIXEDSZ; while ((int)Result.size() < answer_count && pt < answer+answer_len) { - SrvRec rec; u_int16_t type, klass, priority, weight, port, dlen; char buf[MAXDNAME]; @@ -100,11 +116,7 @@ bool GetSrvRecords(std::string name, std::vector<SrvRec> &Result) pt += compressed_name_len; // add it to our class - rec.priority = priority; - rec.weight = weight; - rec.port = port; - rec.target = buf; - Result.push_back(rec); + Result.emplace_back(buf, priority, weight, port); } // implement load balancing as specified in RFC-2782 @@ -112,6 +124,29 @@ bool GetSrvRecords(std::string name, std::vector<SrvRec> &Result) // sort them by priority std::stable_sort(Result.begin(), Result.end()); + for(std::vector<SrvRec>::iterator I = Result.begin(); + I != Result.end(); ++I) + { + if (_config->FindB("Debug::Acquire::SrvRecs", false) == true) + { + std::cerr << "SrvRecs: got " << I->target + << " prio: " << I->priority + << " weight: " << I->weight + << std::endl; + } + } + + return true; +} + +SrvRec PopFromSrvRecs(std::vector<SrvRec> &Recs) +{ + // FIXME: instead of the simplistic shuffle below use the algorithm + // described in rfc2782 (with weights) + // and figure out how the weights need to be adjusted if + // a host refuses connections + +#if 0 // all code below is only needed for the weight adjusted selection // assign random number ranges int prev_weight = 0; int prev_priority = 0; @@ -124,6 +159,12 @@ bool GetSrvRecords(std::string name, std::vector<SrvRec> &Result) I->random_number_range_end = prev_weight + I->weight; prev_weight = I->random_number_range_end; prev_priority = I->priority; + + if (_config->FindB("Debug::Acquire::SrvRecs", false) == true) + std::cerr << "SrvRecs: got " << I->target + << " prio: " << I->priority + << " weight: " << I->weight + << std::endl; } // go over the code in reverse order and note the max random range @@ -136,8 +177,20 @@ bool GetSrvRecords(std::string name, std::vector<SrvRec> &Result) max = I->random_number_range_end; I->random_number_range_max = max; } +#endif - // FIXME: now shuffle + // shuffle in a very simplistic way for now (equal weights) + std::vector<SrvRec>::iterator I = Recs.begin(); + std::vector<SrvRec>::iterator const J = std::find_if(Recs.begin(), Recs.end(), + [&I](SrvRec const &J) { return I->priority != J.priority; }); - return true; + // clock seems random enough. + I += clock() % std::distance(I, J); + SrvRec const selected = std::move(*I); + Recs.erase(I); + + if (_config->FindB("Debug::Acquire::SrvRecs", false) == true) + std::cerr << "PopFromSrvRecs: selecting " << selected.target << std::endl; + + return selected; }