X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fnet%2Fresolve.h;h=3071b771f569aa57f196c41cc4f8f9520c715130;hb=HEAD;hp=256455fcb18febb08384fd7e6f50e17d35064310;hpb=50e9f9ea7f7385a2c5931fca2b8fb1103078e67c;p=libs%2Fnet.git diff --git a/source/net/resolve.h b/source/net/resolve.h index 256455f..3071b77 100644 --- a/source/net/resolve.h +++ b/source/net/resolve.h @@ -1,24 +1,102 @@ #ifndef MSP_NET_RESOLVE_H_ #define MSP_NET_RESOLVE_H_ +#include +#include #include -#include "constants.h" +#include +#include +#include +#include +#include +#include "mspnet_api.h" +#include "sockaddr.h" namespace Msp { namespace Net { -class SockAddr; - /** Resolves host and service names into a socket address. If host is empty, the loopback address will be used. If host is "*", the wildcard address will be used. If service is empty, a socket address with a null service will be returned. With the IP families, these are not very useful. */ -SockAddr *resolve(const std::string &, const std::string &, Family = UNSPEC); +MSPNET_API SockAddr *resolve(const std::string &, const std::string &, Family = UNSPEC); /** And overload of resolve() that takes host and service as a single string, 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); +MSPNET_API 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 MSPNET_API Resolver +{ +private: + struct Task + { + unsigned tag = 0; + std::string host; + std::string serv; + Family family = UNSPEC; + std::unique_ptr addr; + std::unique_ptr error; + + bool is_complete() const { return addr || error; } + }; + + class WorkerThread: public Thread + { + private: + std::deque queue; + Mutex queue_mutex; + Semaphore sem; + IO::Pipe notify_pipe; + bool done = false; + + public: + WorkerThread(); + ~WorkerThread(); + + void add_task(Task &&); + Task *get_complete_task(); + void pop_complete_task(); + + IO::Pipe &get_notify_pipe() { return notify_pipe; } + + private: + void main() override; + }; + +public: + sigc::signal signal_address_resolved; + sigc::signal signal_resolve_failed; + +private: + IO::EventDispatcher *event_disp = nullptr; + WorkerThread thread; + unsigned next_tag = 1; + +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