diff options
Diffstat (limited to 'src/net/tmwserv/network.cpp')
-rw-r--r-- | src/net/tmwserv/network.cpp | 169 |
1 files changed, 169 insertions, 0 deletions
diff --git a/src/net/tmwserv/network.cpp b/src/net/tmwserv/network.cpp new file mode 100644 index 00000000..d3bc88fa --- /dev/null +++ b/src/net/tmwserv/network.cpp @@ -0,0 +1,169 @@ +/* + * The Mana World + * Copyright 2004 The Mana World Development Team + * + * This file is part of The Mana World. + * + * The Mana World 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 2 of the License, or + * any later version. + * + * The Mana World 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 The Mana World; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "network.h" + +#include <enet/enet.h> + +#include <map> + +#include "connection.h" +#include "internal.h" +#include "../messagehandler.h" +#include "../messagein.h" + +#include "../../log.h" + +/** + * The local host which is shared for all outgoing connections. + */ +namespace { + ENetHost *client; +} + +typedef std::map<unsigned short, MessageHandler*> MessageHandlers; +typedef MessageHandlers::iterator MessageHandlerIterator; +static MessageHandlers mMessageHandlers; + +void Net::initialize() +{ + if (enet_initialize()) + { + logger->error("Failed to initialize ENet."); + } + + client = enet_host_create(NULL, 3, 0, 0); + + if (!client) + { + logger->error("Failed to create the local host."); + } +} + +void Net::finalize() +{ + if (!client) + return; // Wasn't initialized at all + + if (Net::connections) { + logger->error("Tried to shutdown the network subsystem while there " + "are network connections left!"); + } + + clearHandlers(); + enet_deinitialize(); +} + +Net::Connection *Net::getConnection() +{ + if (!client) + { + logger->error("Tried to instantiate a network object before " + "initializing the network subsystem!"); + } + + return new Net::Connection(client); +} + +void Net::registerHandler(MessageHandler *handler) +{ + for (const Uint16 *i = handler->handledMessages; *i; i++) + { + mMessageHandlers[*i] = handler; + } +} + +void Net::unregisterHandler(MessageHandler *handler) +{ + for (const Uint16 *i = handler->handledMessages; *i; i++) + { + mMessageHandlers.erase(*i); + } +} + +void Net::clearHandlers() +{ + mMessageHandlers.clear(); +} + + +/** + * Dispatches a message to the appropriate message handler and + * destroys it afterwards. + */ +namespace +{ + void dispatchMessage(ENetPacket *packet) + { + MessageIn msg((const char *)packet->data, packet->dataLength); + + MessageHandlerIterator iter = mMessageHandlers.find(msg.getId()); + + if (iter != mMessageHandlers.end()) { + //logger->log("Received packet %x (%i B)", + // msg.getId(), msg.getLength()); + iter->second->handleMessage(msg); + } + else { + logger->log("Unhandled packet %x (%i B)", + msg.getId(), msg.getLength()); + } + + // Clean up the packet now that we're done using it. + enet_packet_destroy(packet); + } +} + +void Net::flush() +{ + ENetEvent event; + + // Wait up to 10 milliseconds for an event. + while (enet_host_service(client, &event, 10) > 0) + { + switch (event.type) + { + case ENET_EVENT_TYPE_CONNECT: + logger->log("Connected to port %d.", event.peer->address.port); + // Store any relevant server information here. + event.peer->data = 0; + break; + + case ENET_EVENT_TYPE_RECEIVE: + dispatchMessage(event.packet); + break; + + case ENET_EVENT_TYPE_DISCONNECT: + logger->log("Disconnected."); + // Reset the server information. + event.peer->data = 0; + break; + + case ENET_EVENT_TYPE_NONE: + logger->log("No event during 10 milliseconds."); + break; + + default: + logger->log("Unhandled enet event."); + break; + } + } +} |