From 3d3ed7c069fde22a5a54251cd6dfc368777a76c8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fredrik=20H=C3=BCbinette=20=28Hubbe=29?= <hubbe@hubbe.net>
Date: Mon, 15 Sep 1997 02:06:50 -0700
Subject: [PATCH] completely untested async_client added

Rev: lib/modules/Protocols.pmod/DNS.pmod:1.2
---
 lib/modules/Protocols.pmod/DNS.pmod | 97 ++++++++++++++++++++++++++---
 1 file changed, 88 insertions(+), 9 deletions(-)

diff --git a/lib/modules/Protocols.pmod/DNS.pmod b/lib/modules/Protocols.pmod/DNS.pmod
index ae3a26e9ed..5992beeb88 100644
--- a/lib/modules/Protocols.pmod/DNS.pmod
+++ b/lib/modules/Protocols.pmod/DNS.pmod
@@ -36,14 +36,11 @@ class protocol
     return sprintf("%c%s",strlen(s),s);
   }
 
-  // This will have to be generalized for
-  // the server part...
-  string mkquery(string dname,
-		 int cl,
-		 int type)
+  string low_mkquery(int id,
+		    string dname,
+		    int cl,
+		    int type)
   {
-    int id=random(65536); // make spoofing harder
-    
     return sprintf("%2c%c%c%2c%2c%2c%2c%s\000%2c%2c",
 		   id,
 		   1,0,
@@ -56,6 +53,15 @@ class protocol
 
   }
 
+  // This will have to be generalized for
+  // the server part...
+  string mkquery(string dname,
+		 int cl,
+		 int type)
+  {
+    return low_mkquery(random(65536),dname,cl,type);
+  }
+
   string decode_domain(string msg, int *n)
   {
     string *domains=({});
@@ -319,9 +325,82 @@ class client {
 class async_client
 {
   inherit client;
+  inherit spider.dumUDP;
+  int id;
 
-  mapping requests=([]);
-  class request
+  class Request
   {
+    string req;
+    function success;
+    function fail;
+    int retries;
+    mixed *args;
   };
+
+  static private mapping requests=([]);
+
+
+  static private void remove(object(Request) r)
+  {
+    if(!r) return;
+    sscanf(r->req,"%2c",int id);
+    function f=r->fail;
+    mixed *args=r->args;
+    m_delete(requests,id);
+    destruct(r);
+    f(@args);
+  }
+
+  void retry(object(Request) r)
+  {
+    if(!r) return;
+    if(r->retries > 6)
+    {
+      call_out(remove,120,r);
+    }else{
+      send(nameserver,53,r->req);
+    }
+  }
+
+  void do_query(string domain, int cl, int type,
+		function callback,
+		function fail_callback,
+		mixed ... args)
+  {
+    id++;
+    id&=65535;
+    string req=low_mkquery(id,domain,cl,type);
+
+    if(requests[id])
+      throw(({"Cannot find an empty request slot.\n",backtrace()}));
+
+    object r=Request();
+    r->req=req;
+    r->success=callback;
+    r->fail=fail_callback;
+    requests[id]=r;
+    call_out(retry,5,r);
+    send(nameserver,53,r->req);
+  }
+
+  static private void rec_data()
+  {
+    mapping m=read();
+    if(m->port != 53 || m->ip != nameserver) return;
+    sscanf(m->data,"%2c",int id);
+    object r=requests[id];
+    if(!r) return;
+    function f=r->success;
+    mixed *args=r->args;
+    m_delete(requests,id);
+    destruct(r);
+    f(decode_res(m->data),@args);
+  }
+  
+  void creat(string server)
+  {
+    bind(0);
+    set_read_callback(rec_data);
+    ::create(server);
+  }
 };
-- 
GitLab