blob: 682078b4e2a351a3b7fff49234e7a2ae0296deab [file] [log] [blame]
Kevin Clarkab4460d2009-03-20 02:28:41 +00001/**
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
Todd Lipcon53ae9f32009-12-07 00:42:38 +000018 *
19 * Contains some contributions under the Thrift Software License.
20 * Please see doc/old-thrift-license.txt in the Thrift distribution for
21 * details.
Kevin Clarkab4460d2009-03-20 02:28:41 +000022 */
David Reiss7f42bcf2008-01-11 20:59:12 +000023
24using System;
David Reiss7f42bcf2008-01-11 20:59:12 +000025using System.Text;
26using Thrift.Transport;
27
28namespace Thrift.Protocol
29{
30 public class TBinaryProtocol : TProtocol
31 {
32 protected const uint VERSION_MASK = 0xffff0000;
33 protected const uint VERSION_1 = 0x80010000;
34
35 protected bool strictRead_ = false;
36 protected bool strictWrite_ = true;
37
38 protected int readLength_;
39 protected bool checkReadLength_ = false;
40
41
42 #region BinaryProtocol Factory
43 /**
44 * Factory
45 */
46 public class Factory : TProtocolFactory {
47
48 protected bool strictRead_ = false;
49 protected bool strictWrite_ = true;
50
51 public Factory()
52 :this(false, true)
53 {
54 }
55
56 public Factory(bool strictRead, bool strictWrite)
57 {
58 strictRead_ = strictRead;
59 strictWrite_ = strictWrite;
60 }
61
62 public TProtocol GetProtocol(TTransport trans) {
63 return new TBinaryProtocol(trans, strictRead_, strictWrite_);
64 }
65 }
66
67 #endregion
68
69 public TBinaryProtocol(TTransport trans)
70 : this(trans, false, true)
71 {
72 }
73
74 public TBinaryProtocol(TTransport trans, bool strictRead, bool strictWrite)
75 :base(trans)
76 {
77 strictRead_ = strictRead;
78 strictWrite_ = strictWrite;
79 }
80
81 #region Write Methods
82
83 public override void WriteMessageBegin(TMessage message)
84 {
85 if (strictWrite_)
86 {
87 uint version = VERSION_1 | (uint)(message.Type);
88 WriteI32((int)version);
89 WriteString(message.Name);
90 WriteI32(message.SeqID);
91 }
92 else
93 {
94 WriteString(message.Name);
95 WriteByte((byte)message.Type);
96 WriteI32(message.SeqID);
97 }
98 }
99
100 public override void WriteMessageEnd()
101 {
102 }
103
104 public override void WriteStructBegin(TStruct struc)
105 {
106 }
107
108 public override void WriteStructEnd()
109 {
110 }
111
112 public override void WriteFieldBegin(TField field)
113 {
114 WriteByte((byte)field.Type);
115 WriteI16(field.ID);
116 }
117
118 public override void WriteFieldEnd()
119 {
120 }
121
122 public override void WriteFieldStop()
123 {
124 WriteByte((byte)TType.Stop);
125 }
126
127 public override void WriteMapBegin(TMap map)
128 {
129 WriteByte((byte)map.KeyType);
130 WriteByte((byte)map.ValueType);
131 WriteI32(map.Count);
132 }
133
134 public override void WriteMapEnd()
135 {
136 }
137
138 public override void WriteListBegin(TList list)
139 {
140 WriteByte((byte)list.ElementType);
141 WriteI32(list.Count);
142 }
143
144 public override void WriteListEnd()
145 {
146 }
147
148 public override void WriteSetBegin(TSet set)
149 {
150 WriteByte((byte)set.ElementType);
151 WriteI32(set.Count);
152 }
153
154 public override void WriteSetEnd()
155 {
156 }
157
158 public override void WriteBool(bool b)
159 {
160 WriteByte(b ? (byte)1 : (byte)0);
161 }
162
163 private byte[] bout = new byte[1];
164 public override void WriteByte(byte b)
165 {
166 bout[0] = b;
167 trans.Write(bout, 0, 1);
168 }
169
170 private byte[] i16out = new byte[2];
171 public override void WriteI16(short s)
172 {
173 i16out[0] = (byte)(0xff & (s >> 8));
174 i16out[1] = (byte)(0xff & s);
175 trans.Write(i16out, 0, 2);
176 }
177
178 private byte[] i32out = new byte[4];
179 public override void WriteI32(int i32)
180 {
181 i32out[0] = (byte)(0xff & (i32 >> 24));
182 i32out[1] = (byte)(0xff & (i32 >> 16));
183 i32out[2] = (byte)(0xff & (i32 >> 8));
184 i32out[3] = (byte)(0xff & i32);
185 trans.Write(i32out, 0, 4);
186 }
187
188 private byte[] i64out = new byte[8];
189 public override void WriteI64(long i64)
190 {
191 i64out[0] = (byte)(0xff & (i64 >> 56));
192 i64out[1] = (byte)(0xff & (i64 >> 48));
193 i64out[2] = (byte)(0xff & (i64 >> 40));
194 i64out[3] = (byte)(0xff & (i64 >> 32));
195 i64out[4] = (byte)(0xff & (i64 >> 24));
196 i64out[5] = (byte)(0xff & (i64 >> 16));
197 i64out[6] = (byte)(0xff & (i64 >> 8));
198 i64out[7] = (byte)(0xff & i64);
199 trans.Write(i64out, 0, 8);
200 }
201
202 public override void WriteDouble(double d)
203 {
Roger Meier284a9b52011-12-08 13:39:56 +0000204#if !SILVERLIGHT
David Reiss7f42bcf2008-01-11 20:59:12 +0000205 WriteI64(BitConverter.DoubleToInt64Bits(d));
Roger Meier284a9b52011-12-08 13:39:56 +0000206#else
207 var bytes = BitConverter.GetBytes(d);
208 WriteI64(BitConverter.ToInt64(bytes, 0));
209#endif
David Reiss7f42bcf2008-01-11 20:59:12 +0000210 }
211
David Reisscba57272008-02-06 22:09:44 +0000212 public override void WriteBinary(byte[] b)
David Reiss7f42bcf2008-01-11 20:59:12 +0000213 {
David Reiss7f42bcf2008-01-11 20:59:12 +0000214 WriteI32(b.Length);
215 trans.Write(b, 0, b.Length);
216 }
217
218 #endregion
219
220 #region ReadMethods
221
222 public override TMessage ReadMessageBegin()
223 {
224 TMessage message = new TMessage();
225 int size = ReadI32();
226 if (size < 0)
227 {
228 uint version = (uint)size & VERSION_MASK;
229 if (version != VERSION_1)
230 {
231 throw new TProtocolException(TProtocolException.BAD_VERSION, "Bad version in ReadMessageBegin: " + version);
232 }
233 message.Type = (TMessageType)(size & 0x000000ff);
234 message.Name = ReadString();
235 message.SeqID = ReadI32();
236 }
237 else
238 {
239 if (strictRead_)
240 {
241 throw new TProtocolException(TProtocolException.BAD_VERSION, "Missing version in readMessageBegin, old client?");
242 }
243 message.Name = ReadStringBody(size);
244 message.Type = (TMessageType)ReadByte();
245 message.SeqID = ReadI32();
246 }
247 return message;
248 }
249
250 public override void ReadMessageEnd()
251 {
252 }
253
254 public override TStruct ReadStructBegin()
255 {
256 return new TStruct();
257 }
258
259 public override void ReadStructEnd()
260 {
261 }
262
263 public override TField ReadFieldBegin()
264 {
265 TField field = new TField();
266 field.Type = (TType)ReadByte();
267
268 if (field.Type != TType.Stop)
269 {
270 field.ID = ReadI16();
271 }
272
273 return field;
274 }
275
276 public override void ReadFieldEnd()
277 {
278 }
279
280 public override TMap ReadMapBegin()
281 {
282 TMap map = new TMap();
283 map.KeyType = (TType)ReadByte();
284 map.ValueType = (TType)ReadByte();
285 map.Count = ReadI32();
286
287 return map;
288 }
289
290 public override void ReadMapEnd()
291 {
292 }
293
294 public override TList ReadListBegin()
295 {
296 TList list = new TList();
297 list.ElementType = (TType)ReadByte();
298 list.Count = ReadI32();
299
300 return list;
301 }
302
303 public override void ReadListEnd()
304 {
305 }
306
307 public override TSet ReadSetBegin()
308 {
309 TSet set = new TSet();
310 set.ElementType = (TType)ReadByte();
311 set.Count = ReadI32();
312
313 return set;
314 }
315
316 public override void ReadSetEnd()
317 {
318 }
319
320 public override bool ReadBool()
321 {
322 return ReadByte() == 1;
323 }
324
325 private byte[] bin = new byte[1];
326 public override byte ReadByte()
327 {
328 ReadAll(bin, 0, 1);
329 return bin[0];
330 }
331
332 private byte[] i16in = new byte[2];
333 public override short ReadI16()
334 {
335 ReadAll(i16in, 0, 2);
336 return (short)(((i16in[0] & 0xff) << 8) | ((i16in[1] & 0xff)));
337 }
338
339 private byte[] i32in = new byte[4];
340 public override int ReadI32()
341 {
342 ReadAll(i32in, 0, 4);
343 return (int)(((i32in[0] & 0xff) << 24) | ((i32in[1] & 0xff) << 16) | ((i32in[2] & 0xff) << 8) | ((i32in[3] & 0xff)));
344 }
345
346 private byte[] i64in = new byte[8];
347 public override long ReadI64()
348 {
349 ReadAll(i64in, 0, 8);
Jake Farrell98f93772012-10-20 16:47:51 +0000350 unchecked {
351 return (long)(
352 ((long)(i64in[0] & 0xff) << 56) |
353 ((long)(i64in[1] & 0xff) << 48) |
354 ((long)(i64in[2] & 0xff) << 40) |
355 ((long)(i64in[3] & 0xff) << 32) |
356 ((long)(i64in[4] & 0xff) << 24) |
357 ((long)(i64in[5] & 0xff) << 16) |
358 ((long)(i64in[6] & 0xff) << 8) |
359 ((long)(i64in[7] & 0xff)));
360 }
Jake Farrell14c217d2012-10-05 00:38:11 +0000361 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000362
363 public override double ReadDouble()
364 {
Roger Meier284a9b52011-12-08 13:39:56 +0000365#if !SILVERLIGHT
David Reiss7f42bcf2008-01-11 20:59:12 +0000366 return BitConverter.Int64BitsToDouble(ReadI64());
Roger Meier284a9b52011-12-08 13:39:56 +0000367#else
368 var value = ReadI64();
369 var bytes = BitConverter.GetBytes(value);
370 return BitConverter.ToDouble(bytes, 0);
371#endif
David Reiss7f42bcf2008-01-11 20:59:12 +0000372 }
373
374 public void SetReadLength(int readLength)
375 {
376 readLength_ = readLength;
377 checkReadLength_ = true;
378 }
379
380 protected void CheckReadLength(int length)
381 {
382 if (checkReadLength_)
383 {
384 readLength_ -= length;
385 if (readLength_ < 0)
386 {
387 throw new Exception("Message length exceeded: " + length);
388 }
389 }
390 }
391
David Reisscba57272008-02-06 22:09:44 +0000392 public override byte[] ReadBinary()
David Reiss7f42bcf2008-01-11 20:59:12 +0000393 {
394 int size = ReadI32();
David Reisscba57272008-02-06 22:09:44 +0000395 CheckReadLength(size);
396 byte[] buf = new byte[size];
397 trans.ReadAll(buf, 0, size);
398 return buf;
David Reiss7f42bcf2008-01-11 20:59:12 +0000399 }
David Reisscba57272008-02-06 22:09:44 +0000400 private string ReadStringBody(int size)
David Reiss7f42bcf2008-01-11 20:59:12 +0000401 {
402 CheckReadLength(size);
403 byte[] buf = new byte[size];
404 trans.ReadAll(buf, 0, size);
Roger Meier284a9b52011-12-08 13:39:56 +0000405 return Encoding.UTF8.GetString(buf, 0, buf.Length);
David Reiss7f42bcf2008-01-11 20:59:12 +0000406 }
407
408 private int ReadAll(byte[] buf, int off, int len)
409 {
410 CheckReadLength(len);
411 return trans.ReadAll(buf, off, len);
412 }
413
414 #endregion
415 }
416}