| [1168] | 1 | /* | 
|---|
|  | 2 | *   ORXONOX - the hottest 3D action shooter ever to exist | 
|---|
|  | 3 | *                    > www.orxonox.net < | 
|---|
|  | 4 | * | 
|---|
|  | 5 | * | 
|---|
|  | 6 | *   License notice: | 
|---|
|  | 7 | * | 
|---|
|  | 8 | *   This program is free software; you can redistribute it and/or | 
|---|
|  | 9 | *   modify it under the terms of the GNU General Public License | 
|---|
|  | 10 | *   as published by the Free Software Foundation; either version 2 | 
|---|
|  | 11 | *   of the License, or (at your option) any later version. | 
|---|
|  | 12 | * | 
|---|
|  | 13 | *   This program is distributed in the hope that it will be useful, | 
|---|
|  | 14 | *   but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|---|
|  | 15 | *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|---|
|  | 16 | *   GNU General Public License for more details. | 
|---|
|  | 17 | * | 
|---|
|  | 18 | *   You should have received a copy of the GNU General Public License | 
|---|
|  | 19 | *   along with this program; if not, write to the Free Software | 
|---|
|  | 20 | *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA. | 
|---|
|  | 21 | * | 
|---|
|  | 22 | *   Author: | 
|---|
|  | 23 | *      Dumeni Manatschal, (C) 2007 | 
|---|
|  | 24 | *   Co-authors: | 
|---|
|  | 25 | *      ... | 
|---|
|  | 26 | * | 
|---|
|  | 27 | */ | 
|---|
| [1180] | 28 |  | 
|---|
|  | 29 | /* | 
|---|
|  | 30 | * Class generates packets that can be send by enet | 
|---|
|  | 31 | * ->don't read this without the class PacketDecoder, since they belong together | 
|---|
|  | 32 | * | 
|---|
|  | 33 | * Autor: Dumeni Manatschal | 
|---|
|  | 34 | * | 
|---|
|  | 35 | */ | 
|---|
|  | 36 |  | 
|---|
|  | 37 | #include "PacketManager.h" | 
|---|
|  | 38 | #include "PacketTypes.h" | 
|---|
|  | 39 |  | 
|---|
|  | 40 | #include <iostream> | 
|---|
|  | 41 | #include <list> | 
|---|
|  | 42 | #include <string> | 
|---|
|  | 43 | #include <cstring> | 
|---|
|  | 44 |  | 
|---|
|  | 45 |  | 
|---|
|  | 46 | namespace network | 
|---|
|  | 47 | { | 
|---|
| [1360] | 48 | void calcCRCBit(uint32_t &crc32, int bit){ | 
|---|
|  | 49 | int hbit; | 
|---|
|  | 50 |  | 
|---|
|  | 51 | hbit=(crc32 & 0x80000000) ? 1 : 0; | 
|---|
|  | 52 | if (hbit != bit) | 
|---|
|  | 53 | crc32=(crc32<<1) ^ NETWORK_CRC32POLY; | 
|---|
|  | 54 | else | 
|---|
|  | 55 | crc32=crc32<<1; | 
|---|
|  | 56 | } | 
|---|
|  | 57 |  | 
|---|
|  | 58 | uint32_t calcCRC(unsigned char *data, unsigned int dataLength){ | 
|---|
|  | 59 | uint32_t crc32=0; | 
|---|
|  | 60 | for(unsigned int i=0; i<dataLength; i++){ | 
|---|
|  | 61 | calcCRCBit(crc32, (data[i]&0x1)>>0); // 1st bit | 
|---|
|  | 62 | calcCRCBit(crc32, (data[i]&0x2)>>1); // 2nd bit | 
|---|
|  | 63 | calcCRCBit(crc32, (data[i]&0x3)>>2); // 3rd bit | 
|---|
|  | 64 | calcCRCBit(crc32, (data[i]&0x4)>>3); // 4th bit | 
|---|
|  | 65 | calcCRCBit(crc32, (data[i]&0x5)>>4); // 5th bit | 
|---|
|  | 66 | calcCRCBit(crc32, (data[i]&0x6)>>5); // 6th bit | 
|---|
|  | 67 | calcCRCBit(crc32, (data[i]&0x7)>>6); // 7th bit | 
|---|
|  | 68 | calcCRCBit(crc32, (data[i]&0x8)>>7); // 8th bit | 
|---|
|  | 69 | } | 
|---|
|  | 70 | return crc32; | 
|---|
|  | 71 | } | 
|---|
|  | 72 |  | 
|---|
| [1180] | 73 | PacketGenerator::PacketGenerator() { } | 
|---|
|  | 74 |  | 
|---|
|  | 75 | //following functions create a packet in form of bytestream | 
|---|
|  | 76 |  | 
|---|
|  | 77 | ENetPacket* PacketGenerator::acknowledgement( int state, int reliable ) | 
|---|
|  | 78 | { | 
|---|
|  | 79 | COUT(4) << "PacketGenerator: generating new acknowledgement, id: " << state << std::endl; | 
|---|
|  | 80 | ack* ackreq = new ack; | 
|---|
|  | 81 | ackreq->id = ACK; | 
|---|
|  | 82 | ackreq->a = state; | 
|---|
|  | 83 |  | 
|---|
|  | 84 | ENetPacket *packet = enet_packet_create( ackreq , sizeof( *ackreq ), reliable ); | 
|---|
| [1248] | 85 | delete ackreq; | 
|---|
| [1180] | 86 | return packet; | 
|---|
|  | 87 | } | 
|---|
| [1232] | 88 |  | 
|---|
|  | 89 | ENetPacket* command( int dataLength, void *data, int reliable = ENET_PACKET_FLAG_RELIABLE ) | 
|---|
|  | 90 | { | 
|---|
| [1360] | 91 | unsigned char *stream = new unsigned char[dataLength + 2*sizeof(int)]; | 
|---|
| [1232] | 92 | if(!stream) | 
|---|
|  | 93 | return NULL; | 
|---|
|  | 94 | packet_id a = COMMAND; | 
|---|
|  | 95 | memcpy(stream, (void*)&a, sizeof(int)); | 
|---|
|  | 96 | memcpy((unsigned char *)stream+sizeof(int), (void*)&dataLength, sizeof(int)); | 
|---|
|  | 97 | memcpy((unsigned char *)stream+2*sizeof(int), data, dataLength); | 
|---|
| [1248] | 98 | ENetPacket *packet = enet_packet_create(stream, dataLength+2*sizeof(int), reliable); | 
|---|
|  | 99 | delete[] stream; // TODO: we could also tell enet not to copy the data, but to use the exisiting memory | 
|---|
|  | 100 | return packet; | 
|---|
| [1232] | 101 | } | 
|---|
| [1180] | 102 |  | 
|---|
|  | 103 | /*### mouseupdates */ | 
|---|
|  | 104 | ENetPacket* PacketGenerator::mousem( double x, double y, int reliable ) | 
|---|
|  | 105 | { | 
|---|
|  | 106 | COUT(4) << "PacketGenerator: generating new mouse" << std::endl; | 
|---|
|  | 107 | mouse* mousemove = new mouse; | 
|---|
|  | 108 | mousemove->id = MOUSE; | 
|---|
|  | 109 | mousemove->x = x; | 
|---|
|  | 110 | mousemove->y = y; | 
|---|
|  | 111 |  | 
|---|
|  | 112 | ENetPacket *packet = enet_packet_create( mousemove , sizeof( *mousemove ), reliable ); | 
|---|
| [1248] | 113 | delete mousemove; | 
|---|
| [1180] | 114 | return packet; | 
|---|
|  | 115 | } | 
|---|
|  | 116 |  | 
|---|
|  | 117 | /*### keystrikes updates */ | 
|---|
|  | 118 | ENetPacket* PacketGenerator::keystrike( char press, int reliable ) | 
|---|
|  | 119 | { | 
|---|
|  | 120 | COUT(4) << "PacketGenerator: generating new keyboard" << std::endl; | 
|---|
|  | 121 | keyboard* key = new keyboard; | 
|---|
|  | 122 | key->id = KEYBOARD; | 
|---|
|  | 123 | key->press = press; | 
|---|
|  | 124 |  | 
|---|
|  | 125 | ENetPacket *packet = enet_packet_create( key , sizeof( *key ), reliable ); | 
|---|
| [1248] | 126 | delete key; | 
|---|
| [1180] | 127 | return packet; | 
|---|
|  | 128 | } | 
|---|
|  | 129 |  | 
|---|
|  | 130 | /*### chat messages packet */ | 
|---|
|  | 131 | ENetPacket* PacketGenerator::chatMessage( const char* message, int reliable ) | 
|---|
|  | 132 | { | 
|---|
|  | 133 | int* trans = new int[sizeof(int) + strlen(message) + 1]; | 
|---|
|  | 134 | *trans = CHAT; | 
|---|
|  | 135 | //be carefull here, don't forget to allocate the space before using it ;-) | 
|---|
|  | 136 | memcpy( &trans[1], (const void*)message, strlen( message ) + 1); | 
|---|
|  | 137 | ENetPacket *packet = enet_packet_create( trans , sizeof( int ) + strlen( message ) + 1, reliable ); | 
|---|
| [1248] | 138 | delete[] trans; | 
|---|
| [1180] | 139 | return packet; | 
|---|
|  | 140 | } | 
|---|
|  | 141 |  | 
|---|
|  | 142 | /*### gamestate packet */ | 
|---|
|  | 143 | ENetPacket* PacketGenerator::gstate( GameStateCompressed* states, int reliable ) | 
|---|
|  | 144 | { | 
|---|
|  | 145 | //std::cout << "packetgenerator" << std::endl; | 
|---|
|  | 146 | //std::cout << "states->normsize " << states->normsize << std::endl; | 
|---|
|  | 147 | //std::cout << "states->compsize " << states->compsize << std::endl; | 
|---|
|  | 148 | int gid = GAMESTATE; //first assign the correct enet id | 
|---|
| [1232] | 149 | int totalLen = 5*sizeof( int ) + 2*sizeof(bool) + states->compsize; //calculate the total size of the datastream memory | 
|---|
| [1180] | 150 | //std::cout << "totalLen " << totalLen << std::endl; | 
|---|
| [1232] | 151 | //unsigned char *data = (unsigned char*)malloc( totalLen ); //allocate the memory for datastream | 
|---|
|  | 152 | unsigned char *data = new unsigned char[totalLen]; | 
|---|
| [1180] | 153 | memcpy( (void*)(data), (const void*)&gid, sizeof( int ) ); //this is the enet id | 
|---|
|  | 154 | memcpy( (void*)(data+sizeof(int)), (const void*)&(states->id), sizeof(int) ); //the GameStateCompressed id | 
|---|
|  | 155 | memcpy( (void*)(data+2*sizeof(int)), (const void*)&(states->compsize), sizeof(int)); | 
|---|
|  | 156 | memcpy( (void*)(data+3*sizeof(int)), (const void*)&(states->normsize), sizeof(int)); | 
|---|
|  | 157 | memcpy( (void*)(data+4*sizeof(int)), (const void*)&(states->base_id), sizeof(int)); | 
|---|
|  | 158 | memcpy( (void*)(data+5*sizeof(int)), (const void*)&(states->diffed), sizeof(bool)); | 
|---|
|  | 159 | //place the GameStateCompressed data at the end of the enet datastream | 
|---|
| [1232] | 160 | memcpy( (void*)(data+5*sizeof( int ) + sizeof(bool)), (const void*)&(states->complete), sizeof(bool) ); | 
|---|
|  | 161 | memcpy( (void*)(data+5*sizeof( int ) + 2*sizeof(bool)), (const void*)states->data, states->compsize ); | 
|---|
| [1360] | 162 |  | 
|---|
| [1180] | 163 | //create an enet packet with the generated bytestream | 
|---|
|  | 164 | COUT(4) << "PacketGenerator generating totalLen " << totalLen << std::endl; | 
|---|
|  | 165 | ENetPacket *packet = enet_packet_create( data , totalLen, reliable ); | 
|---|
| [1248] | 166 | delete[] data; | 
|---|
| [1360] | 167 | if(!addCRC(packet)) | 
|---|
|  | 168 | COUT(3) << "could not add crc to gamestate packet" << std::endl; | 
|---|
| [1180] | 169 | return packet; | 
|---|
|  | 170 | } | 
|---|
|  | 171 |  | 
|---|
|  | 172 | ENetPacket* PacketGenerator::clid( int classid, std::string classname, int reliable ) | 
|---|
|  | 173 | { | 
|---|
| [1232] | 174 | //unsigned char* data = (unsigned char *)malloc(3*sizeof(int)+classname.length()+1); | 
|---|
|  | 175 | unsigned char *data = new unsigned char[3*sizeof(int)+classname.length()+1]; | 
|---|
| [1180] | 176 | std::cout << "PacketGenerator: classid: " << classid << ", name: " << classname << std::endl; | 
|---|
|  | 177 | *(int *)data = CLASSID; | 
|---|
|  | 178 | *((int *)data+1) = classname.length()+1; | 
|---|
|  | 179 | *((int *)data+2) = classid; | 
|---|
|  | 180 | memcpy( (void *)(data+3*sizeof(int)), classname.c_str(), classname.length()+1); | 
|---|
|  | 181 | ENetPacket *packet = enet_packet_create( data , 3*sizeof(int)+classname.length()+1, reliable ); | 
|---|
| [1248] | 182 | delete[] data; | 
|---|
| [1180] | 183 | return packet; | 
|---|
|  | 184 | } | 
|---|
| [1232] | 185 |  | 
|---|
|  | 186 | ENetPacket* PacketGenerator::generateWelcome( int clientID,int shipID, bool allowed , int reliable ){ | 
|---|
|  | 187 | welcome *wc = new welcome; | 
|---|
|  | 188 | wc->id = WELCOME; | 
|---|
|  | 189 | wc->clientID = clientID; | 
|---|
|  | 190 | wc->shipID = shipID; | 
|---|
|  | 191 | wc->allowed = true; | 
|---|
|  | 192 | ENetPacket *packet = enet_packet_create( wc, sizeof(welcome), reliable); | 
|---|
| [1248] | 193 | delete wc; | 
|---|
| [1232] | 194 | return packet; | 
|---|
|  | 195 | } | 
|---|
|  | 196 |  | 
|---|
|  | 197 | ENetPacket* PacketGenerator::generateConnectRequest( int reliable ){ | 
|---|
|  | 198 | connectRequest *con = new connectRequest; | 
|---|
|  | 199 | con->id=CONNECT; | 
|---|
| [1248] | 200 | ENetPacket *packet = enet_packet_create( con, sizeof(connectRequest), reliable); | 
|---|
|  | 201 | delete con; | 
|---|
|  | 202 | return packet; | 
|---|
| [1232] | 203 | } | 
|---|
| [1360] | 204 |  | 
|---|
|  | 205 |  | 
|---|
|  | 206 | bool PacketGenerator::addCRC( ENetPacket *packet){ | 
|---|
|  | 207 | unsigned char *data = packet->data; | 
|---|
|  | 208 | uint32_t crc32=calcCRC(data, packet->dataLength); | 
|---|
|  | 209 | // now append the crc to the packet data | 
|---|
|  | 210 | int oldlength = packet->dataLength; | 
|---|
|  | 211 | if(enet_packet_resize(packet, packet->dataLength+sizeof(uint32_t))==0){ | 
|---|
|  | 212 | memcpy(&packet->data[oldlength], &crc32, sizeof(uint32_t)); | 
|---|
|  | 213 | return true; | 
|---|
|  | 214 | }else{ | 
|---|
|  | 215 | COUT(3) << "could not add crc to gamestate" << std::endl; | 
|---|
|  | 216 | return false; | 
|---|
|  | 217 | } | 
|---|
|  | 218 | } | 
|---|
| [1180] | 219 |  | 
|---|
|  | 220 | } | 
|---|