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 "typedefs.h" 22 #include "Exception.h" 23 #include "Util.h" 24 25 namespace dcpp { 26 27 STANDARD_EXCEPTION(ParseException); 28 29 class CID; 30 31 class AdcCommand { 32 public: 33 template<uint32_t T> 34 struct Type { 35 enum { CMD = T }; 36 }; 37 38 enum Error { 39 SUCCESS = 0, 40 ERROR_GENERIC = 0, 41 ERROR_HUB_GENERIC = 10, 42 ERROR_HUB_FULL = 11, 43 ERROR_HUB_DISABLED = 12, 44 ERROR_LOGIN_GENERIC = 20, 45 ERROR_NICK_INVALID = 21, 46 ERROR_NICK_TAKEN = 22, 47 ERROR_BAD_PASSWORD = 23, 48 ERROR_CID_TAKEN = 24, 49 ERROR_COMMAND_ACCESS = 25, 50 ERROR_REGGED_ONLY = 26, 51 ERROR_INVALID_PID = 27, 52 ERROR_BANNED_GENERIC = 30, 53 ERROR_PERM_BANNED = 31, 54 ERROR_TEMP_BANNED = 32, 55 ERROR_PROTOCOL_GENERIC = 40, 56 ERROR_PROTOCOL_UNSUPPORTED = 41, 57 ERROR_CONNECT_FAILED = 42, 58 ERROR_INF_MISSING = 43, 59 ERROR_BAD_STATE = 44, 60 ERROR_FEATURE_MISSING = 45, 61 ERROR_BAD_IP = 46, 62 ERROR_NO_HUB_HASH = 47, 63 ERROR_TRANSFER_GENERIC = 50, 64 ERROR_FILE_NOT_AVAILABLE = 51, 65 ERROR_FILE_PART_NOT_AVAILABLE = 52, 66 ERROR_SLOTS_FULL = 53, 67 ERROR_NO_CLIENT_HASH = 54 68 }; 69 70 enum Severity { 71 SEV_SUCCESS = 0, 72 SEV_RECOVERABLE = 1, 73 SEV_FATAL = 2 74 }; 75 76 static const char TYPE_BROADCAST = 'B'; 77 static const char TYPE_CLIENT = 'C'; 78 static const char TYPE_DIRECT = 'D'; 79 static const char TYPE_ECHO = 'E'; 80 static const char TYPE_FEATURE = 'F'; 81 static const char TYPE_INFO = 'I'; 82 static const char TYPE_HUB = 'H'; 83 static const char TYPE_UDP = 'U'; 84 85 #if defined(_WIN32) || defined(__i386__) || defined(__x86_64__) || defined(__alpha) || defined(__arm__) 86 #define C(n, a, b, c) static const uint32_t CMD_##n = (((uint32_t)a) | (((uint32_t)b)<<8) | (((uint32_t)c)<<16)); typedef Type<CMD_##n> n 87 #else 88 #define C(n, a, b, c) static const uint32_t CMD_##n = ((((uint32_t)a)<<24) | (((uint32_t)b)<<16) | (((uint32_t)c)<<8)); typedef Type<CMD_##n> n 89 #endif 90 // Base commands 91 C(SUP, 'S','U','P'); 92 C(STA, 'S','T','A'); 93 C(INF, 'I','N','F'); 94 C(MSG, 'M','S','G'); 95 C(SCH, 'S','C','H'); 96 C(RES, 'R','E','S'); 97 C(CTM, 'C','T','M'); 98 C(RCM, 'R','C','M'); 99 C(GPA, 'G','P','A'); 100 C(PAS, 'P','A','S'); 101 C(QUI, 'Q','U','I'); 102 C(GET, 'G','E','T'); 103 C(GFI, 'G','F','I'); 104 C(SND, 'S','N','D'); 105 C(SID, 'S','I','D'); 106 // Extensions 107 C(CMD, 'C','M','D'); 108 C(PSR, 'P','S','R'); 109 C(PUB, 'P','U','B'); 110 C(NAT, 'N','A','T'); 111 C(RNT, 'R','N','T'); 112 C(ZON, 'Z','O','N'); 113 C(ZOF, 'Z','O','F'); 114 #undef C 115 116 static const uint32_t HUB_SID = 0xffffffff; // No client will have this sid toFourCC(const char * x)117 static uint32_t toFourCC(const char* x) { return *reinterpret_cast<const uint32_t*>(x); } fromFourCC(uint32_t x)118 static std::string fromFourCC(uint32_t x) { return std::string(reinterpret_cast<const char*>(&x), sizeof(x)); } 119 explicit AdcCommand(uint32_t aCmd, char aType = TYPE_CLIENT); 120 explicit AdcCommand(uint32_t aCmd, const uint32_t aTarget, char aType); 121 explicit AdcCommand(Severity sev, Error err, const string& desc, char aType = TYPE_CLIENT); 122 explicit AdcCommand(const string& aLine, bool nmdc = false); 123 void parse(const string& aLine, bool nmdc = false); 124 getCommand()125 uint32_t getCommand() const { return cmdInt; } getType()126 char getType() const { return type; } setType(char t)127 void setType(char t) { type = t; } getFourCC()128 string getFourCC() const { string tmp(4, 0); tmp[0] = type; tmp[1] = cmd[0]; tmp[2] = cmd[1]; tmp[3] = cmd[2]; return tmp; } 129 getFeatures()130 const string& getFeatures() const { return features; } setFeatures(const string & feat)131 AdcCommand& setFeatures(const string& feat) { features = feat; return *this; } 132 getParameters()133 StringList& getParameters() { return parameters; } getParameters()134 const StringList& getParameters() const { return parameters; } 135 136 string toString(const CID& aCID) const; 137 string toString(uint32_t sid, bool nmdc = false) const; 138 addParam(const string & name,const string & value)139 AdcCommand& addParam(const string& name, const string& value) { 140 parameters.push_back(name); 141 parameters.back() += value; 142 return *this; 143 } addParam(const string & str)144 AdcCommand& addParam(const string& str) { 145 parameters.push_back(str); 146 return *this; 147 } 148 const string& getParam(size_t n) const; 149 /** Return a named parameter where the name is a two-letter code */ 150 bool getParam(const char* name, size_t start, string& ret) const; 151 bool hasFlag(const char* name, size_t start) const; toCode(const char * x)152 static uint16_t toCode(const char* x) { return *((uint16_t*)x); } 153 154 bool operator==(uint32_t aCmd) { return cmdInt == aCmd; } 155 156 static string escape(const string& str, bool old); getTo()157 uint32_t getTo() const { return to; } setTo(const uint32_t sid)158 AdcCommand& setTo(const uint32_t sid) { to = sid; return *this; } getFrom()159 uint32_t getFrom() const { return from; } 160 toSID(const string & aSID)161 static uint32_t toSID(const string& aSID) { return *reinterpret_cast<const uint32_t*>(aSID.data()); } fromSID(const uint32_t aSID)162 static string fromSID(const uint32_t aSID) { return string(reinterpret_cast<const char*>(&aSID), sizeof(aSID)); } 163 private: 164 string getHeaderString(const CID& cid) const; 165 string getHeaderString(uint32_t sid, bool nmdc) const; 166 string getParamString(bool nmdc) const; 167 StringList parameters; 168 string features; 169 union { 170 char cmdChar[4]; 171 uint8_t cmd[4]; 172 uint32_t cmdInt; 173 }; 174 uint32_t from; 175 uint32_t to; 176 char type; 177 178 }; 179 180 template<class T> 181 class CommandHandler { 182 public: 183 void dispatch(const string& aLine, bool nmdc = false) { 184 try { 185 AdcCommand c(aLine, nmdc); 186 187 #define C(n) case AdcCommand::CMD_##n: ((T*)this)->handle(AdcCommand::n(), c); break; 188 switch(c.getCommand()) { 189 C(SUP); 190 C(STA); 191 C(INF); 192 C(MSG); 193 C(SCH); 194 C(RES); 195 C(CTM); 196 C(RCM); 197 C(GPA); 198 C(PAS); 199 C(QUI); 200 C(GET); 201 C(GFI); 202 C(SND); 203 C(SID); 204 C(CMD); 205 C(PSR); 206 C(NAT); 207 C(RNT); 208 C(ZON); 209 C(ZOF); 210 default: 211 dcdebug("Unknown ADC command: %.50s\n", aLine.c_str()); 212 break; 213 #undef C 214 215 } catch(const ParseException &)216 } catch(const ParseException&) { 217 dcdebug("Invalid ADC command: %.50s\n", aLine.c_str()); 218 return; 219 } 220 } 221 }; 222 223 } // namespace dcpp 224