Example #1
0
        public void UdpBroadcastMessage_Serialize()
        {
            // Verify that we can serialize and deserialize a message.

            UdpBroadcastMessage msg;

            byte[]    buffer;
            IPAddress address = Helper.ParseIPAddress("10.1.2.3");

            msg = new UdpBroadcastMessage(UdpBroadcastMessageType.ClientRegister, address, 5, new byte[] { 0, 1, 2, 3, 4 });
            msg.TimeStampUtc = new DateTime(2010, 3, 19);
            Assert.AreEqual(UdpBroadcastMessageType.ClientRegister, msg.MessageType);
            Assert.AreEqual(5, msg.BroadcastGroup);
            CollectionAssert.AreEqual(new byte[] { 0, 1, 2, 3, 4 }, msg.Payload);
            Assert.AreEqual(address, msg.SourceAddress);

            buffer = msg.ToArray(sharedKey);
            msg    = new UdpBroadcastMessage(buffer, sharedKey);

            Assert.AreEqual(UdpBroadcastMessageType.ClientRegister, msg.MessageType);
            Assert.AreEqual(new DateTime(2010, 3, 19), msg.TimeStampUtc);
            Assert.AreEqual(5, msg.BroadcastGroup);
            CollectionAssert.AreEqual(new byte[] { 0, 1, 2, 3, 4 }, msg.Payload);
            Assert.AreEqual(address, msg.SourceAddress);

            // Verify that the message envelope size constant is correct.

            Assert.IsTrue(UdpBroadcastMessage.EnvelopeSize >= buffer.Length - msg.Payload.Length);
        }
Example #2
0
        public void UdpBroadcast_MessageNulls()
        {
            UdpBroadcastMessage msg;

            msg = new UdpBroadcastMessage(UdpBroadcastMessageType.ServerRegister, 10);

            Assert.AreEqual(10, msg.BroadcastGroup);
            CollectionAssert.AreEqual(new byte[0], msg.Payload);
        }
Example #3
0
        /// <summary>
        /// Constructs a <see cref="UdpBroadcastMessage"/> from the parameters passed and
        /// serializes it into the wire format.
        /// </summary>
        /// <param name="messageType">The message type.</param>
        /// <param name="sourceAddress">The IP address of the message source.</param>
        /// <param name="broadcastGroup">The broadcast group.</param>
        /// <param name="payload">The broadcast packet payload.</param>
        /// <returns>The packet bytes.</returns>
        private byte[] GetMessageBytes(UdpBroadcastMessageType messageType, IPAddress sourceAddress, int broadcastGroup, byte[] payload)
        {
            var message = new UdpBroadcastMessage(messageType, sourceAddress, broadcastGroup, payload);

            if (FixedTimestampUtc > DateTime.MinValue)
            {
                message.TimeStampUtc = FixedTimestampUtc;
            }

            return(message.ToArray(settings.SharedKey));
        }
