Ray,
I see that dropping/delaying the requests is "todo", and I needed it for one of my experiments, so I wanted to share some experience of how I did it for your info and feedback.
I was able to get it working rather nicely by adding another bit flag called "defer" to the struct evldns_server_request, and another member called "queue" which is a function pointer with the signature like that of the evldns_server_udp_write_queue, and changing the signature of *_tcp_write_queue to match (and return always 0).
Then evldns_tcp_accept_callback or evldns_udp_read_callback can set the req->queue accordingly.
Also I added an early return from server_process_packet with -1 if the req->defer is set - which avoids any writes if the callback sets it.
Thus, the deferred reply code simply needs to set the req->defer and kick off the long activity with user ptr being the struct evldns_server_request pointer.
Upon the completion of that activity, the callback prepares the wire format by
doing ldns_pkt2wire() call that is otherwise done in server_process_packet, and then call the req->queue(req).
With this, I've quite easily implemented a prototype DNS64 A-filtering proxy based on static.c example and evdns clientside async resolver: for A requests, return 0 replies, for AAAA requests, kick off an async AAAA lookup for the target to upstream, upon completion of that either return the answer or if there are no AAAA records, kick off an A lookup - which, when completes can create a synthesized AAAA reply.
Based on this experience, a couple of things that might be worth doing differently/need further work:
-
create a couple of "wrapper queue" functions that would also prepare the on-the-wire format and put them into the req->queue rather than the existing ones
-
there is no way to do either deferred or immediate free of the req... The deferred free can be easily done by exposing the server_request_free(), but since it can not be done from within the callback, probably having another bitflag req->drop which is processed in the respective TCP/UDP routines, might be a viable option ?
--a
Ray,
I see that dropping/delaying the requests is "todo", and I needed it for one of my experiments, so I wanted to share some experience of how I did it for your info and feedback.
I was able to get it working rather nicely by adding another bit flag called "defer" to the struct evldns_server_request, and another member called "queue" which is a function pointer with the signature like that of the evldns_server_udp_write_queue, and changing the signature of *_tcp_write_queue to match (and return always 0).
Then evldns_tcp_accept_callback or evldns_udp_read_callback can set the req->queue accordingly.
Also I added an early return from server_process_packet with -1 if the req->defer is set - which avoids any writes if the callback sets it.
Thus, the deferred reply code simply needs to set the req->defer and kick off the long activity with user ptr being the struct evldns_server_request pointer.
Upon the completion of that activity, the callback prepares the wire format by
doing ldns_pkt2wire() call that is otherwise done in server_process_packet, and then call the req->queue(req).
With this, I've quite easily implemented a prototype DNS64 A-filtering proxy based on static.c example and evdns clientside async resolver: for A requests, return 0 replies, for AAAA requests, kick off an async AAAA lookup for the target to upstream, upon completion of that either return the answer or if there are no AAAA records, kick off an A lookup - which, when completes can create a synthesized AAAA reply.
Based on this experience, a couple of things that might be worth doing differently/need further work:
create a couple of "wrapper queue" functions that would also prepare the on-the-wire format and put them into the req->queue rather than the existing ones
there is no way to do either deferred or immediate free of the req... The deferred free can be easily done by exposing the server_request_free(), but since it can not be done from within the callback, probably having another bitflag req->drop which is processed in the respective TCP/UDP routines, might be a viable option ?
--a