/* * 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 "RequestHandlers/DisconnectRequestHandler.h" #include "Logger.h" #include #include #include namespace Mad { namespace Common { std::auto_ptr 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(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 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; } void RequestManager::registerConnection(Net::Connection *connection) { requestMaps.insert(std::make_pair(connection, new RequestMap())); 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()) return; delete it->second; requestMaps.erase(it); } 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); } RequestManager::RequestManager(bool core) : requestId(core ? -2 : -1) { registerPacketType(Net::Packet::DISCONNECT); } RequestManager::~RequestManager() { 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; } } }