]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
Merge pull request #3767 from ahupowerdns/dnsdist-yaks
authorbert hubert <bert.hubert@netherlabs.nl>
Wed, 27 Apr 2016 14:13:28 +0000 (16:13 +0200)
committerbert hubert <bert.hubert@netherlabs.nl>
Wed, 27 Apr 2016 14:13:28 +0000 (16:13 +0200)
Please ponder: nodelay, console newlines, print out json, silence some trivia, move to 'return' for Lua statements

1  2 
pdns/dnsdist-console.cc
pdns/dnsdist-lua2.cc
pdns/misc.cc
pdns/misc.hh

diff --combined pdns/dnsdist-console.cc
index 1701634474c93d7ede06fa2f218e7885f6a8d400,5c3523805b8648f907c61041c1463a7a01a3f30b..4e49ae3c3fe31d9a5922412855724eb323033135
@@@ -3,6 -3,7 +3,7 @@@
  #include <readline.h>
  #include <fstream>
  #include "dolog.hh"
+ #include "ext/json11/json11.hpp"
  
  vector<pair<struct timeval, string> > g_confDelta;
  
@@@ -18,14 -19,15 +19,15 @@@ void feedConfigDelta(const std::string
  
  void doClient(ComboAddress server, const std::string& command)
  {
-   cout<<"Connecting to "<<server.toStringWithPort()<<endl;
+   if(g_verbose)
+     cout<<"Connecting to "<<server.toStringWithPort()<<endl;
    int fd=socket(server.sin4.sin_family, SOCK_STREAM, 0);
    if (fd < 0) {
      cerr<<"Unable to connect to "<<server.toStringWithPort()<<endl;
      return;
    }
    SConnect(fd, server);
+   setTCPNoDelay(fd);
    SodiumNonce theirs, ours;
    ours.init();
  
@@@ -34,7 -36,7 +36,7 @@@
  
    if(!command.empty()) {
      string msg=sodEncryptSym(command, g_key, ours);
 -    putMsgLen32(fd, msg.length());
 +    putMsgLen32(fd, (uint32_t) msg.length());
      if(!msg.empty())
        writen2(fd, msg);
      uint32_t len;
@@@ -44,7 -46,7 +46,7 @@@
          readn2(fd, resp.get(), len);
          msg.assign(resp.get(), len);
          msg=sodDecryptSym(msg, g_key, theirs);
-         cout<<msg<<endl;
+         cout<<msg;
        }
      }
      else {
@@@ -86,7 -88,7 +88,7 @@@
        continue;
  
      string msg=sodEncryptSym(line, g_key, ours);
 -    putMsgLen32(fd, msg.length());
 +    putMsgLen32(fd, (uint32_t) msg.length());
      writen2(fd, msg);
      uint32_t len;
      if(!getMsgLen32(fd, &len)) {
        readn2(fd, resp.get(), len);
        msg.assign(resp.get(), len);
        msg=sodDecryptSym(msg, g_key, theirs);
-       cout<<msg<<endl;
+       cout<<msg;
+       cout.flush();
      }
      else {
        cout<<endl;
@@@ -139,30 -142,54 +142,54 @@@ void doConsole(
  
      string response;
      try {
-       std::lock_guard<std::mutex> lock(g_luamutex);
-       g_outputBuffer.clear();
-       resetLuaSideEffect();
-       auto ret=g_lua.executeCode<
-       boost::optional<
-         boost::variant<
-           string, 
-           shared_ptr<DownstreamState>
-           >
-         >
-       >(line);
-       if(ret) {
-       if (const auto strValue = boost::get<shared_ptr<DownstreamState>>(&*ret)) {
-         cout<<(*strValue)->getName()<<endl;
-       }
-       else if (const auto strValue = boost::get<string>(&*ret)) {
-         cout<<*strValue<<endl;
-       }
+       bool withReturn=true;
+     retry:;
+       try {
+         std::lock_guard<std::mutex> lock(g_luamutex);
+         g_outputBuffer.clear();
+         resetLuaSideEffect();
+         auto ret=g_lua.executeCode<
+           boost::optional<
+             boost::variant<
+               string, 
+               shared_ptr<DownstreamState>,
+               std::unordered_map<string, double>
+               >
+             >
+           >(withReturn ? ("return "+line) : line);
+         
+         if(ret) {
+           if (const auto strValue = boost::get<shared_ptr<DownstreamState>>(&*ret)) {
+             cout<<(*strValue)->getName()<<endl;
+           }
+           else if (const auto strValue = boost::get<string>(&*ret)) {
+             cout<<*strValue<<endl;
+           }
+           else if(const auto um = boost::get<std::unordered_map<string, double> >(&*ret)) {
+             using namespace json11;
+             Json::object o;
+             for(const auto& v : *um)
+               o[v.first]=v.second;
+             Json out = o;
+             cout<<out.dump()<<endl;
+           }
+         }
+         else 
+           cout << g_outputBuffer;
+         if(!getLuaNoSideEffect())
+           feedConfigDelta(line);
        }
-       else 
-       cout << g_outputBuffer;
-       if(!getLuaNoSideEffect())
-         feedConfigDelta(line);
+       catch(const LuaContext::SyntaxErrorException&) {
+         if(withReturn) {
+           withReturn=false;
+           goto retry;
+         }
+         throw;
+       }
+     }
+     catch(const LuaContext::WrongTypeException& e) {
+       std::cerr<<"Command returned an object we can't print"<<std::endl;
+       // tried to return something we don't understand
      }
      catch(const LuaContext::ExecutionErrorException& e) {
        std::cerr << e.what(); 
@@@ -255,6 -282,7 +282,7 @@@ char** my_completion( const char * tex
  void controlClientThread(int fd, ComboAddress client)
  try
  {
+   setTCPNoDelay(fd);
    SodiumNonce theirs;
    readn2(fd, (char*)theirs.value, sizeof(theirs.value));
    SodiumNonce ours;
      //    cerr<<"Have decrypted line: "<<line<<endl;
      string response;
      try {
-       std::lock_guard<std::mutex> lock(g_luamutex);
-       g_outputBuffer.clear();
-       resetLuaSideEffect();
-       auto ret=g_lua.executeCode<
-       boost::optional<
-         boost::variant<
-           string, 
-           shared_ptr<DownstreamState>
-           >
-         >
-       >(line);
+       bool withReturn=true;
+     retry:;
+       try {
+         std::lock_guard<std::mutex> lock(g_luamutex);
+         
+         g_outputBuffer.clear();
+         resetLuaSideEffect();
+         auto ret=g_lua.executeCode<
+           boost::optional<
+             boost::variant<
+               string, 
+               shared_ptr<DownstreamState>,
+               std::unordered_map<string, double>
+               >
+             >
+           >(withReturn ? ("return "+line) : line);
  
        if(ret) {
        if (const auto strValue = boost::get<shared_ptr<DownstreamState>>(&*ret)) {
-         response=(*strValue)->getName();
+         response=(*strValue)->getName()+"\n";
        }
        else if (const auto strValue = boost::get<string>(&*ret)) {
-         response=*strValue;
+         response=*strValue+"\n";
        }
+         else if(const auto um = boost::get<std::unordered_map<string, double> >(&*ret)) {
+           using namespace json11;
+           Json::object o;
+           for(const auto& v : *um)
+             o[v.first]=v.second;
+           Json out = o;
+           response=out.dump()+"\n";
+         }
        }
        else
        response=g_outputBuffer;
        if(!getLuaNoSideEffect())
          feedConfigDelta(line);
+       }
+       catch(const LuaContext::SyntaxErrorException&) {
+         if(withReturn) {
+           withReturn=false;
+           goto retry;
+         }
+         throw;
+       }
      }
      catch(const LuaContext::ExecutionErrorException& e) {
        response = "Error: " + string(e.what()) + ": ";
diff --combined pdns/dnsdist-lua2.cc
index 9d52658aa150e0f61ae67febdd0135eb3670cbc1,cb641be16809cabd8048bf19e1a8275fbd709813..ada1ebbd77859fabd218f5ad9aa9a12145900316
@@@ -455,9 -455,12 +455,9 @@@ void moreLua(bool client
      g_lua.writeFunction("generateDNSCryptCertificate", [](const std::string& providerPrivateKeyFile, const std::string& certificateFile, const std::string privateKeyFile, uint32_t serial, time_t begin, time_t end) {
          setLuaNoSideEffect();
  #ifdef HAVE_DNSCRYPT
 -        unsigned char privateKey[DNSCRYPT_PRIVATE_KEY_SIZE];
          unsigned char providerPrivateKey[DNSCRYPT_PROVIDER_PRIVATE_KEY_SIZE];
          sodium_mlock(providerPrivateKey, sizeof(providerPrivateKey));
 -        sodium_mlock(privateKey, sizeof(privateKey));
          sodium_memzero(providerPrivateKey, sizeof(providerPrivateKey));
 -        sodium_memzero(privateKey, sizeof(privateKey));
  
          try {
            DnsCryptPrivateKey privateKey;
          }
  
          sodium_memzero(providerPrivateKey, sizeof(providerPrivateKey));
 -        sodium_memzero(privateKey, sizeof(privateKey));
          sodium_munlock(providerPrivateKey, sizeof(providerPrivateKey));
 -        sodium_munlock(privateKey, sizeof(privateKey));
  #else
        g_outputBuffer="Error: DNSCrypt support is not enabled.\n";
  #endif
  
      g_lua.writeFunction("getAction", [](unsigned int num) {
          setLuaNoSideEffect();
+         boost::optional<std::shared_ptr<DNSAction>> ret;
          auto rulactions = g_rulactions.getCopy();
-         if(num >= rulactions.size())
-           return std::shared_ptr<DNSAction>();
-         return rulactions[num].second;
+         if(num < rulactions.size())
+           ret=rulactions[num].second;
+         return ret;
        });
  
      g_lua.registerFunction("getStats", &DNSAction::getStats);
diff --combined pdns/misc.cc
index 42b88ea093be6bc5114b0879ec08c8945293bb72,3b2c6670d68f25585959cff0b38f609380a18614..a009fb4e63cf50588c82d989176172db079d8e2e
@@@ -46,6 -46,7 +46,7 @@@
  #include <boost/optional.hpp>
  #include <poll.h>
  #include <iomanip>
+ #include <netinet/tcp.h>
  #include <string.h>
  #include <stdlib.h>
  #include <stdio.h>
  
  bool g_singleThreaded;
  
 -int writen2(int fd, const void *buf, size_t count)
 +size_t writen2(int fd, const void *buf, size_t count)
  {
    const char *ptr = (char*)buf;
    const char *eptr = ptr + count;
  
 -  int res;
 +  ssize_t res;
    while(ptr != eptr) {
      res = ::write(fd, ptr, eptr - ptr);
      if(res < 0) {
      else if (res == 0)
        throw std::runtime_error("could not write all bytes, got eof in writen2");
  
 -    ptr += res;
 +    ptr += (size_t) res;
    }
  
    return count;
  }
  
 -int readn2(int fd, void* buffer, unsigned int len)
 +size_t readn2(int fd, void* buffer, size_t len)
  {
 -  unsigned int pos=0;
 -  int res;
 +  size_t pos=0;
 +  ssize_t res;
    for(;;) {
      res = read(fd, (char*)buffer + pos, len - pos);
      if(res == 0)
          unixDie("failed in readn2");
      }
  
 -    pos+=res;
 +    pos+=(size_t)res;
      if(pos == len)
        break;
    }
    return len;
  }
  
 -int readn2WithTimeout(int fd, void* buffer, size_t len, int timeout)
 +size_t readn2WithTimeout(int fd, void* buffer, size_t len, int timeout)
  {
    size_t pos = 0;
    do {
    return len;
  }
  
 -int writen2WithTimeout(int fd, const void * buffer, size_t len, int timeout)
 +size_t writen2WithTimeout(int fd, const void * buffer, size_t len, int timeout)
  {
    size_t pos = 0;
    do {
@@@ -204,7 -205,67 +205,7 @@@ uint32_t getLong(const char* p
    return getLong((unsigned char *)p);
  }
  
 -
 -
 -/** strips a domain suffix from a domain, returns true if it stripped */
 -bool stripDomainSuffix(string *qname, const string &domain)
 -{
 -  if(!endsOn(*qname, domain))
 -    return false;
 -
 -  if(toLower(*qname)==toLower(domain))
 -    *qname="@";
 -  else {
 -    if((*qname)[qname->size()-domain.size()-1]!='.')
 -      return false;
 -
 -    qname->resize(qname->size()-domain.size()-1);
 -  }
 -  return true;
 -}
 -
 -/** Chops off the start of a domain, so goes from 'www.ds9a.nl' to 'ds9a.nl' to 'nl' to ''. Return zero on the empty string */
 -bool chopOff(string &domain)
 -{
 -  if(domain.empty())
 -    return false;
 -
 -  string::size_type fdot=domain.find('.');
 -
 -  if(fdot==string::npos)
 -    domain="";
 -  else {
 -    string::size_type remain = domain.length() - (fdot + 1);
 -    char tmp[remain];
 -    memcpy(tmp, domain.c_str()+fdot+1, remain);
 -    domain.assign(tmp, remain); // don't dare to do this w/o tmp holder :-)
 -  }
 -  return true;
 -}
 -
 -/** Chops off the start of a domain, so goes from 'www.ds9a.nl.' to 'ds9a.nl.' to 'nl.' to '.' Return zero on the empty string */
 -bool chopOffDotted(string &domain)
 -{
 -  if(domain.empty() || (domain.size()==1 && domain[0]=='.'))
 -    return false;
 -
 -  string::size_type fdot=domain.find('.');
 -  if(fdot == string::npos)
 -    return false;
 -
 -  if(fdot==domain.size()-1)
 -    domain=".";
 -  else  {
 -    string::size_type remain = domain.length() - (fdot + 1);
 -    char tmp[remain];
 -    memcpy(tmp, domain.c_str()+fdot+1, remain);
 -    domain.assign(tmp, remain);
 -  }
 -  return true;
 -}
 -
 -
 -bool ciEqual(const string& a, const string& b)
 +static bool ciEqual(const string& a, const string& b)
  {
    if(a.size()!=b.size())
      return false;
  }
  
  /** does domain end on suffix? Is smart about "wwwds9a.nl" "ds9a.nl" not matching */
 -bool endsOn(const string &domain, const string &suffix)
 +static bool endsOn(const string &domain, const string &suffix)
  {
    if( suffix.empty() || ciEqual(domain, suffix) )
      return true;
    return true;
  }
  
 +/** strips a domain suffix from a domain, returns true if it stripped */
 +bool stripDomainSuffix(string *qname, const string &domain)
 +{
 +  if(!endsOn(*qname, domain))
 +    return false;
 +
 +  if(toLower(*qname)==toLower(domain))
 +    *qname="@";
 +  else {
 +    if((*qname)[qname->size()-domain.size()-1]!='.')
 +      return false;
 +
 +    qname->resize(qname->size()-domain.size()-1);
 +  }
 +  return true;
 +}
 +
  static void parseService4(const string &descr, ServiceTuple &st)
  {
    vector<string>parts;
@@@ -1004,6 -1048,17 +1005,17 @@@ bool setSocketTimestamps(int fd
    return true; // we pretend this happened.
  }
  
+ void setTCPNoDelay(int sock)
+ {
+   int flag = 1;
+   setsockopt(sock,            /* socket affected */
+              IPPROTO_TCP,     /* set option at TCP level */
+              TCP_NODELAY,     /* name of option */
+              (char *) &flag,  /* the cast is historical cruft */
+              sizeof(flag));    /* length of option value */
+ }
  bool setNonBlocking(int sock)
  {
    int flags=fcntl(sock,F_GETFL,0);
diff --combined pdns/misc.hh
index 302273eaf5e435d76c8edd1a3909451f7f3df928,a0ea680a920b437003d4ec8fb2201d6aed95132a..252df85e6819cda8c7e8577c5d10336aa2d4b735
@@@ -52,6 -52,10 +52,6 @@@ using namespace ::boost::multi_index
  
  typedef enum { TSIG_MD5, TSIG_SHA1, TSIG_SHA224, TSIG_SHA256, TSIG_SHA384, TSIG_SHA512, TSIG_GSS } TSIGHashEnum;
  
 -bool chopOff(string &domain);
 -bool chopOffDotted(string &domain);
 -
 -bool endsOn(const string &domain, const string &suffix);
  string nowTime();
  const string unquotify(const string &item);
  string humanDuration(time_t passed);
@@@ -142,11 -146,11 +142,11 @@@ vstringtok (Container &container, strin
    }
  }
  
 -int writen2(int fd, const void *buf, size_t count);
 -inline int writen2(int fd, const std::string &s) { return writen2(fd, s.data(), s.size()); }
 -int readn2(int fd, void* buffer, unsigned int len);
 -int readn2WithTimeout(int fd, void* buffer, size_t len, int timeout);
 -int writen2WithTimeout(int fd, const void * buffer, size_t len, int timeout);
 +size_t writen2(int fd, const void *buf, size_t count);
 +inline size_t writen2(int fd, const std::string &s) { return writen2(fd, s.data(), s.size()); }
 +size_t readn2(int fd, void* buffer, size_t len);
 +size_t readn2WithTimeout(int fd, void* buffer, size_t len, int timeout);
 +size_t writen2WithTimeout(int fd, const void * buffer, size_t len, int timeout);
  
  const string toLower(const string &upper);
  const string toLowerCanonic(const string &upper);
@@@ -596,6 -600,7 +596,7 @@@ bool setBlocking( int sock )
  
  //! Sets the socket into non-blocking mode.
  bool setNonBlocking( int sock );
+ void setTCPNoDelay(int sock);
  bool isNonBlocking(int sock);
  int closesocket(int fd);
  bool setCloseOnExec(int sock);