/* * 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 "Request.h" #include "XmlRequest.h" #include "XmlPacket.h" #include "RequestHandlers/DisconnectRequestHandler.h" #include "Logger.h" #include #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; } RequestManager::XmlRequestMap::~XmlRequestMap() { for(iterator it = begin(); it != end(); ++it) delete it->second; } bool RequestManager::XmlRequestMap::addRequest(uint16_t id, XmlRequestHandler *info) { if(!insert(std::make_pair(id, info)).second) return false; info->signalFinished().connect(sigc::hide_return(sigc::bind(sigc::mem_fun(this, &RequestManager::XmlRequestMap::deleteRequest), id))); return true; } XmlRequestHandler* RequestManager::XmlRequestMap::findRequest(uint16_t id) { iterator it = find(id); if(it == end()) return 0; return it->second; } bool RequestManager::XmlRequestMap::deleteRequest(uint16_t id) { iterator it = find(id); if(it == end()) return false; delete it->second; erase(it); return true; } void RequestManager::receiveHandler(Net::Connection *connection, const Net::Packet &packet) { 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(packet.getRequestId()); if(request) { request->handlePacket(connection, packet); return; } std::map::iterator it2 = xmlRequestMaps.find(connection); if(it2 == xmlRequestMaps.end()) { // TODO: Error Logger::log(Logger::ERROR, "Received a packet from an unregistered connection."); return; } XmlRequestMap *xmlRequestMap = it2->second; XmlRequestHandler *xmlRequest = xmlRequestMap->findRequest(packet.getRequestId()); if(xmlRequest) { XmlPacket xmlPacket(packet); xmlRequest->handlePacket(connection, packet.getRequestId(), xmlPacket); return; } if(packet.getType() == Net::Packet::XML) { XmlPacket xmlPacket(packet); std::map::iterator factoryIt = xmlRequestHandlerFactories.find(xmlPacket.getType()); if(factoryIt != xmlRequestHandlerFactories.end()) { xmlRequest = factoryIt->second->createRequestHandler(); xmlRequestMap->addRequest(packet.getRequestId(), xmlRequest); xmlRequest->handlePacket(connection, packet.getRequestId(), xmlPacket); return; } } std::map::iterator factoryIt = requestHandlerFactories.find(packet.getType()); if(factoryIt != requestHandlerFactories.end()) { request = factoryIt->second->createRequestHandler(); requestMap->addRequest(packet.getRequestId(), request); request->handlePacket(connection, packet); return; } Logger::log(Logger::ERROR, "Received an unexpected packet."); connection->send(Net::Packets::ErrorPacket(Net::Packet::ERROR, packet.getRequestId(), Exception(Exception::UNEXPECTED_PACKET))); } bool RequestManager::sendRequest(Net::Connection *connection, std::auto_ptr request) { 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 false; } RequestMap *requestMap = it->second; uint16_t id; do { id = getRequestId(); } while(requestMap->findRequest(id)); request->sendRequest(connection, id); requestMap->addRequest(id, request.release()); return true; } bool RequestManager::sendRequest(Net::Connection *connection, std::auto_ptr request) { std::map::iterator it = xmlRequestMaps.find(connection); if(it == xmlRequestMaps.end()) { Logger::log(Logger::CRITICAL, "Trying to send a request over an unregistered connecion."); return false; } XmlRequestMap *requestMap = it->second; uint16_t id; do { id = getRequestId(); } while(requestMap->findRequest(id)); request->sendRequest(connection, id); requestMap->addRequest(id, request.release()); return true; } void RequestManager::registerConnection(Net::Connection *connection) { requestMaps.insert(std::make_pair(connection, new RequestMap())); xmlRequestMaps.insert(std::make_pair(connection, new XmlRequestMap())); connection->signalReceive().connect(sigc::mem_fun(this, &RequestManager::receiveHandler)); } void RequestManager::unregisterConnection(Net::Connection *connection) { std::map::iterator it = requestMaps.find(connection); if(it != requestMaps.end()) { delete it->second; requestMaps.erase(it); } std::map::iterator it2 = xmlRequestMaps.find(connection); if(it2 != xmlRequestMaps.end()) { delete it2->second; xmlRequestMaps.erase(it2); } } void RequestManager::unregisterPacketType(Net::Packet::Type type) { std::map::iterator it = requestHandlerFactories.find(type); if(it == requestHandlerFactories.end()) return; delete it->second; requestHandlerFactories.erase(it); } void RequestManager::unregisterPacketType(const std::string &type) { std::map::iterator it = xmlRequestHandlerFactories.find(type); if(it == xmlRequestHandlerFactories.end()) return; delete it->second; xmlRequestHandlerFactories.erase(it); } RequestManager::RequestManager() : core(false), requestId(-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 = xmlRequestMaps.begin(); it != xmlRequestMaps.end(); ++it) delete it->second; for(std::map::iterator it = requestHandlerFactories.begin(); it != requestHandlerFactories.end(); ++it) delete it->second; for(std::map::iterator it = xmlRequestHandlerFactories.begin(); it != xmlRequestHandlerFactories.end(); ++it) delete it->second; } } }