private static ICollection <IPEndPoint> getSortedReceivers(VenueState venueState)
        {
            List <IPEndPoint> list = new List <IPEndPoint>(venueState.ReceiverData.Keys);

            list.Sort(myComparer);
            return(list);
        }
        private static ICollection <uint> getSortedSenders(VenueState venueState)
        {
            List <uint> list = new List <uint>(venueState.SenderData.Keys);

            list.Sort();
            return(list);
        }
        //Logging enable/disable
        protected void CheckBox2_CheckedChanged(object sender, EventArgs e)
        {
            bool isChecked = CheckBox2.Checked;

            VenueState vs = CurrentVenueState();

            if (vs != null)
            {
                vs.UseLogging = isChecked;
            }
        }
        private DataTable BuildAdvancedSenderTable(VenueState venueState)
        {
            DataTable senderTable = CreateEmptySenderTable();

            lock (venueState.SenderData)
            {
                foreach (uint ssrc in getSortedSenders(venueState))
                {
                    SenderData senderData = venueState.SenderData[ssrc];

                    if (senderData == null)
                    {
                        continue;
                    }

                    DataRow row = senderTable.NewRow();

                    row["Sender"]  = ssrc;
                    row["IP Addr"] = senderData.Source.ToString();
                    row["CName"]   = senderData.CName;

                    row["Packets Sent"] = senderData.PacketsSent;
                    row["Bytes Sent"]   = senderData.BytesSent;

                    double kb = senderData.DataRate;
                    row["Data rate"]   = kb.ToString("N") + " Kb/sec";
                    row["Packet rate"] = senderData.PacketRate.ToString("N") + " pk/sec";

                    if (senderData.LastSendUpdate.Equals(DateTime.MinValue))
                    {
                        row["Last update*"] = "No sender data received.";
                    }
                    else
                    {
                        row["Last update*"] = senderData.LastSendUpdate.ToString();
                    }

                    senderTable.Rows.Add(row);
                } // for each host in a the venue...
            }     // unlock

            return(senderTable);
        }
        private void BuildAdvancedReceiverTables(VenueState venueState, out DataTable thptTable, out DataTable lossTable)
        {
            thptTable = new DataTable();
            lossTable = new DataTable();

            thptTable.Columns.Add("Receiver IP", Type.GetType("System.String"));
            thptTable.Columns.Add("CName", Type.GetType("System.String"));
            lossTable.Columns.Add("Receiver IP", Type.GetType("System.String"));
            lossTable.Columns.Add("CName", Type.GetType("System.String"));

            // keep track of the packet sending rate for each sender; this avoids having
            // to hold multiple locks at the same time...

            IDictionary <uint, double> sendingRateMap = new Dictionary <uint, double>();

            lock (venueState.SenderData)
            {
                // add a column for each sender... Keep the key set sorted so that elements don't
                // bounce around between rows

                foreach (uint ssrc in getSortedSenders(venueState))
                {
                    thptTable.Columns.Add(ssrc.ToString(), Type.GetType("System.String"));
                    lossTable.Columns.Add(ssrc.ToString(), Type.GetType("System.String"));

                    sendingRateMap[ssrc] = venueState.SenderData[ssrc].PacketRate;
                }
            }

            lock (venueState.ReceiverData)
            {
                // add a row for each receiver

                foreach (IPEndPoint endPoint in getSortedReceivers(venueState))
                {
                    ReceiverData receiverData = venueState.ReceiverData[endPoint];
                    if (receiverData == null)
                    {
                        continue; // shouldn't happen...
                    }
                    // process receiver summaries
                    ICollection <ReceiverSummary> summaries = receiverData.ReceiverSummaries;
                    if (summaries == null || summaries.Count == 0)
                    {
                        continue;
                    }

                    DataRow thptRow = thptTable.NewRow();
                    DataRow lossRow = lossTable.NewRow();

                    thptRow["Receiver IP"] = endPoint.ToString();
                    thptRow["CName"]       = receiverData.CName;

                    lossRow["Receiver IP"] = endPoint.ToString();
                    lossRow["CName"]       = receiverData.CName;


                    // initialize sender columns...
                    foreach (uint ssrc in getSortedSenders(venueState))
                    {
                        lossRow[ssrc.ToString()] = "no data";
                        thptRow[ssrc.ToString()] = "no data";
                    }

                    // process receiver summaries
                    //ICollection<ReceiverSummary> summaries = hostState.ReceiverSummaries;
                    foreach (ReceiverSummary summary in summaries)
                    {
                        uint reporteeSSRC = summary.SSRC;
                        if (thptTable.Columns.Contains(reporteeSSRC.ToString()))
                        {
                            double throughputDifferential = summary.PacketRate - sendingRateMap[reporteeSSRC];
                            thptRow[reporteeSSRC.ToString()] = String.Format("{0:N} pk/sec", throughputDifferential);

                            lossRow[reporteeSSRC.ToString()] = String.Format("{0:P}", summary.LossRate);
                        }
                    } // for each receiver summary...

                    thptTable.Rows.Add(thptRow);
                    lossTable.Rows.Add(lossRow);
                } // for each receiver in the venue
            }     // venue.receiverData lock
        }
        private void BuildTables()
        {
            Label1.Text = "Last updated: " + System.DateTime.Now;

            if (DropDownList1.SelectedIndex < 0)
            {
                HyperLink1.Text = "";
                return;
            }

            bool useAdvanedView = CheckBox1.Checked;

            VenueState venueState = CurrentVenueState();

            if (venueState == null)
            {
                HyperLink1.Text = "";
                return;
            }

            if (Global.LoggingEnabled)
            {
                if (venueState.LogFileName != null)
                {
                    HyperLink1.NavigateUrl = HttpRuntime.AppDomainAppVirtualPath + venueState.LogFileName;
                    HyperLink1.Text        = venueState.LogFileName;
                    HyperLink1.Visible     = true;
                    Label2.Visible         = true;
                }
                else
                {
                    HyperLink1.Visible = false;
                    Label2.Visible     = false;
                }
                CheckBox2.Checked = venueState.UseLogging;
            }
            else
            {
                CheckBox2.Visible  = false;
                HyperLink1.Visible = false;
                Label2.Visible     = false;
            }

            DataTable senderTable;
            DataTable receiverTable;
            DataTable lossTable;

            if (CheckBox1.Checked)
            {
                senderTable = BuildAdvancedSenderTable(venueState);
                BuildAdvancedReceiverTables(venueState, out receiverTable, out lossTable);
            }
            else
            {
                IDictionary <IPEndPoint, SenderData> senderSummaries;
                senderTable = BuildBasicSenderTable(venueState, out senderSummaries);
                BuildBasicReceiverTables(venueState, out receiverTable, out lossTable, senderSummaries);
            }


            //////////////////////////////////////////////
            //////////////////////////////////////
            // views and binding
            DataView view = new DataView(senderTable);

            view.AllowEdit   = false;
            view.AllowNew    = false;
            view.AllowDelete = false;

            GridView1.DataSource = view;

            DataView view2 = new DataView(receiverTable);

            view2.AllowEdit   = false;
            view2.AllowNew    = false;
            view2.AllowDelete = false;

            GridView2.DataSource = view2;

            DataView view3 = new DataView(lossTable);

            view3.AllowEdit      = false;
            view3.AllowNew       = false;
            view3.AllowDelete    = false;
            GridView3.DataSource = view3;

            this.DataBind();
        }
        /// <summary>
        /// Merge all streams from a given IP,Port pair.  Return the summarized sender data in a dictionary,
        /// which can be used to build the BasicReceiverTable
        /// </summary>
        /// <param name="venueState"></param>
        /// <returns></returns>
        private DataTable BuildBasicSenderTable(VenueState venueState,
                                                out IDictionary <IPEndPoint, SenderData> senderSummaries)
        {
            DataTable senderTable = new DataTable();

            senderTable.Columns.Add("IP Addr", Type.GetType("System.String"));
            senderTable.Columns.Add("CName", Type.GetType("System.String"));

            senderTable.Columns.Add("Packets Sent", Type.GetType("System.Int64"));
            senderTable.Columns.Add("Bytes Sent", Type.GetType("System.Int64"));
            senderTable.Columns.Add("Data Rate", Type.GetType("System.String"));
            senderTable.Columns.Add("Packet Rate", Type.GetType("System.String"));
            senderTable.Columns.Add("Last update*", Type.GetType("System.String"));

            senderSummaries = new Dictionary <IPEndPoint, SenderData>();

            lock (venueState.SenderData)
            {
                foreach (uint ssrc in getSortedSenders(venueState))
                {
                    SenderData senderData = venueState.SenderData[ssrc];
                    if (senderData == null)
                    {
                        continue;
                    }


                    IPEndPoint endPoint = senderData.Source;

                    if (endPoint == null)
                    {
                        continue;
                    }

                    if (senderSummaries.ContainsKey(endPoint))
                    {
                        // merge new data with old...
                        SenderData existingData = senderSummaries[endPoint];

                        SenderData mergedData = new SenderData(senderData, existingData);
                        senderSummaries[endPoint] = mergedData;
                    }
                    else
                    {
                        senderSummaries[endPoint] = senderData;
                    }
                }
            }

            foreach (IPEndPoint endPoint in senderSummaries.Keys)
            {
                DataRow    row        = senderTable.NewRow();
                SenderData senderData = senderSummaries[endPoint];

                row["IP Addr"] = senderData.Source.ToString();
                row["CName"]   = senderData.CName;

                row["Packets Sent"] = senderData.PacketsSent;
                row["Bytes Sent"]   = senderData.BytesSent;

                double kb = senderData.DataRate;
                row["Data rate"]   = kb.ToString("N") + " Kb/sec";
                row["Packet rate"] = senderData.PacketRate.ToString("N") + " pk/sec";

                if (senderData.LastSendUpdate.Equals(DateTime.MinValue))
                {
                    row["Last update*"] = "No sender data received.";
                }
                else
                {
                    row["Last update*"] = senderData.LastSendUpdate.ToString();
                }

                senderTable.Rows.Add(row);
            }
            return(senderTable);
        }
        private void BuildBasicReceiverTables(VenueState venueState, out DataTable thptTable, out DataTable lossTable,
                                              IDictionary <IPEndPoint, SenderData> senderSummaries)
        {
            thptTable = new DataTable();
            lossTable = new DataTable();

            thptTable.Columns.Add("Receiver IP", Type.GetType("System.String"));
            thptTable.Columns.Add("CName", Type.GetType("System.String"));
            lossTable.Columns.Add("Receiver IP", Type.GetType("System.String"));
            lossTable.Columns.Add("CName", Type.GetType("System.String"));

            // add a column for each sender...
            foreach (IPEndPoint endPoint in senderSummaries.Keys)
            {
                thptTable.Columns.Add(endPoint.ToString(), Type.GetType("System.String"));
                lossTable.Columns.Add(endPoint.ToString(), Type.GetType("System.String"));
            }


            lock (venueState.ReceiverData)
            {
                // add a row for each receiver
                foreach (IPEndPoint receiverEndpoint in getSortedReceivers(venueState))
                {
                    ReceiverData receiverData = venueState.ReceiverData[receiverEndpoint];
                    if (receiverData == null)
                    {
                        continue; // shouldn't happen...
                    }
                    // process receiver summaries
                    ICollection <ReceiverSummary> summaries = receiverData.ReceiverSummaries;
                    if (summaries == null || summaries.Count == 0)
                    {
                        continue;
                    }

                    DataRow thptRow = thptTable.NewRow();
                    DataRow lossRow = lossTable.NewRow();

                    thptRow["Receiver IP"] = receiverEndpoint.ToString();
                    thptRow["CName"]       = receiverData.CName;

                    lossRow["Receiver IP"] = receiverEndpoint.ToString();
                    lossRow["CName"]       = receiverData.CName;

                    // initialize sender columns...
                    foreach (IPEndPoint endPoint in senderSummaries.Keys)
                    {
                        lossRow[endPoint.ToString()] = "no data";
                        thptRow[endPoint.ToString()] = "no data";
                    }

                    // process receiver summaries, while merging data from co-located data streams
                    // thus, we should end up with one column per sending host, regardless of its
                    // number of output streams...
                    IDictionary <IPEndPoint, ReceiverSummary> mergedReceiverSummaries =
                        new Dictionary <IPEndPoint, ReceiverSummary>();

                    // this is the merge phase...
                    foreach (ReceiverSummary summary in summaries)
                    {
                        SenderData senderData;
                        if (!venueState.SenderData.TryGetValue(summary.SSRC, out senderData))
                        {
                            continue; // no sender data for this receiver summary
                        }
                        IPEndPoint senderEndpoint = senderData.Source;
                        if (senderEndpoint == null)
                        {
                            continue;
                        }

                        if (mergedReceiverSummaries.ContainsKey(senderEndpoint))
                        {
                            // merge the summary data with existing data from this sender
                            ReceiverSummary existingSummary = mergedReceiverSummaries[senderEndpoint];
                            ReceiverSummary updatedSummary  = new ReceiverSummary(existingSummary, summary);
                            mergedReceiverSummaries[senderEndpoint] = updatedSummary;
                        }
                        else
                        {
                            // otherwise, create a new summary entry for this EndPoint
                            mergedReceiverSummaries[senderEndpoint] = summary;
                        }
                    }

                    // At this point, we have merged data from co-located data streams.  Populate
                    // the columns corresponding to source IP addreses.
                    foreach (IPEndPoint senderEndpoint in mergedReceiverSummaries.Keys)
                    {
                        if (thptTable.Columns.Contains(senderEndpoint.ToString()))
                        {
                            ReceiverSummary summary    = mergedReceiverSummaries[senderEndpoint];
                            SenderData      senderData = senderSummaries[senderEndpoint];

                            double throughputDifferential = summary.PacketRate - senderData.PacketRate;

                            try
                            {
                                thptRow[senderEndpoint.ToString()] = String.Format("{0:N} pk/sec", throughputDifferential);

                                //String.Format("{1:N} - {2:N} = {0:N} pk/sec", throughputDifferential,
                                //summary.PacketRate , senderData.PacketRate);

                                lossRow[senderEndpoint.ToString()] = String.Format("{0:P}", summary.LossRate);
                            }
                            catch (Exception)
                            {
                                // these operations can fail when sender and receiver tables are out of sync
                            }
                        }
                    }

                    // mark "loopback" data as such
                    try
                    {
                        thptRow[receiverEndpoint.ToString()] = "loopback";
                        lossRow[receiverEndpoint.ToString()] = "loopback";
                    }
                    catch (Exception)
                    {
                        // these operations can fail if sender, receiver tables are out of sync...
                    }

                    thptTable.Rows.Add(thptRow);
                    lossTable.Rows.Add(lossRow);
                } // for each receiver in the venue
            }     // venue.receiverData lock
        }
