/* * RequestManager.cpp * * Copyright (C) 2008 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 "RequestManager.h" #include "RequestHandlers/DisconnectRequestHandler.h" #include "Logger.h" #include #include namespace Mad { namespace Common { RequestManager RequestManager::requestManager; RequestManager::RequestMap::~RequestMap() { for(iterator it = begin(); it != end(); ++it) delete it->second; } bool RequestManager::RequestMap::addRequest(uint16_t id, RequestHandler *info) { if(!insert(std::make_pair(id, info)).second) return false; info->signalFinished().connect(sigc::hide_return(sigc::bind(sigc::mem_fun(this, &RequestManager::RequestMap::deleteRequest), id))); return true; } RequestHandler* RequestManager::RequestMap::findRequest(uint16_t id) { iterator it = find(id); if(it == end()) return 0; return it->second; } bool RequestManager::RequestMap::deleteRequest(uint16_t id) { iterator it = find(id); if(it == end()) return false; delete it->second; erase(it); return true; } void RequestManager::receiveHandler(Connection *connection, const XmlPacket &packet, uint16_t requestId) { std::map::iterator it = requestMaps.find(connection); if(it == requestMaps.end()) { // TODO: Error Logger::log(Logger::ERROR, "Received a packet from an unregistered connection."); return; } RequestMap *requestMap = it->second; RequestHandler *request = requestMap->findRequest(requestId); if(request) { request->handlePacket(packet); return; } std::map::iterator factoryIt = requestHandlerFactories.find(packet.getType()); if(factoryIt != requestHandlerFactories.end()) { request = factoryIt->second->createRequestHandler(connection, requestId); requestMap->addRequest(requestId, request); request->handlePacket(packet); return; } Logger::logf(Logger::ERROR, "Received an unexpected packet with type '%s'.", packet.getType().c_str()); XmlPacket ret; ret.setType("Error"); ret.add("ErrorCode", Net::Exception::UNEXPECTED_PACKET); connection->sendPacket(ret, requestId); } RequestManager::RequestMap* RequestManager::getUnusedRequestId(Connection *connection, uint16_t *requestId) { std::map::iterator it = requestMaps.find(connection); if(it == requestMaps.end()) { Logger::log(Logger::CRITICAL, "Trying to send a request over an unregistered connecion."); return 0; } RequestMap *requestMap = it->second; do { *requestId = getRequestId(); } while(requestMap->findRequest(*requestId)); return requestMap; } void RequestManager::registerConnection(Connection *connection) { requestMaps.insert(std::make_pair(connection, new RequestMap())); connection->signalReceive().connect(sigc::bind<0>(sigc::mem_fun(this, &RequestManager::receiveHandler), connection)); } void RequestManager::unregisterConnection(Connection *connection) { std::map::iterator it = requestMaps.find(connection); if(it != requestMaps.end()) { delete it->second; requestMaps.erase(it); } } void RequestManager::unregisterPacketType(const std::string &type) { std::map::iterator it = requestHandlerFactories.find(type); if(it == requestHandlerFactories.end()) return; delete it->second; requestHandlerFactories.erase(it); } RequestManager::RequestManager() : server(false), lastRequestId(-1) { registerPacketType("Disconnect"); } RequestManager::~RequestManager() { unregisterPacketType("Disconnect"); for(std::map::iterator it = requestMaps.begin(); it != requestMaps.end(); ++it) delete it->second; for(std::map::iterator it = requestHandlerFactories.begin(); it != requestHandlerFactories.end(); ++it) delete it->second; } } }