Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/netp2/src/network/packet/Packet.cc @ 3050

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

this is another commit for testing purpose
still trying to get network function calls to work (first success)

  • Property svn:eol-style set to native
File size: 7.1 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#include <boost/thread/recursive_mutex.hpp>
36
37#include "network/ConnectionManager.h"
38#include "network/ClientInformation.h"
39
40#include "Acknowledgement.h"
41#include "DeleteObjects.h"
42#include "Chat.h"
43#include "ClassID.h"
44#include "FunctionCalls.h"
45#include "FunctionIDs.h"
46#include "Gamestate.h"
47#include "Welcome.h"
48#include "network/Host.h"
49#include "core/CoreIncludes.h"
50
51namespace orxonox{
52
53namespace packet{
54
55#define PACKET_FLAG_DEFAULT ENET_PACKET_FLAG_NO_ALLOCATE
56#define _PACKETID           0
57
58std::map<size_t, Packet *> Packet::packetMap_;
59//! Static mutex for any packetMap_ access
60static boost::recursive_mutex packetMap_mutex_g;
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(packetMap_mutex_g);
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  Host::addPacket( enetPacket_, clientID_);
168  return true;
169}
170
171Packet *Packet::createPacket(ENetPacket *packet, ENetPeer *peer){
172  uint8_t *data = packet->data;
173  assert(ClientInformation::findClient(&peer->address)->getID() != (unsigned int)-2 || !Host::isServer());
174  unsigned int clientID = ClientInformation::findClient(&peer->address)->getID();
175  Packet *p = 0;
176  COUT(6) << "packet type: " << *(ENUM::Type *)&data[_PACKETID] << std::endl;
177  switch( *(ENUM::Type *)(data + _PACKETID) )
178  {
179    case ENUM::Acknowledgement:
180      COUT(5) << "ack" << std::endl;
181      p = new Acknowledgement( data, clientID );
182      break;
183    case ENUM::Chat:
184      COUT(5) << "chat" << std::endl;
185      p = new Chat( data, clientID );
186      break;
187    case ENUM::ClassID:
188      COUT(5) << "classid" << std::endl;
189      p = new ClassID( data, clientID );
190      break;
191    case ENUM::Gamestate:
192      COUT(5) << "gamestate" << std::endl;
193      // TODO: remove brackets
194      p = new Gamestate( data, clientID );
195      break;
196    case ENUM::Welcome:
197      COUT(5) << "welcome" << std::endl;
198      p = new Welcome( data, clientID );
199      break;
200    case ENUM::DeleteObjects:
201      COUT(5) << "deleteobjects" << std::endl;
202      p = new DeleteObjects( data, clientID );
203      break;
204    case ENUM::FunctionCalls:
205      COUT(5) << "functionCalls" << std::endl;
206      p = new FunctionCalls( data, clientID );
207      break;
208    case ENUM::FunctionIDs:
209      COUT(5) << "functionIDs" << std::endl;
210      p = new FunctionIDs( data, clientID );
211      break;
212    default:
213      assert(0); //TODO: repair this
214      break;
215  }
216
217  // Data was created by ENet
218  p->bDataENetAllocated_ = true;
219
220  return p;
221}
222
223/**
224@brief
225    ENet calls this method whenever it wants to destroy a packet that contains
226    data we allocated ourselves.
227*/
228void Packet::deletePacket(ENetPacket *enetPacket){
229  boost::recursive_mutex::scoped_lock lock(packetMap_mutex_g);
230  // Get our Packet from a gloabal map with all Packets created in the send() method of Packet.
231  std::map<size_t, Packet*>::iterator it = packetMap_.find((size_t)enetPacket);
232  assert(it != packetMap_.end());
233  // Make sure we don't delete it again in the destructor
234  it->second->enetPacket_ = 0;
235  delete it->second;
236  packetMap_.erase(it);
237  COUT(4) << "PacketMap size: " << packetMap_.size() << std::endl;
238}
239
240} // namespace packet
241
242} // namespace orxonox
243
Note: See TracBrowser for help on using the repository browser.