Beispiel #9
0
        private void Start()
        {
            //BufferChunk chunk = new BufferChunk(2048);
            CompoundPacket compoundPacket = new CompoundPacket();
            EndPoint       endPoint       = null;

            while (isRunning)
            {
                try
                {
                    compoundPacket.Reset();
                    udpListener.ReceiveFrom(compoundPacket.Buffer, out endPoint);

                    compoundPacket.ParseBuffer();
                    //IPAddress ipAddress = ((IPEndPoint)endPoint).Address;
                    IPEndPoint ipEndpoint = (IPEndPoint)endPoint;

                    // The compound packet enumerator destroys its list during enumeration,
                    // so we keep track of packets that have yet to be processed
                    IList <RtcpPacket> yetToBeProcessed = new List <RtcpPacket>();


                    String venueName = null;
                    //uint ssrc = 0;
                    long when = 0; // in units of "ticks"

                    // scan through the compound packet, looking for key pieces of meta-data
                    // first, look for the app packet that specifies the venue
                    // also, obtain the ssrc and the time stamp

                    foreach (RtcpPacket packet in compoundPacket)
                    {
                        if (packet.PacketType == (byte)Rtcp.PacketType.APP)
                        {
                            AppPacket appPacket = new AppPacket(packet);
                            if (appPacket.Name.Equals(Rtcp.APP_PACKET_NAME) &&
                                appPacket.Subtype == Rtcp.VENUE_APP_PACKET_SUBTYPE)
                            {
                                BufferChunk chunk = new BufferChunk(appPacket.Data);
                                when      = chunk.NextInt64();
                                venueName = chunk.NextUtf8String(chunk.Length);
                                int padIndex = venueName.IndexOf((char)0);
                                if (padIndex > 0)
                                {
                                    venueName = venueName.Substring(0, padIndex);
                                }
                            }
                        }
                        else
                        {
                            yetToBeProcessed.Add(packet);
                        }
                    }

                    if (venueName == null)
                    {
                        continue; // can't do anything if we don't know the venue for this packet
                    }
                    if (when == 0)
                    {
                        continue; // need a timestamp
                    }
                    VenueState venueState = null;

                    // compound operations must always be locked...
                    lock (venueStateMap)
                    {
                        if (!venueStateMap.ContainsKey(venueName))
                        {
                            venueState = new VenueState(venueName);
                        }
                        else
                        {
                            venueState = venueStateMap[venueName];
                        }
                    }


                    // scan again, this time processing the RTCP packets
                    foreach (RtcpPacket packet in yetToBeProcessed)
                    {
                        switch (packet.PacketType)
                        {
                        case (byte)Rtcp.PacketType.SR:
                        {
                            SrPacket sr = new SrPacket(packet);

                            SenderData senderData = venueState.GetSenderState(sr.SSRC);
                            senderData.Source = ipEndpoint;

                            senderData.updateSenderState(sr.SenderReport, when);

                            // this "refreshes" the host state (so that it won't expire)
                            venueState.SenderData[sr.SSRC] = senderData;
                            break;
                        }

                        case (byte)Rtcp.PacketType.RR:
                        {
                            RrPacket     rr           = new RrPacket(packet);
                            ReceiverData receiverData = venueState.GetReceiverData(ipEndpoint);

                            // currently, we replace all receiver summaries with the data
                            // from a single RR packet
                            receiverData.updateReceiverState(rr.ReceiverReports, when, venueState);


                            // this "refreshes" the host state (so that it won't expire)
                            venueState.ReceiverData[ipEndpoint] = receiverData;
                            break;
                        }

                        case (byte)Rtcp.PacketType.SDES:
                        {
                            SdesPacket sdp = new SdesPacket(packet);

                            foreach (SdesReport report in sdp.Reports())
                            {
                                SenderData senderData = venueState.GetSenderState(report.SSRC);
                                senderData.CName  = report.SdesData.CName;
                                senderData.Source = ipEndpoint;

                                // this "refreshes" the host state (so that it won't expire)
                                venueState.SenderData[report.SSRC] = senderData;

                                ReceiverData receiverData =
                                    venueState.GetReceiverDataWithoutCreating(ipEndpoint);

                                if (receiverData != null)
                                {
                                    receiverData.CName = report.SdesData.CName;
                                }
                            }
                            break;
                        }

                        case (byte)Rtcp.PacketType.BYE:
                        {
                            //BYE packets occur when capabilities stop.  Clean out sender data only for the
                            //ssrc's affected.  We leave receiver reports alone for now.
                            ByePacket byePacket = new ByePacket(packet);
                            foreach (uint ssrc in byePacket.SSRCs)
                            {
                                venueState.SenderData.Remove(ssrc);
                            }
                            //Set a flag to cause the matrix for this venue to be rebuilt on the next request.
                            venueState.ParticipantChange = true;
                            continue;
                        }

                        case (byte)Rtcp.PacketType.APP:
                        {
                            // ignored

                            break;
                        }
                        }
                    }   // foreach packet...

                    // refresh the venue state
                    venueStateMap[venueName] = venueState;
                }
                catch (Exception e)
                {
                    Console.Out.WriteLine("Exception : " + e.ToString());

                    writeEventLog("Exception in receive thread: " + e.ToString(), EventLogEntryType.Warning);
                }
            } // loop forever...
        }
