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