1 /*
2  *  Copyright (C) 2014-2019 Savoir-faire Linux Inc.
3  *  Author(s) : Mingrui Zhang <mingrui.zhang@savoirfairelinux.com>
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 3 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program. If not, see <https://www.gnu.org/licenses/>.
17  */
18 
19 #pragma once
20 
21 #include "def.h"
22 #include "sockaddr.h"
23 #include "infohash.h"
24 
25 #include <thread>
26 #include <mutex>
27 #include <condition_variable>
28 
29 namespace dht {
30 
31 class OPENDHT_PUBLIC PeerDiscovery
32 {
33 public:
34     static constexpr in_port_t DEFAULT_PORT = 8888;
35     using ServiceDiscoveredCallback = std::function<void(msgpack::object&&, SockAddr&&)>;
36 
37     PeerDiscovery(in_port_t port = DEFAULT_PORT);
38     ~PeerDiscovery();
39 
40     /**
41      * startDiscovery - Keep Listening data from the sender until node is joinned or stop is called
42     */
43     void startDiscovery(const std::string &type, ServiceDiscoveredCallback callback);
44 
45     template<typename T>
startDiscovery(const std::string & type,std::function<void (T &&,SockAddr &&)> cb)46     void startDiscovery(const std::string &type, std::function<void(T&&, SockAddr&&)> cb) {
47         startDiscovery(type, [cb](msgpack::object&& ob, SockAddr&& addr) {
48             cb(ob.as<T>(), std::move(addr));
49         });
50     }
51 
52     /**
53      * startPublish - Keeping sending data until node is joinned or stop is called - msgpack
54     */
55     void startPublish(const std::string &type, const msgpack::sbuffer &pack_buf);
56     void startPublish(sa_family_t domain, const std::string &type, const msgpack::sbuffer &pack_buf);
57 
58     template<typename T>
startPublish(const std::string & type,const T & object)59     void startPublish(const std::string &type, const T& object) {
60         msgpack::sbuffer buf;
61         msgpack::pack(buf, object);
62         startPublish(type, buf);
63     }
64 
65     /**
66      * Thread Stopper
67     */
68     void stop();
69 
70     /**
71      * Remove possible callBack to discovery
72     */
73     bool stopDiscovery(const std::string &type);
74 
75     /**
76      * Remove different serivce message to send
77     */
78     bool stopPublish(const std::string &type);
79     bool stopPublish(sa_family_t domain, const std::string &type);
80 
81     /**
82      * Configure the sockopt to be able to listen multicast group
83     */
84     static void socketJoinMulticast(int sockfd, sa_family_t family);
85 
86     /**
87      * Join the threads
88     */
89     void join();
90 
91 private:
92     class DomainPeerDiscovery;
93     std::unique_ptr<DomainPeerDiscovery> peerDiscovery4_;
94     std::unique_ptr<DomainPeerDiscovery> peerDiscovery6_;
95 };
96 
97 }
98