239 lines
7.3 KiB
C++
239 lines
7.3 KiB
C++
/*
|
|
* Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point com
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
#ifndef ADCHPP_ADC_COMMAND_H
|
|
#define ADCHPP_ADC_COMMAND_H
|
|
|
|
#include "common.h"
|
|
#include "Exception.h"
|
|
#include "Util.h"
|
|
#include "Buffer.h"
|
|
|
|
namespace adchpp {
|
|
|
|
STANDARD_EXCEPTION(ParseException);
|
|
|
|
class AdcCommand : private boost::noncopyable {
|
|
public:
|
|
template<uint32_t T>
|
|
struct Type {
|
|
enum { CMD = T };
|
|
};
|
|
|
|
enum Error {
|
|
ERROR_GENERIC = 0,
|
|
ERROR_HUB_GENERIC = 10,
|
|
ERROR_HUB_FULL = 11,
|
|
ERROR_HUB_DISABLED = 12,
|
|
ERROR_LOGIN_GENERIC = 20,
|
|
ERROR_NICK_INVALID = 21,
|
|
ERROR_NICK_TAKEN = 22,
|
|
ERROR_BAD_PASSWORD = 23,
|
|
ERROR_CID_TAKEN = 24,
|
|
ERROR_COMMAND_ACCESS = 25,
|
|
ERROR_REGGED_ONLY = 26,
|
|
ERROR_INVALID_PID = 27,
|
|
ERROR_BANNED_GENERIC = 30,
|
|
ERROR_PERM_BANNED = 31,
|
|
ERROR_TEMP_BANNED = 32,
|
|
ERROR_PROTOCOL_GENERIC = 40,
|
|
ERROR_PROTOCOL_UNSUPPORTED = 41,
|
|
ERROR_CONNECT_FAILED = 42,
|
|
ERROR_INF_MISSING = 43,
|
|
ERROR_BAD_STATE = 44,
|
|
ERROR_FEATURE_MISSING = 45,
|
|
ERROR_BAD_IP = 46,
|
|
ERROR_NO_HUB_HASH = 47,
|
|
ERROR_TRANSFER_GENERIC = 50,
|
|
ERROR_FILE_NOT_AVAILABLE = 51,
|
|
ERROR_FILE_PART_NOT_AVAILABLE = 52,
|
|
ERROR_SLOTS_FULL = 53,
|
|
ERROR_NO_CLIENT_HASH = 54
|
|
};
|
|
|
|
enum Severity {
|
|
SEV_SUCCESS = 0,
|
|
SEV_RECOVERABLE = 1,
|
|
SEV_FATAL = 2
|
|
};
|
|
|
|
enum Priority {
|
|
PRIORITY_NORMAL, ///< Default priority, command will be sent out normally
|
|
PRIORITY_LOW, ///< Low priority, command will only be sent if connection isn't saturated
|
|
PRIORITY_IGNORE ///< Ignore, command will not be put in send queue
|
|
};
|
|
|
|
static const char TYPE_BROADCAST = 'B';
|
|
static const char TYPE_CLIENT = 'C';
|
|
static const char TYPE_DIRECT = 'D';
|
|
static const char TYPE_ECHO = 'E';
|
|
static const char TYPE_FEATURE = 'F';
|
|
static const char TYPE_INFO = 'I';
|
|
static const char TYPE_HUB = 'H';
|
|
static const char TYPE_UDP = 'U';
|
|
|
|
// Known commands...
|
|
#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
|
|
// Base commands
|
|
C(SUP, 'S','U','P');
|
|
C(STA, 'S','T','A');
|
|
C(INF, 'I','N','F');
|
|
C(MSG, 'M','S','G');
|
|
C(SCH, 'S','C','H');
|
|
C(RES, 'R','E','S');
|
|
C(CTM, 'C','T','M');
|
|
C(RCM, 'R','C','M');
|
|
C(GPA, 'G','P','A');
|
|
C(PAS, 'P','A','S');
|
|
C(QUI, 'Q','U','I');
|
|
C(GET, 'G','E','T');
|
|
C(GFI, 'G','F','I');
|
|
C(SND, 'S','N','D');
|
|
C(SID, 'S','I','D');
|
|
// Extensions
|
|
C(CMD, 'C','M','D');
|
|
C(NAT, 'N','A','T');
|
|
C(RNT, 'R','N','T');
|
|
#undef C
|
|
|
|
static const uint32_t HUB_SID = static_cast<uint32_t>(-1);
|
|
static const uint32_t INVALID_SID = static_cast<uint32_t>(-2);
|
|
|
|
static uint32_t toSID(const std::string& aSID) { return *reinterpret_cast<const uint32_t*>(aSID.data()); }
|
|
static std::string fromSID(const uint32_t aSID) { return std::string(reinterpret_cast<const char*>(&aSID), sizeof(aSID)); }
|
|
static void appendSID(std::string& str, uint32_t aSID) { str.append(reinterpret_cast<const char*>(&aSID), sizeof(aSID)); }
|
|
|
|
static uint32_t toCMD(uint8_t a, uint8_t b, uint8_t c) { return (((uint32_t)a) | (((uint32_t)b)<<8) | (((uint32_t)c)<<16)); }
|
|
static uint32_t toCMD(const char* str) { return toCMD(str[0], str[1], str[2]); }
|
|
|
|
static uint16_t toField(const char* x) { return *((uint16_t*)x); }
|
|
static std::string fromField(const uint16_t aField) { return std::string(reinterpret_cast<const char*>(&aField), sizeof(aField)); }
|
|
|
|
static uint32_t toFourCC(const char* x) { return *reinterpret_cast<const uint32_t*>(x); }
|
|
static std::string fromFourCC(uint32_t x) { return std::string(reinterpret_cast<const char*>(&x), sizeof(x)); }
|
|
|
|
ADCHPP_DLL AdcCommand();
|
|
ADCHPP_DLL explicit AdcCommand(Severity sev, Error err, const std::string& desc, char aType = TYPE_INFO);
|
|
explicit AdcCommand(uint32_t cmd, char aType = TYPE_INFO, uint32_t aFrom = HUB_SID) : cmdInt(cmd), priority(PRIORITY_NORMAL), from(aFrom), to(INVALID_SID), type(aType) { }
|
|
explicit AdcCommand(const std::string& aLine) throw(ParseException) : cmdInt(0), priority(PRIORITY_NORMAL), from(INVALID_SID), to(INVALID_SID), type(0) { parse(aLine); }
|
|
explicit AdcCommand(const BufferPtr& buffer_) throw(ParseException) : buffer(buffer_), cmdInt(0), priority(PRIORITY_NORMAL), from(INVALID_SID), to(INVALID_SID), type(0) { parse((const char*)buffer->data(), buffer->size()); }
|
|
|
|
void parse(const std::string& str) throw(ParseException) { parse(str.data(), str.size()); }
|
|
ADCHPP_DLL void parse(const char* buf, size_t len) throw(ParseException);
|
|
uint32_t getCommand() const { return cmdInt; }
|
|
char getType() const { return type; }
|
|
std::string getFourCC() const { std::string tmp(4, 0); tmp[0] = type; tmp[1] = cmd[0]; tmp[2] = cmd[1]; tmp[3] = cmd[2]; return tmp; }
|
|
StringList& getParameters() { return parameters; }
|
|
const StringList& getParameters() const { return parameters; }
|
|
ADCHPP_DLL std::string toString() const;
|
|
|
|
AdcCommand& addParam(const std::string& param) {
|
|
parameters.push_back(param);
|
|
resetBuffer();
|
|
return *this;
|
|
}
|
|
|
|
AdcCommand& addParam(const std::string& name, const std::string& value) {
|
|
return addParam(name + value);
|
|
}
|
|
|
|
const std::string& getParam(size_t n) const {
|
|
return getParameters().size() > n ? getParameters()[n] : Util::emptyString;
|
|
}
|
|
|
|
void resetBuffer() { buffer.reset(); }
|
|
|
|
const std::string& getFeatures() const { return features; }
|
|
|
|
/** Return a named parameter where the name is a two-letter code */
|
|
ADCHPP_DLL bool getParam(const char* name, size_t start, std::string& ret) const;
|
|
ADCHPP_DLL bool delParam(const char* name, size_t start);
|
|
|
|
ADCHPP_DLL bool hasFlag(const char* name, size_t start) const;
|
|
|
|
bool operator==(uint32_t aCmd) const { return cmdInt == aCmd; }
|
|
|
|
ADCHPP_DLL static void escape(const std::string& s, std::string& out);
|
|
|
|
ADCHPP_DLL const BufferPtr& getBuffer() const;
|
|
|
|
uint32_t getTo() const { return to; }
|
|
void setTo(uint32_t aTo) { to = aTo; }
|
|
uint32_t getFrom() const { return from; }
|
|
void setFrom(uint32_t aFrom) { from = aFrom; }
|
|
|
|
Priority getPriority() const { return priority; }
|
|
void setPriority(Priority priority_) { priority = priority_; }
|
|
|
|
private:
|
|
StringList parameters;
|
|
std::string features;
|
|
|
|
mutable BufferPtr buffer;
|
|
|
|
union {
|
|
char cmdChar[4];
|
|
uint8_t cmd[4];
|
|
uint32_t cmdInt;
|
|
};
|
|
|
|
Priority priority;
|
|
uint32_t from;
|
|
uint32_t to;
|
|
char type;
|
|
};
|
|
|
|
class Client;
|
|
class Entity;
|
|
|
|
template<class T>
|
|
class CommandHandler {
|
|
public:
|
|
bool dispatch(Entity& c, AdcCommand& cmd) {
|
|
#define C(n) case AdcCommand::CMD_##n: return ((T*)this)->handle(AdcCommand::n(), c, cmd); break;
|
|
switch(cmd.getCommand()) {
|
|
C(SUP);
|
|
C(STA);
|
|
C(INF);
|
|
C(MSG);
|
|
C(SCH);
|
|
C(RES);
|
|
C(CTM);
|
|
C(RCM);
|
|
C(GPA);
|
|
C(PAS);
|
|
C(QUI);
|
|
C(GET);
|
|
C(GFI);
|
|
C(SND);
|
|
C(SID);
|
|
C(CMD);
|
|
C(NAT);
|
|
C(RNT);
|
|
default:
|
|
dcdebug("Unknown ADC command: %.50s\n", cmd.toString().c_str());
|
|
return true;
|
|
#undef C
|
|
}
|
|
}
|
|
};
|
|
|
|
}
|
|
|
|
#endif // ADC_COMMAND_H
|