Beispiel #10
0
        public void updateReceiverState(ArrayList receiverReports, long when, VenueState venueState)
        {
            IDictionary <uint, ReceiverSummary> newSummaries = new Dictionary <uint, ReceiverSummary>();

            if (when <= lastReceiverStateUpdate)
            {
                return; // duplicate information
            }
            String timeString = DateTime.Now.ToString("s");

            foreach (ReceiverReport receiverReport in receiverReports)
            {
                ReceiverSummary summary = null;
                if (receiverSummaries.ContainsKey(receiverReport.SSRC) && lastReceiverStateUpdate > 0)
                {
                    /// We have an existing receiver summary: update session statistics

                    summary = receiverSummaries[receiverReport.SSRC];

                    double packetsReceivedThisInterval =
                        receiverReport.ExtendedHighestSequence - summary.TotalPacketsReceived;

                    double lossesThisInterval = ((ulong)receiverReport.PacketsLost) - summary.TotalLosses;

                    double seconds = ((double)(when - lastReceiverStateUpdate)) / TimeSpan.TicksPerSecond;

                    summary.PacketRate = packetsReceivedThisInterval / seconds;
                    if (lossesThisInterval + packetsReceivedThisInterval == 0)
                    {
                        summary.LossRate = 0.0;  //This can happen because some capabilities don't send much data.
                    }
                    else
                    {
                        summary.LossRate = lossesThisInterval / (lossesThisInterval + packetsReceivedThisInterval);
                    }

                    if (venueState.UseLogging)
                    {
                        SenderData senderState = venueState.GetSenderState(receiverReport.SSRC);
                        venueState.WriteLog(timeString + " " + endpoint + " " + senderState.Source + "/" + receiverReport.SSRC +
                                            " " + summary.PacketRate + " " + lossesThisInterval);
                    }
                }
                else
                {
                    /// create a new summary
                    summary = new ReceiverSummary(receiverReport.SSRC);
                }

                /// in either case, update the session statistics
                summary.TotalLosses = (ulong)receiverReport.PacketsLost;

                /// Note: we use EHS as total packets received!
                summary.TotalPacketsReceived = receiverReport.ExtendedHighestSequence;

                newSummaries[receiverReport.SSRC] = summary;
            } // for each receiver report...

            this.receiverSummaries  = newSummaries;
            lastReceiverStateUpdate = when;
        }
