blob: 14ca43b745b180a4606b90721546b2a581841435 [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.
18 */
David Reiss7f42bcf2008-01-11 20:59:12 +000019
20using System;
David Reiss7f42bcf2008-01-11 20:59:12 +000021using System.Text;
22using Thrift.Transport;
23
24namespace Thrift.Protocol
25{
26 public class TBinaryProtocol : TProtocol
27 {
28 protected const uint VERSION_MASK = 0xffff0000;
29 protected const uint VERSION_1 = 0x80010000;
30
31 protected bool strictRead_ = false;
32 protected bool strictWrite_ = true;
33
34 protected int readLength_;
35 protected bool checkReadLength_ = false;
36
37
38 #region BinaryProtocol Factory
39 /**
40 * Factory
41 */
42 public class Factory : TProtocolFactory {
43
44 protected bool strictRead_ = false;
45 protected bool strictWrite_ = true;
46
47 public Factory()
48 :this(false, true)
49 {
50 }
51
52 public Factory(bool strictRead, bool strictWrite)
53 {
54 strictRead_ = strictRead;
55 strictWrite_ = strictWrite;
56 }
57
58 public TProtocol GetProtocol(TTransport trans) {
59 return new TBinaryProtocol(trans, strictRead_, strictWrite_);
60 }
61 }
62
63 #endregion
64
65 public TBinaryProtocol(TTransport trans)
66 : this(trans, false, true)
67 {
68 }
69
70 public TBinaryProtocol(TTransport trans, bool strictRead, bool strictWrite)
71 :base(trans)
72 {
73 strictRead_ = strictRead;
74 strictWrite_ = strictWrite;
75 }
76
77 #region Write Methods
78
79 public override void WriteMessageBegin(TMessage message)
80 {
81 if (strictWrite_)
82 {
83 uint version = VERSION_1 | (uint)(message.Type);
84 WriteI32((int)version);
85 WriteString(message.Name);
86 WriteI32(message.SeqID);
87 }
88 else
89 {
90 WriteString(message.Name);
91 WriteByte((byte)message.Type);
92 WriteI32(message.SeqID);
93 }
94 }
95
96 public override void WriteMessageEnd()
97 {
98 }
99
100 public override void WriteStructBegin(TStruct struc)
101 {
102 }
103
104 public override void WriteStructEnd()
105 {
106 }
107
108 public override void WriteFieldBegin(TField field)
109 {
110 WriteByte((byte)field.Type);
111 WriteI16(field.ID);
112 }
113
114 public override void WriteFieldEnd()
115 {
116 }
117
118 public override void WriteFieldStop()
119 {
120 WriteByte((byte)TType.Stop);
121 }
122
123 public override void WriteMapBegin(TMap map)
124 {
125 WriteByte((byte)map.KeyType);
126 WriteByte((byte)map.ValueType);
127 WriteI32(map.Count);
128 }
129
130 public override void WriteMapEnd()
131 {
132 }
133
134 public override void WriteListBegin(TList list)
135 {
136 WriteByte((byte)list.ElementType);
137 WriteI32(list.Count);
138 }
139
140 public override void WriteListEnd()
141 {
142 }
143
144 public override void WriteSetBegin(TSet set)
145 {
146 WriteByte((byte)set.ElementType);
147 WriteI32(set.Count);
148 }
149
150 public override void WriteSetEnd()
151 {
152 }
153
154 public override void WriteBool(bool b)
155 {
156 WriteByte(b ? (byte)1 : (byte)0);
157 }
158
159 private byte[] bout = new byte[1];
160 public override void WriteByte(byte b)
161 {
162 bout[0] = b;
163 trans.Write(bout, 0, 1);
164 }
165
166 private byte[] i16out = new byte[2];
167 public override void WriteI16(short s)
168 {
169 i16out[0] = (byte)(0xff & (s >> 8));
170 i16out[1] = (byte)(0xff & s);
171 trans.Write(i16out, 0, 2);
172 }
173
174 private byte[] i32out = new byte[4];
175 public override void WriteI32(int i32)
176 {
177 i32out[0] = (byte)(0xff & (i32 >> 24));
178 i32out[1] = (byte)(0xff & (i32 >> 16));
179 i32out[2] = (byte)(0xff & (i32 >> 8));
180 i32out[3] = (byte)(0xff & i32);
181 trans.Write(i32out, 0, 4);
182 }
183
184 private byte[] i64out = new byte[8];
185 public override void WriteI64(long i64)
186 {
187 i64out[0] = (byte)(0xff & (i64 >> 56));
188 i64out[1] = (byte)(0xff & (i64 >> 48));
189 i64out[2] = (byte)(0xff & (i64 >> 40));
190 i64out[3] = (byte)(0xff & (i64 >> 32));
191 i64out[4] = (byte)(0xff & (i64 >> 24));
192 i64out[5] = (byte)(0xff & (i64 >> 16));
193 i64out[6] = (byte)(0xff & (i64 >> 8));
194 i64out[7] = (byte)(0xff & i64);
195 trans.Write(i64out, 0, 8);
196 }
197
198 public override void WriteDouble(double d)
199 {
200 WriteI64(BitConverter.DoubleToInt64Bits(d));
201 }
202
David Reisscba57272008-02-06 22:09:44 +0000203 public override void WriteBinary(byte[] b)
David Reiss7f42bcf2008-01-11 20:59:12 +0000204 {
David Reiss7f42bcf2008-01-11 20:59:12 +0000205 WriteI32(b.Length);
206 trans.Write(b, 0, b.Length);
207 }
208
209 #endregion
210
211 #region ReadMethods
212
213 public override TMessage ReadMessageBegin()
214 {
215 TMessage message = new TMessage();
216 int size = ReadI32();
217 if (size < 0)
218 {
219 uint version = (uint)size & VERSION_MASK;
220 if (version != VERSION_1)
221 {
222 throw new TProtocolException(TProtocolException.BAD_VERSION, "Bad version in ReadMessageBegin: " + version);
223 }
224 message.Type = (TMessageType)(size & 0x000000ff);
225 message.Name = ReadString();
226 message.SeqID = ReadI32();
227 }
228 else
229 {
230 if (strictRead_)
231 {
232 throw new TProtocolException(TProtocolException.BAD_VERSION, "Missing version in readMessageBegin, old client?");
233 }
234 message.Name = ReadStringBody(size);
235 message.Type = (TMessageType)ReadByte();
236 message.SeqID = ReadI32();
237 }
238 return message;
239 }
240
241 public override void ReadMessageEnd()
242 {
243 }
244
245 public override TStruct ReadStructBegin()
246 {
247 return new TStruct();
248 }
249
250 public override void ReadStructEnd()
251 {
252 }
253
254 public override TField ReadFieldBegin()
255 {
256 TField field = new TField();
257 field.Type = (TType)ReadByte();
258
259 if (field.Type != TType.Stop)
260 {
261 field.ID = ReadI16();
262 }
263
264 return field;
265 }
266
267 public override void ReadFieldEnd()
268 {
269 }
270
271 public override TMap ReadMapBegin()
272 {
273 TMap map = new TMap();
274 map.KeyType = (TType)ReadByte();
275 map.ValueType = (TType)ReadByte();
276 map.Count = ReadI32();
277
278 return map;
279 }
280
281 public override void ReadMapEnd()
282 {
283 }
284
285 public override TList ReadListBegin()
286 {
287 TList list = new TList();
288 list.ElementType = (TType)ReadByte();
289 list.Count = ReadI32();
290
291 return list;
292 }
293
294 public override void ReadListEnd()
295 {
296 }
297
298 public override TSet ReadSetBegin()
299 {
300 TSet set = new TSet();
301 set.ElementType = (TType)ReadByte();
302 set.Count = ReadI32();
303
304 return set;
305 }
306
307 public override void ReadSetEnd()
308 {
309 }
310
311 public override bool ReadBool()
312 {
313 return ReadByte() == 1;
314 }
315
316 private byte[] bin = new byte[1];
317 public override byte ReadByte()
318 {
319 ReadAll(bin, 0, 1);
320 return bin[0];
321 }
322
323 private byte[] i16in = new byte[2];
324 public override short ReadI16()
325 {
326 ReadAll(i16in, 0, 2);
327 return (short)(((i16in[0] & 0xff) << 8) | ((i16in[1] & 0xff)));
328 }
329
330 private byte[] i32in = new byte[4];
331 public override int ReadI32()
332 {
333 ReadAll(i32in, 0, 4);
334 return (int)(((i32in[0] & 0xff) << 24) | ((i32in[1] & 0xff) << 16) | ((i32in[2] & 0xff) << 8) | ((i32in[3] & 0xff)));
335 }
336
337 private byte[] i64in = new byte[8];
338 public override long ReadI64()
339 {
340 ReadAll(i64in, 0, 8);
341 return (long)(((long)(i64in[0] & 0xff) << 56) | ((long)(i64in[1] & 0xff) << 48) | ((long)(i64in[2] & 0xff) << 40) | ((long)(i64in[3] & 0xff) << 32) |
342 ((long)(i64in[4] & 0xff) << 24) | ((long)(i64in[5] & 0xff) << 16) | ((long)(i64in[6] & 0xff) << 8) | ((long)(i64in[7] & 0xff)));
343 }
344
345 public override double ReadDouble()
346 {
347 return BitConverter.Int64BitsToDouble(ReadI64());
348 }
349
350 public void SetReadLength(int readLength)
351 {
352 readLength_ = readLength;
353 checkReadLength_ = true;
354 }
355
356 protected void CheckReadLength(int length)
357 {
358 if (checkReadLength_)
359 {
360 readLength_ -= length;
361 if (readLength_ < 0)
362 {
363 throw new Exception("Message length exceeded: " + length);
364 }
365 }
366 }
367
David Reisscba57272008-02-06 22:09:44 +0000368 public override byte[] ReadBinary()
David Reiss7f42bcf2008-01-11 20:59:12 +0000369 {
370 int size = ReadI32();
David Reisscba57272008-02-06 22:09:44 +0000371 CheckReadLength(size);
372 byte[] buf = new byte[size];
373 trans.ReadAll(buf, 0, size);
374 return buf;
David Reiss7f42bcf2008-01-11 20:59:12 +0000375 }
David Reisscba57272008-02-06 22:09:44 +0000376 private string ReadStringBody(int size)
David Reiss7f42bcf2008-01-11 20:59:12 +0000377 {
378 CheckReadLength(size);
379 byte[] buf = new byte[size];
380 trans.ReadAll(buf, 0, size);
381 return Encoding.UTF8.GetString(buf);
382 }
383
384 private int ReadAll(byte[] buf, int off, int len)
385 {
386 CheckReadLength(len);
387 return trans.ReadAll(buf, off, len);
388 }
389
390 #endregion
391 }
392}