THRIFT-4535: XML docs; code cleanup (tabs->spaces; String->string)

Client: C#
Patch: Christian Weiss

This closes #1524
This commit is contained in:
Christian Weiss 2018-03-30 21:26:04 +02:00 committed by Jens Geyer
parent d4fb364d30
commit 8fb719efb1
36 changed files with 1653 additions and 1606 deletions

View File

@ -79,7 +79,7 @@ namespace Thrift.Collections
} }
int hashcode = 0; int hashcode = 0;
foreach (Object obj in enumerable) foreach (object obj in enumerable)
{ {
IEnumerable enum2 = obj as IEnumerable; IEnumerable enum2 = obj as IEnumerable;
int objHash = enum2 == null ? obj.GetHashCode () : GetHashCode (enum2); int objHash = enum2 == null ? obj.GetHashCode () : GetHashCode (enum2);
@ -91,4 +91,4 @@ namespace Thrift.Collections
return hashcode; return hashcode;
} }
} }
} }

View File

@ -21,9 +21,9 @@ namespace Thrift.Protocol
{ {
public interface TAbstractBase public interface TAbstractBase
{ {
/// /// <summary>
/// Writes the objects out to the protocol /// Writes the objects out to the protocol.
/// /// </summary>
void Write(TProtocol tProtocol); void Write(TProtocol tProtocol);
} }
} }

View File

@ -21,9 +21,9 @@ namespace Thrift.Protocol
{ {
public interface TBase : TAbstractBase public interface TBase : TAbstractBase
{ {
/// /// <summary>
/// Reads the TObject from the given input protocol. /// Reads the TObject from the given input protocol.
/// /// </summary>
void Read(TProtocol tProtocol); void Read(TProtocol tProtocol);
} }
} }

View File

