]> git.tdb.fi Git - libs/net.git/blob - source/net/resolve.h
212a7f0a47574068b1b7573acf973ef76cbbc5ca
[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 "sockaddr.h"
13
14 namespace Msp {
15 namespace Net {
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 = 0;
39                 std::string host;
40                 std::string serv;
41                 Family family = UNSPEC;
42                 std::unique_ptr<SockAddr> addr;
43                 std::unique_ptr<std::runtime_error> error;
44
45                 bool is_complete() const { return addr || error; }
46         };
47
48         class WorkerThread: public Thread
49         {
50         private:
51                 std::deque<Task> queue;
52                 Mutex queue_mutex;
53                 Semaphore sem;
54                 IO::Pipe notify_pipe;
55                 bool done = false;
56
57         public:
58                 WorkerThread();
59                 ~WorkerThread();
60
61                 void add_task(Task &&);
62                 Task *get_complete_task();
63                 void pop_complete_task();
64
65                 IO::Pipe &get_notify_pipe() { return notify_pipe; }
66
67         private:
68                 void main() override;
69         };
70
71 public:
72         sigc::signal<void, unsigned, const SockAddr &> signal_address_resolved;
73         sigc::signal<void, unsigned, const std::exception &> signal_resolve_failed;
74
75 private:
76         IO::EventDispatcher *event_disp = nullptr;
77         WorkerThread thread;
78         unsigned next_tag = 1;
79
80 public:
81         Resolver();
82
83         /** Sets the event dispatcher to use.  With no event dispatcher, tick() must
84         be called regularly to emit the completion signals. */
85         void use_event_dispatcher(IO::EventDispatcher *);
86
87         /** Resolves host and service names into a socket address.  Semantics are
88         the same as the namespace-scope resolve function. */
89         unsigned resolve(const std::string &, const std::string &, Family = UNSPEC);
90
91         unsigned resolve(const std::string &, Family = UNSPEC);
92
93         /** Checks for any completed tasks and emits the appropriate singals. */
94         void tick();
95
96 private:
97         void task_done();
98 };
99
100 } // namespace Net
101 } // namespace Msp
102
103 #endif