diff options
author | Matthias Schiffer <matthias@gamezock.de> | 2009-06-04 22:23:07 +0200 |
---|---|---|
committer | Matthias Schiffer <matthias@gamezock.de> | 2009-06-04 22:23:07 +0200 |
commit | 0b27c37fe95c6aced613d51a3624f8930a96ad3f (patch) | |
tree | 5cb92568f70fe9789e99633ec71048389efb7fa4 /src/Common | |
parent | 50d92f64547c5c06851976ceab5ed631ec93f647 (diff) | |
download | mad-0b27c37fe95c6aced613d51a3624f8930a96ad3f.tar mad-0b27c37fe95c6aced613d51a3624f8930a96ad3f.zip |
RequestHandler-Interface ?berarbeitet
Diffstat (limited to 'src/Common')
26 files changed, 260 insertions, 293 deletions
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<Net::Packet> packet) { - signalReceive.emit(XmlPacket(*packet), packet->getRequestId()); + signalReceive.emit(boost::shared_ptr<XmlPacket>(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<const XmlPacket&, uint16_t> signalReceive; + Net::Signals::Signal22<boost::shared_ptr<const XmlPacket>, 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<const XmlPacket&, uint16_t>::slot_type &slot) { + Net::Signals::Connection2 connectSignalReceive(const Net::Signals::Signal22<boost::shared_ptr<const XmlPacket>, 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<const XmlPacket> 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 <http://www.gnu.org/licenses/>. */ -#ifndef MAD_COMMON_XMLREQUEST_H_ -#define MAD_COMMON_XMLREQUEST_H_ +#ifndef MAD_COMMON_REQUEST_H_ +#define MAD_COMMON_REQUEST_H_ #include "RequestHandler.h" #include <Net/Exception.h> @@ -37,80 +37,54 @@ class Request : public RequestHandler { private: friend class RequestManager; - Net::Signals::Signal1<Request&> finished; - - std::auto_ptr<XmlPacket> res; - Net::Exception exp; - boost::mutex mutex; boost::condition_variable finishCond; bool isFinished; - static void doNothing(Request&) {} + boost::shared_ptr<const XmlPacket> packet; + Net::Exception exception; - public: - typedef Net::Signals::Signal1<Request&>::slot_type slot_type; + Net::Signals::Signal22<boost::shared_ptr<const XmlPacket>, 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<XmlPacket> result) { + void signalFinished(boost::shared_ptr<const XmlPacket> pkt, Net::Exception exp) { { boost::lock_guard<boost::mutex> 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<boost::mutex> 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<boost::mutex> lock(mutex); + void signalFinished(boost::shared_ptr<const XmlPacket> packet) { + signalFinished(packet, Net::Exception()); + } - exp = e; - isFinished = true; - } + void signalFinished(Net::Exception exp) { + signalFinished(boost::shared_ptr<const XmlPacket>(), exp); + } - finishCond.notify_all(); - finished.emit(*this); + void signalFinished() { + signalFinished(boost::shared_ptr<const XmlPacket>(), Net::Exception()); } virtual void sendRequest() = 0; - virtual void handlePacket(const XmlPacket &packet); + virtual void handlePacket(boost::shared_ptr<const XmlPacket> packet); public: - const XmlPacket& getResult() throw(Net::Exception) { - boost::lock_guard<boost::mutex> lock(mutex); - - if(res.get()) - return *res; - - throw exp; + Net::Signals::Connection2 connectSignalFinished(const Net::Signals::Signal22<boost::shared_ptr<const XmlPacket>, 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<boost::shared_ptr<const XmlPacket>, Net::Exception> getResult() { + boost::lock_guard<boost::mutex> lock(mutex); + + if(!isFinished) + return std::make_pair(boost::shared_ptr<const XmlPacket>(), 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 <matthias@gamezock.de> + * + * 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 <http://www.gnu.org/licenses/>. + */ + +#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<Connection*, boost::uint16_t> 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 <http://www.gnu.org/licenses/>. */ -#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 <Net/Signals/Signals.h> #include <boost/cstdint.hpp> +#include <boost/thread/locks.hpp> +#include <boost/thread/mutex.hpp> 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<const XmlPacket> packet) { + boost::lock_guard<boost::mutex> 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<const XmlPacket> 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<const XmlPacket> 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<const XmlPacket> 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<const XmlPacket> 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<const XmlPacket> 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<const XmlPacket> 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<const XmlPacket> 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<RequestHandler> info) { - if(!insert(std::make_pair(id, info)).second) +void RequestManager::RequestMap::unregisterConnection(Connection *connection) { + std::map<Connection*, IdMap>::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<RequestHandler> request) { + std::map<Connection*, IdMap>::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<RequestHandler> RequestManager::RequestMap::findRequest(boost::uint16_t id) { - iterator it = find(id); - if(it == end()) +boost::shared_ptr<RequestHandler> RequestManager::RequestMap::findRequest(Connection *con, boost::uint16_t id) { + std::map<Connection*, IdMap>::iterator idMap = connectionMap.find(con); + if(idMap == connectionMap.end()) + return boost::shared_ptr<RequestHandler>(); + + IdMap::iterator it = idMap->second.find(id); + if(it == idMap->second.end()) return boost::shared_ptr<RequestHandler>(); 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<Connection*, IdMap>::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<Connection*, boost::uint16_t> RequestManager::RequestMap::getRequestInfo(const RequestHandler *requestHandler) { + HandlerMap::iterator it = handlerMap.find(requestHandler); + if(it == handlerMap.end()) + return std::pair<Connection*, boost::uint16_t>(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<const XmlPacket> packet, boost::uint16_t requestId) { boost::upgrade_lock<boost::shared_mutex> lock(mutex); - std::map<Connection*, boost::shared_ptr<RequestMap> >::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<RequestHandler> request = requestMap.findRequest(connection, requestId); + if(request) { + lock.unlock(); + request->callHandlePacket(packet); return; } - boost::shared_ptr<RequestMap> requestMap = it->second; - boost::shared_ptr<RequestHandler> 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<std::string, boost::shared_ptr<RequestHandlerFactory> >::iterator factoryIt = requestHandlerFactories.find(packet.getType()); + std::map<std::string, boost::shared_ptr<RequestHandlerFactory> >::iterator factoryIt = requestHandlerFactories.find(packet->getType()); if(factoryIt != requestHandlerFactories.end()) { { boost::upgrade_to_unique_lock<boost::shared_mutex> 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::RequestMap> RequestManager::_getUnusedRequestId(Connection *connection, boost::uint16_t *requestId) { - std::map<Connection*, boost::shared_ptr<RequestMap> >::iterator it = requestMaps.find(connection); +// XXX Error handling! +bool RequestManager::sendRequest(Connection *connection, boost::shared_ptr<Request> request) { + boost::unique_lock<boost::shared_mutex> 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<RequestMap>(); + return false; } - boost::shared_ptr<RequestMap> 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<boost::shared_mutex> 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 <Net/ThreadManager.h> #include <map> #include <memory> @@ -40,29 +39,49 @@ namespace Common { class RequestManager : boost::noncopyable { private: - class RequestMap : private std::map<boost::uint16_t, boost::shared_ptr<RequestHandler> >, boost::noncopyable { - public: - bool addRequest(boost::uint16_t id, boost::shared_ptr<RequestHandler> info); - boost::shared_ptr<RequestHandler> 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<boost::uint16_t, boost::shared_ptr<RequestHandler> > IdMap; + typedef std::map<const RequestHandler*, std::pair<Connection*, boost::uint16_t> > HandlerMap; + + std::map<Connection*, IdMap> 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<RequestHandler> info); + boost::shared_ptr<RequestHandler> findRequest(Connection *con, boost::uint16_t id); + void deleteRequest(Connection *con, boost::uint16_t id); + + std::pair<Connection*, boost::uint16_t> getRequestInfo(const RequestHandler *requestHandler); }; + + class RequestHandlerFactory { protected: RequestHandlerFactory() {} public: - virtual boost::shared_ptr<RequestHandler> createRequestHandler(Connection *connection, boost::uint16_t requestId) = 0; + virtual boost::shared_ptr<RequestHandler> createRequestHandler() = 0; virtual ~RequestHandlerFactory() {} }; template<class T> class SpecificRequestHandlerFactory : public RequestHandlerFactory { public: - virtual boost::shared_ptr<RequestHandler> createRequestHandler(Connection *connection, boost::uint16_t requestId) { - return boost::shared_ptr<RequestHandler>(new T(connection, requestId)); + virtual boost::shared_ptr<RequestHandler> createRequestHandler() { + return boost::shared_ptr<RequestHandler>(new T()); } }; @@ -70,7 +89,8 @@ class RequestManager : boost::noncopyable { boost::shared_mutex mutex; - std::map<Connection*, boost::shared_ptr<RequestMap> > 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<const XmlPacket> packet, boost::uint16_t requestId); + + void handleRequestFinished(Connection *con, boost::uint16_t requestId) { + boost::lock_guard<boost::shared_mutex> lock(mutex); + requestMap.deleteRequest(con, requestId); + } - boost::shared_ptr<RequestMap> _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<boost::shared_mutex> lock(mutex); - requestMaps.erase(connection); + requestMap.unregisterConnection(connection); } template <class T> void registerPacketType(const std::string &type) { @@ -126,110 +151,7 @@ class RequestManager : boost::noncopyable { requestHandlerFactories.erase(type); } - template <class T> - boost::shared_ptr<Request> sendRequest0(Connection *connection, Request::slot_type slot = Request::empty_slot) { - boost::unique_lock<boost::shared_mutex> lock(mutex); - - boost::shared_ptr<RequestMap> requestMap; - boost::uint16_t requestId; - - requestMap = _getUnusedRequestId(connection, &requestId); - - if(!requestMap) - return boost::shared_ptr<Request>(); - - boost::shared_ptr<Request> request(new T(connection, requestId, slot)); - requestMap->addRequest(requestId, request); - lock.unlock(); - - Net::ThreadManager::get()->pushWork(boost::bind(&Request::sendRequest, request)); - - return request; - } - - template <class T, typename T1> - boost::shared_ptr<Request> sendRequest1(Connection *connection, T1 t1, Request::slot_type slot = Request::empty_slot) { - boost::unique_lock<boost::shared_mutex> lock(mutex); - - boost::shared_ptr<RequestMap> requestMap; - boost::uint16_t requestId; - - requestMap = _getUnusedRequestId(connection, &requestId); - - if(!requestMap) - return boost::shared_ptr<Request>(); - - boost::shared_ptr<Request> 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 <class T, typename T1, typename T2> - boost::shared_ptr<Request> sendRequest2(Connection *connection, T1 t1, T2 t2, Request::slot_type slot = Request::empty_slot) { - boost::unique_lock<boost::shared_mutex> lock(mutex); - - boost::shared_ptr<RequestMap> requestMap; - boost::uint16_t requestId; - - requestMap = _getUnusedRequestId(connection, &requestId); - - if(!requestMap) - return boost::shared_ptr<Request>(); - - boost::shared_ptr<Request> 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 <class T, typename T1, typename T2, typename T3> - boost::shared_ptr<Request> sendRequest3(Connection *connection, T1 t1, T2 t2, T3 t3, Request::slot_type slot = Request::empty_slot) { - boost::unique_lock<boost::shared_mutex> lock(mutex); - - boost::shared_ptr<RequestMap> requestMap; - boost::uint16_t requestId; - - requestMap = _getUnusedRequestId(connection, &requestId); - - if(!requestMap) - return boost::shared_ptr<Request>(); - - boost::shared_ptr<T> 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 <class T, typename T1, typename T2, typename T3, typename T4> - boost::shared_ptr<Request> sendRequest4(Connection *connection, T1 t1, T2 t2, T3 t3, T4 t4, Request::slot_type slot = Request::empty_slot) { - boost::unique_lock<boost::shared_mutex> lock(mutex); - - boost::shared_ptr<RequestMap> requestMap; - boost::uint16_t requestId; - - requestMap = _getUnusedRequestId(connection, &requestId); - - if(!requestMap) - return boost::shared_ptr<Request>(); - - boost::shared_ptr<Request> 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> 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<const XmlPacket> 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<const XmlPacket> 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") {} }; } |