@ -36,29 +36,28 @@ namespace Thrift.Protocol
protected bool strictWrite_ = true; protected bool strictWrite_ = true;
#region BinaryProtocol Factory #region BinaryProtocol Factory
/**
* Factory
*/
public class Factory : TProtocolFactory {
protected bool strictRead_ = false; public class Factory : TProtocolFactory
protected bool strictWrite_ = true; {
protected bool strictRead_ = false;
protected bool strictWrite_ = true;
public Factory() public Factory()
:this(false, true) : this(false, true)
{ {
}
public Factory(bool strictRead, bool strictWrite)
{
strictRead_ = strictRead;
strictWrite_ = strictWrite;
}
public TProtocol GetProtocol(TTransport trans) {
return new TBinaryProtocol(trans, strictRead_, strictWrite_);
} }
}
public Factory(bool strictRead, bool strictWrite)
{
strictRead_ = strictRead;
strictWrite_ = strictWrite;
}
public TProtocol GetProtocol(TTransport trans)
{
return new TBinaryProtocol(trans, strictRead_, strictWrite_);
}
}
#endregion #endregion
@ -68,7 +67,7 @@ namespace Thrift.Protocol
} }
public TBinaryProtocol(TTransport trans, bool strictRead, bool strictWrite) public TBinaryProtocol(TTransport trans, bool strictRead, bool strictWrite)
:base(trans) : base(trans)
{ {
strictRead_ = strictRead; strictRead_ = strictRead;
strictWrite_ = strictWrite; strictWrite_ = strictWrite;
@ -345,16 +344,17 @@ namespace Thrift.Protocol
public override long ReadI64() public override long ReadI64()
{ {
ReadAll(i64in, 0, 8); ReadAll(i64in, 0, 8);
unchecked { unchecked
return (long)( {
((long)(i64in[0] & 0xff) << 56) | return (long)(
((long)(i64in[1] & 0xff) << 48) | ((long)(i64in[0] & 0xff) << 56) |
((long)(i64in[2] & 0xff) << 40) | ((long)(i64in[1] & 0xff) << 48) |
((long)(i64in[3] & 0xff) << 32) | ((long)(i64in[2] & 0xff) << 40) |
((long)(i64in[4] & 0xff) << 24) | ((long)(i64in[3] & 0xff) << 32) |
((long)(i64in[5] & 0xff) << 16) | ((long)(i64in[4] & 0xff) << 24) |
((long)(i64in[6] & 0xff) << 8) | ((long)(i64in[5] & 0xff) << 16) |
((long)(i64in[7] & 0xff))); ((long)(i64in[6] & 0xff) << 8) |
((long)(i64in[7] & 0xff)));
} }
} }
@ -378,7 +378,7 @@ namespace Thrift.Protocol
trans.ReadAll(buf, 0, size); trans.ReadAll(buf, 0, size);
return buf; return buf;
} }
private string ReadStringBody(int size) private string ReadStringBody(int size)
{ {
byte[] buf = new byte[size]; byte[] buf = new byte[size];
trans.ReadAll(buf, 0, size); trans.ReadAll(buf, 0, size);

View File

@ -44,9 +44,9 @@ namespace Thrift.Protocol
private const byte TYPE_BITS = 0x07; // 0000 0111 private const byte TYPE_BITS = 0x07; // 0000 0111
private const int TYPE_SHIFT_AMOUNT = 5; private const int TYPE_SHIFT_AMOUNT = 5;
/** /// <summary>
* All of the on-wire type codes. /// All of the on-wire type codes.
*/ /// </summary>
private static class Types private static class Types
{ {
public const byte STOP = 0x00; public const byte STOP = 0x00;
@ -64,32 +64,29 @@ namespace Thrift.Protocol
public const byte STRUCT = 0x0C; public const byte STRUCT = 0x0C;
} }
/** /// <summary>
* Used to keep track of the last field for the current and previous structs, /// Used to keep track of the last field for the current and previous structs,
* so we can do the delta stuff. /// so we can do the delta stuff.
*/ /// </summary>
private Stack<short> lastField_ = new Stack<short>(15); private Stack<short> lastField_ = new Stack<short>(15);
private short lastFieldId_ = 0; private short lastFieldId_ = 0;
/** /// <summary>
* If we encounter a boolean field begin, save the TField here so it can /// If we encounter a boolean field begin, save the TField here so it can
* have the value incorporated. /// have the value incorporated.
*/ /// </summary>
private Nullable<TField> booleanField_; private Nullable<TField> booleanField_;
/** /// <summary>
* If we Read a field header, and it's a boolean field, save the boolean /// If we Read a field header, and it's a boolean field, save the boolean
* value here so that ReadBool can use it. /// value here so that ReadBool can use it.
*/ /// </summary>
private Nullable<Boolean> boolValue_; private Nullable<Boolean> boolValue_;
#region CompactProtocol Factory #region CompactProtocol Factory
/**
* Factory
*/
public class Factory : TProtocolFactory public class Factory : TProtocolFactory
{ {
public Factory() { } public Factory() { }
@ -127,31 +124,32 @@ namespace Thrift.Protocol
#region Write Methods #region Write Methods
/// <summary>
/** /// Writes a byte without any possibility of all that field header nonsense.
* Writes a byte without any possibility of all that field header nonsense. /// Used internally by other writing methods that know they need to Write a byte.
* Used internally by other writing methods that know they need to Write a byte. /// </summary>
*/
private byte[] byteDirectBuffer = new byte[1]; private byte[] byteDirectBuffer = new byte[1];
private void WriteByteDirect(byte b) private void WriteByteDirect(byte b)
{ {
byteDirectBuffer[0] = b; byteDirectBuffer[0] = b;
trans.Write(byteDirectBuffer); trans.Write(byteDirectBuffer);
} }
/** /// <summary>
* Writes a byte without any possibility of all that field header nonsense. /// Writes a byte without any possibility of all that field header nonsense.
*/ /// </summary>
private void WriteByteDirect(int n) private void WriteByteDirect(int n)
{ {
WriteByteDirect((byte)n); WriteByteDirect((byte)n);
} }
/** /// <summary>
* Write an i32 as a varint. Results in 1-5 bytes on the wire. /// Write an i32 as a varint. Results in 1-5 bytes on the wire.
* TODO: make a permanent buffer like WriteVarint64? /// TODO: make a permanent buffer like WriteVarint64?
*/ /// </summary>
byte[] i32buf = new byte[5]; byte[] i32buf = new byte[5];
private void WriteVarint32(uint n) private void WriteVarint32(uint n)
{ {
int idx = 0; int idx = 0;
@ -174,10 +172,10 @@ namespace Thrift.Protocol
trans.Write(i32buf, 0, idx); trans.Write(i32buf, 0, idx);
} }
/** /// <summary>
* Write a message header to the wire. Compact Protocol messages contain the /// Write a message header to the wire. Compact Protocol messages contain the
* protocol version so we can migrate forwards in the future if need be. /// protocol version so we can migrate forwards in the future if need be.
*/ /// </summary>
public override void WriteMessageBegin(TMessage message) public override void WriteMessageBegin(TMessage message)
{ {
WriteByteDirect(PROTOCOL_ID); WriteByteDirect(PROTOCOL_ID);
@ -186,33 +184,33 @@ namespace Thrift.Protocol
WriteString(message.Name); WriteString(message.Name);
} }
/** /// <summary>
* Write a struct begin. This doesn't actually put anything on the wire. We /// Write a struct begin. This doesn't actually put anything on the wire. We
* use it as an opportunity to put special placeholder markers on the field /// use it as an opportunity to put special placeholder markers on the field
* stack so we can get the field id deltas correct. /// stack so we can get the field id deltas correct.
*/ /// </summary>
public override void WriteStructBegin(TStruct strct) public override void WriteStructBegin(TStruct strct)
{ {
lastField_.Push(lastFieldId_); lastField_.Push(lastFieldId_);
lastFieldId_ = 0; lastFieldId_ = 0;
} }
/** /// <summary>
* Write a struct end. This doesn't actually put anything on the wire. We use /// Write a struct end. This doesn't actually put anything on the wire. We use
* this as an opportunity to pop the last field from the current struct off /// this as an opportunity to pop the last field from the current struct off
* of the field stack. /// of the field stack.
*/ /// </summary>
public override void WriteStructEnd() public override void WriteStructEnd()
{ {
lastFieldId_ = lastField_.Pop(); lastFieldId_ = lastField_.Pop();
} }
/** /// <summary>
* Write a field header containing the field id and field type. If the /// Write a field header containing the field id and field type. If the
* difference between the current field id and the last one is small (< 15), /// difference between the current field id and the last one is small (&lt; 15),
* then the field id will be encoded in the 4 MSB as a delta. Otherwise, the /// then the field id will be encoded in the 4 MSB as a delta. Otherwise, the
* field id will follow the type header as a zigzag varint. /// field id will follow the type header as a zigzag varint.
*/ /// </summary>
public override void WriteFieldBegin(TField field) public override void WriteFieldBegin(TField field)
{ {
if (field.Type == TType.Bool) if (field.Type == TType.Bool)
@ -226,11 +224,11 @@ namespace Thrift.Protocol
} }
} }
/** /// <summary>
* The workhorse of WriteFieldBegin. It has the option of doing a /// The workhorse of WriteFieldBegin. It has the option of doing a
* 'type override' of the type header. This is used specifically in the /// 'type override' of the type header. This is used specifically in the
* boolean field case. /// boolean field case.
*/ /// </summary>
private void WriteFieldBeginInternal(TField field, byte typeOverride) private void WriteFieldBeginInternal(TField field, byte typeOverride)
{ {
// short lastField = lastField_.Pop(); // short lastField = lastField_.Pop();
@ -255,18 +253,18 @@ namespace Thrift.Protocol
// lastField_.push(field.id); // lastField_.push(field.id);
} }
/** /// <summary>
* Write the STOP symbol so we know there are no more fields in this struct. /// Write the STOP symbol so we know there are no more fields in this struct.
*/ /// </summary>
public override void WriteFieldStop() public override void WriteFieldStop()
{ {
WriteByteDirect(Types.STOP); WriteByteDirect(Types.STOP);
} }
/** /// <summary>
* Write a map header. If the map is empty, omit the key and value type /// Write a map header. If the map is empty, omit the key and value type
* headers, as we don't need any additional information to skip it. /// headers, as we don't need any additional information to skip it.
*/ /// </summary>
public override void WriteMapBegin(TMap map) public override void WriteMapBegin(TMap map)
{ {
if (map.Count == 0) if (map.Count == 0)
@ -280,28 +278,28 @@ namespace Thrift.Protocol
} }
} }
/** /// <summary>
* Write a list header. /// Write a list header.
*/ /// </summary>
public override void WriteListBegin(TList list) public override void WriteListBegin(TList list)
{ {
WriteCollectionBegin(list.ElementType, list.Count); WriteCollectionBegin(list.ElementType, list.Count);
} }
/** /// <summary>
* Write a set header. /// Write a set header.
*/ /// </summary>
public override void WriteSetBegin(TSet set) public override void WriteSetBegin(TSet set)
{ {
WriteCollectionBegin(set.ElementType, set.Count); WriteCollectionBegin(set.ElementType, set.Count);
} }
/** /// <summary>
* Write a boolean value. Potentially, this could be a boolean field, in /// Write a boolean value. Potentially, this could be a boolean field, in
* which case the field header info isn't written yet. If so, decide what the /// which case the field header info isn't written yet. If so, decide what the
* right type header is for the value and then Write the field header. /// right type header is for the value and then Write the field header.
* Otherwise, Write a single byte. /// Otherwise, Write a single byte.
*/ /// </summary>
public override void WriteBool(Boolean b) public override void WriteBool(Boolean b)
{ {
if (booleanField_ != null) if (booleanField_ != null)
@ -317,41 +315,41 @@ namespace Thrift.Protocol
} }
} }
/** /// <summary>
* Write a byte. Nothing to see here! /// Write a byte. Nothing to see here!
*/ /// </summary>
public override void WriteByte(sbyte b) public override void WriteByte(sbyte b)
{ {
WriteByteDirect((byte)b); WriteByteDirect((byte)b);
} }
/** /// <summary>
* Write an I16 as a zigzag varint. /// Write an I16 as a zigzag varint.
*/ /// </summary>
public override void WriteI16(short i16) public override void WriteI16(short i16)
{ {
WriteVarint32(intToZigZag(i16)); WriteVarint32(intToZigZag(i16));
} }
/** /// <summary>
* Write an i32 as a zigzag varint. /// Write an i32 as a zigzag varint.
*/ /// </summary>
public override void WriteI32(int i32) public override void WriteI32(int i32)
{ {
WriteVarint32(intToZigZag(i32)); WriteVarint32(intToZigZag(i32));
} }
/** /// <summary>
* Write an i64 as a zigzag varint. /// Write an i64 as a zigzag varint.
*/ /// </summary>
public override void WriteI64(long i64) public override void WriteI64(long i64)
{ {
WriteVarint64(longToZigzag(i64)); WriteVarint64(longToZigzag(i64));
} }
/** /// <summary>
* Write a double to the wire as 8 bytes. /// Write a double to the wire as 8 bytes.
*/ /// </summary>
public override void WriteDouble(double dub) public override void WriteDouble(double dub)
{ {
byte[] data = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }; byte[] data = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 };
@ -359,18 +357,18 @@ namespace Thrift.Protocol
trans.Write(data); trans.Write(data);
} }
/** /// <summary>
* Write a string to the wire with a varint size preceding. /// Write a string to the wire with a varint size preceding.
*/ /// </summary>
public override void WriteString(String str) public override void WriteString(string str)
{ {
byte[] bytes = UTF8Encoding.UTF8.GetBytes(str); byte[] bytes = UTF8Encoding.UTF8.GetBytes(str);
WriteBinary(bytes, 0, bytes.Length); WriteBinary(bytes, 0, bytes.Length);
} }
/** /// <summary>
* Write a byte array, using a varint for the size. /// Write a byte array, using a varint for the size.
*/ /// </summary>
public override void WriteBinary(byte[] bin) public override void WriteBinary(byte[] bin)
{ {
WriteBinary(bin, 0, bin.Length); WriteBinary(bin, 0, bin.Length);
@ -397,10 +395,10 @@ namespace Thrift.Protocol
// Internal writing methods // Internal writing methods
// //
/** /// <summary>
* Abstract method for writing the start of lists and sets. List and sets on /// Abstract method for writing the start of lists and sets. List and sets on
* the wire differ only by the type indicator. /// the wire differ only by the type indicator.
*/ /// </summary>
protected void WriteCollectionBegin(TType elemType, int size) protected void WriteCollectionBegin(TType elemType, int size)
{ {
if (size <= 14) if (size <= 14)
@ -414,9 +412,9 @@ namespace Thrift.Protocol
} }
} }
/** /// <summary>
* Write an i64 as a varint. Results in 1-10 bytes on the wire. /// Write an i64 as a varint. Results in 1-10 bytes on the wire.
*/ /// </summary>
byte[] varint64out = new byte[10]; byte[] varint64out = new byte[10];
private void WriteVarint64(ulong n) private void WriteVarint64(ulong n)
{ {
@ -437,28 +435,28 @@ namespace Thrift.Protocol
trans.Write(varint64out, 0, idx); trans.Write(varint64out, 0, idx);
} }
/** /// <summary>
* Convert l into a zigzag long. This allows negative numbers to be /// Convert l into a zigzag long. This allows negative numbers to be
* represented compactly as a varint. /// represented compactly as a varint.
*/ /// </summary>
private ulong longToZigzag(long n) private ulong longToZigzag(long n)
{ {
return (ulong)(n << 1) ^ (ulong)(n >> 63); return (ulong)(n << 1) ^ (ulong)(n >> 63);
} }
/** /// <summary>
* Convert n into a zigzag int. This allows negative numbers to be /// Convert n into a zigzag int. This allows negative numbers to be
* represented compactly as a varint. /// represented compactly as a varint.
*/ /// </summary>
private uint intToZigZag(int n) private uint intToZigZag(int n)
{ {
return (uint)(n << 1) ^ (uint)(n >> 31); return (uint)(n << 1) ^ (uint)(n >> 31);
} }
/** /// <summary>
* Convert a long into little-endian bytes in buf starting at off and going /// Convert a long into little-endian bytes in buf starting at off and going
* until off+7. /// until off+7.
*/ /// </summary>
private void fixedLongToBytes(long n, byte[] buf, int off) private void fixedLongToBytes(long n, byte[] buf, int off)
{ {
buf[off + 0] = (byte)(n & 0xff); buf[off + 0] = (byte)(n & 0xff);
@ -475,9 +473,9 @@ namespace Thrift.Protocol
#region ReadMethods #region ReadMethods
/** /// <summary>
* Read a message header. /// Read a message header.
*/ /// </summary>
public override TMessage ReadMessageBegin() public override TMessage ReadMessageBegin()
{ {
byte protocolId = (byte)ReadByte(); byte protocolId = (byte)ReadByte();
@ -493,14 +491,14 @@ namespace Thrift.Protocol
} }
byte type = (byte)((versionAndType >> TYPE_SHIFT_AMOUNT) & TYPE_BITS); byte type = (byte)((versionAndType >> TYPE_SHIFT_AMOUNT) & TYPE_BITS);
int seqid = (int)ReadVarint32(); int seqid = (int)ReadVarint32();
String messageName = ReadString(); string messageName = ReadString();
return new TMessage(messageName, (TMessageType)type, seqid); return new TMessage(messageName, (TMessageType)type, seqid);
} }
/** /// <summary>
* Read a struct begin. There's nothing on the wire for this, but it is our /// Read a struct begin. There's nothing on the wire for this, but it is our
* opportunity to push a new struct begin marker onto the field stack. /// opportunity to push a new struct begin marker onto the field stack.
*/ /// </summary>
public override TStruct ReadStructBegin() public override TStruct ReadStructBegin()
{ {
lastField_.Push(lastFieldId_); lastField_.Push(lastFieldId_);
@ -508,19 +506,19 @@ namespace Thrift.Protocol
return ANONYMOUS_STRUCT; return ANONYMOUS_STRUCT;
} }
/** /// <summary>
* Doesn't actually consume any wire data, just removes the last field for /// Doesn't actually consume any wire data, just removes the last field for
* this struct from the field stack. /// this struct from the field stack.
*/ /// </summary>
public override void ReadStructEnd() public override void ReadStructEnd()
{ {
// consume the last field we Read off the wire. // consume the last field we Read off the wire.
lastFieldId_ = lastField_.Pop(); lastFieldId_ = lastField_.Pop();
} }
/** /// <summary>
* Read a field header off the wire. /// Read a field header off the wire.
*/ /// </summary>
public override TField ReadFieldBegin() public override TField ReadFieldBegin()
{ {
byte type = (byte)ReadByte(); byte type = (byte)ReadByte();
@ -560,11 +558,11 @@ namespace Thrift.Protocol
return field; return field;
} }
/** /// <summary>
* Read a map header off the wire. If the size is zero, skip Reading the key /// Read a map header off the wire. If the size is zero, skip Reading the key
* and value type. This means that 0-length maps will yield TMaps without the /// and value type. This means that 0-length maps will yield TMaps without the
* "correct" types. /// "correct" types.
*/ /// </summary>
public override TMap ReadMapBegin() public override TMap ReadMapBegin()
{ {
int size = (int)ReadVarint32(); int size = (int)ReadVarint32();
@ -572,12 +570,12 @@ namespace Thrift.Protocol
return new TMap(getTType((byte)(keyAndValueType >> 4)), getTType((byte)(keyAndValueType & 0xf)), size); return new TMap(getTType((byte)(keyAndValueType >> 4)), getTType((byte)(keyAndValueType & 0xf)), size);
} }
/** /// <summary>
* Read a list header off the wire. If the list size is 0-14, the size will /// Read a list header off the wire. If the list size is 0-14, the size will
* be packed into the element type header. If it's a longer list, the 4 MSB /// be packed into the element type header. If it's a longer list, the 4 MSB
* of the element type header will be 0xF, and a varint will follow with the /// of the element type header will be 0xF, and a varint will follow with the
* true size. /// true size.
*/ /// </summary>
public override TList ReadListBegin() public override TList ReadListBegin()
{ {
byte size_and_type = (byte)ReadByte(); byte size_and_type = (byte)ReadByte();
@ -590,22 +588,22 @@ namespace Thrift.Protocol
return new TList(type, size); return new TList(type, size);
} }
/** /// <summary>
* Read a set header off the wire. If the set size is 0-14, the size will /// Read a set header off the wire. If the set size is 0-14, the size will
* be packed into the element type header. If it's a longer set, the 4 MSB /// be packed into the element type header. If it's a longer set, the 4 MSB
* of the element type header will be 0xF, and a varint will follow with the /// of the element type header will be 0xF, and a varint will follow with the
* true size. /// true size.
*/ /// </summary>
public override TSet ReadSetBegin() public override TSet ReadSetBegin()
{ {
return new TSet(ReadListBegin()); return new TSet(ReadListBegin());
} }
/** /// <summary>
* Read a boolean off the wire. If this is a boolean field, the value should /// Read a boolean off the wire. If this is a boolean field, the value should
* already have been Read during ReadFieldBegin, so we'll just consume the /// already have been Read during ReadFieldBegin, so we'll just consume the
* pre-stored value. Otherwise, Read a byte. /// pre-stored value. Otherwise, Read a byte.
*/ /// </summary>
public override Boolean ReadBool() public override Boolean ReadBool()
{ {
if (boolValue_ != null) if (boolValue_ != null)
@ -618,42 +616,42 @@ namespace Thrift.Protocol
} }
byte[] byteRawBuf = new byte[1]; byte[] byteRawBuf = new byte[1];
/** /// <summary>
* Read a single byte off the wire. Nothing interesting here. /// Read a single byte off the wire. Nothing interesting here.
*/ /// </summary>
public override sbyte ReadByte() public override sbyte ReadByte()
{ {
trans.ReadAll(byteRawBuf, 0, 1); trans.ReadAll(byteRawBuf, 0, 1);
return (sbyte)byteRawBuf[0]; return (sbyte)byteRawBuf[0];
} }
/** /// <summary>
* Read an i16 from the wire as a zigzag varint. /// Read an i16 from the wire as a zigzag varint.
*/ /// </summary>
public override short ReadI16() public override short ReadI16()
{ {
return (short)zigzagToInt(ReadVarint32()); return (short)zigzagToInt(ReadVarint32());
} }
/** /// <summary>
* Read an i32 from the wire as a zigzag varint. /// Read an i32 from the wire as a zigzag varint.
*/ /// </summary>
public override int ReadI32() public override int ReadI32()
{ {
return zigzagToInt(ReadVarint32()); return zigzagToInt(ReadVarint32());
} }
/** /// <summary>
* Read an i64 from the wire as a zigzag varint. /// Read an i64 from the wire as a zigzag varint.
*/ /// </summary>
public override long ReadI64() public override long ReadI64()
{ {
return zigzagToLong(ReadVarint64()); return zigzagToLong(ReadVarint64());
} }
/** /// <summary>
* No magic here - just Read a double off the wire. /// No magic here - just Read a double off the wire.
*/ /// </summary>
public override double ReadDouble() public override double ReadDouble()
{ {
byte[] longBits = new byte[8]; byte[] longBits = new byte[8];
@ -661,10 +659,10 @@ namespace Thrift.Protocol
return BitConverter.Int64BitsToDouble(bytesToLong(longBits)); return BitConverter.Int64BitsToDouble(bytesToLong(longBits));
} }
/** /// <summary>
* Reads a byte[] (via ReadBinary), and then UTF-8 decodes it. /// Reads a byte[] (via ReadBinary), and then UTF-8 decodes it.
*/ /// </summary>
public override String ReadString() public override string ReadString()
{ {
int length = (int)ReadVarint32(); int length = (int)ReadVarint32();
@ -676,9 +674,9 @@ namespace Thrift.Protocol
return Encoding.UTF8.GetString(ReadBinary(length)); return Encoding.UTF8.GetString(ReadBinary(length));
} }
/** /// <summary>
* Read a byte[] from the wire. /// Read a byte[] from the wire.
*/ /// </summary>
public override byte[] ReadBinary() public override byte[] ReadBinary()
{ {
int length = (int)ReadVarint32(); int length = (int)ReadVarint32();
@ -689,9 +687,9 @@ namespace Thrift.Protocol
return buf; return buf;
} }
/** /// <summary>
* Read a byte[] of a known length from the wire. /// Read a byte[] of a known length from the wire.
*/ /// </summary>
private byte[] ReadBinary(int length) private byte[] ReadBinary(int length)
{ {
if (length == 0) return new byte[0]; if (length == 0) return new byte[0];
@ -715,10 +713,10 @@ namespace Thrift.Protocol
// Internal Reading methods // Internal Reading methods
// //
/** /// <summary>
* Read an i32 from the wire as a varint. The MSB of each byte is set /// Read an i32 from the wire as a varint. The MSB of each byte is set
* if there is another byte to follow. This can Read up to 5 bytes. /// if there is another byte to follow. This can Read up to 5 bytes.
*/ /// </summary>
private uint ReadVarint32() private uint ReadVarint32()
{ {
uint result = 0; uint result = 0;
@ -733,10 +731,10 @@ namespace Thrift.Protocol
return result; return result;
} }
/** /// <summary>
* Read an i64 from the wire as a proper varint. The MSB of each byte is set /// Read an i64 from the wire as a proper varint. The MSB of each byte is set
* if there is another byte to follow. This can Read up to 10 bytes. /// if there is another byte to follow. This can Read up to 10 bytes.
*/ /// </summary>
private ulong ReadVarint64() private ulong ReadVarint64()
{ {
int shift = 0; int shift = 0;
@ -758,27 +756,27 @@ namespace Thrift.Protocol
// encoding helpers // encoding helpers
// //
/** /// <summary>
* Convert from zigzag int to int. /// Convert from zigzag int to int.
*/ /// </summary>
private int zigzagToInt(uint n) private int zigzagToInt(uint n)
{ {
return (int)(n >> 1) ^ (-(int)(n & 1)); return (int)(n >> 1) ^ (-(int)(n & 1));
} }
/** /// <summary>
* Convert from zigzag long to long. /// Convert from zigzag long to long.
*/ /// </summary>
private long zigzagToLong(ulong n) private long zigzagToLong(ulong n)
{ {
return (long)(n >> 1) ^ (-(long)(n & 1)); return (long)(n >> 1) ^ (-(long)(n & 1));
} }
/** /// <summary>
* Note that it's important that the mask bytes are long literals, /// Note that it's important that the mask bytes are long literals,
* otherwise they'll default to ints, and when you shift an int left 56 bits, /// otherwise they'll default to ints, and when you shift an int left 56 bits,
* you just get a messed up int. /// you just get a messed up int.
*/ /// </summary>
private long bytesToLong(byte[] bytes) private long bytesToLong(byte[] bytes)
{ {
return return
@ -802,10 +800,10 @@ namespace Thrift.Protocol
return lowerNibble == Types.BOOLEAN_TRUE || lowerNibble == Types.BOOLEAN_FALSE; return lowerNibble == Types.BOOLEAN_TRUE || lowerNibble == Types.BOOLEAN_FALSE;
} }
/** /// <summary>
* Given a TCompactProtocol.Types constant, convert it to its corresponding /// Given a TCompactProtocol.Types constant, convert it to its corresponding
* TType value. /// TType value.
*/ /// </summary>
private TType getTType(byte type) private TType getTType(byte type)
{ {
switch ((byte)(type & 0x0f)) switch ((byte)(type & 0x0f))
@ -840,9 +838,9 @@ namespace Thrift.Protocol
} }
} }
/** /// <summary>
* Given a TType value, find the appropriate TCompactProtocol.Types constant. /// Given a TType value, find the appropriate TCompactProtocol.Types constant.
*/ /// </summary>
private byte getCompactType(TType ttype) private byte getCompactType(TType ttype)
{ {
return ttypeToCompactType[(int)ttype]; return ttypeToCompactType[(int)ttype];

View File

@ -29,18 +29,18 @@ namespace Thrift.Protocol
{ {
/// <summary> /// <summary>
/// JSON protocol implementation for thrift. /// JSON protocol implementation for thrift.
/// /// <para/>
/// This is a full-featured protocol supporting Write and Read. /// This is a full-featured protocol supporting Write and Read.
/// /// <para/>
/// Please see the C++ class header for a detailed description of the /// Please see the C++ class header for a detailed description of the
/// protocol's wire format. /// protocol's wire format.
/// /// <para/>
/// Adapted from the Java version. /// Adapted from the Java version.
/// </summary> /// </summary>
public class TJSONProtocol : TProtocol public class TJSONProtocol : TProtocol
{ {
/// <summary> /// <summary>
/// Factory for JSON protocol objects /// Factory for JSON protocol objects.
/// </summary> /// </summary>
public class Factory : TProtocolFactory public class Factory : TProtocolFactory
{ {
@ -179,11 +179,11 @@ namespace Thrift.Protocol
return result; return result;
} }
///<summary> /// <summary>
/// Base class for tracking JSON contexts that may require /// Base class for tracking JSON contexts that may require
/// inserting/Reading additional JSON syntax characters /// inserting/Reading additional JSON syntax characters
/// This base context does nothing. /// This base context does nothing.
///</summary> /// </summary>
protected class JSONBaseContext protected class JSONBaseContext
{ {
protected TJSONProtocol proto; protected TJSONProtocol proto;
@ -200,10 +200,10 @@ namespace Thrift.Protocol
public virtual bool EscapeNumbers() { return false; } public virtual bool EscapeNumbers() { return false; }
} }
///<summary> /// <summary>
/// Context for JSON lists. Will insert/Read commas before each item except /// Context for JSON lists. Will insert/Read commas before each item except
/// for the first one /// for the first one
///</summary> /// </summary>
protected class JSONListContext : JSONBaseContext protected class JSONListContext : JSONBaseContext
{ {
public JSONListContext(TJSONProtocol protocol) public JSONListContext(TJSONProtocol protocol)
@ -239,12 +239,12 @@ namespace Thrift.Protocol
} }
} }
///<summary> /// <summary>
/// Context for JSON records. Will insert/Read colons before the value portion /// Context for JSON records. Will insert/Read colons before the value portion
/// of each record pair, and commas before each key except the first. In /// of each record pair, and commas before each key except the first. In
/// addition, will indicate that numbers in the key position need to be /// addition, will indicate that numbers in the key position need to be
/// escaped in quotes (since JSON keys must be strings). /// escaped in quotes (since JSON keys must be strings).
///</summary> /// </summary>
protected class JSONPairContext : JSONBaseContext protected class JSONPairContext : JSONBaseContext
{ {
public JSONPairContext(TJSONProtocol proto) public JSONPairContext(TJSONProtocol proto)
@ -290,9 +290,9 @@ namespace Thrift.Protocol
} }
} }
///<summary> /// <summary>
/// Holds up to one byte from the transport /// Holds up to one byte from the transport
///</summary> /// </summary>
protected class LookaheadReader protected class LookaheadReader
{ {
protected TJSONProtocol proto; protected TJSONProtocol proto;
@ -305,10 +305,10 @@ namespace Thrift.Protocol
private bool hasData; private bool hasData;
private byte[] data = new byte[1]; private byte[] data = new byte[1];
///<summary> /// <summary>
/// Return and consume the next byte to be Read, either taking it from the /// Return and consume the next byte to be Read, either taking it from the
/// data buffer if present or getting it from the transport otherwise. /// data buffer if present or getting it from the transport otherwise.
///</summary> /// </summary>
public byte Read() public byte Read()
{ {
if (hasData) if (hasData)
@ -322,10 +322,10 @@ namespace Thrift.Protocol
return data[0]; return data[0];
} }
///<summary> /// <summary>
/// Return the next byte to be Read without consuming, filling the data /// Return the next byte to be Read without consuming, filling the data
/// buffer if it has not been filled alReady. /// buffer if it has not been filled alReady.
///</summary> /// </summary>
public byte Peek() public byte Peek()
{ {
if (!hasData) if (!hasData)
@ -349,26 +349,26 @@ namespace Thrift.Protocol
// Reader that manages a 1-byte buffer // Reader that manages a 1-byte buffer
protected LookaheadReader reader; protected LookaheadReader reader;
///<summary> /// <summary>
/// Push a new JSON context onto the stack. /// Push a new JSON context onto the stack.
///</summary> /// </summary>
protected void PushContext(JSONBaseContext c) protected void PushContext(JSONBaseContext c)
{ {
contextStack.Push(context); contextStack.Push(context);
context = c; context = c;
} }
///<summary> /// <summary>
/// Pop the last JSON context off the stack /// Pop the last JSON context off the stack
///</summary> /// </summary>
protected void PopContext() protected void PopContext()
{ {
context = contextStack.Pop(); context = contextStack.Pop();
} }
///<summary> /// <summary>
/// TJSONProtocol Constructor /// TJSONProtocol Constructor
///</summary> /// </summary>
public TJSONProtocol(TTransport trans) public TJSONProtocol(TTransport trans)
: base(trans) : base(trans)
{ {
@ -379,11 +379,11 @@ namespace Thrift.Protocol
// Temporary buffer used by several methods // Temporary buffer used by several methods
private byte[] tempBuffer = new byte[4]; private byte[] tempBuffer = new byte[4];
///<summary> /// <summary>
/// Read a byte that must match b[0]; otherwise an exception is thrown. /// Read a byte that must match b[0]; otherwise an exception is thrown.
/// Marked protected to avoid synthetic accessor in JSONListContext.Read /// Marked protected to avoid synthetic accessor in JSONListContext.Read
/// and JSONPairContext.Read /// and JSONPairContext.Read
///</summary> /// </summary>
protected void ReadJSONSyntaxChar(byte[] b) protected void ReadJSONSyntaxChar(byte[] b)
{ {
byte ch = reader.Read(); byte ch = reader.Read();
@ -394,10 +394,10 @@ namespace Thrift.Protocol
} }
} }
///<summary> /// <summary>
/// Convert a byte containing a hex char ('0'-'9' or 'a'-'f') into its /// Convert a byte containing a hex char ('0'-'9' or 'a'-'f') into its
/// corresponding hex value /// corresponding hex value
///</summary> /// </summary>
private static byte HexVal(byte ch) private static byte HexVal(byte ch)
{ {
if ((ch >= '0') && (ch <= '9')) if ((ch >= '0') && (ch <= '9'))
@ -416,9 +416,9 @@ namespace Thrift.Protocol
} }
} }
///<summary> /// <summary>
/// Convert a byte containing a hex value to its corresponding hex character /// Convert a byte containing a hex value to its corresponding hex character
///</summary> /// </summary>
private static byte HexChar(byte val) private static byte HexChar(byte val)
{ {
val &= 0x0F; val &= 0x0F;
@ -433,9 +433,9 @@ namespace Thrift.Protocol
} }
} }
///<summary> /// <summary>
/// Write the bytes in array buf as a JSON characters, escaping as needed /// Write the bytes in array buf as a JSON characters, escaping as needed
///</summary> /// </summary>
private void WriteJSONString(byte[] b) private void WriteJSONString(byte[] b)
{ {
context.Write(); context.Write();
@ -479,14 +479,14 @@ namespace Thrift.Protocol
trans.Write(QUOTE); trans.Write(QUOTE);
} }
///<summary> /// <summary>
/// Write out number as a JSON value. If the context dictates so, it will be /// Write out number as a JSON value. If the context dictates so, it will be
/// wrapped in quotes to output as a JSON string. /// wrapped in quotes to output as a JSON string.
///</summary> /// </summary>
private void WriteJSONInteger(long num) private void WriteJSONInteger(long num)
{ {
context.Write(); context.Write();
String str = num.ToString(); string str = num.ToString();
bool escapeNum = context.EscapeNumbers(); bool escapeNum = context.EscapeNumbers();
if (escapeNum) if (escapeNum)
@ -498,14 +498,14 @@ namespace Thrift.Protocol
trans.Write(QUOTE); trans.Write(QUOTE);
} }
///<summary> /// <summary>
/// Write out a double as a JSON value. If it is NaN or infinity or if the /// Write out a double as a JSON value. If it is NaN or infinity or if the
/// context dictates escaping, Write out as JSON string. /// context dictates escaping, Write out as JSON string.
///</summary> /// </summary>
private void WriteJSONDouble(double num) private void WriteJSONDouble(double num)
{ {
context.Write(); context.Write();
String str = num.ToString("G17", CultureInfo.InvariantCulture); string str = num.ToString("G17", CultureInfo.InvariantCulture);
bool special = false; bool special = false;
switch (str[0]) switch (str[0])
@ -532,10 +532,10 @@ namespace Thrift.Protocol
if (escapeNum) if (escapeNum)
trans.Write(QUOTE); trans.Write(QUOTE);
} }
///<summary> /// <summary>
/// Write out contents of byte array b as a JSON string with base-64 encoded /// Write out contents of byte array b as a JSON string with base-64 encoded
/// data /// data
///</summary> /// </summary>
private void WriteJSONBase64(byte[] b) private void WriteJSONBase64(byte[] b)
{ {
context.Write(); context.Write();
@ -698,7 +698,7 @@ namespace Thrift.Protocol
WriteJSONDouble(dub); WriteJSONDouble(dub);
} }
public override void WriteString(String str) public override void WriteString(string str)
{ {
byte[] b = utf8Encoding.GetBytes(str); byte[] b = utf8Encoding.GetBytes(str);
WriteJSONString(b); WriteJSONString(b);
@ -713,10 +713,10 @@ namespace Thrift.Protocol
* Reading methods. * Reading methods.
*/ */
///<summary> /// <summary>
/// Read in a JSON string, unescaping as appropriate.. Skip Reading from the /// Read in a JSON string, unescaping as appropriate.. Skip Reading from the
/// context if skipContext is true. /// context if skipContext is true.
///</summary> /// </summary>
private byte[] ReadJSONString(bool skipContext) private byte[] ReadJSONString(bool skipContext)
{ {
MemoryStream buffer = new MemoryStream(); MemoryStream buffer = new MemoryStream();
@ -803,9 +803,9 @@ namespace Thrift.Protocol
return buffer.ToArray(); return buffer.ToArray();
} }
///<summary> /// <summary>
/// Return true if the given byte could be a valid part of a JSON number. /// Return true if the given byte could be a valid part of a JSON number.
///</summary> /// </summary>
private bool IsJSONNumeric(byte b) private bool IsJSONNumeric(byte b)
{ {
switch (b) switch (b)
@ -830,11 +830,11 @@ namespace Thrift.Protocol
return false; return false;
} }
///<summary> /// <summary>
/// Read in a sequence of characters that are all valid in JSON numbers. Does /// Read in a sequence of characters that are all valid in JSON numbers. Does
/// not do a complete regex check to validate that this is actually a number. /// not do a complete regex check to validate that this is actually a number.
////</summary> /// </summary>
private String ReadJSONNumericChars() private string ReadJSONNumericChars()
{ {
StringBuilder strbld = new StringBuilder(); StringBuilder strbld = new StringBuilder();
while (true) while (true)
@ -849,9 +849,9 @@ namespace Thrift.Protocol
return strbld.ToString(); return strbld.ToString();
} }
///<summary> /// <summary>
/// Read in a JSON number. If the context dictates, Read in enclosing quotes. /// Read in a JSON number. If the context dictates, Read in enclosing quotes.
///</summary> /// </summary>
private long ReadJSONInteger() private long ReadJSONInteger()
{ {
context.Read(); context.Read();
@ -859,7 +859,7 @@ namespace Thrift.Protocol
{ {
ReadJSONSyntaxChar(QUOTE); ReadJSONSyntaxChar(QUOTE);
} }
String str = ReadJSONNumericChars(); string str = ReadJSONNumericChars();
if (context.EscapeNumbers()) if (context.EscapeNumbers())
{ {
ReadJSONSyntaxChar(QUOTE); ReadJSONSyntaxChar(QUOTE);
@ -875,17 +875,17 @@ namespace Thrift.Protocol
} }
} }
///<summary> /// <summary>
/// Read in a JSON double value. Throw if the value is not wrapped in quotes /// Read in a JSON double value. Throw if the value is not wrapped in quotes
/// when expected or if wrapped in quotes when not expected. /// when expected or if wrapped in quotes when not expected.
///</summary> /// </summary>
private double ReadJSONDouble() private double ReadJSONDouble()
{ {
context.Read(); context.Read();
if (reader.Peek() == QUOTE[0]) if (reader.Peek() == QUOTE[0])
{ {
byte[] arr = ReadJSONString(true); byte[] arr = ReadJSONString(true);
double dub = Double.Parse(utf8Encoding.GetString(arr,0,arr.Length), CultureInfo.InvariantCulture); double dub = Double.Parse(utf8Encoding.GetString(arr, 0, arr.Length), CultureInfo.InvariantCulture);
if (!context.EscapeNumbers() && !Double.IsNaN(dub) && if (!context.EscapeNumbers() && !Double.IsNaN(dub) &&
!Double.IsInfinity(dub)) !Double.IsInfinity(dub))
@ -915,9 +915,9 @@ namespace Thrift.Protocol
} }
} }
//<summary> /// <summary>
/// Read in a JSON string containing base-64 encoded data and decode it. /// Read in a JSON string containing base-64 encoded data and decode it.
///</summary> /// </summary>
private byte[] ReadJSONBase64() private byte[] ReadJSONBase64()
{ {
byte[] b = ReadJSONString(false); byte[] b = ReadJSONString(false);
@ -989,7 +989,7 @@ namespace Thrift.Protocol
} }
var buf = ReadJSONString(false); var buf = ReadJSONString(false);
message.Name = utf8Encoding.GetString(buf,0,buf.Length); message.Name = utf8Encoding.GetString(buf, 0, buf.Length);
message.Type = (TMessageType)ReadJSONInteger(); message.Type = (TMessageType)ReadJSONInteger();
message.SeqID = (int)ReadJSONInteger(); message.SeqID = (int)ReadJSONInteger();
return message; return message;
@ -1108,10 +1108,10 @@ namespace Thrift.Protocol
return ReadJSONDouble(); return ReadJSONDouble();
} }
public override String ReadString() public override string ReadString()
{ {
var buf = ReadJSONString(false); var buf = ReadJSONString(false);
return utf8Encoding.GetString(buf,0,buf.Length); return utf8Encoding.GetString(buf, 0, buf.Length);
} }
public override byte[] ReadBinary() public override byte[] ReadBinary()

View File

@ -29,74 +29,77 @@ using System.IO;
namespace Thrift.Protocol namespace Thrift.Protocol
{ {
/// <summary>
/** /// <see cref="TMultiplexedProcessor"/> is a <see cref="TProcessor"/> allowing a single <see cref="Thrift.Server.TServer"/>
* TMultiplexedProcessor is a TProcessor allowing a single TServer to provide multiple services. /// to provide multiple services.
* To do so, you instantiate the processor and then register additional processors with it, /// <para/>
* as shown in the following example: /// To do so, you instantiate the processor and then register additional processors with it,
* /// as shown in the following example:
* TMultiplexedProcessor processor = new TMultiplexedProcessor(); /// <para/>
* /// <code>
* processor.registerProcessor( /// TMultiplexedProcessor processor = new TMultiplexedProcessor();
* "Calculator", ///
* new Calculator.Processor(new CalculatorHandler())); /// processor.registerProcessor(
* /// "Calculator",
* processor.registerProcessor( /// new Calculator.Processor(new CalculatorHandler()));
* "WeatherReport", ///
* new WeatherReport.Processor(new WeatherReportHandler())); /// processor.registerProcessor(
* /// "WeatherReport",
* TServerTransport t = new TServerSocket(9090); /// new WeatherReport.Processor(new WeatherReportHandler()));
* TSimpleServer server = new TSimpleServer(processor, t); ///
* /// TServerTransport t = new TServerSocket(9090);
* server.serve(); /// TSimpleServer server = new TSimpleServer(processor, t);
*/ ///
/// server.serve();
/// </code>
/// </summary>
public class TMultiplexedProcessor : TProcessor public class TMultiplexedProcessor : TProcessor
{ {
private Dictionary<String,TProcessor> ServiceProcessorMap = new Dictionary<String,TProcessor>(); private Dictionary<string, TProcessor> ServiceProcessorMap = new Dictionary<string, TProcessor>();
/** /// <summary>
* 'Register' a service with this TMultiplexedProcessor. This allows us to broker /// 'Register' a service with this TMultiplexedProcessor. This allows us to broker
* requests to individual services by using the service name to select them at request time. /// requests to individual services by using the service name to select them at request time.
* ///
* Args: /// Args:
* - serviceName Name of a service, has to be identical to the name /// - serviceName Name of a service, has to be identical to the name
* declared in the Thrift IDL, e.g. "WeatherReport". /// declared in the Thrift IDL, e.g. "WeatherReport".
* - processor Implementation of a service, usually referred to as "handlers", /// - processor Implementation of a service, usually referred to as "handlers",
* e.g. WeatherReportHandler implementing WeatherReport.Iface. /// e.g. WeatherReportHandler implementing WeatherReport.Iface.
*/ /// </summary>
public void RegisterProcessor(String serviceName, TProcessor processor) public void RegisterProcessor(string serviceName, TProcessor processor)
{ {
ServiceProcessorMap.Add(serviceName, processor); ServiceProcessorMap.Add(serviceName, processor);
} }
private void Fail( TProtocol oprot, TMessage message, TApplicationException.ExceptionType extype, string etxt) private void Fail(TProtocol oprot, TMessage message, TApplicationException.ExceptionType extype, string etxt)
{ {
TApplicationException appex = new TApplicationException( extype, etxt); TApplicationException appex = new TApplicationException(extype, etxt);
TMessage newMessage = new TMessage(message.Name, TMessageType.Exception, message.SeqID); TMessage newMessage = new TMessage(message.Name, TMessageType.Exception, message.SeqID);
oprot.WriteMessageBegin(newMessage); oprot.WriteMessageBegin(newMessage);
appex.Write( oprot); appex.Write(oprot);
oprot.WriteMessageEnd(); oprot.WriteMessageEnd();
oprot.Transport.Flush(); oprot.Transport.Flush();
} }
/** /// <summary>
* This implementation of process performs the following steps: /// This implementation of process performs the following steps:
* ///
* - Read the beginning of the message. /// - Read the beginning of the message.
* - Extract the service name from the message. /// - Extract the service name from the message.
* - Using the service name to locate the appropriate processor. /// - Using the service name to locate the appropriate processor.
* - Dispatch to the processor, with a decorated instance of TProtocol /// - Dispatch to the processor, with a decorated instance of TProtocol
* that allows readMessageBegin() to return the original TMessage. /// that allows readMessageBegin() to return the original TMessage.
* /// <para/>
* Throws an exception if /// Throws an exception if
* - the message type is not CALL or ONEWAY, /// - the message type is not CALL or ONEWAY,
* - the service name was not found in the message, or /// - the service name was not found in the message, or
* - the service name has not been RegisterProcessor()ed. /// - the service name has not been RegisterProcessor()ed.
*/ /// </summary>
public bool Process(TProtocol iprot, TProtocol oprot) public bool Process(TProtocol iprot, TProtocol oprot)
{ {
/* Use the actual underlying protocol (e.g. TBinaryProtocol) to read the /* Use the actual underlying protocol (e.g. TBinaryProtocol) to read the
@ -155,17 +158,17 @@ namespace Thrift.Protocol
} }
/** /// <summary>
* Our goal was to work with any protocol. In order to do that, we needed /// Our goal was to work with any protocol. In order to do that, we needed
* to allow them to call readMessageBegin() and get a TMessage in exactly /// to allow them to call readMessageBegin() and get a TMessage in exactly
* the standard format, without the service name prepended to TMessage.name. /// the standard format, without the service name prepended to TMessage.name.
*/ /// </summary>
private class StoredMessageProtocol : TProtocolDecorator private class StoredMessageProtocol : TProtocolDecorator
{ {
TMessage MsgBegin; TMessage MsgBegin;
public StoredMessageProtocol(TProtocol protocol, TMessage messageBegin) public StoredMessageProtocol(TProtocol protocol, TMessage messageBegin)
:base(protocol) : base(protocol)
{ {
this.MsgBegin = messageBegin; this.MsgBegin = messageBegin;
} }

View File

@ -29,63 +29,62 @@ using System.Collections.Generic;
namespace Thrift.Protocol namespace Thrift.Protocol
{ {
/** /// <summary>
* TMultiplexedProtocol is a protocol-independent concrete decorator that allows a Thrift /// TMultiplexedProtocol is a protocol-independent concrete decorator that allows a Thrift
* client to communicate with a multiplexing Thrift server, by prepending the service name /// client to communicate with a multiplexing Thrift server, by prepending the service name
* to the function name during function calls. /// to the function name during function calls.
* /// <para/>
* NOTE: THIS IS NOT TO BE USED BY SERVERS. /// NOTE: THIS IS NOT TO BE USED BY SERVERS.
* On the server, use TMultiplexedProcessor to handle requests from a multiplexing client. /// On the server, use TMultiplexedProcessor to handle requests from a multiplexing client.
* /// <para/>
* This example uses a single socket transport to invoke two services: /// This example uses a single socket transport to invoke two services:
* /// <code>
* TSocket transport = new TSocket("localhost", 9090); /// TSocket transport = new TSocket("localhost", 9090);
* transport.open(); /// transport.open();
* ///
* TBinaryProtocol protocol = new TBinaryProtocol(transport); /// TBinaryProtocol protocol = new TBinaryProtocol(transport);
* ///
* TMultiplexedProtocol mp = new TMultiplexedProtocol(protocol, "Calculator"); /// TMultiplexedProtocol mp = new TMultiplexedProtocol(protocol, "Calculator");
* Calculator.Client service = new Calculator.Client(mp); /// Calculator.Client service = new Calculator.Client(mp);
* ///
* TMultiplexedProtocol mp2 = new TMultiplexedProtocol(protocol, "WeatherReport"); /// TMultiplexedProtocol mp2 = new TMultiplexedProtocol(protocol, "WeatherReport");
* WeatherReport.Client service2 = new WeatherReport.Client(mp2); /// WeatherReport.Client service2 = new WeatherReport.Client(mp2);
* ///
* System.out.println(service.add(2,2)); /// System.out.println(service.add(2,2));
* System.out.println(service2.getTemperature()); /// System.out.println(service2.getTemperature());
* /// </code>
*/ /// </summary>
public class TMultiplexedProtocol : TProtocolDecorator public class TMultiplexedProtocol : TProtocolDecorator
{ {
/** Used to delimit the service name from the function name */ /// <summary>
public static String SEPARATOR = ":"; /// Used to delimit the service name from the function name.
/// </summary>
public static string SEPARATOR = ":";
private String ServiceName; private string ServiceName;
/** /// <summary>
* Wrap the specified protocol, allowing it to be used to communicate with a /// Wrap the specified protocol, allowing it to be used to communicate with a
* multiplexing server. The <code>serviceName</code> is required as it is /// multiplexing server. The <paramref name="serviceName"/> is required as it is
* prepended to the message header so that the multiplexing server can broker /// prepended to the message header so that the multiplexing server can broker
* the function call to the proper service. /// the function call to the proper service.
* /// </summary>
* Args: /// <param name="protocol">Your communication protocol of choice, e.g. <see cref="TBinaryProtocol"/>.</param>
* protocol Your communication protocol of choice, e.g. TBinaryProtocol /// <param name="serviceName">The service name of the service communicating via this protocol.</param>
* serviceName The service name of the service communicating via this protocol. public TMultiplexedProtocol(TProtocol protocol, string serviceName)
*/
public TMultiplexedProtocol(TProtocol protocol, String serviceName)
: base(protocol) : base(protocol)
{ {
ServiceName = serviceName; ServiceName = serviceName;
} }
/** /// <summary>
* Prepends the service name to the function name, separated by TMultiplexedProtocol.SEPARATOR. /// Prepends the service name to the function name, separated by TMultiplexedProtocol.SEPARATOR.
* Args: /// </summary>
* tMessage The original message. /// <param name="tMessage">The original message.</param>
*/
public override void WriteMessageBegin(TMessage tMessage) public override void WriteMessageBegin(TMessage tMessage)
{ {
switch(tMessage.Type) switch (tMessage.Type)
{ {
case TMessageType.Call: case TMessageType.Call:
case TMessageType.Oneway: case TMessageType.Oneway:
@ -101,5 +100,4 @@ namespace Thrift.Protocol
} }
} }
} }
} }

View File

@ -108,7 +108,8 @@ namespace Thrift.Protocol
public abstract void WriteI32(int i32); public abstract void WriteI32(int i32);
public abstract void WriteI64(long i64); public abstract void WriteI64(long i64);
public abstract void WriteDouble(double d); public abstract void WriteDouble(double d);
public virtual void WriteString(string s) { public virtual void WriteString(string s)
{
WriteBinary(Encoding.UTF8.GetBytes(s)); WriteBinary(Encoding.UTF8.GetBytes(s));
} }
public abstract void WriteBinary(byte[] b); public abstract void WriteBinary(byte[] b);
@ -131,7 +132,8 @@ namespace Thrift.Protocol
public abstract int ReadI32(); public abstract int ReadI32();
public abstract long ReadI64(); public abstract long ReadI64();
public abstract double ReadDouble(); public abstract double ReadDouble();
public virtual string ReadString() { public virtual string ReadString()
{
var buf = ReadBinary(); var buf = ReadBinary();
return Encoding.UTF8.GetString(buf, 0, buf.Length); return Encoding.UTF8.GetString(buf, 0, buf.Length);
} }

View File

@ -28,26 +28,25 @@ using System.Collections.Generic;
namespace Thrift.Protocol namespace Thrift.Protocol
{ {
/// <summary>
/** /// <see cref="TProtocolDecorator"/> forwards all requests to an enclosed <see cref="TProtocol"/> instance,
* TProtocolDecorator forwards all requests to an enclosed TProtocol instance, /// providing a way to author concise concrete decorator subclasses. While it has
* providing a way to author concise concrete decorator subclasses. While it has /// no abstract methods, it is marked abstract as a reminder that by itself,
* no abstract methods, it is marked abstract as a reminder that by itself, /// it does not modify the behaviour of the enclosed <see cref="TProtocol"/>.
* it does not modify the behaviour of the enclosed TProtocol. /// <para/>
* /// See p.175 of Design Patterns (by Gamma et al.)
* See p.175 of Design Patterns (by Gamma et al.) /// </summary>
* See TMultiplexedProtocol /// <seealso cref="TMultiplexedProtocol"/>
*/
public abstract class TProtocolDecorator : TProtocol public abstract class TProtocolDecorator : TProtocol
{ {
private TProtocol WrappedProtocol; private TProtocol WrappedProtocol;
/** /// <summary>
* Encloses the specified protocol. /// Encloses the specified protocol.
* @param protocol All operations will be forward to this protocol. Must be non-null. /// </summary>
*/ /// <param name="protocol">All operations will be forward to this protocol. Must be non-null.</param>
public TProtocolDecorator(TProtocol protocol) public TProtocolDecorator(TProtocol protocol)
: base( protocol.Transport) : base(protocol.Transport)
{ {
WrappedProtocol = protocol; WrappedProtocol = protocol;
@ -104,7 +103,7 @@ namespace Thrift.Protocol
} }
public override void WriteListEnd() public override void WriteListEnd()
{ {
WrappedProtocol.WriteListEnd(); WrappedProtocol.WriteListEnd();
} }
@ -148,7 +147,7 @@ namespace Thrift.Protocol
WrappedProtocol.WriteDouble(v); WrappedProtocol.WriteDouble(v);
} }
public override void WriteString(String s) public override void WriteString(string s)
{ {
WrappedProtocol.WriteString(s); WrappedProtocol.WriteString(s);
} }
@ -248,7 +247,7 @@ namespace Thrift.Protocol
return WrappedProtocol.ReadDouble(); return WrappedProtocol.ReadDouble();
} }
public override String ReadString() public override string ReadString()
{ {
return WrappedProtocol.ReadString(); return WrappedProtocol.ReadString();
} }

View File

@ -48,13 +48,13 @@ namespace Thrift.Protocol
type_ = type; type_ = type;
} }
public TProtocolException(int type, String message) public TProtocolException(int type, string message)
: base(message) : base(message)
{ {
type_ = type; type_ = type;
} }
public TProtocolException(String message) public TProtocolException(string message)
: base(message) : base(message)
{ {
} }

View File

@ -98,7 +98,6 @@ namespace Thrift.Protocol
default: default:
throw new TProtocolException(TProtocolException.INVALID_DATA, "Unknown data type " + type.ToString("d")); throw new TProtocolException(TProtocolException.INVALID_DATA, "Unknown data type " + type.ToString("d"));
} }
} }
finally finally
{ {

View File

@ -28,128 +28,128 @@ using System.IO;
namespace Thrift.Server namespace Thrift.Server
{ {
public abstract class TServer public abstract class TServer
{ {
//Attributes //Attributes
protected TProcessorFactory processorFactory; protected TProcessorFactory processorFactory;
protected TServerTransport serverTransport; protected TServerTransport serverTransport;
protected TTransportFactory inputTransportFactory; protected TTransportFactory inputTransportFactory;
protected TTransportFactory outputTransportFactory; protected TTransportFactory outputTransportFactory;
protected TProtocolFactory inputProtocolFactory; protected TProtocolFactory inputProtocolFactory;
protected TProtocolFactory outputProtocolFactory; protected TProtocolFactory outputProtocolFactory;
protected TServerEventHandler serverEventHandler = null; protected TServerEventHandler serverEventHandler = null;
//Methods //Methods
public void setEventHandler(TServerEventHandler seh) public void setEventHandler(TServerEventHandler seh)
{ {
serverEventHandler = seh; serverEventHandler = seh;
} }
public TServerEventHandler getEventHandler() public TServerEventHandler getEventHandler()
{ {
return serverEventHandler; return serverEventHandler;
} }
//Log delegation //Log delegation
public delegate void LogDelegate(string str); public delegate void LogDelegate(string str);
private LogDelegate _logDelegate; private LogDelegate _logDelegate;
protected LogDelegate logDelegate protected LogDelegate logDelegate
{ {
get { return _logDelegate; } get { return _logDelegate; }
set { _logDelegate = (value != null) ? value : DefaultLogDelegate; } set { _logDelegate = (value != null) ? value : DefaultLogDelegate; }
} }
protected static void DefaultLogDelegate(string s) protected static void DefaultLogDelegate(string s)
{ {
Console.Error.WriteLine(s); Console.Error.WriteLine(s);
} }
//Construction //Construction
public TServer(TProcessor processor, public TServer(TProcessor processor,
TServerTransport serverTransport) TServerTransport serverTransport)
: this(processor, serverTransport, : this(processor, serverTransport,
new TTransportFactory(), new TTransportFactory(),
new TTransportFactory(), new TTransportFactory(),
new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(),
new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(),
DefaultLogDelegate) DefaultLogDelegate)
{ {
} }
public TServer(TProcessor processor, public TServer(TProcessor processor,
TServerTransport serverTransport,
LogDelegate logDelegate)
: this(processor,
serverTransport,
new TTransportFactory(),
new TTransportFactory(),
new TBinaryProtocol.Factory(),
new TBinaryProtocol.Factory(),
logDelegate)
{
}
public TServer(TProcessor processor,
TServerTransport serverTransport,
TTransportFactory transportFactory)
: this(processor,
serverTransport,
transportFactory,
transportFactory,
new TBinaryProtocol.Factory(),
new TBinaryProtocol.Factory(),
DefaultLogDelegate)
{
}
public TServer(TProcessor processor,
TServerTransport serverTransport,
TTransportFactory transportFactory,
TProtocolFactory protocolFactory)
: this(processor,
serverTransport,
transportFactory,
transportFactory,
protocolFactory,
protocolFactory,
DefaultLogDelegate)
{
}
public TServer(TProcessor processor,
TServerTransport serverTransport, TServerTransport serverTransport,
TTransportFactory inputTransportFactory,
TTransportFactory outputTransportFactory,
TProtocolFactory inputProtocolFactory,
TProtocolFactory outputProtocolFactory,
LogDelegate logDelegate) LogDelegate logDelegate)
: this(processor, {
serverTransport, this.processorFactory = new TSingletonProcessorFactory(processor);
new TTransportFactory(), this.serverTransport = serverTransport;
new TTransportFactory(), this.inputTransportFactory = inputTransportFactory;
new TBinaryProtocol.Factory(), this.outputTransportFactory = outputTransportFactory;
new TBinaryProtocol.Factory(), this.inputProtocolFactory = inputProtocolFactory;
logDelegate) this.outputProtocolFactory = outputProtocolFactory;
{ this.logDelegate = (logDelegate != null) ? logDelegate : DefaultLogDelegate;
} }
public TServer(TProcessor processor, public TServer(TProcessorFactory processorFactory,
TServerTransport serverTransport, TServerTransport serverTransport,
TTransportFactory transportFactory) TTransportFactory inputTransportFactory,
: this(processor, TTransportFactory outputTransportFactory,
serverTransport, TProtocolFactory inputProtocolFactory,
transportFactory, TProtocolFactory outputProtocolFactory,
transportFactory, LogDelegate logDelegate)
new TBinaryProtocol.Factory(), {
new TBinaryProtocol.Factory(), this.processorFactory = processorFactory;
DefaultLogDelegate) this.serverTransport = serverTransport;
{ this.inputTransportFactory = inputTransportFactory;
} this.outputTransportFactory = outputTransportFactory;
this.inputProtocolFactory = inputProtocolFactory;
this.outputProtocolFactory = outputProtocolFactory;
this.logDelegate = (logDelegate != null) ? logDelegate : DefaultLogDelegate;
}
public TServer(TProcessor processor, //Abstract Interface
TServerTransport serverTransport, public abstract void Serve();
TTransportFactory transportFactory, public abstract void Stop();
TProtocolFactory protocolFactory)
: this(processor,
serverTransport,
transportFactory,
transportFactory,
protocolFactory,
protocolFactory,
DefaultLogDelegate)
{
} }
public TServer(TProcessor processor,
TServerTransport serverTransport,
TTransportFactory inputTransportFactory,
TTransportFactory outputTransportFactory,
TProtocolFactory inputProtocolFactory,
TProtocolFactory outputProtocolFactory,
LogDelegate logDelegate)
{
this.processorFactory = new TSingletonProcessorFactory(processor);
this.serverTransport = serverTransport;
this.inputTransportFactory = inputTransportFactory;
this.outputTransportFactory = outputTransportFactory;
this.inputProtocolFactory = inputProtocolFactory;
this.outputProtocolFactory = outputProtocolFactory;
this.logDelegate = (logDelegate != null) ? logDelegate : DefaultLogDelegate;
}
public TServer(TProcessorFactory processorFactory,
TServerTransport serverTransport,
TTransportFactory inputTransportFactory,
TTransportFactory outputTransportFactory,
TProtocolFactory inputProtocolFactory,
TProtocolFactory outputProtocolFactory,
LogDelegate logDelegate)
{
this.processorFactory = processorFactory;
this.serverTransport = serverTransport;
this.inputTransportFactory = inputTransportFactory;
this.outputTransportFactory = outputTransportFactory;
this.inputProtocolFactory = inputProtocolFactory;
this.outputProtocolFactory = outputProtocolFactory;
this.logDelegate = (logDelegate != null) ? logDelegate : DefaultLogDelegate;
}
//Abstract Interface
public abstract void Serve();
public abstract void Stop();
}
} }

View File

@ -25,26 +25,29 @@ using System;
namespace Thrift.Server namespace Thrift.Server
{ {
/// <summary>
/// Interface implemented by server users to handle events from the server
/// </summary>
public interface TServerEventHandler
{
/// <summary> /// <summary>
/// Called before the server begins */ /// Interface implemented by server users to handle events from the server.
/// </summary> /// </summary>
void preServe(); public interface TServerEventHandler
/// <summary> {
/// Called when a new client has connected and is about to being processing */ /// <summary>
/// </summary> /// Called before the server begins.
Object createContext(Thrift.Protocol.TProtocol input, Thrift.Protocol.TProtocol output); /// </summary>
/// <summary> void preServe();
/// Called when a client has finished request-handling to delete server context */
/// </summary> /// <summary>
void deleteContext(Object serverContext, Thrift.Protocol.TProtocol input, Thrift.Protocol.TProtocol output); /// Called when a new client has connected and is about to being processing.
/// <summary> /// </summary>
/// Called when a client is about to call the processor */ object createContext(Thrift.Protocol.TProtocol input, Thrift.Protocol.TProtocol output);
/// </summary>
void processContext(Object serverContext, Thrift.Transport.TTransport transport); /// <summary>
}; /// Called when a client has finished request-handling to delete server context.
/// </summary>
void deleteContext(object serverContext, Thrift.Protocol.TProtocol input, Thrift.Protocol.TProtocol output);
/// <summary>
/// Called when a client is about to call the processor.
/// </summary>
void processContext(object serverContext, Thrift.Transport.TTransport transport);
};
} }

View File

@ -27,154 +27,154 @@ using Thrift.Protocol;
namespace Thrift.Server namespace Thrift.Server
{ {
/// <summary> /// <summary>
/// Simple single-threaded server for testing /// Simple single-threaded server for testing.
/// </summary> /// </summary>
public class TSimpleServer : TServer public class TSimpleServer : TServer
{
private bool stop = false;
public TSimpleServer(TProcessor processor,
TServerTransport serverTransport)
: base(processor, serverTransport, new TTransportFactory(), new TTransportFactory(), new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(), DefaultLogDelegate)
{ {
} private bool stop = false;
public TSimpleServer(TProcessor processor, public TSimpleServer(TProcessor processor,
TServerTransport serverTransport, TServerTransport serverTransport)
LogDelegate logDel) : base(processor, serverTransport, new TTransportFactory(), new TTransportFactory(), new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(), DefaultLogDelegate)
: base(processor, serverTransport, new TTransportFactory(), new TTransportFactory(), new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(), logDel)
{
}
public TSimpleServer(TProcessor processor,
TServerTransport serverTransport,
TTransportFactory transportFactory)
: base(processor,
serverTransport,
transportFactory,
transportFactory,
new TBinaryProtocol.Factory(),
new TBinaryProtocol.Factory(),
DefaultLogDelegate)
{
}
public TSimpleServer(TProcessor processor,
TServerTransport serverTransport,
TTransportFactory transportFactory,
TProtocolFactory protocolFactory)
: base(processor,
serverTransport,
transportFactory,
transportFactory,
protocolFactory,
protocolFactory,
DefaultLogDelegate)
{
}
public TSimpleServer(TProcessorFactory processorFactory,
TServerTransport serverTransport,
TTransportFactory transportFactory,
TProtocolFactory protocolFactory)
: base(processorFactory,
serverTransport,
transportFactory,
transportFactory,
protocolFactory,
protocolFactory,
DefaultLogDelegate)
{
}
public override void Serve()
{
try
{
serverTransport.Listen();
}
catch (TTransportException ttx)
{
logDelegate(ttx.ToString());
return;
}
//Fire the preServe server event when server is up but before any client connections
if (serverEventHandler != null)
serverEventHandler.preServe();
while (!stop)
{
TProcessor processor = null;
TTransport client = null;
TTransport inputTransport = null;
TTransport outputTransport = null;
TProtocol inputProtocol = null;
TProtocol outputProtocol = null;
Object connectionContext = null;
try
{ {
using (client = serverTransport.Accept()) }
{
processor = processorFactory.GetProcessor(client); public TSimpleServer(TProcessor processor,
if (client != null) TServerTransport serverTransport,
LogDelegate logDel)
: base(processor, serverTransport, new TTransportFactory(), new TTransportFactory(), new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(), logDel)
{
}
public TSimpleServer(TProcessor processor,
TServerTransport serverTransport,
TTransportFactory transportFactory)
: base(processor,
serverTransport,
transportFactory,
transportFactory,
new TBinaryProtocol.Factory(),
new TBinaryProtocol.Factory(),
DefaultLogDelegate)
{
}
public TSimpleServer(TProcessor processor,
TServerTransport serverTransport,
TTransportFactory transportFactory,
TProtocolFactory protocolFactory)
: base(processor,
serverTransport,
transportFactory,
transportFactory,
protocolFactory,
protocolFactory,
DefaultLogDelegate)
{
}
public TSimpleServer(TProcessorFactory processorFactory,
TServerTransport serverTransport,
TTransportFactory transportFactory,
TProtocolFactory protocolFactory)
: base(processorFactory,
serverTransport,
transportFactory,
transportFactory,
protocolFactory,
protocolFactory,
DefaultLogDelegate)
{
}
public override void Serve()
{
try
{ {
using (inputTransport = inputTransportFactory.GetTransport(client)) serverTransport.Listen();
{ }
using (outputTransport = outputTransportFactory.GetTransport(client)) catch (TTransportException ttx)
{ {
inputProtocol = inputProtocolFactory.GetProtocol(inputTransport); logDelegate(ttx.ToString());
outputProtocol = outputProtocolFactory.GetProtocol(outputTransport); return;
}
//Recover event handler (if any) and fire createContext server event when a client connects
if (serverEventHandler != null) //Fire the preServe server event when server is up but before any client connections
connectionContext = serverEventHandler.createContext(inputProtocol, outputProtocol); if (serverEventHandler != null)
serverEventHandler.preServe();
//Process client requests until client disconnects
while (!stop) while (!stop)
{ {
if (!inputTransport.Peek()) TProcessor processor = null;
break; TTransport client = null;
TTransport inputTransport = null;
//Fire processContext server event TTransport outputTransport = null;
//N.B. This is the pattern implemented in C++ and the event fires provisionally. TProtocol inputProtocol = null;
//That is to say it may be many minutes between the event firing and the client request TProtocol outputProtocol = null;
//actually arriving or the client may hang up without ever makeing a request. object connectionContext = null;
if (serverEventHandler != null) try
serverEventHandler.processContext(connectionContext, inputTransport); {
//Process client request (blocks until transport is readable) using (client = serverTransport.Accept())
if (!processor.Process(inputProtocol, outputProtocol)) {
break; processor = processorFactory.GetProcessor(client);
} if (client != null)
} {
} using (inputTransport = inputTransportFactory.GetTransport(client))
{
using (outputTransport = outputTransportFactory.GetTransport(client))
{
inputProtocol = inputProtocolFactory.GetProtocol(inputTransport);
outputProtocol = outputProtocolFactory.GetProtocol(outputTransport);
//Recover event handler (if any) and fire createContext server event when a client connects
if (serverEventHandler != null)
connectionContext = serverEventHandler.createContext(inputProtocol, outputProtocol);
//Process client requests until client disconnects
while (!stop)
{
if (!inputTransport.Peek())
break;
//Fire processContext server event
//N.B. This is the pattern implemented in C++ and the event fires provisionally.
//That is to say it may be many minutes between the event firing and the client request
//actually arriving or the client may hang up without ever makeing a request.
if (serverEventHandler != null)
serverEventHandler.processContext(connectionContext, inputTransport);
//Process client request (blocks until transport is readable)
if (!processor.Process(inputProtocol, outputProtocol))
break;
}
}
}
}
}
}
catch (TTransportException ttx)
{
if (!stop || ttx.Type != TTransportException.ExceptionType.Interrupted)
{
logDelegate(ttx.ToString());
}
}
catch (Exception x)
{
//Unexpected
logDelegate(x.ToString());
}
//Fire deleteContext server event after client disconnects
if (serverEventHandler != null)
serverEventHandler.deleteContext(connectionContext, inputProtocol, outputProtocol);
} }
}
}
catch (TTransportException ttx)
{
if (!stop || ttx.Type != TTransportException.ExceptionType.Interrupted)
{
logDelegate(ttx.ToString());
}
}
catch (Exception x)
{
//Unexpected
logDelegate(x.ToString());
} }
//Fire deleteContext server event after client disconnects public override void Stop()
if (serverEventHandler != null) {
serverEventHandler.deleteContext(connectionContext, inputProtocol, outputProtocol); stop = true;
} serverTransport.Close();
}
} }
public override void Stop()
{
stop = true;
serverTransport.Close();
}
}
} }

View File

@ -28,268 +28,268 @@ using Thrift.Transport;
namespace Thrift.Server namespace Thrift.Server
{ {
/// <summary>
/// Server that uses C# built-in ThreadPool to spawn threads when handling requests
/// </summary>
public class TThreadPoolServer : TServer
{
private const int DEFAULT_MIN_THREADS = -1; // use .NET ThreadPool defaults
private const int DEFAULT_MAX_THREADS = -1; // use .NET ThreadPool defaults
private volatile bool stop = false;
public struct Configuration
{
public int MinWorkerThreads;
public int MaxWorkerThreads;
public int MinIOThreads;
public int MaxIOThreads;
public Configuration(int min = DEFAULT_MIN_THREADS, int max = DEFAULT_MAX_THREADS)
{
MinWorkerThreads = min;
MaxWorkerThreads = max;
MinIOThreads = min;
MaxIOThreads = max;
}
public Configuration(int minWork, int maxWork, int minIO, int maxIO)
{
MinWorkerThreads = minWork;
MaxWorkerThreads = maxWork;
MinIOThreads = minIO;
MaxIOThreads = maxIO;
}
}
public TThreadPoolServer(TProcessor processor, TServerTransport serverTransport)
: this(new TSingletonProcessorFactory(processor), serverTransport,
new TTransportFactory(), new TTransportFactory(),
new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(),
new Configuration(), DefaultLogDelegate)
{
}
public TThreadPoolServer(TProcessor processor, TServerTransport serverTransport, LogDelegate logDelegate)
: this(new TSingletonProcessorFactory(processor), serverTransport,
new TTransportFactory(), new TTransportFactory(),
new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(),
new Configuration(), logDelegate)
{
}
public TThreadPoolServer(TProcessor processor,
TServerTransport serverTransport,
TTransportFactory transportFactory,
TProtocolFactory protocolFactory)
: this(new TSingletonProcessorFactory(processor), serverTransport,
transportFactory, transportFactory,
protocolFactory, protocolFactory,
new Configuration(), DefaultLogDelegate)
{
}
public TThreadPoolServer(TProcessorFactory processorFactory,
TServerTransport serverTransport,
TTransportFactory transportFactory,
TProtocolFactory protocolFactory)
: this(processorFactory, serverTransport,
transportFactory, transportFactory,
protocolFactory, protocolFactory,
new Configuration(), DefaultLogDelegate)
{
}
public TThreadPoolServer(TProcessorFactory processorFactory,
TServerTransport serverTransport,
TTransportFactory inputTransportFactory,
TTransportFactory outputTransportFactory,
TProtocolFactory inputProtocolFactory,
TProtocolFactory outputProtocolFactory,
int minThreadPoolThreads, int maxThreadPoolThreads, LogDelegate logDel)
: this(processorFactory, serverTransport, inputTransportFactory, outputTransportFactory,
inputProtocolFactory, outputProtocolFactory,
new Configuration(minThreadPoolThreads, maxThreadPoolThreads),
logDel)
{
}
public TThreadPoolServer(TProcessorFactory processorFactory,
TServerTransport serverTransport,
TTransportFactory inputTransportFactory,
TTransportFactory outputTransportFactory,
TProtocolFactory inputProtocolFactory,
TProtocolFactory outputProtocolFactory,
Configuration threadConfig,
LogDelegate logDel)
: base(processorFactory, serverTransport, inputTransportFactory, outputTransportFactory,
inputProtocolFactory, outputProtocolFactory, logDel)
{
lock (typeof(TThreadPoolServer))
{
if ((threadConfig.MaxWorkerThreads > 0) || (threadConfig.MaxIOThreads > 0))
{
int work, comm;
ThreadPool.GetMaxThreads(out work, out comm);
if (threadConfig.MaxWorkerThreads > 0)
work = threadConfig.MaxWorkerThreads;
if (threadConfig.MaxIOThreads > 0)
comm = threadConfig.MaxIOThreads;
if (!ThreadPool.SetMaxThreads(work, comm))
throw new Exception("Error: could not SetMaxThreads in ThreadPool");
}
if ((threadConfig.MinWorkerThreads > 0) || (threadConfig.MinIOThreads > 0))
{
int work, comm;
ThreadPool.GetMinThreads(out work, out comm);
if (threadConfig.MinWorkerThreads > 0)
work = threadConfig.MinWorkerThreads;
if (threadConfig.MinIOThreads > 0)
comm = threadConfig.MinIOThreads;
if (!ThreadPool.SetMinThreads(work, comm))
throw new Exception("Error: could not SetMinThreads in ThreadPool");
}
}
}
/// <summary> /// <summary>
/// Use new ThreadPool thread for each new client connection /// Server that uses C# built-in ThreadPool to spawn threads when handling requests.
/// </summary> /// </summary>
public override void Serve() public class TThreadPoolServer : TServer
{ {
try private const int DEFAULT_MIN_THREADS = -1; // use .NET ThreadPool defaults
{ private const int DEFAULT_MAX_THREADS = -1; // use .NET ThreadPool defaults
serverTransport.Listen(); private volatile bool stop = false;
}
catch (TTransportException ttx)
{
logDelegate("Error, could not listen on ServerTransport: " + ttx);
return;
}
//Fire the preServe server event when server is up but before any client connections public struct Configuration
if (serverEventHandler != null)
serverEventHandler.preServe();
while (!stop)
{
int failureCount = 0;
try
{ {
TTransport client = serverTransport.Accept(); public int MinWorkerThreads;
ThreadPool.QueueUserWorkItem(this.Execute, client); public int MaxWorkerThreads;
public int MinIOThreads;
public int MaxIOThreads;
public Configuration(int min = DEFAULT_MIN_THREADS, int max = DEFAULT_MAX_THREADS)
{
MinWorkerThreads = min;
MaxWorkerThreads = max;
MinIOThreads = min;
MaxIOThreads = max;
}
public Configuration(int minWork, int maxWork, int minIO, int maxIO)
{
MinWorkerThreads = minWork;
MaxWorkerThreads = maxWork;
MinIOThreads = minIO;
MaxIOThreads = maxIO;
}
} }
catch (TTransportException ttx)
{
if (!stop || ttx.Type != TTransportException.ExceptionType.Interrupted)
{
++failureCount;
logDelegate(ttx.ToString());
}
public TThreadPoolServer(TProcessor processor, TServerTransport serverTransport)
: this(new TSingletonProcessorFactory(processor), serverTransport,
new TTransportFactory(), new TTransportFactory(),
new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(),
new Configuration(), DefaultLogDelegate)
{
} }
}
if (stop) public TThreadPoolServer(TProcessor processor, TServerTransport serverTransport, LogDelegate logDelegate)
{ : this(new TSingletonProcessorFactory(processor), serverTransport,
try new TTransportFactory(), new TTransportFactory(),
new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(),
new Configuration(), logDelegate)
{ {
serverTransport.Close();
} }
catch (TTransportException ttx)
{
logDelegate("TServerTransport failed on close: " + ttx.Message);
}
stop = false;
}
}
/// <summary> public TThreadPoolServer(TProcessor processor,
/// Loops on processing a client forever TServerTransport serverTransport,
/// threadContext will be a TTransport instance TTransportFactory transportFactory,
/// </summary> TProtocolFactory protocolFactory)
/// <param name="threadContext"></param> : this(new TSingletonProcessorFactory(processor), serverTransport,
private void Execute(Object threadContext) transportFactory, transportFactory,
{ protocolFactory, protocolFactory,
using( TTransport client = (TTransport)threadContext) new Configuration(), DefaultLogDelegate)
{
TProcessor processor = processorFactory.GetProcessor(client, this);
TTransport inputTransport = null;
TTransport outputTransport = null;
TProtocol inputProtocol = null;
TProtocol outputProtocol = null;
Object connectionContext = null;
try
{ {
try }
{
inputTransport = inputTransportFactory.GetTransport(client); public TThreadPoolServer(TProcessorFactory processorFactory,
outputTransport = outputTransportFactory.GetTransport(client); TServerTransport serverTransport,
inputProtocol = inputProtocolFactory.GetProtocol(inputTransport); TTransportFactory transportFactory,
outputProtocol = outputProtocolFactory.GetProtocol(outputTransport); TProtocolFactory protocolFactory)
: this(processorFactory, serverTransport,
//Recover event handler (if any) and fire createContext server event when a client connects transportFactory, transportFactory,
protocolFactory, protocolFactory,
new Configuration(), DefaultLogDelegate)
{
}
public TThreadPoolServer(TProcessorFactory processorFactory,
TServerTransport serverTransport,
TTransportFactory inputTransportFactory,
TTransportFactory outputTransportFactory,
TProtocolFactory inputProtocolFactory,
TProtocolFactory outputProtocolFactory,
int minThreadPoolThreads, int maxThreadPoolThreads, LogDelegate logDel)
: this(processorFactory, serverTransport, inputTransportFactory, outputTransportFactory,
inputProtocolFactory, outputProtocolFactory,
new Configuration(minThreadPoolThreads, maxThreadPoolThreads),
logDel)
{
}
public TThreadPoolServer(TProcessorFactory processorFactory,
TServerTransport serverTransport,
TTransportFactory inputTransportFactory,
TTransportFactory outputTransportFactory,
TProtocolFactory inputProtocolFactory,
TProtocolFactory outputProtocolFactory,
Configuration threadConfig,
LogDelegate logDel)
: base(processorFactory, serverTransport, inputTransportFactory, outputTransportFactory,
inputProtocolFactory, outputProtocolFactory, logDel)
{
lock (typeof(TThreadPoolServer))
{
if ((threadConfig.MaxWorkerThreads > 0) || (threadConfig.MaxIOThreads > 0))
{
int work, comm;
ThreadPool.GetMaxThreads(out work, out comm);
if (threadConfig.MaxWorkerThreads > 0)
work = threadConfig.MaxWorkerThreads;
if (threadConfig.MaxIOThreads > 0)
comm = threadConfig.MaxIOThreads;
if (!ThreadPool.SetMaxThreads(work, comm))
throw new Exception("Error: could not SetMaxThreads in ThreadPool");
}
if ((threadConfig.MinWorkerThreads > 0) || (threadConfig.MinIOThreads > 0))
{
int work, comm;
ThreadPool.GetMinThreads(out work, out comm);
if (threadConfig.MinWorkerThreads > 0)
work = threadConfig.MinWorkerThreads;
if (threadConfig.MinIOThreads > 0)
comm = threadConfig.MinIOThreads;
if (!ThreadPool.SetMinThreads(work, comm))
throw new Exception("Error: could not SetMinThreads in ThreadPool");
}
}
}
/// <summary>
/// Use new ThreadPool thread for each new client connection.
/// </summary>
public override void Serve()
{
try
{
serverTransport.Listen();
}
catch (TTransportException ttx)
{
logDelegate("Error, could not listen on ServerTransport: " + ttx);
return;
}
//Fire the preServe server event when server is up but before any client connections
if (serverEventHandler != null) if (serverEventHandler != null)
connectionContext = serverEventHandler.createContext(inputProtocol, outputProtocol); serverEventHandler.preServe();
//Process client requests until client disconnects
while (!stop) while (!stop)
{ {
if (!inputTransport.Peek()) int failureCount = 0;
break; try
{
//Fire processContext server event TTransport client = serverTransport.Accept();
//N.B. This is the pattern implemented in C++ and the event fires provisionally. ThreadPool.QueueUserWorkItem(this.Execute, client);
//That is to say it may be many minutes between the event firing and the client request }
//actually arriving or the client may hang up without ever makeing a request. catch (TTransportException ttx)
if (serverEventHandler != null) {
serverEventHandler.processContext(connectionContext, inputTransport); if (!stop || ttx.Type != TTransportException.ExceptionType.Interrupted)
//Process client request (blocks until transport is readable) {
if (!processor.Process(inputProtocol, outputProtocol)) ++failureCount;
break; logDelegate(ttx.ToString());
} }
}
catch (TTransportException)
{
//Usually a client disconnect, expected
}
catch (Exception x)
{
//Unexpected
logDelegate("Error: " + x);
}
//Fire deleteContext server event after client disconnects
if (serverEventHandler != null)
serverEventHandler.deleteContext(connectionContext, inputProtocol, outputProtocol);
}
finally
{
//Close transports
if (inputTransport != null)
inputTransport.Close();
if (outputTransport != null)
outputTransport.Close();
// disposable stuff should be disposed
if( inputProtocol != null)
inputProtocol.Dispose();
if( outputProtocol != null)
outputProtocol.Dispose();
if( inputTransport != null)
inputTransport.Dispose();
if( outputTransport != null)
outputTransport.Dispose();
}
}
}
public override void Stop() }
{ }
stop = true;
serverTransport.Close(); if (stop)
{
try
{
serverTransport.Close();
}
catch (TTransportException ttx)
{
logDelegate("TServerTransport failed on close: " + ttx.Message);
}
stop = false;
}
}
/// <summary>
/// Loops on processing a client forever
/// threadContext will be a TTransport instance
/// </summary>
/// <param name="threadContext"></param>
private void Execute(object threadContext)
{
using (TTransport client = (TTransport)threadContext)
{
TProcessor processor = processorFactory.GetProcessor(client, this);
TTransport inputTransport = null;
TTransport outputTransport = null;
TProtocol inputProtocol = null;
TProtocol outputProtocol = null;
object connectionContext = null;
try
{
try
{
inputTransport = inputTransportFactory.GetTransport(client);
outputTransport = outputTransportFactory.GetTransport(client);
inputProtocol = inputProtocolFactory.GetProtocol(inputTransport);
outputProtocol = outputProtocolFactory.GetProtocol(outputTransport);
//Recover event handler (if any) and fire createContext server event when a client connects
if (serverEventHandler != null)
connectionContext = serverEventHandler.createContext(inputProtocol, outputProtocol);
//Process client requests until client disconnects
while (!stop)
{
if (!inputTransport.Peek())
break;
//Fire processContext server event
//N.B. This is the pattern implemented in C++ and the event fires provisionally.
//That is to say it may be many minutes between the event firing and the client request
//actually arriving or the client may hang up without ever makeing a request.
if (serverEventHandler != null)
serverEventHandler.processContext(connectionContext, inputTransport);
//Process client request (blocks until transport is readable)
if (!processor.Process(inputProtocol, outputProtocol))
break;
}
}
catch (TTransportException)
{
//Usually a client disconnect, expected
}
catch (Exception x)
{
//Unexpected
logDelegate("Error: " + x);
}
//Fire deleteContext server event after client disconnects
if (serverEventHandler != null)
serverEventHandler.deleteContext(connectionContext, inputProtocol, outputProtocol);
}
finally
{
//Close transports
if (inputTransport != null)
inputTransport.Close();
if (outputTransport != null)
outputTransport.Close();
// disposable stuff should be disposed
if (inputProtocol != null)
inputProtocol.Dispose();
if (outputProtocol != null)
outputProtocol.Dispose();
if (inputTransport != null)
inputTransport.Dispose();
if (outputTransport != null)
outputTransport.Dispose();
}
}
}
public override void Stop()
{
stop = true;
serverTransport.Close();
}
} }
}
} }

View File

@ -26,258 +26,257 @@ using Thrift.Transport;
namespace Thrift.Server namespace Thrift.Server
{ {
/// <summary>
/// Server that uses C# threads (as opposed to the ThreadPool) when handling requests
/// </summary>
public class TThreadedServer : TServer
{
private const int DEFAULT_MAX_THREADS = 100;
private volatile bool stop = false;
private readonly int maxThreads;
private Queue<TTransport> clientQueue;
private THashSet<Thread> clientThreads;
private object clientLock;
private Thread workerThread;
public int ClientThreadsCount {
get { return clientThreads.Count; }
}
public TThreadedServer(TProcessor processor, TServerTransport serverTransport)
: this(new TSingletonProcessorFactory(processor), serverTransport,
new TTransportFactory(), new TTransportFactory(),
new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(),
DEFAULT_MAX_THREADS, DefaultLogDelegate)
{
}
public TThreadedServer(TProcessor processor, TServerTransport serverTransport, LogDelegate logDelegate)
: this(new TSingletonProcessorFactory(processor), serverTransport,
new TTransportFactory(), new TTransportFactory(),
new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(),
DEFAULT_MAX_THREADS, logDelegate)
{
}
public TThreadedServer(TProcessor processor,
TServerTransport serverTransport,
TTransportFactory transportFactory,
TProtocolFactory protocolFactory)
: this(new TSingletonProcessorFactory(processor), serverTransport,
transportFactory, transportFactory,
protocolFactory, protocolFactory,
DEFAULT_MAX_THREADS, DefaultLogDelegate)
{
}
public TThreadedServer(TProcessorFactory processorFactory,
TServerTransport serverTransport,
TTransportFactory transportFactory,
TProtocolFactory protocolFactory)
: this(processorFactory, serverTransport,
transportFactory, transportFactory,
protocolFactory, protocolFactory,
DEFAULT_MAX_THREADS, DefaultLogDelegate)
{
}
public TThreadedServer(TProcessorFactory processorFactory,
TServerTransport serverTransport,
TTransportFactory inputTransportFactory,
TTransportFactory outputTransportFactory,
TProtocolFactory inputProtocolFactory,
TProtocolFactory outputProtocolFactory,
int maxThreads, LogDelegate logDel)
: base(processorFactory, serverTransport, inputTransportFactory, outputTransportFactory,
inputProtocolFactory, outputProtocolFactory, logDel)
{
this.maxThreads = maxThreads;
clientQueue = new Queue<TTransport>();
clientLock = new object();
clientThreads = new THashSet<Thread>();
}
/// <summary> /// <summary>
/// Use new Thread for each new client connection. block until numConnections < maxThreads /// Server that uses C# threads (as opposed to the ThreadPool) when handling requests.
/// </summary> /// </summary>
public override void Serve() public class TThreadedServer : TServer
{ {
try private const int DEFAULT_MAX_THREADS = 100;
{ private volatile bool stop = false;
//start worker thread private readonly int maxThreads;
workerThread = new Thread(new ThreadStart(Execute));
workerThread.Start();
serverTransport.Listen();
}
catch (TTransportException ttx)
{
logDelegate("Error, could not listen on ServerTransport: " + ttx);
return;
}
//Fire the preServe server event when server is up but before any client connections private Queue<TTransport> clientQueue;
if (serverEventHandler != null) private THashSet<Thread> clientThreads;
serverEventHandler.preServe(); private object clientLock;
private Thread workerThread;
while (!stop) public int ClientThreadsCount
{
int failureCount = 0;
try
{ {
TTransport client = serverTransport.Accept(); get { return clientThreads.Count; }
lock (clientLock)
{
clientQueue.Enqueue(client);
Monitor.Pulse(clientLock);
}
} }
catch (TTransportException ttx)
{
if (!stop || ttx.Type != TTransportException.ExceptionType.Interrupted)
{
++failureCount;
logDelegate(ttx.ToString());
}
public TThreadedServer(TProcessor processor, TServerTransport serverTransport)
: this(new TSingletonProcessorFactory(processor), serverTransport,
new TTransportFactory(), new TTransportFactory(),
new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(),
DEFAULT_MAX_THREADS, DefaultLogDelegate)
{
} }
}
if (stop) public TThreadedServer(TProcessor processor, TServerTransport serverTransport, LogDelegate logDelegate)
{ : this(new TSingletonProcessorFactory(processor), serverTransport,
try new TTransportFactory(), new TTransportFactory(),
new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(),
DEFAULT_MAX_THREADS, logDelegate)
{ {
serverTransport.Close();
} }
catch (TTransportException ttx)
public TThreadedServer(TProcessor processor,
TServerTransport serverTransport,
TTransportFactory transportFactory,
TProtocolFactory protocolFactory)
: this(new TSingletonProcessorFactory(processor), serverTransport,
transportFactory, transportFactory,
protocolFactory, protocolFactory,
DEFAULT_MAX_THREADS, DefaultLogDelegate)
{ {
logDelegate("TServeTransport failed on close: " + ttx.Message);
} }
stop = false;
}
}
/// <summary> public TThreadedServer(TProcessorFactory processorFactory,
/// Loops on processing a client forever TServerTransport serverTransport,
/// threadContext will be a TTransport instance TTransportFactory transportFactory,
/// </summary> TProtocolFactory protocolFactory)
/// <param name="threadContext"></param> : this(processorFactory, serverTransport,
private void Execute() transportFactory, transportFactory,
{ protocolFactory, protocolFactory,
while (!stop) DEFAULT_MAX_THREADS, DefaultLogDelegate)
{
TTransport client;
Thread t;
lock (clientLock)
{ {
//don't dequeue if too many connections
while (clientThreads.Count >= maxThreads)
{
Monitor.Wait(clientLock);
}
while (clientQueue.Count == 0)
{
Monitor.Wait(clientLock);
}
client = clientQueue.Dequeue();
t = new Thread(new ParameterizedThreadStart(ClientWorker));
clientThreads.Add(t);
} }
//start processing requests from client on new thread public TThreadedServer(TProcessorFactory processorFactory,
t.Start(client); TServerTransport serverTransport,
} TTransportFactory inputTransportFactory,
} TTransportFactory outputTransportFactory,
TProtocolFactory inputProtocolFactory,
private void ClientWorker(Object context) TProtocolFactory outputProtocolFactory,
{ int maxThreads, LogDelegate logDel)
using( TTransport client = (TTransport)context) : base(processorFactory, serverTransport, inputTransportFactory, outputTransportFactory,
{ inputProtocolFactory, outputProtocolFactory, logDel)
TProcessor processor = processorFactory.GetProcessor(client);
TTransport inputTransport = null;
TTransport outputTransport = null;
TProtocol inputProtocol = null;
TProtocol outputProtocol = null;
Object connectionContext = null;
try
{ {
try this.maxThreads = maxThreads;
{ clientQueue = new Queue<TTransport>();
inputTransport = inputTransportFactory.GetTransport(client); clientLock = new object();
outputTransport = outputTransportFactory.GetTransport(client); clientThreads = new THashSet<Thread>();
inputProtocol = inputProtocolFactory.GetProtocol(inputTransport); }
outputProtocol = outputProtocolFactory.GetProtocol(outputTransport);
/// <summary>
//Recover event handler (if any) and fire createContext server event when a client connects /// Use new Thread for each new client connection. block until numConnections &lt; maxThreads.
/// </summary>
public override void Serve()
{
try
{
//start worker thread
workerThread = new Thread(new ThreadStart(Execute));
workerThread.Start();
serverTransport.Listen();
}
catch (TTransportException ttx)
{
logDelegate("Error, could not listen on ServerTransport: " + ttx);
return;
}
//Fire the preServe server event when server is up but before any client connections
if (serverEventHandler != null) if (serverEventHandler != null)
connectionContext = serverEventHandler.createContext(inputProtocol, outputProtocol); serverEventHandler.preServe();
//Process client requests until client disconnects
while (!stop) while (!stop)
{ {
if (!inputTransport.Peek()) int failureCount = 0;
break; try
{
//Fire processContext server event TTransport client = serverTransport.Accept();
//N.B. This is the pattern implemented in C++ and the event fires provisionally. lock (clientLock)
//That is to say it may be many minutes between the event firing and the client request {
//actually arriving or the client may hang up without ever makeing a request. clientQueue.Enqueue(client);
if (serverEventHandler != null) Monitor.Pulse(clientLock);
serverEventHandler.processContext(connectionContext, inputTransport); }
//Process client request (blocks until transport is readable) }
if (!processor.Process(inputProtocol, outputProtocol)) catch (TTransportException ttx)
break; {
if (!stop || ttx.Type != TTransportException.ExceptionType.Interrupted)
{
++failureCount;
logDelegate(ttx.ToString());
}
}
} }
}
catch (TTransportException)
{
//Usually a client disconnect, expected
}
catch (Exception x)
{
//Unexpected
logDelegate("Error: " + x);
}
//Fire deleteContext server event after client disconnects
if (serverEventHandler != null)
serverEventHandler.deleteContext(connectionContext, inputProtocol, outputProtocol);
lock (clientLock)
{
clientThreads.Remove(Thread.CurrentThread);
Monitor.Pulse(clientLock);
}
} if (stop)
finally {
{ try
//Close transports {
if (inputTransport != null) serverTransport.Close();
inputTransport.Close(); }
if (outputTransport != null) catch (TTransportException ttx)
outputTransport.Close(); {
logDelegate("TServeTransport failed on close: " + ttx.Message);
// disposable stuff should be disposed }
if (inputProtocol != null) stop = false;
inputProtocol.Dispose(); }
if (outputProtocol != null)
outputProtocol.Dispose();
} }
}
}
public override void Stop() /// <summary>
{ /// Loops on processing a client forever
stop = true; /// </summary>
serverTransport.Close(); private void Execute()
//clean up all the threads myself {
workerThread.Abort(); while (!stop)
foreach (Thread t in clientThreads) {
{ TTransport client;
t.Abort(); Thread t;
} lock (clientLock)
{
//don't dequeue if too many connections
while (clientThreads.Count >= maxThreads)
{
Monitor.Wait(clientLock);
}
while (clientQueue.Count == 0)
{
Monitor.Wait(clientLock);
}
client = clientQueue.Dequeue();
t = new Thread(new ParameterizedThreadStart(ClientWorker));
clientThreads.Add(t);
}
//start processing requests from client on new thread
t.Start(client);
}
}
private void ClientWorker(object context)
{
using (TTransport client = (TTransport)context)
{
TProcessor processor = processorFactory.GetProcessor(client);
TTransport inputTransport = null;
TTransport outputTransport = null;
TProtocol inputProtocol = null;
TProtocol outputProtocol = null;
object connectionContext = null;
try
{
try
{
inputTransport = inputTransportFactory.GetTransport(client);
outputTransport = outputTransportFactory.GetTransport(client);
inputProtocol = inputProtocolFactory.GetProtocol(inputTransport);
outputProtocol = outputProtocolFactory.GetProtocol(outputTransport);
//Recover event handler (if any) and fire createContext server event when a client connects
if (serverEventHandler != null)
connectionContext = serverEventHandler.createContext(inputProtocol, outputProtocol);
//Process client requests until client disconnects
while (!stop)
{
if (!inputTransport.Peek())
break;
//Fire processContext server event
//N.B. This is the pattern implemented in C++ and the event fires provisionally.
//That is to say it may be many minutes between the event firing and the client request
//actually arriving or the client may hang up without ever makeing a request.
if (serverEventHandler != null)
serverEventHandler.processContext(connectionContext, inputTransport);
//Process client request (blocks until transport is readable)
if (!processor.Process(inputProtocol, outputProtocol))
break;
}
}
catch (TTransportException)
{
//Usually a client disconnect, expected
}
catch (Exception x)
{
//Unexpected
logDelegate("Error: " + x);
}
//Fire deleteContext server event after client disconnects
if (serverEventHandler != null)
serverEventHandler.deleteContext(connectionContext, inputProtocol, outputProtocol);
lock (clientLock)
{
clientThreads.Remove(Thread.CurrentThread);
Monitor.Pulse(clientLock);
}
}
finally
{
//Close transports
if (inputTransport != null)
inputTransport.Close();
if (outputTransport != null)
outputTransport.Close();
// disposable stuff should be disposed
if (inputProtocol != null)
inputProtocol.Dispose();
if (outputProtocol != null)
outputProtocol.Dispose();
}
}
}
public override void Stop()
{
stop = true;
serverTransport.Close();
//clean up all the threads myself
workerThread.Abort();
foreach (Thread t in clientThreads)
{
t.Abort();
}
}
} }
}
} }

View File

@ -103,7 +103,7 @@ namespace Thrift
oprot.WriteStructBegin(struc); oprot.WriteStructBegin(struc);
if (!String.IsNullOrEmpty(Message)) if (!string.IsNullOrEmpty(Message))
{ {
field.Name = "message"; field.Name = "message";
field.Type = TType.String; field.Type = TType.String;

View File

@ -31,7 +31,7 @@ namespace Thrift
{ {
} }
public TException( string message) public TException(string message)
: base(message) : base(message)
{ {
} }

View File

@ -42,7 +42,7 @@ namespace Thrift
public TProcessor GetProcessor(TTransport trans, TServer server = null) public TProcessor GetProcessor(TTransport trans, TServer server = null)
{ {
H handler = (H) Activator.CreateInstance(typeof(H), handlerArgs); H handler = (H)Activator.CreateInstance(typeof(H), handlerArgs);
TControllingHandler handlerServerRef = handler as TControllingHandler; TControllingHandler handlerServerRef = handler as TControllingHandler;
if (handlerServerRef != null) if (handlerServerRef != null)

View File

@ -17,7 +17,7 @@
* under the License. * under the License.
*/ */
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;

View File

@ -154,11 +154,11 @@ namespace Thrift.Transport
{ {
if (disposing) if (disposing)
{ {
if(inputBuffer != null) if (inputBuffer != null)
inputBuffer.Dispose(); inputBuffer.Dispose();
if(outputBuffer != null) if (outputBuffer != null)
outputBuffer.Dispose(); outputBuffer.Dispose();
if(transport != null) if (transport != null)
transport.Dispose(); transport.Dispose();
} }
} }

View File

@ -116,8 +116,8 @@ namespace Thrift.Transport
byte[] buf = writeBuffer.GetBuffer(); byte[] buf = writeBuffer.GetBuffer();
int len = (int)writeBuffer.Length; int len = (int)writeBuffer.Length;
int data_len = len - HeaderSize; int data_len = len - HeaderSize;
if ( data_len < 0 ) if (data_len < 0)
throw new System.InvalidOperationException (); // logic error actually throw new System.InvalidOperationException(); // logic error actually
// Inject message header into the reserved buffer space // Inject message header into the reserved buffer space
EncodeFrameSize(data_len, buf); EncodeFrameSize(data_len, buf);
@ -130,7 +130,7 @@ namespace Thrift.Transport
transport.Flush(); transport.Flush();
} }
private void InitWriteBuffer () private void InitWriteBuffer()
{ {
// Reserve space for message header to be put right before sending it out // Reserve space for message header to be put right before sending it out
writeBuffer.SetLength(HeaderSize); writeBuffer.SetLength(HeaderSize);
@ -150,7 +150,7 @@ namespace Thrift.Transport
return return
((buf[0] & 0xff) << 24) | ((buf[0] & 0xff) << 24) |
((buf[1] & 0xff) << 16) | ((buf[1] & 0xff) << 16) |
((buf[2] & 0xff) << 8) | ((buf[2] & 0xff) << 8) |
((buf[3] & 0xff)); ((buf[3] & 0xff));
} }
@ -171,11 +171,11 @@ namespace Thrift.Transport
{ {
if (disposing) if (disposing)
{ {
if(readBuffer != null) if (readBuffer != null)
readBuffer.Dispose(); readBuffer.Dispose();
if(writeBuffer != null) if (writeBuffer != null)
writeBuffer.Dispose(); writeBuffer.Dispose();
if(transport != null) if (transport != null)
transport.Dispose(); transport.Dispose();
} }
} }

View File

@ -30,7 +30,6 @@ using System.IO.Compression;
namespace Thrift.Transport namespace Thrift.Transport
{ {
public class THttpClient : TTransport, IDisposable public class THttpClient : TTransport, IDisposable
{ {
private readonly Uri uri; private readonly Uri uri;
@ -43,7 +42,7 @@ namespace Thrift.Transport
private int readTimeout = 30000; private int readTimeout = 30000;
private IDictionary<String, String> customHeaders = new Dictionary<string, string>(); private IDictionary<string, string> customHeaders = new Dictionary<string, string>();
#if !SILVERLIGHT #if !SILVERLIGHT
private IWebProxy proxy = WebRequest.DefaultWebProxy; private IWebProxy proxy = WebRequest.DefaultWebProxy;
@ -64,7 +63,7 @@ namespace Thrift.Transport
{ {
set set
{ {
connectTimeout = value; connectTimeout = value;
} }
} }
@ -76,7 +75,7 @@ namespace Thrift.Transport
} }
} }
public IDictionary<String, String> CustomHeaders public IDictionary<string, string> CustomHeaders
{ {
get get
{ {
@ -325,7 +324,7 @@ namespace Thrift.Transport
{ {
try try
{ {
var flushAsyncResult = (FlushAsyncResult) asyncResult; var flushAsyncResult = (FlushAsyncResult)asyncResult;
if (!flushAsyncResult.IsCompleted) if (!flushAsyncResult.IsCompleted)
{ {
@ -338,7 +337,8 @@ namespace Thrift.Transport
{ {
throw flushAsyncResult.AsyncException; throw flushAsyncResult.AsyncException;
} }
} finally }
finally
{ {
outputStream = new MemoryStream(); outputStream = new MemoryStream();
} }
@ -387,9 +387,9 @@ namespace Thrift.Transport
private volatile Boolean _isCompleted; private volatile Boolean _isCompleted;
private ManualResetEvent _evt; private ManualResetEvent _evt;
private readonly AsyncCallback _cbMethod; private readonly AsyncCallback _cbMethod;
private readonly Object _state; private readonly object _state;
public FlushAsyncResult(AsyncCallback cbMethod, Object state) public FlushAsyncResult(AsyncCallback cbMethod, object state)
{ {
_cbMethod = cbMethod; _cbMethod = cbMethod;
_state = state; _state = state;
@ -415,7 +415,7 @@ namespace Thrift.Transport
{ {
get { return _isCompleted; } get { return _isCompleted; }
} }
private readonly Object _locker = new Object(); private readonly object _locker = new object();
private ManualResetEvent GetEvtHandle() private ManualResetEvent GetEvtHandle()
{ {
lock (_locker) lock (_locker)
@ -452,7 +452,7 @@ namespace Thrift.Transport
} }
} }
#region " IDisposable Support " #region " IDisposable Support "
private bool _IsDisposed; private bool _IsDisposed;
// IDisposable // IDisposable
@ -470,6 +470,6 @@ namespace Thrift.Transport
} }
_IsDisposed = true; _IsDisposed = true;
} }
#endregion #endregion
} }
} }

View File

@ -22,45 +22,56 @@ using System.IO;
using System.Reflection; using System.Reflection;
using Thrift.Protocol; using Thrift.Protocol;
namespace Thrift.Transport { namespace Thrift.Transport
public class TMemoryBuffer : TTransport { {
public class TMemoryBuffer : TTransport
{
private readonly MemoryStream byteStream; private readonly MemoryStream byteStream;
public TMemoryBuffer() { public TMemoryBuffer()
{
byteStream = new MemoryStream(); byteStream = new MemoryStream();
} }
public TMemoryBuffer(byte[] buf) { public TMemoryBuffer(byte[] buf)
{
byteStream = new MemoryStream(buf); byteStream = new MemoryStream(buf);
} }
public override void Open() { public override void Open()
{
/** do nothing **/ /** do nothing **/
} }
public override void Close() { public override void Close()
{
/** do nothing **/ /** do nothing **/
} }
public override int Read(byte[] buf, int off, int len) { public override int Read(byte[] buf, int off, int len)
{
return byteStream.Read(buf, off, len); return byteStream.Read(buf, off, len);
} }
public override void Write(byte[] buf, int off, int len) { public override void Write(byte[] buf, int off, int len)
{
byteStream.Write(buf, off, len); byteStream.Write(buf, off, len);
} }
public byte[] GetBuffer() { public byte[] GetBuffer()
{
return byteStream.ToArray(); return byteStream.ToArray();
} }
public override bool IsOpen { public override bool IsOpen
{
get { return true; } get { return true; }
} }
public static byte[] Serialize(TAbstractBase s) { public static byte[] Serialize(TAbstractBase s)
{
var t = new TMemoryBuffer(); var t = new TMemoryBuffer();
var p = new TBinaryProtocol(t); var p = new TBinaryProtocol(t);
@ -69,26 +80,33 @@ namespace Thrift.Transport {
return t.GetBuffer(); return t.GetBuffer();
} }
public static T DeSerialize<T>(byte[] buf) where T : TAbstractBase { public static T DeSerialize<T>(byte[] buf) where T : TAbstractBase
{
var trans = new TMemoryBuffer(buf); var trans = new TMemoryBuffer(buf);
var p = new TBinaryProtocol(trans); var p = new TBinaryProtocol(trans);
if (typeof (TBase).IsAssignableFrom(typeof (T))) { if (typeof(TBase).IsAssignableFrom(typeof(T)))
var method = typeof (T).GetMethod("Read", BindingFlags.Instance | BindingFlags.Public); {
var method = typeof(T).GetMethod("Read", BindingFlags.Instance | BindingFlags.Public);
var t = Activator.CreateInstance<T>(); var t = Activator.CreateInstance<T>();
method.Invoke(t, new object[] {p}); method.Invoke(t, new object[] { p });
return t; return t;
} else { }
var method = typeof (T).GetMethod("Read", BindingFlags.Static | BindingFlags.Public); else
return (T) method.Invoke(null, new object[] {p}); {
var method = typeof(T).GetMethod("Read", BindingFlags.Static | BindingFlags.Public);
return (T)method.Invoke(null, new object[] { p });
} }
} }
private bool _IsDisposed; private bool _IsDisposed;
// IDisposable // IDisposable
protected override void Dispose(bool disposing) { protected override void Dispose(bool disposing)
if (!_IsDisposed) { {
if (disposing) { if (!_IsDisposed)
{
if (disposing)
{
if (byteStream != null) if (byteStream != null)
byteStream.Dispose(); byteStream.Dispose();
} }
@ -96,4 +114,4 @@ namespace Thrift.Transport {
_IsDisposed = true; _IsDisposed = true;
} }
} }
} }

View File

@ -108,4 +108,4 @@ namespace Thrift.Transport
client.Dispose(); client.Dispose();
} }
} }
} }

View File

@ -27,150 +27,150 @@ using System.Net.Sockets;
namespace Thrift.Transport namespace Thrift.Transport
{ {
public class TServerSocket : TServerTransport public class TServerSocket : TServerTransport
{ {
/** /// <summary>
* Underlying server with socket /// Underlying server with socket.
*/ /// </summary>
private TcpListener server = null; private TcpListener server = null;
/** /// <summary>
* Port to listen on /// Port to listen on.
*/ /// </summary>
private int port = 0; private int port = 0;
/** /// <summary>
* Timeout for client sockets from accept /// Timeout for client sockets from accept.
*/ /// </summary>
private int clientTimeout = 0; private int clientTimeout = 0;
/** /// <summary>
* Whether or not to wrap new TSocket connections in buffers /// Whether or not to wrap new TSocket connections in buffers.
*/ /// </summary>
private bool useBufferedSockets = false; private bool useBufferedSockets = false;
/** /// <summary>
* Creates a server socket from underlying socket object /// Creates a server socket from underlying socket object.
*/ /// </summary>
public TServerSocket(TcpListener listener) public TServerSocket(TcpListener listener)
:this(listener, 0) : this(listener, 0)
{ {
} }
/** /// <summary>
* Creates a server socket from underlying socket object /// Creates a server socket from underlying socket object.
*/ /// </summary>
public TServerSocket(TcpListener listener, int clientTimeout) public TServerSocket(TcpListener listener, int clientTimeout)
{ {
this.server = listener; this.server = listener;
this.clientTimeout = clientTimeout; this.clientTimeout = clientTimeout;
} }
/** /// <summary>
* Creates just a port listening server socket /// Creates just a port listening server socket.
*/ /// </summary>
public TServerSocket(int port) public TServerSocket(int port)
: this(port, 0) : this(port, 0)
{ {
} }
/** /// <summary>
* Creates just a port listening server socket /// Creates just a port listening server socket.
*/ /// </summary>
public TServerSocket(int port, int clientTimeout) public TServerSocket(int port, int clientTimeout)
:this(port, clientTimeout, false) : this(port, clientTimeout, false)
{ {
} }
public TServerSocket(int port, int clientTimeout, bool useBufferedSockets) public TServerSocket(int port, int clientTimeout, bool useBufferedSockets)
{ {
this.port = port; this.port = port;
this.clientTimeout = clientTimeout; this.clientTimeout = clientTimeout;
this.useBufferedSockets = useBufferedSockets; this.useBufferedSockets = useBufferedSockets;
try try
{ {
// Make server socket // Make server socket
this.server = TSocketVersionizer.CreateTcpListener(this.port); this.server = TSocketVersionizer.CreateTcpListener(this.port);
this.server.Server.NoDelay = true; this.server.Server.NoDelay = true;
} }
catch (Exception) catch (Exception)
{ {
server = null; server = null;
throw new TTransportException("Could not create ServerSocket on port " + this.port + "."); throw new TTransportException("Could not create ServerSocket on port " + this.port + ".");
} }
} }
public override void Listen() public override void Listen()
{ {
// Make sure not to block on accept // Make sure not to block on accept
if (server != null) if (server != null)
{ {
try try
{ {
server.Start(); server.Start();
} }
catch (SocketException sx) catch (SocketException sx)
{ {
throw new TTransportException("Could not accept on listening socket: " + sx.Message); throw new TTransportException("Could not accept on listening socket: " + sx.Message);
} }
} }
} }
protected override TTransport AcceptImpl() protected override TTransport AcceptImpl()
{ {
if (server == null) if (server == null)
{ {
throw new TTransportException(TTransportException.ExceptionType.NotOpen, "No underlying server socket."); throw new TTransportException(TTransportException.ExceptionType.NotOpen, "No underlying server socket.");
} }
try try
{ {
TSocket result2 = null; TSocket result2 = null;
TcpClient result = server.AcceptTcpClient(); TcpClient result = server.AcceptTcpClient();
try try
{ {
result2 = new TSocket(result); result2 = new TSocket(result);
result2.Timeout = clientTimeout; result2.Timeout = clientTimeout;
if (useBufferedSockets) if (useBufferedSockets)
{ {
TBufferedTransport result3 = new TBufferedTransport(result2); TBufferedTransport result3 = new TBufferedTransport(result2);
return result3; return result3;
} }
else else
{ {
return result2; return result2;
} }
} }
catch (System.Exception) catch (System.Exception)
{ {
// If a TSocket was successfully created, then let // If a TSocket was successfully created, then let
// it do proper cleanup of the TcpClient object. // it do proper cleanup of the TcpClient object.
if (result2 != null) if (result2 != null)
result2.Dispose(); result2.Dispose();
else // Otherwise, clean it up ourselves. else // Otherwise, clean it up ourselves.
((IDisposable)result).Dispose(); ((IDisposable)result).Dispose();
throw; throw;
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
throw new TTransportException(ex.ToString()); throw new TTransportException(ex.ToString());
} }
} }
public override void Close() public override void Close()
{ {
if (server != null) if (server != null)
{ {
try try
{ {
server.Stop(); server.Stop();
} }
catch (Exception ex) catch (Exception ex)
{ {
throw new TTransportException("WARNING: Could not close server socket: " + ex); throw new TTransportException("WARNING: Could not close server socket: " + ex);
} }
server = null; server = null;
} }
} }
} }
} }

View File

@ -34,10 +34,11 @@ namespace Thrift.Transport
public TTransport Accept() public TTransport Accept()
{ {
TTransport transport = AcceptImpl(); TTransport transport = AcceptImpl();
if (transport == null) { if (transport == null)
throw new TTransportException("accept() may not return NULL"); {
throw new TTransportException("accept() may not return NULL");
} }
return transport; return transport;
} }
} }
} }

View File

@ -112,7 +112,7 @@ namespace Thrift.Transport
throw new TTransportException(TTransportException.ExceptionType.AlreadyOpen, "Socket already connected"); throw new TTransportException(TTransportException.ExceptionType.AlreadyOpen, "Socket already connected");
} }
if (String.IsNullOrEmpty(host)) if (string.IsNullOrEmpty(host))
{ {
throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot open null host"); throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot open null host");
} }
@ -282,9 +282,9 @@ namespace Thrift.Transport
private volatile Boolean _isCompleted; private volatile Boolean _isCompleted;
private ManualResetEvent _evt; private ManualResetEvent _evt;
private readonly AsyncCallback _cbMethod; private readonly AsyncCallback _cbMethod;
private readonly Object _state; private readonly object _state;
public FlushAsyncResult(AsyncCallback cbMethod, Object state) public FlushAsyncResult(AsyncCallback cbMethod, object state)
{ {
_cbMethod = cbMethod; _cbMethod = cbMethod;
_state = state; _state = state;
@ -314,7 +314,7 @@ namespace Thrift.Transport
get { return _isCompleted; } get { return _isCompleted; }
} }
private readonly Object _locker = new Object(); private readonly object _locker = new object();
private ManualResetEvent GetEvtHandle() private ManualResetEvent GetEvtHandle()
{ {
@ -362,7 +362,7 @@ namespace Thrift.Transport
} }
} }
#region " IDisposable Support " #region " IDisposable Support "
private bool _IsDisposed; private bool _IsDisposed;
// IDisposable // IDisposable
@ -385,7 +385,7 @@ namespace Thrift.Transport
} }
_IsDisposed = true; _IsDisposed = true;
} }
#endregion #endregion
} }
} }

