Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/network/src/network/PacketDecoder.cc @ 1432

Last change on this file since 1432 was 1432, checked in by scheusso, 16 years ago

found a bug in gamestate diffing (in some cases the gamestate diffed was
filled with zeros at the end)

File size: 11.8 KB
Line 
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 */
28
29/*
30* Class contains functions to determine and decode incomming packages
31* ->don't read this without the class PacketGenerator, since they belong together
32*
33* Autor: Dumeni Manatschal
34*
35*/
36
37#include "PacketTypes.h"
38#include "PacketManager.h"
39
40#include <iostream>
41
42#include "core/Debug.h"
43
44namespace network
45{
46
47  PacketDecoder::PacketDecoder(){}
48
49  PacketDecoder::~PacketDecoder(){}
50
51  //call this function out of an instance of PacketDecoder
52  //it will determine the type id and call the right decode function
53  bool PacketDecoder::elaborate( ENetPacket* packet, int clientId )
54  {
55    COUT(5) << "PacketDecoder: clientId: " << clientId << std::endl; //control cout, not important, just debugging info
56    int id = (int)*packet->data; //the first 4 bytes are always the enet packet id
57    COUT(5) << "PacketDecoder: packet id: " << id << std::endl;
58    //COUT(5) << "packet size inside packetdecoder: " << packet->dataLength << std::endl;
59
60    if ( packet == NULL ) {
61      COUT(4) << "PacketDecoder: no packets->packetbuffer queue is empty" << std::endl;
62      return false;
63    }
64    switch( id ) {
65    case ACK:
66      acknowledgement( packet, clientId );
67      return true;
68    case COMMAND:
69      return command( packet, clientId );
70    case MOUSE:
71      mousem( packet, clientId );
72      return true;
73    case KEYBOARD:
74      keystrike( packet, clientId );
75      return true;
76    case CHAT:
77      chatMessage( packet, clientId );
78      return true;
79    case GAMESTATE:
80      gstate( packet, clientId );
81      return true;
82    case CLASSID:
83      clid(packet);
84      return true;
85    case WELCOME:
86      return decodeWelcome( packet, clientId );
87    case CONNECT:
88      return decodeConnectRequest( packet, clientId );
89    }
90    return false;
91  }
92 
93  bool PacketDecoder::testAndRemoveCRC(ENetPacket *packet){
94    uint32_t submittetcrc;
95    int dataLength = packet->dataLength;
96    // get the submittet crc code
97    memcpy(&submittetcrc, &packet->data[dataLength-sizeof(uint32_t)], sizeof(uint32_t));
98    unsigned char *data = packet->data;
99    uint32_t crc32=calcCRC(data, packet->dataLength-sizeof(uint32_t));
100    // now append the crc to the packet data
101    if(crc32==submittetcrc){
102      dataLength-=sizeof(uint32_t);
103      enet_packet_resize(packet, dataLength);
104      return true;
105    }
106    COUT(3) << "gamestate crc: " << crc32 << std::endl;
107    COUT(3) << "submitted crc: " << submittetcrc << std::endl;
108    return false;
109  }
110 
111  // ATTENTION: TODO watch, that arguments we pass over to the processFunction gets deleted in THE PROCESSXXX function
112
113  //following are the decode functions for the data of the packets
114
115  void PacketDecoder::acknowledgement( ENetPacket* packet, int clientId )
116  {
117    ack* a = new ack;
118    *a = *(ack*)(packet->data); //press pattern of ack on new data
119
120
121    COUT(4) << "PacketDecoder: got ack id: " << a->a << std::endl;
122    processAck( a, clientId ); //debug info
123    //clean memory
124    enet_packet_destroy( packet );
125  }
126 
127  bool PacketDecoder::command( ENetPacket* packet, int clientId ){
128    int length = *(int*)((unsigned char *)packet->data+sizeof(int));
129    if(length<=0)
130      return false;
131    void *data = (void *)new unsigned char[length];
132    memcpy(data, (void *)(packet->data+2*sizeof(int)), length);
133    enet_packet_destroy( packet );
134    return true;
135  }
136
137  void PacketDecoder::mousem( ENetPacket* packet, int clientId )
138  {
139    mouse* mouseMove = new mouse;
140    //copy data of packet->data to new struct
141    *mouseMove = *(mouse*)packet->data;
142
143    //clean memory
144    enet_packet_destroy( packet );
145    printMouse( mouseMove ); //debug info
146  }
147
148  void PacketDecoder::keystrike( ENetPacket* packet, int clientId )
149  {
150    keyboard* key = new keyboard;
151    *key = *(keyboard*)packet->data; //see above
152
153    //clean memory
154    enet_packet_destroy( packet );
155    printKey( key ); //debug info
156
157  }
158
159  void PacketDecoder::chatMessage( ENetPacket* packet, int clientId )
160  {
161    chat* chatting = new chat;
162    if(packet->dataLength==4)
163      return;
164    chatting->id = (int)*packet->data; //first copy id into new struct
165    //since the chat message is a char*, allocate the memory needed
166    char* reserve = new char[packet->dataLength-4];
167    //copy the transmitted bytestream into the new generated char*,
168    //note the lenght of the message is represented as "packet->dataLength-sizeof( int )"
169    memcpy( &reserve[0], packet->data+sizeof(int), packet->dataLength-sizeof(int) );
170    //put pointer of chatting struct to the begining of the new generated char*
171    chatting->message = reserve;
172
173    //clean memory
174    enet_packet_destroy( packet );
175
176    processChat( chatting, clientId ); //debug info
177  }
178
179  void PacketDecoder::gstate( ENetPacket* packet, int clientID )
180  {
181    if(!testAndRemoveCRC(packet)){
182      COUT(3) << "crc test of gamestate failed - dropping packet" << std::endl;
183      return;
184    }
185    GameStateCompressed* currentState = NULL;
186    currentState = new GameStateCompressed;
187    if(currentState == NULL){
188      COUT(3) << "PacketDecoder: could not generate new GameStateCompressed" << std::endl;
189      return;
190    }
191    //since it's not alowed to use void* for pointer arithmetic
192    //FIXME: variable never used
193    unsigned char* data = (unsigned char *)(packet->data);
194    //copy the GameStateCompressed id into the struct, which is located at second place data+sizeof( int )
195    memcpy( (void*)&(currentState->id), (const void*)(packet->data+1*sizeof( int )), sizeof( int) );
196    COUT(5) << "PacketDecoder: received gs id: " << currentState->id << std::endl;
197    //copy the size of the GameStateCompressed compressed data into the new GameStateCompressed struct, located at 3th
198    //position of the data stream, data+2*sizeof( int )
199    memcpy( (void*)&(currentState->compsize), (const void*)(packet->data+2*sizeof( int )), sizeof( int) );
200    //size of uncompressed data
201    memcpy( (void*)&(currentState->normsize), (const void*)(packet->data+3*sizeof( int )), sizeof( int ) );
202    memcpy( (void*)&(currentState->base_id), (const void*)(packet->data+4*sizeof( int )), sizeof( int ) );
203    //since the packetgenerator was changed, due to a new parameter, change this function too
204    memcpy( (void*)&(currentState->diffed), (const void*)(packet->data+5*sizeof(int)), sizeof(bool));
205    memcpy( (void*)&(currentState->complete), (const void*)(packet->data+5*sizeof(int)+sizeof(bool)), sizeof(bool));
206    //since data is not allocated, because it's just a pointer, allocate it with size of gamestatedatastream
207    if(currentState->compsize==0)
208      COUT(2) << "PacketDecoder: compsize is 0" << std::endl;
209//     currentState->data = (unsigned char*)(malloc( currentState->compsize ));
210    if(currentState->compsize==0)
211      return;
212    currentState->data = new unsigned char[currentState->compsize];
213    if(currentState->data==NULL)
214      COUT(2) << "PacketDecoder: Gamestatepacket-decoder: memory leak" << std::endl;
215    //copy the GameStateCompressed data
216    memcpy( (void*)(currentState->data), (const void*)(packet->data+5*sizeof( int ) + 2*sizeof(bool)), currentState->compsize );
217
218    //clean memory
219    enet_packet_destroy( packet );
220    processGamestate(currentState, clientID);
221  }
222
223  void PacketDecoder::clid( ENetPacket *packet)
224  {
225    classid* cid = new classid;
226    cid->length = ((classid*)(packet->data))->length;
227    cid->id = ((classid *)(packet->data))->id;
228    cid->clid = ((classid *)(packet->data))->clid;
229    if(cid->length==0)
230      return;
231//     cid->message = (const char *)malloc(cid->length);
232    cid->message = new char[cid->length];
233    void *data  = (void *)cid->message;
234    memcpy(data, (const void*)(packet->data+3*sizeof(int)), cid->length);
235    COUT(4) << "PacketDecoder: classid: " << cid->clid << ", name: " << cid->message << std::endl;
236    enet_packet_destroy( packet );
237    processClassid(cid);
238  }
239 
240 
241  bool PacketDecoder::decodeWelcome( ENetPacket* packet, int clientID ){
242    welcome *w = new welcome;
243    w->allowed = ((welcome *)(packet->data))->allowed;
244    w->shipID = ((welcome *)(packet->data))->shipID;
245    w->clientID = ((welcome *)(packet->data))->clientID;
246    w->id = ((welcome *)(packet->data))->id;
247    enet_packet_destroy( packet );
248    return processWelcome(w);
249  }
250 
251  bool PacketDecoder::decodeConnectRequest( ENetPacket *packet, int clientID ){
252    connectRequest *con = new connectRequest;
253    con->id = ((connectRequest *)(packet->data))->id;
254    enet_packet_destroy( packet );
255    return processConnectRequest(con, clientID );
256  }
257
258
259  // now the data processing functions:
260
261  void PacketDecoder::processChat( chat *data, int clientId)
262  {
263    printChat(data, clientId);
264    delete[] data->message;
265    delete data;
266  }
267
268  void PacketDecoder::processGamestate( GameStateCompressed *state, int clientID )
269  {
270    COUT(3) << "PacketDecoder-process: processing Gamestate" << std::endl;
271    //printGamestate( state );
272//     delete[] state->data;
273//     delete state;
274  }
275
276  void PacketDecoder::processClassid( classid *cid)
277  {
278    printClassid(cid);
279    delete cid;
280    return;
281  }
282
283  void PacketDecoder::processAck( ack *data, int clientID)
284  {
285    printAck(data);
286    delete data;
287    return;
288  }
289 
290  bool PacketDecoder::processWelcome( welcome *w ){
291    delete w;
292    return true;
293  }
294 
295  bool PacketDecoder::processConnectRequest( connectRequest *con, int clientID ){
296    COUT(3) << "packetdecoder: processing connectRequest" << std::endl;
297    delete con;
298    return true;
299  }
300
301  //these are some print functions for test stuff
302
303  void PacketDecoder::printAck( ack* data )
304  {
305    COUT(5) << "data id: " << data->id << std::endl;
306    COUT(5) << "data:    " << data->a << std::endl;
307  }
308
309  void PacketDecoder::printMouse( mouse* data )
310  {
311    COUT(5) << "data id: " << data->id << std::endl;
312    COUT(5) << "data:    " << data->x << " " << data->y << std::endl;
313  }
314
315  void PacketDecoder::printKey( keyboard* data )
316  {
317    COUT(5) << "data id: " << data->id << std::endl;
318    COUT(5) << "data:    " << (char)data->press << std::endl;
319  }
320
321  void PacketDecoder::printChat( chat* data, int clientId )
322  {
323    if(clientId!=CLIENTID_CLIENT)
324      COUT(5) << "client: " << clientId << std::endl;
325    COUT(5) << "data id: " << data->id << std::endl;
326    COUT(5) << "data:    " << data->message << std::endl;
327  }
328
329  void PacketDecoder::printGamestate( GameStateCompressed* data )
330  {
331    COUT(5) << "id of GameStateCompressed:   " << data->id << std::endl;
332    COUT(5) << "size of GameStateCompressed: " << data->compsize << std::endl;
333  }
334
335  void PacketDecoder::printClassid( classid *cid)
336  {
337    COUT(5) << "id of classid:    " << cid->id << std::endl;
338    COUT(5) << "size of classid:  " << cid->length << std::endl;
339    COUT(5) << "ID of classid:    " << cid->clid << std::endl;
340    COUT(5) << "data of classid:  " << cid->message << std::endl;
341  }
342
343}
Note: See TracBrowser for help on using the repository browser.