public void AuthService_EndToEnd_Basic() { // Do some authentications against a file realm mapper and a file // authentication extension. LeafRouter router = null; Process svcProcess = null; Authenticator authenticator = null; Assembly assembly; StreamWriter writer; StreamReader reader; string realmsPath; string accountsPath; string orgRealms = null; string orgAccounts = null; assembly = typeof(LillTek.Datacenter.AuthService.Program).Assembly; realmsPath = Helper.GetAssemblyFolder(assembly) + "Realms.txt"; accountsPath = Helper.GetAssemblyFolder(assembly) + "Accounts.txt"; try { // Start a client router for the test and create an authenticator. Config.SetConfig(@" //----------------------------------------------------------------------------- // LeafRouter Settings §ion MsgRouter AppName = LillTek.Test Router AppDescription = Extensible authentication hub RouterEP = physical://DETACHED/$(LillTek.DC.DefHubName)/$(Guid) CloudEP = $(LillTek.DC.CloudEP) CloudAdapter = ANY UdpEP = ANY:0 TcpEP = ANY:0 TcpBacklog = 100 TcpDelay = off BkInterval = 1s MaxIdle = 5m EnableP2P = yes AdvertiseTime = 1m DefMsgTTL = 5 SharedKey = PLAINTEXT SessionCacheTime = 2m SessionRetries = 3 SessionTimeout = 10s MaxLogicalAdvertiseEPs = 256 DeadRouterTTL = 2s // This maps the abstract authentication service client and server endpoints // to their default logical endpoints. AbstractMap[abstract://LillTek/DataCenter/Auth/Client] = logical://LillTek/DataCenter/Auth/Client AbstractMap[abstract://LillTek/DataCenter/Auth/Service] = logical://LillTek/DataCenter/Auth/Service AbstractMap[abstract://LillTek/DataCenter/Auth/*] = logical://LillTek/DataCenter/Auth/* &endsection ".Replace('&', '#')); router = new LeafRouter(); router.Start();; authenticator = new Authenticator(); authenticator.Open(router, new AuthenticatorSettings()); // Initialize Realms.txt and Accounts.txt with some test accounts try { reader = new StreamReader(realmsPath, Helper.AnsiEncoding); orgRealms = reader.ReadToEnd(); reader.Close(); } catch { orgRealms = ""; } writer = new StreamWriter(realmsPath, false, Helper.AnsiEncoding); writer.WriteLine("$$LillTek.Datacenter.Server.FileAuthenticationExtension:LillTek.Datacenter.Server.dll$$path=$(AppPath)/accounts.txt;reload=yes;maxCacheTime=5m$$"); writer.Close(); try { reader = new StreamReader(accountsPath, Helper.AnsiEncoding); orgAccounts = reader.ReadToEnd(); reader.Close(); } catch { orgAccounts = ""; } writer = new StreamWriter(accountsPath, false, Helper.AnsiEncoding); writer.WriteLine(";account1;password1"); writer.WriteLine(";account2;password2"); writer.Close(); // Start the authentication service svcProcess = Helper.StartProcess(assembly, "-mode:form -start"); Thread.Sleep(10000); // Give the process a chance to spin up // Perform the tests. Assert.AreEqual(AuthenticationStatus.Authenticated, authenticator.Authenticate("", "account1", "password1").Status); Assert.AreEqual(AuthenticationStatus.Authenticated, authenticator.Authenticate("", "account2", "password2").Status); Assert.AreNotEqual(AuthenticationStatus.Authenticated, authenticator.Authenticate("x", "account1", "password1").Status); Assert.AreNotEqual(AuthenticationStatus.Authenticated, authenticator.Authenticate("", "account2x", "password2").Status); Assert.AreNotEqual(AuthenticationStatus.Authenticated, authenticator.Authenticate("", "account2x", "password2x").Status); } finally { if (svcProcess != null) { svcProcess.Kill(); svcProcess.Close(); } if (authenticator != null) { authenticator.Close(); } if (router != null) { router.Stop(); } // Restore the Realms.txt and Accounts.txt files. if (orgRealms != null) { writer = new StreamWriter(realmsPath, false, Helper.AnsiEncoding); writer.Write(orgRealms); writer.Close(); } if (orgAccounts != null) { writer = new StreamWriter(accountsPath, false, Helper.AnsiEncoding); writer.Write(orgAccounts); writer.Close(); } Config.SetConfig(null); } }
/// <summary> /// Returns configuration information formatted as an .ini file as /// specified by <see cref="Config" />. /// </summary> /// <param name="settings">Provider specific settings.</param> /// <param name="cacheFile">File path to use for cached settings.</param> /// <param name="machineName">The requesting machine's name.</param> /// <param name="exeFile">The unqualified name of the current process' executable file.</param> /// <param name="exeVersion">The version number of the current executable file.</param> /// <param name="usage">Used to indicate a non-default usage for this application instance.</param> /// <returns>The configuration file data (or <c>null</c>).</returns> /// <remarks> /// <para> /// The settings parameter must specify the <b>RouterEP</b> and <b>CloudEP</b> setting values, /// (the rest are optional): /// </para> /// <code language="none"> /// RouterEP = <Router Physical Endpoint> /// CloudEP = <IP Endpoint> /// ConfigEP = <logical or physical endpoint> (optional) /// EnableP2P = 0 | 1 (optional) /// </code> /// <para> /// <b>RouterEP</b> specifies the unique physical endpoint to be assigned to the /// bootstrap router. This must be unique across all routers so it's best to /// use the $(Guid) environment variable somewhere within the definition. /// </para> /// <para> /// <b>CloudEP</b> specifies the IP endpoint to be used by a bootstrap /// message router to discover the other routers on the network, and <b>ConfigEP</b> /// specifies the logical or physical messaging endpoint of the configuration service. /// The class uses this information to start a leaf bootstrap router which will /// be used to discover and communicate with the configuration service. /// </para> /// <para> /// The <b>EnableP2P</b> setting indicates whether the bootstrap router should be /// peer-to-peer enabled. This parameter is optional and defaults to "1". This /// setting is present for scalability reasons. P2P enabling the bootstrap router /// will cause a lot of network traffic in environments with a lot of servers since /// every other P2P enabled router will establish a connection to the bootstrap /// router to discover its logical routes. This is a significant overhead for a /// router that exposes no routes. <b>EnableP2P</b> should be set to "0" in production /// environments with a lot of servers and with a hub server present to avoid this /// problem. /// </para> /// <para> /// The cacheFile parameter specifies the name of the file where the provider /// may choose to cache configuration settings. This implementation will save a copy /// of the last set of settings returned by a remote service in this file and /// then use these settings if the remote service is unavailable the next time /// the service is started. This improves the operational robustness of a /// large network of servers. Choosing to implement this behavior is completely /// up to the discretion of the provider. Specify <b>(no-cache)</b> to disable /// caching behavior. /// </para> /// <para> /// Note that the method will return null if the requested configuration /// information could not be loaded for any reason. /// </para> /// <para> /// This class queries the configuration service via the following message /// endpoints: /// </para> /// <code language="none"> /// abstract://LillTek/DataCenter/ConfigService /// </code> /// <para> /// This may be remapped to another logical endpoint via the message /// routers <b>MsgRouter.AbstractMap</b> configuation setting. /// </para> /// </remarks> public string GetConfig(ArgCollection settings, string cacheFile, string machineName, string exeFile, Version exeVersion, string usage) { LeafRouter router = null; RouterSettings rSettings; string s; MsgEP routerEP; IPEndPoint cloudEP; MsgEP configEP; bool enableP2P; GetConfigAck ack; string configText = null; Exception queryException = null; // Make sure that the assembly's message types have been // registered with the LillTek.Messaging subsystem. Global.RegisterMsgTypes(); // Parse the settings s = settings["RouterEP"]; if (s == null) { throw new ArgumentException("[RouterEP] setting expected.", "settings"); } try { routerEP = MsgEP.Parse(s); } catch { throw new ArgumentException("[RouterEP] is invalid.", "settings"); } if (!routerEP.IsPhysical) { throw new ArgumentException("[RouterEP] must specify a physical endpoint.", "settings"); } s = settings["CloudEP"]; if (s == null) { throw new ArgumentException("[CloudEP] setting expected.", "settings"); } cloudEP = Serialize.Parse(s, new IPEndPoint(IPAddress.Any, 0)); if (cloudEP == new IPEndPoint(IPAddress.Any, 0)) { throw new ArgumentException("[CloudEP] setting is invalid.", "settings"); } configEP = Serialize.Parse(settings["ConfigEP"], GetConfigEP); enableP2P = Serialize.Parse(settings["EnableP2P"], true); // Crank up a bootstrap leaf router and perform the query. try { router = new LeafRouter(); rSettings = new RouterSettings(routerEP); rSettings.AppName = rSettings.AppName + " (config boot)"; rSettings.CloudEP = cloudEP; rSettings.EnableP2P = enableP2P; router.Start(rSettings); ack = (GetConfigAck)router.Query(configEP, new GetConfigMsg(machineName, exeFile, exeVersion, usage)); configText = ack.ConfigText; } catch (Exception e) { queryException = e; configText = null; } finally { if (router != null) { router.Stop(); } } if (configText != null) { // Cache the query result if requested if (!string.IsNullOrWhiteSpace(cacheFile) && String.Compare(cacheFile, "(no-cache)", true) != 0) { StreamWriter writer; try { writer = new StreamWriter(cacheFile); writer.Write(configText); writer.Close(); } catch { } } } else { // Try loading a cached configuration if (string.IsNullOrWhiteSpace(cacheFile)) { SysLog.LogException(queryException, "GetConfig query failed with no cached settings."); } else { StreamReader reader; SysLog.LogWarning("GetConfig query failed: Loading cached settings."); try { reader = new StreamReader(cacheFile); configText = reader.ReadToEnd(); reader.Close(); } catch { configText = null; } } } return(configText); }
public void Initialize() { // Helper.SetLocalGuidMode(GuidMode.CountUp); NetTrace.Start(); // NetTrace.Enable(MsgRouter.TraceSubsystem,255); NetTrace.Enable(ClusterMember.TraceSubsystem, 255); const string settings = @" §ion MsgRouter AppName = Test AppDescription = Test Description RouterEP = physical://detached/test/leaf CloudEP = $(LillTek.DC.CloudEP) CloudAdapter = ANY UdpEP = ANY:0 TcpEP = ANY:0 TcpBacklog = 100 TcpDelay = off BkInterval = 1s MaxIdle = 5m EnableP2P = yes AdvertiseTime = 1m DefMsgTTL = 5 SharedKey = PLAINTEXT SessionCacheTime = 2m SessionRetries = 3 SessionTimeout = 10s MaxLogicalAdvertiseEPs = 256 DeadRouterTTL = 2s AbstractMap[abstract://LillTek/DataCenter/DynDNS] = logical://LillTek/DataCenter/DynDNS &endsection §ion LillTek.Datacenter.DynDNS NetworkBinding = ANY:DNS UdpBinding = ANY:DYNAMIC-DNS Mode = BOTH SharedKey = aes:BcskocQ2W4aIGEemkPsy5dhAxuWllweKLVToK1NoYzg=:5UUVxRPml8L4WH82unR74A== BkInterval = 1s RegistrationTTL = 185s MessageTTL = 15m ResponseTTL = 5s LogFailures = yes // NameServer[0] = // Host[0] = §ion Cluster ClusterBaseEP = abstract://LillTek/DataCenter/DynDNS Mode = Normal MasterBroadcastInterval = 1s SlaveUpdateInterval = 1s ElectionInterval = 3s MissingMasterCount = 3 MissingSlaveCount = 3 MasterBkInterval = 1s SlaveBkInterval = 1s BkInterval = 1s &endsection &endsection §ion LillTek.Datacenter.DynDNS.AddressCache NetworkBinding = ANY:DNS UdpBinding = ANY:DYNAMIC-DNS Mode = BOTH SharedKey = aes:BcskocQ2W4aIGEemkPsy5dhAxuWllweKLVToK1NoYzg=:5UUVxRPml8L4WH82unR74A== BkInterval = 1s RegistrationTTL = 185s MessageTTL = 15m ResponseTTL = 5s LogFailures = yes // NameServer[0] = Host[-] = test1.lilltek.com, www.lilltek.com, 1800 Host[-] = test2.lilltek.com, www.google.com, 1800 AddressCache[-] = www.google.com AddressCache[-] = www.lilltek.com,1800 §ion Cluster ClusterBaseEP = abstract://LillTek/DataCenter/DynDNS Mode = Normal MasterBroadcastInterval = 1s SlaveUpdateInterval = 1s ElectionInterval = 3s MissingMasterCount = 3 MissingSlaveCount = 3 MasterBkInterval = 1s SlaveBkInterval = 1s BkInterval = 1s &endsection &endsection §ion DynDnsClient Enabled = yes NetworkBinding = ANY Mode = CLUSTER SharedKey = aes:BcskocQ2W4aIGEemkPsy5dhAxuWllweKLVToK1NoYzg=:5UUVxRPml8L4WH82unR74A== BkInterval = 1s DomainRefreshInterval = 15m UdpRegisterInterval = 1m // Domain = // NameServer[0] = // Host[0] = §ion Cluster ClusterBaseEP = abstract://LillTek/DataCenter/DynDNS Mode = Normal MasterBroadcastInterval = 1s SlaveUpdateInterval = 1s ElectionInterval = 3s MissingMasterCount = 3 MissingSlaveCount = 3 MasterBkInterval = 1s SlaveBkInterval = 1s BkInterval = 1s &endsection &endsection §ion DynDnsClient.Disabled Enabled = no NetworkBinding = ANY Mode = CLUSTER SharedKey = aes:BcskocQ2W4aIGEemkPsy5dhAxuWllweKLVToK1NoYzg=:5UUVxRPml8L4WH82unR74A== BkInterval = 1s DomainRefreshInterval = 15m UdpRegisterInterval = 1m // Domain = // NameServer[0] = // Host[0] = §ion Cluster ClusterBaseEP = abstract://LillTek/DataCenter/DynDNS Mode = Normal MasterBroadcastInterval = 1s SlaveUpdateInterval = 1s ElectionInterval = 3s MissingMasterCount = 3 MissingSlaveCount = 3 MasterBkInterval = 1s SlaveBkInterval = 1s BkInterval = 1s &endsection &endsection §ion DynDnsClient.Test Enabled = yes NetworkBinding = ANY Mode = CLUSTER SharedKey = aes:BcskocQ2W4aIGEemkPsy5dhAxuWllweKLVToK1NoYzg=:5UUVxRPml8L4WH82unR74A== BkInterval = 1s DomainRefreshInterval = 15m UdpRegisterInterval = 1m // Domain = // NameServer[0] = Host[0] = test0.com,10.0.0.1 Host[1] = test1.com,10.0.0.2 §ion Cluster ClusterBaseEP = abstract://LillTek/DataCenter/DynDNS Mode = Normal MasterBroadcastInterval = 1s SlaveUpdateInterval = 1s ElectionInterval = 3s MissingMasterCount = 3 MissingSlaveCount = 3 MasterBkInterval = 1s SlaveBkInterval = 1s BkInterval = 1s &endsection &endsection "; Config.SetConfig(settings.Replace('&', '#')); router = new LeafRouter(); router.Start(); }
public void AuthService_EndToEnd_Advanced() { // Perform tests against LDAP, ODBC, FILE, and RADIUS sources. Note that // I'm explicitly avoiding testing the CONFIG source. LeafRouter router = null; Process svcProcess = null; Authenticator authenticator = null; AuthTestState state = null; Assembly assembly; StreamWriter writer; StreamReader reader; string realmsPath; string orgRealms = null; AuthServiceHandlerClient wcfClient = null; AuthTestJsonClient jsonClient = null; assembly = typeof(LillTek.Datacenter.AuthService.Program).Assembly; realmsPath = Helper.GetAssemblyFolder(assembly) + "Realms.txt"; try { // Start a client router for the test and create an authenticator // and WCF client. Config.SetConfig(@" //----------------------------------------------------------------------------- // LeafRouter Settings §ion MsgRouter AppName = LillTek.Test Router AppDescription = Extensible authentication hub RouterEP = physical://DETACHED/$(LillTek.DC.DefHubName)/$(Guid) CloudEP = $(LillTek.DC.CloudEP) CloudAdapter = ANY UdpEP = ANY:0 TcpEP = ANY:0 TcpBacklog = 100 TcpDelay = off BkInterval = 1s MaxIdle = 5m EnableP2P = yes AdvertiseTime = 1m DefMsgTTL = 5 SharedKey = PLAINTEXT SessionCacheTime = 2m SessionRetries = 3 SessionTimeout = 10s MaxLogicalAdvertiseEPs = 256 DeadRouterTTL = 2s // This maps the abstract authentication service client and server endpoints // to their default logical endpoints. AbstractMap[abstract://LillTek/DataCenter/Auth/Client] = logical://LillTek/DataCenter/Auth/Client AbstractMap[abstract://LillTek/DataCenter/Auth/Service] = logical://LillTek/DataCenter/Auth/Service AbstractMap[abstract://LillTek/DataCenter/Auth/*] = logical://LillTek/DataCenter/Auth/* &endsection ".Replace('&', '#')); router = new LeafRouter(); router.Start(); authenticator = new Authenticator(); authenticator.Open(router, new AuthenticatorSettings()); // Initialize Realms.txt state = new AuthTestState(); state.Initialize(); try { reader = new StreamReader(realmsPath, Helper.AnsiEncoding); orgRealms = reader.ReadToEnd(); reader.Close(); } catch { orgRealms = ""; } writer = new StreamWriter(realmsPath, false, Helper.AnsiEncoding); foreach (AuthTestExtensionType type in Enum.GetValues(typeof(AuthTestExtensionType))) { if (type != AuthTestExtensionType.Config) { writer.WriteLine("{0}$${1}$${2}$${3}", state.GetRealm(type), state.GetType(type), state.GetArgs(type), state.GetQuery(type)); } } writer.Close(); // Start the authentication service svcProcess = Helper.StartProcess(assembly, "-mode:form -start"); Thread.Sleep(10000); // Give the process a chance to spin up // Perform the tests. wcfClient = new AuthServiceHandlerClient(new BasicHttpBinding(), new EndpointAddress(string.Format("http://{0}:80/WCF-AuthService/Auth.svc", Helper.MachineName))); wcfClient.Open(); jsonClient = new AuthTestJsonClient(string.Format("http://{0}:80/AuthService/Auth.json", Helper.MachineName)); foreach (AuthTestAccount account in state.Accounts) { if (account.ExtensionType == AuthTestExtensionType.Config) { continue; } // Test using the authenticator client Assert.AreEqual(AuthenticationStatus.Authenticated, authenticator.Authenticate(account.Realm, account.Account, account.Password).Status); Assert.AreNotEqual(AuthenticationStatus.Authenticated, authenticator.Authenticate(account.Realm + "x", account.Account, account.Password).Status); Assert.AreNotEqual(AuthenticationStatus.Authenticated, authenticator.Authenticate(account.Realm, account.Account + "x", account.Password).Status); Assert.AreNotEqual(AuthenticationStatus.Authenticated, authenticator.Authenticate(account.Realm, account.Account, account.Password + "x").Status); // Test using the JSON HTTP/GET Assert.AreEqual(AuthenticationStatus.Authenticated, jsonClient.AuthenticateViaGet(account.Realm, account.Account, account.Password).Status); Assert.AreNotEqual(AuthenticationStatus.Authenticated, jsonClient.AuthenticateViaGet(account.Realm + "x", account.Account, account.Password).Status); Assert.AreNotEqual(AuthenticationStatus.Authenticated, jsonClient.AuthenticateViaGet(account.Realm, account.Account + "x", account.Password).Status); Assert.AreNotEqual(AuthenticationStatus.Authenticated, jsonClient.AuthenticateViaGet(account.Realm, account.Account, account.Password + "x").Status); // Test using the JSON HTTP/POST Assert.AreEqual(AuthenticationStatus.Authenticated, jsonClient.AuthenticateViaPost(account.Realm, account.Account, account.Password).Status); Assert.AreNotEqual(AuthenticationStatus.Authenticated, jsonClient.AuthenticateViaPost(account.Realm + "x", account.Account, account.Password).Status); Assert.AreNotEqual(AuthenticationStatus.Authenticated, jsonClient.AuthenticateViaPost(account.Realm, account.Account + "x", account.Password).Status); Assert.AreNotEqual(AuthenticationStatus.Authenticated, jsonClient.AuthenticateViaPost(account.Realm, account.Account, account.Password + "x").Status); // Test using the WCF client proxy Assert.AreEqual(AuthenticationStatus.Authenticated, wcfClient.Authenticate(account.Realm, account.Account, account.Password).Status); Assert.AreNotEqual(AuthenticationStatus.Authenticated, wcfClient.Authenticate(account.Realm + "x", account.Account, account.Password).Status); Assert.AreNotEqual(AuthenticationStatus.Authenticated, wcfClient.Authenticate(account.Realm, account.Account + "x", account.Password).Status); Assert.AreNotEqual(AuthenticationStatus.Authenticated, wcfClient.Authenticate(account.Realm, account.Account, account.Password + "x").Status); } } finally { if (authenticator != null) { authenticator.Close(); } if (router != null) { router.Stop(); } // Restore Realms.txt. if (orgRealms != null) { writer = new StreamWriter(realmsPath, false, Helper.AnsiEncoding); writer.Write(orgRealms); writer.Close(); } if (wcfClient != null && wcfClient.State == CommunicationState.Opened) { wcfClient.Close(); } if (svcProcess != null) { svcProcess.Kill(); svcProcess.Close(); } if (state != null) { state.Cleanup(); } Config.SetConfig(null); } }
public void BasicTopology_ParallelQuery() { LeafRouter router = null; LeafRouterA[] serverA = null; LeafRouterB[] serverB = null; BasicTopology clusterA = null; BasicTopology clusterB = null; ParallelQuery parallelQuery; try { // Crank up the service instances serverA = new LeafRouterA[3]; serverA[0] = CreateLeafA("detached", "hub", Helper.NewGuid().ToString(), group, dynACounts, 0); serverA[1] = CreateLeafA("detached", "hub", Helper.NewGuid().ToString(), group, dynACounts, 1); serverA[2] = CreateLeafA("detached", "hub", Helper.NewGuid().ToString(), group, dynACounts, 2); serverB = new LeafRouterB[3]; serverB[0] = CreateLeafB("detached", "hub", Helper.NewGuid().ToString(), group, dynBCounts, 0); serverB[1] = CreateLeafB("detached", "hub", Helper.NewGuid().ToString(), group, dynBCounts, 1); serverB[2] = CreateLeafB("detached", "hub", Helper.NewGuid().ToString(), group, dynBCounts, 2); // Create the client and its cluster instances router = CreateLeaf("detached", "hub", Helper.NewGuid().ToString(), group); // Initialize the client clusters clusterA = new BasicTopology(); clusterA.OpenClient(router, "logical://A", null); clusterB = new BasicTopology(); clusterB.OpenClient(router, "logical://B", null); // Delay a bit to allow for endpoint discovery Thread.Sleep(InitDelay); // Make sure that the message handler endpoints were dynamically modified Clear(); parallelQuery = new ParallelQuery(); parallelQuery.Operations.Add(new ParallelOperation(new BlobPropertyMsg())); parallelQuery.Operations.Add(new ParallelOperation(new BlobPropertyMsg())); parallelQuery = clusterA.ParallelQuery(null, parallelQuery); foreach (var operation in parallelQuery.Operations) { Assert.AreEqual("A", ((PropertyMsg)operation.ReplyMsg)["value"]); } Assert.AreEqual(2, dynACounts[0] + dynACounts[1] + dynACounts[2]); Assert.AreEqual(0, dynBCounts[0] + dynBCounts[1] + dynBCounts[2]); Clear(); parallelQuery = new ParallelQuery(); parallelQuery.Operations.Add(new ParallelOperation(new BlobPropertyMsg())); parallelQuery.Operations.Add(new ParallelOperation(new BlobPropertyMsg())); parallelQuery = clusterB.ParallelQuery(null, parallelQuery); foreach (var operation in parallelQuery.Operations) { Assert.AreEqual("B", ((PropertyMsg)operation.ReplyMsg)["value"]); } Assert.AreEqual(0, dynACounts[0] + dynACounts[1] + dynACounts[2]); Assert.AreEqual(2, dynBCounts[0] + dynBCounts[1] + dynBCounts[2]); } finally { if (serverA != null) { for (int i = 0; i < serverA.Length; i++) { if (serverA[i] != null) { serverA[i].Stop(); } } } if (serverB != null) { for (int i = 0; i < serverB.Length; i++) { if (serverB[i] != null) { serverB[i].Stop(); } } } if (clusterA != null) { clusterA.Close(); } if (clusterB != null) { clusterB.Close(); } if (router != null) { router.Stop(); } Config.SetConfig(null); } }
public void BasicTopology_Query() { LeafRouter router = null; LeafRouterA[] serverA = null; LeafRouterB[] serverB = null; BasicTopology clusterA = null; BasicTopology clusterB = null; PropertyMsg reply; try { // Crank up the service instances serverA = new LeafRouterA[3]; serverA[0] = CreateLeafA("detached", "hub", Helper.NewGuid().ToString(), group, dynACounts, 0); serverA[1] = CreateLeafA("detached", "hub", Helper.NewGuid().ToString(), group, dynACounts, 1); serverA[2] = CreateLeafA("detached", "hub", Helper.NewGuid().ToString(), group, dynACounts, 2); serverB = new LeafRouterB[3]; serverB[0] = CreateLeafB("detached", "hub", Helper.NewGuid().ToString(), group, dynBCounts, 0); serverB[1] = CreateLeafB("detached", "hub", Helper.NewGuid().ToString(), group, dynBCounts, 1); serverB[2] = CreateLeafB("detached", "hub", Helper.NewGuid().ToString(), group, dynBCounts, 2); // Create the client and its cluster instances router = CreateLeaf("detached", "hub", Helper.NewGuid().ToString(), group); // Initialize the client clusters clusterA = new BasicTopology(); clusterA.OpenClient(router, "logical://A", null); clusterB = new BasicTopology(); clusterB.OpenClient(router, "logical://B", null); // Delay a bit to allow for endpoint discovery Thread.Sleep(InitDelay); // Make sure that the message handler endpoints were dynamically modified Clear(); reply = (PropertyMsg)clusterA.Query(null, new BlobPropertyMsg()); Assert.AreEqual("A", reply["value"]); Assert.AreEqual(1, dynACounts[0] + dynACounts[1] + dynACounts[2]); Assert.AreEqual(0, dynBCounts[0] + dynBCounts[1] + dynBCounts[2]); Clear(); reply = (PropertyMsg)clusterB.Query(null, new BlobPropertyMsg()); Assert.AreEqual("B", reply["value"]); Assert.AreEqual(0, dynACounts[0] + dynACounts[1] + dynACounts[2]); Assert.AreEqual(1, dynBCounts[0] + dynBCounts[1] + dynBCounts[2]); // Verify that load balancing works Clear(); for (int i = 0; i < 100; i++) { reply = (PropertyMsg)clusterA.Query(null, new BlobPropertyMsg()); Assert.AreEqual("A", reply["value"]); } Thread.Sleep(2000); Assert.AreEqual(0, dynBCounts[0] + dynBCounts[1] + dynBCounts[2]); Assert.AreEqual(100, dynACounts[0] + dynACounts[1] + dynACounts[2]); Assert.IsTrue(dynACounts[0] > 0); Assert.IsTrue(dynACounts[1] > 0); Assert.IsTrue(dynACounts[2] > 0); } finally { if (serverA != null) { for (int i = 0; i < serverA.Length; i++) { if (serverA[i] != null) { serverA[i].Stop(); } } } if (serverB != null) { for (int i = 0; i < serverB.Length; i++) { if (serverB[i] != null) { serverB[i].Stop(); } } } if (clusterA != null) { clusterA.Close(); } if (clusterB != null) { clusterB.Close(); } if (router != null) { router.Stop(); } Config.SetConfig(null); } }
public void BasicTopology_Broadcast() { LeafRouter router = null; LeafRouterA[] serverA = null; LeafRouterB[] serverB = null; BasicTopology clusterA = null; BasicTopology clusterB = null; try { // Crank up the service instances serverA = new LeafRouterA[3]; serverA[0] = CreateLeafA("detached", "hub", Helper.NewGuid().ToString(), group, dynACounts, 0); serverA[1] = CreateLeafA("detached", "hub", Helper.NewGuid().ToString(), group, dynACounts, 1); serverA[2] = CreateLeafA("detached", "hub", Helper.NewGuid().ToString(), group, dynACounts, 2); serverB = new LeafRouterB[3]; serverB[0] = CreateLeafB("detached", "hub", Helper.NewGuid().ToString(), group, dynBCounts, 0); serverB[1] = CreateLeafB("detached", "hub", Helper.NewGuid().ToString(), group, dynBCounts, 1); serverB[2] = CreateLeafB("detached", "hub", Helper.NewGuid().ToString(), group, dynBCounts, 2); // Create the client and its cluster instances router = CreateLeaf("detached", "hub", Helper.NewGuid().ToString(), group); // Initialize the client clusters clusterA = new BasicTopology(); clusterA.OpenClient(router, "logical://A", null); clusterB = new BasicTopology(); clusterB.OpenClient(router, "logical://B", null); // Delay a bit to allow for endpoint discovery Thread.Sleep(InitDelay); // Verify that broadcasting works Clear(); clusterA.Broadcast(null, new PropertyMsg()); Thread.Sleep(1000); Assert.AreEqual(3, dynACounts[0] + dynACounts[1] + dynACounts[2]); Assert.AreEqual(0, dynBCounts[0] + dynBCounts[1] + dynBCounts[2]); Clear(); clusterB.Broadcast(null, new PropertyMsg()); Thread.Sleep(1000); Assert.AreEqual(0, dynACounts[0] + dynACounts[1] + dynACounts[2]); Assert.AreEqual(3, dynBCounts[0] + dynBCounts[1] + dynBCounts[2]); } finally { if (serverA != null) { for (int i = 0; i < serverA.Length; i++) { if (serverA[i] != null) { serverA[i].Stop(); } } } if (serverB != null) { for (int i = 0; i < serverB.Length; i++) { if (serverB[i] != null) { serverB[i].Stop(); } } } if (clusterA != null) { clusterA.Close(); } if (clusterB != null) { clusterB.Close(); } if (router != null) { router.Stop(); } Config.SetConfig(null); } }
public void Initialize() { //NetTrace.Start(); //NetTrace.Enable(MsgRouter.TraceSubsystem,255); //NetTrace.Enable(ReliableTransferSession.TraceSubsystem,255); //NetTrace.Enable(ClusterMember.TraceSubsystem,255); const string settings = @" §ion MsgRouter AppName = Test AppDescription = Message Queuing RouterEP = physical://DETACHED/Test/$(Guid) CloudEP = $(LillTek.DC.CloudEP) CloudAdapter = ANY UdpEP = ANY:0 TcpEP = ANY:0 TcpBacklog = 100 TcpDelay = off BkInterval = 1s MaxIdle = 5m AdvertiseTime = 1m DefMsgTTL = 5 SharedKey = PLAINTEXT IV = 00 SessionCacheTime = 2m SessionRetries = 3 SessionTimeout = 10s &endsection §ion MsgQueueClient BaseEP = logical://Test/Queues/MyQueue Timeout = infinite MessageTTL = 0s Compress = BEST &endsection §ion MsgQueueEngine PersistTo = FILE Folder = {0} LogTo = DISK LogFolder = $(AppPath)\Messages\Log QueueMap[0] = logical://LillTek/DataCenter/MsgQueue FlushInterval = 5m DeadLetterTTL = 7d MaxDeliveryAttempts = 3 KeepAliveInterval = 30s SessionTimeout = 90s PendingCheckInterval = 60s BkTaskInterval = 1s &endsection "; Config.SetConfig(string.Format(settings.Replace('&', '#'), tempFolder)); router = new LeafRouter(); router.Start(); }
/// <summary> /// Starts the service, associating it with an <see cref="IServiceHost" /> instance. /// </summary> /// <param name="serviceHost">The service user interface.</param> /// <param name="args">Command line arguments.</param> public void Start(IServiceHost serviceHost, string[] args) { lock (syncLock) { if (router != null) { return; // Already started } // Global initialization startTime = DateTime.UtcNow; NetTrace.Start(); CoreApp.InstallPerfCounters(); // Service initialization this.serviceHost = serviceHost; try { SysLog.LogInformation("NeonSwitch v{0} Start", Helper.GetVersionString()); router = new LeafRouter(); router.Start(); state = ServiceState.Running; bkTimer = new GatedTimer(OnBkTimer, null, CoreApp.BkTaskInterval); SpeechEngine.Start(SpeechEngineSettings.LoadConfig("NeonSwitch.Speech")); #if DEBUG // $todo(jeff.lill): Delete this. SwitchTest.Test(); #endif // Indicate that the switch core service is open for business. NeonSwitch // application instance loaders will spin, waiting for this to be set before // calling the application's main function. Switch.SetGlobal(SwitchGlobal.NeonSwitchReady, "true"); } catch (Exception e) { SpeechEngine.Stop(); if (bkTimer != null) { bkTimer.Dispose(); bkTimer = null; } if (router != null) { router.Stop(); router = null; } SysLog.LogException(e); throw; } } }