LogCabin
RPC/Protocol.h
Go to the documentation of this file.
00001 /* Copyright (c) 2012 Stanford University
00002  *
00003  * Permission to use, copy, modify, and distribute this software for any
00004  * purpose with or without fee is hereby granted, provided that the above
00005  * copyright notice and this permission notice appear in all copies.
00006  *
00007  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR(S) DISCLAIM ALL WARRANTIES
00008  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
00009  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHORS BE LIABLE FOR
00010  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00011  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
00012  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
00013  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00014  */
00015 
00016 /**
00017  * \file
00018  * This file contains the headers used in all high-level RPCs.
00019  */
00020 
00021 #include <cinttypes>
00022 #include <ostream>
00023 
00024 #ifndef LOGCABIN_RPC_PROTOCOL_H
00025 #define LOGCABIN_RPC_PROTOCOL_H
00026 
00027 namespace LogCabin {
00028 namespace RPC {
00029 namespace Protocol {
00030 
00031 /**
00032  * This is the first part of the request header that RPC clients send, common
00033  * to all versions of the protocol. RPC servers can always expect to receive
00034  * this and RPC clients must always send this.
00035  * This needs to be separate struct because when a server receives a request,
00036  * it does not know the type of the request header, as that depends on its
00037  * version.
00038  */
00039 struct RequestHeaderPrefix {
00040     /**
00041      * Convert the contents to host order from big endian (how this header
00042      * should be transferred on the network).
00043      */
00044     void fromBigEndian();
00045     /**
00046      * Convert the contents to big endian (how this header should be
00047      * transferred on the network) from host order.
00048      */
00049     void toBigEndian();
00050 
00051     /**
00052      * This is the version of the protocol. It should always be set to 1 for
00053      * now.
00054      */
00055     uint8_t version;
00056 
00057 } __attribute__((packed));
00058 
00059 /**
00060  * In version 1 of the protocol, this is the header format for requests from
00061  * clients to servers.
00062  */
00063 struct RequestHeaderVersion1 {
00064     /**
00065      * Convert the contents to host order from big endian (how this header
00066      * should be transferred on the network).
00067      * \warning
00068      *      This does not modify #prefix.
00069      */
00070     void fromBigEndian();
00071     /**
00072      * Convert the contents to big endian (how this header should be
00073      * transferred on the network) from host order.
00074      * \warning
00075      *      This does not modify #prefix.
00076      */
00077     void toBigEndian();
00078 
00079     /**
00080      * This is common to all versions of the protocol. RPC servers can always
00081      * expect to receive this and RPC clients must always send this.
00082      */
00083     RequestHeaderPrefix prefix;
00084 
00085     /**
00086      * This identifies which Service the RPC is destined for.
00087      * See Protocol::Common::ServiceId.
00088      */
00089     uint16_t service;
00090 
00091     /**
00092      * This field tells the service what service-specific errors the client
00093      * understands. Clients should remain backwards-compatible, so that newer
00094      * clients can understand older errors. Services should take care not to
00095      * send a client a service-specific error that it doesn't understand.
00096      */
00097     uint8_t serviceSpecificErrorVersion;
00098 
00099     /**
00100      * This identifies which RPC is being executed, scoped to the service.
00101      */
00102     uint16_t opCode;
00103 
00104 } __attribute__((packed));
00105 
00106 /**
00107  * The status codes returned in server responses.
00108  */
00109 enum class Status : uint8_t {
00110 
00111     /**
00112      * The service processed the request and returned a valid protocol buffer
00113      * with the results.
00114      */
00115     OK = 0,
00116 
00117     /**
00118      * An error specific to the particular service. The format of the remainder
00119      * of the message is specific to the particular service.
00120      */
00121     SERVICE_SPECIFIC_ERROR = 1,
00122 
00123     /**
00124      * The server did not like the version number provided in the request
00125      * header. If the client gets this, it should fall back to an older version
00126      * number or crash.
00127      */
00128     INVALID_VERSION = 2,
00129 
00130     /**
00131      * The server does not have the requested service.
00132      */
00133     INVALID_SERVICE = 3,
00134 
00135     /**
00136      * The server did not like the RPC request. Either it specified an opCode
00137      * the server didn't understand or a request protocol buffer the server
00138      * couldn't accept. The client should avoid ever getting this by
00139      * negotiating with the server about which version of the RPC protocol to
00140      * use.
00141      */
00142     INVALID_REQUEST = 4,
00143 
00144 };
00145 
00146 /// Output a Status to a stream. Improves gtest error messages.
00147 ::std::ostream&
00148 operator<<(::std::ostream& stream, Status status);
00149 
00150 /**
00151  * This is the first part of the response header that servers send, common to
00152  * all versions of the protocol. RPC clients can always expect to receive this
00153  * and RPC servers must always send this.
00154  * This needs to be separate struct because when a client receives a response,
00155  * it might have a status of INVALID_VERSION, in which case the client may not
00156  * assume anything about the remaining bytes in the message.
00157  */
00158 struct ResponseHeaderPrefix {
00159     /**
00160      * Convert the contents to host order from big endian (how this header
00161      * should be transferred on the network).
00162      */
00163     void fromBigEndian();
00164     /**
00165      * Convert the contents to big endian (how this header should be
00166      * transferred on the network) from host order.
00167      */
00168     void toBigEndian();
00169 
00170     /**
00171      * The error code returned by the server.
00172      */
00173     Status status;
00174 
00175     // If status != INVALID_VERSION, the response should be cast
00176     // to the appropriate ResponseHeaderVersion# struct.
00177 } __attribute__((packed));
00178 
00179 /**
00180  * In version 1 of the protocol, this is the header format for RPC responses.
00181  */
00182 struct ResponseHeaderVersion1 {
00183     /**
00184      * Convert the contents to host order from big endian (how this header
00185      * should be transferred on the network). This is just here for
00186      * completeness, as this header has no fields of its own.
00187      * \warning
00188      *      This does not modify #prefix.
00189      */
00190     void fromBigEndian();
00191     /**
00192      * Convert the contents to big endian (how this header should be
00193      * transferred on the network) from host order. This is just here for
00194      * completeness, as this header has no fields of its own.
00195      * \warning
00196      *      This does not modify #prefix.
00197      */
00198     void toBigEndian();
00199 
00200     /**
00201      * This is common to all versions of the protocol. RPC clients can always
00202      * expect to receive this and RPC servers must always send this.
00203      */
00204     ResponseHeaderPrefix prefix;
00205 
00206 } __attribute__((packed));
00207 
00208 } // namespace LogCabin::RPC::Protocol
00209 } // namespace LogCabin::RPC
00210 } // namespace LogCabin
00211 
00212 #endif // LOGCABIN_RPC_PROTOCOL_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines