/// <summary> /// Constructor. /// </summary> public DynDnsClient() { this.syncLock = this; this.isOpen = false; this.router = null; this.cluster = null; this.enabled = false; this.settings = null; this.bkTimer = null; this.hosts = new Dictionary <DynDnsHostEntry, DynDnsHostEntry>(); }
/// <summary> /// Opens the <see cref="DynDnsClient" /> instance enabling it to join /// the Dynamic DNS Service cluster and to start replicating host/IP address /// associations. /// </summary> /// <param name="router">The <see cref="MsgRouter" /> to be associated with the client (or <c>null</c>).</param> /// <param name="settings">The <see cref="DynDnsClientSettings" /> to be used.</param> /// <exception cref="InvalidOperationException">Thrown if the instance is already open.</exception> /// <remarks> /// <note> /// The <see cref="ClusterMemberSettings" />' <see cref="ClusterMemberSettings.Mode" /> /// property will be ignored and the instance aill join the cluster as an /// <see cref="ClusterMemberMode.Observer" />. The rest of the member settings /// should be identical to the settings across all cluster instances to avoid /// strange protocol problems. /// </note> /// </remarks> public void Open(MsgRouter router, DynDnsClientSettings settings) { var orgMode = ClusterMemberMode.Unknown; if (this.isOpen) { throw new InvalidOperationException("DynDnsClient is already open."); } if (settings.Mode == DynDnsMode.Both) { throw new ArgumentException("DynDnsClient does not support [Mode=BOTH]."); } this.isOpen = true; this.settings = settings; // Make sure that the LillTek.Datacenter message types have been // registered with the LillTek.Messaging subsystem. LillTek.Datacenter.Global.RegisterMsgTypes(); // Initialize enabled = settings.Enabled; if (!enabled) { return; } if (settings.Cluster != null) { orgMode = settings.Cluster.Mode; // $hack(jeff.lill): This is a bit of a hack settings.Cluster.Mode = ClusterMemberMode.Observer; } foreach (var entry in settings.Hosts) { Register(entry); } try { using (TimedLock.Lock(syncLock)) { if (settings.Mode == DynDnsMode.Cluster) { if (router == null) { throw new ArgumentException("DynDnsClient requires a valid router when operating with [Mode=CLUSTER]."); } if (settings.Cluster == null) { throw new ArgumentException("Cluster settings must be initialized when [Mode=CLUSTER]."); } this.router = router; this.cluster = new ClusterMember(router, settings.Cluster); foreach (DynDnsHostEntry host in settings.Hosts) { hosts[host] = host; } this.cluster.Start(); Register(); // Add any pre-existing host registrations to // the cluster member state } else if (settings.Mode == DynDnsMode.Udp) { this.udpRegisterTimer = new PolledTimer(settings.UdpRegisterInterval, true); this.udpRegisterTimer.FireNow(); this.domainRefreshTimer = new PolledTimer(settings.DomainRefreshInterval, true); this.domainRefreshTimer.FireNow(); this.bkTimer = new GatedTimer(new TimerCallback(OnBkTask), null, settings.BkInterval); this.socket = new EnhancedSocket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); this.socket.IgnoreUdpConnectionReset = true; this.socket.Bind(settings.NetworkBinding); } } } catch { Close(); throw; } finally { if (settings.Cluster != null) { settings.Cluster.Mode = orgMode; } } }