1 //
2 // Copyright (c) ZeroC, Inc. All rights reserved.
3 //
4 
5 #ifndef ICE_PROTOCOL_H
6 #define ICE_PROTOCOL_H
7 
8 #include <Ice/Config.h>
9 #include <Ice/Version.h>
10 
11 namespace IceInternal
12 {
13 
14 //
15 // Size of the Ice protocol header
16 //
17 // Magic number (4 Bytes)
18 // Protocol version major (Byte)
19 // Protocol version minor (Byte)
20 // Encoding version major (Byte)
21 // Encoding version minor (Byte)
22 // Message type (Byte)
23 // Compression status (Byte)
24 // Message size (Int)
25 //
26 const ::Ice::Int headerSize = 14;
27 
28 //
29 // The magic number at the front of each message
30 //
31 extern const ::Ice::Byte magic[4];
32 
33 //
34 // The current Ice protocol, protocol encoding and encoding version
35 //
36 const ::Ice::Byte protocolMajor = 1;
37 const ::Ice::Byte protocolMinor = 0;
38 const ::Ice::Byte protocolEncodingMajor = 1;
39 const ::Ice::Byte protocolEncodingMinor = 0;
40 
41 const ::Ice::Byte encodingMajor = 1;
42 const ::Ice::Byte encodingMinor = 1;
43 
44 //
45 // The Ice protocol message types
46 //
47 const ::Ice::Byte requestMsg = 0;
48 const ::Ice::Byte requestBatchMsg = 1;
49 const ::Ice::Byte replyMsg = 2;
50 const ::Ice::Byte validateConnectionMsg = 3;
51 const ::Ice::Byte closeConnectionMsg = 4;
52 
53 //
54 // The request header, batch request header and reply header.
55 //
56 extern const ::Ice::Byte requestHdr[headerSize + sizeof(Ice::Int)];
57 extern const ::Ice::Byte requestBatchHdr[headerSize + sizeof(Ice::Int)];
58 extern const ::Ice::Byte replyHdr[headerSize];
59 
60 //
61 // IPv4/IPv6 support enumeration.
62 //
63 enum ProtocolSupport
64 {
65     EnableIPv4,
66     EnableIPv6,
67     EnableBoth
68 };
69 
70 ICE_API void stringToMajorMinor(const ::std::string&, Ice::Byte&, Ice::Byte&);
71 
72 template<typename T> std::string
versionToString(const T & v)73 versionToString(const T& v)
74 {
75     std::ostringstream os;
76     os << v;
77     return os.str();
78 }
79 
80 template<typename T> T
stringToVersion(const::std::string & str)81 stringToVersion(const ::std::string& str)
82 {
83     T v;
84     stringToMajorMinor(str, v.major, v.minor);
85     return v;
86 }
87 
88 template<typename T> bool
isSupported(const T & version,const T & supported)89 isSupported(const T& version, const T& supported)
90 {
91     return version.major == supported.major && version.minor <= supported.minor;
92 }
93 
94 ICE_API void throwUnsupportedProtocolException(const char*, int, const Ice::ProtocolVersion&,
95                                                const Ice::ProtocolVersion&);
96 ICE_API void throwUnsupportedEncodingException(const char*, int, const Ice::EncodingVersion&,
97                                                const Ice::EncodingVersion&);
98 
99 const ::Ice::Byte OPTIONAL_END_MARKER        = 0xFF;
100 
101 const ::Ice::Byte FLAG_HAS_TYPE_ID_STRING    = (1<<0);
102 const ::Ice::Byte FLAG_HAS_TYPE_ID_INDEX     = (1<<1);
103 const ::Ice::Byte FLAG_HAS_TYPE_ID_COMPACT   = (1<<0) | (1<<1);
104 const ::Ice::Byte FLAG_HAS_OPTIONAL_MEMBERS  = (1<<2);
105 const ::Ice::Byte FLAG_HAS_INDIRECTION_TABLE = (1<<3);
106 const ::Ice::Byte FLAG_HAS_SLICE_SIZE        = (1<<4);
107 const ::Ice::Byte FLAG_IS_LAST_SLICE         = (1<<5);
108 
109 }
110 
111 namespace Ice
112 {
113 
114 /** Identifies protocol version 1.0. */
115 ICE_API extern const ProtocolVersion Protocol_1_0;
116 
117 /** Identifies encoding version 1.0. */
118 ICE_API extern const EncodingVersion Encoding_1_0;
119 
120 /** Identifies encoding version 1.1. */
121 ICE_API extern const EncodingVersion Encoding_1_1;
122 
123 /** Identifies the latest protocol version. */
124 ICE_API extern const ProtocolVersion currentProtocol;
125 
126 /** Identifies the latest protocol encoding version. */
127 ICE_API extern const EncodingVersion currentProtocolEncoding;
128 
129 /** Identifies the latest encoding version. */
130 ICE_API extern const EncodingVersion currentEncoding;
131 
132 /**
133  * Converts a protocol version into a string.
134  * @param v The protocol version.
135  * @return A string representing the protocol version.
136  */
137 inline ::std::string
protocolVersionToString(const Ice::ProtocolVersion & v)138 protocolVersionToString(const Ice::ProtocolVersion& v)
139 {
140     return IceInternal::versionToString<ProtocolVersion>(v);
141 }
142 
143 /**
144  * Converts a string into a protocol version.
145  * @param v The string containing a stringified protocol version.
146  * @return The protocol version.
147  * @throws VersionParseException If the given string is not in the X.Y format.
148  */
149 inline ::Ice::ProtocolVersion
stringToProtocolVersion(const::std::string & v)150 stringToProtocolVersion(const ::std::string& v)
151 {
152     return IceInternal::stringToVersion<ProtocolVersion>(v);
153 }
154 
155 /**
156  * Converts an encoding version into a string.
157  * @param v The encoding version.
158  * @return A string representing the encoding version.
159  */
160 inline ::std::string
encodingVersionToString(const Ice::EncodingVersion & v)161 encodingVersionToString(const Ice::EncodingVersion& v)
162 {
163     return IceInternal::versionToString<EncodingVersion>(v);
164 }
165 
166 /**
167  * Converts a string into an encoding version.
168  * @param v The string containing a stringified encoding version.
169  * @return The encoding version.
170  * @throws VersionParseException If the given string is not in the X.Y format.
171  */
172 inline ::Ice::EncodingVersion
stringToEncodingVersion(const::std::string & v)173 stringToEncodingVersion(const ::std::string& v)
174 {
175     return IceInternal::stringToVersion<EncodingVersion>(v);
176 }
177 
178 inline std::ostream&
179 operator<<(std::ostream& out, const ProtocolVersion& version)
180 {
181     return out << static_cast<int>(version.major) << "." << static_cast<int>(version.minor);
182 }
183 
184 inline std::ostream&
185 operator<<(std::ostream& out, const EncodingVersion& version)
186 {
187     return out << static_cast<int>(version.major) << "." << static_cast<int>(version.minor);
188 }
189 
190 }
191 
192 namespace IceInternal
193 {
194 
195 inline void
checkSupportedProtocol(const Ice::ProtocolVersion & v)196 checkSupportedProtocol(const Ice::ProtocolVersion& v)
197 {
198     if(!isSupported(v, Ice::currentProtocol))
199     {
200         throwUnsupportedProtocolException(__FILE__, __LINE__, v, Ice::currentProtocol);
201     }
202 }
203 
204 inline void
checkSupportedProtocolEncoding(const Ice::EncodingVersion & v)205 checkSupportedProtocolEncoding(const Ice::EncodingVersion& v)
206 {
207     if(!isSupported(v, Ice::currentProtocolEncoding))
208     {
209         throwUnsupportedEncodingException(__FILE__, __LINE__, v, Ice::currentProtocolEncoding);
210     }
211 }
212 
213 inline void
checkSupportedEncoding(const Ice::EncodingVersion & v)214 checkSupportedEncoding(const Ice::EncodingVersion& v)
215 {
216     if(!isSupported(v, Ice::currentEncoding))
217     {
218         throwUnsupportedEncodingException(__FILE__, __LINE__, v, Ice::currentEncoding);
219     }
220 }
221 
222 //
223 // Either return the given protocol if not compatible, or the greatest
224 // supported protocol otherwise.
225 //
226 inline const Ice::ProtocolVersion
getCompatibleProtocol(const Ice::ProtocolVersion & v)227 getCompatibleProtocol(const Ice::ProtocolVersion& v)
228 {
229     if(v.major != Ice::currentProtocol.major)
230     {
231         return v; // Unsupported protocol, return as is.
232     }
233     else if(v.minor < Ice::currentProtocol.minor)
234     {
235         return v; // Supported protocol.
236     }
237     else
238     {
239         //
240         // Unsupported but compatible, use the currently supported
241         // protocol, that's the best we can do.
242         //
243         return Ice::currentProtocol;
244     }
245 }
246 
247 //
248 // Either return the given encoding if not compatible, or the greatest
249 // supported encoding otherwise.
250 //
251 inline const Ice::EncodingVersion&
getCompatibleEncoding(const Ice::EncodingVersion & v)252 getCompatibleEncoding(const Ice::EncodingVersion& v)
253 {
254     if(v.major != Ice::currentEncoding.major)
255     {
256         return v; // Unsupported encoding, return as is.
257     }
258     else if(v.minor < Ice::currentEncoding.minor)
259     {
260         return v; // Supported encoding.
261     }
262     else
263     {
264         //
265         // Unsupported but compatible, use the currently supported
266         // encoding, that's the best we can do.
267         //
268         return Ice::currentEncoding;
269     }
270 }
271 
272 }
273 
274 #endif
275