Branch: Tag:

2014-01-24

2014-01-24 17:56:32 by Henrik Grubbström (Grubba) <grubba@grubba.org>

Protocols.DNS: The async operations now return the Request object.

This is to make the caller able to cancel requests and similar.

Note that the returned object is destructed when the request completes.

Also adds some AutoDoc.

1855:       return b;    } - } +     - #define REMOVE_DELAY 120 - #define GIVE_UP_DELAY (RETRIES * RETRY_DELAY + REMOVE_DELAY)*2 -  - // FIXME: Randomized source port! - //! Asynchronous DNS client. - class async_client - { -  inherit client; -  inherit Stdio.UDP : udp; -  async_client next_client; -  +  //!    class Request(string domain, string req,    function(string,mapping,mixed...:void) callback,    array(mixed) args)
1875:    int retries;    int timestamp = time();    +  //! Cancel the current request.    void cancel()    {    remove(this_object());
1883:       mapping requests=([]);    -  protected private void remove(object(Request) r) +  protected void remove(object(Request) r)    {    if(!r) return;    sscanf(r->req,"%2c",int id);    m_delete(requests,id); -  r->callback(r->domain,0,@r->args); +  r->callback && r->callback(r->domain,0,@r->args);    destruct(r);    } -  + }    -  + #define REMOVE_DELAY 120 + #define GIVE_UP_DELAY (RETRIES * RETRY_DELAY + REMOVE_DELAY)*2 +  + // FIXME: Randomized source port! + //! Asynchronous DNS client. + class async_client + { +  inherit client; +  inherit Stdio.UDP : udp; +  async_client next_client; +     void retry(object(Request) r, void|int nsno)    {    if(!r) return;
1909:    call_out(retry,RETRY_DELAY,r,nsno+1);    }    +  //! Enqueue a new raw DNS request.    //! -  void do_query(string domain, int cl, int type, +  //! @returns +  //! Returns a @[Request] object. +  //! +  //! @note +  //! Pike versions prior to 8.0 did not return the @[Request] object. +  Request do_query(string domain, int cl, int type,    function(string,mapping,mixed...:void) callback,    mixed ... args)    {
1925:    requests[lid]=r;    udp::send(nameservers[0],53,r->req);    call_out(retry,RETRY_DELAY,r,1); -  return; +  return r;    }    }   
1936:    if(!next_client)    next_client=this_program(nameservers,domains);    -  next_client->do_query(domain, cl, type, callback, @args); +  return next_client->do_query(domain, cl, type, callback, @args);    }       protected private void rec_data(mapping m)
1960:    }    }    -  protected private void generic_get(string d, +  protected private Request generic_get(string d,    mapping answer,    int multi,    int all,
1978:    callback(domain,0,@args);    } else {    // Multiple domain request. Try the next one... -  do_query(domain+"."+domains[multi], C_IN, type, +  return do_query(domain+"."+domains[multi], C_IN, type,    generic_get, ++multi, all, type, field, domain,    callback, @args);    }
1990:    if(an[field])    {    callback(domain, an[field], @args); -  return; +  return UNDEFINED;    }    callback(domain,0,@args); -  return; +     }    } -  +  return UNDEFINED;    }       //! -  void host_to_ip(string host, function callback, mixed ... args) +  Request host_to_ip(string host, function callback, mixed ... args)    {    if(sizeof(domains) && host[-1] != '.' && sizeof(host/".") < 3) { -  do_query(host, C_IN, T_A, +  return do_query(host, C_IN, T_A,    generic_get, 0, 0, T_A, "a", host, callback, @args );    } else { -  do_query(host, C_IN, T_A, +  return do_query(host, C_IN, T_A,    generic_get, -1, 0, T_A, "a",    host, callback, @args);    }    }       //! -  void ip_to_host(string ip, function callback, mixed ... args) +  Request ip_to_host(string ip, function callback, mixed ... args)    { -  do_query(arpa_from_ip(ip), C_IN, T_PTR, +  return do_query(arpa_from_ip(ip), C_IN, T_PTR,    generic_get, -1, 0, T_PTR, "ptr",    ip, callback,    @args);    }       //! -  void get_mx_all(string host, function callback, mixed ... args) +  Request get_mx_all(string host, function callback, mixed ... args)    {    if(sizeof(domains) && host[-1] != '.' && sizeof(host/".") < 3) { -  do_query(host, C_IN, T_MX, +  return do_query(host, C_IN, T_MX,    generic_get, 0, 1, T_MX, "mx", host, callback, @args);    } else { -  do_query(host, C_IN, T_MX, +  return do_query(host, C_IN, T_MX,    generic_get, -1, 1, T_MX, "mx", host, callback, @args);    }    }       //! -  void get_mx(string host, function callback, mixed ... args) +  Request get_mx(string host, function callback, mixed ... args)    { -  get_mx_all(host, +  return get_mx_all(host,    lambda(string domain, array(mapping) mx,    function callback, mixed ... args) {    array a;
2128:   {    inherit async_client;    -  class Request(string domain, string req, +  //! +  class Request +  { +  inherit ::this_program; +  +  protected Stdio.File sock; +  protected string writebuf="",readbuf=""; +  +  protected void create(string domain, string req,    function(string,mapping,mixed...:void) callback,    array(mixed) args)    { -  Stdio.File sock; -  string writebuf="",readbuf=""; -  -  void create() -  { +  ::create(domain, req, callback, args);    sock=Stdio.File();    sock->async_connect(nameservers[0], 53, connectedcb);    }    -  void connectedcb(int ok) +  protected void close()    { -  +  sock && sock->close(); +  sock = UNDEFINED; +  } +  +  protected 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) +  protected 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(); +  close();    }    }    -  void writecb() +  protected void writecb()    {    if (writebuf!="") writebuf=writebuf[sock->write(writebuf)..];    }    -  void closecb() +  protected void closecb()    { -  sock->close(); -  if (callback) callback(domain, 0, @args); -  callback=0; +  cancel();    } -  +  +  void cancel() +  { +  close(); +  ::cancel();    } -  +  }       //! -  void do_query(string domain, int cl, int type, +  Request 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); +  return Request(domain, req, callback, args);    }   }   
2215:    }       //! -  void do_query(string domain, int cl, int type, +  Request 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); +  return UDP::do_query(domain,cl,type,check_truncation, +  cl,type,callback,@args);    }       void create(mixed ... args) {::create(@args);}
2229:   async_client global_async_client;      #define GAC(X) \ - void async_##X( string host, function callback, mixed ... args ) \ + async_client.Request async_##X( string host, function callback, mixed ... args ) \   { \    if( !global_async_client ) \    global_async_client = async_client(); \ -  global_async_client->X(host,callback,@args); \ +  return global_async_client->X(host,callback,@args); \   }      //! @ignore