netEvent.cpp
Engine/source/sim/netEvent.cpp
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