From 0b27c37fe95c6aced613d51a3624f8930a96ad3f Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Thu, 4 Jun 2009 22:23:07 +0200 Subject: RequestHandler-Interface ?berarbeitet --- src/Common/CMakeLists.txt | 4 +- src/Common/Connection.cpp | 2 +- src/Common/Connection.h | 8 +- src/Common/Request.cpp | 14 +- src/Common/Request.h | 87 +++++------- src/Common/RequestHandler.cpp | 40 ++++++ src/Common/RequestHandler.h | 47 +++--- .../RequestHandlers/DisconnectRequestHandler.cpp | 4 +- .../RequestHandlers/DisconnectRequestHandler.h | 6 +- .../RequestHandlers/FSInfoRequestHandler.cpp | 4 +- src/Common/RequestHandlers/FSInfoRequestHandler.h | 6 +- .../RequestHandlers/StatusRequestHandler.cpp | 4 +- src/Common/RequestHandlers/StatusRequestHandler.h | 6 +- src/Common/RequestManager.cpp | 117 ++++++++++----- src/Common/RequestManager.h | 158 ++++++--------------- src/Common/Requests/DisconnectRequest.cpp | 12 +- src/Common/Requests/DisconnectRequest.h | 6 +- src/Common/Requests/FSInfoRequest.h | 3 +- src/Common/Requests/GroupListRequest.h | 3 +- src/Common/Requests/GroupUserListRequest.h | 3 +- src/Common/Requests/IdentifyRequest.h | 3 +- src/Common/Requests/SimpleRequest.h | 3 +- src/Common/Requests/StatusRequest.h | 3 +- src/Common/Requests/UserGroupListRequest.h | 3 +- src/Common/Requests/UserInfoRequest.h | 4 +- src/Common/Requests/UserListRequest.h | 3 +- 26 files changed, 260 insertions(+), 293 deletions(-) create mode 100644 src/Common/RequestHandler.cpp (limited to 'src/Common') diff --git a/src/Common/CMakeLists.txt b/src/Common/CMakeLists.txt index fe18760..de6dfc7 100644 --- a/src/Common/CMakeLists.txt +++ b/src/Common/CMakeLists.txt @@ -8,7 +8,7 @@ link_directories(${LTDL_LIBRARY_DIR}) add_library(Common Base64Encoder.cpp ClientConnection.cpp ConfigEntry.cpp ConfigManager.cpp Connection.cpp Initializable.cpp Logger.cpp LogManager.cpp - ModuleManager.cpp Request.cpp RequestManager.cpp SystemManager.cpp Tokenizer.cpp - XmlPacket.cpp + ModuleManager.cpp Request.cpp RequestHandler.cpp RequestManager.cpp SystemManager.cpp + Tokenizer.cpp XmlPacket.cpp ) target_link_libraries(Common RequestHandlers Requests Net ${LIBXML2_LIBRARIES} ${LTDL_LIBRARIES}) diff --git a/src/Common/Connection.cpp b/src/Common/Connection.cpp index db962ea..6afd5f0 100644 --- a/src/Common/Connection.cpp +++ b/src/Common/Connection.cpp @@ -24,7 +24,7 @@ namespace Mad { namespace Common { void Connection::receive(boost::shared_ptr packet) { - signalReceive.emit(XmlPacket(*packet), packet->getRequestId()); + signalReceive.emit(boost::shared_ptr(new XmlPacket(*packet)), packet->getRequestId()); } bool Connection::sendPacket(const XmlPacket &packet, uint16_t requestId) { diff --git a/src/Common/Connection.h b/src/Common/Connection.h index b794a88..6f1cffd 100644 --- a/src/Common/Connection.h +++ b/src/Common/Connection.h @@ -39,7 +39,7 @@ class Connection : private boost::noncopyable { private: bool authenticated; - Net::Signals::Signal2 signalReceive; + Net::Signals::Signal22, uint16_t> signalReceive; protected: Connection() : authenticated(0) {} @@ -53,9 +53,13 @@ class Connection : private boost::noncopyable { bool sendPacket(const XmlPacket &packet, uint16_t requestId); - Net::Signals::Connection connectSignalReceive(const Net::Signals::Signal2::slot_type &slot) { + Net::Signals::Connection2 connectSignalReceive(const Net::Signals::Signal22, uint16_t>::slot_type &slot) { return signalReceive.connect(slot); } + void disconnectSignalReceive(const Net::Signals::Connection2 &con) { + signalReceive.disconnect(con); + } + virtual bool disconnect() = 0; //virtual void* getCertificate(size_t *size) const = 0; diff --git a/src/Common/Request.cpp b/src/Common/Request.cpp index e27c1b9..723039f 100644 --- a/src/Common/Request.cpp +++ b/src/Common/Request.cpp @@ -22,19 +22,17 @@ namespace Mad { namespace Common { -Request::slot_type Request::empty_slot(&Request::doNothing); - -void Request::handlePacket(const XmlPacket &packet) { - if(packet.getType() == "Error") { - finishWithError(Net::Exception(packet["Where"], packet["ErrorCode"], packet["SubCode"], packet["SubSubCode"])); +void Request::handlePacket(boost::shared_ptr packet) { + if(packet->getType() == "Error") { + signalFinished(Net::Exception((*packet)["Where"], (*packet)["ErrorCode"], (*packet)["SubCode"], (*packet)["SubSubCode"])); return; } - else if(packet.getType() != "OK") { - finishWithError(Net::Exception(Net::Exception::UNEXPECTED_PACKET)); + else if(packet->getType() != "OK") { + signalFinished(Net::Exception(Net::Exception::UNEXPECTED_PACKET)); return; // TODO Logging } - finish(packet); + signalFinished(packet); } } diff --git a/src/Common/Request.h b/src/Common/Request.h index d351c2a..b8477f7 100644 --- a/src/Common/Request.h +++ b/src/Common/Request.h @@ -17,8 +17,8 @@ * with this program. If not, see . */ -#ifndef MAD_COMMON_XMLREQUEST_H_ -#define MAD_COMMON_XMLREQUEST_H_ +#ifndef MAD_COMMON_REQUEST_H_ +#define MAD_COMMON_REQUEST_H_ #include "RequestHandler.h" #include @@ -37,80 +37,54 @@ class Request : public RequestHandler { private: friend class RequestManager; - Net::Signals::Signal1 finished; - - std::auto_ptr res; - Net::Exception exp; - boost::mutex mutex; boost::condition_variable finishCond; bool isFinished; - static void doNothing(Request&) {} + boost::shared_ptr packet; + Net::Exception exception; - public: - typedef Net::Signals::Signal1::slot_type slot_type; + Net::Signals::Signal22, Net::Exception> finished; protected: - static slot_type empty_slot; - - Request(Connection *connection, uint16_t requestId, slot_type slot) - : RequestHandler(connection, requestId), exp(Net::Exception::NOT_FINISHED), isFinished(false) { - finished.connect(slot); - finished.connect(boost::bind(&Request::signalFinished, this)); - } - - virtual ~Request() { - wait(); - } + Request() : isFinished(false) {} - void finish(std::auto_ptr result) { + void signalFinished(boost::shared_ptr pkt, Net::Exception exp) { { boost::lock_guard lock(mutex); - res = result; isFinished = true; + packet = pkt; + exception = exp; } + finished.emit(pkt, exp); finishCond.notify_all(); - finished.emit(*this); - } - void finish(const XmlPacket& result) { - { - boost::lock_guard lock(mutex); - - res.reset(new XmlPacket(result)); - isFinished = true; - } - - finishCond.notify_all(); - finished.emit(*this); + RequestHandler::signalFinished(); } - void finishWithError(const Net::Exception &e) { - { - boost::lock_guard lock(mutex); + void signalFinished(boost::shared_ptr packet) { + signalFinished(packet, Net::Exception()); + } - exp = e; - isFinished = true; - } + void signalFinished(Net::Exception exp) { + signalFinished(boost::shared_ptr(), exp); + } - finishCond.notify_all(); - finished.emit(*this); + void signalFinished() { + signalFinished(boost::shared_ptr(), Net::Exception()); } virtual void sendRequest() = 0; - virtual void handlePacket(const XmlPacket &packet); + virtual void handlePacket(boost::shared_ptr packet); public: - const XmlPacket& getResult() throw(Net::Exception) { - boost::lock_guard lock(mutex); - - if(res.get()) - return *res; - - throw exp; + Net::Signals::Connection2 connectSignalFinished(const Net::Signals::Signal22, Net::Exception>::slot_type &slot) { + return finished.connect(slot); + } + void disconnectSignalFinished(const Net::Signals::Connection2 &con) { + finished.disconnect(con); } void wait() { @@ -119,9 +93,18 @@ class Request : public RequestHandler { while(!isFinished) finishCond.wait(lock); } + + std::pair, Net::Exception> getResult() { + boost::lock_guard lock(mutex); + + if(!isFinished) + return std::make_pair(boost::shared_ptr(), Net::Exception(Net::Exception::NOT_FINISHED)); + else + return std::make_pair(packet, exception); + } }; } } -#endif /* MAD_COMMON_XMLREQUEST_H_ */ +#endif /* MAD_COMMON_REQUEST_H_ */ diff --git a/src/Common/RequestHandler.cpp b/src/Common/RequestHandler.cpp new file mode 100644 index 0000000..218155d --- /dev/null +++ b/src/Common/RequestHandler.cpp @@ -0,0 +1,40 @@ +/* + * RequestHandler.cpp + * + * Copyright (C) 2009 Matthias Schiffer + * + * 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 3 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, see . + */ + +#include "RequestHandler.h" +#include "RequestManager.h" + +namespace Mad { +namespace Common { + +Connection* RequestHandler::getConnection() const { + return RequestManager::get()->requestMap.getRequestInfo(this).first; +} + +void RequestHandler::sendPacket(const XmlPacket &packet) { + std::pair requestInfo = RequestManager::get()->requestMap.getRequestInfo(this); + + if(!requestInfo.first) + return; + + requestInfo.first->sendPacket(packet, requestInfo.second); +} + +} +} diff --git a/src/Common/RequestHandler.h b/src/Common/RequestHandler.h index d35ab1b..87fccba 100644 --- a/src/Common/RequestHandler.h +++ b/src/Common/RequestHandler.h @@ -17,8 +17,8 @@ * with this program. If not, see . */ -#ifndef MAD_COMMON_XMLREQUESTHANDLER_H_ -#define MAD_COMMON_XMLREQUESTHANDLER_H_ +#ifndef MAD_COMMON_REQUESTHANDLER_H_ +#define MAD_COMMON_REQUESTHANDLER_H_ #include "Connection.h" #include "XmlPacket.h" @@ -26,6 +26,8 @@ #include #include +#include +#include namespace Mad { namespace Common { @@ -35,43 +37,42 @@ class RequestManager; class RequestHandler : private boost::noncopyable { private: - Net::Signals::Signal0 finished; + friend class RequestManager; - Connection *connection; - boost::uint16_t requestId; + boost::mutex mutex; - protected: - RequestHandler(Connection *connection0, boost::uint16_t requestId0) : connection(connection0), requestId(requestId0) {} + Net::Signals::Signal20 finished; - void signalFinished() { - finished.emit(); + void callHandlePacket(boost::shared_ptr packet) { + boost::lock_guard lock(mutex); + handlePacket(packet); } - Net::Signals::Connection connectSignalFinished(const Net::Signals::Signal0::slot_type &slot) { - return finished.connect(slot); - } + protected: + RequestHandler() {} - Connection* getConnection() const { - return connection; + void signalFinished() { + finished.emit(); } - boost::uint16_t getRequestId() const { - return requestId; - } + Connection* getConnection() const; - void sendPacket(const XmlPacket &packet) { - connection->sendPacket(packet, requestId); - } + void sendPacket(const XmlPacket &packet); - virtual void handlePacket(const XmlPacket &packet) = 0; + virtual void handlePacket(boost::shared_ptr packet) = 0; public: virtual ~RequestHandler() {} - friend class RequestManager; + Net::Signals::Connection2 connectSignalFinished(const Net::Signals::Signal20::slot_type &slot) { + return finished.connect(slot); + } + void disconnectSignalFinished(const Net::Signals::Connection2 &con) { + finished.disconnect(con); + } }; } } -#endif /* MAD_COMMON_XMLREQUESTHANDLER_H_ */ +#endif /* MAD_COMMON_REQUESTHANDLER_H_ */ diff --git a/src/Common/RequestHandlers/DisconnectRequestHandler.cpp b/src/Common/RequestHandlers/DisconnectRequestHandler.cpp index ac8e7dc..942da0a 100644 --- a/src/Common/RequestHandlers/DisconnectRequestHandler.cpp +++ b/src/Common/RequestHandlers/DisconnectRequestHandler.cpp @@ -25,8 +25,8 @@ namespace Mad { namespace Common { namespace RequestHandlers { -void DisconnectRequestHandler::handlePacket(const XmlPacket &packet) { - if(packet.getType() != "Disconnect") { +void DisconnectRequestHandler::handlePacket(boost::shared_ptr packet) { + if(packet->getType() != "Disconnect") { Logger::log(Logger::ERROR, "Received an unexpected packet."); XmlPacket ret; diff --git a/src/Common/RequestHandlers/DisconnectRequestHandler.h b/src/Common/RequestHandlers/DisconnectRequestHandler.h index 05b9c50..963f603 100644 --- a/src/Common/RequestHandlers/DisconnectRequestHandler.h +++ b/src/Common/RequestHandlers/DisconnectRequestHandler.h @@ -28,11 +28,7 @@ namespace RequestHandlers { class DisconnectRequestHandler : public RequestHandler { protected: - virtual void handlePacket(const XmlPacket &packet); - - public: - DisconnectRequestHandler(Connection *connection, uint16_t requestId) - : RequestHandler(connection, requestId) {} + virtual void handlePacket(boost::shared_ptr packet); }; } diff --git a/src/Common/RequestHandlers/FSInfoRequestHandler.cpp b/src/Common/RequestHandlers/FSInfoRequestHandler.cpp index 9044c68..845258b 100644 --- a/src/Common/RequestHandlers/FSInfoRequestHandler.cpp +++ b/src/Common/RequestHandlers/FSInfoRequestHandler.cpp @@ -27,8 +27,8 @@ namespace Mad { namespace Common { namespace RequestHandlers { -void FSInfoRequestHandler::handlePacket(const XmlPacket &packet) { - if(packet.getType() != "FSInfo") { +void FSInfoRequestHandler::handlePacket(boost::shared_ptr packet) { + if(packet->getType() != "FSInfo") { Logger::log(Logger::ERROR, "Received an unexpected packet."); XmlPacket ret; diff --git a/src/Common/RequestHandlers/FSInfoRequestHandler.h b/src/Common/RequestHandlers/FSInfoRequestHandler.h index 47fcbd8..6d21787 100644 --- a/src/Common/RequestHandlers/FSInfoRequestHandler.h +++ b/src/Common/RequestHandlers/FSInfoRequestHandler.h @@ -31,11 +31,7 @@ namespace RequestHandlers { class FSInfoRequestHandler : public RequestHandler { protected: - virtual void handlePacket(const XmlPacket &packet); - - public: - FSInfoRequestHandler(Connection *connection, uint16_t requestId) - : RequestHandler(connection, requestId) {} + virtual void handlePacket(boost::shared_ptr packet); }; } diff --git a/src/Common/RequestHandlers/StatusRequestHandler.cpp b/src/Common/RequestHandlers/StatusRequestHandler.cpp index e766670..989ce7c 100644 --- a/src/Common/RequestHandlers/StatusRequestHandler.cpp +++ b/src/Common/RequestHandlers/StatusRequestHandler.cpp @@ -28,8 +28,8 @@ namespace Mad { namespace Common { namespace RequestHandlers { -void StatusRequestHandler::handlePacket(const XmlPacket &packet) { - if(packet.getType() != "GetStatus") { +void StatusRequestHandler::handlePacket(boost::shared_ptr packet) { + if(packet->getType() != "GetStatus") { Logger::log(Logger::ERROR, "Received an unexpected packet."); XmlPacket ret; diff --git a/src/Common/RequestHandlers/StatusRequestHandler.h b/src/Common/RequestHandlers/StatusRequestHandler.h index 151852c..656a1a5 100644 --- a/src/Common/RequestHandlers/StatusRequestHandler.h +++ b/src/Common/RequestHandlers/StatusRequestHandler.h @@ -29,11 +29,7 @@ namespace RequestHandlers { class StatusRequestHandler : public RequestHandler { protected: - virtual void handlePacket(const XmlPacket &packet); - - public: - StatusRequestHandler(Connection *connection, uint16_t requestId) - : RequestHandler(connection, requestId) {} + virtual void handlePacket(boost::shared_ptr packet); }; } diff --git a/src/Common/RequestManager.cpp b/src/Common/RequestManager.cpp index da9979a..3817ff5 100644 --- a/src/Common/RequestManager.cpp +++ b/src/Common/RequestManager.cpp @@ -29,71 +29,105 @@ namespace Common { RequestManager RequestManager::requestManager; -bool RequestManager::RequestMap::addRequest(boost::uint16_t id, boost::shared_ptr info) { - if(!insert(std::make_pair(id, info)).second) +void RequestManager::RequestMap::unregisterConnection(Connection *connection) { + std::map::iterator idMap = connectionMap.find(connection); + if(idMap == connectionMap.end()) + return; + + for(IdMap::iterator request = idMap->second.begin(); request != idMap->second.end(); ++request) + handlerMap.erase(request->second.get()); + + connectionMap.erase(idMap); +} + +bool RequestManager::RequestMap::addRequest(Connection *con, boost::uint16_t id, boost::shared_ptr request) { + std::map::iterator idMap = connectionMap.find(con); + if(idMap == connectionMap.end()) + return false; + + if(!idMap->second.insert(std::make_pair(id, request)).second) return false; - info->connectSignalFinished(boost::bind(&RequestManager::RequestMap::deleteRequest, this, id)); + if(!handlerMap.insert(std::make_pair(request.get(), std::make_pair(con, id))).second) { + idMap->second.erase(id); + return false; + } return true; } -boost::shared_ptr RequestManager::RequestMap::findRequest(boost::uint16_t id) { - iterator it = find(id); - if(it == end()) +boost::shared_ptr RequestManager::RequestMap::findRequest(Connection *con, boost::uint16_t id) { + std::map::iterator idMap = connectionMap.find(con); + if(idMap == connectionMap.end()) + return boost::shared_ptr(); + + IdMap::iterator it = idMap->second.find(id); + if(it == idMap->second.end()) return boost::shared_ptr(); return it->second; } -void RequestManager::RequestMap::deleteRequest(boost::uint16_t id) { - Net::ThreadManager::get()->pushWork(boost::bind(&RequestMap::doDeleteRequest, this, id)); +void RequestManager::RequestMap::deleteRequest(Connection *con, boost::uint16_t id) { + std::map::iterator idMap = connectionMap.find(con); + if(idMap == connectionMap.end()) + return; + + IdMap::iterator it = idMap->second.find(id); + if(it == idMap->second.end()) + return; + + handlerMap.erase(it->second.get()); + idMap->second.erase(it); } -void RequestManager::RequestMap::doDeleteRequest(boost::uint16_t id) { - erase(id); +std::pair RequestManager::RequestMap::getRequestInfo(const RequestHandler *requestHandler) { + HandlerMap::iterator it = handlerMap.find(requestHandler); + if(it == handlerMap.end()) + return std::pair(0, 0); + else + return it->second; } -void RequestManager::receiveHandler(Connection *connection, const XmlPacket &packet, boost::uint16_t requestId) { +void RequestManager::receiveHandler(Connection *connection, boost::shared_ptr packet, boost::uint16_t requestId) { boost::upgrade_lock lock(mutex); - std::map >::iterator it = requestMaps.find(connection); - if(it == requestMaps.end()) { - // TODO: Error - Logger::log(Logger::ERROR, "Received a packet from an unregistered connection."); + boost::shared_ptr request = requestMap.findRequest(connection, requestId); + if(request) { + lock.unlock(); + request->callHandlePacket(packet); return; } - boost::shared_ptr requestMap = it->second; - boost::shared_ptr request = requestMap->findRequest(requestId); - - if(request) { - lock.unlock(); - request->handlePacket(packet); + if(!requestMap.isConnectionRegistered(connection)) { + // TODO: Error + Logger::log(Logger::ERROR, "Received a packet from an unregistered connection."); return; } - std::map >::iterator factoryIt = requestHandlerFactories.find(packet.getType()); + std::map >::iterator factoryIt = requestHandlerFactories.find(packet->getType()); if(factoryIt != requestHandlerFactories.end()) { { boost::upgrade_to_unique_lock upgradeLock(lock); - request = factoryIt->second->createRequestHandler(connection, requestId); - requestMap->addRequest(requestId, request); + request = factoryIt->second->createRequestHandler(); + requestMap.addRequest(connection, requestId, request); + request->connectSignalFinished(boost::bind(&RequestManager::handleRequestFinished, this, connection, requestId)); + } lock.unlock(); - request->handlePacket(packet); + request->callHandlePacket(packet); return; } lock.unlock(); - Logger::logf(Logger::ERROR, "Received an unexpected packet with type '%s'.", packet.getType().c_str()); + Logger::logf(Logger::ERROR, "Received an unexpected packet with type '%s'.", packet->getType().c_str()); XmlPacket ret; ret.setType("Error"); @@ -102,28 +136,37 @@ void RequestManager::receiveHandler(Connection *connection, const XmlPacket &pac connection->sendPacket(ret, requestId); } -boost::shared_ptr RequestManager::_getUnusedRequestId(Connection *connection, boost::uint16_t *requestId) { - std::map >::iterator it = requestMaps.find(connection); +// XXX Error handling! +bool RequestManager::sendRequest(Connection *connection, boost::shared_ptr request) { + boost::unique_lock lock(mutex); - if(it == requestMaps.end()) { + if(!requestMap.isConnectionRegistered(connection)) { Logger::log(Logger::CRITICAL, "Trying to send a request over an unregistered connecion."); - return boost::shared_ptr(); + return false; } - boost::shared_ptr requestMap = it->second; + uint16_t requestId = _getUnusedRequestId(connection); + requestMap.addRequest(connection, requestId, request); + request->connectSignalFinished(boost::bind(&RequestManager::handleRequestFinished, this, connection, requestId)); + lock.unlock(); + + Net::ThreadManager::get()->pushWork(boost::bind(&Request::sendRequest, request)); - do { - *requestId = _getRequestId(); - } while(requestMap->findRequest(*requestId)); + return true; +} - return requestMap; +boost::uint16_t RequestManager::_getUnusedRequestId(Connection *connection) { + while(true) { + boost::uint16_t requestId = _getRequestId(); + if(!requestMap.findRequest(connection, requestId)) + return requestId; + } } void RequestManager::registerConnection(Connection *connection) { boost::lock_guard lock(mutex); - requestMaps.insert(std::make_pair(connection, new RequestMap())); - + requestMap.registerConnection(connection); connection->connectSignalReceive(boost::bind(&RequestManager::receiveHandler, this, connection, _1, _2)); } diff --git a/src/Common/RequestManager.h b/src/Common/RequestManager.h index bd1c12d..07a7c05 100644 --- a/src/Common/RequestManager.h +++ b/src/Common/RequestManager.h @@ -21,7 +21,6 @@ #define MAD_COMMON_REQUESTMANAGER_H_ #include "Request.h" -#include #include #include @@ -40,29 +39,49 @@ namespace Common { class RequestManager : boost::noncopyable { private: - class RequestMap : private std::map >, boost::noncopyable { - public: - bool addRequest(boost::uint16_t id, boost::shared_ptr info); - boost::shared_ptr findRequest(boost::uint16_t id); - void deleteRequest(boost::uint16_t id); + friend class RequestHandler; + class RequestMap : private boost::noncopyable { private: - void doDeleteRequest(boost::uint16_t id); + typedef std::map > IdMap; + typedef std::map > HandlerMap; + + std::map connectionMap; + HandlerMap handlerMap; + + public: + void registerConnection(Connection *connection) { + connectionMap.insert(std::make_pair(connection, IdMap())); + } + + void unregisterConnection(Connection *connection); + + bool isConnectionRegistered(Connection *connection) const { + return connectionMap.count(connection); + } + + bool addRequest(Connection *con, boost::uint16_t id, boost::shared_ptr info); + boost::shared_ptr findRequest(Connection *con, boost::uint16_t id); + void deleteRequest(Connection *con, boost::uint16_t id); + + std::pair getRequestInfo(const RequestHandler *requestHandler); }; + + class RequestHandlerFactory { protected: RequestHandlerFactory() {} public: - virtual boost::shared_ptr createRequestHandler(Connection *connection, boost::uint16_t requestId) = 0; + virtual boost::shared_ptr createRequestHandler() = 0; virtual ~RequestHandlerFactory() {} }; template class SpecificRequestHandlerFactory : public RequestHandlerFactory { public: - virtual boost::shared_ptr createRequestHandler(Connection *connection, boost::uint16_t requestId) { - return boost::shared_ptr(new T(connection, requestId)); + virtual boost::shared_ptr createRequestHandler() { + return boost::shared_ptr(new T()); } }; @@ -70,7 +89,8 @@ class RequestManager : boost::noncopyable { boost::shared_mutex mutex; - std::map > requestMaps; + RequestMap requestMap; + bool server; boost::uint16_t lastRequestId; @@ -80,9 +100,14 @@ class RequestManager : boost::noncopyable { return lastRequestId+=2; } - void receiveHandler(Connection *connection, const XmlPacket &packet, boost::uint16_t requestId); + void receiveHandler(Connection *connection, boost::shared_ptr packet, boost::uint16_t requestId); + + void handleRequestFinished(Connection *con, boost::uint16_t requestId) { + boost::lock_guard lock(mutex); + requestMap.deleteRequest(con, requestId); + } - boost::shared_ptr _getUnusedRequestId(Connection *connection, boost::uint16_t *requestId); + boost::uint16_t _getUnusedRequestId(Connection *connection); bool send(Request *request); @@ -113,7 +138,7 @@ class RequestManager : boost::noncopyable { void unregisterConnection(Connection *connection) { boost::lock_guard lock(mutex); - requestMaps.erase(connection); + requestMap.unregisterConnection(connection); } template void registerPacketType(const std::string &type) { @@ -126,110 +151,7 @@ class RequestManager : boost::noncopyable { requestHandlerFactories.erase(type); } - template - boost::shared_ptr sendRequest0(Connection *connection, Request::slot_type slot = Request::empty_slot) { - boost::unique_lock lock(mutex); - - boost::shared_ptr requestMap; - boost::uint16_t requestId; - - requestMap = _getUnusedRequestId(connection, &requestId); - - if(!requestMap) - return boost::shared_ptr(); - - boost::shared_ptr request(new T(connection, requestId, slot)); - requestMap->addRequest(requestId, request); - lock.unlock(); - - Net::ThreadManager::get()->pushWork(boost::bind(&Request::sendRequest, request)); - - return request; - } - - template - boost::shared_ptr sendRequest1(Connection *connection, T1 t1, Request::slot_type slot = Request::empty_slot) { - boost::unique_lock lock(mutex); - - boost::shared_ptr requestMap; - boost::uint16_t requestId; - - requestMap = _getUnusedRequestId(connection, &requestId); - - if(!requestMap) - return boost::shared_ptr(); - - boost::shared_ptr request(new T(connection, requestId, slot, t1)); - requestMap->addRequest(requestId, request); - lock.unlock(); - - Net::ThreadManager::get()->pushWork(boost::bind(&Request::sendRequest, request)); - - return request; - } - - template - boost::shared_ptr sendRequest2(Connection *connection, T1 t1, T2 t2, Request::slot_type slot = Request::empty_slot) { - boost::unique_lock lock(mutex); - - boost::shared_ptr requestMap; - boost::uint16_t requestId; - - requestMap = _getUnusedRequestId(connection, &requestId); - - if(!requestMap) - return boost::shared_ptr(); - - boost::shared_ptr request(new T(connection, requestId, slot, t1, t2)); - requestMap->addRequest(requestId, request); - lock.unlock(); - - Net::ThreadManager::get()->pushWork(boost::bind(&Request::sendRequest, request)); - - return request; - } - - template - boost::shared_ptr sendRequest3(Connection *connection, T1 t1, T2 t2, T3 t3, Request::slot_type slot = Request::empty_slot) { - boost::unique_lock lock(mutex); - - boost::shared_ptr requestMap; - boost::uint16_t requestId; - - requestMap = _getUnusedRequestId(connection, &requestId); - - if(!requestMap) - return boost::shared_ptr(); - - boost::shared_ptr request(new T(connection, requestId, slot, t1, t2, t3)); - requestMap->addRequest(requestId, request); - lock.unlock(); - - Net::ThreadManager::get()->pushWork(boost::bind(&Request::sendRequest, request)); - - return request; - } - - template - boost::shared_ptr sendRequest4(Connection *connection, T1 t1, T2 t2, T3 t3, T4 t4, Request::slot_type slot = Request::empty_slot) { - boost::unique_lock lock(mutex); - - boost::shared_ptr requestMap; - boost::uint16_t requestId; - - requestMap = _getUnusedRequestId(connection, &requestId); - - if(!requestMap) - return boost::shared_ptr(); - - boost::shared_ptr request(new T(connection, requestId, slot, t1, t2, t3, t4)); - requestMap->addRequest(requestId, request); - lock.unlock(); - - Net::ThreadManager::get()->pushWork(boost::bind(&Request::sendRequest, request)); - - return request; - } + bool sendRequest(Connection *connection, boost::shared_ptr request); }; } diff --git a/src/Common/Requests/DisconnectRequest.cpp b/src/Common/Requests/DisconnectRequest.cpp index 3fac25b..249bbc1 100644 --- a/src/Common/Requests/DisconnectRequest.cpp +++ b/src/Common/Requests/DisconnectRequest.cpp @@ -30,19 +30,19 @@ void DisconnectRequest::sendRequest() { sendPacket(packet); } -void DisconnectRequest::handlePacket(const XmlPacket &packet) { - if(packet.getType() == "Error") { - finishWithError(Net::Exception(packet["Where"], packet["ErrorCode"], packet["SubCode"], packet["SubSubCode"])); +void DisconnectRequest::handlePacket(boost::shared_ptr packet) { + if(packet->getType() == "Error") { + signalFinished(Net::Exception((*packet)["Where"], (*packet)["ErrorCode"], (*packet)["SubCode"], (*packet)["SubSubCode"])); return; } - else if(packet.getType() != "OK") { - finishWithError(Net::Exception(Net::Exception::UNEXPECTED_PACKET)); + else if(packet->getType() != "OK") { + signalFinished(Net::Exception(Net::Exception::UNEXPECTED_PACKET)); return; // TODO Logging } getConnection()->disconnect(); - finish(packet); + signalFinished(packet); } } diff --git a/src/Common/Requests/DisconnectRequest.h b/src/Common/Requests/DisconnectRequest.h index b4fd4db..6da0ac9 100644 --- a/src/Common/Requests/DisconnectRequest.h +++ b/src/Common/Requests/DisconnectRequest.h @@ -29,11 +29,7 @@ namespace Requests { class DisconnectRequest : public Request { protected: virtual void sendRequest(); - virtual void handlePacket(const XmlPacket &packet); - - public: - DisconnectRequest(Connection *connection, uint16_t requestId, slot_type slot) - : Request(connection, requestId, slot) {} + virtual void handlePacket(boost::shared_ptr packet); }; } diff --git a/src/Common/Requests/FSInfoRequest.h b/src/Common/Requests/FSInfoRequest.h index 1db7753..250889a 100644 --- a/src/Common/Requests/FSInfoRequest.h +++ b/src/Common/Requests/FSInfoRequest.h @@ -28,8 +28,7 @@ namespace Requests { class FSInfoRequest : public SimpleRequest { public: - FSInfoRequest(Connection *connection, uint16_t requestId, slot_type slot) - : SimpleRequest(connection, requestId, slot, "FSInfo") {} + FSInfoRequest() : SimpleRequest("FSInfo") {} }; } diff --git a/src/Common/Requests/GroupListRequest.h b/src/Common/Requests/GroupListRequest.h index 5aad003..b1e4115 100644 --- a/src/Common/Requests/GroupListRequest.h +++ b/src/Common/Requests/GroupListRequest.h @@ -28,8 +28,7 @@ namespace Requests { class GroupListRequest : public SimpleRequest { public: - GroupListRequest(Connection *connection, uint16_t requestId, slot_type slot) - : SimpleRequest(connection, requestId, slot, "ListGroups") {} + GroupListRequest() : SimpleRequest("ListGroups") {} }; } diff --git a/src/Common/Requests/GroupUserListRequest.h b/src/Common/Requests/GroupUserListRequest.h index fd56a2f..bb735f1 100644 --- a/src/Common/Requests/GroupUserListRequest.h +++ b/src/Common/Requests/GroupUserListRequest.h @@ -34,8 +34,7 @@ class GroupUserListRequest : public Request { virtual void sendRequest(); public: - GroupUserListRequest(Connection *connection, uint16_t requestId, slot_type slot, unsigned long gid0) - : Request(connection, requestId, slot), gid(gid0) {} + GroupUserListRequest(unsigned long gid0) : gid(gid0) {} }; } diff --git a/src/Common/Requests/IdentifyRequest.h b/src/Common/Requests/IdentifyRequest.h index 3798909..3084ce6 100644 --- a/src/Common/Requests/IdentifyRequest.h +++ b/src/Common/Requests/IdentifyRequest.h @@ -36,8 +36,7 @@ class IdentifyRequest : public Common::Request { virtual void sendRequest(); public: - IdentifyRequest(Common::Connection *connection, uint16_t requestId, slot_type slot, const std::string &hostname0 = std::string()) - : Common::Request(connection, requestId, slot), hostname(hostname0) {} + IdentifyRequest(const std::string &hostname0 = std::string()) : hostname(hostname0) {} }; } diff --git a/src/Common/Requests/SimpleRequest.h b/src/Common/Requests/SimpleRequest.h index 2c3070a..d381ecf 100644 --- a/src/Common/Requests/SimpleRequest.h +++ b/src/Common/Requests/SimpleRequest.h @@ -34,8 +34,7 @@ class SimpleRequest : public Request { virtual void sendRequest(); - SimpleRequest(Connection *connection, uint16_t requestId, slot_type slot, const std::string &type0) - : Request(connection, requestId, slot), type(type0) {} + SimpleRequest(const std::string &type0) : type(type0) {} }; } diff --git a/src/Common/Requests/StatusRequest.h b/src/Common/Requests/StatusRequest.h index 0663fc4..b9b9f02 100644 --- a/src/Common/Requests/StatusRequest.h +++ b/src/Common/Requests/StatusRequest.h @@ -28,8 +28,7 @@ namespace Requests { class StatusRequest : public SimpleRequest { public: - StatusRequest(Connection *connection, uint16_t requestId, slot_type slot) - : SimpleRequest(connection, requestId, slot, "GetStatus") {} + StatusRequest() : SimpleRequest("GetStatus") {} }; } diff --git a/src/Common/Requests/UserGroupListRequest.h b/src/Common/Requests/UserGroupListRequest.h index 2ee33d9..82db411 100644 --- a/src/Common/Requests/UserGroupListRequest.h +++ b/src/Common/Requests/UserGroupListRequest.h @@ -34,8 +34,7 @@ class UserGroupListRequest : public Request { virtual void sendRequest(); public: - UserGroupListRequest(Connection *connection, uint16_t requestId, slot_type slot, unsigned long uid0) - : Request(connection, requestId, slot), uid(uid0) {} + UserGroupListRequest(unsigned long uid0) : uid(uid0) {} }; } diff --git a/src/Common/Requests/UserInfoRequest.h b/src/Common/Requests/UserInfoRequest.h index 27cf1af..c9ac89b 100644 --- a/src/Common/Requests/UserInfoRequest.h +++ b/src/Common/Requests/UserInfoRequest.h @@ -34,8 +34,8 @@ class UserInfoRequest : public Request { virtual void sendRequest(); public: - UserInfoRequest(Connection *connection, uint16_t requestId, slot_type slot, unsigned long uid0) - : Request(connection, requestId, slot), uid(uid0) {} + UserInfoRequest(unsigned long uid0) + : uid(uid0) {} }; } diff --git a/src/Common/Requests/UserListRequest.h b/src/Common/Requests/UserListRequest.h index 7ab3ec7..9b69564 100644 --- a/src/Common/Requests/UserListRequest.h +++ b/src/Common/Requests/UserListRequest.h @@ -28,8 +28,7 @@ namespace Requests { class UserListRequest : public SimpleRequest { public: - UserListRequest(Connection *connection, uint16_t requestId, slot_type slot) - : SimpleRequest(connection, requestId, slot, "ListUsers") {} + UserListRequest() : SimpleRequest("ListUsers") {} }; } -- cgit v1.2.3