1 /*
2  * Copyright (C) 2009-2010 Big Muscle, http://strongdc.sf.net
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17  */
18 
19 #pragma once
20 
21 #include "BootstrapManager.h"
22 #include "Constants.h"
23 #include "KBucket.h"
24 #include "UDPSocket.h"
25 #include "stdafx.h"
26 #include "dcpp/AdcCommand.h"
27 #include "dcpp/CID.h"
28 #include "dcpp/MerkleTree.h"
29 #include "dcpp/Singleton.h"
30 #include "dcpp/TimerManager.h"
31 
32 namespace dht
33 {
34 
35     class DHT :
36         public Singleton<DHT>, public Speaker<ClientListener>, public ClientBase
37     {
38     public:
39         DHT(void);
40         ~DHT(void) throw();
41 
42         enum InfType { NONE = 0, PING = 1, MAKE_ONLINE = 2 };
43 
44         /** ClientBase derived functions */
getHubUrl()45         const string& getHubUrl() const { return NetworkName; }
getHubName()46         string getHubName() const { return NetworkName; }
isOp()47         bool isOp() const { return false; }
48 
49         /** Starts DHT. */
50         void start();
51         void stop(bool exiting = false);
52 
getPort()53         uint16_t getPort() const { return BOOLSETTING(USE_DHT) ? socket.getPort() : 0; }
54 
55         /** Process incoming command */
56         void dispatch(const string& aLine, const string& ip, uint16_t port, bool isUdpKeyValid);
57 
58         /** Sends command to ip and port */
59         void send(AdcCommand& cmd, const string& ip, uint16_t port, const CID& targetCID, const CID& udpKey);
60 
61         /** Creates new (or update existing) node which is NOT added to our routing table */
62         Node::Ptr createNode(const CID& cid, const string& ip, uint16_t port, bool update, bool isUdpKeyValid);
63 
64         /** Adds node to routing table */
65         bool addNode(const Node::Ptr& node, bool makeOnline);
66 
67         /** Returns counts of nodes available in k-buckets */
getNodesCount()68         size_t getNodesCount() { Lock l(cs); return bucket->getNodes().size(); }
69 
70         /** Removes dead nodes */
71         void checkExpiration(uint64_t aTick);
72 
73         /** Finds the file in the network */
74         void findFile(const string& tth, const string& token = Util::toString(Util::rand()));
75 
76         /** Sends our info to specified ip:port */
77         void info(const string& ip, uint16_t port, uint32_t type, const CID& targetCID, const CID& udpKey);
78 
79         /** Sends Connect To Me request to online node */
80         void connect(const OnlineUser& ou, const string& token);
81 
82         /** Sends private message to online node */
83         void privateMessage(const OnlineUser& ou, const string& aMessage, bool thirdPerson);
84 
85         /** Is DHT connected? */
isConnected()86         bool isConnected() const { return lastPacket && (GET_TICK() - lastPacket < CONNECTED_TIMEOUT); }
87 
88         /** Mark that network data should be saved */
setDirty()89         void setDirty() { dirty = true; }
90 
91         /** Saves network information to XML file */
92         void saveData();
93 
94         /** Returns if our UDP port is open */
isFirewalled()95         bool isFirewalled() const { return firewalled; }
96 
97         /** Returns our IP got from the last firewall check */
getLastExternalIP()98         string getLastExternalIP() const { return lastExternalIP; }
99 
setRequestFWCheck()100         void setRequestFWCheck() { Lock l(cs); requestFWCheck = true; firewalledWanted.clear(); firewalledChecks.clear(); }
101 
102     private:
103         /** Classes that can access to my private members */
104         friend class Singleton<DHT>;
105         friend class SearchManager;
106 
107         void handle(AdcCommand::INF, const Node::Ptr& node, AdcCommand& c) throw(); // user's info
108         void handle(AdcCommand::SCH, const Node::Ptr& node, AdcCommand& c) throw(); // incoming search request
109         void handle(AdcCommand::RES, const Node::Ptr& node, AdcCommand& c) throw(); // incoming search result
110         void handle(AdcCommand::PUB, const Node::Ptr& node, AdcCommand& c) throw(); // incoming publish request
111         void handle(AdcCommand::CTM, const Node::Ptr& node, AdcCommand& c) throw(); // connection request
112         void handle(AdcCommand::RCM, const Node::Ptr& node, AdcCommand& c) throw(); // reverse connection request
113         void handle(AdcCommand::STA, const Node::Ptr& node, AdcCommand& c) throw(); // status message
114         void handle(AdcCommand::PSR, const Node::Ptr& node, AdcCommand& c) throw(); // partial file request
115         void handle(AdcCommand::MSG, const Node::Ptr& node, AdcCommand& c) throw(); // private message
116         void handle(AdcCommand::GET, const Node::Ptr& node, AdcCommand& c) throw();
117         void handle(AdcCommand::SND, const Node::Ptr& node, AdcCommand& c) throw();
118 
119         /** Unsupported command */
handle(T,const Node::Ptr & user,AdcCommand &)120         template<typename T> void handle(T, const Node::Ptr&user, AdcCommand&) { }
121 
122         /** UDP socket */
123         UDPSocket   socket;
124 
125         /** Routing table */
126         KBucket*    bucket;
127 
128         /** Lock to routing table */
129         CriticalSection cs;
130         CriticalSection fwCheckCs;
131 
132         /** Our external IP got from last firewalled check */
133         string lastExternalIP;
134 
135         /** Time when last packet was received */
136         uint64_t lastPacket;
137 
138         /** IPs who we received firewalled status from */
139         std::unordered_set<string> firewalledWanted;
140         std::unordered_map< string, std::pair< string, uint16_t > > firewalledChecks;
141         bool firewalled;
142         bool requestFWCheck;
143 
144         /** Should the network data be saved? */
145         bool dirty;
146 
147         /** Finds "max" closest nodes and stores them to the list */
148         void getClosestNodes(const CID& cid, std::map<CID, Node::Ptr>& closest, unsigned int max, uint8_t maxType);
149 
150         /** Loads network information from XML file */
151         void loadData();
152     };
153 
154 }
155