X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/f5c0ab925fdceb1bc0ef0e958cae7d0fafb28caf..34b491e735ad47c4805e63f3b83a659b8d10262b:/apt-pkg/contrib/srvrec.cc?ds=sidebyside diff --git a/apt-pkg/contrib/srvrec.cc b/apt-pkg/contrib/srvrec.cc index b4a3d97d2..327e59937 100644 --- a/apt-pkg/contrib/srvrec.cc +++ b/apt-pkg/contrib/srvrec.cc @@ -13,9 +13,10 @@ #include #include #include -#include +#include #include +#include #include #include @@ -25,11 +26,22 @@ #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 &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 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()); @@ -68,7 +80,6 @@ bool GetSrvRecords(std::string name, std::vector &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]; @@ -105,11 +116,7 @@ bool GetSrvRecords(std::string name, std::vector &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 @@ -173,21 +180,14 @@ SrvRec PopFromSrvRecs(std::vector &Recs) #endif // shuffle in a very simplistic way for now (equal weights) - std::vector::iterator I, J; - I = J = Recs.begin(); - for(;I != Recs.end(); ++I) - { - if(I->priority != J->priority) - break; - } - - // FIXME: meeeeh, where to init this properly - unsigned seed = std::chrono::system_clock::now().time_since_epoch().count(); - std::shuffle(J, I, std::default_random_engine(seed)); - - // meh, no pop_front() in std::vector? - SrvRec selected = *Recs.begin(); - Recs.erase(Recs.begin()); + std::vector::iterator I = Recs.begin(); + std::vector::iterator const J = std::find_if(Recs.begin(), Recs.end(), + [&I](SrvRec const &J) { return I->priority != J.priority; }); + + // clock seems random enough. + I += std::max(static_cast(0), 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;