Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/network/packet/Packet.cc @ 2769

Last change on this file since 2769 was 2756, checked in by rgrieder, 16 years ago

Minimising problems when including windows.h because it defines macros like "min" and "max" if not explicitly specified.
There are two headers we use that include windows.h: OgreWindowEventUtilities.h and enet.h. I had to tweak a little bit there as well.

  • Property svn:eol-style set to native
File size: 6.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 *      Oliver Scheuss, (C) 2008
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29
30#include "Packet.h"
31
32#include <cassert>
33#ifndef WIN32_LEAN_AND_MEAN
34#  define WIN32_LEAN_AND_MEAN
35#endif
36#define NOMINMAX // required to stop windows.h screwing up std::min definition
37#include <enet/enet.h>
38#include <boost/bind.hpp>
39
40#include "network/ConnectionManager.h"
41#include "network/ClientInformation.h"
42
43#include "Acknowledgement.h"
44#include "Chat.h"
45#include "ClassID.h"
46#include "Gamestate.h"
47#include "Welcome.h"
48#include "DeleteObjects.h"
49#include "network/Host.h"
50#include "core/CoreIncludes.h"
51
52namespace orxonox{
53
54namespace packet{
55
56#define PACKET_FLAG_DEFAULT ENET_PACKET_FLAG_NO_ALLOCATE
57#define _PACKETID           0
58
59std::map<size_t, Packet *> Packet::packetMap_;
60boost::recursive_mutex Packet::packetMap_mutex;
61
62Packet::Packet(){
63  flags_ = PACKET_FLAG_DEFAULT;
64  packetDirection_ = ENUM::Outgoing;
65  clientID_=0;
66  data_=0;
67  enetPacket_=0;
68  bDataENetAllocated_ = false;
69}
70
71void blub(ENetPacket *packet){
72  COUT(4) << "blubb" << std::endl;
73}
74
75Packet::Packet(uint8_t *data, unsigned int clientID){
76  flags_ = PACKET_FLAG_DEFAULT;
77  packetDirection_ = ENUM::Incoming;
78  clientID_=clientID;
79  data_=data;
80  enetPacket_=0;
81  bDataENetAllocated_ = false;
82}
83
84
85Packet::Packet(const Packet &p){
86  enetPacket_=p.enetPacket_;
87  flags_=p.flags_;
88  packetDirection_ = p.packetDirection_;
89  clientID_ = p.clientID_;
90  if(p.data_){
91    data_ = new uint8_t[p.getSize()];
92    memcpy(data_, p.data_, p.getSize());
93  }else
94    data_=0;
95  bDataENetAllocated_ = p.bDataENetAllocated_;
96}
97
98/**
99@brief
100    Destroys a packet completely.
101   
102    That also means destroying the ENetPacket if one exists. There
103*/
104Packet::~Packet(){
105  // Deallocate data_ memory if necessary.
106  if (this->bDataENetAllocated_){
107    // In this case ENet allocated data_ and will destroy it.
108  }
109  else if (this->data_) {
110    // This destructor was probably called as a consequence to ENet executing our callback.
111    // It simply serves us to be able to deallocate the packet content (data_) ourselves since
112    // we have created it in the first place.
113    delete[] this->data_;
114  }
115
116  // Destroy the ENetPacket if necessary.
117  // Note: For the case ENet used the callback to destroy the packet, we have already set
118  // enetPacket_ to NULL to avoid destroying it again.
119  if (this->enetPacket_){
120    // enetPacket_->data gets destroyed too by ENet if it was allocated by it.
121    enet_packet_destroy(enetPacket_);
122  }
123}
124
125bool Packet::send(){
126  if(packetDirection_ != ENUM::Outgoing && packetDirection_ != ENUM::Bidirectional ){
127    assert(0);
128    return false;
129  }
130  if(!enetPacket_){
131    if(!data_){
132      assert(0);
133      return false;
134    }
135    // We deliver ENet the data address so that it doesn't memcpy everything again.
136    // --> We have to delete data_ ourselves!
137    enetPacket_ = enet_packet_create(getData(), getSize(), getFlags());
138    enetPacket_->freeCallback = &Packet::deletePacket;
139    // Add the packet to a global list so we can access it again once enet calls our
140    // deletePacket method. We can of course only give a one argument function to the ENet C library.
141    {
142      // Assures we don't create a packet and destroy it right after in another thread
143      // without having a reference in the packetMap_
144      boost::recursive_mutex::scoped_lock lock(Packet::packetMap_mutex);
145      packetMap_[(size_t)(void*)enetPacket_] = this;
146    }
147  }
148#ifndef NDEBUG
149  switch( *(ENUM::Type *)(data_ + _PACKETID) )
150  {
151    case ENUM::Acknowledgement:
152    case ENUM::Chat:
153    case ENUM::ClassID:
154    case ENUM::Gamestate:
155    case ENUM::Welcome:
156    case ENUM::DeleteObjects:
157      break;
158    default:
159      assert(0); //there was some error, if this is the case
160      break;
161  }
162#endif
163//  ENetPacket *temp = enetPacket_;
164//  enetPacket_ = 0; // otherwise we have a double free because enet already handles the deallocation of the packet
165  Host::addPacket( enetPacket_, clientID_);
166  return true;
167}
168
169Packet *Packet::createPacket(ENetPacket *packet, ENetPeer *peer){
170  uint8_t *data = packet->data;
171  assert(ClientInformation::findClient(&peer->address)->getID() != (unsigned int)-2 || !Host::isServer());
172  unsigned int clientID = ClientInformation::findClient(&peer->address)->getID();
173  Packet *p = 0;
174  COUT(5) << "packet type: " << *(ENUM::Type *)&data[_PACKETID] << std::endl;
175  switch( *(ENUM::Type *)(data + _PACKETID) )
176  {
177    case ENUM::Acknowledgement:
178      COUT(4) << "ack" << std::endl;
179      p = new Acknowledgement( data, clientID );
180      break;
181    case ENUM::Chat:
182      COUT(4) << "chat" << std::endl;
183      p = new Chat( data, clientID );
184      break;
185    case ENUM::ClassID:
186      COUT(4) << "classid" << std::endl;
187      p = new ClassID( data, clientID );
188      break;
189    case ENUM::Gamestate:
190      COUT(4) << "gamestate" << std::endl;
191      // TODO: remove brackets
192      p = new Gamestate( data, clientID );
193      break;
194    case ENUM::Welcome:
195      COUT(4) << "welcome" << std::endl;
196      p = new Welcome( data, clientID );
197      break;
198    case ENUM::DeleteObjects:
199      COUT(4) << "deleteobjects" << std::endl;
200      p = new DeleteObjects( data, clientID );
201      break;
202    default:
203      assert(0); //TODO: repair this
204      break;
205  }
206
207  // Data was created by ENet
208  p->bDataENetAllocated_ = true;
209
210  return p;
211}
212
213/**
214@brief
215    ENet calls this method whenever it wants to destroy a packet that contains
216    data we allocated ourselves.
217*/
218void Packet::deletePacket(ENetPacket *enetPacket){
219  boost::recursive_mutex::scoped_lock lock(Packet::packetMap_mutex);
220  // Get our Packet from a gloabal map with all Packets created in the send() method of Packet.
221  std::map<size_t, Packet*>::iterator it = packetMap_.find((size_t)enetPacket);
222  assert(it != packetMap_.end());
223  // Make sure we don't delete it again in the destructor
224  it->second->enetPacket_ = 0;
225  delete it->second;
226  packetMap_.erase(it);
227  COUT(4) << "PacketMap size: " << packetMap_.size() << std::endl;
228}
229
230} // namespace packet
231
232} // namespace orxonox
233
Note: See TracBrowser for help on using the repository browser.