#region Copyright notice and license // Copyright 2015 gRPC authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #endregion using System; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using Grpc.Core.Internal; using Grpc.Core.Utils; namespace Grpc.Core { /// /// Channel option specified when creating a channel. /// Corresponds to grpc_channel_args from grpc/grpc.h. /// Commonly used channel option names are defined in ChannelOptions, /// but any of the GRPC_ARG_* channel options names defined in grpc_types.h can be used. /// public sealed class ChannelOption : IEquatable { /// /// Type of ChannelOption. /// public enum OptionType { /// /// Channel option with integer value. /// Integer, /// /// Channel option with string value. /// String } private readonly OptionType type; private readonly string name; private readonly int intValue; private readonly string stringValue; /// /// Creates a channel option with a string value. /// /// Name. /// String value. public ChannelOption(string name, string stringValue) { this.type = OptionType.String; this.name = GrpcPreconditions.CheckNotNull(name, "name"); this.stringValue = GrpcPreconditions.CheckNotNull(stringValue, "stringValue"); } /// /// Creates a channel option with an integer value. /// /// Name. /// Integer value. public ChannelOption(string name, int intValue) { this.type = OptionType.Integer; this.name = GrpcPreconditions.CheckNotNull(name, "name"); this.intValue = intValue; } /// /// Gets the type of the ChannelOption. /// public OptionType Type { get { return type; } } /// /// Gets the name of the ChannelOption. /// public string Name { get { return name; } } /// /// Gets the integer value the ChannelOption. /// public int IntValue { get { GrpcPreconditions.CheckState(type == OptionType.Integer); return intValue; } } /// /// Gets the string value the ChannelOption. /// public string StringValue { get { GrpcPreconditions.CheckState(type == OptionType.String); return stringValue; } } /// /// Determines whether the specified object is equal to the current object. /// public override bool Equals(object obj) { return Equals(obj as ChannelOption); } /// /// Determines whether the specified object is equal to the current object. /// public bool Equals(ChannelOption other) { return other != null && type == other.type && name == other.name && intValue == other.intValue && stringValue == other.stringValue; } /// /// A hash code for the current object. /// public override int GetHashCode() { var hashCode = 1412678443; hashCode = hashCode * -1521134295 + type.GetHashCode(); hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(name); hashCode = hashCode * -1521134295 + intValue.GetHashCode(); hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(stringValue); return hashCode; } /// /// Equality operator. /// public static bool operator ==(ChannelOption option1, ChannelOption option2) { return EqualityComparer.Default.Equals(option1, option2); } /// /// Inequality operator. /// public static bool operator !=(ChannelOption option1, ChannelOption option2) { return !(option1 == option2); } } /// /// Defines names of most commonly used channel options. /// Other supported options names can be found in grpc_types.h (GRPC_ARG_* definitions) /// public static class ChannelOptions { /// Override SSL target check. Only to be used for testing. public const string SslTargetNameOverride = "grpc.ssl_target_name_override"; /// Enable census for tracing and stats collection public const string Census = "grpc.census"; /// Maximum number of concurrent incoming streams to allow on a http2 connection public const string MaxConcurrentStreams = "grpc.max_concurrent_streams"; /// Maximum message length that the channel can receive public const string MaxReceiveMessageLength = "grpc.max_receive_message_length"; /// Maximum message length that the channel can send public const string MaxSendMessageLength = "grpc.max_send_message_length"; /// Obsolete, for backward compatibility only. [Obsolete("Use MaxReceiveMessageLength instead.")] public const string MaxMessageLength = MaxReceiveMessageLength; /// Initial sequence number for http2 transports public const string Http2InitialSequenceNumber = "grpc.http2.initial_sequence_number"; /// Default authority for calls. public const string DefaultAuthority = "grpc.default_authority"; /// Primary user agent: goes at the start of the user-agent metadata public const string PrimaryUserAgentString = "grpc.primary_user_agent"; /// Secondary user agent: goes at the end of the user-agent metadata public const string SecondaryUserAgentString = "grpc.secondary_user_agent"; /// If non-zero, allow the use of SO_REUSEPORT for server if it's available (default 1) public const string SoReuseport = "grpc.so_reuseport"; /// /// Creates native object for a collection of channel options. /// /// The native channel arguments. internal static ChannelArgsSafeHandle CreateChannelArgs(ICollection options) { if (options == null || options.Count == 0) { return ChannelArgsSafeHandle.CreateNull(); } ChannelArgsSafeHandle nativeArgs = null; try { nativeArgs = ChannelArgsSafeHandle.Create(options.Count); int i = 0; foreach (var option in options) { if (option.Type == ChannelOption.OptionType.Integer) { nativeArgs.SetInteger(i, option.Name, option.IntValue); } else if (option.Type == ChannelOption.OptionType.String) { nativeArgs.SetString(i, option.Name, option.StringValue); } else { throw new InvalidOperationException("Unknown option type"); } i++; } return nativeArgs; } catch (Exception) { if (nativeArgs != null) { nativeArgs.Dispose(); } throw; } } } }