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 "forward.h" 22 #include "TimerManager.h" 23 #include "UserConnectionListener.h" 24 #include "BufferedSocketListener.h" 25 #include "BufferedSocket.h" 26 #include "CriticalSection.h" 27 #include "File.h" 28 #include "User.h" 29 #include "AdcCommand.h" 30 #include "MerkleTree.h" 31 #include "DebugManager.h" 32 #ifdef LUA_SCRIPT 33 #include "ScriptManager.h" 34 #endif 35 36 namespace dcpp { 37 #ifdef LUA_SCRIPT 38 class UserConnectionScriptInstance : public ScriptInstance { 39 protected: 40 bool onUserConnectionMessageIn(UserConnection* aConn, const string& aLine); 41 bool onUserConnectionMessageOut(UserConnection* aConn, const string& aLine); 42 }; 43 #endif 44 45 class UserConnection : public Speaker<UserConnectionListener>, 46 private BufferedSocketListener, public Flags, private CommandHandler<UserConnection>, 47 private boost::noncopyable 48 #ifdef LUA_SCRIPT 49 , public UserConnectionScriptInstance 50 #endif 51 { 52 public: 53 friend class ConnectionManager; 54 55 static const string FEATURE_MINISLOTS; 56 static const string FEATURE_XML_BZLIST; 57 static const string FEATURE_ADCGET; 58 static const string FEATURE_ZLIB_GET; 59 static const string FEATURE_TTHL; 60 static const string FEATURE_TTHF; 61 static const string FEATURE_ADC_BAS0; 62 static const string FEATURE_ADC_BASE; 63 static const string FEATURE_ADC_BZIP; 64 static const string FEATURE_ADC_TIGR; 65 66 static const string FILE_NOT_AVAILABLE; 67 68 enum Modes { 69 MODE_COMMAND = BufferedSocket::MODE_LINE, 70 MODE_DATA = BufferedSocket::MODE_DATA 71 }; 72 73 enum Flags { 74 FLAG_NMDC = 0x01, 75 FLAG_OP = FLAG_NMDC << 1, 76 FLAG_UPLOAD = FLAG_OP << 1, 77 FLAG_DOWNLOAD = FLAG_UPLOAD << 1, 78 FLAG_INCOMING = FLAG_DOWNLOAD << 1, 79 FLAG_ASSOCIATED = FLAG_INCOMING << 1, 80 FLAG_HASSLOT = FLAG_ASSOCIATED << 1, 81 FLAG_HASEXTRASLOT = FLAG_HASSLOT << 1, 82 FLAG_INVALIDKEY = FLAG_HASEXTRASLOT << 1, 83 FLAG_SUPPORTS_MINISLOTS = FLAG_INVALIDKEY << 1, 84 FLAG_SUPPORTS_XML_BZLIST = FLAG_SUPPORTS_MINISLOTS << 1, 85 FLAG_SUPPORTS_ADCGET = FLAG_SUPPORTS_XML_BZLIST << 1, 86 FLAG_SUPPORTS_ZLIB_GET = FLAG_SUPPORTS_ADCGET << 1, 87 FLAG_SUPPORTS_TTHL = FLAG_SUPPORTS_ZLIB_GET << 1, 88 FLAG_SUPPORTS_TTHF = FLAG_SUPPORTS_TTHL << 1, 89 FLAG_SECURE = FLAG_SUPPORTS_TTHF << 1 90 }; 91 92 enum States { 93 // ConnectionManager 94 STATE_UNCONNECTED, 95 STATE_CONNECT, 96 97 // Handshake 98 STATE_SUPNICK, // ADC: SUP, Nmdc: $Nick 99 STATE_INF, 100 STATE_LOCK, 101 STATE_DIRECTION, 102 STATE_KEY, 103 104 // UploadManager 105 STATE_GET, // Waiting for GET 106 STATE_SEND, // Waiting for $Send 107 108 // DownloadManager 109 STATE_SND, // Waiting for SND 110 STATE_IDLE, // No more downloads for the moment 111 112 // Up & down 113 STATE_RUNNING // Transmitting data 114 115 }; 116 getNumber()117 short getNumber() { return (short)((((size_t)this)>>2) & 0x7fff); } getSocket()118 BufferedSocket const* getSocket() { return socket; } 119 120 // NMDC stuff myNick(const string & aNick)121 void myNick(const string& aNick) { send("$MyNick " + Text::fromUtf8(aNick, encoding) + '|'); } lock(const string & aLock,const string & aPk)122 void lock(const string& aLock, const string& aPk) { send ("$Lock " + aLock + " Pk=" + aPk + '|'); } key(const string & aKey)123 void key(const string& aKey) { send("$Key " + aKey + '|'); } direction(const string & aDirection,int aNumber)124 void direction(const string& aDirection, int aNumber) { send("$Direction " + aDirection + " " + Util::toString(aNumber) + '|'); } fileLength(const string & aLength)125 void fileLength(const string& aLength) { send("$FileLength " + aLength + '|'); } error(const string & aError)126 void error(const string& aError) { isSet(FLAG_NMDC) ? send("$Error " + aError + '|') : 127 send(AdcCommand(AdcCommand::SEV_FATAL, AdcCommand::ERROR_TRANSFER_GENERIC, aError)); } listLen(const string & aLength)128 void listLen(const string& aLength) { send("$ListLen " + aLength + '|'); } maxedOut()129 void maxedOut() { isSet(FLAG_NMDC) ? send("$MaxedOut|") : send(AdcCommand(AdcCommand::SEV_RECOVERABLE, AdcCommand::ERROR_SLOTS_FULL, "Slots full")); } 130 void fileNotAvail(const std::string& msg = FILE_NOT_AVAILABLE) { isSet(FLAG_NMDC) ? send("$Error " + msg + "|") : send(AdcCommand(AdcCommand::SEV_RECOVERABLE, AdcCommand::ERROR_FILE_NOT_AVAILABLE, msg)); } 131 void supports(const StringList& feat); 132 133 // ADC Stuff 134 void sup(const StringList& features); 135 void inf(bool withToken); get(const string & aType,const string & aName,const int64_t aStart,const int64_t aBytes)136 void get(const string& aType, const string& aName, const int64_t aStart, const int64_t aBytes) { send(AdcCommand(AdcCommand::CMD_GET).addParam(aType).addParam(aName).addParam(Util::toString(aStart)).addParam(Util::toString(aBytes))); } snd(const string & aType,const string & aName,const int64_t aStart,const int64_t aBytes)137 void snd(const string& aType, const string& aName, const int64_t aStart, const int64_t aBytes) { send(AdcCommand(AdcCommand::CMD_SND).addParam(aType).addParam(aName).addParam(Util::toString(aStart)).addParam(Util::toString(aBytes))); } send(const AdcCommand & c)138 void send(const AdcCommand& c) { send(c.toString(0, isSet(FLAG_NMDC))); } 139 140 void setDataMode(int64_t aBytes = -1) { dcassert(socket); socket->setDataMode(aBytes); } setLineMode(size_t rollback)141 void setLineMode(size_t rollback) { dcassert(socket); socket->setLineMode(rollback); } 142 143 void connect(const string& aServer, uint16_t aPort, uint16_t localPort, const BufferedSocket::NatRoles natRole) throw(SocketException, ThreadException); 144 void accept(const Socket& aServer) throw(SocketException, ThreadException); 145 updated()146 void updated() { if(socket) socket->updated(); } 147 148 void disconnect(bool graceless = false) { if(socket) socket->disconnect(graceless); } transmitFile(InputStream * f)149 void transmitFile(InputStream* f) { socket->transmitFile(f); } 150 getDirectionString()151 const string& getDirectionString() { 152 dcassert(isSet(FLAG_UPLOAD) ^ isSet(FLAG_DOWNLOAD)); 153 return isSet(FLAG_UPLOAD) ? UPLOAD : DOWNLOAD; 154 } 155 getUser()156 const UserPtr& getUser() const { return user; } getUser()157 UserPtr& getUser() { return user; } getHintedUser()158 const HintedUser getHintedUser() const { return HintedUser(user, hubUrl); } 159 isSecure()160 bool isSecure() const { return socket && socket->isSecure(); } isTrusted()161 bool isTrusted() const { return socket && socket->isTrusted(); } getCipherName()162 std::string getCipherName() const { return socket ? socket->getCipherName() : Util::emptyString; } getKeyprint()163 vector<uint8_t> getKeyprint() const { return socket ? socket->getKeyprint() : vector<uint8_t>(); } getRemoteIp()164 std::string getRemoteIp() const { return socket ? socket->getIp() : Util::emptyString; } getDownload()165 Download* getDownload() { dcassert(isSet(FLAG_DOWNLOAD)); return download; } 166 //uint16_t getPort() const { if(socket) return socket->getPort(); else return 0; } setDownload(Download * d)167 void setDownload(Download* d) { dcassert(isSet(FLAG_DOWNLOAD)); download = d; } getUpload()168 Upload* getUpload() { dcassert(isSet(FLAG_UPLOAD)); return upload; } setUpload(Upload * u)169 void setUpload(Upload* u) { dcassert(isSet(FLAG_UPLOAD)); upload = u; } 170 handle(AdcCommand::SUP t,const AdcCommand & c)171 void handle(AdcCommand::SUP t, const AdcCommand& c) { fire(t, this, c); } handle(AdcCommand::INF t,const AdcCommand & c)172 void handle(AdcCommand::INF t, const AdcCommand& c) { fire(t, this, c); } handle(AdcCommand::GET t,const AdcCommand & c)173 void handle(AdcCommand::GET t, const AdcCommand& c) { fire(t, this, c); } handle(AdcCommand::SND t,const AdcCommand & c)174 void handle(AdcCommand::SND t, const AdcCommand& c) { fire(t, this, c); } 175 void handle(AdcCommand::STA t, const AdcCommand& c); handle(AdcCommand::RES t,const AdcCommand & c)176 void handle(AdcCommand::RES t, const AdcCommand& c) { fire(t, this, c); } handle(AdcCommand::GFI t,const AdcCommand & c)177 void handle(AdcCommand::GFI t, const AdcCommand& c) { fire(t, this, c); } 178 179 // Ignore any other ADC commands for now handle(T,const AdcCommand &)180 template<typename T> void handle(T , const AdcCommand& ) { } 181 getChunkSize()182 int64_t getChunkSize() const { return chunkSize; } 183 void updateChunkSize(int64_t leafSize, int64_t lastChunk, uint64_t ticks); sendRaw(const string & raw)184 void sendRaw(const string& raw) { send(raw); }//aded 185 GETSET(string, hubUrl, HubUrl); 186 GETSET(string, token, Token); 187 GETSET(string, encoding, Encoding); 188 GETSET(uint16_t, port, Port); 189 GETSET(States, state, State); 190 GETSET(uint64_t, lastActivity, LastActivity); 191 GETSET(double, speed, Speed); 192 private: 193 int64_t chunkSize; 194 BufferedSocket* socket; 195 bool secure; 196 UserPtr user; 197 198 static const string UPLOAD, DOWNLOAD; 199 200 union { 201 Download* download; 202 Upload* upload; 203 }; 204 205 // We only want ConnectionManager to create this... UserConnection(bool secure_)206 UserConnection(bool secure_) noexcept : encoding(Text::systemCharset), state(STATE_UNCONNECTED), 207 lastActivity(0), speed(0), chunkSize(0), socket(0), secure(secure_), download(NULL) { 208 if (secure_) 209 setFlag(FLAG_SECURE); 210 } 211 ~UserConnection()212 virtual ~UserConnection() noexcept { 213 BufferedSocket::putSocket(socket); 214 } 215 216 friend struct DeleteFunction; 217 setUser(const UserPtr & aUser)218 void setUser(const UserPtr& aUser) { 219 user = aUser; 220 } 221 222 void onLine(const string& aLine) noexcept; 223 send(const string & aString)224 void send(const string& aString) { 225 lastActivity = GET_TICK(); 226 COMMAND_DEBUG(aString, DebugManager::CLIENT_OUT, getRemoteIp()); 227 #ifdef LUA_SCRIPT 228 if(onUserConnectionMessageOut(this, aString)) { 229 disconnect(true); 230 return; 231 } 232 #endif 233 socket->write(aString); 234 } 235 236 virtual void on(Connected) noexcept; 237 virtual void on(Line, const string&) noexcept; 238 virtual void on(Data, uint8_t* data, size_t len) noexcept; 239 virtual void on(BytesSent, size_t bytes, size_t actual) noexcept ; 240 virtual void on(ModeChange) noexcept; 241 virtual void on(TransmitDone) noexcept; 242 virtual void on(Failed, const string&) noexcept; 243 virtual void on(Updated) noexcept; 244 }; 245 246 } // namespace dcpp 247