]> git.tdb.fi Git - libs/net.git/blob - source/net/resolve.h
ae0411bd807c5e37292e0fd76f75e1fd34f9d94d
[libs/net.git] / source / net / resolve.h
1 #ifndef MSP_NET_RESOLVE_H_
2 #define MSP_NET_RESOLVE_H_
3
4 #include <deque>
5 #include <memory>
6 #include <string>
7 #include <msp/core/mutex.h>
8 #include <msp/core/semaphore.h>
9 #include <msp/core/thread.h>
10 #include <msp/io/eventdispatcher.h>
11 #include <msp/io/pipe.h>
12 #include "constants.h"
13
14 namespace Msp {
15 namespace Net {
16
17 class SockAddr;
18
19 /** Resolves host and service names into a socket address.  If host is empty,
20 the loopback address will be used.  If host is "*", the wildcard address will
21 be used.  If service is empty, a socket address with a null service will be
22 returned.  With the IP families, these are not very useful. */
23 SockAddr *resolve(const std::string &, const std::string &, Family = UNSPEC);
24
25 /** And overload of resolve() that takes host and service as a single string,
26 separated by a colon.  If the host part contains colons, such as is the case
27 with a numeric IPv6 address, it must be enclosed in brackets. */
28 SockAddr *resolve(const std::string &, Family = UNSPEC);
29
30
31 /**
32 An asynchronous name resolver.  Blocking calls are performed in a thread and
33 completion is notified with one of the two signals.
34 */
35 class Resolver
36 {
37 private:
38         struct Task
39         {
40                 unsigned tag = 0;
41                 std::string host;
42                 std::string serv;
43                 Family family = UNSPEC;
44                 std::unique_ptr<SockAddr> addr;
45                 std::unique_ptr<std::runtime_error> error;
46
47                 bool is_complete() const { return addr || error; }
48         };
49
50         class WorkerThread: public Thread
51         {
52         private:
53                 std::deque<Task> queue;
54                 Mutex queue_mutex;
55                 Semaphore sem;
56                 IO::Pipe notify_pipe;
57                 bool done = false;
58
59         public:
60                 WorkerThread();
61                 ~WorkerThread();
62
63                 void add_task(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                 void main() override;
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 = nullptr;
79         WorkerThread thread;
80         unsigned next_tag = 1;
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