| | 1 | | // Copyright (c) ZeroC, Inc. |
| | 2 | |
|
| | 3 | | using IceRpc.Internal; |
| | 4 | | using System.Collections.Immutable; |
| | 5 | | using System.Diagnostics.CodeAnalysis; |
| | 6 | |
|
| | 7 | | namespace IceRpc; |
| | 8 | |
|
| | 9 | | /// <summary>Represents an RPC protocol supported by IceRPC.</summary> |
| | 10 | | public class Protocol |
| | 11 | | { |
| | 12 | | /// <summary>Gets the ice protocol.</summary> |
| | 13 | | /// <value>The <see cref="Protocol" /> instance for the ice protocol.</value> |
| 10969 | 14 | | public static Protocol Ice => IceProtocol.Instance; |
| | 15 | |
|
| | 16 | | /// <summary>Gets the icerpc protocol.</summary> |
| | 17 | | /// <value>The <see cref="Protocol" /> instance for the icerpc protocol.</value> |
| 11200 | 18 | | public static Protocol IceRpc => IceRpcProtocol.Instance; |
| | 19 | |
|
| | 20 | | /// <summary>Gets the default port for this protocol.</summary> |
| | 21 | | /// <value>The default port value. Defaults to <c>4061</c> for the ice protocol and <c>4062</c> for the icerpc |
| | 22 | | /// protocol.</value> |
| 2283 | 23 | | public ushort DefaultPort { get; } |
| | 24 | |
|
| | 25 | | /// <summary>Gets a value indicating whether or not this protocol supports arbitrary application-defined fields in |
| | 26 | | /// request and response headers.</summary> |
| | 27 | | /// <value><see langword="true" /> if the protocol supports arbitrary fields; otherwise, <see langword="false" />. |
| | 28 | | /// </value> |
| 41 | 29 | | public bool HasFields { get; } |
| | 30 | |
|
| | 31 | | /// <summary>Gets the name of this protocol.</summary> |
| | 32 | | /// <value>The protocol name.</value> |
| 4203 | 33 | | public string Name { get; } |
| | 34 | |
|
| | 35 | | /// <summary>Gets the byte value for this protocol.</summary> |
| | 36 | | /// <value>The protocol byte value. It's used as the "protocol major" with the Slice1 encoding.</value> |
| 99 | 37 | | internal byte ByteValue { get; } |
| | 38 | |
|
| | 39 | | /// <summary>Gets a value indicating whether or not this protocol supports fragments in service addresses.</summary> |
| | 40 | | /// <value><see langword="true" /> if the protocol supports fragments; otherwise, <see langword="false" />.</value> |
| 757 | 41 | | internal bool HasFragment { get; } |
| | 42 | |
|
| | 43 | | /// <summary>Gets a value indicating whether or not this protocol supports payload continuations.</summary> |
| | 44 | | /// <value><see langword="true" /> if the protocol supports payload continuations; otherwise, |
| | 45 | | /// <see langword="false" />.</value> |
| 311 | 46 | | internal bool HasPayloadContinuation { get; } |
| | 47 | |
|
| | 48 | | /// <summary>Gets a value indicating whether or not the implementation of the protocol connection supports payload |
| | 49 | | /// writer interceptors.</summary> |
| | 50 | | /// <value><see langword="true" /> if the implementation of the protocol connection supports payload writer |
| | 51 | | /// interceptors; otherwise, <see langword="false" />.</value> |
| 18 | 52 | | internal bool SupportsPayloadWriterInterceptors { get; } |
| | 53 | |
|
| | 54 | | /// <summary>Parses a string into a protocol.</summary> |
| | 55 | | /// <param name="name">The name of the protocol.</param> |
| | 56 | | /// <returns>A protocol with the given name in lowercase.</returns> |
| | 57 | | /// <exception cref="FormatException">Thrown when <paramref name="name" /> is not ice or icerpc.</exception> |
| | 58 | | public static Protocol Parse(string name) => |
| 32 | 59 | | TryParse(name, out Protocol? protocol) ? protocol : throw new FormatException($"unknown protocol '{name}'"); |
| | 60 | |
|
| | 61 | | /// <summary>Tries to parse a string into a protocol.</summary> |
| | 62 | | /// <param name="name">The name of the protocol.</param> |
| | 63 | | /// <param name="protocol">The protocol parsed from the name.</param> |
| | 64 | | /// <returns><see langword="true" /> when <paramref name="name" /> was successfully parsed into a protocol; |
| | 65 | | /// otherwise, <see langword="false" />.</returns> |
| | 66 | | public static bool TryParse(string name, [NotNullWhen(true)] out Protocol? protocol) |
| 2573 | 67 | | { |
| 2573 | 68 | | name = name.ToLowerInvariant(); |
| 2573 | 69 | | protocol = name == IceRpc.Name ? IceRpc : (name == Ice.Name ? Ice : null); |
| 2573 | 70 | | return protocol is not null; |
| 2573 | 71 | | } |
| | 72 | |
|
| | 73 | | /// <summary>Converts this protocol into a string.</summary> |
| | 74 | | /// <returns>The name of the protocol.</returns> |
| 582 | 75 | | public override string ToString() => Name; |
| | 76 | |
|
| | 77 | | internal static Protocol FromByteValue(byte value) => |
| 37 | 78 | | value == Ice.ByteValue ? Ice : |
| 37 | 79 | | (value == IceRpc.ByteValue ? IceRpc : |
| 37 | 80 | | throw new NotSupportedException($"Cannot convert '{value}' into a protocol.")); |
| | 81 | |
|
| | 82 | | /// <summary>Checks if a path is valid for this protocol.</summary> |
| | 83 | | /// <param name="uriPath">The absolute path to check. The caller guarantees it's a valid URI absolute path. |
| | 84 | | /// </param> |
| | 85 | | /// <exception cref="FormatException">Thrown if the path is not valid.</exception> |
| | 86 | | internal virtual void CheckPath(string uriPath) |
| 456 | 87 | | { |
| | 88 | | // by default, any URI absolute path is ok |
| 456 | 89 | | } |
| | 90 | |
|
| | 91 | | /// <summary>Checks if these service address parameters are valid for this protocol.</summary> |
| | 92 | | /// <param name="serviceAddressParams">The service address parameters to check.</param> |
| | 93 | | /// <exception cref="FormatException">Thrown if the service address parameters are not valid.</exception> |
| | 94 | | /// <remarks>This method does not and should not check if the parameter names and values are properly escaped; |
| | 95 | | /// it does not check for the invalid empty and alt-server parameter names either.</remarks> |
| | 96 | | internal virtual void CheckServiceAddressParams(ImmutableDictionary<string, string> serviceAddressParams) |
| 94 | 97 | | { |
| | 98 | | // by default, any dictionary is ok |
| 94 | 99 | | } |
| | 100 | |
|
| | 101 | | /// <summary>Constructs a protocol.</summary> |
| 25 | 102 | | private protected Protocol( |
| 25 | 103 | | string name, |
| 25 | 104 | | ushort defaultPort, |
| 25 | 105 | | bool hasFields, |
| 25 | 106 | | bool hasFragment, |
| 25 | 107 | | bool hasPayloadContinuation, |
| 25 | 108 | | bool supportsPayloadWriterInterceptors, |
| 25 | 109 | | byte byteValue) |
| 25 | 110 | | { |
| 25 | 111 | | Name = name; |
| 25 | 112 | | DefaultPort = defaultPort; |
| 25 | 113 | | HasFields = hasFields; |
| 25 | 114 | | HasFragment = hasFragment; |
| 25 | 115 | | HasPayloadContinuation = hasPayloadContinuation; |
| 25 | 116 | | SupportsPayloadWriterInterceptors = supportsPayloadWriterInterceptors; |
| 25 | 117 | | ByteValue = byteValue; |
| 25 | 118 | | } |
| | 119 | | } |