diff --git a/include/dnscpp.h b/include/dnscpp.h index 908cfba..9b13ebd 100644 --- a/include/dnscpp.h +++ b/include/dnscpp.h @@ -37,3 +37,4 @@ #include #include #include +#include diff --git a/include/dnscpp/callbacks.h b/include/dnscpp/callbacks.h new file mode 100644 index 0000000..6dd3c41 --- /dev/null +++ b/include/dnscpp/callbacks.h @@ -0,0 +1,114 @@ +/** + * Callbacks.h + * + * Type definition of the callbacks + * + * @author Emiel Bruijntjes + * @copyright 2020 Copernica BV + */ + +/** + * Include guard + */ +#pragma once + +/** + * Dependencies + */ +#include +#include "handler.h" + +/** + * Begin of namespace + */ +namespace DNS { + +/** + * Forward declarations + */ +class Response; +class Operation; + +/** + * The callback-type used for the callback-based query() methods + * @type function + */ +using SuccessCallback = std::function; +using FailureCallback = std::function; + +/** + * Utility class to turn callbacks into a handler + */ +class Callbacks : public Handler +{ +private: + /** + * The success callback + * @var SuccessCallback + */ + SuccessCallback _success; + + /** + * The failure callback + * @var FailureCallback + */ + FailureCallback _failure; + + + /** + * Method that is called when a valid, successful, response was received. + * @param operation the operation that finished + * @param response the received response + */ + virtual void onResolved(const Operation *operation, const Response &response) override + { + // call to user-space + _success(operation, response); + + // self-destruct + delete this; + } + + /** + * Method that is called when a query could not be processed or answered. + * @param operation the operation that finished + * @param rcode the received rcode + */ + virtual void onFailure(const Operation *operation, int rcode) override + { + // call to user-space + _failure(operation, rcode); + + // self-destruct + delete this; + } + + /** + * Method that is called when the operation is cancelled + * @param operation the operation that was cancelled + */ + virtual void onCancelled(const Operation *operation) override + { + // self-destruct + delete this; + } + + /** + * Private destructor (object is self-destructing) + */ + virtual ~Callbacks() = default; + +public: + /** + * Constructor + * @param success the success-callback + * @param failure the failure-callback + */ + Callbacks(const SuccessCallback &success, const FailureCallback &failure) : + _success(success), _failure(failure) {} +}; + +/** + * End of namespace + */ +} diff --git a/include/dnscpp/context.h b/include/dnscpp/context.h index 259a0a7..c4d4267 100644 --- a/include/dnscpp/context.h +++ b/include/dnscpp/context.h @@ -18,7 +18,7 @@ #include #include "type.h" #include "core.h" -#include "reverse.h" +#include "callbacks.h" /** * Begin of namespace @@ -98,7 +98,7 @@ class Context : private Core } /** - * Do a dns lookup + * Do a dns lookup and pass the result to a user-space handler object * When you supply invalid parameters (for example a syntactivally invalid * domain or an unsupported type) this method returns null. * @param name the record name to look for @@ -115,6 +115,26 @@ class Context : private Core * @return operation object to interact with the operation while it is in progress */ Operation *query(const Ip &ip, Handler *handler); + + /** + * Do a dns lookup and pass the result to callbacks + * @param name the record name to look for + * @param type type of record (normally you ask for an 'a' record) + * @param success function that will be called on success + * @param failure function that will be called on failure + * @return operation object to interact with the operation while it is in progress + */ + Operation *query(const char *domain, ns_type type, const SuccessCallback &success, const FailureCallback &failure); + + /** + * Do a reverse dns lookup and pass the result to callbacks + * @param ip the ip address to lookup + * @param success function that will be called on success + * @param failure function that will be called on failure + * @return operation object to interact with the operation while it is in progress + */ + Operation *query(const DNS::Ip &ip, const SuccessCallback &success, const FailureCallback &failure); + }; /** diff --git a/include/dnscpp/handler.h b/include/dnscpp/handler.h index 19e6056..d169cce 100644 --- a/include/dnscpp/handler.h +++ b/include/dnscpp/handler.h @@ -55,7 +55,7 @@ class Handler * @param operation the operation that finished * @param rcode the received rcode */ - virtual void onFailure(const Operation *operation, int rrcode) {} + virtual void onFailure(const Operation *operation, int rcode) {} /** * Method that is called when an operation times out. @@ -80,6 +80,14 @@ class Handler * @param response the received response */ virtual void onReceived(const Operation *operation, const Response &response); + + /** + * Method that is called when the operation is cancelled + * This method is immediately triggered when operation->cancel() is called. + * + * @param operation the operation that was cancelled + */ + virtual void onCancelled(const Operation *operation) {} }; /** diff --git a/src/context.cpp b/src/context.cpp index 97edbee..0f49265 100644 --- a/src/context.cpp +++ b/src/context.cpp @@ -60,6 +60,32 @@ Operation *Context::query(const Ip &ip, Handler *handler) return query(Reverse(ip), TYPE_PTR, handler); } +/** + * Do a dns lookup and pass the result to callbacks + * @param name the record name to look for + * @param type type of record (normally you ask for an 'a' record) + * @param success function that will be called on success + * @param failure function that will be called on failure + * @return operation object to interact with the operation while it is in progress + */ +Operation *Context::query(const char *domain, ns_type type, const SuccessCallback &success, const FailureCallback &failure) +{ + // use a self-destructing wrapper for the handler + return query(domain, type, new Callbacks(success, failure)); +} + +/** + * Do a reverse dns lookup and pass the result to callbacks + * @param ip the ip address to lookup + * @param success function that will be called on success + * @param failure function that will be called on failure + * @return operation object to interact with the operation while it is in progress + */ +Operation *Context::query(const DNS::Ip &ip, const SuccessCallback &success, const FailureCallback &failure) +{ + // use a self-destructing wrapper for the handler + return query(ip, new Callbacks(success, failure)); +} /** * End of namespace diff --git a/src/locallookup.h b/src/locallookup.h index 173e36b..21a1f4c 100644 --- a/src/locallookup.h +++ b/src/locallookup.h @@ -17,6 +17,7 @@ */ #include "../include/dnscpp/request.h" #include "../include/dnscpp/question.h" +#include "../include/dnscpp/reverse.h" /** * Begin of namespace @@ -74,6 +75,10 @@ class LocalLookup : public Operation, private Timer // stop the timer _loop->cancel(_timer, this); + + // if the operation is destructed while the timer was still running, it means that the + // operation was prematurely cancelled from user-space, let the handler know + _handler->onCancelled(this); } public: diff --git a/src/remotelookup.cpp b/src/remotelookup.cpp index 7f669ba..d7d1652 100644 --- a/src/remotelookup.cpp +++ b/src/remotelookup.cpp @@ -53,6 +53,10 @@ RemoteLookup::~RemoteLookup() // but if userspace decided to kill the job (by calling job->cancel()) we still // have to do some cleaning ourselves cleanup(); + + // if the operation is destructed while the timer was still running, it means that the + // operation was prematurely cancelled from user-space, let the handler know + _handler->onCancelled(this); } /**