syntax = "proto3";

package berty.bridge.v1;

import "berty/errcode.proto";

option go_package = "berty.tech/berty/go/pkg/bertybridge";

// BridgeService used to create advanced grpc transport
// /!\ UNARY SUPPORT ONLY /!\
service BridgeService {
  // ClientInvokeUnary invoke a unary method
  rpc ClientInvokeUnary (ClientInvokeUnary.Request) returns (ClientInvokeUnary.Reply);

  // CreateStream create a stream
  rpc CreateClientStream (ClientCreateStream.Request) returns (ClientCreateStream.Reply);

  // Send Message over the given stream
  rpc ClientStreamSend (ClientStreamSend.Request) returns (ClientStreamSend.Reply);

  // Recv message over the given stream
  rpc ClientStreamRecv (ClientStreamRecv.Request) returns (ClientStreamRecv.Reply);

  // Close the given stream (should not be used)
  rpc ClientStreamClose (ClientStreamClose.Request) returns (ClientStreamClose.Reply);

  // Close the writing end of a stream and return the next reply
  rpc ClientStreamCloseAndRecv (ClientStreamCloseAndRecv.Request) returns (ClientStreamCloseAndRecv.Reply);
}

message ClientInvokeUnary {
  message Request {
    MethodDesc method_desc = 2;
    bytes payload = 3;
    repeated Metadata header = 4;
  }
  message Reply {
    bytes payload = 2;
    repeated Metadata trailer = 3;
    Error error = 4;
  }
}

message ClientCreateStream {
  message Request {
    MethodDesc method_desc = 2;
    bytes payload = 3;
    repeated Metadata header = 4;
  }
  message Reply {
    string stream_id = 1;
    repeated Metadata trailer = 2;
    Error error = 3;
  }
}

message ClientStreamSend {
  message Request {
    string stream_id = 1;
    bytes payload = 2;
  }
  message Reply {
    string stream_id = 1;
    repeated Metadata trailer = 2;
    Error error = 3;
  }
}

message ClientStreamRecv {
  message Request {
    string stream_id = 1;
  }
  message Reply {
    string stream_id = 1;
    bytes payload = 2;
    repeated Metadata trailer = 3;
    Error error = 4;
  };
}

message ClientStreamClose {
  message Request {
    string stream_id = 1;
  }
  message Reply {
    string stream_id = 1;
    repeated Metadata trailer = 2;
    Error error = 3;
  };
}

message ClientStreamCloseAndRecv {
  message Request {
    string stream_id = 1;
  }
  message Reply {
    string stream_id = 1;
    bytes payload = 2;
    repeated Metadata trailer = 3;
    Error error = 4;
  };
}

// Common

message MethodDesc {
  // Name is the method name only, without the service name or package name.
  string name = 1;
  // IsClientStream indicates whether the RPC is a client streaming RPC.
  bool is_client_stream = 2;
  // IsServerStream indicates whether the RPC is a server streaming RPC.
  bool is_server_stream = 3;
}

message Metadata {
  string key = 1;
  repeated string values = 2;
}

message Error {
  // grpc error code
  GRPCErrCode grpc_error_code = 1;
  // toplevel error
  errcode.ErrCode error_code = 2;
  // toplevel error message
  string message = 3;
  // detailed errors
  errcode.ErrDetails error_details = 4;
}

enum GRPCErrCode {
  // OK is returned on success.
  OK = 0;

  // Canceled indicates the operation was canceled (typically by the caller).
  //
  // The gRPC framework will generate this error code when cancellation
  // is requested.
  CANCELED = 1;

  // Unknown error. An example of where this error may be returned is
  // if a Status value received from another address space belongs to
  // an error-space that is not known in this address space. Also
  // errors raised by APIs that do not return enough error information
  // may be converted to this error.
  //
  // The gRPC framework will generate this error code in the above two
  // mentioned cases.
  UNKNOWN = 2;

  // InvalidArgument indicates client specified an invalid argument.
  // Note that this differs from FailedPrecondition. It indicates arguments
  // that are problematic regardless of the state of the system
  // (e.g., a malformed file name).
  //
  // This error code will not be generated by the gRPC framework.
  INVALID_ARGUMENT = 3;

  // DeadlineExceeded means operation expired before completion.
  // For operations that change the state of the system, this error may be
  // returned even if the operation has completed successfully. For
  // example, a successful response from a server could have been delayed
  // long enough for the deadline to expire.
  //
  // The gRPC framework will generate this error code when the deadline is
  // exceeded.
  DEADLINE_EXCEEDED = 4;

  // NotFound means some requested entity (e.g., file or directory) was
  // not found.
  //
  // This error code will not be generated by the gRPC framework.
  NOT_FOUND = 5;

