From: <arn...@us...> - 2007-11-17 14:47:58
|
Revision: 89 http://adchpp.svn.sourceforge.net/adchpp/?rev=89&view=rev Author: arnetheduck Date: 2007-11-17 06:47:54 -0800 (Sat, 17 Nov 2007) Log Message: ----------- Implement type F Modified Paths: -------------- adchpp/trunk/adchpp/AdcCommand.h adchpp/trunk/adchpp/Client.cpp adchpp/trunk/adchpp/Client.h adchpp/trunk/adchpp/ClientManager.cpp adchpp/trunk/adchpp/ManagedSocket.cpp adchpp/trunk/adchpp/ManagedSocket.h adchpp/trunk/swig/adchpp.i Modified: adchpp/trunk/adchpp/AdcCommand.h =================================================================== --- adchpp/trunk/adchpp/AdcCommand.h 2007-11-17 13:53:54 UTC (rev 88) +++ adchpp/trunk/adchpp/AdcCommand.h 2007-11-17 14:47:54 UTC (rev 89) @@ -132,6 +132,8 @@ const string& getParam(size_t n) const { return getParameters().size() > n ? getParameters()[n] : Util::emptyString; } + + const 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, string& ret) const; Modified: adchpp/trunk/adchpp/Client.cpp =================================================================== --- adchpp/trunk/adchpp/Client.cpp 2007-11-17 13:53:54 UTC (rev 88) +++ adchpp/trunk/adchpp/Client.cpp 2007-11-17 14:47:54 UTC (rev 89) @@ -27,184 +27,229 @@ namespace adchpp { using namespace std::tr1::placeholders; - + Client* Client::create(const ManagedSocketPtr& ms) throw() { Client* c = new Client(); c->setSocket(ms); return c; } -Client::Client() throw() : sid(0), state(STATE_PROTOCOL), disconnecting(false), socket(0), dataBytes(0), floodTimer(0) { +Client::Client() throw() : + sid(0), state(STATE_PROTOCOL), disconnecting(false), socket(0), dataBytes(0), floodTimer(0) { } +namespace { +// Lightweight call forwarders, instead of tr1::bind +struct Handler { + Handler(void (Client::*f)(), Client* c_) : + c(c_), f0(f) { + } + Handler(void (Client::*f)(const ByteVector&), Client* c_) : + c(c_), f1(f) { + } + + void operator()() throw() { + (c->*f0)(); + } + void operator()(const ByteVector& bv) throw() { + (c->*f1)(bv); + } + + Client* c; + union { + void (Client::*f0)(); + void (Client::*f1)(const ByteVector&); + }; +}; +} + void Client::setSocket(const ManagedSocketPtr& aSocket) throw() { - dcassert(!socket); - socket = aSocket; - socket->setConnectedHandler(std::tr1::bind(&Client::onConnected, this)); - socket->setDataHandler(std::tr1::bind(&Client::onData, this, _1)); - socket->setFailedHandler(std::tr1::bind(&Client::onFailed, this)); +dcassert(!socket); +socket = aSocket; +socket->setConnectedHandler(Handler(&Client::onConnected, this)); +socket->setDataHandler(Handler(&Client::onData, this)); +socket->setFailedHandler(Handler(&Client::onFailed, this)); } void Client::onConnected() throw() { - dcdebug("Client::onConnected\n"); - ClientManager::getInstance()->onConnected(*this); +dcdebug("Client::onConnected\n"); +ClientManager::getInstance()->onConnected(*this); } void* Client::setPSD(int id, void* data) throw() { - PSDIter i = find_if(psd.begin(), psd.end(), CompareFirst<int, void*>(id)); - if(i != psd.end()) { - void* old = i->second; - i->second = data; - return old; - } else { - psd.push_back(make_pair(id, data)); - return 0; - } +PSDIter i = find_if(psd.begin(), psd.end(), CompareFirst<int, void*>(id)); +if(i != psd.end()) { + void* old = i->second; + i->second = data; + return old; +} else { + psd.push_back(make_pair(id, data)); + return 0; } +} void* Client::getPSD(int id) throw() { - PSDIter i = find_if(psd.begin(), psd.end(), CompareFirst<int, void*>(id)); - if(i != psd.end()) - return i->second; - else - return 0; +PSDIter i = find_if(psd.begin(), psd.end(), CompareFirst<int, void*>(id)); +if(i != psd.end()) +return i->second; +else +return 0; } void Client::onData(const vector<uint8_t>& data) throw() { - dcdebug("In (%d): %.*s\n", data.size(), data.size(), &data[0]); +dcdebug("In (%d): %.*s\n", data.size(), data.size(), &data[0]); - size_t done = 0; - size_t len = data.size(); - while(!disconnecting && done < len) { - if(dataBytes > 0) { - size_t n = (size_t)min(dataBytes, (int64_t)(len - done)); - dataHandler(*this, &data[done], n); - dataBytes -= n; - done += n; - } else { - size_t j = done; - while(j < len && data[j] != '\n') - ++j; - - if(j == len) { - line.append((char*)&data[done], j - done); - return; - } - line.append((char*)&data[done], j - done + 1); // include LF - - done = j + 1; +size_t done = 0; +size_t len = data.size(); +while(!disconnecting && done < len) { + if(dataBytes > 0) { + size_t n = (size_t)min(dataBytes, (int64_t)(len - done)); + dataHandler(*this, &data[done], n); + dataBytes -= n; + done += n; + } else { + size_t j = done; + while(j < len && data[j] != '\n') + ++j; - if(SETTING(MAX_COMMAND_SIZE) > 0 && line.size() > (size_t)SETTING(MAX_COMMAND_SIZE)) { - send(AdcCommand(AdcCommand::SEV_FATAL, AdcCommand::ERROR_PROTOCOL_GENERIC, "Command too long")); - disconnect(Util::REASON_MAX_COMMAND_SIZE); - return; - } - - if(line.size() == 1) { - line.clear(); - continue; - } - - try { - AdcCommand cmd(line); - - if(cmd.getType() == 'H') { - cmd.setFrom(getSID()); - } else if(cmd.getFrom() != getSID()) { - disconnect(Util::REASON_INVALID_SID); - return; - } - ClientManager::getInstance()->onReceive(*this, cmd); - } catch(const ParseException&) { - ClientManager::getInstance()->onBadLine(*this, line); - } - line.clear(); + if(j == len) { + line.append((char*)&data[done], j - done); + return; } - } -} + line.append((char*)&data[done], j - done + 1); // include LF -void Client::setField(const char* name, const string& value) throw() { - if(value.empty()) { - info.erase(*(uint16_t*)name); - } else { - info[*(uint16_t*)name] = value; - } - changed[*(uint16_t*)name] = value; - INF.clear(); + done = j + 1; + + if(SETTING(MAX_COMMAND_SIZE) > 0 && line.size() > (size_t)SETTING(MAX_COMMAND_SIZE)) { + send(AdcCommand(AdcCommand::SEV_FATAL, AdcCommand::ERROR_PROTOCOL_GENERIC, "Command too long")); + disconnect(Util::REASON_MAX_COMMAND_SIZE); + return; + } + + if(line.size() == 1) { + line.clear(); + continue; + } + + try { + AdcCommand cmd(line); + + if(cmd.getType() == 'H') { + cmd.setFrom(getSID()); + } else if(cmd.getFrom() != getSID()) { + disconnect(Util::REASON_INVALID_SID); + return; + } + ClientManager::getInstance()->onReceive(*this, cmd); + } catch(const ParseException&) { + ClientManager::getInstance()->onBadLine(*this, line); + } + line.clear(); + } + } } +void Client::setField(const char* name, const string& value) throw() { + if(value.empty()) { + info.erase(AdcCommand::toCode(name)); + } else { + info[AdcCommand::toCode(name)] = value; + } + changed[AdcCommand::toCode(name)] = value; + INF.clear(); +} + bool Client::getChangedFields(AdcCommand& cmd) const throw() { - for(InfMap::const_iterator i = changed.begin(); i != changed.end(); ++i) - cmd.addParam(string((char*)&i->first, 2)); - return !changed.empty(); + for(InfMap::const_iterator i = changed.begin(); i != changed.end(); ++i) + cmd.addParam(string((char*)&i->first, 2)); + return !changed.empty(); } bool Client::getAllFields(AdcCommand& cmd) const throw() { - for(InfMap::const_iterator i = info.begin(); i != info.end(); ++i) - cmd.addParam(string((char*)&i->first, 2), i->second); - return !info.empty(); + for(InfMap::const_iterator i = info.begin(); i != info.end(); ++i) + cmd.addParam(string((char*)&i->first, 2), i->second); + return !info.empty(); } const string& Client::getINF() const throw() { - if(INF.empty()) { - AdcCommand cmd(AdcCommand::CMD_INF, AdcCommand::TYPE_BROADCAST, getSID()); - getAllFields(cmd); - INF = cmd.toString(); - } - return INF; + if(INF.empty()) { + AdcCommand cmd(AdcCommand::CMD_INF, AdcCommand::TYPE_BROADCAST, getSID()); + getAllFields(cmd); + INF = cmd.toString(); + } + return INF; } void Client::updateFields(const AdcCommand& cmd) throw() { - dcassert(cmd.getCommand() == AdcCommand::CMD_INF); - for(StringIterC j = cmd.getParameters().begin(); j != cmd.getParameters().end(); ++j) { - if(j->size() < 2) - continue; - setField(j->substr(0, 2).c_str(), j->substr(2)); - } + dcassert(cmd.getCommand() == AdcCommand::CMD_INF); + for(StringIterC j = cmd.getParameters().begin(); j != cmd.getParameters().end(); ++j) { + if(j->size() < 2) + continue; + setField(j->substr(0, 2).c_str(), j->substr(2)); + } } +bool Client::isFiltered(const string& features) const { + if(filters.empty()) { + return true; + } + + for(size_t i = 0; i < features.size(); i += 5) { + if(features[i] == '-') { + if(std::find(filters.begin(), filters.end(), features.substr(i+1, 4)) != filters.end()) { + return true; + } + } else if(features[i] == '+') { + if(std::find(filters.begin(), filters.end(), features.substr(i+1, 4)) == filters.end()) { + return true; + } + } + } + return false; +} + void Client::updateSupports(const AdcCommand& cmd) throw() { - for(StringIterC i = cmd.getParameters().begin(); i != cmd.getParameters().end(); ++i) { - const string& str = *i; - if(str.size() != 6) { - continue; - } - if(str.compare(0, 2, "AD") == 0) { - supportList.push_back(str.substr(2)); - } else if(str.compare(0, 2, "RM") == 0) { - supportList.erase(std::remove(supportList.begin(), supportList.end(), str.substr(2)), supportList.end()); - } else { - continue; - } - } + for(StringIterC i = cmd.getParameters().begin(); i != cmd.getParameters().end(); ++i) { + const string& str = *i; + if(str.size() != 6) { + continue; + } + if(str.compare(0, 2, "AD") == 0) { + supportList.push_back(str.substr(2)); + } else if(str.compare(0, 2, "RM") == 0) { + supportList.erase(std::remove(supportList.begin(), supportList.end(), str.substr(2)), supportList.end()); + } else { + continue; + } + } } bool Client::isFlooding(time_t addSeconds) { - time_t now = GET_TIME(); - if(floodTimer < now) { - floodTimer = now; - } - - floodTimer += addSeconds; - - if(floodTimer > now + SETTING(FLOOD_THRESHOLD)) { - return true; - } - - return false; + time_t now = GET_TIME(); + if(floodTimer < now) { + floodTimer = now; + } + + floodTimer += addSeconds; + + if(floodTimer > now + SETTING(FLOOD_THRESHOLD)) { + return true; + } + + return false; } void Client::disconnect(Util::Reason reason) throw() { - if(socket && !disconnecting) { - disconnecting = true; - line.clear(); - socket->disconnect(reason); - } + if(socket && !disconnecting) { + disconnecting = true; + line.clear(); + socket->disconnect(reason); + } } void Client::onFailed() throw() { - ClientManager::getInstance()->onFailed(*this); - delete this; + ClientManager::getInstance()->onFailed(*this); + delete this; } } Modified: adchpp/trunk/adchpp/Client.h =================================================================== --- adchpp/trunk/adchpp/Client.h 2007-11-17 13:53:54 UTC (rev 88) +++ adchpp/trunk/adchpp/Client.h 2007-11-17 14:47:54 UTC (rev 89) @@ -99,14 +99,16 @@ void resetChanged() { changed.clear(); } - const string& getField(const char* name) const throw() { InfMap::const_iterator i = info.find(*(uint16_t*)name); return i == info.end() ? Util::emptyString : i->second; } + const string& getField(const char* name) const throw() { InfMap::const_iterator i = info.find(AdcCommand::toCode(name)); return i == info.end() ? Util::emptyString : i->second; } ADCHPP_DLL void setField(const char* name, const string& value) throw(); ADCHPP_DLL void updateFields(const AdcCommand& cmd) throw(); ADCHPP_DLL void updateSupports(const AdcCommand& cmd) throw(); - bool isUdpActive() const { return info.find(*(uint16_t*)"U4") != info.end(); } - bool isTcpActive() const { return info.find(*(uint16_t*)"I4") != info.end(); } + bool isUdpActive() const { return info.find(AdcCommand::toCode("U4")) != info.end(); } + bool isTcpActive() const { return info.find(AdcCommand::toCode("I4")) != info.end(); } + + ADCHPP_DLL bool isFiltered(const std::string& features) const; ADCHPP_DLL bool isFlooding(time_t addSeconds); @@ -138,6 +140,9 @@ Client() throw(); virtual ~Client() throw() { } + /** H-C INF SU */ + StringList filters; + /** H-C SUP */ StringList supportList; typedef pair<int, void*> PSDPair; typedef vector<PSDPair> PSDList; Modified: adchpp/trunk/adchpp/ClientManager.cpp =================================================================== --- adchpp/trunk/adchpp/ClientManager.cpp 2007-11-17 13:53:54 UTC (rev 88) +++ adchpp/trunk/adchpp/ClientManager.cpp 2007-11-17 14:47:54 UTC (rev 89) @@ -51,9 +51,11 @@ case AdcCommand::TYPE_FEATURE: case AdcCommand::TYPE_BROADCAST: { - FastMutex::Lock l(ManagedSocket::getWriteLock()); + bool all = (cmd.getType() == AdcCommand::TYPE_BROADCAST); + FastMutex::Lock l(ManagedSocket::getWriteMutex()); for(ClientIter i = clients.begin(); i != clients.end(); ++i) { - i->second->fastSend(txt, lowPrio); + if(all || !i->second->isFiltered(cmd.getFeatures())) + i->second->fastSend(txt, lowPrio); } } SocketManager::getInstance()->addAllWriters(); @@ -78,7 +80,7 @@ void ClientManager::sendToAll(const string& cmd) throw() { { - FastMutex::Lock l(ManagedSocket::getWriteLock()); + FastMutex::Lock l(ManagedSocket::getWriteMutex()); for(ClientIter i = clients.begin(); i != clients.end(); ++i) { i->second->fastSend(cmd); } @@ -89,7 +91,7 @@ size_t ClientManager::getQueuedBytes() throw() { size_t total = 0; - FastMutex::Lock l(ManagedSocket::getWriteLock()); + FastMutex::Lock l(ManagedSocket::getWriteMutex()); for(ClientIter i = clients.begin(); i != clients.end(); ++i) { total += i->second->getQueuedBytes(); } Modified: adchpp/trunk/adchpp/ManagedSocket.cpp =================================================================== --- adchpp/trunk/adchpp/ManagedSocket.cpp 2007-11-17 13:53:54 UTC (rev 88) +++ adchpp/trunk/adchpp/ManagedSocket.cpp 2007-11-17 14:47:54 UTC (rev 89) @@ -27,7 +27,7 @@ namespace adchpp { -FastMutex ManagedSocket::outbufCS; +FastMutex ManagedSocket::writeMutex; ManagedSocket::ManagedSocket() throw() : outBuf(0), overFlow(0), disc(0) #ifdef _WIN32 @@ -54,7 +54,7 @@ void ManagedSocket::write(const char* buf, size_t len) throw() { bool add = false; { - FastMutex::Lock l(outbufCS); + FastMutex::Lock l(writeMutex); add = fastWrite(buf, len); } if(add) { @@ -93,7 +93,7 @@ ByteVector* buffer = 0; { - FastMutex::Lock l(outbufCS); + FastMutex::Lock l(writeMutex); if(outBuf == 0) { return 0; @@ -119,7 +119,7 @@ bool moreData; { - FastMutex::Lock l(outbufCS); + FastMutex::Lock l(writeMutex); if(written != buf->size()) { if(outBuf == 0) { Modified: adchpp/trunk/adchpp/ManagedSocket.h =================================================================== --- adchpp/trunk/adchpp/ManagedSocket.h 2007-11-17 13:53:54 UTC (rev 88) +++ adchpp/trunk/adchpp/ManagedSocket.h 2007-11-17 14:47:54 UTC (rev 89) @@ -44,7 +44,7 @@ ADCHPP_DLL bool fastWrite(const char* buf, size_t len, bool lowPrio = false) throw(); /** Returns the lock used for the write buffers */ - static FastMutex& getWriteLock() { return outbufCS; } + static FastMutex& getWriteMutex() { return writeMutex; } /** Returns the number of bytes in the output buffer; buffers must be locked */ size_t getQueuedBytes() { return outBuf ? outBuf->size() : 0; } @@ -110,7 +110,7 @@ DataHandler dataHandler; FailedHandler failedHandler; - ADCHPP_DLL static FastMutex outbufCS; + ADCHPP_DLL static FastMutex writeMutex; }; typedef boost::intrusive_ptr<ManagedSocket> ManagedSocketPtr; Modified: adchpp/trunk/swig/adchpp.i =================================================================== --- adchpp/trunk/swig/adchpp.i 2007-11-17 13:53:54 UTC (rev 88) +++ adchpp/trunk/swig/adchpp.i 2007-11-17 14:47:54 UTC (rev 89) @@ -85,15 +85,10 @@ template<typename F> struct Signal { - - ~Signal() { } }; template<typename Sig> struct ManagedConnection { - ManagedConnection(Sig* signal_, const typename Sig::SlotList::iterator& iter_); - ~ManagedConnection(); - void disconnect(); void release(); }; @@ -330,6 +325,8 @@ AdcCommand& addParam(const string& name, const string& value); AdcCommand& addParam(const string& str); const string& getParam(size_t n) const; + + const string& getFeatures() const; #ifndef SWIGLUA bool getParam(const char* name, size_t start, string& OUTPUT) const; @@ -423,6 +420,8 @@ bool isUdpActive(); bool isTcpActive(); + bool isFiltered(const std::string& features) const; + bool isFlooding(time_t addSeconds); //void* setPSD(int id, void* data) throw(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |