Client.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "adchpp.h"
00020
00021 #include "Client.h"
00022
00023 #include "ClientManager.h"
00024 #include "TimerManager.h"
00025 #include "SocketManager.h"
00026
00027 namespace adchpp {
00028
00029 using namespace std;
00030 using namespace std::placeholders;
00031
00032 size_t Client::defaultMaxCommandSize = 16 * 1024;
00033
00034 Client* Client::create(const ManagedSocketPtr& ms, uint32_t sid) throw() {
00035 Client* c = new Client(sid);
00036 c->setSocket(ms);
00037 return c;
00038 }
00039
00040 Client::Client(uint32_t sid_) throw() : Entity(sid_), disconnecting(false),
00041 dataBytes(0), maxCommandSize(getDefaultMaxCommandSize()) {
00042 }
00043
00044 Client::~Client() {
00045
00046 }
00047
00048 namespace {
00049
00050 template<void (Client::*F)()>
00051 struct Handler0 {
00052 Handler0(Client* c_) : c(c_) { }
00053 void operator()() { (c->*F)(); }
00054 Client* c;
00055 };
00056
00057 template<void (Client::*F)(const boost::system::error_code&)>
00058 struct Handler0x {
00059 Handler0x(Client* c_) : c(c_) { }
00060 void operator()() { (c->*F)(boost::system::error_code(boost::system::errc::timed_out, boost::system::get_generic_category())); }
00061 Client* c;
00062 };
00063
00064 template<typename T, void (Client::*F)(const T&)>
00065 struct Handler1 {
00066 Handler1(Client* c_) : c(c_) { }
00067 void operator()(const T& bv) { (c->*F)(bv); }
00068 Client* c;
00069 };
00070 }
00071
00072 void Client::setSocket(const ManagedSocketPtr& aSocket) throw() {
00073 dcassert(!socket);
00074 socket = aSocket;
00075 socket->setConnectedHandler(Handler0<&Client::onConnected>(this));
00076 socket->setDataHandler(Handler1<BufferPtr, &Client::onData>(this));
00077 socket->setFailedHandler(Handler1<boost::system::error_code, &Client::onFailed>(this));
00078 }
00079
00080 void Client::onConnected() throw() {
00081 ClientManager::getInstance()->onConnected(*this);
00082 }
00083
00084 void Client::onData(const BufferPtr& buf) throw() {
00085 uint8_t* data = buf->data();
00086 size_t done = 0;
00087 size_t len = buf->size();
00088 while(!disconnecting && done < len) {
00089 if(dataBytes > 0) {
00090 size_t n = (size_t)min(dataBytes, (int64_t)(len - done));
00091 dataHandler(*this, data + done, n);
00092 dataBytes -= n;
00093 done += n;
00094 } else {
00095 size_t j = done;
00096 while(j < len && data[j] != '\n')
00097 ++j;
00098
00099 if(j == len) {
00100 if(!buffer) {
00101 if(done == 0) {
00102 buffer = buf;
00103 } else {
00104 buffer = make_shared<Buffer>(data + done, len - done);
00105 }
00106 } else {
00107 buffer->append(data + done, data + len);
00108 }
00109 return;
00110 } else if(!buffer) {
00111 if(done == 0 && j == len-1) {
00112 buffer = buf;
00113 } else {
00114 buffer = make_shared<Buffer>(data + done, j - done + 1);
00115 }
00116 } else {
00117 buffer->append(data + done, data + j + 1);
00118 }
00119
00120 done = j + 1;
00121
00122 if(getMaxCommandSize() > 0 && buffer->size() > getMaxCommandSize()) {
00123 send(AdcCommand(AdcCommand::SEV_FATAL, AdcCommand::ERROR_PROTOCOL_GENERIC, "Command too long"));
00124 disconnect(Util::REASON_MAX_COMMAND_SIZE);
00125 return;
00126 }
00127
00128 if(buffer->size() == 1) {
00129 buffer.reset();
00130 continue;
00131 }
00132
00133 try {
00134 AdcCommand cmd(buffer);
00135
00136 if(cmd.getType() == 'H') {
00137 cmd.setFrom(getSID());
00138 } else if(cmd.getFrom() != getSID()) {
00139 disconnect(Util::REASON_INVALID_SID);
00140 return;
00141 }
00142 ClientManager::getInstance()->onReceive(*this, cmd);
00143 } catch(const ParseException&) {
00144 ClientManager::getInstance()->onBadLine(*this, string((char*)buffer->data(), buffer->size()));
00145 }
00146 buffer.reset();
00147 }
00148 }
00149 }
00150
00151 void Client::disconnect(Util::Reason reason) throw() {
00152 dcassert(socket);
00153 if(!disconnecting) {
00154 dcdebug("%s disconnecting because %d\n", AdcCommand::fromSID(getSID()).c_str(), reason);
00155 disconnecting = true;
00156
00157 socket->setConnectedHandler(ManagedSocket::ConnectedHandler());
00158 socket->setDataHandler(ManagedSocket::DataHandler());
00159 socket->setFailedHandler(ManagedSocket::FailedHandler());
00160
00162 socket->disconnect(5000, reason);
00163
00164
00165 SocketManager::getInstance()->addJob(Handler0x<&Client::onFailed>(this));
00166 }
00167 }
00168
00169 void Client::onFailed(const boost::system::error_code& ec) throw() {
00170 ClientManager::getInstance()->onFailed(*this, ec);
00171 delete this;
00172 }
00173
00174 }