]> granicus.if.org Git - pdns/commitdiff
Allow multiple simulaneous incoming TCP queries over a connection.
authorOtto Moerbeek <otto.moerbeek@open-xchange.com>
Wed, 18 Sep 2019 10:01:01 +0000 (12:01 +0200)
committerOtto Moerbeek <otto.moerbeek@open-xchange.com>
Tue, 8 Oct 2019 14:15:29 +0000 (16:15 +0200)
Answers are sent out the moment the become available, so not
necesarily in the same order as received. There's a limit on how
many queries per TCP induced connection we may have in flight.

pdns/pdns_recursor.cc
pdns/sdig.cc
pdns/syncres.hh

index 3637d11ae707b4081f329d12d4b294195d77f93f..e5a781134114efa8c49b8b6bae68a728e6059542 100644 (file)
@@ -746,7 +746,7 @@ static void writePid(void)
   }
 }
 
-TCPConnection::TCPConnection(int fd, const ComboAddress& addr) : data(2, 0), d_remote(addr), d_fd(fd)
+TCPConnection::TCPConnection(int fd, const ComboAddress& addr) : data(2, 0), d_remote(addr), d_requestsInFlight(0), d_fd(fd)
 {
   ++s_currentConnections;
   (*t_tcpClientCounts)[d_remote]++;
@@ -767,6 +767,8 @@ TCPConnection::~TCPConnection()
   --s_currentConnections;
 }
 
+int TCPConnection::s_maxInFlight = 10;
+
 AtomicCounter TCPConnection::s_currentConnections;
 
 static void handleRunningTCPQuestion(int fd, FDMultiplexer::funcparam_t& var);
@@ -1760,12 +1762,16 @@ static void startDoResolve(void *p)
           dc->d_socket = -1;
         }
         else {
-          dc->d_tcpConnection->state=TCPConnection::BYTE0;
           Utility::gettimeofday(&g_now, 0); // needs to be updated
           struct timeval ttd = g_now;
-          ttd.tv_sec += g_tcpTimeout;
-
-          t_fdm->addReadFD(dc->d_socket, handleRunningTCPQuestion, dc->d_tcpConnection, &ttd);
+          dc->d_tcpConnection->d_requestsInFlight--;
+          if (dc->d_tcpConnection->d_requestsInFlight == TCPConnection::s_maxInFlight - 1) {
+            //cerr << "Reenabling... " << dc->d_tcpConnection->d_requestsInFlight << ' ' << dc->d_socket << endl;
+            ttd.tv_sec += g_tcpTimeout;
+            t_fdm->addReadFD(dc->d_socket, handleRunningTCPQuestion, dc->d_tcpConnection, &ttd);
+          } else {
+            t_fdm->setReadTTD(dc->d_socket, ttd,  g_tcpTimeout);
+          }
         }
       }
     }
