]> granicus.if.org Git - pdns/commitdiff
service pack 2 for the remotebackend, submitted by Aki Tuomi. Additional patch by...
authorPeter van Dijk <peter.van.dijk@netherlabs.nl>
Mon, 10 Dec 2012 14:30:49 +0000 (14:30 +0000)
committerPeter van Dijk <peter.van.dijk@netherlabs.nl>
Mon, 10 Dec 2012 14:30:49 +0000 (14:30 +0000)
git-svn-id: svn://svn.powerdns.com/pdns/trunk/pdns@2980 d19b8d6e-7fed-0310-83ef-9ca221ded41b

modules/remotebackend/httpconnector.cc
modules/remotebackend/pipeconnector.cc
modules/remotebackend/regression-tests/backend.rb
modules/remotebackend/regression-tests/http-backend.rb
modules/remotebackend/regression-tests/pipe-backend.rb
modules/remotebackend/remotebackend.cc
modules/remotebackend/remotebackend.hh
modules/remotebackend/unixconnector.cc
pdns/docs/pdns.xml
regression-tests/start-test-stop

index efb378d5a2c608d461583390a463210fb339acec..4ab9deec303a35107c01b4cf89959796dbed7b7c 100644 (file)
@@ -22,6 +22,10 @@ HTTPConnector::HTTPConnector(std::map<std::string,std::string> options) {
     } else {
       this->d_url_suffix = "";
     }