View File

@ -26,216 +26,220 @@ using System.Net.Sockets;
namespace Thrift.Transport namespace Thrift.Transport
{ {
public class TSocket : TStreamTransport public class TSocket : TStreamTransport
{ {
private TcpClient client = null; private TcpClient client = null;
private string host = null; private string host = null;
private int port = 0; private int port = 0;
private int timeout = 0; private int timeout = 0;
public TSocket(TcpClient client) public TSocket(TcpClient client)
{ {
this.client = client; this.client = client;
if (IsOpen) if (IsOpen)
{ {
inputStream = client.GetStream(); inputStream = client.GetStream();
outputStream = client.GetStream(); outputStream = client.GetStream();
} }
} }
public TSocket(string host, int port) public TSocket(string host, int port)
: this(host, port, 0) : this(host, port, 0)
{ {
} }
public TSocket(string host, int port, int timeout) public TSocket(string host, int port, int timeout)
{ {
this.host = host; this.host = host;
this.port = port; this.port = port;
this.timeout = timeout; this.timeout = timeout;
InitSocket(); InitSocket();
} }
private void InitSocket() private void InitSocket()
{ {
this.client = TSocketVersionizer.CreateTcpClient(); this.client = TSocketVersionizer.CreateTcpClient();
this.client.ReceiveTimeout = client.SendTimeout = timeout; this.client.ReceiveTimeout = client.SendTimeout = timeout;
this.client.Client.NoDelay = true; this.client.Client.NoDelay = true;
} }
public int Timeout public int Timeout
{ {
set set
{ {
client.ReceiveTimeout = client.SendTimeout = timeout = value; client.ReceiveTimeout = client.SendTimeout = timeout = value;
} }
} }
public TcpClient TcpClient public TcpClient TcpClient
{ {
get get
{ {
return client; return client;
} }
} }
public string Host public string Host
{ {
get get
{ {
return host; return host;
} }
} }
public int Port public int Port
{ {
get get
{ {
return port; return port;
} }
} }
public override bool IsOpen public override bool IsOpen
{ {
get get
{ {
if (client == null) if (client == null)
{ {
return false; return false;
} }
return client.Connected; return client.Connected;
} }
} }
public override void Open() public override void Open()
{ {
if (IsOpen) if (IsOpen)
{ {
throw new TTransportException(TTransportException.ExceptionType.AlreadyOpen, "Socket already connected"); throw new TTransportException(TTransportException.ExceptionType.AlreadyOpen, "Socket already connected");
} }
if (String.IsNullOrEmpty(host)) if (string.IsNullOrEmpty(host))
{ {
throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot open null host"); throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot open null host");
} }
if (port <= 0) if (port <= 0)
{ {
throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot open without port"); throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot open without port");
} }
if (client == null) if (client == null)
{ {
InitSocket(); InitSocket();
} }
if( timeout == 0) // no timeout -> infinite if (timeout == 0) // no timeout -> infinite
{ {
client.Connect(host, port); client.Connect(host, port);
} }
else // we have a timeout -> use it else // we have a timeout -> use it
{ {
ConnectHelper hlp = new ConnectHelper(client); ConnectHelper hlp = new ConnectHelper(client);
IAsyncResult asyncres = client.BeginConnect(host, port, new AsyncCallback(ConnectCallback), hlp); IAsyncResult asyncres = client.BeginConnect(host, port, new AsyncCallback(ConnectCallback), hlp);
bool bConnected = asyncres.AsyncWaitHandle.WaitOne(timeout) && client.Connected; bool bConnected = asyncres.AsyncWaitHandle.WaitOne(timeout) && client.Connected;
if (!bConnected) if (!bConnected)
{ {
lock (hlp.Mutex) lock (hlp.Mutex)
{ {
if( hlp.CallbackDone) if (hlp.CallbackDone)
{ {
asyncres.AsyncWaitHandle.Close(); asyncres.AsyncWaitHandle.Close();
client.Close(); client.Close();
} }
else else
{ {
hlp.DoCleanup = true; hlp.DoCleanup = true;
client = null; client = null;
} }
} }
throw new TTransportException(TTransportException.ExceptionType.TimedOut, "Connect timed out"); throw new TTransportException(TTransportException.ExceptionType.TimedOut, "Connect timed out");
} }
} }
inputStream = client.GetStream(); inputStream = client.GetStream();
outputStream = client.GetStream(); outputStream = client.GetStream();
} }
static void ConnectCallback(IAsyncResult asyncres) static void ConnectCallback(IAsyncResult asyncres)
{ {
ConnectHelper hlp = asyncres.AsyncState as ConnectHelper; ConnectHelper hlp = asyncres.AsyncState as ConnectHelper;
lock (hlp.Mutex) lock (hlp.Mutex)
{ {
hlp.CallbackDone = true; hlp.CallbackDone = true;
try try
{ {
if( hlp.Client.Client != null) if (hlp.Client.Client != null)
hlp.Client.EndConnect(asyncres); hlp.Client.EndConnect(asyncres);
} }
catch (Exception) catch (Exception)
{ {
// catch that away // catch that away
} }
if (hlp.DoCleanup) if (hlp.DoCleanup)
{ {
try { try
asyncres.AsyncWaitHandle.Close(); {
} catch (Exception) {} asyncres.AsyncWaitHandle.Close();
}
catch (Exception) { }
try { try
if (hlp.Client is IDisposable) {
((IDisposable)hlp.Client).Dispose(); if (hlp.Client is IDisposable)
} catch (Exception) {} ((IDisposable)hlp.Client).Dispose();
hlp.Client = null; }
} catch (Exception) { }
} hlp.Client = null;
} }
}
}
private class ConnectHelper private class ConnectHelper
{ {
public object Mutex = new object(); public object Mutex = new object();
public bool DoCleanup = false; public bool DoCleanup = false;
public bool CallbackDone = false; public bool CallbackDone = false;
public TcpClient Client; public TcpClient Client;
public ConnectHelper(TcpClient client) public ConnectHelper(TcpClient client)
{ {
Client = client; Client = client;
} }
} }
public override void Close() public override void Close()
{ {
base.Close(); base.Close();
if (client != null) if (client != null)
{ {
client.Close(); client.Close();
client = null; client = null;
} }
} }
#region " IDisposable Support " #region " IDisposable Support "
private bool _IsDisposed; private bool _IsDisposed;
// IDisposable // IDisposable
protected override void Dispose(bool disposing) protected override void Dispose(bool disposing)
{ {
if (!_IsDisposed) if (!_IsDisposed)
{ {
if (disposing) if (disposing)
{ {
if (client != null) if (client != null)
((IDisposable)client).Dispose(); ((IDisposable)client).Dispose();
base.Dispose(disposing); base.Dispose(disposing);
} }
} }
_IsDisposed = true; _IsDisposed = true;
} }
#endregion #endregion
} }
} }

