Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/netp5/src/network/packet/Packet.cc @ 3211

Last change on this file since 3211 was 3211, checked in by rgrieder, 15 years ago

Moved PacketFlag and added includes for memcpy() and abort() (Mingw didn't seem to care).

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