pike.git
/
lib
/
modules
/
Protocols.pmod
/
DNS.pmod
version
»
Context lines:
10
20
40
80
file
none
3
pike.git/lib/modules/Protocols.pmod/DNS.pmod:1959:
Inside #if 0
"%s\n", server, domain, udp::query_address(), describe_backtrace(backtrace())); #endif /* 0 */ udp::set_read_callback(rec_data); ::create(server,domain); } };
+
// FIXME: Reuse sockets where possible?
+
//! Synchronous DNS client using TCP
+
//! Can handle larger responses than @[client] can.
+
class tcp_client
+
{
+
inherit client;
+
+
//! Perform a synchronous DNS query.
+
//!
+
//! @param s
+
//! Result of @[Protocols.DNS.protocol.mkquery]
+
//! @returns
+
//! mapping containing query result or 0 on failure/timeout
+
//!
+
//! @example
+
//! @code
+
//! // Perform a hostname lookup, results stored in r->an
+
//! object d=Protocols.DNS.tcp_client();
+
//! mapping r=d->do_sync_query(d->mkquery("pike.lysator.liu.se", C_IN, T_A));
+
//! @endcode
+
mapping do_sync_query(string s)
+
{
+
for (int i=0; i < RETRIES; i++) {
+
object tcp = Stdio.File();
+
if (tcp->connect(nameservers[i % sizeof(nameservers)], 53))
+
{
+
tcp->write("%2H",s);
+
sscanf(tcp->read(2),"%2c",int len);
+
return decode_res(tcp->read(len));
+
}
+
}
+
// Failure.
+
return 0;
+
}
+
}
+
+
// FIXME: Reuse sockets? Acknowledge RETRIES?
+
//! Asynchronous DNS client using TCP
+
class async_tcp_client
+
{
+
inherit client;
+
+
class Request(string domain, string req,
+
function(string,mapping,mixed...:void) callback,
+
array(mixed) args)
+
{
+
Stdio.File sock;
+
string writebuf="",readbuf="";
+
+
void create()
+
{
+
sock=Stdio.File();
+
sock->async_connect(nameservers[0], 53, connectedcb);
+
}
+
+
void connectedcb(int ok)
+
{
+
if (!ok) {callback(domain, 0, @args); return;}
+
sock->set_nonblocking(readcb, writecb, closecb);
+
writebuf=sprintf("%2H",req);
+
writecb();
+
}
+
+
void readcb(mixed id,string data)
+
{
+
readbuf+=data;
+
if (sscanf(readbuf,"%2H",string ret))
+
{
+
if (callback) callback(domain, decode_res(ret), @args);
+
callback=0;
+
sock->close();
+
}
+
}
+
+
void writecb()
+
{
+
if (writebuf!="") writebuf=writebuf[sock->write(writebuf)..];
+
}
+
+
void closecb()
+
{
+
sock->close();
+
if (callback) callback(domain, 0, @args);
+
callback=0;
+
}
+
}
+
+
//!
+
void do_query(string domain, int cl, int type,
+
function(string,mapping,mixed...:void) callback,
+
mixed ... args)
+
{
+
string req=low_mkquery(random(65536),domain,cl,type);
+
Request(domain, req, callback, args);
+
}
+
}
+
+
//! Both a @[client] and a @[tcp_client].
+
class dual_client
+
{
+
inherit client : UDP;
+
inherit tcp_client : TCP;
+
+
//!
+
mapping do_sync_query(string s)
+
{
+
mapping ret = UDP::do_sync_query(s);
+
if (!ret->tc) return ret;
+
return TCP::do_sync_query(s);
+
}
+
+
void create(mixed ... args) {::create(@args);}
+
}
+
+
//! Both an @[async_client] and an @[async_tcp_client].
+
class async_dual_client
+
{
+
inherit async_client : UDP;
+
inherit async_tcp_client : TCP;
+
+
void check_truncation(string domain, mapping result, int cl, int type,
+
function(string,mapping,mixed...:void) callback,
+
mixed ... args)
+
{
+
if (!result || !result->tc) callback(domain,result,@args);
+
else TCP::do_query(domain,cl,type,callback,@args);
+
}
+
+
//!
+
void do_query(string domain, int cl, int type,
+
function(string,mapping,mixed...:void) callback,
+
mixed ... args)
+
{
+
UDP::do_query(domain,cl,type,check_truncation,cl,type,callback,@args);
+
}
+
+
void create(mixed ... args) {::create(@args);}
+
}
+
+
async_client global_async_client; #define GAC(X) \ void async_##X( string host, function callback, mixed ... args ) \ { \ if( !global_async_client ) \ global_async_client = async_client(); \ global_async_client->X(host,callback,@args); \ }