| // Copyright 2015 The Vanadium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package rpc |
| |
| import ( |
| "time" |
| "v.io/v23/security" |
| "v.io/v23/vtrace" |
| ) |
| |
| // The communications between a client and server is based on RPCs. Assume a |
| // server published on object name "a/b/c" implements the following method: |
| // |
| // type myServer struct{} |
| // func (myServer) Method(_ ServerCall, a0 int, a1 string) (r0 uint, err error) { |
| // return 123, nil |
| // } |
| // |
| // A client trying to call the method looks like: |
| // |
| // call, err := client.StartCall("a/b/c", "Method", []interface{}{1, "a"}) |
| // var result uint |
| // err = call.Finish(&result) |
| // |
| // The client resolves "a/b/c" to an endpoint, establishes an authenticated |
| // connection with the endpoint and exchanges RPC requests/responses over it. |
| // |
| // ##### Non-streaming RPC call ##### |
| // |
| // # Client sends request header and positional in-args to server. |
| // Request{Suffix:"", Method:"Method", NumPosArgs:2, EndStreamArgs:true} --> |
| // int(1) --> |
| // string("a") --> |
| // |
| // # Server sends response header and positional out-args to client. |
| // <-- Response{Error: err, EndStreamResults: true, NumPosResults: 1} |
| // <-- int(123) |
| // |
| // ##### Streaming RPC call ##### |
| // |
| // # Client sends request header and positional in-args to server. |
| // Request{Suffix:"", Method:"Method", NumPosArgs:2} --> |
| // int(1) --> |
| // string("a") --> |
| // |
| // # Client and server exchange streaming args and results. Each arg (or |
| // # result) is preceeded by a zero-value Request (or Response) header. The |
| // # EndStream* fields will cause the other end to read io.EOF. |
| // # |
| // # The request / response sequencing protocol is left up to the user. E.g. |
| // # the client may be the only one streaming to the server, or vice versa. |
| // # Or the server may send a response only after each group of N client |
| // # requests, or vice versa. Or the protocol may be dynamic, based on the |
| // # arg and result values. The client and server implement their protocol |
| // # by structuring their Send and Recv calls on both ends, and sending the |
| // # EOF at the appropriate time. |
| // # |
| // # Here's one example that uses synchronized request / response. |
| // Request{} --> |
| // streamingArg0{...} --> |
| // <-- Response{} |
| // <-- streamingResult0{...} |
| // ... |
| // Request{} --> |
| // streamingArgN{...} --> |
| // <-- Response{} |
| // <-- streamingResultN{...} |
| // Request{EndStreamArgs:true} --> |
| // |
| // # Server sends response header and positional out-args to client. |
| // <-- Response{Error: err, EndStreamResults: true, NumPosResults: 1} |
| // <-- int(123) |
| |
| // Request describes the request header sent by the client to the server. A |
| // non-zero request header is sent at the beginning of the RPC call, followed by |
| // the positional args. Thereafter a zero request header is sent before each |
| // streaming arg, terminated by a non-zero request header with EndStreamArgs set |
| // to true. |
| type Request struct { |
| // Suffix of the name used to identify the object hosting the service. |
| Suffix string |
| |
| // Method to invoke on the service. |
| Method string |
| |
| // NumPosArgs is the number of positional arguments, which follow this message |
| // (and any blessings) on the request stream. |
| NumPosArgs uint64 |
| |
| // EndStreamArgs is true iff no more streaming arguments will be sent. No |
| // more data will be sent on the request stream. |
| // |
| // NOTE(bprosnitz): We can support multiple stream values per request (+response) header |
| // efficiently by adding a NumExtraStreamArgs (+NumExtraStreamResults to response) field |
| // that is the uint64 (number of stream args to send) - 1. The request is then zero when |
| // exactly one streaming arg is sent. Since the request and response headers are small, |
| // this is only likely necessary for frequently streaming small values. |
| // See implementation in CL: 3913 |
| EndStreamArgs bool |
| |
| // Deadline after which the request should be cancelled. This is a hint to |
| // the server, to avoid wasted work. |
| Deadline time.WireDeadline |
| |
| // GrantedBlessings are blessings bound to the principal running the server, |
| // provided by the client. |
| GrantedBlessings security.WireBlessings |
| |
| // Blessings is the blessings of the Client used for the current RPC. |
| Blessings BlessingsRequest |
| |
| // Discharges are third party caveat discharges that may be required |
| // to make Blessings valid. |
| Discharges []security.WireDischarge |
| |
| // TraceRequest maintains the vtrace context between clients and servers |
| // and specifies additional parameters that control how tracing behaves. |
| TraceRequest vtrace.Request |
| |
| // Language indicates the language of the instegator of the RPC. |
| // By convention it should be an IETF language tag: |
| // http://en.wikipedia.org/wiki/IETF_language_tag |
| Language string |
| } |
| |
| // Response describes the response header sent by the server to the client. A |
| // zero response header is sent before each streaming arg. Thereafter a |
| // non-zero response header is sent at the end of the RPC call, right before |
| // the positional results. |
| type Response struct { |
| // Error in processing the RPC at the server. Implies EndStreamResults. |
| Error error |
| |
| // EndStreamResults is true iff no more streaming results will be sent; the |
| // remainder of the stream consists of NumPosResults positional results. |
| EndStreamResults bool |
| |
| // NumPosResults is the number of positional results, which immediately follow |
| // on the response stream. After these results, no further data will be sent |
| // on the response stream. |
| NumPosResults uint64 |
| |
| // TraceResponse maintains the vtrace context between clients and servers. |
| // In some cases trace data will be included in this response as well. |
| TraceResponse vtrace.Response |
| |
| // AckBlessings is true if the server successfully recevied the client's |
| // blessings and stored them in the server's blessings cache. |
| AckBlessings bool |
| } |
| |
| // BlessingsRequest represents security.Blessings for a particular request. |
| // Since multiple requests on the same authenticated connection often use the |
| // same blessings, we implement a caching scheme, where the client picks an |
| // unused key and sends it along with the blessings. After the client receives |
| // confirmation that the server has received the key, subsequent client requests |
| // only send the key. |
| // |
| // If BlessingRequest.Key is 0, the Client is running in SecurityNone and the |
| // Blessings information should ignored. |
| type BlessingsRequest struct { |
| // Key is the required key that the Client has cached Blessings with. |
| Key uint64 |
| |
| // Blessings is optional if the Server has already been notified of Key. |
| Blessings ?security.WireBlessings |
| } |
| |
| // The reserved method names that we currently understand. |
| const ( |
| // TODO(toddw): Rename GlobMethod to ReservedGlob. |
| GlobMethod = "__Glob" |
| ReservedSignature = "__Signature" |
| ReservedMethodSignature = "__MethodSignature" |
| ) |