netEvent.cpp

Engine/source/sim/netEvent.cpp

More...

Public Defines

define
DebugChecksum() 0xF00DBAAD

Detailed Description

Public Defines

DebugChecksum() 0xF00DBAAD
  1
  2//-----------------------------------------------------------------------------
  3// Copyright (c) 2012 GarageGames, LLC
  4//
  5// Permission is hereby granted, free of charge, to any person obtaining a copy
  6// of this software and associated documentation files (the "Software"), to
  7// deal in the Software without restriction, including without limitation the
  8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9// sell copies of the Software, and to permit persons to whom the Software is
 10// furnished to do so, subject to the following conditions:
 11//
 12// The above copyright notice and this permission notice shall be included in
 13// all copies or substantial portions of the Software.
 14//
 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 21// IN THE SOFTWARE.
 22//-----------------------------------------------------------------------------
 23
 24#include "platform/platform.h"
 25#include "core/dnet.h"
 26#include "console/simBase.h"
 27#include "sim/netConnection.h"
 28#include "core/stream/bitStream.h"
 29
 30#define DebugChecksum 0xF00DBAAD
 31
 32FreeListChunker<NetEventNote> NetConnection::mEventNoteChunker;
 33
 34NetEvent::~NetEvent()
 35{
 36}
 37
 38void NetEvent::notifyDelivered(NetConnection *, bool)
 39{
 40}
 41
 42void NetEvent::notifySent(NetConnection *)
 43{
 44}
 45
 46#ifdef TORQUE_DEBUG_NET
 47const char *NetEvent::getDebugName()
 48{
 49   return getClassName();
 50}
 51#endif
 52
 53void NetConnection::eventOnRemove()
 54{
 55   while(mNotifyEventList)
 56   {
 57      NetEventNote *temp = mNotifyEventList;
 58      mNotifyEventList = temp->mNextEvent;
 59
 60      temp->mEvent->notifyDelivered(this, true);
 61      temp->mEvent->decRef();
 62      mEventNoteChunker.free(temp);
 63   }
 64
 65   while(mUnorderedSendEventQueueHead)
 66   {
 67      NetEventNote *temp = mUnorderedSendEventQueueHead;
 68      mUnorderedSendEventQueueHead = temp->mNextEvent;
 69
 70      temp->mEvent->notifyDelivered(this, true);
 71      temp->mEvent->decRef();
 72      mEventNoteChunker.free(temp);
 73   }
 74
 75   while(mSendEventQueueHead)
 76   {
 77      NetEventNote *temp = mSendEventQueueHead;
 78      mSendEventQueueHead = temp->mNextEvent;
 79
 80      temp->mEvent->notifyDelivered(this, true);
 81      temp->mEvent->decRef();
 82      mEventNoteChunker.free(temp);
 83   }
 84}
 85
 86void NetConnection::eventPacketDropped(PacketNotify *notify)
 87{
 88   NetEventNote *walk = notify->eventList;
 89   NetEventNote **insertList = &mSendEventQueueHead;
 90   NetEventNote *temp;
 91
 92   while(walk)
 93   {
 94      switch(walk->mEvent->mGuaranteeType)
 95      {
 96         // It was a guaranteed ordered packet, reinsert it back into
 97         // mSendEventQueueHead in the right place (based on seq numbers)
 98         case NetEvent::GuaranteedOrdered:
 99
100            //Con::printf("EVT  %d: DROP - %d", getId(), walk->mSeqCount);
101
102            while(*insertList && (*insertList)->mSeqCount < walk->mSeqCount)
103               insertList = &((*insertList)->mNextEvent);
104
105            temp = walk->mNextEvent;
106            walk->mNextEvent = *insertList;
107            if(!walk->mNextEvent)
108               mSendEventQueueTail = walk;
109            *insertList = walk;
110            insertList = &(walk->mNextEvent);
111            walk = temp;
112            break;
113
114         // It was a guaranteed packet, put it at the top of
115         // mUnorderedSendEventQueueHead.
116         case NetEvent::Guaranteed:
117            temp = walk->mNextEvent;
118            walk->mNextEvent = mUnorderedSendEventQueueHead;
119            mUnorderedSendEventQueueHead = walk;
120            if(!walk->mNextEvent)
121               mUnorderedSendEventQueueTail = walk;
122            walk = temp;
123            break;
124
125         // Or else it was an unguaranteed packet, notify that
126         // it was _not_ delivered and blast it.
127         case NetEvent::Unguaranteed:
128            walk->mEvent->notifyDelivered(this, false);
129            walk->mEvent->decRef();
130            temp = walk->mNextEvent;
131            mEventNoteChunker.free(walk);
132            walk = temp;
133      }
134   }
135}
136
137void NetConnection::eventPacketReceived(PacketNotify *notify)
138{
139   NetEventNote *walk = notify->eventList;
140   NetEventNote **noteList = &mNotifyEventList;
141
142   while(walk)
143   {
144      NetEventNote *next = walk->mNextEvent;
145      if(walk->mEvent->mGuaranteeType != NetEvent::GuaranteedOrdered)
146      {
147         walk->mEvent->notifyDelivered(this, true);
148         walk->mEvent->decRef();
149         mEventNoteChunker.free(walk);
150         walk = next;
151      }
152      else
153      {
154         while(*noteList && (*noteList)->mSeqCount < walk->mSeqCount)
155            noteList = &((*noteList)->mNextEvent);
156
157         walk->mNextEvent = *noteList;
158         *noteList = walk;
159         noteList = &walk->mNextEvent;
160         walk = next;
161      }
162   }
163   while(mNotifyEventList && mNotifyEventList->mSeqCount == mLastAckedEventSeq + 1)
164   {
165      mLastAckedEventSeq++;
166      NetEventNote *next = mNotifyEventList->mNextEvent;
167      //Con::printf("EVT  %d: ACK - %d", getId(), mNotifyEventList->mSeqCount);
168      mNotifyEventList->mEvent->notifyDelivered(this, true);
169      mNotifyEventList->mEvent->decRef();
170      mEventNoteChunker.free(mNotifyEventList);
171      mNotifyEventList = next;
172   }
173}
174
175void NetConnection::eventWritePacket(BitStream *bstream, PacketNotify *notify)
176{
177#ifdef TORQUE_DEBUG_NET
178   bstream->writeInt(DebugChecksum, 32);
179#endif
180
181   NetEventNote *packQueueHead = NULL, *packQueueTail = NULL;
182
183   while(mUnorderedSendEventQueueHead)
184   {
185      if(bstream->isFull())
186         break;
187      // dequeue the first event
188      NetEventNote *ev = mUnorderedSendEventQueueHead;
189      mUnorderedSendEventQueueHead = ev->mNextEvent;
190#ifdef TORQUE_DEBUG_NET
191      U32 start = bstream->getCurPos();
192#endif
193
194      bstream->writeFlag(true);
195      S32 classId = ev->mEvent->getClassId(getNetClassGroup());
196      AssertFatal(classId>=0, "NetConnection::eventWritePacket - event not in group!");
197      bstream->writeClassId(classId, NetClassTypeEvent, getNetClassGroup());
198
199#ifdef TORQUE_NET_STATS
200      U32 beginSize = bstream->getBitPosition();
201#endif
202      ev->mEvent->pack(this, bstream);
203#ifdef TORQUE_NET_STATS
204      ev->mEvent->getClassRep()->updateNetStatPack(0, bstream->getBitPosition() - beginSize);
205#endif
206      DEBUG_LOG(("PKLOG %d EVENT %d: %s", getId(), bstream->getBitPosition() - start, ev->mEvent->getDebugName()) );
207
208#ifdef TORQUE_DEBUG_NET
209      bstream->writeInt(classId ^ DebugChecksum, 32);
210#endif
211      // add this event onto the packet queue
212      ev->mNextEvent = NULL;
213      if(!packQueueHead)
214         packQueueHead = ev;
215      else
216         packQueueTail->mNextEvent = ev;
217      packQueueTail = ev;
218   }
219
220   bstream->writeFlag(false);
221   S32 prevSeq = -2;
222
223   while(mSendEventQueueHead)
224   {
225      if(bstream->isFull())
226         break;
227
228      // if the event window is full, stop processing
229      if(mSendEventQueueHead->mSeqCount > mLastAckedEventSeq + 126)
230         break;
231
232      // dequeue the first event
233      NetEventNote *ev = mSendEventQueueHead;
234      mSendEventQueueHead = ev->mNextEvent;
235
236      //Con::printf("EVT  %d: SEND - %d", getId(), ev->mSeqCount);
237
238      bstream->writeFlag(true);
239
240      ev->mNextEvent = NULL;
241      if(!packQueueHead)
242         packQueueHead = ev;
243      else
244         packQueueTail->mNextEvent = ev;
245      packQueueTail = ev;
246      if(!bstream->writeFlag(ev->mSeqCount == prevSeq + 1))
247         bstream->writeInt(ev->mSeqCount & 0x7F, 7);
248
249      prevSeq = ev->mSeqCount;
250
251#ifdef TORQUE_DEBUG_NET
252      U32 start = bstream->getCurPos();
253#endif
254
255      S32 classId = ev->mEvent->getClassId(getNetClassGroup());
256      bstream->writeClassId(classId, NetClassTypeEvent, getNetClassGroup());
257#ifdef TORQUE_NET_STATS
258      U32 beginSize = bstream->getBitPosition();
259#endif
260      ev->mEvent->pack(this, bstream);
261#ifdef TORQUE_NET_STATS
262      ev->mEvent->getClassRep()->updateNetStatPack(0, bstream->getBitPosition() - beginSize);
263#endif
264      DEBUG_LOG(("PKLOG %d EVENT %d: %s", getId(), bstream->getBitPosition() - start, ev->mEvent->getDebugName()) );
265#ifdef TORQUE_DEBUG_NET
266      bstream->writeInt(classId ^ DebugChecksum, 32);
267#endif
268   }
269   for(NetEventNote *ev = packQueueHead; ev; ev = ev->mNextEvent)
270      ev->mEvent->notifySent(this);
271
272   notify->eventList = packQueueHead;
273   bstream->writeFlag(false);
274}
275
276void NetConnection::eventReadPacket(BitStream *bstream)
277{
278#ifdef TORQUE_DEBUG_NET
279   U32 sum = bstream->readInt(32);
280   AssertISV(sum == DebugChecksum, "Invalid checksum.");
281#endif
282
283   S32 prevSeq = -2;
284   NetEventNote **waitInsert = &mWaitSeqEvents;
285   bool unguaranteedPhase = true;
286
287   while(true)
288   {
289      bool bit = bstream->readFlag();
290      if(unguaranteedPhase && !bit)
291      {
292         unguaranteedPhase = false;
293         bit = bstream->readFlag();
294      }
295      if(!unguaranteedPhase && !bit)
296         break;
297
298      S32 seq = -1;
299
300      if(!unguaranteedPhase) // get the sequence
301      {
302         if(bstream->readFlag())
303            seq = (prevSeq + 1) & 0x7f;
304         else
305            seq = bstream->readInt(7);
306         prevSeq = seq;
307      }
308      S32 classId = bstream->readClassId(NetClassTypeEvent, getNetClassGroup());
309      if(classId == -1)
310      {
311         setLastError("Invalid packet. (bad event class id)");
312         return;
313      }
314      StrongRefPtr<NetEvent> evt = (NetEvent *) ConsoleObject::create(getNetClassGroup(), NetClassTypeEvent, classId);
315      if(evt.isNull())
316      {
317         setLastError("Invalid packet. (bad ghost class id)");
318         return;
319      }
320      AbstractClassRep *rep = evt->getClassRep();
321      if((rep->mNetEventDir == NetEventDirServerToClient && !isConnectionToServer())
322         || (rep->mNetEventDir == NetEventDirClientToServer && isConnectionToServer()) )
323      {
324         setLastError("Invalid Packet. (invalid direction)");
325         return;
326      }
327
328
329      evt->mSourceId = getId();
330#ifdef TORQUE_NET_STATS
331      U32 beginSize = bstream->getBitPosition();
332#endif
333      evt->unpack(this, bstream);
334#ifdef TORQUE_NET_STATS
335      evt->getClassRep()->updateNetStatUnpack(bstream->getBitPosition() - beginSize);
336#endif
337      if(mErrorBuffer.isNotEmpty())
338         return;
339#ifdef TORQUE_DEBUG_NET
340      U32 checksum = bstream->readInt(32);
341      AssertISV( (checksum ^ DebugChecksum) == (U32)classId,
342         avar("unpack did not match pack for event of class %s.",
343            evt->getClassName()) );
344#endif
345      if(unguaranteedPhase)
346      {
347         evt->process(this);
348         evt = NULL;
349         if(mErrorBuffer.isNotEmpty())
350            return;
351         continue;
352      }
353      seq |= (mNextRecvEventSeq & ~0x7F);
354      if(seq < mNextRecvEventSeq)
355         seq += 128;
356
357      NetEventNote *note = mEventNoteChunker.alloc();
358      note->mEvent = evt;
359      note->mEvent->incRef();
360
361      note->mSeqCount = seq;
362      //Con::printf("EVT  %d: RECV - %d", getId(), evt->mSeqCount);
363      while(*waitInsert && (*waitInsert)->mSeqCount < seq)
364         waitInsert = &((*waitInsert)->mNextEvent);
365
366      note->mNextEvent = *waitInsert;
367      *waitInsert = note;
368      waitInsert = &(note->mNextEvent);
369   }
370   while(mWaitSeqEvents && mWaitSeqEvents->mSeqCount == mNextRecvEventSeq)
371   {
372      mNextRecvEventSeq++;
373      NetEventNote *temp = mWaitSeqEvents;
374      mWaitSeqEvents = temp->mNextEvent;
375
376      //Con::printf("EVT  %d: PROCESS - %d", getId(), temp->mSeqCount);
377      temp->mEvent->process(this);
378      temp->mEvent->decRef();
379      mEventNoteChunker.free(temp);
380      if(mErrorBuffer.isNotEmpty())
381         return;
382   }
383}
384
385bool NetConnection::postNetEvent(NetEvent *theEvent)
386{
387   if(!mSendingEvents)
388   {
389      theEvent->decRef();
390      return false;
391   }
392   NetEventNote *event = mEventNoteChunker.alloc();
393   event->mEvent = theEvent;
394   theEvent->incRef();
395
396   event->mNextEvent = NULL;
397   if(theEvent->mGuaranteeType == NetEvent::GuaranteedOrdered)
398   {
399      event->mSeqCount = mNextSendEventSeq++;
400      if(!mSendEventQueueHead)
401         mSendEventQueueHead = event;
402      else
403         mSendEventQueueTail->mNextEvent = event;
404      mSendEventQueueTail = event;
405   }
406   else
407   {
408      event->mSeqCount = InvalidSendEventSeq;
409      if(!mUnorderedSendEventQueueHead)
410         mUnorderedSendEventQueueHead = event;
411      else
412         mUnorderedSendEventQueueTail->mNextEvent = event;
413      mUnorderedSendEventQueueTail = event;
414   }
415   return true;
416}
417
418
419void NetConnection::eventWriteStartBlock(ResizeBitStream *stream)
420{
421   stream->write(mNextRecvEventSeq);
422   for(NetEventNote *walk = mWaitSeqEvents; walk; walk = walk->mNextEvent)
423   {
424      stream->writeFlag(true);
425      S32 classId = walk->mEvent->getClassId(getNetClassGroup());
426      stream->writeClassId(classId, NetClassTypeEvent, getNetClassGroup());
427      walk->mEvent->write(this, stream);
428      stream->validate();
429   }
430   stream->writeFlag(false);
431}
432
433void NetConnection::eventReadStartBlock(BitStream *stream)
434{
435   stream->read(&mNextRecvEventSeq);
436
437   NetEventNote *lastEvent = NULL;
438   while(stream->readFlag())
439   {
440      S32 classTag = stream->readClassId(NetClassTypeEvent, getNetClassGroup());
441      NetEvent *evt = (NetEvent *) ConsoleObject::create(getNetClassGroup(), NetClassTypeEvent, classTag);
442      evt->unpack(this, stream);
443      NetEventNote *add = mEventNoteChunker.alloc();
444      add->mEvent = evt;
445      evt->incRef();
446      add->mNextEvent = NULL;
447
448      if(!lastEvent)
449         mWaitSeqEvents = add;
450      else
451         lastEvent->mNextEvent = add;
452      lastEvent = add;
453   }
454}
455