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 "compiler.h"
22 #include "forward.h"
23 #include "User.h"
24 #include "Speaker.h"
25 #include "BufferedSocketListener.h"
26 #include "TimerManager.h"
27 #include "ClientListener.h"
28 #include "Atomic.h"
29 #include "SearchQueue.h"
30 
31 #ifdef LUA_SCRIPT
32 #include "ScriptManager.h"
33 #endif
34 
35 namespace dcpp {
36 #ifdef LUA_SCRIPT
37     struct ClientScriptInstance : public ScriptInstance {
38     bool onHubFrameEnter(Client* aClient, const string& aLine);
39     string formatChatMessage(const string& aLine);
40 };
41 #endif
42 class ClientBase
43 {
44 public:
45 
ClientBase()46     ClientBase() : type(DIRECT_CONNECT) { }
47 
48     enum P2PType { DIRECT_CONNECT, DHT };
49     P2PType type;
getType()50     P2PType getType() const { return type; }
51     virtual const string& getHubUrl() const = 0;
52     virtual string getHubName() const = 0;
53     virtual bool isOp() const = 0;
54     virtual void connect(const OnlineUser& user, const string& token) = 0;
55     virtual void privateMessage(const OnlineUser& user, const string& aMessage, bool thirdPerson = false) = 0;
56 
57 };
58 /** Yes, this should probably be called a Hub */
59 class Client : public ClientBase, public Speaker<ClientListener>, public BufferedSocketListener, protected TimerManagerListener
60 #ifdef LUA_SCRIPT
61 , public ClientScriptInstance
62 #endif
63 {
64 public:
65     typedef Client* Ptr;
66     typedef list<Ptr> List;
67     typedef List::iterator Iter;
68 
69     virtual void connect();
70     virtual void disconnect(bool graceless);
71 
72     virtual void connect(const OnlineUser& user, const string& token) = 0;
73     virtual void hubMessage(const string& aMessage, bool thirdPerson = false) = 0;
74     virtual void privateMessage(const OnlineUser& user, const string& aMessage, bool thirdPerson = false) = 0;
75     virtual void sendUserCmd(const UserCommand& command, const StringMap& params) = 0;
76 
77     uint64_t search(int aSizeMode, int64_t aSize, int aFileType, const string& aString, const string& aToken, const StringList& aExtList, void* owner);
cancelSearch(void * aOwner)78     void cancelSearch(void* aOwner) { searchQueue.cancelSearch(aOwner); }
79 
80     virtual void password(const string& pwd) = 0;
81     virtual void info(bool force) = 0;
82 
83     virtual size_t getUserCount() const = 0;
84     virtual int64_t getAvailable() const = 0;
getTotalCounts()85     static int getTotalCounts() { return counts.normal + counts.registered + counts.op; }
86     virtual void send(const AdcCommand& command) = 0;
87 
escape(string const & str)88     virtual string escape(string const& str) const { return str; }
89 
isConnected()90     bool isConnected() const { return state != STATE_DISCONNECTED; }
isReady()91     bool isReady() const { return state != STATE_CONNECTING && state != STATE_DISCONNECTED; }
92     bool isSecure() const;
93     bool isTrusted() const;
94     std::string getCipherName() const;
95     vector<uint8_t> getKeyprint() const;
96 
isOp()97     bool isOp() const { return getMyIdentity().isOp(); }
98 
getPort()99     uint16_t getPort() const { return port; }
getAddress()100     const string& getAddress() const { return address; }
101 
getIp()102     const string& getIp() const { return ip; }
getIpPort()103     string getIpPort() const { return getIp() + ':' + Util::toString(port); }
104     string getLocalIp() const;
105 
updated(const OnlineUser & aUser)106     void updated(const OnlineUser& aUser) { fire(ClientListener::UserUpdated(), this, aUser); }
107 
getCounts()108     static string getCounts() {
109         char buf[128];
110         return string(buf, snprintf(buf, sizeof(buf), "%ld/%ld/%ld",
111             static_cast<long>(counts.normal),
112             static_cast<long>(counts.registered),
113             static_cast<long>(counts.op)));
114     }
115 
escapeParams(StringMap & sm)116     StringMap& escapeParams(StringMap& sm) {
117         for(StringMapIter i = sm.begin(); i != sm.end(); ++i) {
118             i->second = escape(i->second);
119         }
120         return sm;
121     }
setSearchInterval(uint32_t aInterval)122     void setSearchInterval(uint32_t aInterval) {
123         searchQueue.interval = (aInterval + min(aInterval, (uint32_t)1)) * (uint32_t)1000;
124     }
125 
getSearchInterval()126     uint32_t getSearchInterval() const {
127         return searchQueue.interval;
128     }
129 
130     void reconnect();
131     void shutdown();
132     bool isActive() const;
send(const string & aMessage)133     void send(const string& aMessage) { send(aMessage.c_str(), aMessage.length()); }
134     void send(const char* aMessage, size_t aLen);
135 
getMyNick()136     string getMyNick() const { return getMyIdentity().getNick(); }
getHubName()137     string getHubName() const { return getHubIdentity().getNick().empty() ? getHubUrl() : getHubIdentity().getNick(); }
getHubDescription()138     string getHubDescription() const { return getHubIdentity().getDescription(); }
139 
getHubIdentity()140     Identity& getHubIdentity() { return hubIdentity; }
141 
getHubUrl()142     const string& getHubUrl() const { return hubUrl; }
143 
144     GETSET(Identity, myIdentity, MyIdentity);
145     GETSET(Identity, hubIdentity, HubIdentity);
146 
147     GETSET(string, defpassword, Password);
148     GETSET(uint32_t, reconnDelay, ReconnDelay);
149     GETSET(uint64_t, lastActivity, LastActivity);
150     GETSET(bool, registered, Registered);
151     GETSET(bool, autoReconnect, AutoReconnect);
152     GETSET(string, encoding, Encoding);
153     GETSET(string, clientId, ClientId);
154     GETSET(string, currentNick, CurrentNick);
155     GETSET(string, currentDescription, CurrentDescription);
156 
getFavIp()157     string getFavIp() const { return externalIP; }
158 
159     /** Reload details from favmanager or settings */
160     void reloadSettings(bool updateNick);
161 protected:
162     friend class ClientManager;
163     Client(const string& hubURL, char separator, bool secure_);
164     virtual ~Client();
165     struct Counts {
166         private:
167             typedef Atomic<boost::int32_t> atomic_counter_t;
168         public:
169             typedef boost::int32_t value_type;
normalCounts170             Counts(value_type n = 0, value_type r = 0, value_type o = 0) : normal(n), registered(r), op(o) { }
171             atomic_counter_t normal;
172             atomic_counter_t registered;
173             atomic_counter_t op;
174     };
175 
176     enum States {
177         STATE_CONNECTING,   ///< Waiting for socket to connect
178         STATE_PROTOCOL,     ///< Protocol setup
179         STATE_IDENTIFY,     ///< Nick setup
180         STATE_VERIFY,       ///< Checking password
181         STATE_NORMAL,       ///< Running
182         STATE_DISCONNECTED  ///< Nothing in particular
183     } state;
184     SearchQueue searchQueue;
185     BufferedSocket* sock;
186 
187     static Counts counts;
188     Counts lastCounts;
189 
190     void updateCounts(bool aRemove);
updateActivity()191     void updateActivity() { lastActivity = GET_TICK(); }
192 
193     virtual string checkNick(const string& nick) = 0;
194     virtual void search(int aSizeMode, int64_t aSize, int aFileType, const string& aString, const string& aToken, const StringList& aExtList) = 0;
195 
196     // TimerManagerListener
197     virtual void on(Second, uint64_t aTick) noexcept;
198     // BufferedSocketListener
on(Connecting)199     virtual void on(Connecting) noexcept { fire(ClientListener::Connecting(), this); }
200     virtual void on(Connected) noexcept;
201     virtual void on(Line, const string& aLine) noexcept;
202     virtual void on(Failed, const string&) noexcept;
203 
204 private:
205 
206     enum CountType {
207         COUNT_UNCOUNTED,
208         COUNT_NORMAL,
209         COUNT_REGISTERED,
210         COUNT_OP
211     };
212 
213     Client(const Client&);
214     Client& operator=(const Client&);
215 
216     string hubUrl;
217     string address;
218     string ip;
219     string localIp;
220     string keyprint;
221     uint16_t port;
222     string externalIP;
223     char separator;
224     bool secure;
225     CountType countType;
226 };
227 
228 } // namespace dcpp
229