summaryrefslogtreecommitdiff
path: root/apt-pkg
diff options
context:
space:
mode:
authorDavid Kalnischkies <david@kalnischkies.de>2015-09-01 18:32:22 +0200
committerDavid Kalnischkies <david@kalnischkies.de>2015-09-01 19:01:45 +0200
commit76abe9a5aad69eb7e67295588c6825cdae0341af (patch)
treef118c70def8f789a07a2e81a3c8966fa56e322e7 /apt-pkg
parent63d609985eb7eefa5f2332bfe4fab96f017760a1 (diff)
use clock() as source for SRV randomness
Initializing a random number generator with the time since epoch could be good enough, but reaches its limits in test code as the 100 iterations might very well happen in the same second and hence the seed number is always the sameā€¦ clock() has a way lower resolution so it changes more often and not unimportant: If many users start the update at the same time it isn't to unlikely the SRV record will be ordered in the same second choosing the same for them all, but it seems less likely that the exact same clock() time has passed for them. And if I have to touch this, lets change a few other things as well to make me and/or compilers a bit happier (clang complained about the usage of a GNU extension in the testcase for example).
Diffstat (limited to 'apt-pkg')
-rw-r--r--apt-pkg/contrib/srvrec.cc32
-rw-r--r--apt-pkg/contrib/srvrec.h10
2 files changed, 18 insertions, 24 deletions
diff --git a/apt-pkg/contrib/srvrec.cc b/apt-pkg/contrib/srvrec.cc
index b4a3d97d2..174668274 100644
--- a/apt-pkg/contrib/srvrec.cc
+++ b/apt-pkg/contrib/srvrec.cc
@@ -13,7 +13,7 @@
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <resolv.h>
-#include <chrono>
+#include <time.h>
#include <algorithm>
@@ -68,7 +68,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];
@@ -105,11 +104,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
@@ -173,21 +168,14 @@ SrvRec PopFromSrvRecs(std::vector<SrvRec> &Recs)
#endif
// shuffle in a very simplistic way for now (equal weights)
- std::vector<SrvRec>::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<SrvRec>::const_iterator I = Recs.begin();
+ std::vector<SrvRec>::const_iterator const J = std::find_if(Recs.cbegin(), Recs.cend(),
+ [&I](SrvRec const &J) { return I->priority != J.priority; });
+
+ // 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;
diff --git a/apt-pkg/contrib/srvrec.h b/apt-pkg/contrib/srvrec.h
index e07edc683..2adad03e9 100644
--- a/apt-pkg/contrib/srvrec.h
+++ b/apt-pkg/contrib/srvrec.h
@@ -26,9 +26,15 @@ class SrvRec
int random_number_range_end;
int random_number_range_max;
- bool operator<(SrvRec const &other) const {
- return this->priority < other.priority;
+ bool operator<(SrvRec const &other) const {
+ return this->priority < other.priority;
}
+
+ SrvRec(std::string const Target, u_int16_t const Priority,
+ u_int16_t const Weight, u_int16_t const Port) :
+ target(Target), priority(Priority), weight(Weight), port(Port),
+ random_number_range_start(0), random_number_range_end(0),
+ random_number_range_max(0) {}
};
/** \brief Get SRV records from host/port (builds the query string internally)