Beispiel #11
0
       private void Start()
       {
            //BufferChunk chunk = new BufferChunk(2048);
            CompoundPacket compoundPacket = new CompoundPacket();
            EndPoint endPoint = null;

            while (isRunning)
            {
                try
                {
                     compoundPacket.Reset();
                   udpListener.ReceiveFrom(compoundPacket.Buffer, out endPoint);

                    compoundPacket.ParseBuffer();
                    //IPAddress ipAddress = ((IPEndPoint)endPoint).Address;
                    IPEndPoint ipEndpoint = (IPEndPoint)endPoint;

                    // The compound packet enumerator destroys its list during enumeration,
                    // so we keep track of packets that have yet to be processed
                    IList<RtcpPacket> yetToBeProcessed = new List<RtcpPacket>();


                    String venueName = null;
                    //uint ssrc = 0;
                    long when = 0; // in units of "ticks"

                    // scan through the compound packet, looking for key pieces of meta-data
                    // first, look for the app packet that specifies the venue
                    // also, obtain the ssrc and the time stamp
                    
                    foreach (RtcpPacket packet in compoundPacket)
                    {
                        if (packet.PacketType == (byte)Rtcp.PacketType.APP)
                        {
                            AppPacket appPacket = new AppPacket(packet);
                            if (appPacket.Name.Equals(Rtcp.APP_PACKET_NAME) &&
                                appPacket.Subtype == Rtcp.VENUE_APP_PACKET_SUBTYPE)
                            {

                                BufferChunk chunk = new BufferChunk(appPacket.Data);
                                when = chunk.NextInt64();
                                venueName = chunk.NextUtf8String(chunk.Length);
                                int padIndex = venueName.IndexOf((char)0);
                                if (padIndex > 0)
                                    venueName = venueName.Substring(0, padIndex);
                            }
                        }
                        else
                        {
                            yetToBeProcessed.Add(packet);
                        }
                    }

                    if (venueName == null)
                        continue; // can't do anything if we don't know the venue for this packet
                    if (when == 0)
                        continue; // need a timestamp
                    
                    VenueState venueState = null;
                    
                    // compound operations must always be locked...
                    lock (venueStateMap)
                    {
                        if (!venueStateMap.ContainsKey(venueName))
                            venueState = new VenueState(venueName);
                        else venueState = venueStateMap[venueName];
                    }


                    // scan again, this time processing the RTCP packets
                    foreach (RtcpPacket packet in yetToBeProcessed)
                    {

                        switch (packet.PacketType)
                        {
                            case (byte)Rtcp.PacketType.SR:
                                {
                                    SrPacket sr = new SrPacket(packet);
                                    
                                    SenderData senderData = venueState.GetSenderState(sr.SSRC);
                                    senderData.Source = ipEndpoint;

                                    senderData.updateSenderState(sr.SenderReport, when);

                                    // this "refreshes" the host state (so that it won't expire)
                                    venueState.SenderData[sr.SSRC] = senderData;
                                    break;
                                }

                            case (byte)Rtcp.PacketType.RR:
                                {
                                    RrPacket rr = new RrPacket(packet);
                                    ReceiverData receiverData = venueState.GetReceiverData (ipEndpoint);

                                    // currently, we replace all receiver summaries with the data
                                    // from a single RR packet
                                    receiverData.updateReceiverState(rr.ReceiverReports, when, venueState);
                                        

                                    // this "refreshes" the host state (so that it won't expire)
                                    venueState.ReceiverData[ipEndpoint] = receiverData;
                                    break;
                                }

                            case (byte)Rtcp.PacketType.SDES:
                                {
                                    SdesPacket sdp = new SdesPacket(packet);                                   

                                    foreach(SdesReport report in sdp.Reports())
                                    {
                                        SenderData senderData = venueState.GetSenderState(report.SSRC);
                                        senderData.CName = report.SdesData.CName;
                                        senderData.Source = ipEndpoint;

                                        // this "refreshes" the host state (so that it won't expire)
                                        venueState.SenderData[report.SSRC] = senderData;

                                        ReceiverData receiverData = 
                                            venueState.GetReceiverDataWithoutCreating(ipEndpoint);

                                        if (receiverData != null)
                                            receiverData.CName = report.SdesData.CName;
                                    }
                                    break;
                                }

                            case (byte)Rtcp.PacketType.BYE:
                                {
                                    //BYE packets occur when capabilities stop.  Clean out sender data only for the
                                    //ssrc's affected.  We leave receiver reports alone for now.
                                    ByePacket byePacket = new ByePacket(packet);
                                    foreach (uint ssrc in byePacket.SSRCs) {
                                        venueState.SenderData.Remove(ssrc);
                                    }
                                    //Set a flag to cause the matrix for this venue to be rebuilt on the next request.
                                    venueState.ParticipantChange = true;
                                    continue;
                                }

                            case (byte)Rtcp.PacketType.APP:
                                {
                                    // ignored

                                    break;
                                }
                        }
                     }  // foreach packet...

                    // refresh the venue state
                     venueStateMap[venueName] = venueState;
                 }
                catch (Exception e)
                {
                    Console.Out.WriteLine("Exception : " + e.ToString());

                    writeEventLog("Exception in receive thread: " + e.ToString(), EventLogEntryType.Warning);
                }
            } // loop forever...
        }
