//--------------------------------------------------------------------- // Static members /// <summary> /// Reads the GeoTracker server settings from the application's configuration /// using the specified key prefix. /// </summary> /// <param name="keyPrefix">The application configuration key prefix.</param> /// <returns>The server settings.</returns> /// <remarks> /// <para> /// The GeoTracker server settings are loaded from the application /// configuration, using the specified key prefix. The following /// settings are recognized by the class: /// </para> /// <div class="tablediv"> /// <table class="dtTABLE" cellspacing="0" ID="Table1"> /// <tr valign="top"> /// <th width="1">Setting</th> /// <th width="1">Default</th> /// <th width="90%">Description</th> /// </tr> /// <tr valign="top"> /// <td>ServerEP</td> /// <td><b>logical://LillTek/GeoTracker/Server</b></td> /// <td> /// The external LillTek Messaging endpoint for the GeoTracker server cluster. /// This is the endpoint that <see cref="GeoTrackerClient" /> instances will /// use to communicate with the cluster. /// </td> /// </tr> /// <tr valign="top"> /// <td>ClusterEP</td> /// <td><b>logical://LillTek/GeoTracker/Cluster</b></td> /// <td> /// The internal LillTek Messaging endpoint for the root of the GeoTracker server cluster. /// This is the endpoint that cluster servers will use to communicate with each other. /// </td> /// </tr> /// <tr valign="top"> /// <td>ClusterTopology</td> /// <td><see cref="DynamicHashedTopology"/></td> /// <td> /// Describes the topology provider to be used to distribute traffic to /// GeoTracker server instances within the cluster. This provide must /// implement <see cref="TopologyCapability" />.<see cref="TopologyCapability.Locality" />. /// </td> /// </tr> /// <tr valign="top"> /// <td>ClusterArgs</td> /// <td>None</td> /// <td> /// Cluster topology specific parameters formatted as <b>name=value</b> pairs separated /// by LF ('\n') characters. Use the <see cref="Config" /> "{{" ... ""}}" setting syntax /// and place each argument on a separate line in the config file. /// </td> /// </tr> /// <tr valign="top"> /// <td>GeoFixArchiver</td> /// <td><see cref="NullGeoFixArchiver"/></td> /// <td> /// The pluggable <see cref="IGeoFixArchiver" /> type to be used to archive /// <see cref="GeoFix" />es received by the server. /// </td> /// </tr> /// <tr valign="top"> /// <td>GeoFixArchiverArgs</td> /// <td>Empty</td> /// <td> /// Archiver specific parameters formatted as <b>name=value</b> pairs separated /// by LF ('\n') characters. Use the <see cref="Config" /> "{{" ... ""}}" setting syntax /// and place each argument on a separate line in the config file. /// </td> /// </tr> /// <tr valign="top"> /// <td>GeoFixRetentionInterval</td> /// <td>1h</td> /// <td> /// The length of time entity <see cref="GeoFix" />es will be retained by GeoTracker. /// </td> /// </tr> /// <tr valign="top"> /// <td>GeoFixPurgeInterval</td> /// <td>1m</td> /// <td> /// The interval at which old cached entity <see cref="GeoFix" />es will be purged. /// </td> /// </tr> /// <tr valign="top"> /// <td>MaxEntityGeoFixes</td> /// <td>50</td> /// <td> /// The maximum number of <see cref="GeoFix" />es to be cached in memory for an entity. /// </td> /// </tr> /// <tr valign="top"> /// <td>IndexHighWatermarkLimit</td> /// <td>1000</td> /// <td> /// <para> /// Used to decide when to attempt split an index block into sub-blocks when the number /// of entities in a block is greater than or equal to this value. /// </para> /// <note> /// <b>IndexHighWatermarkLimit</b> must be greater than or equal to <b>IndexLowWatermarkLimit</b>. /// </note> /// </td> /// </tr> /// <tr valign="top"> /// <td>IndexLowWatermarkLimit</td> /// <td>750</td> /// <td> /// <para> /// Used to decide when to attempt coalesce sub-blocks when the number /// of entities in a block is greater than or equal to this value. /// </para> /// <note> /// <b>IndexHighWatermarkLimit</b> must be greater than or equal to <b>IndexLowWatermarkLimit</b>. /// </note> /// </td> /// </tr> /// <tr valign="top"> /// <td>IndexMaxGroupTableLevel</td> /// <td>2</td> /// <td> /// Controls how deep into the index heirarchy group hash tables will be maintained by /// the GeoTracker server. Enabling these tables deeper in the heirarchy may result in better /// performance for queries with group constraints but potentially at the cost of /// severe memory utilizaton. /// </td> /// </tr> /// <tr> /// <td>IndexBalancingInterval</td> /// <td>5m</td> /// <td> /// The interval at which the server will attempt to rebalance the location index. /// </td> /// </tr> /// <tr valign="top"> /// <td>IPGeocodeEnabled</td> /// <td><c>true</c></td> /// <td> /// Controls whether IP geocoding services are to be made available by the GeoTracker server. /// </td> /// </tr> /// <tr valign="top"> /// <td>IPGeocodeSourceUri</td> /// <td><b>see note</b></td> /// <td> /// The URL where the current IP to location Geocoding database from <a href="http://maxmind.com">maxmind.com</a> /// can be downloaded. This must be a decompressed GeoIP City or GeoLite City database file encrypted /// into a <see cref="SecureFile" />. This setting defaults to: http://www.lilltek.com/Config/GeoTracker/IP2City.encrypted.dat /// </td> /// </tr> /// <tr valign="top"> /// <td>IPGeocodeSourceRsaKey</td> /// <td><b>See note</b></td> /// <td> /// The private RSA key used to decrypt the downloaded Geocoding database. (defaults to /// the value used to manually encrypt the file hosted on http://www.lilltek.com). /// </td> /// </tr> /// <tr valign="top"> /// <td>IPGeocodeSourcePollInterval</td> /// <td><b>1d</b></td> /// <td> /// The interval at which server instances will poll for updates to the IP Geocode database, /// Note that server will use the HTTP <b>If-Modified-Since</b> header for efficency since this /// database is updated only once a month. /// </td> /// </tr> /// <tr valign="top"> /// <td>IPGeocodeSourceTimeout</td> /// <td><b>5m</b></td> /// <td> /// The maximum time the server will wait for the download of the IP Geocode database file. /// </td> /// </tr> /// <tr valign="top"> /// <td>SweepInterval</td> /// <td><b>2.5m</b></td> /// <td> /// The interval at which old <see cref="GeoFix" />es, entities, and groups will be /// swept up and discarded by the server. /// </td> /// </tr> /// <tr valign="top"> /// <td>BkInterval</td> /// <td><b>1s</b></td> /// <td> /// The minimum interval at which background activities will be scheduled. /// </td> /// </tr> /// </table> /// </div> /// </remarks> public static GeoTrackerServerSettings LoadConfig(string keyPrefix) { var config = new Config(keyPrefix); var settings = new GeoTrackerServerSettings(); settings.ServerEP = config.Get("ServerEP", settings.ServerEP); settings.ClusterEP = config.Get("ClusterEP", settings.ClusterEP); settings.ClusterTopology = config.Get("ClusterTopology", settings.ClusterTopology); settings.ClusterArgs = new ArgCollection(config.Get("ClusterArgs", settings.ClusterArgs.ToString()), '=', '\n'); settings.GeoFixArchiver = config.Get("GeoFixArchiver", settings.GeoFixArchiver); settings.GeoFixArchiverArgs = ArgCollection.Parse(config.Get("GeoFixArchiverArgs", settings.GeoFixArchiverArgs.ToString()), '=', '\n'); settings.GeoFixRetentionInterval = config.Get("GeoFixRetentionInterval", settings.GeoFixRetentionInterval); settings.GeoFixPurgeInterval = config.Get("GeoFixPurgeInterval", settings.GeoFixPurgeInterval); settings.MaxEntityGeoFixes = config.Get("MaxEntityGeoFixes", settings.MaxEntityGeoFixes); settings.IndexHighWatermarkLimit = config.Get("IndexHighWatermarkLimit", settings.IndexHighWatermarkLimit); settings.IndexLowWatermarkLimit = config.Get("IndexLowWatermarkLimit", settings.IndexLowWatermarkLimit); settings.IndexMaxGroupTableLevel = config.Get("IndexMaxGroupTableLevel", settings.IndexMaxGroupTableLevel); settings.IndexBalancingInterval = config.Get("IndexBalancingInterval", settings.IndexBalancingInterval); settings.IPGeocodeEnabled = config.Get("IPGeocodeEnabled", settings.IPGeocodeEnabled); settings.IPGeocodeSourceUri = config.Get("IPGeocodeSourceUri", settings.IPGeocodeSourceUri); settings.IPGeocodeSourceRsaKey = config.Get("IPGeocodeSourceRsaKey", settings.IPGeocodeSourceRsaKey); settings.IPGeocodeSourcePollInterval = config.Get("IPGeocodeSourcePollInterval", settings.IPGeocodeSourcePollInterval); settings.IPGeocodeSourceTimeout = config.Get("IPGeocodeSourceTimeout", settings.IPGeocodeSourceTimeout); settings.SweepInterval = config.Get("SweepInterval", settings.SweepInterval); settings.BkInterval = config.Get("BkInterval", settings.BkInterval); return(settings); }
/// <summary> /// Loads any override settings from a <see cref="ArgCollection" />. /// </summary> /// <param name="args">The override settings.</param> public void LoadCustom(ArgCollection args) { this.DefBlockSize = args.Get("DefBlockSize", this.DefBlockSize); this.MaxBlockSize = args.Get("MaxBlockSize", this.MaxBlockSize); this.RetryWaitTime = args.Get("RetryWaitTime", this.RetryWaitTime); this.MaxTries = args.Get("MaxTries", this.MaxTries); }
/// <summary> /// Verifies request arguments against a signature using a shared <see cref="SymmetricKey" /> /// and the current time. /// </summary> /// <param name="sharedKey">The shared <see cref="SymmetricKey" />.</param> /// <param name="signature">The base-64 encoded signature.</param> /// <param name="args">The request argument collection.</param> /// <param name="signatureKey"> /// The name of the signature key within the event arguments or <c>null</c> /// if the signature is not present. /// </param> /// <param name="graceInterval">Specifies the time period used for verifying the signature request time.</param> /// <exception cref="SecurityException">Thrown if the signature could not be verified.</exception> /// <remarks> /// <para> /// <paramref name="graceInterval" /> is used when comparing the request time (UTC) embedded /// in the signature with the current machine time (UTC). Request times within the range of: /// </para> /// <code language="none"> /// DateTime.UtcNow - graceInterval <= requestTime <= DateTime.UtcNow + graceInterval /// </code> /// <para> /// will be considered to be valid. Request times outside this range will be invalid. /// Larger grace intervals provide help avoid the problems of incorrect system times or /// long request delivery delays but at the price of the increased exposure to replay /// attacks. /// </para> /// <note> /// If the signature is present in the arguments, then the <paramref name="signatureKey" /> <b>must</b> /// be passed as its name or else the verification will always fail. The reason for this is /// that the hash was originally computed before the signature was added so the hash will be /// different if it includes the signature. /// </note> /// </remarks> public static void Verify(SymmetricKey sharedKey, string signature, ArgCollection args, string signatureKey, TimeSpan graceInterval) { if (!TryVerify(sharedKey, signature, args, signatureKey, graceInterval)) { throw new SecurityException("Access denied."); } }
/// <summary> /// Opens the topology instance in client mode. /// </summary> /// <param name="router">The message router to be used by the cluster.</param> /// <param name="clusterEP">The cluster's logical endpoint.</param> /// <param name="args">Topology implementation specific parameters (ignored for this implementation).</param> /// <remarks> /// </remarks> public virtual void OpenClient(MsgRouter router, MsgEP clusterEP, ArgCollection args) { if (!clusterEP.IsLogical) { throw new ArgumentException(TopologyHelper.ClusterEPNotLogicalMsg); } if (!router.EnableP2P) { SysLog.LogWarning(NoP2PMsg); } this.router = router; this.instanceID = Helper.NewGuid(); this.clusterEP = clusterEP; this.broadcastEP = new MsgEP(clusterEP, "*"); this.instanceEP = null; this.isClient = true; ArgCollection argsCopy; argsCopy = args.Clone(); argsCopy["topology-type"] = TopologyHelper.SerializeType(this.GetType()); serialized = argsCopy.ToString(); OnLogicalChange(); // Forces the initial load of the instance EPs }
static HlaAssignMain CreateProgramFromArguments(string[] args) { ArgCollection argCollection = ArgCollection.GetInstance(args); if (argCollection.ExtractOptionalFlag("help")) { Console.WriteLine(); Console.WriteLine(UsageMessage); Console.WriteLine(HelpMessage); return(null); } bool bExcel = argCollection.ExtractOptionalFlag("EXCEL"); argCollection.CheckNoMoreOptions(); double?leakProbabilityOrNull = argCollection.ExtractNext <double?>("leakProbabilityOrNull"); double pValue = argCollection.ExtractNext <double>("pValue"); string directoryName = argCollection.ExtractNext <string>("directory"); string caseName = argCollection.ExtractNext <string>("caseName"); string hlaFactoryName = argCollection.ExtractNext <string>("hlaFactory"); RangeCollection pieceIndexRange = argCollection.ExtractNext <RangeCollection>("pieceIndexRange"); int pieceCount = argCollection.ExtractNext <int>("pieceCount"); SpecialFunctions.CheckCondition(0 <= pieceIndexRange.FirstElement && pieceIndexRange.LastElement < pieceCount, "The pieceIndexRange must be a subrange of " + RangeCollection.GetInstance(0, pieceCount - 1).ToString()); RangeCollection nullIndexRange = argCollection.ExtractNext <RangeCollection>("nullIndexRange"); argCollection.CheckThatEmpty(); return(new HlaAssignMain(bExcel, leakProbabilityOrNull, pValue, directoryName, caseName, hlaFactoryName, pieceIndexRange, pieceCount, nullIndexRange)); }
/// <summary> /// Instantiates and initializes an <see cref="IReliableMessenger" /> plug-in defined by a configuration setting /// and then opens it as a server side messenger. /// </summary> /// <param name="router">The message router to associate with the messenger.</param> /// <param name="argsKey">The fully qualified configuration key specifying the messenger arguments formatted for <see cref="ArgCollection" />.</param> /// <returns>The messenger instance.</returns> /// <remarks> /// <para> /// The messenger arguments must include an argument named <b>messenger-type</b> which must be /// a reference to a <see cref="IReliableMessenger" /> implementation formatted as described /// in <see cref="Config.Parse(string,System.Type)" />. /// </para> /// <para> /// This utility method maps the messenger type reference to a .NET assembly and type and then /// instantiates an instance and then opens it as a client side messenger. The arguments loaded /// are then passed to the messenger's <see cref="IReliableMessenger.OpenServer" /> method. /// </para> /// </remarks> public static IReliableMessenger OpenServer(MsgRouter router, string argsKey) { IReliableMessenger messenger; ArgCollection args; string messengerType; System.Type type; if (!router.IsOpen) { throw new InvalidOperationException(RouterClosedMsg); } args = ArgCollection.Parse(Config.Global.Get(argsKey)); messengerType = args["messenger-type"]; if (messengerType == null) { throw new ArgumentException("Messenger arguments must specify [messenger-type]."); } type = Config.Parse(messengerType, (System.Type)null); if (type == null || !typeof(IReliableMessenger).IsAssignableFrom(type)) { throw new ArgumentException(string.Format("Unable to map setting [{0}] into an IReliableMessenger.", messengerType)); } messenger = Helper.CreateInstance <IReliableMessenger>(type); messenger.OpenServer(router, args); return(messenger); }
public void OnMsg(ReliableTransferMsg msg) { if (netFail) { return; } StreamTransferSession session; ArgCollection args; AppRef appRef; AppPackageInfo packageInfo; string path; args = ArgCollection.Parse(msg.Args); appRef = AppRef.Parse(args["appref"]); if (msg.Direction == TransferDirection.Upload) { path = packageFolder.BeginTransit(appRef); session = StreamTransferSession.ServerUpload(router, msg, path); session.BeginTransfer(onTransfer, new TransferInfo(session, path, msg.Direction)); } else { packageInfo = packageFolder.GetPackageInfo(appRef); if (packageInfo == null) { throw SessionException.Create(null, "Package [{0}] cannot be found.", appRef); } path = packageInfo.FullPath; session = StreamTransferSession.ServerDownload(router, msg, path); session.BeginTransfer(onTransfer, new TransferInfo(session, path, msg.Direction)); } }
/// <summary> /// Initalizes the fix archiver instance. /// </summary> /// <param name="node">The parent <see cref="GeoTrackerNode" /> instance.</param> /// <param name="args"> /// This implementation's settings come directly from the application /// configuration as described below. /// </param> /// <remarks> /// <note> /// <para> /// Note that some of the application log settings are loaded directly from the application's <b>LillTek.AppLog</b> /// configuration settings section as described in <see cref="AppLog" />. The valid arguments passed to the /// <see cref="Start" /> are: /// </para> /// <list type="table"> /// <item> /// <term><b>LogName</b></term> /// <description> /// The name of the application log. This defaults to <b>GeoTrackerFixes</b>. /// </description> /// </item> /// <item> /// <term><b>MaxSize</b></term> /// <description> /// The approximate maximum size of the log on disk or zero for no limit. /// This defaults to <b>5GB</b>. /// </description> /// </item> /// <item> /// <term><b>PurgeInterval</b></term> /// <description> /// The interval at which the log will purge old log files so that the /// total log size remains within the <b>MaxSize</b> limit. /// This defaults to <b>5 minutes</b>. /// </description> /// </item> /// </list> /// <see cref="IGeoFixArchiver" /> implementations must silently handle any internal /// error conditions. <see cref="GeoTrackerNode" /> does not expect to see any /// exceptions raised from calls to any of these methods. Implementations should /// catch any exceptions thrown internally and log errors or warnings as necessary. /// </note> /// </remarks> public void Start(GeoTrackerNode node, ArgCollection args) { lock (syncLock) { try { if (this.logWriter != null) { throw new InvalidOperationException("AppLogGeoFixArchiver: Archiver has already been started."); } if (this.isStopped) { throw new InvalidOperationException("AppLogGeoFixArchiver: Cannot restart a stopped archiver."); } this.node = node; this.logName = args.Get("LogName", "GeoTrackerFixes"); this.maxSize = args.Get("MaxSize", 5L * 1024L * 1024L * 1024L); this.purgeInterval = args.Get("PurgeInterval", TimeSpan.FromMinutes(5)); this.logWriter = new AppLogWriter(logName, SchemaName, SchemaVersion, maxSize); this.logWriter.PurgeInterval = purgeInterval; } catch (Exception e) { SysLog.LogException(e); } } }
/// <summary> /// Parses and authentication result from a string. /// </summary> /// <param name="input"> /// The serialized result (see <see cref="ToString" /> for a description /// of the format. /// </param> /// <returns>The parsed result.</returns> /// <exception cref="FormatException">Thrown if the input is improperly formatted.</exception> public static AuthenticationResult Parse(string input) { var args = new ArgCollection(input, '=', '\t'); return(new AuthenticationResult(args.Get <AuthenticationStatus>("Status", AuthenticationStatus.AccessDenied), args.Get("Message", string.Empty), args.Get("MaxCacheTime", TimeSpan.FromMinutes(5)))); }
public void ArgCollection_Parsing() { var ps = new ArgCollection(@" bool=yes; int=-10; timespan=10m; double=123.45; guid={28676DD2-1C0F-4217-96DF-1714A7B3BEFA}; ip=192.168.1.1; ep=192.168.1.2:80; enum0=zero; enum1=One; enum2=TWO; enum3=xxx; uri=http://www.lilltek.com/; type=" + this.GetType().FullName + ":" + GetType().Assembly.Location); Assert.AreEqual(true, ps.Get("bool", false)); Assert.AreEqual(-10, ps.Get("int", 0)); Assert.AreEqual(TimeSpan.FromMinutes(10), ps.Get("timespan", TimeSpan.Zero)); Assert.AreEqual(123.45, ps.Get("double", 0.0)); Assert.AreEqual(IPAddress.Parse("192.168.1.1"), ps.Get("ip", IPAddress.Any)); Assert.AreEqual(new Guid("{28676DD2-1C0F-4217-96DF-1714A7B3BEFA}"), ps.Get("guid", Guid.Empty)); Assert.IsTrue(new NetworkBinding(IPAddress.Parse("192.168.1.2"), 80).Equals(ps.Get("ep", new IPEndPoint(IPAddress.Any, 0)))); Assert.IsTrue(object.ReferenceEquals(this.GetType(), ps.Get("type", typeof(int)))); Assert.AreEqual(TestEnum.Zero, ps.Get <TestEnum>("enum0", TestEnum.Unknown)); Assert.AreEqual(TestEnum.One, ps.Get <TestEnum>("enum1", TestEnum.Unknown)); Assert.AreEqual(TestEnum.Two, ps.Get <TestEnum>("enum2", TestEnum.Unknown)); Assert.AreEqual(TestEnum.Unknown, ps.Get <TestEnum>("enum3", TestEnum.Unknown)); Assert.AreEqual(new Uri("http://www.lilltek.com/"), ps.Get("uri", (Uri)null)); DateTime now = Helper.UtcNowRounded; ps.Clear(); ps.Set("bool", true); ps.Set("int", -10); ps.Set("timespan", TimeSpan.FromMinutes(10)); ps.Set("date", now); ps.Set("double", 123.45); ps.Set("ip", IPAddress.Parse("192.168.1.1")); ps.Set("guid", new Guid("{28676DD2-1C0F-4217-96DF-1714A7B3BEFA}")); ps.Set("ep", new NetworkBinding(IPAddress.Parse("192.168.1.2"), 80)); ps.Set("long", 1024L * 1024L * 1024L * 1024L); ps.Set("uri", new Uri("http://www.lilltek.com/test.htm")); Assert.AreEqual(true, ps.Get("bool", false)); Assert.AreEqual(-10, ps.Get("int", 0)); Assert.AreEqual(TimeSpan.FromMinutes(10), ps.Get("timespan", TimeSpan.Zero)); Assert.AreEqual(now, ps.Get("date", DateTime.MinValue)); Assert.AreEqual(123.45, ps.Get("double", 0.0)); Assert.AreEqual(IPAddress.Parse("192.168.1.1"), ps.Get("ip", IPAddress.Any)); Assert.AreEqual(new Guid("{28676DD2-1C0F-4217-96DF-1714A7B3BEFA}"), ps.Get("guid", Guid.Empty)); Assert.IsTrue(new NetworkBinding(IPAddress.Parse("192.168.1.2"), 80).Equals(ps.Get("ep", new IPEndPoint(IPAddress.Any, 0)))); Assert.AreEqual(Serialize.Parse("1T", 0L), ps.Get("long", -1L)); Assert.AreEqual(new Uri("http://www.lilltek.com/test.htm"), ps.Get("uri", (Uri)null)); }
public void ArgCollection_SetNull() { var ps = new ArgCollection(); ps.Set("hello", "test"); ps.Set("hello", (string)null); Assert.IsNull(ps.Get("hello")); Assert.AreEqual("world", ps.Get("hello", "world")); }
/// <summary> /// Serializes the result to a string. /// </summary> /// <returns>The serialized string.</returns> /// <remarks> /// The result is formatted as a <see cref="ArgCollection" /> using TABs as /// separator characters. /// </remarks> public override string ToString() { var args = new ArgCollection('=', '\t'); args.Set("Status", this.Status.ToString()); args.Set("Message", this.Message); args.Set("MaxCacheTime", this.MaxCacheTime); return(args.ToString()); }
/// <summary> /// Copies the fields from the attribute instance passed to this instance. /// </summary> /// <param name="attr">The [MsgSession] attribute instance.</param> public SessionHandlerInfo(MsgSessionAttribute attr) { this.Idempotent = attr.Idempotent; this.KeepAliveTime = attr.KeepAliveTime; this.IsAsync = attr.IsAsync; this.MaxAsyncKeepAliveTime = attr.MaxAsyncKeepAliveTime; this.SessionTimeoutTime = attr.SessionTimeoutTime; this.SessionType = attr.SessionType; this.Parameters = ArgCollection.Parse(attr.Parameters); }
/// <summary> /// Initializes the instance with default session properties. /// </summary> public SessionHandlerInfo() { this.Idempotent = false; this.KeepAliveTime = TimeSpan.FromMinutes(2); this.IsAsync = false; this.MaxAsyncKeepAliveTime = TimeSpan.MaxValue; this.SessionTimeoutTime = TimeSpan.FromTicks(this.KeepAliveTime.Ticks * 2); this.SessionType = null; this.Parameters = new ArgCollection(); }
public void ArgCollection_Malformed() { ArgCollection ps; ps = ArgCollection.Parse(";a=1;;b=2; ; c = 3"); Assert.AreEqual("1", ps["a"]); Assert.AreEqual("2", ps["b"]); Assert.AreEqual("3", ps["c"]); Assert.AreEqual(3, ps.Count); }
/// <summary> /// Extends <see cref="ArgCollection" /> by adding a method to retrieve an encrypted string value. /// </summary> /// <param name="args">The current collection.</param> /// <param name="name">The argument name.</param> /// <param name="key">The symmetric encryption key.</param> /// <returns>The decrypted value.</returns> public static string GetEncrypted(this ArgCollection args, string name, SymmetricKey key) { var encrypted = args.Get(name, (byte[])null); if (encrypted == null) { return(null); } return(Crypto.DecryptStringWithSalt8(encrypted, key)); }
public void Extensions_ArgCollection_Encryption() { // Verify that encrypted settings work. var key = new SymmetricKey("aes:RTML47oOp7OoRVDyJLwJOWNaAQRbwGgAU5skz3d6L9A=:hWpp+NJrWNCPkS3H89dINA=="); var args = new ArgCollection(ArgCollectionType.Unconstrained); args.SetEncrypted("test", "Hello World!", key); Assert.AreEqual("Hello World!", args.GetEncrypted("test", key)); Assert.AreNotEqual("Hello World!", args.Get("test")); }
/// <summary> /// Extends <see cref="ArgCollection" /> by adding a method to set an encrypted string value. /// </summary> /// <param name="args">The current collection.</param> /// <param name="name">The argument name.</param> /// <param name="value">The plain text value.</param> /// <param name="key">The symmetric encryption key.</param> public static void SetEncrypted(this ArgCollection args, string name, string value, SymmetricKey key) { if (value == null) { args.Set(name, (byte[])null); } else { args.Set(name, Crypto.EncryptStringWithSalt8(value, key)); } }
public void ArgCollection_Remove() { ArgCollection ps = new ArgCollection(); ps.Remove("Hello"); // Shouldn't barf if the key doesn't exist ps["Hello"] = "World!"; Assert.IsTrue(ps.ContainsKey("Hello")); ps.Remove("Hello"); Assert.IsFalse(ps.ContainsKey("Hello")); }
/// <summary> /// Generates a request signature using a shared <see cref="SymmetricKey" /> /// for request arguments as well as the current time. /// </summary> /// <param name="sharedKey">The shared <see cref="SymmetricKey" />.</param> /// <param name="args">The request argument collection.</param> /// <returns>The base-64 encoded signature.</returns> public static string Generate(SymmetricKey sharedKey, ArgCollection args) { using (var ms = new EnhancedMemoryStream(512)) { ms.WriteBytesNoLen(Crypto.GetSalt8()); ms.WriteInt32(Magic); ms.WriteInt64(DateTime.UtcNow.Ticks); ms.WriteBytesNoLen(ComputeHash(args, null)); return(Convert.ToBase64String(Crypto.Encrypt(ms.ToArray(), sharedKey))); } }
/// <summary> /// Instantiates and initializes an <see cref="IReliableMessenger" /> plug-in defined by a configuration setting /// and then opens it as a client side messenger. /// </summary> /// <param name="router">The message router to associate with the messenger.</param> /// <param name="argsKey">The fully qualified configuration key specifying the messenger arguments formatted for <see cref="ArgCollection" />.</param> /// <param name="confirmCallback">The callback for delivery confirmations or <c>null</c> to disable confirmations.</param> /// <returns>The messenger instance.</returns> /// <remarks> /// <para> /// The messenger arguments must include an argument named <b>messenger-type</b> which must be /// a reference to a <see cref="IReliableMessenger" /> implementation formatted as described /// in <see cref="Config.Parse(string,System.Type)" />. /// </para> /// <para> /// This utility method maps the messenger type reference to a .NET assembly and type and then /// instantiates an instance and then opens it as a client side messenger. The arguments loaded /// are then passed to the messenger's <see cref="IReliableMessenger.OpenClient" /> method. /// </para> /// <para> /// The optional <b>confirm-ep</b> argument may also be present in the arguments loaded from /// the configuration. If present, this specifies the logical endpoint where delivery confirmations /// are to be addressed. This is used internally by <see cref="IReliableMessenger" /> implementations /// for the server side of a messenger to send notifications back to a client side instance. /// </para> /// </remarks> public static IReliableMessenger OpenClient(MsgRouter router, string argsKey, DeliveryConfirmCallback confirmCallback) { IReliableMessenger messenger; ArgCollection args; string messengerType; string s; MsgEP confirmEP; System.Type type; if (!router.IsOpen) { throw new InvalidOperationException(RouterClosedMsg); } args = ArgCollection.Parse(Config.Global.Get(argsKey)); messengerType = args["messenger-type"]; if (messengerType == null) { throw new ArgumentException("Messenger arguments must specify [messenger-type]."); } type = Config.Parse(messengerType, (System.Type)null); if (type == null || !typeof(IReliableMessenger).IsAssignableFrom(type)) { throw new ArgumentException(string.Format("Unable to map setting [{0}] into an IReliableMessenger.", messengerType)); } s = args["confirm-ep"]; if (s != null) { try { confirmEP = MsgEP.Parse(s); } catch { throw new ArgumentException("[{0}] is not a valid endpoint for [confirm-ep].", s); } } else { confirmEP = null; } messenger = Helper.CreateInstance <IReliableMessenger>(type); messenger.OpenClient(router, confirmEP, args, confirmCallback); return(messenger); }
/// <summary> /// Constructs a connection info instance by parsing the parameters /// encoded in the string passed. /// </summary> /// <param name="conString">The input connection string.</param> public SqlConnectionInfo(string conString) { var args = ArgCollection.Parse(conString, '=', ';'); foreach (string param in args) { switch (param.ToLowerInvariant()) { case "data source": properties.Set("server", args[param]); break; case "initial catalog": properties.Set("database", args[param]); break; case "user id": properties.Set("uid", args[param]); break; case "password": properties.Set("pwd", args[param]); break; case "trusted_connection": switch (args[param].ToLowerInvariant()) { case "true": case "yes": properties.Set("integrated security", "SSPI"); break; case "false": case "no": break; } break; default: properties.Set(param.ToLowerInvariant(), args[param]); break; } } }
public void ArgCollection_Clone() { ArgCollection ps; ArgCollection clone; ps = new ArgCollection(); ps.Set("foo", "bar"); ps.Set("bar", "foo"); clone = ps.Clone(); Assert.AreEqual("bar", clone["foo"]); Assert.AreEqual("foo", clone["bar"]); }
/// <summary> /// Constructs a packet to be used internally for queuing commands for submission /// to the switch. /// </summary> /// <param name="commandText">The command text (without the terminating LFLF characters).</param> /// <param name="headers">The headers for <b>sendevent</b> commands or <c>null</c>.</param> /// <param name="contentType">The content type or <c>null</c>.</param> /// <param name="content">The content data for<b>sendevent</b> commands or <c>null</c>.</param> internal SwitchPacket(string commandText, ArgCollection headers, string contentType, byte[] content) { this.PacketType = SwitchPacketType.Command; this.CommandText = commandText; this.Headers = headers; this.Content = content; this.ContentType = contentType; if (content != null && content.Length > 0 && contentType != null && contentType.StartsWith("text")) { this.ContentText = Helper.ASCIIEncoding.GetString(content); } }
/// <summary> /// Constructor. /// </summary> /// <param name="engineSettings">The <see cref="AuthenticationEngineSettings" />.</param> /// <param name="realm">The realm string.</param> /// <param name="extensionType">The <see cref="IAuthenticationExtension" /> type.</param> /// <param name="args">The realm and provider arguments.</param> /// <param name="query">The optional provider query.</param> /// <remarks> /// See the <see cref="RealmMapping" /> comments for a description of the /// realm settings retrieved from the <b>args</b> parameter and the /// comments for the specific <see cref="IAuthenticationExtension" /> /// implementation for a description of the provider specific arguments. /// </remarks> public RealmMapping(AuthenticationEngineSettings engineSettings, string realm, System.Type extensionType, ArgCollection args, string query) { this.Realm = realm; this.ExtensionType = extensionType; this.ExtensionName = extensionType.Name; this.Args = args; this.Query = query; this.AuthExtension = null; this.LockoutCount = args.Get("LockoutCount", engineSettings.LockoutCount); this.LockoutThreshold = args.Get("LockoutThreshold", engineSettings.LockoutThreshold); this.LockoutTime = args.Get("LockoutTime", engineSettings.LockoutTime); }
/// <summary> /// Establishes a session with the authentication extension. /// </summary> /// <param name="args">The extension specific arguments (see the remarks).</param> /// <param name="query">Ignored for this extension.</param> /// <param name="perfCounters">The application's performance counter set (or <c>null</c>).</param> /// <param name="perfPrefix">The string to prefix any performance counter names (or <c>null</c>).</param> /// <remarks> /// <para> /// This extension recognises the following arguments: /// </para> /// <list type="table"> /// <item> /// <term>Servers</term> /// <description> /// Specifies the list of RADIUS server network bindings specifying the /// IP address or host name of the server as well as the port number /// or well-known port name. Each server binding is formatted as /// described by <see cref="NetworkBinding.Parse" /> and the server /// bindings are separated by commas. This argument must be present. /// </description> /// </item> /// <item> /// <term>Secret</term> /// <description> /// The shared secret to be used to secure RADIUS packets delivered /// between this client and the any of the RADIUS servers. This /// string may include any valid characters besides semi-colons. /// This argument must be present. /// </description> /// </item> /// <item> /// <term>SocketBuffer</term> /// <description> /// Byte size of the client socket's send and receive buffers. Default /// value is 32K. /// </description> /// </item> /// <item> /// <term>NetworkBinding</term> /// <description> /// <para> /// Specifies the IP address of the network card the client is /// and port bindings. Use an IP address of ANY to bind to /// all network interfaces. ANY is suitable for single homed machines. /// Machines that are actually connected to multiple networks should /// specify a specific network binding here to ensure that the NAS-IP-Address /// of RADIUS authentication packets are initialized properly. /// </para> /// <para> /// A specific port number may be selected or 0 can be specified, /// indicating that the operating system should select a free port. /// </para> /// <para> /// Default value is ANY:0. /// </para> /// </description> /// </item> /// <item> /// <term>PortCount</term> /// <description> /// The number of RADIUS client UDP ports to open. Multiple ports may /// be required under high authentication loads. Default value is 4. /// </description> /// </item> /// <item> /// <term>RetryInterval</term> /// <description> /// Maximum time to wait for a response packet from a RADIUS before retransmitting /// an authentication request. Default is 5 seconds. /// </description> /// </item> /// <item> /// <term></term> /// <description> /// </description> /// </item> /// <item> /// <term>BkTaskInterval</term> /// <description> /// The interval at which background tasks such as retransmitting /// a request should be processed. Default is 1 second. /// </description> /// </item> /// <item> /// <term>MaxTransmissions</term> /// <description> /// The maximum number of authentication transmission attempts before aborting /// with an authentication with a timeout. Default is 4. /// </description> /// </item> /// <item> /// <term>RealmFormat</term> /// <description> /// Specifies how user names are to be generated from the /// <b>realm</b> and <b>account</b> components. See /// <see cref="RealmFormat" /> for more information. /// The possible values are: <b>Slash</b> and <b>Email</b>. /// Default is <b>Email</b>. /// </description> /// </item> /// <item> /// <term>MaxCacheTime</term> /// <description> /// Specifies the maximum time clients should retain authentication information. /// This is expressed in the same format as timespans parsed by <see cref="Config.Parse(string,TimeSpan)" />. /// This argument defaults to "5m". /// </description> /// </item> /// <item> /// <term>LockoutCount</term> /// <description> /// Specifies the limiting failed authentication count. Accounts /// will be locked when the fail count reaches this number. /// </description> /// </item> /// <item> /// <term>LockoutThreshold</term> /// <description> /// The period of time that can elapse between failed authentication /// attempts where the failed attempts will <b>not</b> be counted against the /// <b>LockoutCount</b>. Set this to <see cref="TimeSpan.Zero" /> /// to disable account lockout for the realm. /// </description> /// </item> /// <item> /// <term>LockoutTime</term> /// <description> /// The period of time an account will remain locked after being locked /// out due to too many failed authentication attempts. /// </description> /// </item> /// </list> /// <note> /// All calls to <see cref="Open" /> must be matched with a call /// to <see cref="Close" /> or <see cref="Dispose" />. /// </note> /// </remarks> public void Open(ArgCollection args, string query, PerfCounterSet perfCounters, string perfPrefix) { RadiusClientSettings settings; string[] rawBindings; List <NetworkBinding> bindings; string secret; using (TimedLock.Lock(this)) { if (IsOpen) { throw new AuthenticationException("Authentication extension is already open."); } perf = new Perf(perfCounters, perfPrefix); rawBindings = args.Get("servers", string.Empty).Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); if (rawBindings.Length == 0) { throw new AuthenticationException("RADUIS authentication extension requires at least one server network binding."); } bindings = new List <NetworkBinding>(rawBindings.Length); for (int i = 0; i < rawBindings.Length; i++) { bindings.Add(NetworkBinding.Parse(rawBindings[i])); } secret = args.Get("secret", (string)null); if (secret == null || secret.Length == 0) { throw new AuthenticationException("RADIUS authentication extension requires a shared NAS secret."); } settings = new RadiusClientSettings(bindings.ToArray(), secret); settings.SocketBuffer = args.Get("SocketBuffer", settings.SocketBuffer); settings.NetworkBinding = args.Get("NetworkBinding", settings.NetworkBinding); settings.PortCount = args.Get("PortCount", settings.PortCount); settings.RetryInterval = args.Get("RetryInterval", settings.RetryInterval); settings.BkTaskInterval = args.Get("BkTaskInterval", settings.BkTaskInterval); settings.MaxTransmissions = args.Get("settings.MaxTransmissions", settings.MaxTransmissions); settings.RealmFormat = args.Get <RealmFormat>("RealmFormat", settings.RealmFormat); maxCacheTime = args.Get("MaxCacheTime", TimeSpan.FromMinutes(5)); radiusClient.Open(settings); } }
/// <summary> /// Instantiates and initializes an <see cref="ITopologyProvider" /> plug-in defined by a configuration setting /// and then opens it client mode. /// </summary> /// <param name="router">The message router to associate with the topology.</param> /// <param name="typeKey">The fully qualified configuration setting specifying the topology type specification (or <c>null</c>).</param> /// <param name="argsKey">The fully qualified configuration key specifying the topology arguments formatted for <see cref="ArgCollection" />.</param> /// <returns>The <see cref="ITopologyProvider" /> instance.</returns> /// <remarks> /// <para> /// This utility uses <see cref="Config.Get(string,System.Type)" /> to map the configuration setting /// to a .NET assembly and type and then instantiates an instance and then opens it as a client side /// cluster. argsKey names the configuration string to be be instantiated into a <see cref="ArgCollection" /> /// and then passed to the cluster's <see cref="ITopologyProvider.OpenClient" /> method. /// </para> /// <para> /// typeKey may be passed as null. In this case, the configuration arguments must include a /// parameter named <b>"topology-type"</b> that defines the type assembly and class. /// </para> /// <note> /// The topology arguments must include an logical endpoint string argument named <b>cluster-ep</b>. /// This argument specifies the cluster endpoint to use when opening the topology. /// </note> /// </remarks> public static ITopologyProvider OpenClient(MsgRouter router, string typeKey, string argsKey) { System.Type type; ITopologyProvider topology; ArgCollection args; string clusterEP; if (!router.IsOpen) { throw new InvalidOperationException(RouterClosedMsg); } args = ArgCollection.Parse(Config.Global.Get(argsKey)); if (typeKey == null) { string topologyType; typeKey = "args[\"topology-type\"]"; topologyType = args["topology-type"]; if (topologyType == null) { throw new ArgumentException("Topology arguments must specify [topology-type] if [typeKey] is null."); } type = Config.Parse(topologyType, (System.Type)null); } else { type = Config.Global.Get(typeKey, (System.Type)null); } if (type == null || !typeof(ITopologyProvider).IsAssignableFrom(type)) { throw new ArgumentException(string.Format("Unable to map setting [{0}] to [ITopologyProvider].", typeKey)); } clusterEP = args["cluster-ep"]; if (clusterEP == null) { throw new ArgumentException("Topology arguments must specify [cluster-ep]"); } topology = Helper.CreateInstance <ITopologyProvider>(type); topology.OpenClient(router, clusterEP, args); return(topology); }
/// <summary> /// Establishes a session with the authentication extension. /// </summary> /// <param name="args">The extension specific arguments (see the remarks).</param> /// <param name="query">Not used.</param> /// <param name="perfCounters">The application's performance counter set (or <c>null</c>).</param> /// <param name="perfPrefix">The string to prefix any performance counter names (or <c>null</c>).</param> /// <remarks> /// <para> /// This extension recognises the following arguments: /// </para> /// <list type="table"> /// <item> /// <term>IsAD</term> /// <description> /// Set this to "true" or "yes" if the directory server is Microsoft Active Directory. /// This argument defaults to "true". /// </description> /// </item> /// <item> /// <term>AuthType</term> /// <description> /// Specifies the authentication method. The possible values are <b>Basic</b>, <b>Digest</b>, /// <b>DPA</b>, <b>External</b>, <b>Kerberos</b>, <b>MSN</b>, <b>Negotiate</b>, <b>NTLM</b>, /// or <b>Sicily</b>. This argument defaults to "Digest". /// </description> /// </item> /// <item> /// <term>Servers</term> /// <description> /// Specifies zero or more LDAP server host names or IP addresses separated by commas. /// This argument defaults an empty list. <b>Note that due to an unresolved bug with /// default Active Directory support, at least one LDAP server must be explicitly /// specified in the current build.</b> /// </description> /// </item> /// <item> /// <term>DNSHost</term> /// <description> /// Set this to "true" or "yes" if the host names specified by <b>Servers</b> should be /// interpreted as fully qualified DNS host names. If set to "no" or "false", the /// host names can be interpreted as an IP address or a DNS host name and if no host /// is specified, then an Active Directory server associated with the computer account /// will be used. This argument defaults to "false". /// </description> /// </item> /// <item> /// <term>UDP</term> /// <description> /// Set this to "true" or "yes" to enable UDP the connection over UDP, rather than over TCP/IP. /// This argument defaults to "false". /// </description> /// </item> /// <item> /// <term>MaxCacheTime</term> /// <description> /// Specifies the maximum time clients should retain authentication information. /// This is expressed in the same format as timespans parsed by <see cref="Config.Parse(string,TimeSpan)" />. /// This argument defaults to "5m". /// </description> /// </item> /// <item> /// <term>LockoutCount</term> /// <description> /// Specifies the limiting failed authentication count. Accounts /// will be locked when the fail count reaches this number. /// </description> /// </item> /// <item> /// <term>LockoutThreshold</term> /// <description> /// The period of time that can elapse between failed authentication /// attempts where the failed attempts will <b>not</b> be counted against the /// <b>LockoutCount</b>. Set this to <see cref="TimeSpan.Zero" /> /// to disable account lockout for the realm. /// </description> /// </item> /// <item> /// <term>LockoutTime</term> /// <description> /// The period of time an account will remain locked after being locked /// out due to too many failed authentication attempts. /// </description> /// </item> /// </list> /// <para> /// The defaults values for the arguments were selected so that ommiting all arguments /// will configure the extension so that it authenticates against the Active Directory /// domain the computer belongs to. There are some problems with some combinations of /// parameters. /// </para> /// <note> /// All calls to <see cref="Open" /> must be matched with a call /// to <see cref="Close" /> or <see cref="Dispose" />. /// </note> /// </remarks> public void Open(ArgCollection args, string query, PerfCounterSet perfCounters, string perfPrefix) { using (TimedLock.Lock(this)) { if (IsOpen) { throw new AuthenticationException("Authentication extension is already open."); } perf = new Perf(perfCounters, perfPrefix); // Load the arguments isAD = args.Get("IsAD", true); switch (args.Get("AuthType", "Digest").ToUpper()) { case "BASIC": authType = AuthType.Basic; break; case "DIGEST": authType = AuthType.Digest; break; case "DPA": authType = AuthType.Dpa; break; case "EXTERNAL": authType = AuthType.External; break; case "KERBEROS": authType = AuthType.Kerberos; break; case "MSN": authType = AuthType.Msn; break; case "NEGOTIATE": authType = AuthType.Negotiate; break; case "NTLM": authType = AuthType.Ntlm; break; case "SICILY": authType = AuthType.Sicily; break; default: throw new AuthenticationException("Unexpected authentication type argument [{0}].", args.Get("AuthType", "Negotiate")); } servers = args.Get("Servers", string.Empty).Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < servers.Length; i++) { servers[i] = servers[i].Trim(); } dnsHosts = args.Get("DNSHost", false); udp = args.Get("UDP", false); maxCacheTime = args.Get("MaxCacheTime", TimeSpan.FromMinutes(5)); } }
/// <summary> /// This constructor initializes the attribute to tag a non-default, non-idempotent, /// physical message handler. /// </summary> public MsgSessionAttribute() { this.Idempotent = false; this.KeepAlive = "5s"; this.SessionTimeout = null; this.IsAsync = false; this.MaxAsyncKeepAlive = "infinite"; this.sessionType = null; this.Type = SessionTypeID.Custom; this.TypeRef = null; this.parameters = string.Empty; this.custom = new ArgCollection(); }
public void ArgCollection_ReadOnly() { ArgCollection ps = new ArgCollection(); ps["hello"] = "world!"; Assert.IsFalse(ps.IsReadOnly); Assert.AreEqual("world!", ps["hello"]); ps.IsReadOnly = true; Assert.IsTrue(ps.IsReadOnly); Assert.AreEqual("world!", ps["hello"]); ExtendedAssert.Throws <InvalidOperationException>(() => ps.IsReadOnly = false); ExtendedAssert.Throws <NotSupportedException>(() => ps["foo"] = "bar"); }