]> git.tdb.fi Git - libs/net.git/blobdiff - source/net/resolve.h
Implement an asynchronous name resolver class
[libs/net.git] / source / net / resolve.h
index 256455fcb18febb08384fd7e6f50e17d35064310..21737ff4794bb0def530bd364cae00a2291ec1c2 100644 (file)
@@ -2,6 +2,11 @@
 #define MSP_NET_RESOLVE_H_
 
 #include <string>
+#include <msp/core/mutex.h>
+#include <msp/core/semaphore.h>
+#include <msp/core/thread.h>
+#include <msp/io/eventdispatcher.h>
+#include <msp/io/pipe.h>
 #include "constants.h"
 
 namespace Msp {
@@ -20,6 +25,80 @@ separated by a colon.  If the host part contains colons, such as is the case
 with a numeric IPv6 address, it must be enclosed in brackets. */
 SockAddr *resolve(const std::string &, Family = UNSPEC);
 
+
+/**
+An asynchronous name resolver.  Blocking calls are performed in a thread and
+completion is notified with one of the two signals.
+*/
+class Resolver
+{
+private:
+       struct Task
+       {
+               unsigned tag;
+               std::string host;
+               std::string serv;
+               Family family;
+               SockAddr *addr;
+               std::runtime_error *error;
+
+               Task();
+
+               bool is_complete() const { return addr || error; }
+       };
+
+       class WorkerThread: public Thread
+       {
+       private:
+               std::list<Task> queue;
+               Mutex queue_mutex;
+               Semaphore sem;
+               IO::Pipe notify_pipe;
+               bool done;
+
+       public:
+               WorkerThread();
+               ~WorkerThread();
+
+               void add_task(const Task &);
+               Task *get_complete_task();
+               void pop_complete_task();
+
+               IO::Pipe &get_notify_pipe() { return notify_pipe; }
+
+       private:
+               virtual void main();
+       };
+
+public:
+       sigc::signal<void, unsigned, const SockAddr &> signal_address_resolved;
+       sigc::signal<void, unsigned, const std::exception &> signal_resolve_failed;
+
+private:
+       IO::EventDispatcher *event_disp;
+       WorkerThread thread;
+       unsigned next_tag;
+
+public:
+       Resolver();
+
+       /** Sets the event dispatcher to use.  With no event dispatcher, tick() must
+       be called regularly to emit the completion signals. */
+       void use_event_dispatcher(IO::EventDispatcher *);
+
+       /** Resolves host and service names into a socket address.  Semantics are
+       the same as the namespace-scope resolve function. */
+       unsigned resolve(const std::string &, const std::string &, Family = UNSPEC);
+
+       unsigned resolve(const std::string &, Family = UNSPEC);
+
+       /** Checks for any completed tasks and emits the appropriate singals. */
+       void tick();
+
+private:
+       void task_done();
+};
+
 } // namespace Net
 } // namespace Msp