1 /* 2 * Copyright (C) 2001-2012 Jacek Sieka, arnetheduck on gmail point com 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 "TimerManager.h" 22 #include "UserConnection.h" 23 #include "User.h" 24 #include "CriticalSection.h" 25 #include "Singleton.h" 26 #include "Util.h" 27 #include "ConnectionManagerListener.h" 28 29 namespace dcpp { 30 31 class SocketException; 32 33 class ConnectionQueueItem : boost::noncopyable { 34 public: 35 typedef ConnectionQueueItem* Ptr; 36 typedef vector<Ptr> List; 37 typedef List::iterator Iter; 38 39 enum State { 40 CONNECTING, // Recently sent request to connect 41 WAITING, // Waiting to send request to connect 42 NO_DOWNLOAD_SLOTS, // Not needed right now 43 ACTIVE // In one up/downmanager 44 }; 45 ConnectionQueueItem(const HintedUser & aUser,bool aDownload)46 ConnectionQueueItem(const HintedUser& aUser, bool aDownload) : token(Util::toString(Util::rand())), 47 lastAttempt(0), errors(0), state(WAITING), download(aDownload), user(aUser) { } 48 49 GETSET(string, token, Token); 50 GETSET(uint64_t, lastAttempt, LastAttempt); 51 GETSET(int, errors, Errors); // Number of connection errors, or -1 after a protocol error 52 GETSET(State, state, State); 53 GETSET(bool, download, Download); 54 getUser()55 const HintedUser& getUser() const { return user; } 56 57 private: 58 HintedUser user; 59 }; 60 61 class ExpectedMap { 62 public: add(const string & aNick,const string & aMyNick,const string & aHubUrl)63 void add(const string& aNick, const string& aMyNick, const string& aHubUrl) { 64 Lock l(cs); 65 expectedConnections.insert(make_pair(aNick, make_pair(aMyNick, aHubUrl))); 66 } 67 remove(const string & aNick)68 StringPair remove(const string& aNick) { 69 Lock l(cs); 70 auto i = expectedConnections.find(aNick); 71 72 if(i == expectedConnections.end()) 73 return make_pair(Util::emptyString, Util::emptyString); 74 75 StringPair tmp = i->second; 76 expectedConnections.erase(i); 77 78 return tmp; 79 } 80 81 private: 82 /** Nick -> myNick, hubUrl for expected NMDC incoming connections */ 83 typedef map<string, StringPair> ExpectMap; 84 ExpectMap expectedConnections; 85 86 CriticalSection cs; 87 }; 88 89 // Comparing with a user... 90 inline bool operator==(ConnectionQueueItem::Ptr ptr, const UserPtr& aUser) { return ptr->getUser() == aUser; } 91 92 class ConnectionManager : public Speaker<ConnectionManagerListener>, 93 public UserConnectionListener, TimerManagerListener, 94 public Singleton<ConnectionManager> 95 { 96 public: nmdcExpect(const string & aNick,const string & aMyNick,const string & aHubUrl)97 void nmdcExpect(const string& aNick, const string& aMyNick, const string& aHubUrl) { 98 expectedConnections.add(aNick, aMyNick, aHubUrl); 99 } 100 101 void nmdcConnect(const string& aServer, uint16_t aPort, const string& aMyNick, const string& hubUrl, const string& encoding, bool secure); 102 void nmdcConnect(const string& aServer, uint16_t aPort, uint16_t localPort, BufferedSocket::NatRoles natRole, const string& aNick, const string& hubUrl, const string& encoding, bool secure); 103 void adcConnect(const OnlineUser& aUser, uint16_t aPort, const string& aToken, bool secure); 104 void adcConnect(const OnlineUser& aUser, uint16_t aPort, uint16_t localPort, BufferedSocket::NatRoles natRole, const string& aToken, bool secure); 105 106 void getDownloadConnection(const HintedUser& aUser); 107 void force(const UserPtr& aUser); 108 109 void disconnect(const UserPtr& aUser); // disconnect downloads and uploads 110 void disconnect(const UserPtr& aUser, int isDownload); 111 112 void shutdown(); 113 114 /** Find a suitable port to listen on, and start doing it */ 115 void listen(); 116 void disconnect() noexcept; 117 getPort()118 uint16_t getPort() { return server ? static_cast<uint16_t>(server->getPort()) : 0; } getSecurePort()119 uint16_t getSecurePort() { return secureServer ? static_cast<uint16_t>(secureServer->getPort()) : 0; } 120 121 void addCTM2HUB(const string &server, const string &port); 122 123 private: 124 125 unordered_set<string> ddosctm2hub; 126 127 class Server : public Thread { 128 public: 129 Server(bool secure_, uint16_t port, const string& ip = "0.0.0.0"); getPort()130 uint16_t getPort() { return port; } ~Server()131 virtual ~Server() { die = true; join(); } 132 private: 133 virtual int run() noexcept; 134 135 Socket sock; 136 uint16_t port; 137 string ip; 138 bool secure; 139 bool die; 140 }; 141 142 friend class Server; 143 144 CriticalSection cs; 145 146 /** All ConnectionQueueItems */ 147 ConnectionQueueItem::List downloads; 148 ConnectionQueueItem::List uploads; 149 150 /** All active connections */ 151 UserConnectionList userConnections; 152 153 StringList features; 154 StringList adcFeatures; 155 156 ExpectedMap expectedConnections; 157 158 uint32_t floodCounter; 159 160 Server* server; 161 Server* secureServer; 162 163 bool shuttingDown; 164 165 friend class Singleton<ConnectionManager>; 166 ConnectionManager(); 167 ~ConnectionManager()168 virtual ~ConnectionManager() { shutdown(); } 169 170 UserConnection* getConnection(bool aNmdc, bool secure) noexcept; 171 void putConnection(UserConnection* aConn); 172 173 void addUploadConnection(UserConnection* uc); 174 void addDownloadConnection(UserConnection* uc); 175 176 ConnectionQueueItem* getCQI(const HintedUser& aUser, bool download); 177 void putCQI(ConnectionQueueItem* cqi); 178 179 bool checkKeyprint(UserConnection *aSource); 180 181 void accept(const Socket& sock, bool secure) noexcept; 182 183 void failed(UserConnection* aSource, const string& aError, bool protocolError); 184 185 // UserConnectionListener 186 virtual void on(Connected, UserConnection*) noexcept; 187 virtual void on(Failed, UserConnection*, const string&) noexcept; 188 virtual void on(ProtocolError, UserConnection*, const string&) noexcept; 189 virtual void on(CLock, UserConnection*, const string&, const string&) noexcept; 190 virtual void on(Key, UserConnection*, const string&) noexcept; 191 virtual void on(Direction, UserConnection*, const string&, const string&) noexcept; 192 virtual void on(MyNick, UserConnection*, const string&) noexcept; 193 virtual void on(Supports, UserConnection*, const StringList&) noexcept; 194 195 virtual void on(AdcCommand::SUP, UserConnection*, const AdcCommand&) noexcept; 196 virtual void on(AdcCommand::INF, UserConnection*, const AdcCommand&) noexcept; 197 virtual void on(AdcCommand::STA, UserConnection*, const AdcCommand&) noexcept; 198 199 // TimerManagerListener 200 virtual void on(TimerManagerListener::Second, uint64_t aTick) noexcept; 201 virtual void on(TimerManagerListener::Minute, uint64_t aTick) noexcept; 202 203 }; 204 205 } // namespace dcpp 206