Implement an asynchronous name resolver class
[libs/net.git] / source / net / resolve.h
1 #ifndef MSP_NET_RESOLVE_H_
2 #define MSP_NET_RESOLVE_H_
3
4 #include <string>
5 #include <msp/core/mutex.h>
6 #include <msp/core/semaphore.h>
7 #include <msp/core/thread.h>
8 #include <msp/io/eventdispatcher.h>
9 #include <msp/io/pipe.h>
10 #include "constants.h"
11
12 namespace Msp {
13 namespace Net {
14
15 class SockAddr;
16
17 /** Resolves host and service names into a socket address.  If host is empty,
18 the loopback address will be used.  If host is "*", the wildcard address will
19 be used.  If service is empty, a socket address with a null service will be
20 returned.  With the IP families, these are not very useful. */
21 SockAddr *resolve(const std::string &, const std::string &, Family = UNSPEC);
22
23 /** And overload of resolve() that takes host and service as a single string,
24 separated by a colon.  If the host part contains colons, such as is the case
25 with a numeric IPv6 address, it must be enclosed in brackets. */
26 SockAddr *resolve(const std::string &, Family = UNSPEC);
27
28
29 /**
30 An asynchronous name resolver.  Blocking calls are performed in a thread and
31 completion is notified with one of the two signals.
32 */
33 class Resolver
34 {
35 private:
36         struct Task
37         {
38                 unsigned tag;
39                 std::string host;
40                 std::string serv;
41                 Family family;
42                 SockAddr *addr;
43                 std::runtime_error *error;
44
45                 Task();
46
47                 bool is_complete() const { return addr || error; }
48         };
49
50         class WorkerThread: public Thread
51         {
52         private:
53                 std::list<Task> queue;
54                 Mutex queue_mutex;
55                 Semaphore sem;
56                 IO::Pipe notify_pipe;
57                 bool done;
58
59         public:
60                 WorkerThread();
61                 ~WorkerThread();
62
63                 void add_task(const Task &);
64                 Task *get_complete_task();
65                 void pop_complete_task();
66
67                 IO::Pipe &get_notify_pipe() { return notify_pipe; }
68
69         private:
70                 virtual void main();
71         };
72
73 public:
74         sigc::signal<void, unsigned, const SockAddr &> signal_address_resolved;
75         sigc::signal<void, unsigned, const std::exception &> signal_resolve_failed;
76
77 private:
78         IO::EventDispatcher *event_disp;
79         WorkerThread thread;
80         unsigned next_tag;
81
82 public:
83         Resolver();
84
85         /** Sets the event dispatcher to use.  With no event dispatcher, tick() must
86         be called regularly to emit the completion signals. */
87         void use_event_dispatcher(IO::EventDispatcher *);
88
89         /** Resolves host and service names into a socket address.  Semantics are
90         the same as the namespace-scope resolve function. */
91         unsigned resolve(const std::string &, const std::string &, Family = UNSPEC);
92
93         unsigned resolve(const std::string &, Family = UNSPEC);
94
95         /** Checks for any completed tasks and emits the appropriate singals. */
96         void tick();
97
98 private:
99         void task_done();
100 };
101
102 } // namespace Net
103 } // namespace Msp
104
105 #endif