Beispiel #12
0
        public void updateReceiverState(ArrayList receiverReports, long when,VenueState venueState)
        {
            IDictionary<uint, ReceiverSummary> newSummaries = new Dictionary<uint, ReceiverSummary>();

            if (when <= lastReceiverStateUpdate)
                return; // duplicate information

            String timeString = DateTime.Now.ToString("s");

            foreach (ReceiverReport receiverReport in receiverReports)
            {

                ReceiverSummary summary = null;
                if (receiverSummaries.ContainsKey(receiverReport.SSRC) && lastReceiverStateUpdate > 0)
                {

                    /// We have an existing receiver summary: update session statistics 

                    summary = receiverSummaries[receiverReport.SSRC];

                    double packetsReceivedThisInterval =
                        receiverReport.ExtendedHighestSequence - summary.TotalPacketsReceived;

                    double lossesThisInterval = ((ulong) receiverReport.PacketsLost) - summary.TotalLosses;
                                       
                    double seconds = ((double)(when - lastReceiverStateUpdate)) / TimeSpan.TicksPerSecond;

                    summary.PacketRate = packetsReceivedThisInterval / seconds;
                    if (lossesThisInterval + packetsReceivedThisInterval == 0) {
                        summary.LossRate = 0.0;  //This can happen because some capabilities don't send much data.
                    }
                    else {
                        summary.LossRate = lossesThisInterval / (lossesThisInterval + packetsReceivedThisInterval);
                    }

                    if (venueState.UseLogging) {
                        SenderData senderState = venueState.GetSenderState(receiverReport.SSRC);
                        venueState.WriteLog(timeString + " " + endpoint + " " + senderState.Source + "/" + receiverReport.SSRC +
                                    " " + summary.PacketRate + " " + lossesThisInterval);
                    }
                }
                else
                {
                    /// create a new summary
                    summary = new ReceiverSummary(receiverReport.SSRC);
                }

                /// in either case, update the session statistics
                summary.TotalLosses = (ulong)receiverReport.PacketsLost;

                /// Note: we use EHS as total packets received!
                summary.TotalPacketsReceived = receiverReport.ExtendedHighestSequence;

                newSummaries[receiverReport.SSRC] = summary;
            } // for each receiver report...

            this.receiverSummaries = newSummaries;
            lastReceiverStateUpdate = when;
        }
            /// <summary>
            /// Build a new matrix
            /// </summary>
            /// <param name="venueState"></param>
            public ConnectivityMatrix(VenueState venueState) {
                // Aggregate total sender packet rates for each unique sender cname, and 
                // compile a mapping of sender ssrc to cname which we will use for merging receiver reports.
                Dictionary<string, Row> matrix = new Dictionary<string, Row>(); 
                Dictionary<uint, string> ssrc2cname = new Dictionary<uint, string>();
                lock (venueState.SenderData) {
                    foreach (uint ssrc in venueState.SenderData.Keys) {
                        SenderData sd = venueState.SenderData[ssrc];
                        //Debug.WriteLine("  Building Matrix SenderData.cname=" + sd.CName + ";ssrc=" + ssrc.ToString());
                        if (matrix.ContainsKey(sd.CName)) {
                            matrix[sd.CName].SenderPacketRate += sd.PacketRate;
                        }
                        else {
                            matrix.Add(sd.CName, new Row(sd.CName, sd.PacketRate));
                        }
                        ssrc2cname.Add(ssrc, sd.CName);
                    }
                }

                ////Test code:  Create and remove a bogus sender to test missing participant functionality.
                //if (DateTime.Now.Second < 30) {
                //    matrix.Add("*****@*****.**", new Row("*****@*****.**", 50.15));
                //}
                ////End test code

                // Create the NxN matrix with row and column for each cname
                foreach (Row r in matrix.Values) {
                    r.CreateCells(matrix.Values);
                }

                lock (venueState.ReceiverData) {
                    // For each receiver summary, find the sender cname and update the appropriate sender's row.
                    foreach (ReceiverData rd in venueState.ReceiverData.Values) {
                        foreach (ReceiverSummary rs in rd.ReceiverSummaries) {
                            if (ssrc2cname.ContainsKey(rs.SSRC)) {
                                string senderCname = ssrc2cname[rs.SSRC];
                                if (matrix.ContainsKey(senderCname)) {
                                    matrix[senderCname].UpdateReceiver(rd.CName, rs.PacketRate);
                                }
                            }
                        }
                    }
                }

                //Commit: copy to serialized arrays
                foreach (Row r in matrix.Values) {
                    r.CommitRow();
                }
                Rows = new Row[matrix.Count];
                matrix.Values.CopyTo(Rows, 0);

                CreationTime = DateTime.Now;

            }