public void Decode(RtpPacket packet) { Debug.WriteLine("DECODING: Original length: " + packet.Payload.Length); packet.Payload = SymmetricEncryption(packet,decrypter); Debug.WriteLine("New length: " + packet.Payload.Length); }
private BufferChunk SymmetricEncryption(RtpPacket packet,ICryptoTransform crypto) { BufferChunk payload = packet.Payload; byte[] data = crypto.TransformFinalBlock(payload.Buffer, payload.Index, payload.Length); return new BufferChunk(data); }
private static void XorPacket(RtpPacket packet) { BufferChunk chunk = packet.Payload; byte[] data = chunk.Buffer; for (int i = chunk.Index; i <= chunk.Length; i++) { data[i] ^= 0x0b; } }
public void Encode(RtpPacket packet) { Debug.WriteLine("ENCODING: Original length: " + packet.Payload.Length); Debug.Assert(packet.ReservedPaddingBytes == RtpPacket.MAX_CRYPTO_BLOCK_SIZE); BufferChunk chunk = SymmetricEncryption(packet, encrypter); // set the payload; this method indicates that we are allowed to use // the portion of the payload that is reserved for padding packet.SetPaddedPayload(chunk); Debug.WriteLine("New length: " + packet.Payload.Length); }
/// <summary> /// DistributePackets is responsible for receiving all incoming packets on the Rtp Listener, /// casting them into RtpPackets, creating new RtpStreams if one doesn't exist for the RtpPacket's SSRC, /// then calling RtpStream.newPacket(rtpPacket) to place the RtpPacket into the RtpStream's Queue for processing. /// </summary> private void DistributePackets() { while (newPacket.WaitOne()) { while(receivedPackets.Count > 0) { object[] ao = (object[])receivedPackets.Dequeue(); BufferChunk bc = (BufferChunk)ao[0]; IPEndPoint ep = (IPEndPoint)ao[1]; try { //Turn the raw UDP packet data into an Rtp packet RtpPacketBase packet = new RtpPacketBase(bc); // For now, we support 2 types of packets - RtpPacket and RtpPacketFec. If // the number of packet types grows, we may need to push the casting onto // the streams, since they know what type of packets they expect. For now // we will handle the casting here. JVE 6/17/2004 if(packet.PayloadType == PayloadType.FEC) { packet = new RtpPacketFec(packet); } else { packet = new RtpPacket(packet); } #region Fault Injection #if FaultInjection if(rtpSession.DropPacketsPercent > 0 ) { if (rtpSession.Rnd.Next(1,100) <= rtpSession.DropPacketsPercent) { if(packet.PayloadType == PayloadType.FEC) { RtpPacketFec fecPacket = (RtpPacketFec)packet; string msg = string.Format( "Dropping fec packet: {0}, FecIndex: {1}, DataRangeMin: {2}", fecPacket.Sequence, fecPacket.FecIndex, fecPacket.DataRangeMin); Trace.WriteLine(msg); pcDroppedFecPackets++; pcDroppedFecBytes += packet.PayloadSize; } else { RtpPacket dataPacket = (RtpPacket)packet; string msg = string.Format( "Dropping data packet: {0}, FecIndex: {1}, FrameIndex: {2}, TS: {3}", dataPacket.Sequence, dataPacket.FecIndex, dataPacket.FrameIndex, dataPacket.TimeStamp); Trace.WriteLine(msg); pcDroppedDataPackets++; pcDroppedDataBytes += packet.PayloadSize; } ReturnBuffer(bc); continue; } } #endif #endregion Fault Injection // Get the stream if it exists RtpStream stream = rtpSession.GetStream(packet.SSRC, ep.Address); if (stream != null) { stream.ProcessPacket(packet); } else { // Otherwise return the packet to the pool ReturnBuffer(bc); unchecked{pcStreamlessPackets++;} } } catch(ThreadAbortException){} catch (InvalidRtpPacketException e) { HandleInvalidPacket(bc, ep, e.ToString()); ReturnBuffer(bc); } catch(PoolExhaustedException e) { LogEvent(e.ToString(), EventLogEntryType.Error, (int)RtpEL.ID.UnboundedGrowth); return; // Exit the thread gracefully } catch(Exception e) { ReturnBuffer(bc); LogEvent(e.ToString(), EventLogEntryType.Error, (int)RtpEL.ID.Error); } } } }
internal override void SendPacket(RtpPacket rtpPacket) { // Set the FecIndex of the packet rtpPacket.FecIndex = dataFecIndex; // Store the packet in 2 formats dataPx[dataFecIndex] = rtpPacket; data[dataFecIndex] = (BufferChunk)rtpPacket; dataFecIndex++; // The packet is still valid after the Send base.SendPacket(rtpPacket); // See if we have reached the time to send FEC packets if(dataFecIndex == cDataPx) { dataFecIndex = 0; dataRangeMin = dataPx[0].Sequence; fecEncoder.Encode(data, checksum); SendPacketsFec(); } }
internal virtual void SendPacket(RtpPacket rtpPacket) { rtpPacket.SSRC = ssrc; rtpPacket.Sequence = seq++; rtpNetworkSender.Send((BufferChunk)rtpPacket); }
/// <summary> /// newPacket is how RtpListener sends an incoming RtpPacket who's SSRC matches this /// RtpStream into the RtpStream's queue for processing /// /// This method assumes there is only one thread calling newPacket /// </summary> internal virtual void ProcessPacket(RtpPacket packet) { int frame_Index = 0; int packets_Size = 0; #region Mark this stream and its participant as not stale stale = 0; // TODO - trade SdesData for Participant JVE // TODO - mark participant or we will destory and recreate streams JVE // if (participant != null) // { // participant.stale = 0; // } #endregion // Mark raw packet received packetsLost += LostPackets(ref maxSeq, packet.Sequence); packetsReceived++; bytesReceived += packet.PayloadSize; #region Reject Late Packets uint packetTS = packet.TimeStamp; uint deltaTS = 0; if (packetsReceived != 1) // Skip this test if we're in a startup state { deltaTS = unchecked(packetTS - currentFrameTS); if (deltaTS > HALF_UINT_MAX) { packetsReceivedLate++; returnBufferHandler(packet.ReleaseBuffer()); return; } } #endregion // A packet from a future frame has been received, so send out the incomplete current frame // Note we cannot check for deltaTS == 1 because we may miss more than 1 frame if (deltaTS > 0) { if(frame != null) { frame.Dispose(); frame = null; } RtpRetransmit.FrameIncomplete(this, (int)deltaTS); } // We're receiving the first packet for a new frame if (frame == null) { frame = new RtpFrame(128, packetTS, returnBufferHandler); currentFrameTS = packetTS; } try { // Store the packet // payload type is jpeg frame_Index = packet.JpgOffset/packet.MaxPayloadSize; frame.ApproximatePacketsInFrame((uint)frame_Index + 1); frame[frame_Index] = packet; } catch(DuplicatePacketException) { // Note: We have already updated the performance counters for these bytes / this packet // and we are rejecting it now. So pcs could be higher than expected. eventLog.WriteEntry("Duplicate packet received in RtpStream - " + packet.ToString(), EventLogEntryType.Error, (int)RtpEL.ID.DuplicatePacketReceived); return; } // We've received the correct number of data packets, so we can now re-create the frame //if (frame.Complete) if (packet.Marker) { packets_Size = frame_Index + 1; frame.PacketsInFrame = (uint)packets_Size; } if (frame.Complete) { // Raise the event OnFrameReceivedEvent(frame.Data); // Clean up frame - like returning packets to RtpListener frame.Dispose(); frame = null; // CXP RtpSenders increment by 1, to do otherwise is a signal from the Sender // which means the stream needs to know what the signal means currentFrameTS++; } }
private void Decode() { pcDecodePath++; try { fecDecoder.Decode(data, fecPxExp, recovery); dataPxAct = dataPxExp; // Trigger ForwardDataPacketsToBase // Cast BufferChunks back into RtpPackets int recoveryIndex = 0; for(int i = 0; i < dataPxExp; i++) { if(dataPx[i] == null) { try { dataPx[i] = new RtpPacket(recovery[recoveryIndex]); } catch(InvalidRtpPacketException e) { eventLog.WriteEntry(e.ToString(), EventLogEntryType.Error, (int)RtpEL.ID.InvalidPacket); ReturnDataBuffer(recovery[recoveryIndex]); } finally { recovery[recoveryIndex] = null; recoveryIndex++; } } } } catch(ThreadAbortException){} // Because we catch a generic exception next catch(Exception e) { eventLog.WriteEntry(e.ToString(), EventLogEntryType.Error, (int)RtpEL.ID.Error); // Return recovery packets for(int recoveryIndex = 0; recoveryIndex < fecPxAct; recoveryIndex++) { ReturnDataBuffer(recovery[recoveryIndex]); recovery[recoveryIndex] = null; } } }
// Check to see if packet is inside the recovery range protected bool InRangeData(RtpPacket packet) { bool inRange = true; if(rangeInitialized) { ushort minDiff = unchecked((ushort)(packet.Sequence - minSeq)); ushort maxDiff = unchecked((ushort)(maxSeq - packet.Sequence)); if(minDiff > HALF_USHORT_MAX) // Wrong data range - too late { inRange = false; pcDataPacketsLate++; base.ProcessPacket(packet); } else if(maxDiff > HALF_USHORT_MAX) // Wrong data range - too new { Undecodable(); } } return inRange; }
private void ProcessPacketData(RtpPacket packet) { pcDataPacketsLost += LostPackets(ref maxDataSeq, packet.Sequence); pcDataPackets++; pcDataBytes += packet.PayloadSize; if(InRangeData(packet)) { // New sequence of packets if(dataPxAct + fecPxAct == 0) { ResetDecodingState(packet); } int dataFecIndex = packet.FecIndex; // Duplicate packet check for flaky networks if(dataPx[dataFecIndex] != null) { eventLog.WriteEntry("Duplicate packet received!", EventLogEntryType.Warning, (int)RtpEL.ID.DuplicatePacketReceived); return; } dataPxAct++; dataPx[dataFecIndex] = packet; data[dataFecIndex] = (BufferChunk)packet; } }
private RtpPacket GetPacket(int index) { RtpPacket rtpPacket = pool[index]; if(rtpPacket == null) { rtpPacket = new RtpPacket((int)packetSize); rtpPacket.PayloadType = payloadType; rtpPacket.FrameIndex = (ushort)(index); rtpPacket.SSRC = streamSsrc; pool[index] = rtpPacket; packetsInFramePool = (uint)index + 1; } return rtpPacket; }
private void GrowPool(uint packets) { // Use a local so that we don't change the member variable until everything is committed uint localPoolLength = poolLength; // Startup condition if(localPoolLength == 0) { localPoolLength = poolInitialSize; } // Determine amount of growth necessary while(packets > localPoolLength) { poolGrows++; if(poolGrows > poolGrowsMax) { throw new FrameTooLargeException(); } localPoolLength *= poolGrowthFactor; } // Copy old packets RtpPacket[] clone = new RtpPacket[localPoolLength]; for(int i = 0; i < packetsInFramePool; i++) { clone[i] = pool[i]; } pool = clone; poolLength = localPoolLength; }
public void Decode (RtpPacket packet) { XorPacket(packet); }
private RtpPacket GetPacket(int index) { RtpPacket rtpPacket = pool[index]; if(rtpPacket == null) { rtpPacket = new RtpPacket((int)packetSize); rtpPacket.PayloadType = payloadType; rtpPacket.SSRC = streamSsrc; pool[index] = rtpPacket; packetsInFramePool = (uint)index + 1; } rtpPacket.Marker = false; // allway reset return rtpPacket; }
private void Packetize(IntPtr[] ptrs, int[] lengths, bool prependLengths) { // This assumes length member variable has been set already ApproximatePacketsInFrame(); // Initialize to enter loop packetsInFrame = 0; // We'll find out real number of packets RtpPacket packet = null; int pktAvailable = 0; int ptrIndex = 0; int ptrAvailable = 0; IntPtr ptr = IntPtr.Zero; bool writePtrLength = false; int ptrsLength = ptrs.Length; while (true) { // If there is no data left in this ptr, get a new one if (ptrAvailable == 0) { if (ptrIndex + 1 > ptrs.Length) { break; // while(true) } ptrAvailable = lengths[ptrIndex]; ptr = ptrs[ptrIndex]; ptrIndex++; // Write the length of the ptr to the packet if (prependLengths) { writePtrLength = true; if (pktAvailable < 4) { pktAvailable = 0; // Get a new packet } } } // Note: // pktAvailable == 0 is handled after ptrAvailable == 0 to bypass the case where // the final ptr fit into the packet perfectly. We want to exit the loop at that // point before grabbing another packet which won't have anything put in it. The // case for prepending the length of ptr still works if the previous packet didn't // have room for the length. // If there is no room in the current packet, get a new one if (pktAvailable == 0) { packet = GetNextPacket(); // In the event that we re-add support for custom headers, add that data here // before making the call to packet.MaxPayloadSize - 9/23/2004 JVE // Find out how much room is left in the packet packet.Reset(); // Mimic packet.Payload = ... pktAvailable = packet.MaxPayloadSize - packet.PayloadSize; } // Write length of ptr to packet if (writePtrLength) { // Add 4 bytes for length packet.AppendPayload(ptrAvailable); pktAvailable -= 4; writePtrLength = false; // Place holder ptr if (ptrAvailable == 0) { continue; // Nothing to copy } } // Copy as much as the packet can hold if (ptrAvailable >= pktAvailable) { packet.AppendPayload(ptr, pktAvailable); // buffer.CopyFrom(ptr, pktAvailable); ptr = (IntPtr)(ptr.ToInt32() + pktAvailable); // Advance pointer ptrAvailable -= pktAvailable; pktAvailable = 0; } else // Copy as much as the ptr can provide { packet.AppendPayload(ptr, ptrAvailable); pktAvailable -= ptrAvailable; ptrAvailable = 0; } } }