@@ -2002,7 +2008,11 @@ static void handleRunningTCPQuestion(int fd, FDMultiplexer::funcparam_t& var)
     }
     conn->bytesread+=(uint16_t)bytes;
     if(conn->bytesread==conn->qlen) {
-      t_fdm->removeReadFD(fd); // should no longer awake ourselves when there is data to read
+      conn->d_requestsInFlight++;
+      if (conn->d_requestsInFlight >= TCPConnection::s_maxInFlight) {
+        //cerr << "Disabling... " << conn->d_requestsInFlight << ' ' << fd << endl;
+        t_fdm->removeReadFD(fd); // should no longer awake ourselves when there is data to read
+      }
 
       std::unique_ptr<DNSComboWriter> dc;
       try {
@@ -2137,7 +2147,8 @@ static void handleRunningTCPQuestion(int fd, FDMultiplexer::funcparam_t& var)
       else {
         ++g_stats.qcounter;
         ++g_stats.tcpqcounter;
-        MT->makeThread(startDoResolve, dc.release()); // deletes dc, will set state to BYTE0 again
+        MT->makeThread(startDoResolve, dc.release()); // deletes dc
+        conn->state = TCPConnection::BYTE0;
         return;
       }
     }
index a7e41de8efe5a190d9481721387aef29785f19a4..fc0d36074d7fcb850a9aced45dbbf9e6175407ab 100644 (file)
@@ -2,14 +2,14 @@
 #include "config.h"
 #endif
 #include "dnsparser.hh"
+#include "dnsrecords.hh"
+#include "dnswriter.hh"
 #include "ednsoptions.hh"
-#include "sstuff.hh"
+#include "ednssubnet.hh"
 #include "misc.hh"
-#include "dnswriter.hh"
-#include "dnsrecords.hh"
+#include "sstuff.hh"
 #include "statbag.hh"
 #include <boost/array.hpp>
-#include "ednssubnet.hh"
 
 #ifdef HAVE_LIBCURL
 #include "minicurl.hh"
 
 StatBag S;
 
-bool hidettl=false;
+bool hidettl = false;
 
 string ttl(uint32_t ttl)
 {
-  if(hidettl)
+  if (hidettl)
     return "[ttl]";
   else
     return std::to_string(ttl);
 }
 
-void usage() {
-  cerr<<"sdig"<<endl;
-  cerr<<"Syntax: sdig IP-ADDRESS-OR-DOH-URL PORT QUESTION QUESTION-TYPE [dnssec] [ednssubnet SUBNET/MASK] [hidesoadetails] [hidettl] [recurse] [showflags] [tcp] [xpf XPFDATA]"<<endl;
+void usage()
+{
+  cerr << "sdig" << endl;
+  cerr << "Syntax: sdig IP-ADDRESS-OR-DOH-URL PORT QUESTION QUESTION-TYPE "
+          "[dnssec] [ednssubnet SUBNET/MASK] [hidesoadetails] [hidettl] "
+          "[recurse] [showflags] [tcp] [xpf XPFDATA]"
+       << endl;
 }
 
 const string nameForClass(uint16_t qclass, uint16_t qtype)
 {
-  if (qtype == QType::OPT) return "IN";
+  if (qtype == QType::OPT)
+    return "IN";
 
-  switch(qclass) {
-    case QClass::IN:    return "IN";
-    case QClass::CHAOS: return "CHAOS";
-    case QClass::NONE:  return "NONE";
-    case QClass::ANY:   return "ANY";
-    default:            return string("CLASS")+std::to_string(qclass);
+  switch (qclass) {
+  case QClass::IN:
+    return "IN";
+  case QClass::CHAOS:
+    return "CHAOS";
+  case QClass::NONE:
+    return "NONE";
+  case QClass::ANY:
+    return "ANY";
+  default:
+    return string("CLASS") + std::to_string(qclass);
   }
 }
 
-int main(int argc, char** argv)
-try
+void fillPacket(vector<uint8_t>& packet, const string& q, const string& t,
+  bool dnssec, const boost::optional<Netmask> ednsnm,
+  bool recurse, uint16_t xpfcode, uint16_t xpfversion,
+  uint64_t xpfproto, char* xpfsrc, char* xpfdst)
+{
+  DNSPacketWriter pw(packet, DNSName(q), DNSRecordContent::TypeToNumber(t));
+
+  if (dnssec || ednsnm || getenv("SDIGBUFSIZE")) {
+    char* sbuf = getenv("SDIGBUFSIZE");
+    int bufsize;
+    if (sbuf)
+      bufsize = atoi(sbuf);
+    else
+      bufsize = 2800;
+    DNSPacketWriter::optvect_t opts;
+    if (ednsnm) {
+      EDNSSubnetOpts eo;
+      eo.source = *ednsnm;
+      opts.push_back(
+        make_pair(EDNSOptionCode::ECS, makeEDNSSubnetOptsString(eo)));
+    }
+
+    pw.addOpt(bufsize, 0, dnssec ? EDNSOpts::DNSSECOK : 0, opts);
+    pw.commit();
+  }
+
+  if (xpfcode) {
+    ComboAddress src(xpfsrc), dst(xpfdst);
+    pw.startRecord(DNSName("."), xpfcode, 0, 1, DNSResourceRecord::ADDITIONAL);
+    // xpf->toPacket(pw);
+    pw.xfr8BitInt(xpfversion);
+    pw.xfr8BitInt(xpfproto);
+    pw.xfrCAWithoutPort(xpfversion, src);
+    pw.xfrCAWithoutPort(xpfversion, dst);
+    pw.xfrCAPort(src);
+    pw.xfrCAPort(dst);
+    pw.commit();
+  }
+
+  if (recurse) {
+    pw.getHeader()->rd = true;
+  }
+}
+
+void printReply(const string& reply, bool showflags, bool hidesoadetails)
 {
-  bool dnssec=false;
-  bool recurse=false;
-  bool tcp=false;
-  bool showflags=false;
-  bool hidesoadetails=false;
-  bool doh=false;
+  MOADNSParser mdp(false, reply);
+  cout << "Reply to question for qname='" << mdp.d_qname.toString()
+       << "', qtype=" << DNSRecordContent::NumberToType(mdp.d_qtype) << endl;
+  cout << "Rcode: " << mdp.d_header.rcode << " ("
+       << RCode::to_s(mdp.d_header.rcode) << "), RD: " << mdp.d_header.rd
+       << ", QR: " << mdp.d_header.qr;
+  cout << ", TC: " << mdp.d_header.tc << ", AA: " << mdp.d_header.aa
+       << ", opcode: " << mdp.d_header.opcode << endl;
+
+  for (MOADNSParser::answers_t::const_iterator i = mdp.d_answers.begin();
+       i != mdp.d_answers.end(); ++i) {
+    cout << i->first.d_place - 1 << "\t" << i->first.d_name.toString() << "\t"
+         << nameForClass(i->first.d_class, i->first.d_type) << "\t"
+         << DNSRecordContent::NumberToType(i->first.d_type);
+    if (i->first.d_class == QClass::IN) {
+      if (i->first.d_type == QType::RRSIG) {
+        string zoneRep = i->first.d_content->getZoneRepresentation();
+        vector<string> parts;
+        stringtok(parts, zoneRep);
+        cout << "\t" << ttl(i->first.d_ttl) << "\t" << parts[0] << " "
+             << parts[1] << " " << parts[2] << " " << parts[3]
+             << " [expiry] [inception] [keytag] " << parts[7] << " ...\n";
+        continue;
+      }
+      if (!showflags && i->first.d_type == QType::NSEC3) {
+        string zoneRep = i->first.d_content->getZoneRepresentation();
+        vector<string> parts;
+        stringtok(parts, zoneRep);
+        cout << "\t" << ttl(i->first.d_ttl) << "\t" << parts[0] << " [flags] "
+             << parts[2] << " " << parts[3] << " " << parts[4];
+        for (vector<string>::iterator iter = parts.begin() + 5;
+             iter != parts.end(); ++iter)
+          cout << " " << *iter;
+        cout << "\n";
+        continue;
+      }
+      if (i->first.d_type == QType::DNSKEY) {
+        string zoneRep = i->first.d_content->getZoneRepresentation();
+        vector<string> parts;
+        stringtok(parts, zoneRep);
+        cout << "\t" << ttl(i->first.d_ttl) << "\t" << parts[0] << " "
+             << parts[1] << " " << parts[2] << " ...\n";
+        continue;
+      }
+      if (i->first.d_type == QType::SOA && hidesoadetails) {
+        string zoneRep = i->first.d_content->getZoneRepresentation();
+        vector<string> parts;
+        stringtok(parts, zoneRep);
+        cout << "\t" << ttl(i->first.d_ttl) << "\t" << parts[0] << " "
+             << parts[1] << " [serial] " << parts[3] << " " << parts[4] << " "
+             << parts[5] << " " << parts[6] << "\n";
+        continue;
+      }
+    }
+    cout << "\t" << ttl(i->first.d_ttl) << "\t"
+         << i->first.d_content->getZoneRepresentation() << "\n";
+  }
+
+  EDNSOpts edo;
+  if (getEDNSOpts(mdp, &edo)) {
+    //    cerr<<"Have "<<edo.d_options.size()<<" options!"<<endl;
+    for (vector<pair<uint16_t, string>>::const_iterator iter = edo.d_options.begin();
+         iter != edo.d_options.end(); ++iter) {
+      if (iter->first == EDNSOptionCode::ECS) { // 'EDNS subnet'
+        EDNSSubnetOpts reso;
+        if (getEDNSSubnetOptsFromString(iter->second, &reso)) {
+          cerr << "EDNS Subnet response: " << reso.source.toString()
+               << ", scope: " << reso.scope.toString()
+               << ", family = " << reso.scope.getNetwork().sin4.sin_family
+               << endl;
+        }
+      } else if (iter->first == EDNSOptionCode::PADDING) {
+        cerr << "EDNS Padding size: " << (iter->second.size()) << endl;
+      } else {
+        cerr << "Have unknown option " << (int)iter->first << endl;
+      }
+    }
+  }
+}
+
+int main(int argc, char** argv)
+try {
+  bool dnssec = false;
+  bool recurse = false;
+  bool tcp = false;
+  bool showflags = false;
+  bool hidesoadetails = false;
+  bool doh = false;
   boost::optional<Netmask> ednsnm;
   uint16_t xpfcode = 0, xpfversion = 0, xpfproto = 0;
   char *xpfsrc = NULL, *xpfdst = NULL;
 
-  for(int i=1; i<argc; i++) {
-    if ((string) argv[i] == "--help") {
+  for (int i = 1; i < argc; i++) {
+    if ((string)argv[i] == "--help") {
       usage();
       exit(EXIT_SUCCESS);
     }
 
-    if ((string) argv[i] == "--version") {
-      cerr<<"sdig "<<VERSION<<endl;
+    if ((string)argv[i] == "--version") {
+      cerr << "sdig " << VERSION << endl;
       exit(EXIT_SUCCESS);
     }
   }
 
-  if(argc < 5) {
+  if (argc < 5) {
     usage();
     exit(EXIT_FAILURE);
   }
@@ -78,29 +213,29 @@ try
   reportAllTypes();
 
   if (argc > 5) {
-    for(int i=5; i<argc; i++) {
+    for (int i = 5; i < argc; i++) {
       if (strcmp(argv[i], "dnssec") == 0)
-        dnssec=true;
+        dnssec = true;
       if (strcmp(argv[i], "recurse") == 0)
-        recurse=true;
+        recurse = true;
       if (strcmp(argv[i], "showflags") == 0)
-        showflags=true;
+        showflags = true;
       if (strcmp(argv[i], "hidesoadetails") == 0)
-        hidesoadetails=true;
+        hidesoadetails = true;
       if (strcmp(argv[i], "hidettl") == 0)
-        hidettl=true;
+        hidettl = true;
       if (strcmp(argv[i], "tcp") == 0)
-        tcp=true;
+        tcp = true;
       if (strcmp(argv[i], "ednssubnet") == 0) {
-        if(argc < i+2) {
-          cerr<<"ednssubnet needs an argument"<<endl;
+        if (argc < i + 2) {
+          cerr << "ednssubnet needs an argument" << endl;
           exit(EXIT_FAILURE);
         }
-        ednsnm=Netmask(argv[++i]);
+        ednsnm = Netmask(argv[++i]);
       }
       if (strcmp(argv[i], "xpf") == 0) {
-        if(argc < i+6) {
-          cerr<<"xpf needs five arguments"<<endl;
+        if (argc < i + 6) {
+          cerr << "xpf needs five arguments" << endl;
           exit(EXIT_FAILURE);
         }
         xpfcode = atoi(argv[++i]);
@@ -112,181 +247,100 @@ try
     }
   }
 
-  vector<uint8_t> packet;
-  
-  DNSPacketWriter pw(packet, DNSName(argv[3]), DNSRecordContent::TypeToNumber(argv[4]));
-
-  if(dnssec || ednsnm || getenv("SDIGBUFSIZE"))
-  {
-    char *sbuf=getenv("SDIGBUFSIZE");
-    int bufsize;
-    if(sbuf)
-      bufsize=atoi(sbuf);
-    else
-      bufsize=2800;
-    DNSPacketWriter::optvect_t opts;
-    if(ednsnm) {
-      EDNSSubnetOpts eo;
-      eo.source = *ednsnm;
-      opts.push_back(make_pair(EDNSOptionCode::ECS, makeEDNSSubnetOptsString(eo)));
-    }
-
-    pw.addOpt(bufsize, 0, dnssec ? EDNSOpts::DNSSECOK : 0, opts);
-    pw.commit();
-  }
-
-  if(xpfcode)
-  {
-    ComboAddress src(xpfsrc), dst(xpfdst);
-    pw.startRecord(DNSName("."), xpfcode, 0, 1, DNSResourceRecord::ADDITIONAL);
-    // xpf->toPacket(pw);
-    pw.xfr8BitInt(xpfversion);
-    pw.xfr8BitInt(xpfproto);
-    pw.xfrCAWithoutPort(xpfversion, src);
-    pw.xfrCAWithoutPort(xpfversion, dst);
-    pw.xfrCAPort(src);
-    pw.xfrCAPort(dst);
-    pw.commit();
-  }
-
-  if(recurse)
-  {
-    pw.getHeader()->rd=true;
-  }
-
   string reply;
-  string question(packet.begin(), packet.end());
   ComboAddress dest;
-  if(*argv[1]=='h') {
+  if (*argv[1] == 'h') {
     doh = true;
+  } else {
+    dest = ComboAddress(argv[1] + (*argv[1] == '@'), atoi(argv[2]));
   }
-  else {
-    dest = ComboAddress(argv[1] + (*argv[1]=='@'), atoi(argv[2]));
+
+  string name = string(argv[3]);
+  string type = string(argv[4]);
+
+  vector<pair<string, string>> questions;
+  if (name == "-" && type == "-") {
+    if (!tcp) {
+      throw PDNSException("multi-query from stdin only supported for tcp");
+    }
+    string line;
+    while (getline(std::cin, line)) {
+      auto fields = splitField(line, ' ');
+
+      questions.push_back(make_pair(fields.first, fields.second));
+    }
+  } else {
+    questions.push_back(make_pair(name, type));
   }
 
-  if(doh) {
+  if (doh) {
 #ifdef HAVE_LIBCURL
+    vector<uint8_t> packet;
+    fillPacket(packet, name, type, dnssec, ednsnm, recurse, xpfcode, xpfversion,
+      xpfproto, xpfsrc, xpfdst);
     MiniCurl mc;
     MiniCurl::MiniCurlHeaders mch;
     mch.insert(std::make_pair("Content-Type", "application/dns-message"));
     mch.insert(std::make_pair("Accept", "application/dns-message"));
+    string question(packet.begin(), packet.end());
     reply = mc.postURL(argv[1], question, mch);
+    printReply(reply, showflags, hidesoadetails);
 #else
     throw PDNSException("please link sdig against libcurl for DoH support");
 #endif
-  }
-  else if(tcp) {
+  } else if (tcp) {
     Socket sock(dest.sin4.sin_family, SOCK_STREAM);
     sock.connect(dest);
-    uint16_t len;
-    len = htons(packet.size());
-    if(sock.write((char *) &len, 2) != 2)
-      throw PDNSException("tcp write failed");
-
-    sock.writen(question);
-    
-    if(sock.read((char *) &len, 2) != 2)
-      throw PDNSException("tcp read failed");
+    for (const auto& it : questions) {
+      vector<uint8_t> packet;
+      fillPacket(packet, it.first, it.second, dnssec, ednsnm, recurse, xpfcode,
+        xpfversion, xpfproto, xpfsrc, xpfdst);
 
-    len=ntohs(len);
-    std::unique_ptr<char[]> creply(new char[len]);
-    int n=0;
-    int numread;
-    while(n<len) {
-      numread=sock.read(creply.get()+n, len-n);
-      if(numread<0)
-        throw PDNSException("tcp read failed");
-      n+=numread;
+      uint16_t len = htons(packet.size());
+      if (sock.write((const char *)&len, 2) != 2)
+        throw PDNSException("tcp write failed");
+      string question(packet.begin(), packet.end());
+      sock.writen(question);
     }
+    for (const auto& it : questions) {
+      uint16_t len;
+      if (sock.read((char *)&len, 2) != 2)
+        throw PDNSException("tcp read failed");
 
-    reply=string(creply.get(), len);
-  }
-  else //udp
+      len = ntohs(len);
+      char* creply = new char[len];
+      int n = 0;
+      int numread;
+      while (n < len) {
+        numread = sock.read(creply + n, len - n);
+        if (numread < 0)
+          throw PDNSException("tcp read failed");
+        n += numread;
+      }
+
+      reply = string(creply, len);
+      delete[] creply;
+      printReply(reply, showflags, hidesoadetails);
+    }
+  } else // udp
   {
+    vector<uint8_t> packet;
+    fillPacket(packet, name, type, dnssec, ednsnm, recurse, xpfcode, xpfversion,
+      xpfproto, xpfsrc, xpfdst);
+    string question(packet.begin(), packet.end());
     Socket sock(dest.sin4.sin_family, SOCK_DGRAM);
     sock.sendTo(question, dest);
-    int result=waitForData(sock.getHandle(), 10);
-    if(result < 0) 
-      throw std::runtime_error("Error waiting for data: "+stringerror());
-    if(!result)
+    int result = waitForData(sock.getHandle(), 10);
+    if (result < 0)
+      throw std::runtime_error("Error waiting for data: " + stringerror());
+    if (!result)
       throw std::runtime_error("Timeout waiting for data");
     sock.recvFrom(reply, dest);
+    printReply(reply, showflags, hidesoadetails);
   }
-  MOADNSParser mdp(false, reply);
-  cout<<"Reply to question for qname='"<<mdp.d_qname.toString()<<"', qtype="<<DNSRecordContent::NumberToType(mdp.d_qtype)<<endl;
-  cout<<"Rcode: "<<mdp.d_header.rcode<<" ("<<RCode::to_s(mdp.d_header.rcode)<<"), RD: "<<mdp.d_header.rd<<", QR: "<<mdp.d_header.qr;
-  cout<<", TC: "<<mdp.d_header.tc<<", AA: "<<mdp.d_header.aa<<", opcode: "<<mdp.d_header.opcode<<endl;
 
-  for(MOADNSParser::answers_t::const_iterator i=mdp.d_answers.begin(); i!=mdp.d_answers.end(); ++i) {          
-    cout<<i->first.d_place-1<<"\t"<<i->first.d_name.toString()<<"\t"<<nameForClass(i->first.d_class, i->first.d_type)<<"\t"<<DNSRecordContent::NumberToType(i->first.d_type);
-    if(i->first.d_class == QClass::IN)
-    {
-      if(i->first.d_type == QType::RRSIG) 
-      {
-        string zoneRep = i->first.d_content->getZoneRepresentation();
-        vector<string> parts;
-        stringtok(parts, zoneRep);
-        cout<<"\t"<<ttl(i->first.d_ttl)<<"\t"<< parts[0]<<" "<<parts[1]<<" "<<parts[2]<<" "<<parts[3]<<" [expiry] [inception] [keytag] "<<parts[7]<<" ...\n";
-        continue;
-      }
-      if(!showflags && i->first.d_type == QType::NSEC3)
-      {
-        string zoneRep = i->first.d_content->getZoneRepresentation();
-        vector<string> parts;
-        stringtok(parts, zoneRep);
-        cout<<"\t"<<ttl(i->first.d_ttl)<<"\t"<< parts[0]<<" [flags] "<<parts[2]<<" "<<parts[3]<<" "<<parts[4];
-        for(vector<string>::iterator iter = parts.begin()+5; iter != parts.end(); ++iter)
-          cout<<" "<<*iter;
-        cout<<"\n";
-        continue;
-      }
-      if(i->first.d_type == QType::DNSKEY)
-      {
-        string zoneRep = i->first.d_content->getZoneRepresentation();
-        vector<string> parts;
-        stringtok(parts, zoneRep);
-        cout<<"\t"<<ttl(i->first.d_ttl)<<"\t"<< parts[0]<<" "<<parts[1]<<" "<<parts[2]<<" ...\n";
-        continue;
-      }
-      if (i->first.d_type == QType::SOA && hidesoadetails)
-      {
-        string zoneRep = i->first.d_content->getZoneRepresentation();
-        vector<string> parts;
-        stringtok(parts, zoneRep);
-        cout<<"\t"<<ttl(i->first.d_ttl)<<"\t"<<parts[0]<<" "<<parts[1]<<" [serial] "<<parts[3]<<" "<<parts[4]<<" "<<parts[5]<<" "<<parts[6]<<"\n";
-        continue;
-      }
-    }
-    cout<<"\t"<<ttl(i->first.d_ttl)<<"\t"<< i->first.d_content->getZoneRepresentation()<<"\n";
-  }
-
-  EDNSOpts edo;
-  if(getEDNSOpts(mdp, &edo)) {
-//    cerr<<"Have "<<edo.d_options.size()<<" options!"<<endl;
-    for(vector<pair<uint16_t, string> >::const_iterator iter = edo.d_options.begin();
-        iter != edo.d_options.end(); 
-        ++iter) {
-      if(iter->first == EDNSOptionCode::ECS) {// 'EDNS subnet'
-       EDNSSubnetOpts reso;
-        if(getEDNSSubnetOptsFromString(iter->second, &reso)) {
-          cerr<<"EDNS Subnet response: "<<reso.source.toString()<<", scope: "<<reso.scope.toString()<<", family = "<<reso.scope.getNetwork().sin4.sin_family<<endl;
-       }
-      }
-      else if(iter->first == EDNSOptionCode::PADDING) {
-        cerr<<"EDNS Padding size: "<<(iter->second.size())<<endl;
-      }
-      else {
-        cerr<<"Have unknown option "<<(int)iter->first<<endl;
-      }
-    }
-
-  }
-}
-catch(std::exception &e)
-{
-  cerr<<"Fatal: "<<e.what()<<endl;
-}
-catch(PDNSException &e)
-{
-  cerr<<"Fatal: "<<e.reason<<endl;
+} catch (std::exception& e) {
+  cerr << "Fatal: " << e.what() << endl;
+} catch (PDNSException& e) {
+  cerr << "Fatal: " << e.reason << endl;
 }
index 728a067bb43e250fc86076ddbd3b90a779b813a7..c4e0a605d0e5db045751901b9c226a3c5b26c3ba 100644 (file)
@@ -1012,8 +1012,10 @@ public:
   enum stateenum {BYTE0, BYTE1, GETQUESTION, DONE} state{BYTE0};
   uint16_t qlen{0};
   uint16_t bytesread{0};
-
+  std::atomic<int> d_requestsInFlight;
   static unsigned int getCurrentConnections() { return s_currentConnections; }
+  // The max number of concurent TCP queries we're willing to process
+  static int s_maxInFlight;
 private:
   const int d_fd;
   static AtomicCounter s_currentConnections; //!< total number of current TCP connections