summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apt-pkg/contrib/srvrec.cc32
-rw-r--r--apt-pkg/contrib/srvrec.h10
-rw-r--r--cmdline/apt-helper.cc30
-rw-r--r--test/libapt/srvrecs_test.cc24
4 files changed, 50 insertions, 46 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)
diff --git a/cmdline/apt-helper.cc b/cmdline/apt-helper.cc
index 3c49bf149..2d24a8aee 100644
--- a/cmdline/apt-helper.cc
+++ b/cmdline/apt-helper.cc
@@ -82,25 +82,27 @@ static bool DoDownloadFile(CommandLine &CmdL)
static bool DoSrvLookup(CommandLine &CmdL)
{
if (CmdL.FileSize() < 1)
- return _error->Error(_("Must specifc at least one srv record"));
+ return _error->Error("Must specify at least one SRV record");
- std::vector<SrvRec> srv_records;
- c1out << "# target priority weight port" << std::endl;
- for(int i=1; CmdL.FileList[i] != NULL; i++)
+ for(size_t i = 1; CmdL.FileList[i] != NULL; ++i)
{
- if(GetSrvRecords(CmdL.FileList[i], srv_records) == false)
- _error->Warning(_("GetSrvRec failed for %s"), CmdL.FileList[i]);
- for (std::vector<SrvRec>::const_iterator I = srv_records.begin();
- I != srv_records.end(); ++I)
+ std::vector<SrvRec> srv_records;
+ std::string const name = CmdL.FileList[i];
+ c0out << "# Target\tPriority\tWeight\tPort # for " << name << std::endl;
+ size_t const found = name.find(":");
+ if (found != std::string::npos)
{
- c1out << (*I).target.c_str() << " "
- << (*I).priority << " "
- << (*I).weight << " "
- << (*I).port << " "
- << std::endl;
+ std::string const host = name.substr(0, found);
+ size_t const port = atoi(name.c_str() + found + 1);
+ if(GetSrvRecords(host, port, srv_records) == false)
+ _error->Warning(_("GetSrvRec failed for %s"), name.c_str());
}
- }
+ else if(GetSrvRecords(name, srv_records) == false)
+ _error->Warning(_("GetSrvRec failed for %s"), name.c_str());
+ for (SrvRec const &I : srv_records)
+ c1out << I.target << "\t" << I.priority << "\t" << I.weight << "\t" << I.port << std::endl;
+ }
return true;
}
diff --git a/test/libapt/srvrecs_test.cc b/test/libapt/srvrecs_test.cc
index 7e43cc757..4b63d2ccd 100644
--- a/test/libapt/srvrecs_test.cc
+++ b/test/libapt/srvrecs_test.cc
@@ -12,20 +12,28 @@ TEST(SrvRecTest, PopFromSrvRecs)
// the PopFromSrvRecs() is using a random number so we must
// run it a bunch of times to ensure we are not fooled by randomness
std::set<std::string> selected;
- for(int i=0;i<100;i++)
+ for(size_t i = 0; i < 100; ++i)
{
std::vector<SrvRec> Meep;
- SrvRec foo = {target:"foo", priority: 20, weight: 0, port: 80};
- Meep.push_back(foo);
-
- SrvRec bar = {target:"bar", priority: 20, weight: 0, port: 80};
- Meep.push_back(bar);
+ Meep.emplace_back("foo", 20, 0, 80);
+ Meep.emplace_back("bar", 20, 0, 80);
+ Meep.emplace_back("baz", 30, 0, 80);
- EXPECT_EQ(Meep.size(), 2);
- SrvRec result = PopFromSrvRecs(Meep);
+ EXPECT_EQ(Meep.size(), 3);
+ SrvRec const result = PopFromSrvRecs(Meep);
selected.insert(result.target);
// ensure that pop removed one element
+ EXPECT_EQ(Meep.size(), 2);
+ EXPECT_NE(result.target, "baz");
+
+ SrvRec const result2 = PopFromSrvRecs(Meep);
+ EXPECT_NE(result.target, result2.target);
+ EXPECT_NE(result2.target, "baz");
EXPECT_EQ(Meep.size(), 1);
+
+ SrvRec const result3 = PopFromSrvRecs(Meep);
+ EXPECT_EQ(result3.target, "baz");
+ EXPECT_TRUE(Meep.empty());
}
// ensure that after enough runs we end up with both selected