public void ByeEncode() { // Define variables ByePacket p1 = new ByePacket(); string encodedString = p1.Encode(true); // Check result Assert.AreEqual("b", encodedString, "Bye message didn't encode correctly"); }
public void ByeDecode() { // Define variables ByePacket p1 = new ByePacket(); string encodedString = p1.Encode(true); // Try to decode packet try { ByePacket p2 = ByePacket.Decode(encodedString); } catch (System.Exception e) { Assert.Fail("Bye packet exception: " + e.Message); } }
// This function is meant to be run in its own thread // Is writes and reads Packets to/from the UdpClient private void _networkRun() { if (!_running.Value) { return; } Console.WriteLine("[Server] Waiting for UDP datagrams on port {0}", Port); while (_running.Value) { bool canRead = _udpClient.Available > 0; int numToWrite = _outgoingMessages.Count; int numToDisconnect = _sendByePacketTo.Count; // Get data if there is some if (canRead) { // Read in one datagram IPEndPoint ep = new IPEndPoint(IPAddress.Any, 0); byte[] data = _udpClient.Receive(ref ep); // Blocks // Enque a new message NetworkMessage nm = new NetworkMessage(); nm.Sender = ep; nm.Packet = new Packet(data); nm.ReceiveTime = DateTime.Now; _incomingMessages.Enqueue(nm); //Console.WriteLine("RCVD: {0}", nm.Packet); } // Write out queued for (int i = 0; i < numToWrite; i++) { // Send some data Tuple <Packet, IPEndPoint> msg; bool have = _outgoingMessages.TryDequeue(out msg); if (have) { msg.Item1.Send(_udpClient, msg.Item2); } //Console.WriteLine("SENT: {0}", msg.Item1); } // Notify clients of Bye for (int i = 0; i < numToDisconnect; i++) { IPEndPoint to; bool have = _sendByePacketTo.TryDequeue(out to); if (have) { ByePacket bp = new ByePacket(); bp.Send(_udpClient, to); } } // If Nothing happened, take a nap if (!canRead && (numToWrite == 0) && (numToDisconnect == 0)) { Thread.Sleep(1); } } Console.WriteLine("[Server] Done listening for UDP datagrams"); // Wait for all arena's thread to join Queue <Arena> arenas = new Queue <Arena>(_activeArenas.Keys); if (arenas.Count > 0) { Console.WriteLine("[Server] Waiting for active Areans to finish..."); foreach (Arena arena in arenas) { arena.JoinThread(); } } // See which clients are left to notify of Bye if (_sendByePacketTo.Count > 0) { Console.WriteLine("[Server] Notifying remaining clients of shutdown..."); // run in a loop until we've told everyone else IPEndPoint to; bool have = _sendByePacketTo.TryDequeue(out to); while (have) { ByePacket bp = new ByePacket(); bp.Send(_udpClient, to); have = _sendByePacketTo.TryDequeue(out to); } } }
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... }
/// <summary> /// A ByePacket can contain multiple SSRCs so we need to process them in a loop /// </summary> /// <param name="packet">ByePacket</param> /// <param name="ipAddress">IPAddress packet was received from</param> private void ProcessBYEPacket(ByePacket packet, IPAddress ipAddress) { // Remove stream does a special form of AddSsrcToIp // to try and prevent mischievous programming foreach(uint ssrc in packet.SSRCs) { RemoveSSRC(ssrc, ipAddress); } }