Skip to content
Snippets Groups Projects
Commit cd6ed0a2 authored by Fredrik Hübinette (Hubbe)'s avatar Fredrik Hübinette (Hubbe)
Browse files

no more "cannot find a request" errors

Rev: lib/modules/Protocols.pmod/DNS.pmod:1.18
parent 366e6d30
No related branches found
No related tags found
No related merge requests found
...@@ -273,7 +273,7 @@ class client { ...@@ -273,7 +273,7 @@ class client {
array(string) nameservers = ({}); array(string) nameservers = ({});
array domains = ({}); array domains = ({});
void create(void|string server) void create(void|string|array(string) server, void|int|array(string) domain)
{ {
if(!server) if(!server)
{ {
...@@ -342,7 +342,16 @@ class client { ...@@ -342,7 +342,16 @@ class client {
return d; return d;
}); });
} else { } else {
nameservers= ({ server }); if(arrayp(server))
nameservers= server;
else
nameservers= ({ server });
if(arrayp(domain))
domains = domain;
else
domains = ({ domains });
} }
} }
...@@ -458,15 +467,20 @@ class client { ...@@ -458,15 +467,20 @@ class client {
} }
} }
#define RETRIES 12
#define RETRY_DELAY 5
#define REMOVE_DELAY 120
#define GIVE_UP_DELAY (RETRIES * RETRY_DELAY + REMOVE_DELAY)*2
class async_client class async_client
{ {
inherit client; inherit client;
inherit spider.dumUDP : udp; inherit spider.dumUDP : udp;
int id; int id;
async_client next_client;
#if constant(thread_create) #if constant(thread_create)
object lock = Thread.Mutex(); static private inherit Thread.Mutex : lock;
#endif /* constant(thread_create) */ #endif /* constant(thread_create) */
class Request class Request
...@@ -475,12 +489,12 @@ class async_client ...@@ -475,12 +489,12 @@ class async_client
string domain; string domain;
function callback; function callback;
int retries; int retries;
int timestamp;
mixed *args; mixed *args;
}; };
mapping requests=([]); mapping requests=([]);
static private void remove(object(Request) r) static private void remove(object(Request) r)
{ {
if(!r) return; if(!r) return;
...@@ -494,9 +508,9 @@ class async_client ...@@ -494,9 +508,9 @@ class async_client
{ {
if(!r) return; if(!r) return;
if (nsno >= sizeof(nameservers)) { if (nsno >= sizeof(nameservers)) {
if(r->retries++ > 12) if(r->retries++ > RETRIES)
{ {
call_out(remove,120,r); call_out(remove,REMOVE_DELAY,r);
return; return;
} else { } else {
nsno = 0; nsno = 0;
...@@ -504,26 +518,63 @@ class async_client ...@@ -504,26 +518,63 @@ class async_client
} }
send(nameservers[nsno],53,r->req); send(nameservers[nsno],53,r->req);
call_out(retry,5,r,nsno+1); call_out(retry,RETRY_DELAY,r,nsno+1);
} }
void do_query(string domain, int cl, int type, void do_query(string domain, int cl, int type,
function(string,mapping,mixed...:void) callback, function(string,mapping,mixed...:void) callback,
mixed ... args) mixed ... args)
{ {
int lid;
#if constant(thread_create) #if constant(thread_create)
object key = lock->lock(); object key=lock::lock();
#endif /* constant(thread_create) */ #endif /* constant(thread_create) */
id++; for(int e=next_client ? 5 : 1024;e>=0;e--)
id&=65535; {
int lid = id; id++;
id&=65535;
lid=id;
if(requests[lid])
{
if(time() - requests[lid]->timestamp > GIVE_UP_DELAY)
{
#if constant(thread_create)
// We need to unlock the lock for the remove operation...
key=0;
#endif /* constant(thread_create) */
remove(requests[lid]);
#if constant(thread_create) #if constant(thread_create)
key = 0; key=lock::lock();
#endif /* constant(thread_create) */ #endif /* constant(thread_create) */
if(requests[lid]) continue;
}else{
continue;
}
}
break;
}
if(requests[lid]) if(requests[lid])
throw(({"Cannot find an empty request slot.\n",backtrace()})); {
/* We failed miserably to find a request id to use,
* so we create a second UDP port to be able to have more
* requests 'in the air'. /Hubbe
*/
if(!next_client)
{
next_client=async_client(nameservers,domains);
next_client->nameservers=nameservers;
next_client->domains=domains;
}
#if constant(thread_create)
key=0;
#endif /* constant(thread_create) */
next_client->do_query(domain, cl, type, callback, @args);
return;
}
string req=low_mkquery(lid,domain,cl,type); string req=low_mkquery(lid,domain,cl,type);
...@@ -532,9 +583,10 @@ class async_client ...@@ -532,9 +583,10 @@ class async_client
r->domain=domain; r->domain=domain;
r->callback=callback; r->callback=callback;
r->args=args; r->args=args;
r->timestamp=time();
requests[lid]=r; requests[lid]=r;
udp::send(nameservers[0],53,r->req); udp::send(nameservers[0],53,r->req);
call_out(retry,5,r,1); call_out(retry,RETRY_DELAY,r,1);
} }
static private void rec_data() static private void rec_data()
...@@ -607,12 +659,12 @@ class async_client ...@@ -607,12 +659,12 @@ class async_client
@args); @args);
} }
void create(void|string server) void create(void|string|array(string) server, void|string|array(string) domain)
{ {
if(!udp::bind(0)) if(!udp::bind(0))
throw(({"DNS: failed to bind a port.\n",backtrace()})); throw(({"DNS: failed to bind a port.\n",backtrace()}));
udp::set_read_callback(rec_data); udp::set_read_callback(rec_data);
::create(server); ::create(server,domain);
} }
}; };
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment