MDBDbi::MDBDbi(MDB_env* env, MDB_txn* txn, const string_view dbname, int flags)
{
// A transaction that uses this function must finish (either commit or abort) before any other transaction in the process may use this function.
-
+
int rc = mdb_dbi_open(txn, dbname.empty() ? 0 : &dbname[0], flags, &d_dbi);
if(rc)
throw std::runtime_error("Unable to open named database: " + MDBError(rc));
-
+
// Database names are keys in the unnamed database, and may be read but not written.
}
weak_ptr<MDBEnv> wp;
int flags;
};
-
+
static std::map<tuple<dev_t, ino_t>, Value> s_envs;
static std::mutex mut;
-
+
struct stat statbuf;
if(stat(fname, &statbuf)) {
if(errno != ENOENT)
auto fresh = std::make_shared<MDBEnv>(fname, flags, mode, mapsizeMB);
s_envs[key] = {fresh, flags};
-
+
return fresh;
}
This function must not be called from multiple concurrent transactions in the same process. A transaction that uses this function must finish (either commit or abort) before any other transaction in the process may use this function.
*/
std::lock_guard<std::mutex> l(d_openmut);
-
+
if(!(envflags & MDB_RDONLY)) {
auto rwt = getRWTransaction();
MDBDbi ret = rwt->openDB(dbname, flags);
MDBDbi ret;
{
- auto rwt = getROTransaction();
+ auto rwt = getROTransaction();
ret = rwt->openDB(dbname, flags);
}
return ret;
{
if(env->getRWTX())
throw std::runtime_error("Duplicate RO transaction");
-
+
/*
A transaction and its cursors must only be used by a single thread, and a thread may only have a single transaction at a time. If MDB_NOTLS is in use, this does not apply to read-only transactions. */
MDB_txn *result = nullptr;
typedef uint32_t type; // dummy
};
-
/** The main class. Templatized only on the indexes and typename right now */
template<typename T, class I1=nullindex_t, class I2=nullindex_t, class I3 = nullindex_t, class I4 = nullindex_t>
class TypedDBI
#include "pdns/auth-zonecache.hh"
#include "pdns/auth-caches.hh"
-/*
+/*
All instances of this backend share one s_state, which is indexed by zone name and zone id.
The s_state is protected by a read/write lock, and the goal it to only interact with it briefly.
When a query comes in, we take a read lock and COPY the best zone to answer from s_state (BB2DomainInfo object)
#include "ldaputils.hh"
/*****************************
- *
+ *
* LdapSimpleAuthenticator
- *
+ *
****************************/
LdapSimpleAuthenticator::LdapSimpleAuthenticator(const std::string& dn, const std::string& pw, int tmout) :
}
/*****************************
- *
+ *
* LdapGssapiAuthenticator
- *
+ *
****************************/
static int ldapGssapiAuthenticatorSaslInteractCallback(LDAP* conn, unsigned flags, void* defaults, void* in)
}
/* Here's the complicated story. Other backends have just one transaction, which is either
- on or not.
-
+ on or not.
+
You can't call feedRecord without a transaction started with startTransaction.
However, other functions can be called after startTransaction() or without startTransaction()
#include "../../namespaces.hh"
#include "../../misc.hh"
-class SSqlException
+class SSqlException
{
-public:
+public:
SSqlException(const string &reason) : d_reason(reason)
{
}
-
+
string txtReason()
{
return d_reason;
private:
string d_reason;
};
-
+
class SSqlStatement
{
public:
po::variables_map g_vm;
ArgvMap& arg()
-{
+{
static ArgvMap theArg;
return theArg;
}
("stats-dir", po::value<string>()->default_value("."), "Directory where statistics will be saved")
("write-failures,w", po::value<string>()->default_value(""), "if set, write weird packets to this PCAP file")
("verbose,v", "be verbose");
-
+
hidden.add_options()
("files", po::value<vector<string> >(), "files");
- alloptions.add(desc).add(hidden);
+ alloptions.add(desc).add(hidden);
po::positional_options_description p;
p.add("files", -1);
po::store(po::command_line_parser(argc, argv).options(alloptions).positional(p).run(), g_vm);
po::notify(g_vm);
-
+
vector<string> files;
- if(g_vm.count("files"))
- files = g_vm["files"].as<vector<string> >();
+ if(g_vm.count("files"))
+ files = g_vm["files"].as<vector<string> >();
if(g_vm.count("version")) {
cerr<<"dnsscope "<<VERSION<<endl;
unsigned int reuses=0;
typedef map<uint16_t,uint32_t> rcodes_t;
rcodes_t rcodes;
-
+
time_t lowestTime=0, highestTime=0;
time_t lastsec=0;
LiveCounts lastcounts;
rdFilterMismatch++;
continue;
}
-
+
if(!filtername.empty() && !qname.isPartOf(filtername)) {
nameMismatch++;
continue;
}
-
+
if(!header.qr) {
uint16_t udpsize, z;
if(getEDNSUDPPayloadSizeAndZ((const char*)pr.d_payload, pr.d_len, &udpsize, &z)) {
}
}
- if(pr.d_ip->ip_v == 4)
+ if(pr.d_ip->ip_v == 4)
++ipv4DNSPackets;
else
++ipv6DNSPackets;
-
+
if(pr.d_pheader.ts.tv_sec != lastsec) {
LiveCounts lc;
if(lastsec) {
lc.questions = queries;
lc.answers = answers;
- lc.outstanding = liveQuestions();
+ lc.outstanding = liveQuestions();
LiveCounts diff = lc - lastcounts;
pcounts.emplace_back(pr.d_pheader.ts.tv_sec, diff);
ComboAddress rem = pr.getSource();
rem.sin4.sin_port=0;
- requestors.insert(rem);
+ requestors.insert(rem);
QuestionData& qd=statmap[qi];
-
+
if(!qd.d_firstquestiontime.tv_sec)
qd.d_firstquestiontime=pr.d_pheader.ts;
else {
rdNonRAAnswers++;
rdnonra.insert(pr.getDest());
}
-
+
if(header.ra) {
ComboAddress rem = pr.getDest();
rem.sin4.sin_port=0;
- recipients.insert(rem);
+ recipients.insert(rem);
}
QuestionData& qd=statmap[qi];
qd.d_answercount++;
if(qd.d_qcount) {
- uint32_t usecs= (pr.d_pheader.ts.tv_sec - qd.d_firstquestiontime.tv_sec) * 1000000 +
+ uint32_t usecs= (pr.d_pheader.ts.tv_sec - qd.d_firstquestiontime.tv_sec) * 1000000 +
(pr.d_pheader.ts.tv_usec - qd.d_firstquestiontime.tv_usec) ;
// cout<<"Usecs for "<<qi<<": "<<usecs<<endl;
if(!noservfailstats || header.rcode != 2)
cumul[usecs]++;
-
- if(header.rcode != 0 && header.rcode!=3)
+
+ if(header.rcode != 0 && header.rcode!=3)
errorresult++;
ComboAddress rem = pr.getDest();
rem.sin4.sin_port=0;
cout<<a.first<<": qcount="<<a.second.d_qcount<<", answercount="<<a.second.d_answercount<<endl;
}
*/
-
+
cout<<"Timespan: "<<(highestTime-lowestTime)/3600.0<<" hours"<<endl;
cout<<nonDNSIP<<" non-DNS UDP, "<<dnserrors<<" dns decoding errors, "<<parsefail<<" packets failed to parse"<<endl;
totpairs+=i->second;
tottime+=i->first*i->second;
}
-
+
typedef map<uint32_t, bool> done_t;
done_t done;
for(auto a : {50, 100, 200, 300, 400, 800, 1000, 2000, 4000, 8000, 32000, 64000, 256000, 1024000, 2048000})
}
#endif
-
+
sum=0;
double lastperc=0, perc=0;
uint64_t lastsum=0;
cout<< perc <<"% of questions answered within " << j->first << " usec (";
else
cout<< perc <<"% of questions answered within " << j->first/1000.0 << " msec (";
-
+
cout<<perc-lastperc<<"%)\n";
lastperc=sum*100.0/totpairs;
lastsum=sum;
cout<< perc <<"% of questions answered within " << j->first << " usec (";
else
cout<< perc <<"% of questions answered within " << j->first/1000.0 << " msec (";
-
+
cout<<perc-lastperc<<"%)\n";
lastperc=sum*100.0/totpairs;
lastsum=sum;
break;
}
}
-
+
cout<< (totpairs-lastsum)<<" responses ("<<((totpairs-lastsum)*100.0/answers) <<"%) older than "<< (done.rbegin()->first/1000000.0) <<" seconds"<<endl;
if(totpairs)
cout<<"Average non-late response time: "<<tottime/totpairs<<" usec"<<endl;
if(!g_vm["load-stats"].as<string>().empty()) {
ofstream load(g_vm["load-stats"].as<string>().c_str());
- if(!load)
+ if(!load)
throw runtime_error("Error writing load statistics to "+g_vm["load-stats"].as<string>());
for(pcounts_t::value_type& val : pcounts) {
- load<<val.first<<'\t'<<val.second.questions<<'\t'<<val.second.answers<<'\t'<<val.second.outstanding<<'\n';
+ load<<val.first<<'\t'<<val.second.questions<<'\t'<<val.second.answers<<'\t'<<val.second.outstanding<<'\n';
}
}
vector<ComboAddress> diff;
set_difference(requestors.begin(), requestors.end(), recipients.begin(), recipients.end(), back_inserter(diff), ComboAddress::addressOnlyLessThan());
cout<<"Saw "<<diff.size()<<" unique remotes asking questions, but not getting RA answers"<<endl;
-
+
ofstream ignored("ignored");
for(const ComboAddress& rem : diff) {
ignored<<rem.toString()<<'\n';
rrc.d_type=signQType;
rrc.d_labels=signQName.countLabels()-signQName.isWildcard();
- rrc.d_originalttl=signTTL;
+ rrc.d_originalttl=signTTL;
rrc.d_siginception=startOfWeek - 7*86400; // XXX should come from zone metadata
rrc.d_sigexpire=startOfWeek + 14*86400;
rrc.d_signer = signer;
if(getRRSIGsForRRSET(dk, signer, wildcardname.countLabels() ? wildcardname : signQName, signQType, signTTL, toSign, rrcs) < 0) {
// cerr<<"Error signing a record!"<<endl;
return;
- }
-
+ }
+
DNSZoneRecord rr;
rr.dr.d_name=signQName;
rr.dr.d_type=QType::RRSIG;
}
}
while(sname.chopOff());
-
+
return false;
}
void addRRSigs(DNSSECKeeper& dk, UeberBackend& db, const set<DNSName>& authSet, vector<DNSZoneRecord>& rrs)
{
stable_sort(rrs.begin(), rrs.end(), rrsigncomp);
-
+
DNSName signQName, wildcardQName;
uint16_t signQType=0;
uint32_t signTTL=0;
uint32_t origTTL=0;
-
+
DNSResourceRecord::Place signPlace=DNSResourceRecord::ANSWER;
sortedRecords_t toSign;
#include <limits.h>
/* d_content: <---- d_stuff ---->
- v d_truncatemarker
+ v d_truncatemarker
dnsheader | qname | qtype | qclass | {recordname| dnsrecordheader | record }
- ^ d_rollbackmarker ^ d_sor
-
+ ^ d_rollbackmarker ^ d_sor
+
*/
/* name might be a.root-servers.net, we need to be able to benefit from finding:
b.root-servers.net, or even:
- b\xc0\x0c
+ b\xc0\x0c
*/
unsigned int bestpos=0;
*matchLen=0;
cout<<"Domain "<<name<<" too large to compress"<<endl;
return 0;
}
-
+
if(l_verbose) {
cout<<"Input vector for lookup "<<name<<": ";
- for(const auto n : nvect)
+ for(const auto n : nvect)
cout << n<<" ";
cout<<endl;
cout<<makeHexDump(string(raw.c_str(), raw.c_str()+raw.size()))<<endl;
}
if(l_verbose) {
cout<<"Packet vector: "<<endl;
- for(const auto n : pvect)
+ for(const auto n : pvect)
cout << n<<" ";
cout<<endl;
}
uint16_t li=0;
uint16_t matchlen=0;
if(d_compress && compress && (li=lookupName(name, &matchlen)) && li < maxCompressionOffset) {
- const auto& dns=name.getStorage();
+ const auto& dns=name.getStorage();
if(l_verbose)
cout<<"Found a substring of "<<matchlen<<" bytes from the back, offset: "<<li<<", dnslen: "<<dns.size()<<endl;
// found a substring, if www.powerdns.com matched powerdns.com, we get back matchlen = 13
sum += i.first;
pick.emplace_back(sum, i.second);
}
-
+
if (sum == 0) {
throw std::invalid_argument("The sum of items cannot be zero");
}
-
+
int r = dns_random(sum);
auto p = upper_bound(pick.begin(), pick.end(), r, [](int rarg, const typename decltype(pick)::value_type& a) { return rarg < a.first; });
return p->second;
sum += i.first;
pick.push_back({sum, i.second});
}
-
+
if (sum == 0) {
throw std::invalid_argument("The sum of items cannot be zero");
}
}
template <typename T>
-static vector<T> pickRandomSample(int n, const vector<T>& items)
+static vector<T> pickRandomSample(int n, const vector<T>& items)
{
if (items.empty()) {
throw std::invalid_argument("The items list cannot be empty");
}
-
+
vector<T> pick;
pick.reserve(items.size());
-
+
for(auto& item : items) {
pick.push_back(item);
}
-
+
int count = std::min(std::max<size_t>(0, n), items.size());
if (count == 0) {
return vector<T>();
- }
+ }
std::shuffle(pick.begin(), pick.end(), pdns::dns_random_engine());
-
+
vector<T> result = {pick.begin(), pick.begin() + count};
return result;
}
auto labels = s_lua_record_ctx->qname.getRawLabels();
if(labels.size()<4)
return std::string("unknown");
-
+
vector<ComboAddress> candidates;
-
+
// so, query comes in for 4.3.2.1.in-addr.arpa, zone is called 2.1.in-addr.arpa
// e["1.2.3.4"]="bert.powerdns.com" then provides an exception
if(e) {
boost::format fmt(format);
fmt.exceptions( boost::io::all_error_bits ^ ( boost::io::too_many_args_bit | boost::io::too_few_args_bit ) );
fmt % labels[3] % labels[2] % labels[1] % labels[0];
-
+
fmt % (labels[3]+"-"+labels[2]+"-"+labels[1]+"-"+labels[0]);
boost::format fmt2("%02x%02x%02x%02x");
lua.writeFunction("all", [](const vector< pair<int,string> >& ips) {
vector<string> result;
result.reserve(ips.size());
-
+
for(const auto& ip : ips) {
result.emplace_back(ip.second);
}
s_lua_record_ctx->qname = query;
s_lua_record_ctx->zone = zone;
s_lua_record_ctx->zoneid = zoneid;
-
+
lua.writeVariable("qname", query);
lua.writeVariable("zone", zone);
lua.writeVariable("zoneid", zoneid);
if(bitmap.size() < 2) {
throw MOADNSException("NSEC record with impossibly small bitmap");
}
-
+
for(unsigned int n = 0; n+1 < bitmap.size();) {
uint8_t window=static_cast<uint8_t>(bitmap[n++]);
uint8_t blen=static_cast<uint8_t>(bitmap[n++]);
rtr.xfrHexBlob(d_salt);
rtr.xfrBase32HexBlob(d_nexthash);
-
+
while(!rtr.eof()) {
uint16_t type;
rtr.xfrType(type);
}
}
-void NSEC3RecordContent::toPacket(DNSPacketWriter& pw)
+void NSEC3RecordContent::toPacket(DNSPacketWriter& pw)
{
pw.xfr8BitInt(d_algorithm);
pw.xfr8BitInt(d_flags);
NSEC3PARAMRecordContent::NSEC3PARAMRecordContent(const string& content, const DNSName& zone)
{
RecordTextReader rtr(content, zone);
- rtr.xfr8BitInt(d_algorithm);
- rtr.xfr8BitInt(d_flags);
- rtr.xfr16BitInt(d_iterations);
+ rtr.xfr8BitInt(d_algorithm);
+ rtr.xfr8BitInt(d_flags);
+ rtr.xfr16BitInt(d_iterations);
rtr.xfrHexBlob(d_salt);
}
-void NSEC3PARAMRecordContent::toPacket(DNSPacketWriter& pw)
+void NSEC3PARAMRecordContent::toPacket(DNSPacketWriter& pw)
{
- pw.xfr8BitInt(d_algorithm);
- pw.xfr8BitInt(d_flags);
- pw.xfr16BitInt(d_iterations);
+ pw.xfr8BitInt(d_algorithm);
+ pw.xfr8BitInt(d_flags);
+ pw.xfr16BitInt(d_iterations);
pw.xfr8BitInt(d_salt.length());
// cerr<<"salt: '"<<makeHexDump(d_salt)<<"', "<<d_salt.length()<<endl;
pw.xfrBlob(d_salt);
std::shared_ptr<NSEC3PARAMRecordContent::DNSRecordContent> NSEC3PARAMRecordContent::make(const DNSRecord &dr, PacketReader& pr)
{
auto ret=std::make_shared<NSEC3PARAMRecordContent>();
- pr.xfr8BitInt(ret->d_algorithm);
- pr.xfr8BitInt(ret->d_flags);
- pr.xfr16BitInt(ret->d_iterations);
+ pr.xfr8BitInt(ret->d_algorithm);
+ pr.xfr8BitInt(ret->d_flags);
+ pr.xfr16BitInt(ret->d_iterations);
uint8_t len;
pr.xfr8BitInt(len);
pr.xfrHexBlob(ret->d_salt, len);
{
string ret;
RecordTextWriter rtw(ret);
- rtw.xfr8BitInt(d_algorithm);
- rtw.xfr8BitInt(d_flags);
- rtw.xfr16BitInt(d_iterations);
+ rtw.xfr8BitInt(d_algorithm);
+ rtw.xfr8BitInt(d_flags);
+ rtw.xfr16BitInt(d_iterations);
rtw.xfrHexBlob(d_salt);
return ret;
}
while (isdigit(*cp))
deg = deg * 10 + (*cp++ - '0');
-
+
while (isspace(*cp))
cp++;
-
+
if (!(isdigit(*cp)))
goto fndhemi;
-
+
while (isdigit(*cp))
min = min * 10 + (*cp++ - '0');
-
+
while (isspace(*cp))
cp++;
-
+
if (*cp && !(isdigit(*cp)))
goto fndhemi;
-
+
while (isdigit(*cp))
secs = secs * 10 + (*cp++ - '0');
}
}
}
-
+
while (*cp && !isspace(*cp)) /* if any trailing garbage */
cp++;
-
+
while (isspace(*cp))
cp++;
-
+
fndhemi:
switch (*cp) {
case 'N': case 'n':
retval = 0; /* invalid value -- indicates error */
break;
}
-
+
switch (*cp) {
case 'N': case 'n':
case 'S': case 's':
return 0;
cp++; /* skip the hemisphere */
-
+
while (*cp && !isspace(*cp)) /* if any trailing garbage */
cp++;
-
+
while (isspace(*cp)) /* move to next field */
cp++;
-
+
*latlonstrptr = cp;
-
+
return (retval);
}
pr.xfr32BitInt(ret->d_latitude);
pr.xfr32BitInt(ret->d_longitude);
pr.xfr32BitInt(ret->d_altitude);
-
+
return ret;
}
d_version = 0;
const char *cp, *maxcp;
-
+
uint32_t lltemp1 = 0, lltemp2 = 0;
int altmeters = 0, altfrac = 0, altsign = 1;
d_horizpre = 0x16; /* default = 1e6 cm = 10000.00m = 10km */
if (*cp == '+')
cp++;
-
+
while (isdigit(*cp))
altmeters = altmeters * 10 + (*cp++ - '0');
-
+
if (*cp == '.') { /* decimal meters */
cp++;
if (isdigit(*cp)) {
}
}
}
-
+
d_altitude = (10000000 + (altsign * (altmeters * 100 + altfrac)));
-
+
while (!isspace(*cp) && (cp < maxcp))
/* if trailing garbage or m */
cp++;
-
+
while (isspace(*cp) && (cp < maxcp))
cp++;
-
-
+
+
if (cp >= maxcp)
goto defaults;
-
+
d_size = precsize_aton(&cp);
-
+
while (!isspace(*cp) && (cp < maxcp))/*if trailing garbage or m*/
cp++;
-
+
while (isspace(*cp) && (cp < maxcp))
cp++;
-
+
if (cp >= maxcp)
goto defaults;
-
+
d_horizpre = precsize_aton(&cp);
-
+
while (!isspace(*cp) && (cp < maxcp))/*if trailing garbage or m*/
cp++;
-
+
while (isspace(*cp) && (cp < maxcp))
cp++;
-
+
if (cp >= maxcp)
goto defaults;
-
+
d_vertpre = precsize_aton(&cp);
-
+
defaults:
;
}
double latitude= ((int32_t)((uint32_t)d_latitude - ((uint32_t)1<<31)))/3600000.0;
double longitude=((int32_t)((uint32_t)d_longitude - ((uint32_t)1<<31)))/3600000.0;
double altitude= ((int32_t)d_altitude )/100.0 - 100000;
-
+
double size=0.01*((d_size>>4)&0xf);
int count=d_size & 0xf;
while(count--)
auto deltas = getIXFRDeltas(remote, domain, drsoa, xfrTimeout, false, tt, laddr.sin4.sin_family ? &laddr : nullptr, ((size_t) ::arg().asNum("xfr-max-received-mbytes")) * 1024 * 1024);
zs.numDeltas=deltas.size();
// cout<<"Got "<<deltas.size()<<" deltas from serial "<<di.serial<<", applying.."<<endl;
-
+
for(const auto& d : deltas) {
const auto& remove = d.first;
const auto& add = d.second;
// cout<<"Delta sizes: "<<remove.size()<<", "<<add.size()<<endl;
-
+
if(remove.empty()) { // we got passed an AXFR!
*axfr = add;
return;
}
-
+
// our hammer is 'replaceRRSet(domain_id, qname, qt, vector<DNSResourceRecord>& rrset)
// which thinks in terms of RRSETs
// however, IXFR does not, and removes and adds *records* (bummer)
// this means that we must group updates by {qname,qtype}, retrieve the RRSET, apply
- // the add/remove updates, and replaceRRSet the whole thing.
-
-
+ // the add/remove updates, and replaceRRSet the whole thing.
+
+
map<pair<DNSName,uint16_t>, pair<vector<DNSRecord>, vector<DNSRecord> > > grouped;
-
+
for(const auto& x: remove)
grouped[{x.d_name, x.d_type}].first.push_back(x);
for(const auto& x: add)
}
}
// O(N^2)!
- rrset.erase(remove_if(rrset.begin(), rrset.end(),
+ rrset.erase(remove_if(rrset.begin(), rrset.end(),
[&g](const DNSRecord& dr) {
- return count(g.second.first.cbegin(),
+ return count(g.second.first.cbegin(),
g.second.first.cend(), dr);
}), rrset.end());
// the DNSRecord== operator compares on name, type, class and lowercase content representation
auto sr = getRR<SOARecordContent>(dr);
zs.soa_serial=sr->d_st.serial;
}
-
+
replacement.push_back(rr);
}
catch(PDNSException& p) {
g_log<<Logger::Error<<logPrefix<<"got exception (PDNSException): "<<p.reason<<endl;
throw;
- }
+ }
}
-
static bool processRecordForZS(const DNSName& domain, bool& firstNSEC3, DNSResourceRecord& rr, ZoneStatus& zs)
{
switch(rr.qtype.getCode()) {
- case QType::NSEC3PARAM:
+ case QType::NSEC3PARAM:
zs.ns3pr = NSEC3PARAMRecordContent(rr.content);
zs.isDnssecZone = zs.isNSEC3 = true;
zs.isNarrow = false;
}
return false;
}
-
- case QType::NSEC:
+
+ case QType::NSEC:
zs.isDnssecZone = zs.isPresigned = true;
return false;
-
- case QType::NS:
+
+ case QType::NS:
if(rr.qname!=domain)
zs.nsset.insert(rr.qname);
break;
return true;
}
-/* So this code does a number of things.
+/* So this code does a number of things.
1) It will AXFR a domain from a master
The code can retrieve the current serial number in the database itself.
It may attempt an IXFR
}
}
return rrs;
-}
+}
void CommunicatorClass::suck(const DNSName &domain, const ComboAddress& remote, bool force)
{
auto data = d_data.lock();
if (data->d_inprogress.count(domain)) {
- return;
+ return;
}
data->d_inprogress.insert(domain);
}
d_buffer.resize(s_buflen);
if((bytes=recvfrom(d_socket, &d_buffer[0], s_buflen, 0, reinterpret_cast<sockaddr *>(&ep) , &remlen)) <0)
throw NetworkError("After recvfrom: "+stringerror());
-
+
dgram.assign(d_buffer, 0, static_cast<size_t>(bytes));
}
throw NetworkError("After send: "+stringerror());
}
-
+
/** For datagram sockets, send a datagram to a destination
\param dgram The datagram
\param ep The intended destination of the datagram */
}
- //! Write this data to the socket, taking care that all bytes are written out
+ //! Write this data to the socket, taking care that all bytes are written out
void writen(const string &data)
{
if(data.empty())
do {
res=::send(d_socket, ptr, toWrite, 0);
- if(res<0)
+ if(res<0)
throw NetworkError("Writing to a socket: "+stringerror());
if(!res)
throw NetworkError("EOF on socket");
if(errno==EAGAIN)
return 0;
-
+
throw NetworkError("Writing to a socket: "+stringerror());
}
}
}
- //! reads one character from the socket
+ //! reads one character from the socket
int getChar()
{
char c;
{
d_buffer.resize(s_buflen);
ssize_t res=::recv(d_socket, &d_buffer[0], s_buflen, 0);
- if(res<0)
+ if(res<0)
throw NetworkError("Reading from a socket: "+stringerror());
data.assign(d_buffer, 0, static_cast<size_t>(res));
}
size_t read(char *buffer, size_t bytes)
{
ssize_t res=::recv(d_socket, buffer, bytes, 0);
- if(res<0)
+ if(res<0)
throw NetworkError("Reading from a socket: "+stringerror());
return static_cast<size_t>(res);
}
return read(buffer, n);
}
- //! Sets the socket to listen with a default listen backlog of 10 pending connections
+ //! Sets the socket to listen with a default listen backlog of 10 pending connections
void listen(unsigned int length=10)
{
if(::listen(d_socket,length)<0)
int n;
for(n=0; n < 100; ++n) {
Question q;
- q.d_dt.set();
+ q.d_dt.set();
d->question(q, report);
}
sleep(1);
// bound should be higher than max-queue-length
for(n=0; n < 2000; ++n) {
Question q;
- q.d_dt.set();
+ q.d_dt.set();
d->question(q, report1);
}
}, DistributorFatal, [](DistributorFatal) { return true; });
try {
for(int n=0; n < 100; ++n) {
Question q;
- q.d_dt.set();
+ q.d_dt.set();
q.qdomain=DNSName(std::to_string(n));
q.qtype = QType(QType::A);
d->question(q, report2);
ts.tv_sec = usec / 1000000;
ts.tv_nsec = (usec % 1000000) * 1000;
// POSIX.1 recommends using nanosleep instead of usleep
- ::nanosleep(&ts, nullptr);
+ ::nanosleep(&ts, nullptr);
}
return (!(year%4) && ((year%100) || !(year%400)));
}
-time_t Utility::timegm(struct tm *const t)
+time_t Utility::timegm(struct tm *const t)
{
const static short spm[13] = /* days per month -- nonleap! */
{ 0,
if (t->tm_min>60) { t->tm_hour += t->tm_min/60; t->tm_min%=60; }
if (t->tm_hour>60) { t->tm_mday += t->tm_hour/60; t->tm_hour%=60; }
if (t->tm_mon>11) { t->tm_year += t->tm_mon/12; t->tm_mon%=12; }
-
+
while (t->tm_mday>spm[1+t->tm_mon]) {
if (t->tm_mon==1 && isleap(t->tm_year+1900)) {
if (t->tm_mon==31+29) break;
i = 60;
return ((day + t->tm_hour) * i + t->tm_min) * i + t->tm_sec;
}
-