1 #region Copyright notice and license
2 // Copyright 2015 gRPC authors.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //     http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 #endregion
16 using System;
17 using System.Collections.Generic;
18 using System.Runtime.InteropServices;
19 using System.Threading;
20 using System.Threading.Tasks;
21 using Grpc.Core.Internal;
22 using Grpc.Core.Utils;
23 
24 namespace Grpc.Core
25 {
26     /// <summary>
27     /// Channel option specified when creating a channel.
28     /// Corresponds to grpc_channel_args from grpc/grpc.h.
29     /// </summary>
30     public sealed class ChannelOption
31     {
32         /// <summary>
33         /// Type of <c>ChannelOption</c>.
34         /// </summary>
35         public enum OptionType
36         {
37             /// <summary>
38             /// Channel option with integer value.
39             /// </summary>
40             Integer,
41 
42             /// <summary>
43             /// Channel option with string value.
44             /// </summary>
45             String
46         }
47 
48         private readonly OptionType type;
49         private readonly string name;
50         private readonly int intValue;
51         private readonly string stringValue;
52 
53         /// <summary>
54         /// Creates a channel option with a string value.
55         /// </summary>
56         /// <param name="name">Name.</param>
57         /// <param name="stringValue">String value.</param>
ChannelOption(string name, string stringValue)58         public ChannelOption(string name, string stringValue)
59         {
60             this.type = OptionType.String;
61             this.name = GrpcPreconditions.CheckNotNull(name, "name");
62             this.stringValue = GrpcPreconditions.CheckNotNull(stringValue, "stringValue");
63         }
64 
65         /// <summary>
66         /// Creates a channel option with an integer value.
67         /// </summary>
68         /// <param name="name">Name.</param>
69         /// <param name="intValue">Integer value.</param>
ChannelOption(string name, int intValue)70         public ChannelOption(string name, int intValue)
71         {
72             this.type = OptionType.Integer;
73             this.name = GrpcPreconditions.CheckNotNull(name, "name");
74             this.intValue = intValue;
75         }
76 
77         /// <summary>
78         /// Gets the type of the <c>ChannelOption</c>.
79         /// </summary>
80         public OptionType Type
81         {
82             get
83             {
84                 return type;
85             }
86         }
87 
88         /// <summary>
89         /// Gets the name of the <c>ChannelOption</c>.
90         /// </summary>
91         public string Name
92         {
93             get
94             {
95                 return name;
96             }
97         }
98 
99         /// <summary>
100         /// Gets the integer value the <c>ChannelOption</c>.
101         /// </summary>
102         public int IntValue
103         {
104             get
105             {
106                 GrpcPreconditions.CheckState(type == OptionType.Integer);
107                 return intValue;
108             }
109         }
110 
111         /// <summary>
112         /// Gets the string value the <c>ChannelOption</c>.
113         /// </summary>
114         public string StringValue
115         {
116             get
117             {
118                 GrpcPreconditions.CheckState(type == OptionType.String);
119                 return stringValue;
120             }
121         }
122     }
123 
124     /// <summary>
125     /// Defines names of supported channel options.
126     /// </summary>
127     public static class ChannelOptions
128     {
129         /// <summary>Override SSL target check. Only to be used for testing.</summary>
130         public const string SslTargetNameOverride = "grpc.ssl_target_name_override";
131 
132         /// <summary>Enable census for tracing and stats collection</summary>
133         public const string Census = "grpc.census";
134 
135         /// <summary>Maximum number of concurrent incoming streams to allow on a http2 connection</summary>
136         public const string MaxConcurrentStreams = "grpc.max_concurrent_streams";
137 
138         /// <summary>Maximum message length that the channel can receive</summary>
139         public const string MaxReceiveMessageLength = "grpc.max_receive_message_length";
140 
141         /// <summary>Maximum message length that the channel can send</summary>
142         public const string MaxSendMessageLength = "grpc.max_send_message_length";
143 
144         /// <summary>Obsolete, for backward compatibility only.</summary>
145         [Obsolete("Use MaxReceiveMessageLength instead.")]
146         public const string MaxMessageLength = MaxReceiveMessageLength;
147 
148         /// <summary>Initial sequence number for http2 transports</summary>
149         public const string Http2InitialSequenceNumber = "grpc.http2.initial_sequence_number";
150 
151         /// <summary>Default authority for calls.</summary>
152         public const string DefaultAuthority = "grpc.default_authority";
153 
154         /// <summary>Primary user agent: goes at the start of the user-agent metadata</summary>
155         public const string PrimaryUserAgentString = "grpc.primary_user_agent";
156 
157         /// <summary>Secondary user agent: goes at the end of the user-agent metadata</summary>
158         public const string SecondaryUserAgentString = "grpc.secondary_user_agent";
159 
160         /// <summary>If non-zero, allow the use of SO_REUSEPORT for server if it's available (default 1)</summary>
161         public const string SoReuseport = "grpc.so_reuseport";
162 
163         /// <summary>
164         /// Creates native object for a collection of channel options.
165         /// </summary>
166         /// <returns>The native channel arguments.</returns>
CreateChannelArgs(ICollection<ChannelOption> options)167         internal static ChannelArgsSafeHandle CreateChannelArgs(ICollection<ChannelOption> options)
168         {
169             if (options == null || options.Count == 0)
170             {
171                 return ChannelArgsSafeHandle.CreateNull();
172             }
173             ChannelArgsSafeHandle nativeArgs = null;
174             try
175             {
176                 nativeArgs = ChannelArgsSafeHandle.Create(options.Count);
177                 int i = 0;
178                 foreach (var option in options)
179                 {
180                     if (option.Type == ChannelOption.OptionType.Integer)
181                     {
182                         nativeArgs.SetInteger(i, option.Name, option.IntValue);
183                     }
184                     else if (option.Type == ChannelOption.OptionType.String)
185                     {
186                         nativeArgs.SetString(i, option.Name, option.StringValue);
187                     }
188                     else
189                     {
190                         throw new InvalidOperationException("Unknown option type");
191                     }
192                     i++;
193                 }
194                 return nativeArgs;
195             }
196             catch (Exception)
197             {
198                 if (nativeArgs != null)
199                 {
200                     nativeArgs.Dispose();
201                 }
202                 throw;
203             }
204         }
205     }
206 }
207