  // AlreadyExists means an attempt to create an entity failed because one
  // already exists.
  //
  // This error code will not be generated by the gRPC framework.
  ALREADY_EXISTS = 6;

  // PermissionDenied indicates the caller does not have permission to
  // execute the specified operation. It must not be used for rejections
  // caused by exhausting some resource (use ResourceExhausted
  // instead for those errors). It must not be
  // used if the caller cannot be identified (use Unauthenticated
  // instead for those errors).
  //
  // This error code will not be generated by the gRPC core framework,
  // but expect authentication middleware to use it.
  PERMISSION_DENIED = 7;

  // ResourceExhausted indicates some resource has been exhausted, perhaps
  // a per-user quota, or perhaps the entire file system is out of space.
  //
  // This error code will be generated by the gRPC framework in
  // out-of-memory and server overload situations, or when a message is
  // larger than the configured maximum size.
  RESOURCE_EXHAUSTED = 8;

  // FailedPrecondition indicates operation was rejected because the
  // system is not in a state required for the operation's execution.
  // For example, directory to be deleted may be non-empty, an rmdir
  // operation is applied to a non-directory, etc.
  //
  // A litmus test that may help a service implementor in deciding
  // between FailedPrecondition, Aborted, and Unavailable:
  //  (a) Use Unavailable if the client can retry just the failing call.
  //  (b) Use Aborted if the client should retry at a higher-level
  //      (e.g., restarting a read-modify-write sequence).
  //  (c) Use FailedPrecondition if the client should not retry until
  //      the system state has been explicitly fixed. E.g., if an "rmdir"
  //      fails because the directory is non-empty, FailedPrecondition
  //      should be returned since the client should not retry unless
  //      they have first fixed up the directory by deleting files from it.
  //  (d) Use FailedPrecondition if the client performs conditional
  //      REST Get/Update/Delete on a resource and the resource on the
  //      server does not match the condition. E.g., conflicting
  //      read-modify-write on the same resource.
  //
  // This error code will not be generated by the gRPC framework.
  FAILED_PRECONDITION = 9;

  // Aborted indicates the operation was aborted, typically due to a
  // concurrency issue like sequencer check failures, transaction aborts,
  // etc.
  //
  // See litmus test above for deciding between FailedPrecondition,
  // Aborted, and Unavailable.
  //
  // This error code will not be generated by the gRPC framework.
  ABORTED = 10;

  // OutOfRange means operation was attempted past the valid range.
  // E.g., seeking or reading past end of file.
  //
  // Unlike InvalidArgument, this error indicates a problem that may
  // be fixed if the system state changes. For example, a 32-bit file
  // system will generate InvalidArgument if asked to read at an
  // offset that is not in the range [0,2^32-1], but it will generate
  // OutOfRange if asked to read from an offset past the current
  // file size.
  //
  // There is a fair bit of overlap between FailedPrecondition and
  // OutOfRange. We recommend using OutOfRange (the more specific
  // error) when it applies so that callers who are iterating through
  // a space can easily look for an OutOfRange error to detect when
  // they are done.
  //
  // This error code will not be generated by the gRPC framework.
  OUT_OF_RANGE = 11;

  // Unimplemented indicates operation is not implemented or not
  // supported/enabled in this service.
  //
  // This error code will be generated by the gRPC framework. Most
  // commonly, you will see this error code when a method implementation
  // is missing on the server. It can also be generated for unknown
  // compression algorithms or a disagreement as to whether an RPC should
  // be streaming.
  UNIMPLEMENTED = 12;

  // Internal errors. Means some invariants expected by underlying
  // system has been broken. If you see one of these errors,
  // something is very broken.
  //
  // This error code will be generated by the gRPC framework in several
  // internal error conditions.
  INTERNAL = 13;

  // Unavailable indicates the service is currently unavailable.
  // This is a most likely a transient condition and may be corrected
  // by retrying with a backoff. Note that it is not always safe to retry
  // non-idempotent operations.
  //
  // See litmus test above for deciding between FailedPrecondition,
  // Aborted, and Unavailable.
  //
  // This error code will be generated by the gRPC framework during
  // abrupt shutdown of a server process or network connection.
  UNAVAILABLE = 14;

  // DataLoss indicates unrecoverable data loss or corruption.
  //
  // This error code will not be generated by the gRPC framework.
  DATA_LOSS = 15;

  // Unauthenticated indicates the request does not have valid
  // authentication credentials for the operation.
  //
  // The gRPC framework will generate this error code when the
  // authentication metadata is invalid or a Credentials callback fails,
  // but also expect authentication middleware to generate it.
  UNAUTHENTICATED = 16;
}