+    this->timeout = 2;
+    if (options.find("timeout") != options.end()) { 
+      this->timeout = boost::lexical_cast<int>(options.find("timeout")->second)/1000;
+    }
 }
 
 HTTPConnector::~HTTPConnector() {
@@ -83,7 +87,7 @@ void HTTPConnector::requestbuilder(const std::string &method, const rapidjson::V
     // finally add suffix
     ss << d_url_suffix;
     curl_easy_setopt(d_c, CURLOPT_URL, ss.str().c_str());
-
+    
     (*slist) = NULL;
     // set the correct type of request based on method
     if (method == "activateDomainKey" || method == "deactivateDomainKey") { 
@@ -154,7 +158,8 @@ int HTTPConnector::send_message(const rapidjson::Document &input) {
     d_c = curl_easy_init();
     d_data = "";
     curl_easy_setopt(d_c, CURLOPT_NOSIGNAL, 1);
-    curl_easy_setopt(d_c, CURLOPT_TIMEOUT, 2);
+    curl_easy_setopt(d_c, CURLOPT_TIMEOUT, this->timeout);
+
     slist = NULL;
 
     // build request
index b2cd5777eecb745cad471959d5e162122e90e1b1..2f256552d69de1c0489bbeb0646b8819d1aceeef 100644 (file)
@@ -20,7 +20,11 @@ void PipeConnector::launch() {
   if (coproc != NULL) return;
   rapidjson::Value val;
   rapidjson::Document init,res;
-  coproc = new CoProcess(this->command, 2000);
+  int timeout=2000;
+  if (options.find("timeout") != options.end()) { 
+     timeout = boost::lexical_cast<int>(options.find("timeout")->second);
+  }
+  coproc = new CoProcess(this->command, timeout);
   init.SetObject();
   val = "initialize";
   init.AddMember("method",val, init.GetAllocator());
index 8f859418094fb44ad43cfa0dd3860058ccd89adf..444e402182ed07a56410a3a837bf5047a215fce2 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/ruby1.9.1
+#!/usr/bin/ruby
 
 require 'json'
 require 'sqlite3'
index 8a49989dc61cba48946a8934273f2975a3f24b33..6bf6be373b1ea035a76f39fa4dcd330e789636ae 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/ruby1.9.1
+#!/usr/bin/ruby
 require "rubygems"
 #require "bundler/setup"
 require "webrick"
@@ -6,10 +6,10 @@ require "../modules/remotebackend/regression-tests/dnsbackend"
 require "../modules/remotebackend/regression-tests/backend"
 
 server = WEBrick::HTTPServer.new(
-       Port: 62434,
-       BindAddress: "localhost",
+       :Port=>62434,
+       :BindAddress=>"localhost",
 #      Logger: WEBrick::Log.new("remotebackend-server.log"),
-       AccessLog: [ [ File.open("remotebackend-access.log", "w"), WEBrick::AccessLog::COMBINED_LOG_FORMAT ] ] 
+       :AccessLog=>[ [ File.open("remotebackend-access.log", "w"), WEBrick::AccessLog::COMBINED_LOG_FORMAT ] ] 
 )
 
 be = Handler.new("../modules/remotebackend/regression-tests/remote.sqlite3") 
index a71c519b9e7532c25e0fb0b5d43f92afcae35a84..271c782128c3bc79822a9523dcc30314cbb5bfe2 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/ruby1.9.1
+#!/usr/bin/ruby
 
 require 'json'
 require '../modules/remotebackend/regression-tests/backend'
@@ -28,7 +28,7 @@ begin
          res, log = h.send(method)
       end
       puts ({:result => res, :log => log}).to_json
-      f.puts ({:result => res, :log => log}).to_json
+      f.puts({:result => res, :log => log}).to_json
     rescue JSON::ParserError
       puts ({:result => false, :log => "Cannot parse input #{line}"}).to_json
       next
index 6d1b644079e1946471bfb47bd9f38f246996710b..622897bf6f053ac2b78f93b01c418963585854e4 100644 (file)
@@ -136,11 +136,18 @@ void RemoteBackend::lookup(const QType &qtype, const std::string &qdomain, DNSPa
    JSON_ADD_MEMBER(parameters, "qtype", qtype.getName().c_str(), query.GetAllocator());
    JSON_ADD_MEMBER(parameters, "qname", qdomain.c_str(), query.GetAllocator());
 
-   if (pkt_p != NULL) {
-     JSON_ADD_MEMBER(parameters, "remote", pkt_p->getRemote().c_str(), query.GetAllocator());
-     JSON_ADD_MEMBER(parameters, "local", pkt_p->getRemote().c_str(), query.GetAllocator());
-     JSON_ADD_MEMBER(parameters, "real-remote", pkt_p->getRealRemote().toString().c_str(), query.GetAllocator());
+   string localIP="0.0.0.0";
+   string remoteIP="0.0.0.0";
+   string realRemote="0.0.0.0/0";
+   if (pkt_p) {
+     localIP=pkt_p->getLocal();
+     realRemote = pkt_p->getRealRemote().toString();
+     remoteIP = pkt_p->getRemote();
    }
+
+   JSON_ADD_MEMBER(parameters, "remote", remoteIP.c_str(), query.GetAllocator());
+   JSON_ADD_MEMBER(parameters, "local", localIP.c_str(), query.GetAllocator());
+   JSON_ADD_MEMBER(parameters, "real-remote", realRemote.c_str(), query.GetAllocator());
    JSON_ADD_MEMBER(parameters, "zone-id", zoneId, query.GetAllocator());
    query.AddMember("parameters", parameters, query.GetAllocator());
 
@@ -249,8 +256,12 @@ bool RemoteBackend::getDomainMetadata(const std::string& name, const std::string
    if (connector->recv(answer) == false)
      return true;
 
-   for(rapidjson::Value::ValueIterator iter = answer.Begin(); iter != answer.End(); iter++) {
-          meta.push_back(iter->GetString());
+   if (answer.IsArray()) {
+      for(rapidjson::Value::ValueIterator iter = answer.Begin(); iter != answer.End(); iter++) {
+         meta.push_back(iter->GetString());
+      }
+   } else if (answer.IsString()) {
+      meta.push_back(answer.GetString());
    }
 
    return true;
@@ -501,7 +512,6 @@ class RemoteBackendFactory : public BackendFactory
       {
           declare(suffix,"dnssec","Enable dnssec support","no");
           declare(suffix,"connection-string","Connection string","");
-          declare(suffix,"timeout","Timeout in milliseconds to wait for reply","2000");
       }
 
       DNSBackend *make(const std::string &suffix="")
index 98445380a22cf28a3e14f0c83696790e3ee415ff..924b27876612773fe9f78d2d51f3da9bcd804c6e 100644 (file)
@@ -47,6 +47,7 @@ class UnixsocketConnector: public Connector {
     int fd;
     std::string path;
     bool connected;
+    int timeout;
 };
 
 #ifdef REMOTEBACKEND_HTTP
@@ -64,6 +65,7 @@ class HTTPConnector: public Connector {
     std::string d_url_suffix;
     CURL *d_c;
     std::string d_data;
+    int timeout;
     void json2string(const rapidjson::Value &input, std::string &output);
     void requestbuilder(const std::string &method, const rapidjson::Value &parameters, struct curl_slist **slist);
     void addUrlComponent(const rapidjson::Value &parameters, const char *element, std::stringstream& ss);
index 560f1da131b29b82d0265f463a38d23b0a87e518..c7894de3031e9dcbcd41884bb761bcbfcc3007c8 100644 (file)
@@ -13,6 +13,10 @@ UnixsocketConnector::UnixsocketConnector(std::map<std::string,std::string> optio
      L<<Logger::Error<<"Cannot find 'path' option in connection string"<<endl;
      throw new AhuException();
    } 
+   this->timeout = 2000;
+   if (options.find("timeout") != options.end()) { 
+     this->timeout = boost::lexical_cast<int>(options.find("timeout")->second);
+   }
    this->path = options.find("path")->second;
    this->options = options;
    this->connected = false;
@@ -41,13 +45,14 @@ int UnixsocketConnector::recv_message(rapidjson::Document &output) {
         std::string s_output;
         rapidjson::GenericReader<rapidjson::UTF8<> , rapidjson::MemoryPoolAllocator<> > r;
 
-        time_t t0;
+        struct timeval t0,t;
 
         nread = 0;
-        t0 = time(NULL);
+        gettimeofday(&t0, NULL);
+        memcpy(&t,&t0,sizeof(t0));
         s_output = "";       
-        while(time(NULL) - t0 < 2) { // 2 second timeout 
+
+        while((t.tv_sec - t0.tv_sec)*1000 + (t.tv_usec - t0.tv_usec)/1000 < this->timeout) { 
           std::string temp;
           temp.clear();
 
@@ -63,6 +68,7 @@ int UnixsocketConnector::recv_message(rapidjson::Document &output) {
             if (output.HasParseError() == false)
               return s_output.size();
           }
+          gettimeofday(&t, NULL);
         }
 
         return -1;
index 31a8b01fff372811c967d8698ba2553f56f2ef5f..8a5e1e0625dc3f64c5a7ff8ffd7ce9c8a2c43bbc 100644 (file)
@@ -17961,7 +17961,8 @@ record building scripts on his <ulink url="http://anders.com/projects/sysadmin/d
       </para>
      <sect2 id="remotebackend-compiling"><title>Compiling</title>
         <para>
-        Install following libraries for dependencies: libjsoncpp, libcurl. To compile this backend, you need to configure --with-modules="remote pipe", for now.
+        Install following libraries for dependencies: libjsoncpp. To compile this backend, you need to configure --with-modules="remote pipe", for
+        now. If you want to use http connector, you need libcurl and use --enable-remotebackend-http. 
       </para>
       </sect2>
       <sect2 id="remotebackend-usage"><title>Usage</title>
@@ -17976,11 +17977,12 @@ remote-connection-string=&lt;type&gt;:&lt;param&gt;=&lt;value&gt;,&lt;param&gt;=
         <para>
           You can pass as many parameters as you want. For unix and pipe backends, these
           are passed along to the remote end as initialization. See <xref linkend="remotebackend-api" />.
+          Initialize is not called for http backend. 
         </para>
 
       <sect3 id="remotebackend-unix"><title>Unix backend</title>
         <para>
-          parameters: path 
+          parameters: path, timeout (default 2000ms)
         </para>
         <para>
           <programlisting>
@@ -17991,11 +17993,11 @@ remote-connection-string=unix:path=/path/to/socket
 
             <sect3 id="remotebackend-pipe"><title>Pipe backend</title>
         <para>
-          parameters: command 
+          parameters: command,timeout (default 2000ms)
         </para>
         <para>
           <programlisting>
-remote-connection-string=unix:command=/path/to/executable
+remote-connection-string=unix:command=/path/to/executable,timeout=2000
 </programlisting>
         </para>
       </sect3>
@@ -18003,7 +18005,7 @@ remote-connection-string=unix:command=/path/to/executable
 
       <sect3 id="remotebackend-HTTP"><title>HTTP backend</title>
         <para>
-          parameters: url, url-suffix
+          parameters: url, url-suffix, timeout (default 2000)
         </para>
         <para>
           HTTP backend tries to do RESTful requests to your server. See examples.
@@ -18011,10 +18013,11 @@ remote-connection-string=unix:command=/path/to/executable
         <para>
           URL should not end with /, and url-suffix is optional, but if you define it, it's
           up to you to write the ".php" or ".json". Lack of dot causes lack of dot in
-          URL. 
+          URL. Timeout is divided by 1000 because libcurl only supports seconds, but this is
+          given in milliseconds for consistency with other backends. 
         </para>
       </sect3>
-               </sect2>
+      </sect2>
 
       <sect2 id="remotebackend-api"><title>API</title>
         <sect3 id="remotebackend-api-queries"><title>Queries</title>
@@ -18039,6 +18042,46 @@ remote-connection-string=unix:command=/path/to/executable
           </para>
         </sect3>
         <sect3 id="remotebackend-api-methods"><title>Methods</title>
+
+<sect4 id="remotebackend-api-methods-initialize"><title>Method: initialize</title>
+<variablelist>
+ <varlistentry>
+   <term>Mandatory:</term>
+   <listitem><para>Yes (except HTTP backend)</para></listitem>
+ </varlistentry>
+ <varlistentry>
+   <term>Parameters:</term>
+   <listitem><para>all parameters in connection string</para></listitem>
+ </varlistentry>
+ <varlistentry>
+   <term>Reply:</term>
+   <listitem><para>true on success / false on failure</para></listitem>
+ </varlistentry>
+ <varlistentry>
+  <term>Description</term>
+  <listitem><para>Called to initialize the backend. This is not called for HTTP backend. You should
+do your initializations here.</para></listitem>
+ </varlistentry>
+ <varlistentry>
+  <term>Example JSON/RPC:</term>
+<listitem>
+<para>
+Query:
+<programlisting>
+{"method":"initialize", "parameters":{"command":"/path/to/something", "timeout":"2000", "something":"else"}}
+</programlisting>
+</para>
+<para>
+Response:
+<programlisting>
+{"result":true}
+</programlisting>
+</para>
+</listitem>
+ </varlistentry>
+</variablelist>
+</sect4>
+
 <sect4 id="remotebackend-api-methods-lookup"><title>Method: lookup</title>
 <variablelist>
  <varlistentry>
index d886b17ea7fc221cddde7c35e2309921d88440de..9b5e2351bb0559b3eee8c62ef9b40e1d9828176c 100755 (executable)
@@ -375,6 +375,9 @@ __EOF__
                        narrow=$(echo $context | cut -d- -f 4)
                         testsdir=../modules/remotebackend/regression-tests/
 
+                        # cleanup unbound-host.conf to avoid failures
+                        rm -f unbound-host.conf
+
                        case $remotetype in
                        http)
                                connstr="http:url=http://localhost:62434/dns"