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