void RtcpListener.IRtpSession.ProcessCompoundPacket(CompoundPacket cp, IPAddress ip) { foreach(RtcpPacket packet in cp) { ProcessPacket(packet, ip); } }
public void ListenThread() { CompoundPacket compoundPacket = new CompoundPacket(); EndPoint endPoint = null; while(!disposed) { try { // Reset the packet for the next round of data compoundPacket.Reset(); // Wait for data off the wire rtcpNetworkListener.ReceiveFrom(compoundPacket.Buffer, out endPoint); #region Fault Injection #if FaultInjection // Drop packets if (rtpSession.DropPacketsPercent > 0) { if (rtpSession.Rnd.Next(1, 100) <= rtpSession.DropPacketsPercent) { continue; } } #endif #endregion Fault Injection // Parse the data and rigorously validate it compoundPacket.ParseBuffer(); // Pass it on to the rtpSession to analyze and distribute data rtpSession.ProcessCompoundPacket(compoundPacket, ((IPEndPoint)endPoint).Address); } catch (System.Net.Sockets.SocketException e) { // No data received before timeout if (e.ErrorCode == 10060) { rtpSession.RaiseNetworkTimeoutEvent("Rtcp"); } // We get 10054 socket exceptions in some situations during unicast connections. Ignore them for now. // Pri2: Find a better solution for the unicast socket exceptions else if(e.ErrorCode == 10054 && !Utility.IsMulticast(rtcpNetworkListener.ExternalInterface) ) { continue; } else { Object[] args = new Object[]{this, new RtpEvents.HiddenSocketExceptionEventArgs((RtpSession)rtpSession, e)}; EventThrower.QueueUserWorkItem( new RtpEvents.RaiseEvent(RtpEvents.RaiseHiddenSocketExceptionEvent), args ); LogEvent(e.ToString(), EventLogEntryType.Error, (int)RtpEL.ID.Error); } } catch(RtcpHeader.RtcpHeaderException e) { // TODO - this is a pretty serious error - what should we do - exit thread, squelch? JVE LogEvent(e.ToString(), EventLogEntryType.Error, (int)RtpEL.ID.RtcpHeaderException); } catch(CompoundPacket.CompoundPacketException e) { // TODO - this is a pretty serious error - what should we do - exit thread, squelch? JVE LogEvent(e.ToString(), EventLogEntryType.Error, (int)RtpEL.ID.CompoundPacketException); } catch (ThreadAbortException) {} catch (Exception e) { LogEvent(e.ToString(), EventLogEntryType.Error, (int)RtpEL.ID.Error); } } }
private void AddAppPackets(CompoundPacket cp) { while(!cpComplete && appPackets.Count > 0) { AppPacket app = (AppPacket)appPackets.Peek(); if(space >= app.Size) { int start = cp.Buffer.Length; cp.AddPacket(app); int end = cp.Buffer.Length; space -= app.Size; appPackets.Dequeue(); Debug.Assert( (end-start) == app.Size ); // math check } else { cpComplete = true; } } }
private void AddByeReports(CompoundPacket cp) { while(!cpComplete && byeReports.Count > 0) { bool byepComplete = false; bool addedReport = false; ByePacket byep = new ByePacket(); // Remove the size of the header + ssrc if(space >= byep.Size) { space -= byep.Size; // Add the rest while(space >= Rtp.SSRC_SIZE && byeReports.Count > 0) { try { uint ssrc = (uint)byeReports.Peek(); byep.AddSSRC(ssrc); byeReports.Dequeue(); space -= Rtp.SSRC_SIZE; addedReport = true; } catch(RtcpPacket.InsufficientItemSpaceException) { // No more room in bp for reports byepComplete = true; break; } } } // We broke out of the loop for one of 3 reasons // 1. There were no more byeReports // 2. There was no more room in bp // 3. There was no more room in cp (cpComplete) // If we added a report to bp, add bp to cp if(addedReport) { int start = cp.Buffer.Length; cp.AddPacket(byep); int end = cp.Buffer.Length; Debug.Assert( (end-start) == byep.Size ); // math check } // Figure out if we exited because cp is complete if(byeReports.Count > 0 && byepComplete == false) { cpComplete = true; } } }
private void AddSdesReports(CompoundPacket cp) { while(!cpComplete && sdesReports.Count > 0) { bool sdespComplete = false; bool addedReport = false; SdesPacket sdesp = new SdesPacket(); if(space >= sdesp.Size) { space -= sdesp.Size; while(sdesReports.Count > 0) { SdesReport report = (SdesReport)sdesReports.Peek(); if( space >= report.Size ) { try { sdesp.AddReport(report); sdesReports.Pop(); space -= report.Size; addedReport = true; } catch(RtcpPacket.InsufficientItemSpaceException) { // No more room in rrp for reports sdespComplete = true; break; } } else { break; // while loop } } } // We broke out of the loop for one of 3 reasons // 1. There were no more sdesReports // 2. There was no more room in sdesp // 3. There was no more room in cp (cpComplete) // If we added a report to sdesp, add sdesp to cp if(addedReport) { int start = cp.Buffer.Length; cp.AddPacket(sdesp); int end = cp.Buffer.Length; Debug.Assert( (end-start) == sdesp.Size ); // math check } // Figure out if we exited because cp is complete if(sdesReports.Count > 0 && sdespComplete == false) { cpComplete = true; } } }
private void AddReceiverReports(CompoundPacket cp) { while(!cpComplete && receiverReports.Count > 0) { bool rrpComplete = false; bool addedReport = false; RrPacket rrp = new RrPacket(); rrp.SSRC = participant.SSRC; // Remove the size of the header + ssrc if(space >= rrp.Size) { space -= rrp.Size; // Add the rest while(space >= ReceiverReport.SIZE && receiverReports.Count > 0) { try { ReceiverReport rr = (ReceiverReport)receiverReports.Peek(); rrp.AddReceiverReport(rr); receiverReports.Dequeue(); space -= ReceiverReport.SIZE; addedReport = true; } catch(RtcpPacket.InsufficientItemSpaceException) { // No more room in rrp for reports rrpComplete = true; break; } } } // We broke out of the loop for one of 3 reasons // 1. There were no more ReceiverReports // 2. There was no more room in rrp // 3. There was no more room in cp (cpComplete) // If we added a report to rrp, add rrp to cp if(addedReport) { int start = cp.Buffer.Length; cp.AddPacket(rrp); int end = cp.Buffer.Length; Debug.Assert( (end - start) == rrp.Size ); // math check } // Figure out if we exited because cp is complete if(receiverReports.Count > 0 && rrpComplete == false) { cpComplete = true; } } }
private void AddSenderReportPackets(CompoundPacket cp) { while(!cpComplete && senderReportPackets.Count > 0) { SrPacket sr = (SrPacket)senderReportPackets.Peek(); if(space >= sr.Size) { int start = cp.Buffer.Length; cp.AddPacket(sr); int end = cp.Buffer.Length; space -= sr.Size; senderReportPackets.Dequeue(); Debug.Assert( (end - start) == sr.Size ); // math check } else { cpComplete = true; } } }
private void AddEmptyReceiverReportPacket(CompoundPacket cp) { RrPacket rr = new RrPacket(); rr.SSRC = participant.SSRC; int start = cp.Buffer.Length; cp.AddPacket(rr); int end = cp.Buffer.Length; space -= rr.Size; Debug.Assert( (end - start) == rr.Size ); // math check }
internal void BuildCompoundPackets() { // Add the local participant / session info sdesReports.Push(new SdesReport(participant.SSRC, participant)); while(DataRemains()) { CompoundPacket cp = new CompoundPacket(); space = cp.Size; cpComplete = false; // All compound packets must start with a SenderReportPacket or a // ReceiverReportPacket. If we don't have real ones, add an empty // ReceiverReportPacket. if(senderReportPackets.Count == 0 && receiverReports.Count == 0) { AddEmptyReceiverReportPacket(cp); } else { AddSenderReportPackets(cp); AddReceiverReports(cp); } AddSdesReports(cp); AddAppPackets(cp); AddByeReports(cp); compoundPackets.Enqueue(cp); } }