// <auto-generated>
//     Generated by the protocol buffer compiler.  DO NOT EDIT!
//     source: src/proto/grpc/testing/echo_messages.proto
// </auto-generated>
#pragma warning disable 1591, 0612, 3021
#region Designer generated code

using pb = global::Google.Protobuf;
using pbc = global::Google.Protobuf.Collections;
using pbr = global::Google.Protobuf.Reflection;
using scg = global::System.Collections.Generic;
namespace Grpc.Testing {

  /// <summary>Holder for reflection information generated from src/proto/grpc/testing/echo_messages.proto</summary>
  public static partial class EchoMessagesReflection {

    #region Descriptor
    /// <summary>File descriptor for src/proto/grpc/testing/echo_messages.proto</summary>
    public static pbr::FileDescriptor Descriptor {
      get { return descriptor; }
    }
    private static pbr::FileDescriptor descriptor;

    static EchoMessagesReflection() {
      byte[] descriptorData = global::System.Convert.FromBase64String(
          string.Concat(
            "CipzcmMvcHJvdG8vZ3JwYy90ZXN0aW5nL2VjaG9fbWVzc2FnZXMucHJvdG8S",
            "DGdycGMudGVzdGluZyIyCglEZWJ1Z0luZm8SFQoNc3RhY2tfZW50cmllcxgB",
            "IAMoCRIOCgZkZXRhaWwYAiABKAkiUAoLRXJyb3JTdGF0dXMSDAoEY29kZRgB",
            "IAEoBRIVCg1lcnJvcl9tZXNzYWdlGAIgASgJEhwKFGJpbmFyeV9lcnJvcl9k",
            "ZXRhaWxzGAMgASgJIv8DCg1SZXF1ZXN0UGFyYW1zEhUKDWVjaG9fZGVhZGxp",
            "bmUYASABKAgSHgoWY2xpZW50X2NhbmNlbF9hZnRlcl91cxgCIAEoBRIeChZz",
            "ZXJ2ZXJfY2FuY2VsX2FmdGVyX3VzGAMgASgFEhUKDWVjaG9fbWV0YWRhdGEY",
            "BCABKAgSGgoSY2hlY2tfYXV0aF9jb250ZXh0GAUgASgIEh8KF3Jlc3BvbnNl",
            "X21lc3NhZ2VfbGVuZ3RoGAYgASgFEhEKCWVjaG9fcGVlchgHIAEoCBIgChhl",
            "eHBlY3RlZF9jbGllbnRfaWRlbnRpdHkYCCABKAkSHAoUc2tpcF9jYW5jZWxs",
            "ZWRfY2hlY2sYCSABKAgSKAogZXhwZWN0ZWRfdHJhbnNwb3J0X3NlY3VyaXR5",
            "X3R5cGUYCiABKAkSKwoKZGVidWdfaW5mbxgLIAEoCzIXLmdycGMudGVzdGlu",
            "Zy5EZWJ1Z0luZm8SEgoKc2VydmVyX2RpZRgMIAEoCBIcChRiaW5hcnlfZXJy",
            "b3JfZGV0YWlscxgNIAEoCRIxCg5leHBlY3RlZF9lcnJvchgOIAEoCzIZLmdy",
            "cGMudGVzdGluZy5FcnJvclN0YXR1cxIXCg9zZXJ2ZXJfc2xlZXBfdXMYDyAB",
            "KAUSGwoTYmFja2VuZF9jaGFubmVsX2lkeBgQIAEoBSJKCgtFY2hvUmVxdWVz",
            "dBIPCgdtZXNzYWdlGAEgASgJEioKBXBhcmFtGAIgASgLMhsuZ3JwYy50ZXN0",
            "aW5nLlJlcXVlc3RQYXJhbXMiRgoOUmVzcG9uc2VQYXJhbXMSGAoQcmVxdWVz",
            "dF9kZWFkbGluZRgBIAEoAxIMCgRob3N0GAIgASgJEgwKBHBlZXIYAyABKAki",
            "TAoMRWNob1Jlc3BvbnNlEg8KB21lc3NhZ2UYASABKAkSKwoFcGFyYW0YAiAB",
            "KAsyHC5ncnBjLnRlc3RpbmcuUmVzcG9uc2VQYXJhbXNiBnByb3RvMw=="));
      descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
          new pbr::FileDescriptor[] { },
          new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] {
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.DebugInfo), global::Grpc.Testing.DebugInfo.Parser, new[]{ "StackEntries", "Detail" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ErrorStatus), global::Grpc.Testing.ErrorStatus.Parser, new[]{ "Code", "ErrorMessage", "BinaryErrorDetails" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.RequestParams), global::Grpc.Testing.RequestParams.Parser, new[]{ "EchoDeadline", "ClientCancelAfterUs", "ServerCancelAfterUs", "EchoMetadata", "CheckAuthContext", "ResponseMessageLength", "EchoPeer", "ExpectedClientIdentity", "SkipCancelledCheck", "ExpectedTransportSecurityType", "DebugInfo", "ServerDie", "BinaryErrorDetails", "ExpectedError", "ServerSleepUs", "BackendChannelIdx" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.EchoRequest), global::Grpc.Testing.EchoRequest.Parser, new[]{ "Message", "Param" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ResponseParams), global::Grpc.Testing.ResponseParams.Parser, new[]{ "RequestDeadline", "Host", "Peer" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.EchoResponse), global::Grpc.Testing.EchoResponse.Parser, new[]{ "Message", "Param" }, null, null, null)
          }));
    }
    #endregion

  }
  #region Messages
  /// <summary>
  /// Message to be echoed back serialized in trailer.
  /// </summary>
  public sealed partial class DebugInfo : pb::IMessage<DebugInfo> {
    private static readonly pb::MessageParser<DebugInfo> _parser = new pb::MessageParser<DebugInfo>(() => new DebugInfo());
    private pb::UnknownFieldSet _unknownFields;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<DebugInfo> Parser { get { return _parser; } }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Grpc.Testing.EchoMessagesReflection.Descriptor.MessageTypes[0]; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public DebugInfo() {
      OnConstruction();
    }

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public DebugInfo(DebugInfo other) : this() {
      stackEntries_ = other.stackEntries_.Clone();
      detail_ = other.detail_;
      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public DebugInfo Clone() {
      return new DebugInfo(this);
    }

    /// <summary>Field number for the "stack_entries" field.</summary>
    public const int StackEntriesFieldNumber = 1;
    private static readonly pb::FieldCodec<string> _repeated_stackEntries_codec
        = pb::FieldCodec.ForString(10);
    private readonly pbc::RepeatedField<string> stackEntries_ = new pbc::RepeatedField<string>();
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public pbc::RepeatedField<string> StackEntries {
      get { return stackEntries_; }
    }

    /// <summary>Field number for the "detail" field.</summary>
    public const int DetailFieldNumber = 2;
    private string detail_ = "";
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public string Detail {
      get { return detail_; }
      set {
        detail_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override bool Equals(object other) {
      return Equals(other as DebugInfo);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(DebugInfo other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if(!stackEntries_.Equals(other.stackEntries_)) return false;
      if (Detail != other.Detail) return false;
      return Equals(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      hash ^= stackEntries_.GetHashCode();
      if (Detail.Length != 0) hash ^= Detail.GetHashCode();
      if (_unknownFields != null) {
        hash ^= _unknownFields.GetHashCode();
      }
      return hash;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override string ToString() {
      return pb::JsonFormatter.ToDiagnosticString(this);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void WriteTo(pb::CodedOutputStream output) {
      stackEntries_.WriteTo(output, _repeated_stackEntries_codec);
      if (Detail.Length != 0) {
        output.WriteRawTag(18);
        output.WriteString(Detail);
      }
      if (_unknownFields != null) {
        _unknownFields.WriteTo(output);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      size += stackEntries_.CalculateSize(_repeated_stackEntries_codec);
      if (Detail.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(Detail);
      }
      if (_unknownFields != null) {
        size += _unknownFields.CalculateSize();
      }
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(DebugInfo other) {
      if (other == null) {
        return;
      }
      stackEntries_.Add(other.stackEntries_);
      if (other.Detail.Length != 0) {
        Detail = other.Detail;
      }
      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
            break;
          case 10: {
            stackEntries_.AddEntriesFrom(input, _repeated_stackEntries_codec);
            break;
          }
          case 18: {
            Detail = input.ReadString();
            break;
          }
        }
      }
    }

  }

  /// <summary>
  /// Error status client expects to see.
  /// </summary>
  public sealed partial class ErrorStatus : pb::IMessage<ErrorStatus> {
    private static readonly pb::MessageParser<ErrorStatus> _parser = new pb::MessageParser<ErrorStatus>(() => new ErrorStatus());
    private pb::UnknownFieldSet _unknownFields;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<ErrorStatus> Parser { get { return _parser; } }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Grpc.Testing.EchoMessagesReflection.Descriptor.MessageTypes[1]; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ErrorStatus() {
      OnConstruction();
    }

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ErrorStatus(ErrorStatus other) : this() {
      code_ = other.code_;
      errorMessage_ = other.errorMessage_;
      binaryErrorDetails_ = other.binaryErrorDetails_;
      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ErrorStatus Clone() {
      return new ErrorStatus(this);
    }

    /// <summary>Field number for the "code" field.</summary>
    public const int CodeFieldNumber = 1;
    private int code_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int Code {
      get { return code_; }
      set {
        code_ = value;
      }
    }

    /// <summary>Field number for the "error_message" field.</summary>
    public const int ErrorMessageFieldNumber = 2;
    private string errorMessage_ = "";
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public string ErrorMessage {
      get { return errorMessage_; }
      set {
        errorMessage_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
      }
    }

    /// <summary>Field number for the "binary_error_details" field.</summary>
    public const int BinaryErrorDetailsFieldNumber = 3;
    private string binaryErrorDetails_ = "";
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public string BinaryErrorDetails {
      get { return binaryErrorDetails_; }
      set {
        binaryErrorDetails_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override bool Equals(object other) {
      return Equals(other as ErrorStatus);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(ErrorStatus other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (Code != other.Code) return false;
      if (ErrorMessage != other.ErrorMessage) return false;
      if (BinaryErrorDetails != other.BinaryErrorDetails) return false;
      return Equals(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (Code != 0) hash ^= Code.GetHashCode();
      if (ErrorMessage.Length != 0) hash ^= ErrorMessage.GetHashCode();
      if (BinaryErrorDetails.Length != 0) hash ^= BinaryErrorDetails.GetHashCode();
      if (_unknownFields != null) {
        hash ^= _unknownFields.GetHashCode();
      }
      return hash;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override string ToString() {
      return pb::JsonFormatter.ToDiagnosticString(this);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void WriteTo(pb::CodedOutputStream output) {
      if (Code != 0) {
        output.WriteRawTag(8);
        output.WriteInt32(Code);
      }
      if (ErrorMessage.Length != 0) {
        output.WriteRawTag(18);
        output.WriteString(ErrorMessage);
      }
      if (BinaryErrorDetails.Length != 0) {
        output.WriteRawTag(26);
        output.WriteString(BinaryErrorDetails);
      }
      if (_unknownFields != null) {
        _unknownFields.WriteTo(output);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      if (Code != 0) {
        size += 1 + pb::CodedOutputStream.ComputeInt32Size(Code);
      }
      if (ErrorMessage.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(ErrorMessage);
      }
      if (BinaryErrorDetails.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(BinaryErrorDetails);
      }
      if (_unknownFields != null) {
        size += _unknownFields.CalculateSize();
      }
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(ErrorStatus other) {
      if (other == null) {
        return;
      }
      if (other.Code != 0) {
        Code = other.Code;
      }
      if (other.ErrorMessage.Length != 0) {
        ErrorMessage = other.ErrorMessage;
      }
      if (other.BinaryErrorDetails.Length != 0) {
        BinaryErrorDetails = other.BinaryErrorDetails;
      }
      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
            break;
          case 8: {
            Code = input.ReadInt32();
            break;
          }
          case 18: {
            ErrorMessage = input.ReadString();
            break;
          }
          case 26: {
            BinaryErrorDetails = input.ReadString();
            break;
          }
        }
      }
    }

  }

  public sealed partial class RequestParams : pb::IMessage<RequestParams> {
    private static readonly pb::MessageParser<RequestParams> _parser = new pb::MessageParser<RequestParams>(() => new RequestParams());
    private pb::UnknownFieldSet _unknownFields;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<RequestParams> Parser { get { return _parser; } }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Grpc.Testing.EchoMessagesReflection.Descriptor.MessageTypes[2]; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public RequestParams() {
      OnConstruction();
    }

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public RequestParams(RequestParams other) : this() {
      echoDeadline_ = other.echoDeadline_;
      clientCancelAfterUs_ = other.clientCancelAfterUs_;
      serverCancelAfterUs_ = other.serverCancelAfterUs_;
      echoMetadata_ = other.echoMetadata_;
      checkAuthContext_ = other.checkAuthContext_;
      responseMessageLength_ = other.responseMessageLength_;
      echoPeer_ = other.echoPeer_;
      expectedClientIdentity_ = other.expectedClientIdentity_;
      skipCancelledCheck_ = other.skipCancelledCheck_;
      expectedTransportSecurityType_ = other.expectedTransportSecurityType_;
      debugInfo_ = other.debugInfo_ != null ? other.debugInfo_.Clone() : null;
      serverDie_ = other.serverDie_;
      binaryErrorDetails_ = other.binaryErrorDetails_;
      expectedError_ = other.expectedError_ != null ? other.expectedError_.Clone() : null;
      serverSleepUs_ = other.serverSleepUs_;
      backendChannelIdx_ = other.backendChannelIdx_;
      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public RequestParams Clone() {
      return new RequestParams(this);
    }

    /// <summary>Field number for the "echo_deadline" field.</summary>
    public const int EchoDeadlineFieldNumber = 1;
    private bool echoDeadline_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool EchoDeadline {
      get { return echoDeadline_; }
      set {
        echoDeadline_ = value;
      }
    }

    /// <summary>Field number for the "client_cancel_after_us" field.</summary>
    public const int ClientCancelAfterUsFieldNumber = 2;
    private int clientCancelAfterUs_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int ClientCancelAfterUs {
      get { return clientCancelAfterUs_; }
      set {
        clientCancelAfterUs_ = value;
      }
    }

    /// <summary>Field number for the "server_cancel_after_us" field.</summary>
    public const int ServerCancelAfterUsFieldNumber = 3;
    private int serverCancelAfterUs_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int ServerCancelAfterUs {
      get { return serverCancelAfterUs_; }
      set {
        serverCancelAfterUs_ = value;
      }
    }

    /// <summary>Field number for the "echo_metadata" field.</summary>
    public const int EchoMetadataFieldNumber = 4;
    private bool echoMetadata_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool EchoMetadata {
      get { return echoMetadata_; }
      set {
        echoMetadata_ = value;
      }
    }

    /// <summary>Field number for the "check_auth_context" field.</summary>
    public const int CheckAuthContextFieldNumber = 5;
    private bool checkAuthContext_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool CheckAuthContext {
      get { return checkAuthContext_; }
      set {
        checkAuthContext_ = value;
      }
    }

    /// <summary>Field number for the "response_message_length" field.</summary>
    public const int ResponseMessageLengthFieldNumber = 6;
    private int responseMessageLength_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int ResponseMessageLength {
      get { return responseMessageLength_; }
      set {
        responseMessageLength_ = value;
      }
    }

    /// <summary>Field number for the "echo_peer" field.</summary>
    public const int EchoPeerFieldNumber = 7;
    private bool echoPeer_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool EchoPeer {
      get { return echoPeer_; }
      set {
        echoPeer_ = value;
      }
    }

    /// <summary>Field number for the "expected_client_identity" field.</summary>
    public const int ExpectedClientIdentityFieldNumber = 8;
    private string expectedClientIdentity_ = "";
    /// <summary>
    /// will force check_auth_context.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public string ExpectedClientIdentity {
      get { return expectedClientIdentity_; }
      set {
        expectedClientIdentity_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
      }
    }

    /// <summary>Field number for the "skip_cancelled_check" field.</summary>
    public const int SkipCancelledCheckFieldNumber = 9;
    private bool skipCancelledCheck_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool SkipCancelledCheck {
      get { return skipCancelledCheck_; }
      set {
        skipCancelledCheck_ = value;
      }
    }

    /// <summary>Field number for the "expected_transport_security_type" field.</summary>
    public const int ExpectedTransportSecurityTypeFieldNumber = 10;
    private string expectedTransportSecurityType_ = "";
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public string ExpectedTransportSecurityType {
      get { return expectedTransportSecurityType_; }
      set {
        expectedTransportSecurityType_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
      }
    }

    /// <summary>Field number for the "debug_info" field.</summary>
    public const int DebugInfoFieldNumber = 11;
    private global::Grpc.Testing.DebugInfo debugInfo_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Testing.DebugInfo DebugInfo {
      get { return debugInfo_; }
      set {
        debugInfo_ = value;
      }
    }

    /// <summary>Field number for the "server_die" field.</summary>
    public const int ServerDieFieldNumber = 12;
    private bool serverDie_;
    /// <summary>
    /// Server should not see a request with this set.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool ServerDie {
      get { return serverDie_; }
      set {
        serverDie_ = value;
      }
    }

    /// <summary>Field number for the "binary_error_details" field.</summary>
    public const int BinaryErrorDetailsFieldNumber = 13;
    private string binaryErrorDetails_ = "";
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public string BinaryErrorDetails {
      get { return binaryErrorDetails_; }
      set {
        binaryErrorDetails_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
      }
    }

    /// <summary>Field number for the "expected_error" field.</summary>
    public const int ExpectedErrorFieldNumber = 14;
    private global::Grpc.Testing.ErrorStatus expectedError_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Testing.ErrorStatus ExpectedError {
      get { return expectedError_; }
      set {
        expectedError_ = value;
      }
    }

    /// <summary>Field number for the "server_sleep_us" field.</summary>
    public const int ServerSleepUsFieldNumber = 15;
    private int serverSleepUs_;
    /// <summary>
    /// Amount to sleep when invoking server
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int ServerSleepUs {
      get { return serverSleepUs_; }
      set {
        serverSleepUs_ = value;
      }
    }

    /// <summary>Field number for the "backend_channel_idx" field.</summary>
    public const int BackendChannelIdxFieldNumber = 16;
    private int backendChannelIdx_;
    /// <summary>
    /// which backend to send request to
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int BackendChannelIdx {
      get { return backendChannelIdx_; }
      set {
        backendChannelIdx_ = value;
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override bool Equals(object other) {
      return Equals(other as RequestParams);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(RequestParams other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (EchoDeadline != other.EchoDeadline) return false;
      if (ClientCancelAfterUs != other.ClientCancelAfterUs) return false;
      if (ServerCancelAfterUs != other.ServerCancelAfterUs) return false;
      if (EchoMetadata != other.EchoMetadata) return false;
      if (CheckAuthContext != other.CheckAuthContext) return false;
      if (ResponseMessageLength != other.ResponseMessageLength) return false;
      if (EchoPeer != other.EchoPeer) return false;
      if (ExpectedClientIdentity != other.ExpectedClientIdentity) return false;
      if (SkipCancelledCheck != other.SkipCancelledCheck) return false;
      if (ExpectedTransportSecurityType != other.ExpectedTransportSecurityType) return false;
      if (!object.Equals(DebugInfo, other.DebugInfo)) return false;
      if (ServerDie != other.ServerDie) return false;
      if (BinaryErrorDetails != other.BinaryErrorDetails) return false;
      if (!object.Equals(ExpectedError, other.ExpectedError)) return false;
      if (ServerSleepUs != other.ServerSleepUs) return false;
      if (BackendChannelIdx != other.BackendChannelIdx) return false;
      return Equals(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (EchoDeadline != false) hash ^= EchoDeadline.GetHashCode();
      if (ClientCancelAfterUs != 0) hash ^= ClientCancelAfterUs.GetHashCode();
      if (ServerCancelAfterUs != 0) hash ^= ServerCancelAfterUs.GetHashCode();
      if (EchoMetadata != false) hash ^= EchoMetadata.GetHashCode();
      if (CheckAuthContext != false) hash ^= CheckAuthContext.GetHashCode();
      if (ResponseMessageLength != 0) hash ^= ResponseMessageLength.GetHashCode();
      if (EchoPeer != false) hash ^= EchoPeer.GetHashCode();
      if (ExpectedClientIdentity.Length != 0) hash ^= ExpectedClientIdentity.GetHashCode();
      if (SkipCancelledCheck != false) hash ^= SkipCancelledCheck.GetHashCode();
      if (ExpectedTransportSecurityType.Length != 0) hash ^= ExpectedTransportSecurityType.GetHashCode();
      if (debugInfo_ != null) hash ^= DebugInfo.GetHashCode();
      if (ServerDie != false) hash ^= ServerDie.GetHashCode();
      if (BinaryErrorDetails.Length != 0) hash ^= BinaryErrorDetails.GetHashCode();
      if (expectedError_ != null) hash ^= ExpectedError.GetHashCode();
      if (ServerSleepUs != 0) hash ^= ServerSleepUs.GetHashCode();
      if (BackendChannelIdx != 0) hash ^= BackendChannelIdx.GetHashCode();
      if (_unknownFields != null) {
        hash ^= _unknownFields.GetHashCode();
      }
      return hash;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override string ToString() {
      return pb::JsonFormatter.ToDiagnosticString(this);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void WriteTo(pb::CodedOutputStream output) {
      if (EchoDeadline != false) {
        output.WriteRawTag(8);
        output.WriteBool(EchoDeadline);
      }
      if (ClientCancelAfterUs != 0) {
        output.WriteRawTag(16);
        output.WriteInt32(ClientCancelAfterUs);
      }
      if (ServerCancelAfterUs != 0) {
        output.WriteRawTag(24);
        output.WriteInt32(ServerCancelAfterUs);
      }
      if (EchoMetadata != false) {
        output.WriteRawTag(32);
        output.WriteBool(EchoMetadata);
      }
      if (CheckAuthContext != false) {
        output.WriteRawTag(40);
        output.WriteBool(CheckAuthContext);
      }
      if (ResponseMessageLength != 0) {
        output.WriteRawTag(48);
        output.WriteInt32(ResponseMessageLength);
      }
      if (EchoPeer != false) {
        output.WriteRawTag(56);
        output.WriteBool(EchoPeer);
      }
      if (ExpectedClientIdentity.Length != 0) {
        output.WriteRawTag(66);
        output.WriteString(ExpectedClientIdentity);
      }
      if (SkipCancelledCheck != false) {
        output.WriteRawTag(72);
        output.WriteBool(SkipCancelledCheck);
      }
      if (ExpectedTransportSecurityType.Length != 0) {
        output.WriteRawTag(82);
        output.WriteString(ExpectedTransportSecurityType);
      }
      if (debugInfo_ != null) {
        output.WriteRawTag(90);
        output.WriteMessage(DebugInfo);
      }
      if (ServerDie != false) {
        output.WriteRawTag(96);
        output.WriteBool(ServerDie);
      }
      if (BinaryErrorDetails.Length != 0) {
        output.WriteRawTag(106);
        output.WriteString(BinaryErrorDetails);
      }
      if (expectedError_ != null) {
        output.WriteRawTag(114);
        output.WriteMessage(ExpectedError);
      }
      if (ServerSleepUs != 0) {
        output.WriteRawTag(120);
        output.WriteInt32(ServerSleepUs);
      }
      if (BackendChannelIdx != 0) {
        output.WriteRawTag(128, 1);
        output.WriteInt32(BackendChannelIdx);
      }
      if (_unknownFields != null) {
        _unknownFields.WriteTo(output);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      if (EchoDeadline != false) {
        size += 1 + 1;
      }
      if (ClientCancelAfterUs != 0) {
        size += 1 + pb::CodedOutputStream.ComputeInt32Size(ClientCancelAfterUs);
      }
      if (ServerCancelAfterUs != 0) {
        size += 1 + pb::CodedOutputStream.ComputeInt32Size(ServerCancelAfterUs);
      }
      if (EchoMetadata != false) {
        size += 1 + 1;
      }
      if (CheckAuthContext != false) {
        size += 1 + 1;
      }
      if (ResponseMessageLength != 0) {
        size += 1 + pb::CodedOutputStream.ComputeInt32Size(ResponseMessageLength);
      }
      if (EchoPeer != false) {
        size += 1 + 1;
      }
      if (ExpectedClientIdentity.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(ExpectedClientIdentity);
      }
      if (SkipCancelledCheck != false) {
        size += 1 + 1;
      }
      if (ExpectedTransportSecurityType.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(ExpectedTransportSecurityType);
      }
      if (debugInfo_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(DebugInfo);
      }
      if (ServerDie != false) {
        size += 1 + 1;
      }
      if (BinaryErrorDetails.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(BinaryErrorDetails);
      }
      if (expectedError_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(ExpectedError);
      }
      if (ServerSleepUs != 0) {
        size += 1 + pb::CodedOutputStream.ComputeInt32Size(ServerSleepUs);
      }
      if (BackendChannelIdx != 0) {
        size += 2 + pb::CodedOutputStream.ComputeInt32Size(BackendChannelIdx);
      }
      if (_unknownFields != null) {
        size += _unknownFields.CalculateSize();
      }
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(RequestParams other) {
      if (other == null) {
        return;
      }
      if (other.EchoDeadline != false) {
        EchoDeadline = other.EchoDeadline;
      }
      if (other.ClientCancelAfterUs != 0) {
        ClientCancelAfterUs = other.ClientCancelAfterUs;
      }
      if (other.ServerCancelAfterUs != 0) {
        ServerCancelAfterUs = other.ServerCancelAfterUs;
      }
      if (other.EchoMetadata != false) {
        EchoMetadata = other.EchoMetadata;
      }
      if (other.CheckAuthContext != false) {
        CheckAuthContext = other.CheckAuthContext;
      }
      if (other.ResponseMessageLength != 0) {
        ResponseMessageLength = other.ResponseMessageLength;
      }
      if (other.EchoPeer != false) {
        EchoPeer = other.EchoPeer;
      }
      if (other.ExpectedClientIdentity.Length != 0) {
        ExpectedClientIdentity = other.ExpectedClientIdentity;
      }
      if (other.SkipCancelledCheck != false) {
        SkipCancelledCheck = other.SkipCancelledCheck;
      }
      if (other.ExpectedTransportSecurityType.Length != 0) {
        ExpectedTransportSecurityType = other.ExpectedTransportSecurityType;
      }
      if (other.debugInfo_ != null) {
        if (debugInfo_ == null) {
          DebugInfo = new global::Grpc.Testing.DebugInfo();
        }
        DebugInfo.MergeFrom(other.DebugInfo);
      }
      if (other.ServerDie != false) {
        ServerDie = other.ServerDie;
      }
      if (other.BinaryErrorDetails.Length != 0) {
        BinaryErrorDetails = other.BinaryErrorDetails;
      }
      if (other.expectedError_ != null) {
        if (expectedError_ == null) {
          ExpectedError = new global::Grpc.Testing.ErrorStatus();
        }
        ExpectedError.MergeFrom(other.ExpectedError);
      }
      if (other.ServerSleepUs != 0) {
        ServerSleepUs = other.ServerSleepUs;
      }
      if (other.BackendChannelIdx != 0) {
        BackendChannelIdx = other.BackendChannelIdx;
      }
      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
            break;
          case 8: {
            EchoDeadline = input.ReadBool();
            break;
          }
          case 16: {
            ClientCancelAfterUs = input.ReadInt32();
            break;
          }
          case 24: {
            ServerCancelAfterUs = input.ReadInt32();
            break;
          }
          case 32: {
            EchoMetadata = input.ReadBool();
            break;
          }
          case 40: {
            CheckAuthContext = input.ReadBool();
            break;
          }
          case 48: {
            ResponseMessageLength = input.ReadInt32();
            break;
          }
          case 56: {
            EchoPeer = input.ReadBool();
            break;
          }
          case 66: {
            ExpectedClientIdentity = input.ReadString();
            break;
          }
          case 72: {
            SkipCancelledCheck = input.ReadBool();
            break;
          }
          case 82: {
            ExpectedTransportSecurityType = input.ReadString();
            break;
          }
          case 90: {
            if (debugInfo_ == null) {
              DebugInfo = new global::Grpc.Testing.DebugInfo();
            }
            input.ReadMessage(DebugInfo);
            break;
          }
          case 96: {
            ServerDie = input.ReadBool();
            break;
          }
          case 106: {
            BinaryErrorDetails = input.ReadString();
            break;
          }
          case 114: {
            if (expectedError_ == null) {
              ExpectedError = new global::Grpc.Testing.ErrorStatus();
            }
            input.ReadMessage(ExpectedError);
            break;
          }
          case 120: {
            ServerSleepUs = input.ReadInt32();
            break;
          }
          case 128: {
            BackendChannelIdx = input.ReadInt32();
            break;
          }
        }
      }
    }

  }

  public sealed partial class EchoRequest : pb::IMessage<EchoRequest> {
    private static readonly pb::MessageParser<EchoRequest> _parser = new pb::MessageParser<EchoRequest>(() => new EchoRequest());
    private pb::UnknownFieldSet _unknownFields;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<EchoRequest> Parser { get { return _parser; } }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Grpc.Testing.EchoMessagesReflection.Descriptor.MessageTypes[3]; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public EchoRequest() {
      OnConstruction();
    }

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public EchoRequest(EchoRequest other) : this() {
      message_ = other.message_;
      param_ = other.param_ != null ? other.param_.Clone() : null;
      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public EchoRequest Clone() {
      return new EchoRequest(this);
    }

    /// <summary>Field number for the "message" field.</summary>
    public const int MessageFieldNumber = 1;
    private string message_ = "";
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public string Message {
      get { return message_; }
      set {
        message_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
      }
    }

    /// <summary>Field number for the "param" field.</summary>
    public const int ParamFieldNumber = 2;
    private global::Grpc.Testing.RequestParams param_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Testing.RequestParams Param {
      get { return param_; }
      set {
        param_ = value;
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override bool Equals(object other) {
      return Equals(other as EchoRequest);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(EchoRequest other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (Message != other.Message) return false;
      if (!object.Equals(Param, other.Param)) return false;
      return Equals(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (Message.Length != 0) hash ^= Message.GetHashCode();
      if (param_ != null) hash ^= Param.GetHashCode();
      if (_unknownFields != null) {
        hash ^= _unknownFields.GetHashCode();
      }
      return hash;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override string ToString() {
      return pb::JsonFormatter.ToDiagnosticString(this);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void WriteTo(pb::CodedOutputStream output) {
      if (Message.Length != 0) {
        output.WriteRawTag(10);
        output.WriteString(Message);
      }
      if (param_ != null) {
        output.WriteRawTag(18);
        output.WriteMessage(Param);
      }
      if (_unknownFields != null) {
        _unknownFields.WriteTo(output);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      if (Message.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(Message);
      }
      if (param_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Param);
      }
      if (_unknownFields != null) {
        size += _unknownFields.CalculateSize();
      }
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(EchoRequest other) {
      if (other == null) {
        return;
      }
      if (other.Message.Length != 0) {
        Message = other.Message;
      }
      if (other.param_ != null) {
        if (param_ == null) {
          Param = new global::Grpc.Testing.RequestParams();
        }
        Param.MergeFrom(other.Param);
      }
      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
            break;
          case 10: {
            Message = input.ReadString();
            break;
          }
          case 18: {
            if (param_ == null) {
              Param = new global::Grpc.Testing.RequestParams();
            }
            input.ReadMessage(Param);
            break;
          }
        }
      }
    }

  }

  public sealed partial class ResponseParams : pb::IMessage<ResponseParams> {
    private static readonly pb::MessageParser<ResponseParams> _parser = new pb::MessageParser<ResponseParams>(() => new ResponseParams());
    private pb::UnknownFieldSet _unknownFields;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<ResponseParams> Parser { get { return _parser; } }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Grpc.Testing.EchoMessagesReflection.Descriptor.MessageTypes[4]; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ResponseParams() {
      OnConstruction();
    }

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ResponseParams(ResponseParams other) : this() {
      requestDeadline_ = other.requestDeadline_;
      host_ = other.host_;
      peer_ = other.peer_;
      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ResponseParams Clone() {
      return new ResponseParams(this);
    }

    /// <summary>Field number for the "request_deadline" field.</summary>
    public const int RequestDeadlineFieldNumber = 1;
    private long requestDeadline_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public long RequestDeadline {
      get { return requestDeadline_; }
      set {
        requestDeadline_ = value;
      }
    }

    /// <summary>Field number for the "host" field.</summary>
    public const int HostFieldNumber = 2;
    private string host_ = "";
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public string Host {
      get { return host_; }
      set {
        host_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
      }
    }

    /// <summary>Field number for the "peer" field.</summary>
    public const int PeerFieldNumber = 3;
    private string peer_ = "";
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public string Peer {
      get { return peer_; }
      set {
        peer_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override bool Equals(object other) {
      return Equals(other as ResponseParams);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(ResponseParams other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (RequestDeadline != other.RequestDeadline) return false;
      if (Host != other.Host) return false;
      if (Peer != other.Peer) return false;
      return Equals(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (RequestDeadline != 0L) hash ^= RequestDeadline.GetHashCode();
      if (Host.Length != 0) hash ^= Host.GetHashCode();
      if (Peer.Length != 0) hash ^= Peer.GetHashCode();
      if (_unknownFields != null) {
        hash ^= _unknownFields.GetHashCode();
      }
      return hash;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override string ToString() {
      return pb::JsonFormatter.ToDiagnosticString(this);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void WriteTo(pb::CodedOutputStream output) {
      if (RequestDeadline != 0L) {
        output.WriteRawTag(8);
        output.WriteInt64(RequestDeadline);
      }
      if (Host.Length != 0) {
        output.WriteRawTag(18);
        output.WriteString(Host);
      }
      if (Peer.Length != 0) {
        output.WriteRawTag(26);
        output.WriteString(Peer);
      }
      if (_unknownFields != null) {
        _unknownFields.WriteTo(output);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      if (RequestDeadline != 0L) {
        size += 1 + pb::CodedOutputStream.ComputeInt64Size(RequestDeadline);
      }
      if (Host.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(Host);
      }
      if (Peer.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(Peer);
      }
      if (_unknownFields != null) {
        size += _unknownFields.CalculateSize();
      }
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(ResponseParams other) {
      if (other == null) {
        return;
      }
      if (other.RequestDeadline != 0L) {
        RequestDeadline = other.RequestDeadline;
      }
      if (other.Host.Length != 0) {
        Host = other.Host;
      }
      if (other.Peer.Length != 0) {
        Peer = other.Peer;
      }
      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
            break;
          case 8: {
            RequestDeadline = input.ReadInt64();
            break;
          }
          case 18: {
            Host = input.ReadString();
            break;
          }
          case 26: {
            Peer = input.ReadString();
            break;
          }
        }
      }
    }

  }

  public sealed partial class EchoResponse : pb::IMessage<EchoResponse> {
    private static readonly pb::MessageParser<EchoResponse> _parser = new pb::MessageParser<EchoResponse>(() => new EchoResponse());
    private pb::UnknownFieldSet _unknownFields;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<EchoResponse> Parser { get { return _parser; } }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Grpc.Testing.EchoMessagesReflection.Descriptor.MessageTypes[5]; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public EchoResponse() {
      OnConstruction();
    }

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public EchoResponse(EchoResponse other) : this() {
      message_ = other.message_;
      param_ = other.param_ != null ? other.param_.Clone() : null;
      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public EchoResponse Clone() {
      return new EchoResponse(this);
    }

    /// <summary>Field number for the "message" field.</summary>
    public const int MessageFieldNumber = 1;
    private string message_ = "";
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public string Message {
      get { return message_; }
      set {
        message_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
      }
    }

    /// <summary>Field number for the "param" field.</summary>
    public const int ParamFieldNumber = 2;
    private global::Grpc.Testing.ResponseParams param_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Testing.ResponseParams Param {
      get { return param_; }
      set {
        param_ = value;
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override bool Equals(object other) {
      return Equals(other as EchoResponse);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(EchoResponse other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (Message != other.Message) return false;
      if (!object.Equals(Param, other.Param)) return false;
      return Equals(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (Message.Length != 0) hash ^= Message.GetHashCode();
      if (param_ != null) hash ^= Param.GetHashCode();
      if (_unknownFields != null) {
        hash ^= _unknownFields.GetHashCode();
      }
      return hash;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override string ToString() {
      return pb::JsonFormatter.ToDiagnosticString(this);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void WriteTo(pb::CodedOutputStream output) {
      if (Message.Length != 0) {
        output.WriteRawTag(10);
        output.WriteString(Message);
      }
      if (param_ != null) {
        output.WriteRawTag(18);
        output.WriteMessage(Param);
      }
      if (_unknownFields != null) {
        _unknownFields.WriteTo(output);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      if (Message.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(Message);
      }
      if (param_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Param);
      }
      if (_unknownFields != null) {
        size += _unknownFields.CalculateSize();
      }
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(EchoResponse other) {
      if (other == null) {
        return;
      }
      if (other.Message.Length != 0) {
        Message = other.Message;
      }
      if (other.param_ != null) {
        if (param_ == null) {
          Param = new global::Grpc.Testing.ResponseParams();
        }
        Param.MergeFrom(other.Param);
      }
      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
            break;
          case 10: {
            Message = input.ReadString();
            break;
          }
          case 18: {
            if (param_ == null) {
              Param = new global::Grpc.Testing.ResponseParams();
            }
            input.ReadMessage(Param);
            break;
          }
        }
      }
    }

  }

  #endregion

}

#endregion Designer generated code
