/*************************************************************************** * The contents of this file are subject to the Mozilla Public * * License Version 1.1 (the "License"); you may not use this file * * except in compliance with the License. You may obtain a copy of * * the License at http://www.mozilla.org/MPL/ * * * * Software distributed under the License is distributed on an "AS * * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * * implied. See the License for the specific language governing * * rights and limitations under the License. * * * * The Original Code is Game Network Framework (GaNeF). * * * * The Initial Developers of the Original Code are * * Lars Langer and Emanuel Greisen * * Copyright (C) 2005. Lars Langer & Emanuel Greisen * * All Rights Reserved. * * * * Contributor(s): * * none yet.... * * * ***************************************************************************/ #ifndef AGGR_PLUGIN_H #define AGGR_PLUGIN_H #include <map> #include "../Ganef/common/plugin.h" template<class PacketType> class AggregationPlugin : public Plugin<PacketType> { private: std::map<unsigned int, PacketType *> aggr_packs; typedef typename std::map<unsigned int, PacketType *>::iterator MapIterator; public: /// This method must return a unique number identifying the plugin. virtual const unsigned int getUniqueId() const { return 0x12345; } /// Will be called when ever a packet must be packed. virtual void pack(PacketType * packet) { //std::cout << "AggregationPlugin::pack(" << packet << ")\n"; if(aggr_packs.find(packet->getUserID()) == aggr_packs.end()) { std::cout << "Creating new Aggregation packet for client: " << packet->getUserID() << std::endl; aggr_packs[packet->getUserID()] = PacketType::createPluginPacket(this, packet); } // Add a new packet aggr_packs[packet->getUserID()]->writeUInt32(packet->getSize()); aggr_packs[packet->getUserID()]->writePacket(packet); delete packet; } /// Will be called when ever a packet must be unpacked. virtual void unpack(PacketType * packet) { std::cout << "AggregationPlugin::unpack(" << packet << ")\n"; unsigned int psize; while((psize = packet->readUInt32()) != 0) { //std::cout << "There is a packet of size:" << psize << std::endl; PacketType * p = packet->readPacket(psize); forwardUnpack(p); } // This is of no more use delete packet; } /// Will be called when ever we must purge our packets virtual void onPurge() { MapIterator it; for(it = aggr_packs.begin(); it != aggr_packs.end(); ++it) { PacketType * pack = it->second; pack->writeUInt32(0); // This ends the packet std::cout << "Purging a packet of size: " << pack->getSize() << std::endl; forwardPack(pack); } // Clean up our map aggr_packs.clear(); } }; #endif
/*************************************************************************** * The contents of this file are subject to the Mozilla Public * * License Version 1.1 (the "License"); you may not use this file * * except in compliance with the License. You may obtain a copy of * * the License at http://www.mozilla.org/MPL/ * * * * Software distributed under the License is distributed on an "AS * * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * * implied. See the License for the specific language governing * * rights and limitations under the License. * * * * The Original Code is Game Network Framework (GaNeF). * * * * The Initial Developers of the Original Code are * * Lars Langer and Emanuel Greisen * * Copyright (C) 2005. Lars Langer & Emanuel Greisen * * All Rights Reserved. * * * * Contributor(s): * * none yet.... * * * ***************************************************************************/ #ifndef ZLIB_PLUGIN_H #define ZLIB_PLUGIN_H #include <zlib.h> #include "../Ganef/common/plugin.h" template<class PacketType> class ZlibPlugin : public Plugin<PacketType> { public: /// This method must return a unique number identifying the plugin. virtual const unsigned int getUniqueId() const { return 0x711b; } /// Will be called when ever a packet must be packed. virtual void pack(PacketType * packet) { // First make the packet ready for transmission packet->makeSendReady(); unsigned long have; // According to ZLIB the outbuffer must be 0.1% bigger, plus 12 bytes. // We just make sure nothing happen an take 10% + 12 bytes :) unsigned int outbuffsize = (packet->getSize() * 110) / 100 + 12; unsigned char out[outbuffsize]; int ret = compress(out, &have, (unsigned char *)packet->getData(), packet->getSize()); PacketType * compressedpacket = PacketType::createPluginPacket(this, packet); compressedpacket->writeUInt16(static_cast<unsigned short>(packet->getSize())); compressedpacket->writeData(out, have); delete packet; std::cout << "ZLIB::pack(" << packet << ") ["<<packet->getSize()<<"->"<<have<<"]\n"; // And forward the packet forwardPack(compressedpacket); } /// Will be called when ever a packet must be unpacked. virtual void unpack(PacketType * packet) { unsigned long insize = packet->getDataSize() - sizeof(unsigned short); unsigned long outsize = static_cast<unsigned long>(packet->readUInt16()); std::cout << "ZLIB::unpack(" << packet << ") ["<<insize<<"->"<<outsize<<"]\n"; unsigned char in[insize]; packet->readData(in, insize); unsigned char dest[outsize]; int ret = uncompress(dest, &outsize, in, insize); std::cout << "Actual size: " << outsize << ",ret:" << ret << std::endl; // OAK: create the packet PacketType * uncompressedpacket = new PacketType((char *)dest, outsize); // This is of no more use delete packet; // Finally forward the packet forwardUnpack(uncompressedpacket); } }; #endif
/// @cond EXCLUDEDTESTSOURCES /*************************************************************************** * The contents of this file are subject to the Mozilla Public * * License Version 1.1 (the "License"); you may not use this file * * except in compliance with the License. You may obtain a copy of * * the License at http://www.mozilla.org/MPL/ * * * * Software distributed under the License is distributed on an "AS * * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * * implied. See the License for the specific language governing * * rights and limitations under the License. * * * * The Original Code is Game Network Framework (GaNeF). * * * * The Initial Developers of the Original Code are * * Lars Langer and Emanuel Greisen * * Copyright (C) 2005. Lars Langer & Emanuel Greisen * * All Rights Reserved. * * * * Contributor(s): * * none yet.... * * * ***************************************************************************/ #include <iostream> #include <cstdlib> #include "../Ganef/client/clientframework.h" #include "../Ganef/client/clientdata.h" #include "aggr_plugin.h" #include "zlib_plugin.h" class MyClientData : public ClientData { private: int x,y; public: MyClientData(ClientFramework * f, ClientPacket * p) : ClientData(f,p),x(0),y(0) { x = p->readInt32(); y = p->readInt32(); std::cout << "Constructed a new object of class: MyClientData("; std::cout << "ID:" << getFrameworkId() << ","; std::cout << "x:"<<x<<",y:"<<y<<")" << std::endl; } virtual void updatePacket(ClientFramework * f, unsigned char updatetype, ClientPacket * packet) { // Here we receive updates (but no updates are comming in this test) } static ClientData * constructMyClientData(ClientFramework * f, ClientPacket * p) { return new MyClientData(f,p); } }; /** * This is just a test-client-framework. * @author Lars Langer and Emanuel Greisen */ class TestClientFramework : public ClientFramework { private: bool is_running; std::string server_hostname; public: TestClientFramework(const std::string & server_hostname) : ClientFramework(int(0)),server_hostname(server_hostname) { // Notice how the constructor is registered, now all we need is the // server sending a packet telling us to construct an object of // class with id: 0x424242 registerConstructor(0x424242, MyClientData::constructMyClientData); } ~TestClientFramework() { }; protected: // These must be implemented in a derived class virtual void writeHandshakeInitMessage( ClientPacket * fp ){} virtual void onHandshakingDiscontinue( ClientPacket * fp ){} virtual bool onHandshakeDescription( ClientPacket * fp, ClientPacket * reply ) { return true; } virtual void onDisconnect( ) { std::cout << "Disconnected\n"; } virtual void onConnect( ){ std::cout << "Connected\n"; } public: void mainLoop( ) { // First we register the plugin for use when decoding packets. // You might note that the plugin is a template class and that // we use different packet-types on the server and client // This is no big issue, because they are almost the same (they // both implement the same methods used in the plugin). registerPlugin(new AggregationPlugin<ClientPacket>()); registerPlugin(new ZlibPlugin<ClientPacket>()); // Then we connect to the server std::cout << "Connecting to: " << server_hostname <<":"<< 8000<< std::endl; initServerConnection(server_hostname, 8000); is_running = true; while(is_running) { // Get/handle Packets from the framework keepAlive(); // Then we sleep to let the CPU live psleep(50); } } }; int main(int argc, char *argv[]) { std::string server_host("localhost"); if(argc > 1) server_host = argv[1]; TestClientFramework app(server_host); // Start the Application app.mainLoop(); } /// @endcond
/// @cond EXCLUDEDTESTSOURCES /*************************************************************************** * The contents of this file are subject to the Mozilla Public * * License Version 1.1 (the "License"); you may not use this file * * except in compliance with the License. You may obtain a copy of * * the License at http://www.mozilla.org/MPL/ * * * * Software distributed under the License is distributed on an "AS * * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * * implied. See the License for the specific language governing * * rights and limitations under the License. * * * * The Original Code is Game Network Framework (GaNeF). * * * * The Initial Developers of the Original Code are * * Lars Langer and Emanuel Greisen * * Copyright (C) 2005. Lars Langer & Emanuel Greisen * * All Rights Reserved. * * * * Contributor(s): * * none yet.... * * * ***************************************************************************/ #include <iostream> #include <cstdlib> #include <vector> #include "../Ganef/server/serverframework.h" #include "aggr_plugin.h" #include "zlib_plugin.h" class MyServerData : public ServerData { private: int x,y; public: // The two last parameters for ServerData is the priority of its updatepackets // and wether they should be sent reliable. MyServerData(ServerFramework * fw) : ServerData(fw, 10, false) { x = 200; y = 150; }; public: /// This must produce a unique id for this class, it will be used on the client side to construct new objects. virtual const unsigned int getClassId() const { return 0x424242; }; /// Here the data-class should fill in data according to update type `type`. virtual void fillUpdatePacket(ServerPacket * packet, unsigned char type) const { // We do not use updates in this test. switch(type) { case 5: packet->writeInt32(x); packet->writeInt32(y); break; } } /// Here the data-class should fill in all data required by the constructor on the client side. virtual void fillCreateObjectPacket(ServerPacket * packet) const { // Here we supply enough data to create the client-version of this object // Remember to make absolutely sure that what you write here is exactly the // same as the client version reads in its constructor. packet->writeInt32(x); packet->writeInt32(y); } /// Called when ever we receive a packet for this object from a client. virtual void clientPacket(Client * client, unsigned char type, ServerPacket * packet) { // We do not receive any actions from the client in this test. } }; /** * This is just a test server-framework; * @author Lars Langer and Emanuel Greisen */ class TestServerFramework : public ServerFramework { public: TestServerFramework() : ServerFramework(8000) { } ~TestServerFramework() { } protected: // These method should be implemented on the GameServer virtual bool onInitialHandshake(ServerPacket * handshake, ServerPacket * reply) { return true; // Accept all clients. } virtual void onClientConnected(Client * client) { std::cout << "Client: " << client->getId() << " connected\n"; // Here we send the construction packages for all Framework Data // But first we change the "chain" of plugins to use our registered one. setPreSendingChain("MyPluginChain"); std::map<unsigned int, ServerData *>::const_iterator it; for(it = getServerDataObjects().begin(); it != getServerDataObjects().end(); ++it) { ServerData * s_data = it->second; s_data->sendCreateObject(client); } // Since our plugin aggregates the packets we need to purge it to make // sure everything is sent. purgeCurrentPreSendingChain(); // Once we have sent all our constructor packets to the client we revert to // the default send-chain (the empty send chain) setDefaultPreSendingChain(); } virtual void onClientDisconnected(Client * client) { std::cout << "Client: " << client->getId() << " disconnected\n"; } virtual Client * createClient(const ipaddress &addr, int port) { return new Client(this, addr, port); } public: void mainLoop() { // First we create a vector of plugins (this one only containing one) std::vector< Plugin<ServerPacket> * > chainlist; chainlist.push_back(new AggregationPlugin<ServerPacket>()); chainlist.push_back(new ZlibPlugin<ServerPacket>()); // Then we register this "chain" under a name registerPreSendingChain("MyPluginChain", chainlist); std::cout << "TestServerFramework: Running\n"; // Construct a lot of data std::vector<MyServerData *> mydata; for(int i = 0; i < 25; i++) mydata.push_back(new MyServerData(this)); int counter = 0; while(true) { // Get all incomming messages keepAlive(); if(counter++ % 100 == 0) { setPreSendingChain("MyPluginChain"); std::vector< MyServerData *>::const_iterator it; for(it = mydata.begin(); it != mydata.end(); ++it) { MyServerData * s_data = *it; s_data->sendUpdateToAll(5, false); } purgeCurrentPreSendingChain(); setDefaultPreSendingChain(); } // Sleep a little psleep(100); } } }; int main(int argc, char *argv[]) { try { // Create a framework TestServerFramework framework; // Start the framework framework.start(); // GameLoop framework.mainLoop(); } catch(FrameworkError *err) { std::cout << "FrameworkError:" << err->msg << std::endl; } catch(PacketError *err) { std::cout << "PacketError:" << err->msg << std::endl; } return EXIT_SUCCESS; } /// @endcond