View File

@ -1,4 +1,27 @@
using System; /**
* 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.
*
* Contains some contributions under the Thrift Software License.
* Please see doc/old-thrift-license.txt in the Thrift distribution for
* details.
*/
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net.Sockets; using System.Net.Sockets;
@ -10,46 +33,46 @@ using System.Threading.Tasks;
namespace Thrift.Transport namespace Thrift.Transport
{ {
/** /// <summary>
* PropertyInfo for the DualMode property of the System.Net.Sockets.Socket class. Used to determine if the sockets are capable of /// PropertyInfo for the DualMode property of the System.Net.Sockets.Socket class. Used to determine if the sockets are capable of
* automatic IPv4 and IPv6 handling. If DualMode is present the sockets automatically handle IPv4 and IPv6 connections. /// automatic IPv4 and IPv6 handling. If DualMode is present the sockets automatically handle IPv4 and IPv6 connections.
* If the DualMode is not available the system configuration determines whether IPv4 or IPv6 is used. /// If the DualMode is not available the system configuration determines whether IPv4 or IPv6 is used.
*/ /// </summary>
internal static class TSocketVersionizer internal static class TSocketVersionizer
{ {
/* /// <summary>
* Creates a TcpClient according to the capabilitites of the used framework /// Creates a TcpClient according to the capabilitites of the used framework
*/ /// </summary>
internal static TcpClient CreateTcpClient() internal static TcpClient CreateTcpClient()
{ {
TcpClient client = null; TcpClient client = null;
#if NET45 #if NET45
client = new TcpClient(AddressFamily.InterNetworkV6); client = new TcpClient(AddressFamily.InterNetworkV6);
client.Client.DualMode = true; client.Client.DualMode = true;
#else #else
client = new TcpClient(AddressFamily.InterNetwork); client = new TcpClient(AddressFamily.InterNetwork);
#endif #endif
return client; return client;
} }
/* /// <summary>
* Creates a TcpListener according to the capabilitites of the used framework /// Creates a TcpListener according to the capabilitites of the used framework.
*/ /// </summary>
internal static TcpListener CreateTcpListener(Int32 port) internal static TcpListener CreateTcpListener(Int32 port)
{ {
TcpListener listener = null; TcpListener listener = null;
#if NET45 #if NET45
listener = new TcpListener(System.Net.IPAddress.IPv6Any, port); listener = new TcpListener(System.Net.IPAddress.IPv6Any, port);
listener.Server.DualMode = true; listener.Server.DualMode = true;
#else #else
listener = new TcpListener(System.Net.IPAddress.Any, port); listener = new TcpListener(System.Net.IPAddress.Any, port);
#endif #endif
return listener; return listener;
} }
} }
} }