Example #4
0
        /// <summary>
        /// Called when a packet is received on the socket.
        /// </summary>
        /// <param name="ar">The async result.</param>
        private void OnReceive(IAsyncResult ar)
        {
            UdpBroadcastMessage message = null;
            IPEndPoint          recvEP  = null;
            int cbRecv = 0;

            lock (syncLock)
            {
                if (socket == null)
                {
                    return; // Client is closed
                }
                try
                {
                    // Parse received packet.

                    cbRecv = socket.EndReceiveFrom(ar, ref rawRecvEP);
                    recvEP = (IPEndPoint)rawRecvEP;

                    if (cbRecv == 0)
                    {
                        return;     // This happens when we receive an ICMP(connection-reset) from a
                    }
                    // remote host that's actively refusing an earlier packet transmission.
                    // We're just going to ignore this.

                    perf.TotalMessageRate.Increment();
                    perf.TotalByteRate.IncrementBy(cbRecv);

                    message = new UdpBroadcastMessage(Helper.Extract(recvBuf, 0, cbRecv), settings.SharedKey);

                    // Validate that the message timestamp is reasonable and discard
                    // messages with timestamps from too far in the past or too far
                    // in the future.

                    DateTime now = DateTime.UtcNow;

                    if (!Helper.Within(now, message.TimeStampUtc, settings.MessageTTL))
                    {
                        SysLog.LogWarning("UDP Broadcast message timestamp out of range. SystemTime={0}, Timestamp={1}, Source={2}, BroadcastGroup={3}",
                                          now.ToString("u"), message.TimeStampUtc.ToString("u"), recvEP, message.BroadcastGroup);
                        return;
                    }
                }
                catch (Exception e)
                {
                    SysLog.LogException(e);
                }
                finally
                {
                    // Initiate the next receive.

                    try
                    {
                        rawRecvEP = new IPEndPoint(IPAddress.Any, 0);
                        socket.BeginReceiveFrom(recvBuf, 0, recvBuf.Length, SocketFlags.None, ref rawRecvEP, onReceive, null);
                    }
                    catch (Exception e)
                    {
                        SysLog.LogException(e);
                    }
                }

                // Process the message (if any).

                if (message == null || PauseNetwork)
                {
                    return;
                }

                ServerState server;
                ClientState client;

                switch (message.MessageType)
                {
                case UdpBroadcastMessageType.ServerRegister:

                    // Add the server to the tracking table if it's not already
                    // present and update its TTD.

                    if (!servers.TryGetValue(recvEP, out server))
                    {
                        server = new ServerState(recvEP, SysTime.Now + settings.ServerTTL);
                        servers.Add(recvEP, server);
                    }
                    else
                    {
                        server.TTD = SysTime.Now + settings.ServerTTL;
                    }

                    perf.AdminByteRate.IncrementBy(cbRecv);
                    perf.AdminMessageRate.Increment();
                    break;

                case UdpBroadcastMessageType.ServerUnregister:

                    // Remove the server from the tracking table (if present).

                    if (servers.ContainsKey(recvEP))
                    {
                        servers.Remove(recvEP);
                    }

                    perf.AdminByteRate.IncrementBy(cbRecv);
                    perf.AdminMessageRate.Increment();
                    break;

                case UdpBroadcastMessageType.ClientRegister:

                    // Add the client to the tracking table if it's not already
                    // present and update its TTD.

                    if (!clients.TryGetValue(recvEP, out client))
                    {
                        client = new ClientState(recvEP, message.BroadcastGroup, SysTime.Now + settings.ServerTTL);
                        clients.Add(recvEP, client);
                    }
                    else
                    {
                        client.TTD = SysTime.Now + settings.ServerTTL;
                    }

                    perf.AdminByteRate.IncrementBy(cbRecv);
                    perf.AdminMessageRate.Increment();
                    break;

                case UdpBroadcastMessageType.ClientUnregister:

                    // Remove the client from the tracking table (if present).

                    if (clients.ContainsKey(recvEP))
                    {
                        clients.Remove(recvEP);
                    }

                    perf.AdminByteRate.IncrementBy(cbRecv);
                    perf.AdminMessageRate.Increment();
                    break;

                case UdpBroadcastMessageType.Broadcast:

                    // Transmit the message to all clients the belong to the same broadcast group,
                    // if this is the master server.

                    if (!IsMaster)
                    {
                        return;
                    }

                    var packet     = GetMessageBytes(UdpBroadcastMessageType.Broadcast, message.SourceAddress, message.BroadcastGroup, message.Payload);
                    int cDelivered = 0;

                    foreach (var c in clients.Values)
                    {
                        if (c.BroadcastGroup == message.BroadcastGroup)
                        {
                            socket.SendTo(packet, c.EndPoint);
                            cDelivered++;
                        }
                    }

                    perf.BroadcastReceiveByteRate.IncrementBy(cbRecv);
                    perf.BroadcastReceiveMessageRate.Increment();
                    perf.BroadcastSendByteRate.IncrementBy(cbRecv * packet.Length);
                    perf.BroadcastSendMessageRate.IncrementBy(cDelivered);
                    break;
                }
            }
        }
Example #5
0
        /// <summary>
        /// Called when a packet is received on the socket.
        /// </summary>
        /// <param name="ar">The async result.</param>
        private void OnReceive(IAsyncResult ar)
        {
            UdpBroadcastMessage message = null;
            IPEndPoint          recvEP;
            int cbRecv;

            lock (syncLock)
            {
                if (socket == null)
                {
                    return; // Client is closed
                }
                try
                {
                    // Parse received packet.

                    cbRecv = socket.EndReceiveFrom(ar, ref rawRecvEP);
                    recvEP = (IPEndPoint)rawRecvEP;

                    if (cbRecv == 0)
                    {
                        return;     // This happens when we receive an ICMP(connection-reset) from a
                    }
                    // remote host that's actively refusing an earlier packet transmission.
                    // We're just going to ignore this.

                    message = new UdpBroadcastMessage(Helper.Extract(recvBuf, 0, cbRecv), settings.SharedKey);

                    // Validate that the message timestamp is reasonable and discard
                    // messages with timestamps from too far in the past or too far
                    // in the future.

                    DateTime now = DateTime.UtcNow;

                    if (!Helper.Within(now, message.TimeStampUtc, settings.MessageTTL))
                    {
                        SysLog.LogWarning("UDP Broadcast message timestamp out of range. SystemTime={0}, Timestamp={1}, Source={2}, BroadcastGroup={3}",
                                          now.ToString("u"), message.TimeStampUtc.ToString("u"), recvEP, message.BroadcastGroup);
                        return;
                    }
                }
                catch (Exception e)
                {
                    SysLog.LogException(e);
                }
                finally
                {
                    // Initiate the next receive.

                    try
                    {
                        rawRecvEP = new IPEndPoint(IPAddress.Any, 0);
                        socket.BeginReceiveFrom(recvBuf, 0, recvBuf.Length, SocketFlags.None, ref rawRecvEP, onReceive, null);
                    }
                    catch (Exception e)
                    {
                        SysLog.LogException(e);
                    }
                }
            }

            // Process the message (if any) outside of the lock.  Note that only
            // broadcast messages are processed by UDP broadcast clients.

            if (message == null || message.MessageType != UdpBroadcastMessageType.Broadcast || PauseNetwork)
            {
                return;
            }

            // Ignore messages that don't match the broadcast group.

            if (settings.BroadcastGroup != message.BroadcastGroup)
            {
                return;
            }

            if (PacketReceived != null)
            {
                PacketReceived(this, new UdpBroadcastEventArgs(message.SourceAddress, message.Payload));
            }
        }