diff options
Diffstat (limited to 'lib/csharp/src/Protocol/TBinaryProtocol.cs')
-rw-r--r-- | lib/csharp/src/Protocol/TBinaryProtocol.cs | 392 |
1 files changed, 392 insertions, 0 deletions
diff --git a/lib/csharp/src/Protocol/TBinaryProtocol.cs b/lib/csharp/src/Protocol/TBinaryProtocol.cs new file mode 100644 index 000000000..14ca43b74 --- /dev/null +++ b/lib/csharp/src/Protocol/TBinaryProtocol.cs @@ -0,0 +1,392 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +using System; +using System.Text; +using Thrift.Transport; + +namespace Thrift.Protocol +{ + public class TBinaryProtocol : TProtocol + { + protected const uint VERSION_MASK = 0xffff0000; + protected const uint VERSION_1 = 0x80010000; + + protected bool strictRead_ = false; + protected bool strictWrite_ = true; + + protected int readLength_; + protected bool checkReadLength_ = false; + + + #region BinaryProtocol Factory + /** + * Factory + */ + public class Factory : TProtocolFactory { + + protected bool strictRead_ = false; + protected bool strictWrite_ = true; + + public Factory() + :this(false, true) + { + } + + public Factory(bool strictRead, bool strictWrite) + { + strictRead_ = strictRead; + strictWrite_ = strictWrite; + } + + public TProtocol GetProtocol(TTransport trans) { + return new TBinaryProtocol(trans, strictRead_, strictWrite_); + } + } + + #endregion + + public TBinaryProtocol(TTransport trans) + : this(trans, false, true) + { + } + + public TBinaryProtocol(TTransport trans, bool strictRead, bool strictWrite) + :base(trans) + { + strictRead_ = strictRead; + strictWrite_ = strictWrite; + } + + #region Write Methods + + public override void WriteMessageBegin(TMessage message) + { + if (strictWrite_) + { + uint version = VERSION_1 | (uint)(message.Type); + WriteI32((int)version); + WriteString(message.Name); + WriteI32(message.SeqID); + } + else + { + WriteString(message.Name); + WriteByte((byte)message.Type); + WriteI32(message.SeqID); + } + } + + public override void WriteMessageEnd() + { + } + + public override void WriteStructBegin(TStruct struc) + { + } + + public override void WriteStructEnd() + { + } + + public override void WriteFieldBegin(TField field) + { + WriteByte((byte)field.Type); + WriteI16(field.ID); + } + + public override void WriteFieldEnd() + { + } + + public override void WriteFieldStop() + { + WriteByte((byte)TType.Stop); + } + + public override void WriteMapBegin(TMap map) + { + WriteByte((byte)map.KeyType); + WriteByte((byte)map.ValueType); + WriteI32(map.Count); + } + + public override void WriteMapEnd() + { + } + + public override void WriteListBegin(TList list) + { + WriteByte((byte)list.ElementType); + WriteI32(list.Count); + } + + public override void WriteListEnd() + { + } + + public override void WriteSetBegin(TSet set) + { + WriteByte((byte)set.ElementType); + WriteI32(set.Count); + } + + public override void WriteSetEnd() + { + } + + public override void WriteBool(bool b) + { + WriteByte(b ? (byte)1 : (byte)0); + } + + private byte[] bout = new byte[1]; + public override void WriteByte(byte b) + { + bout[0] = b; + trans.Write(bout, 0, 1); + } + + private byte[] i16out = new byte[2]; + public override void WriteI16(short s) + { + i16out[0] = (byte)(0xff & (s >> 8)); + i16out[1] = (byte)(0xff & s); + trans.Write(i16out, 0, 2); + } + + private byte[] i32out = new byte[4]; + public override void WriteI32(int i32) + { + i32out[0] = (byte)(0xff & (i32 >> 24)); + i32out[1] = (byte)(0xff & (i32 >> 16)); + i32out[2] = (byte)(0xff & (i32 >> 8)); + i32out[3] = (byte)(0xff & i32); + trans.Write(i32out, 0, 4); + } + + private byte[] i64out = new byte[8]; + public override void WriteI64(long i64) + { + i64out[0] = (byte)(0xff & (i64 >> 56)); + i64out[1] = (byte)(0xff & (i64 >> 48)); + i64out[2] = (byte)(0xff & (i64 >> 40)); + i64out[3] = (byte)(0xff & (i64 >> 32)); + i64out[4] = (byte)(0xff & (i64 >> 24)); + i64out[5] = (byte)(0xff & (i64 >> 16)); + i64out[6] = (byte)(0xff & (i64 >> 8)); + i64out[7] = (byte)(0xff & i64); + trans.Write(i64out, 0, 8); + } + + public override void WriteDouble(double d) + { + WriteI64(BitConverter.DoubleToInt64Bits(d)); + } + + public override void WriteBinary(byte[] b) + { + WriteI32(b.Length); + trans.Write(b, 0, b.Length); + } + + #endregion + + #region ReadMethods + + public override TMessage ReadMessageBegin() + { + TMessage message = new TMessage(); + int size = ReadI32(); + if (size < 0) + { + uint version = (uint)size & VERSION_MASK; + if (version != VERSION_1) + { + throw new TProtocolException(TProtocolException.BAD_VERSION, "Bad version in ReadMessageBegin: " + version); + } + message.Type = (TMessageType)(size & 0x000000ff); + message.Name = ReadString(); + message.SeqID = ReadI32(); + } + else + { + if (strictRead_) + { + throw new TProtocolException(TProtocolException.BAD_VERSION, "Missing version in readMessageBegin, old client?"); + } + message.Name = ReadStringBody(size); + message.Type = (TMessageType)ReadByte(); + message.SeqID = ReadI32(); + } + return message; + } + + public override void ReadMessageEnd() + { + } + + public override TStruct ReadStructBegin() + { + return new TStruct(); + } + + public override void ReadStructEnd() + { + } + + public override TField ReadFieldBegin() + { + TField field = new TField(); + field.Type = (TType)ReadByte(); + + if (field.Type != TType.Stop) + { + field.ID = ReadI16(); + } + + return field; + } + + public override void ReadFieldEnd() + { + } + + public override TMap ReadMapBegin() + { + TMap map = new TMap(); + map.KeyType = (TType)ReadByte(); + map.ValueType = (TType)ReadByte(); + map.Count = ReadI32(); + + return map; + } + + public override void ReadMapEnd() + { + } + + public override TList ReadListBegin() + { + TList list = new TList(); + list.ElementType = (TType)ReadByte(); + list.Count = ReadI32(); + + return list; + } + + public override void ReadListEnd() + { + } + + public override TSet ReadSetBegin() + { + TSet set = new TSet(); + set.ElementType = (TType)ReadByte(); + set.Count = ReadI32(); + + return set; + } + + public override void ReadSetEnd() + { + } + + public override bool ReadBool() + { + return ReadByte() == 1; + } + + private byte[] bin = new byte[1]; + public override byte ReadByte() + { + ReadAll(bin, 0, 1); + return bin[0]; + } + + private byte[] i16in = new byte[2]; + public override short ReadI16() + { + ReadAll(i16in, 0, 2); + return (short)(((i16in[0] & 0xff) << 8) | ((i16in[1] & 0xff))); + } + + private byte[] i32in = new byte[4]; + public override int ReadI32() + { + ReadAll(i32in, 0, 4); + return (int)(((i32in[0] & 0xff) << 24) | ((i32in[1] & 0xff) << 16) | ((i32in[2] & 0xff) << 8) | ((i32in[3] & 0xff))); + } + + private byte[] i64in = new byte[8]; + public override long ReadI64() + { + ReadAll(i64in, 0, 8); + return (long)(((long)(i64in[0] & 0xff) << 56) | ((long)(i64in[1] & 0xff) << 48) | ((long)(i64in[2] & 0xff) << 40) | ((long)(i64in[3] & 0xff) << 32) | + ((long)(i64in[4] & 0xff) << 24) | ((long)(i64in[5] & 0xff) << 16) | ((long)(i64in[6] & 0xff) << 8) | ((long)(i64in[7] & 0xff))); + } + + public override double ReadDouble() + { + return BitConverter.Int64BitsToDouble(ReadI64()); + } + + public void SetReadLength(int readLength) + { + readLength_ = readLength; + checkReadLength_ = true; + } + + protected void CheckReadLength(int length) + { + if (checkReadLength_) + { + readLength_ -= length; + if (readLength_ < 0) + { + throw new Exception("Message length exceeded: " + length); + } + } + } + + public override byte[] ReadBinary() + { + int size = ReadI32(); + CheckReadLength(size); + byte[] buf = new byte[size]; + trans.ReadAll(buf, 0, size); + return buf; + } + private string ReadStringBody(int size) + { + CheckReadLength(size); + byte[] buf = new byte[size]; + trans.ReadAll(buf, 0, size); + return Encoding.UTF8.GetString(buf); + } + + private int ReadAll(byte[] buf, int off, int len) + { + CheckReadLength(len); + return trans.ReadAll(buf, off, len); + } + + #endregion + } +} |