Exemplo n.º 1
0
bool EventConnection::readConnectAccept(BitStream *stream, NetConnection::TerminationReason &reason)
{
   if(!Parent::readConnectAccept(stream, reason))
      return false;

   stream->read(&mEventClassCount);                                                      // Number of RPCs the remote server is willing to support
   U32 myCount = NetClassRep::getNetClassCount(getNetClassGroup(), NetClassTypeEvent);   // Number we, the client, support

   if(mEventClassCount > myCount)      // Normally, these should be equal.  If the server is not willing to support
   {                                   // as many RPCs as we want to use, then bail.
      logprintf(LogConsumer::LogConnection, "Connection to master failed due to a disagreement on the number of RPCs supported.");
      return false;                    
   }

   if(!NetClassRep::isVersionBorderCount(getNetClassGroup(), NetClassTypeEvent, mEventClassCount))
   {
      logprintf(LogConsumer::LogConnection, "Connection to master failed due to incompatible versions.");
      return false;
   }

   mEventClassBitSize = getNextBinLog2(mEventClassCount);

   clearSendEvents();
   clearRecvEvents();

   return true;
}
Exemplo n.º 2
0
// Reads the NetEvent class count max that the remote host is requesting.
// If this host has MORE NetEvent classes declared, the mEventClassCount
// is set to the requested count, and is verified to lie on a boundary between versions.
// This gets run when someone is connecting to us
bool EventConnection::readConnectRequest(BitStream *stream, NetConnection::TerminationReason &reason)
{
   if(!Parent::readConnectRequest(stream, reason))
      return false;

   U32 remoteClassCount;
   stream->read(&remoteClassCount);

   U32 localClassCount = NetClassRep::getNetClassCount(getNetClassGroup(), NetClassTypeEvent);   // Essentially a count of RPCs 

   // If remote client has more classes defined than we do, hope/assume they're defined in the same order, so that we at least agree
   // on the available set of RPCs.
   // This implies the client is higher version than the server  
   if(localClassCount <= remoteClassCount)
      mEventClassCount = localClassCount;    // We're only willing to support as many as we have
   else     // We have more RPCs on the local machine ==> implies server is higher version than client
   {
      mEventClassCount = remoteClassCount;   // We're willing to support the number of classes the client has

      // Check if the next RPC is a higher version than the current one specified by mEventClassCount
      if(!NetClassRep::isVersionBorderCount(getNetClassGroup(), NetClassTypeEvent, mEventClassCount))
      {
         reason = ReasonIncompatibleRPCCounts;
         return false;     // If not, abort connection
      }
   }

   mEventClassVersion = NetClassRep::getClass(getNetClassGroup(), NetClassTypeEvent, mEventClassCount-1)->getClassVersion();
   mEventClassBitSize = getNextBinLog2(mEventClassCount);

   clearSendEvents();
   clearRecvEvents();

   return true;
}
Exemplo n.º 3
0
NetEvent *EventConnection::unpackNetEvent(BitStream *bstream)
{
   U32 endingPosition;
   if(mConnectionParameters.mDebugObjectSizes)
      endingPosition = bstream->readInt(BitStreamPosBitSize);

   U32 classId = bstream->readInt(mEventClassBitSize);
   if(classId >= mEventClassCount)
   {
      setLastError("Invalid packet -- classId too high.");
      return NULL;
   }

   NetEvent *evt = (NetEvent *) Object::create(getNetClassGroup(), NetClassTypeEvent, classId);
   if(!evt)
   {
      setLastError("Invalid packet -- couldn't create event.");
      return NULL;
   }

   // Check if the direction this event moves is a valid direction.
   if(   (evt->getEventDirection() == NetEvent::DirUnset)
      || (evt->getEventDirection() == NetEvent::DirServerToClient && isConnectionToClient())
      || (evt->getEventDirection() == NetEvent::DirClientToServer && isConnectionToServer()) )
   {
      setLastError("Invalid Packet -- event direction wrong. %s", evt->getClassName());
      delete evt;
      return NULL;
   }


   evt->unpack(this, bstream);
   if(mErrorBuffer[0])
   {
      delete evt;
      return NULL;
   }

   if(mConnectionParameters.mDebugObjectSizes)
   {
      TNLAssert(((endingPosition - bstream->getBitPosition()) & ~(~0 << BitStreamPosBitSize)) == 0,
                avar("Unpack did not match pack for event of class %s.", evt->getClassName()) );
   }
   return evt;
}
Exemplo n.º 4
0
void GhostConnection::readPacket(BitStream *bstream)
{
   Parent::readPacket(bstream);

   if(mConnectionParameters.mDebugObjectSizes)
   {
      U32 sum = bstream->readInt(32);
      TNLAssert(sum == DebugChecksum, "Invalid checksum.");
   }

   if(!doesGhostTo())
      return;
   if(!bstream->readFlag())
      return;

   S32 idSize;
   idSize = bstream->readInt( 3 );
   idSize += 3;

   // while there's an object waiting...

   while(bstream->readFlag())
   {
      U32 index;
      //S32 startPos = bstream->getCurPos();
      index = (U32) bstream->readInt(idSize);
      if(bstream->readFlag()) // is this ghost being deleted?
      {
         TNLAssert(mLocalGhosts[index] != NULL, "Error, NULL ghost encountered.");
		   if(mLocalGhosts[index])
         {
            mLocalGhosts[index]->onGhostRemove();
		      delete mLocalGhosts[index];
            mLocalGhosts[index] = NULL;
         }
      }
      else
      {
         U32 endPosition = 0;
         if(mConnectionParameters.mDebugObjectSizes)
            endPosition = bstream->readInt(BitStreamPosBitSize);

         if(!mLocalGhosts[index]) // it's a new ghost... cool
         {
            S32 classId = bstream->readClassId(NetClassTypeObject, getNetClassGroup());
            if(classId == -1)
            {
               setLastError("Invalid packet.");
               return;
            }

            NetObject *obj = (NetObject *) Object::create(getNetClassGroup(), NetClassTypeObject, classId);
            if(!obj)
            {
               setLastError("Invalid packet.");
               return;
            }
            obj->mOwningConnection = this;
            obj->mNetFlags = NetObject::IsGhost;

            // object gets initial update before adding to the manager

            obj->mNetIndex = index;
            mLocalGhosts[index] = obj;

            NetObject::mIsInitialUpdate = true;
            mLocalGhosts[index]->unpackUpdate(this, bstream);
            NetObject::mIsInitialUpdate = false;
            
            if(!obj->onGhostAdd(this))
            {
               if(!mErrorBuffer[0])
                  setLastError("Invalid packet.");
               return;
            }
            if(mRemoteConnection)
            {
               GhostConnection *gc = static_cast<GhostConnection *>(mRemoteConnection.getPointer());
               obj->mServerObject = gc->resolveGhostParent(index);
            }
         }
         else
         {
            mLocalGhosts[index]->unpackUpdate(this, bstream);
         }

         if(mConnectionParameters.mDebugObjectSizes)
         {
            TNLAssert(bstream->getBitPosition() == endPosition,
            avar("unpackUpdate did not match packUpdate for object of class %s. Expected %d bits, got %d bits.",
               mLocalGhosts[index]->getClassName(), endPosition, bstream->getBitPosition()) );
         }

         if(mErrorBuffer[0])
            return;
      }
   }
}
Exemplo n.º 5
0
void GhostConnection::writePacket(BitStream *bstream, PacketNotify *pnotify)
{
   Parent::writePacket(bstream, pnotify);
   GhostPacketNotify *notify = static_cast<GhostPacketNotify *>(pnotify);

   if(mConnectionParameters.mDebugObjectSizes)
      bstream->writeInt(DebugChecksum, 32);

   notify->ghostList = NULL;
   
   if(!doesGhostFrom())
      return;
   
   if(!bstream->writeFlag(mGhosting && mScopeObject.isValid()))
      return;
      
   // fill a packet (or two) with ghosting data

   // 2. call scoped objects' priority functions if the flag set is nonzero
   //    A removed ghost is assumed to have a high priority
   // 3. call updates based on sorted priority until the packet is
   //    full.  set flags to zero for all updated objects

   GhostInfo *walk;

   for(S32 i = mGhostZeroUpdateIndex - 1; i >= 0; i--)
   {
      if(!(mGhostArray[i]->flags & GhostInfo::InScope))
         detachObject(mGhostArray[i]);
   }

   U32 maxIndex = 0;
   for(S32 i = mGhostZeroUpdateIndex - 1; i >= 0; i--)
   {
      walk = mGhostArray[i];
      if(walk->index > maxIndex)
         maxIndex = walk->index;

      // clear out any kill objects that haven't been ghosted yet
      if((walk->flags & GhostInfo::KillGhost) && (walk->flags & GhostInfo::NotYetGhosted))
      {
         freeGhostInfo(walk);
         continue;
      }
      // don't do any ghost processing on objects that are being killed
      // or in the process of ghosting
      else if(!(walk->flags & (GhostInfo::KillingGhost | GhostInfo::Ghosting)))
      {
         if(walk->flags & GhostInfo::KillGhost)
            walk->priority = 10000;
         else
            walk->priority = walk->obj->getUpdatePriority(mScopeObject, walk->updateMask, walk->updateSkipCount);
      }
      else
         walk->priority = 0;
   }
   GhostRef *updateList = NULL;
   qsort(mGhostArray, mGhostZeroUpdateIndex, sizeof(GhostInfo *), UQECompare);
   // reset the array indices...
   for(S32 i = mGhostZeroUpdateIndex - 1; i >= 0; i--)
      mGhostArray[i]->arrayIndex = i;

   S32 sendSize = 1;
   while(maxIndex >>= 1)
      sendSize++;

   if(sendSize < 3)
      sendSize = 3;

   bstream->writeInt(sendSize - 3, 3); // 0-7 3 bit number

   U32 count = 0;
   // 
   for(S32 i = mGhostZeroUpdateIndex - 1; i >= 0 && !bstream->isFull(); i--)
   {
      GhostInfo *walk = mGhostArray[i];
		if(walk->flags & (GhostInfo::KillingGhost | GhostInfo::Ghosting))
		   continue;

      size_t updateStart = bstream->getBitPosition();
      U32 updateMask = walk->updateMask;
      U32 retMask = 0;
		   
      bstream->writeFlag(true);
      bstream->writeInt(walk->index, sendSize);
      if(!bstream->writeFlag(walk->flags & GhostInfo::KillGhost))
      {
         // this is an update of some kind:
         if(mConnectionParameters.mDebugObjectSizes)
            bstream->advanceBitPosition(BitStreamPosBitSize);

         size_t startPos = bstream->getBitPosition();

         if(walk->flags & GhostInfo::NotYetGhosted)
         {
            S32 classId = walk->obj->getClassId(getNetClassGroup());
            bstream->writeClassId(classId, NetClassTypeObject, getNetClassGroup());
            NetObject::mIsInitialUpdate = true;
         }

         // update the object
         retMask = walk->obj->packUpdate(this, updateMask, bstream);

         if(NetObject::mIsInitialUpdate)
         {
            NetObject::mIsInitialUpdate = false;
            walk->obj->getClassRep()->addInitialUpdate(bstream->getBitPosition() - startPos);
         }
         else
            walk->obj->getClassRep()->addPartialUpdate(bstream->getBitPosition() - startPos);

		  if(mConnectionParameters.mDebugObjectSizes){
			  size_t bpL = bstream->getBitPosition();
			  U32 bp = static_cast<U32>(bpL);
			  TNLAssert(bp == bpL, "This stream position is too long");
			bstream->writeIntAt(bp, BitStreamPosBitSize, startPos - BitStreamPosBitSize);
		  }
		  

         TNLLogMessageV(LogGhostConnection, ("GhostConnection %s GHOST %d", walk->obj->getClassName(), bstream->getBitPosition() - 16 - startPos));

         TNLAssert((retMask & (~updateMask)) == 0, "Cannot set new bits in packUpdate return");
      }

      // check for packet overrun, and rewind this update if there
      // was one:
      if(bstream->getBitSpaceAvailable() < MinimumPaddingBits)
      {
         bstream->setBitPosition(updateStart);
         bstream->clearError();
         break;
      }

      // otherwise, create a record of this ghost update and
      // attach it to the packet.
      GhostRef *upd = new GhostRef;

      upd->nextRef = updateList;
      updateList = upd;

      if(walk->lastUpdateChain)
         walk->lastUpdateChain->updateChain = upd;
      walk->lastUpdateChain = upd;

      upd->ghost = walk;
      upd->ghostInfoFlags = 0;
      upd->updateChain = NULL;

      if(walk->flags & GhostInfo::KillGhost)
      {
         walk->flags &= ~GhostInfo::KillGhost;
         walk->flags |= GhostInfo::KillingGhost;
         walk->updateMask = 0;
         upd->mask = updateMask;
         ghostPushToZero(walk);
         upd->ghostInfoFlags = GhostInfo::KillingGhost;
      }
      else
      {
         if(walk->flags & GhostInfo::NotYetGhosted)
         {
            walk->flags &= ~GhostInfo::NotYetGhosted;
            walk->flags |= GhostInfo::Ghosting;
            upd->ghostInfoFlags = GhostInfo::Ghosting;
         }
         walk->updateMask = retMask;
         if(!retMask)
            ghostPushToZero(walk);
         upd->mask = updateMask & ~retMask;
         walk->updateSkipCount = 0;
         count++;
      }
   }
   // count # of ghosts have been updated,
   // mGhostZeroUpdateIndex # of ghosts remain to be updated.
   // no more objects...
   bstream->writeFlag(false);
   notify->ghostList = updateList;
}
Exemplo n.º 6
0
bool EventConnection::postNetEvent(NetEvent *theEvent)
{
   // Check if the direction this event moves is a valid direction.
   TNLAssertV(   (theEvent->getEventDirection() != NetEvent::DirUnset)
      && (theEvent->getEventDirection() != NetEvent::DirServerToClient || !isConnectionToServer())
      && (theEvent->getEventDirection() != NetEvent::DirClientToServer || !isConnectionToClient()),
      ("Trying to send wrong event direction in %s", theEvent->getClassName()));

   S32 classId = theEvent->getClassId(getNetClassGroup());
   if(U32(classId) >= mEventClassCount && getConnectionState() == Connected)
   {
      theEvent->incRef();
      theEvent->decRef(); // Avoids some type of memory leak by deleting here if nothing reference it.
      return false;
   }

   theEvent->notifyPosted(this);

   EventNote *event = mEventNoteChunker.alloc();
   event->mEvent = theEvent;
   event->mNextEvent = NULL;

   if(event->mEvent->mGuaranteeType == NetEvent::GuaranteedOrdered)
   {
      event->mSeqCount = mNextSendEventSeq++;
      if(!mSendEventQueueHead)
         mSendEventQueueHead = event;
      else
         mSendEventQueueTail->mNextEvent = event;
      mSendEventQueueTail = event;
   }
   else if(event->mEvent->mGuaranteeType == NetEvent::GuaranteedOrderedBigData)
   {
      BitStream bstream;
      const U32 start = 0;
      const U32 partsSize = 512;

      if(mConnectionParameters.mDebugObjectSizes)
         bstream.advanceBitPosition(BitStreamPosBitSize);
      
      S32 classId = event->mEvent->getClassId(getNetClassGroup());
      bstream.writeInt(classId, mEventClassBitSize);

      event->mEvent->pack(this, &bstream);
      logprintf(LogConsumer::LogEventConnection, "EventConnection %s: WroteEvent %s - %d bits", getNetAddressString(), event->mEvent->getDebugName(), bstream.getBitPosition() - start);

      if(mConnectionParameters.mDebugObjectSizes)
         bstream.writeIntAt(bstream.getBitPosition(), BitStreamPosBitSize, start);

      U32 size = bstream.getBytePosition();

      for(U32 i=0; i<size; i+=partsSize)
      {
         if(i+partsSize < size)
         {
            ByteBuffer *bytebuffer = new ByteBuffer(&bstream.getBuffer()[i], partsSize);
            bytebuffer->takeOwnership();  // may have to use this to prevent errors.
            s2rTNLSendDataParts(0, ByteBufferPtr(bytebuffer));
         }
         else
         {
            ByteBuffer *bytebuffer = new ByteBuffer(&bstream.getBuffer()[i], size-i);
            bytebuffer->takeOwnership();
            s2rTNLSendDataParts(1, ByteBufferPtr(bytebuffer));
         }
      }
      mEventNoteChunker.free(event);
   }
   else
   {
      event->mSeqCount = InvalidSendEventSeq;
      if(!mUnorderedSendEventQueueHead)
         mUnorderedSendEventQueueHead = event;
      else
         mUnorderedSendEventQueueTail->mNextEvent = event;
      mUnorderedSendEventQueueTail = event;
   }
   return true;
}
Exemplo n.º 7
0
void EventConnection::writePacket(BitStream *bstream, PacketNotify *pnotify)
{
   Parent::writePacket(bstream, pnotify);
   EventPacketNotify *notify = static_cast<EventPacketNotify *>(pnotify);
   
   bool have_something_to_send = bstream->getBitPosition() >= 128;

   if(mConnectionParameters.mDebugObjectSizes)
      bstream->writeInt(DebugChecksum, 32);

   EventNote *packQueueHead = NULL, *packQueueTail = NULL;

   while(mUnorderedSendEventQueueHead)
   {
      if(bstream->isFull())
         break;
      // get the first event
      EventNote *ev = mUnorderedSendEventQueueHead;
      ConnectionStringTable::PacketEntry *strEntry = getCurrentWritePacketNotify()->stringList.stringTail;

      bstream->writeFlag(true);
      S32 start = bstream->getBitPosition();

      if(mConnectionParameters.mDebugObjectSizes)
         bstream->advanceBitPosition(BitStreamPosBitSize);
      
      S32 classId = ev->mEvent->getClassId(getNetClassGroup());
      bstream->writeInt(classId, mEventClassBitSize);

      ev->mEvent->pack(this, bstream);
      logprintf(LogConsumer::LogEventConnection, "EventConnection %s: WroteEvent %s - %d bits", getNetAddressString(), ev->mEvent->getDebugName(), bstream->getBitPosition() - start);

      if(mConnectionParameters.mDebugObjectSizes)
         bstream->writeIntAt(bstream->getBitPosition(), BitStreamPosBitSize, start);

      // check for packet overrun, and rewind this update if there
      // was one:
      if(!bstream->isValid() || bstream->getBitPosition() >= mWriteMaxBitSize)
      {
         mStringTable->packetRewind(&getCurrentWritePacketNotify()->stringList, strEntry);  // we never sent those stuff (TableStringEntry), so let it drop
         TNLAssert(have_something_to_send || bstream->getBitPosition() < mWriteMaxBitSize, "Packet too big to send");
         if(have_something_to_send)
         {
            bstream->setBitPosition(start - 1);
            bstream->clearError();
            break;
         }
         else //if(bstream->getBitPosition() < MaxPacketDataSize*8 - MinimumPaddingBits)
         {
            TNLAssertV(false, ("%s Packet too big to send, one or more events may be unable to send", ev->mEvent->getDebugName()));
            // dequeue the event:
            mUnorderedSendEventQueueHead = ev->mNextEvent;
            ev->mNextEvent = NULL;
            ev->mEvent->notifyDelivered(this, false);
            mEventNoteChunker.free(ev);
            bstream->setBitPosition(start - 1);
            bstream->clearError();
            break;
         }
      }
      have_something_to_send = true;

      // dequeue the event and add this event onto the packet queue
      mUnorderedSendEventQueueHead = ev->mNextEvent;
      ev->mNextEvent = NULL;

      if(!packQueueHead)
         packQueueHead = ev;
      else
         packQueueTail->mNextEvent = ev;
      packQueueTail = ev;
   }
   
   bstream->writeFlag(false);   
   S32 prevSeq = -2;
   
   while(mSendEventQueueHead)
   {
      if(bstream->isFull())
         break;
      
      // if the event window is full, stop processing
      if(mSendEventQueueHead->mSeqCount > mLastAckedEventSeq + 126)
         break;

      // get the first event
      EventNote *ev = mSendEventQueueHead;
      S32 eventStart = bstream->getBitPosition();
      ConnectionStringTable::PacketEntry *strEntry = getCurrentWritePacketNotify()->stringList.stringTail;

      bstream->writeFlag(true);

      if(!bstream->writeFlag(ev->mSeqCount == prevSeq + 1))
         bstream->writeInt(ev->mSeqCount, 7);
      prevSeq = ev->mSeqCount;

      if(mConnectionParameters.mDebugObjectSizes)
         bstream->advanceBitPosition(BitStreamPosBitSize);

      S32 start = bstream->getBitPosition();

      S32 classId = ev->mEvent->getClassId(getNetClassGroup());
      bstream->writeInt(classId, mEventClassBitSize);
      ev->mEvent->pack(this, bstream);

      ev->mEvent->getClassRep()->addInitialUpdate(bstream->getBitPosition() - start);
      logprintf(LogConsumer::LogEventConnection, "EventConnection %s: WroteEvent %s - %d bits", getNetAddressString(), ev->mEvent->getDebugName(), bstream->getBitPosition() - start);

      if(mConnectionParameters.mDebugObjectSizes)
         bstream->writeIntAt(bstream->getBitPosition(), BitStreamPosBitSize, start - BitStreamPosBitSize);

      // check for packet overrun, and rewind this update if there
      // was one:
      if(!bstream->isValid() || bstream->getBitPosition() >= mWriteMaxBitSize)
      {
         mStringTable->packetRewind(&getCurrentWritePacketNotify()->stringList, strEntry);  // we never sent those stuff (TableStringEntry), so let it drop
         if(have_something_to_send)
         {
            bstream->setBitPosition(eventStart);
            bstream->clearError();
            break;
         }
         else
         {
            TNLAssertV(false, ("%s Packet too big to send, one or more events may be unable to send", ev->mEvent->getDebugName()));
            for(EventNote *walk = ev->mNextEvent; walk; walk = walk->mNextEvent)
               walk->mSeqCount--;    // removing a GuaranteedOrdered needs to re-order mSeqCount
            mNextSendEventSeq--;

            // dequeue the event:
            mSendEventQueueHead = ev->mNextEvent;
            ev->mNextEvent = NULL;
            ev->mEvent->notifyDelivered(this, false);
            mEventNoteChunker.free(ev);
            bstream->setBitPosition(eventStart);
            bstream->clearError();
            break;
         }
      }
      have_something_to_send = true;

      // dequeue the event:
      mSendEventQueueHead = ev->mNextEvent;      
      ev->mNextEvent = NULL;
      if(!packQueueHead)
         packQueueHead = ev;
      else
         packQueueTail->mNextEvent = ev;
      packQueueTail = ev;
   }
   for(EventNote *ev = packQueueHead; ev; ev = ev->mNextEvent)
      ev->mEvent->notifySent(this);
      
   notify->eventList = packQueueHead;
   bstream->writeFlag(0);
}
Exemplo n.º 8
0
void EventConnection::writeConnectRequest(BitStream *stream)
{
   Parent::writeConnectRequest(stream);
   stream->write(NetClassRep::getNetClassCount(getNetClassGroup(), NetClassTypeEvent));   // Essentially a count of RPCs (c2s, s2c, etc.)
}