public void UdpBroadcastSettings_Server() { try { UdpBroadcastServerSettings settings; // Verify that we can read reasonable settings. var cfg1 = @" §ion Settings NetworkBinding = 1.1.1.1:10 SocketBufferSize = 128K Server[0] = 1.1.1.1:10 Server[1] = 2.2.2.2:20 SharedKey = aes:NtSkj76eyCAsJE4TnTqmPOuKd5hDDWwSS7ccTfeKEL8=:S9Xc6skGFWtxoxBaoTxJlQ== MessageTTL = 15m BkTaskInterval = 7s ClusterKeepAliveInterval = 10s ServerTTL = 15s ClientTTL = 20s &endsection "; Config.SetConfig(cfg1.Replace('&', '#')); settings = new UdpBroadcastServerSettings("Settings"); Assert.AreEqual(new NetworkBinding("1.1.1.1:10"), settings.NetworkBinding); Assert.AreEqual(128 * 1024, settings.SocketBufferSize); CollectionAssert.AreEqual(new NetworkBinding[] { new NetworkBinding("1.1.1.1:10"), new NetworkBinding("2.2.2.2:20") }, settings.Servers); Assert.AreEqual(TimeSpan.FromSeconds(7), settings.BkTaskInterval); Assert.AreEqual(TimeSpan.FromSeconds(10), settings.ClusterKeepAliveInterval); Assert.AreEqual(TimeSpan.FromSeconds(15), settings.ServerTTL); Assert.AreEqual(TimeSpan.FromSeconds(20), settings.ClientTTL); // Verify that an exception is thrown if no servers are specified. Config.SetConfig(string.Empty); try { settings = new UdpBroadcastServerSettings("Settings"); } catch (Exception e) { Assert.IsInstanceOfType(e, typeof(FormatException)); } } finally { Config.SetConfig(null); } }
/// <summary> /// Creates and starts a UDP broadcast server using the settings passed. /// </summary> /// <param name="settings">The server settings.</param> /// <param name="perfCounters">The application's performance counters (or <c>null</c>).</param> /// <param name="perfPrefix">The string to prefix any performance counter names (or <c>null</c>).</param> /// <remarks> /// <note> /// The <paramref name="perfCounters" /> parameter is type as <see cref="object" /> so that /// applications using this class will not be required to reference the <b>LillTel.Advanced</b> /// assembly. /// </note> /// </remarks> /// <exception cref="ArgumentException">Thrown if the settings passed are not valid.</exception> public UdpBroadcastServer(UdpBroadcastServerSettings settings, object perfCounters, string perfPrefix) { if (settings == null) { throw new ArgumentNullException("settings"); } if (settings.Servers == null || settings.Servers.Length == 0) { throw new ArgumentException("Invalid UDP broadcast server settings: At least one broadcast server endpoint is required."); } if (perfCounters != null && !(perfCounters is PerfCounterSet)) { throw new ArgumentException("Only instances of type [PerfCounterSet] may be passed in the [perfCounters] parameter.", "perfCounters"); } this.startTime = DateTime.UtcNow; this.closePending = false; this.settings = settings; this.perf = new Perf(perfCounters as PerfCounterSet, perfPrefix); bool found = false; for (int i = 0; i < settings.Servers.Length; i++) { var binding = settings.Servers[i]; if (binding == settings.NetworkBinding) { found = true; // I'm going to special case the situation where the network binding address is ANY. // In this case, one of the server endpoints must also include an ANY entry and I'll // fill out with the loop back addres (127.1.0.1). if (binding.IsAnyAddress) { settings.Servers[i] = new NetworkBinding(IPAddress.Loopback, settings.Servers[i].Port); } break; } } if (!found) { if (!settings.NetworkBinding.IsAnyAddress) { throw new ArgumentException("Invalid UDP broadcast server settings: The current server's network binding must also be present in the Servers[] bindings."); } } // Initialize the clients and servers state. clients = new Dictionary <IPEndPoint, ClientState>(); servers = new Dictionary <IPEndPoint, ServerState>(); // Open the socket and start receiving packets. socket = new EnhancedSocket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); socket.IgnoreUdpConnectionReset = true; socket.ReceiveBufferSize = settings.SocketBufferSize; socket.SendBufferSize = settings.SocketBufferSize; socket.Bind(settings.NetworkBinding); onReceive = new AsyncCallback(OnReceive); recvBuf = new byte[TcpConst.MTU]; rawRecvEP = new IPEndPoint(IPAddress.Any, 0); socket.BeginReceiveFrom(recvBuf, 0, recvBuf.Length, SocketFlags.None, ref rawRecvEP, onReceive, null); // Crank up a timer to send the ClientRegister messages to the server cluster. registerTimer = new PolledTimer(settings.ClusterKeepAliveInterval, true); registerTimer.FireNow(); // Make sure that we send registration messages immediately bkTimer = new GatedTimer(new TimerCallback(OnBkTask), null, TimeSpan.Zero, settings.BkTaskInterval); }