Packet* IPReassembly::getCurrentPacket(const PacketKey& key) { // create a hash out of the packet key uint32_t hash = key.getHashValue(); // look for this hash value in the map std::map<uint32_t, IPFragmentData*>::iterator iter = m_FragmentMap.find(hash); // hash was found if (iter != m_FragmentMap.end()) { IPFragmentData* fragData = iter->second; // some data already exists if (fragData != NULL && fragData->data != NULL) { // create a copy of the RawPacket object RawPacket* partialRawPacket = new RawPacket(*(fragData->data)); // fix IP length field if (fragData->packetKey->getProtocolType() == IPv4) { Packet tempPacket(partialRawPacket, IPv4); tempPacket.getLayerOfType<IPv4Layer>()->getIPv4Header()->totalLength = htons(fragData->currentOffset + tempPacket.getLayerOfType<IPv4Layer>()->getHeaderLen()); } else { Packet tempPacket(partialRawPacket, IPv6); tempPacket.getLayerOfType<IPv6Layer>()->getIPv6Header()->payloadLength = fragData->currentOffset; } // create a packet object wrapping the RawPacket we've just created Packet* partialDataPacket = new Packet(partialRawPacket, true); // prepare the packet and return it if (key.getProtocolType() == IPv4) { IPv4Layer* ipLayer = partialDataPacket->getLayerOfType<IPv4Layer>(); ipLayer->getIPv4Header()->fragmentOffset = 0; ipLayer->computeCalculateFields(); } else // key.getProtocolType() == IPv6 { IPv6Layer* ipLayer = partialDataPacket->getLayerOfType<IPv6Layer>(); ipLayer->removeAllExtensions(); ipLayer->computeCalculateFields(); } return partialDataPacket; } } return NULL; }
void VideoChannel::onReceive(const UInt8* pBuf, UInt32 iLen,unsigned int iSeq) { if (m_bUserCancel) { ErrTrace("VideoChannel::onReceive 已经取消操作....正在销毁...\n"); return; } Packet tempPacket(-1); tempPacket.setContentPtr(const_cast<UInt8*>(pBuf), iLen); UInt16 sPacketType = ntohs(*(UInt16*)(&pBuf[2])); switch (sPacketType) { case VIDEO_PACKET_TYPE: processVideoPacket(&tempPacket); break; case VIDEO_PIECE_PACKET_TYPE: processVideoPiecePacket(&tempPacket); break; default: Assert(0); break; } tempPacket.setContentPtr(NULL, 0); }
bool CBufferOutputVideoEngine::ParsePack(const UInt8* pBuf, UInt32 iLen,UInt32& iFrameSeq,UInt32& iPieceCount) { //BufferTrace("CBufferOutputVideoEngine::ParsePack() begin %d\n",GetTickCount()); Packet tempPacket(-1); tempPacket.setContentPtr(const_cast<UInt8*>(pBuf), iLen); bool bSucc = false;iPieceCount = 1; UInt16 sPacketType = ntohs(*(UInt16*)(&pBuf[2])); switch (sPacketType) { case VIDEO_PACKET_TYPE: ParseAllPack(&tempPacket,iFrameSeq,bSucc); break; case VIDEO_PIECE_PACKET_TYPE: ParsePiecePack(&tempPacket,iFrameSeq,iPieceCount,bSucc); break; default: Assert(0); break; } tempPacket.setContentPtr(NULL, 0); return bSucc; }
Packet* IPReassembly::processPacket(Packet* fragment, ReassemblyStatus& status, ProtocolType parseUntil, OsiModelLayer parseUntilLayer) { status = NON_IP_PACKET; // packet is not an IP packet if (!fragment->isPacketOfType(IPv4) && !fragment->isPacketOfType(IPv6)) { LOG_DEBUG("Got a non-IP packet, returning packet to user"); status = NON_IP_PACKET; return fragment; } // get IPv4 layer //IPv4Layer* ipLayer = fragment->getLayerOfType<IPv4Layer>(); // create fragment wrapper IPv4FragmentWrapper ipv4Wrapper(fragment); IPv6FragmentWrapper ipv6Wrapper(fragment); IPFragmentWrapper* fragWrapper = NULL; if (fragment->isPacketOfType(IPv4)) fragWrapper = &ipv4Wrapper; else // fragment->isPacketOfType(IPv6) fragWrapper = &ipv6Wrapper; // packet is not a fragment if (!(fragWrapper->isFragment())) { LOG_DEBUG("Got a non fragment packet with FragID=0x%X, returning packet to user", fragWrapper->getFragmentId()); status = NON_FRAGMENT; return fragment; } // create a hash from source IP, destination IP and IP/fragment ID uint32_t hash = fragWrapper->hashPacket(); IPFragmentData* fragData = NULL; // check whether this packet already exists in the map std::map<uint32_t, IPFragmentData*>::iterator iter = m_FragmentMap.find(hash); // this is the first fragment seen for this packet if (iter == m_FragmentMap.end()) { LOG_DEBUG("Got new packet with FragID=0x%X, allocating place in map", fragWrapper->getFragmentId()); // create the IPFragmentData object fragData = new IPFragmentData(fragWrapper->createPacketKey(), fragWrapper->getFragmentId()); // add the new fragment to the map addNewFragment(hash, fragData); } else // packet was seen before { // get the IPFragmentData object fragData = iter->second; // mark this packet as used uint32_t* removedElement = m_PacketLRU->put(hash); if (removedElement != NULL) delete removedElement; } bool gotLastFragment = false; // if current fragment is the first fragment of this packet if (fragWrapper->isFirstFragment()) { if (fragData->data == NULL) // first fragment { LOG_DEBUG("[FragID=0x%X] Got first fragment, allocating RawPacket", fragWrapper->getFragmentId()); // create the reassembled packet and copy the fragment data to it fragData->data = new RawPacket(*(fragment->getRawPacket())); fragData->currentOffset = fragWrapper->getIPLayerPayloadSize(); status = FIRST_FRAGMENT; // check if the next fragments already arrived out-of-order and waiting in the out-of-order list gotLastFragment = matchOutOfOrderFragments(fragData); } else // duplicated first fragment { LOG_DEBUG("[FragID=0x%X] Got duplicated first fragment", fragWrapper->getFragmentId()); status = FRAGMENT; return NULL; } } else // not first fragment { LOG_DEBUG("[FragID=0x%X] Got fragment", fragWrapper->getFragmentId()); uint16_t fragOffset = fragWrapper->getFragmentOffset(); // check if the current fragment offset matches the expected fragment offset if (fragData->currentOffset == fragOffset) { // malformed fragment which is not the first fragment but its offset is 0 if (fragData->data == NULL) { LOG_DEBUG("[FragID=0x%X] Fragment is malformed", fragWrapper->getFragmentId()); status = MALFORMED_FRAGMENT; return NULL; } LOG_DEBUG("[FragID=0x%X] Found next matching fragment with offset %d, adding fragment data to reassembled packet", fragWrapper->getFragmentId(), (int)fragOffset); // copy fragment data to reassembled packet fragData->data->reallocateData(fragData->data->getRawDataLen() + fragWrapper->getIPLayerPayloadSize()); fragData->data->appendData(fragWrapper->getIPLayerPayload(), fragWrapper->getIPLayerPayloadSize()); // update expected offset fragData->currentOffset += fragWrapper->getIPLayerPayloadSize(); // if this is the last fragment - mark it if (fragWrapper->isLastFragment()) gotLastFragment = true; else // if not the last fragment - check if the next fragments are waiting in the out-of-order list gotLastFragment = matchOutOfOrderFragments(fragData); } // if current fragment offset is larger than expected - this means this fragment is out-of-order else if (fragOffset > fragData->currentOffset) { LOG_DEBUG("[FragID=0x%X] Got out-of-ordered fragment with offset %d (expected: %d). Adding it to out-of-order list", fragWrapper->getFragmentId(), (int)fragOffset, (int)fragData->currentOffset); // create a new IPFragment and copy the fragment data and params to it IPFragment* newFrag = new IPFragment(); newFrag->fragmentOffset = fragWrapper->getFragmentOffset(); newFrag->fragmentData = new uint8_t[fragWrapper->getIPLayerPayloadSize()]; newFrag->fragmentDataLen = fragWrapper->getIPLayerPayloadSize(); memcpy(newFrag->fragmentData, fragWrapper->getIPLayerPayload(), newFrag->fragmentDataLen); newFrag->lastFragment = fragWrapper->isLastFragment(); // store the IPFragment in the out-of-order fragment list fragData->outOfOrderFragments.pushBack(newFrag); status = OUT_OF_ORDER_FRAGMENT; return NULL; } else { LOG_DEBUG("[FragID=0x%X] Got a fragment with an offset that was already seen: %d (current offset is: %d), probably duplicated fragment", fragWrapper->getFragmentId(), (int)fragOffset, (int)fragData->currentOffset); } } // if seen the last fragment if (gotLastFragment) { LOG_DEBUG("[FragID=0x%X] Reassembly process completed, allocating a packet and returning it", fragWrapper->getFragmentId()); fragData->deleteData = false; // fix IP length field if (fragData->packetKey->getProtocolType() == IPv4) { Packet tempPacket(fragData->data, IPv4); tempPacket.getLayerOfType<IPv4Layer>()->getIPv4Header()->totalLength = htons(fragData->currentOffset + tempPacket.getLayerOfType<IPv4Layer>()->getHeaderLen()); } else { Packet tempPacket(fragData->data, IPv6); tempPacket.getLayerOfType<IPv6Layer>()->getIPv6Header()->payloadLength = fragData->currentOffset; } // create a new Packet object with the reassembled data as its RawPacket Packet* reassembledPacket = new Packet(fragData->data, true, parseUntil, parseUntilLayer); if (fragData->packetKey->getProtocolType() == IPv4) { // set the fragment offset to 0 IPv4Layer* ipLayer = reassembledPacket->getLayerOfType<IPv4Layer>(); ipLayer->getIPv4Header()->fragmentOffset = 0; // re-calculate all IPv4 fields ipLayer->computeCalculateFields(); } else { // remove fragment extension IPv6Layer* ipLayer = reassembledPacket->getLayerOfType<IPv6Layer>(); ipLayer->removeAllExtensions(); // re-calculate all IPv4 fields ipLayer->computeCalculateFields(); } LOG_DEBUG("[FragID=0x%X] Deleting fragment data from map", fragWrapper->getFragmentId()); // delete the IPFragmentData object and remove it from the map delete fragData; m_FragmentMap.erase(iter); m_PacketLRU->eraseElement(hash); status = REASSEMBLED; return reassembledPacket; } // if got to here it means this fragment is either the first fragment or a fragment in the middle. Set the appropriate status and return if (status != FIRST_FRAGMENT) status = FRAGMENT; return NULL; }