LogCabin
|
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