Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 2751 was 2710, checked in by rgrieder, 16 years ago

Merged buildsystem3 containing buildsystem2 containing Adi's buildsystem branch back to the trunk.
Please update the media directory if you were not using buildsystem3 before.

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