bool HuffmanStringProcessor::writeHuffBuffer(BitStream* pStream, const char* out_pBuffer, U32 maxLen) { if (out_pBuffer == NULL) { pStream->writeFlag(false); pStream->writeInt(0, 8); return true; } if (mTablesBuilt == false) buildTables(); size_t llen = out_pBuffer ? strlen(out_pBuffer) : 0; TNLAssertV(llen <= 255, ("String \"%s\" TOO long for writeString", out_pBuffer)); U32 len = static_cast<U32>(llen); if (len > maxLen) len = maxLen; U32 numBits = 0; U32 i; for (i = 0; i < len; i++) numBits += mHuffLeaves[(unsigned char)out_pBuffer[i]].numBits; if (numBits >= (len * 8)) { pStream->writeFlag(false); pStream->writeInt(len, 8); pStream->write(len, out_pBuffer); } else { pStream->writeFlag(true); pStream->writeInt(len, 8); for (i = 0; i < len; i++) { HuffLeaf& rLeaf = mHuffLeaves[((unsigned char)out_pBuffer[i])]; pStream->writeBits(rLeaf.numBits, &rLeaf.code); } } return true; }
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; }
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); }