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