View File

@ -105,24 +105,24 @@ namespace Thrift.Transport
} }
#region " IDisposable Support " #region " IDisposable Support "
private bool _IsDisposed; private bool _IsDisposed;
// IDisposable // IDisposable
protected override void Dispose(bool disposing) protected override void Dispose(bool disposing)
{
if (!_IsDisposed)
{
if (disposing)
{ {
if (InputStream != null) if (!_IsDisposed)
InputStream.Dispose(); {
if (OutputStream != null) if (disposing)
OutputStream.Dispose(); {
if (InputStream != null)
InputStream.Dispose();
if (OutputStream != null)
OutputStream.Dispose();
}
}
_IsDisposed = true;
} }
} #endregion
_IsDisposed = true;
} }
#endregion
}
} }

View File

@ -76,7 +76,7 @@ namespace Thrift.Transport
/// <param name="port">The port where the server runs.</param> /// <param name="port">The port where the server runs.</param>
/// <param name="certificate">The certificate object.</param> /// <param name="certificate">The certificate object.</param>
public TTLSServerSocket(int port, X509Certificate2 certificate) public TTLSServerSocket(int port, X509Certificate2 certificate)
: this(port, 0, certificate) : this(port, 0, certificate)
{ {
} }

View File

@ -263,7 +263,7 @@ namespace Thrift.Transport
/// <param name="sender">The sender-object.</param> /// <param name="sender">The sender-object.</param>
/// <param name="certificate">The used certificate.</param> /// <param name="certificate">The used certificate.</param>
/// <param name="chain">The certificate chain.</param> /// <param name="chain">The certificate chain.</param>
/// <param name="sslPolicyErrors">An enum, which lists all the errors from the .NET certificate check.</param> /// <param name="sslValidationErrors">An enum, which lists all the errors from the .NET certificate check.</param>
/// <returns></returns> /// <returns></returns>
private bool DefaultCertificateValidator(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslValidationErrors) private bool DefaultCertificateValidator(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslValidationErrors)
{ {
@ -280,7 +280,7 @@ namespace Thrift.Transport
throw new TTransportException(TTransportException.ExceptionType.AlreadyOpen, "Socket already connected"); throw new TTransportException(TTransportException.ExceptionType.AlreadyOpen, "Socket already connected");
} }
if (String.IsNullOrEmpty(host)) if (string.IsNullOrEmpty(host))
{ {
throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot open null host"); throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot open null host");
} }
@ -307,7 +307,7 @@ namespace Thrift.Transport
{ {
RemoteCertificateValidationCallback validator = this.certValidator ?? DefaultCertificateValidator; RemoteCertificateValidationCallback validator = this.certValidator ?? DefaultCertificateValidator;
if( this.localCertificateSelectionCallback != null) if (this.localCertificateSelectionCallback != null)
{ {
this.secureStream = new SslStream( this.secureStream = new SslStream(
this.client.GetStream(), this.client.GetStream(),
@ -335,7 +335,7 @@ namespace Thrift.Transport
else else
{ {
// Client authentication // Client authentication
X509CertificateCollection certs = certificate != null ? new X509CertificateCollection { certificate } : new X509CertificateCollection(); X509CertificateCollection certs = certificate != null ? new X509CertificateCollection { certificate } : new X509CertificateCollection();
this.secureStream.AuthenticateAsClient(host, certs, sslProtocols, true); this.secureStream.AuthenticateAsClient(host, certs, sslProtocols, true);
} }
} }

View File

@ -53,7 +53,7 @@ namespace Thrift.Transport
if (bytes == 0) if (bytes == 0)
return false; return false;
} }
catch( IOException) catch (IOException)
{ {
return false; return false;
} }
@ -108,7 +108,7 @@ namespace Thrift.Transport
public virtual void Write(byte[] buf) public virtual void Write(byte[] buf)
{ {
Write (buf, 0, buf.Length); Write(buf, 0, buf.Length);
} }
public abstract void Write(byte[] buf, int off, int len); public abstract void Write(byte[] buf, int off, int len);

View File

@ -26,7 +26,7 @@ using System;
namespace Thrift.Transport namespace Thrift.Transport
{ {
/// <summary> /// <summary>
/// From Mark Slee & Aditya Agarwal of Facebook: /// From Mark Slee &amp; Aditya Agarwal of Facebook:
/// Factory class used to create wrapped instance of Transports. /// Factory class used to create wrapped instance of Transports.
/// This is used primarily in servers, which get Transports from /// This is used primarily in servers, which get Transports from
/// a ServerTransport and then may want to mutate them (i.e. create /// a ServerTransport and then may want to mutate them (i.e. create