THRIFT-5370 Haxe 4 compatibility incl TConfiguration & MAX_MESSAGE_SIZE
Client: haxe
Patch: Jens Geyer

This closes #2349
diff --git a/lib/haxe/README.md b/lib/haxe/README.md
index c9f74b5..1f09c2c 100644
--- a/lib/haxe/README.md
+++ b/lib/haxe/README.md
@@ -26,16 +26,14 @@
 Haxe setup
 ---------------
 
-Thrift requires Haxe 3.1.3. Installers for Windows and OSX
+Thrift requires Haxe 4.2.1. Installers for Windows and OSX
 platforms are available at `http://haxe.org/download`. 
 
 Depending on the desired targets, you may have to install the appropriate HaxeLibs 
-after installing Haxe itself. For example, if you plan to target C#, Java and C++,
-enter the following commands after installing Haxe:
+after installing Haxe itself. For example, if you plan to target C++, enter the 
+following command after installing Haxe:
 
     haxelib install hxcpp
-    haxelib install hxjava
-    haxelib install hxcs
 
 For other targets, please consult the Haxe documentation whether or not any additional
 target libraries need to be installed and how to achieve this.
@@ -66,12 +64,12 @@
 Thrift Haxe bindings
 -------------------
 	
-Thrift Haxe bindings can be set up via the `haxelib` tool  
-either from the official ASF repo, or via the github mirror.
+Thrift Haxe bindings can be set up via the `haxelib` tool  as usual.
+Alternatively, the "github" method can be used.
 
-- To set up any **stable version**, choose the appropriate branch (e.g. `0.12.0`):
+- To set up any **stable version**, choose the appropriate branch (e.g. `0.14.1`):
 
-    - `haxelib git thrift https://github.com/apache/thrift.git 0.12.0 lib/haxe`
+    - `haxelib git thrift https://github.com/apache/thrift.git 0.14.1 lib/haxe`
 
 - To set up the current **development version**, use the `master` branch:
   
@@ -85,36 +83,25 @@
 downloads and more information can be found at http://thrift.apache.org
 	
 To get started, visit the /tutorial/haxe and /test/haxe dirs for examples. 
-If you are using HIDE or the FlashDevelop IDE, you'll find appropriate 
-project files in these folders.
+If you are using the HaxeDevelop IDE, you'll find appropriate project files 
+in these folders.
 
 
-Current status
+Breaking changes
 ========================
-- tested with Haxe C++ target
-- tested with Haxe PHP target (console/web server, binary protocols)
-- transports: Socket, HTTP (servers run inside PHP server/PHP target only), Stream
-- protocols: Binary, JSON, Multiplex, Compact
-- tutorial client and server available
-- cross-test client and server available 
+This version requires Haxe 4 and cannot be used with earlier versions.
 
+It is recommended to clear out all gen-haxe contents once before switching 
+to the new version. Otherwise you may run into troubles with leftovers from 
+previous versions.
 
-Further developments
-========================
-- improve to work with C#, Java and JavaScript Haxe/OpenFL targets
-- improve to work with more (ideally all) Haxe/OpenFL targets
-- add HTTP server, update tutorial and tests accordingly
+The compiler option ```callbacks``` is now obsolete. The compiler will always 
+generate a dual interface (i.e. with optional callback style) for use on the 
+client side, plus a new ```_service``` interface to be used for server 
+implementations. Consequentially, your client and server implementations will
+need some manual intervention.
 
 
-Known restrictions
-========================
-
-Although designed with maximum portability in mind, for technical reasons some platforms
-may only support parts of the library, or not be compatible at all.
-
-Javascript:
-- tutorial fails to build because of unsupported Sys.args
-
 PHP HTTP Server notes
 ========================
 
diff --git a/lib/haxe/haxelib.json b/lib/haxe/haxelib.json
index 14d0dcb..61448da 100644
--- a/lib/haxe/haxelib.json
+++ b/lib/haxe/haxelib.json
@@ -2,11 +2,19 @@
 	"name": "thrift",
 	"url" : "http://thrift.apache.org",
 	"license": "Apache",
-	"tags": ["thrift", "rpc", "serialization", "cross", "framework"],
+	"tags": [
+		"thrift", 
+		"rpc", 
+		"serialization", 
+		"cross", 
+		"framework"
+	],
 	"description": "Haxe bindings for the Apache Thrift RPC and serialization framework",
 	"version": "0.15.0",
 	"releasenote": "Licensed under Apache License, Version 2.0. The Apache Thrift compiler needs to be installed separately.",
 	"contributors": ["ApacheThrift"],
-	"dependencies": { },
+	"dependencies": { 
+		"crypto": ""
+	},
 	"classPath": "src"
 }
diff --git a/lib/haxe/src/org/apache/thrift/Limits.hx b/lib/haxe/src/org/apache/thrift/Limits.hx
index 44eec3a..3a7807d 100644
--- a/lib/haxe/src/org/apache/thrift/Limits.hx
+++ b/lib/haxe/src/org/apache/thrift/Limits.hx
@@ -23,9 +23,9 @@
 
     // Haxe limits are not fixed values, they depend on the target platform
     // For example, neko limits an int to 31 bits instead of 32. So we detect
-    // the values once during intialisation in order to
+    // the values once during initialization in order to
     // (a) get the right values for the current  platform, and
-    // (b) prevent us from dependecies to a bunch of defines
+    // (b) prevent us from dependencies to a bunch of defines
 
     public static var I32_MAX = {
         var last : Int = 0;
diff --git a/lib/haxe/src/org/apache/thrift/TConfiguration.hx b/lib/haxe/src/org/apache/thrift/TConfiguration.hx
new file mode 100644
index 0000000..c5ec4e5
--- /dev/null
+++ b/lib/haxe/src/org/apache/thrift/TConfiguration.hx
@@ -0,0 +1,36 @@
+// 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.
+
+package org.apache.thrift;
+
+class TConfiguration
+{
+	public static inline var DEFAULT_MAX_MESSAGE_SIZE = 100 * 1024 * 1024;
+	public static inline var DEFAULT_MAX_FRAME_SIZE = 16384000;      // this value is used consistently across all Thrift libraries
+	public static inline var DEFAULT_RECURSION_DEPTH = 64;
+
+	public var MaxMessageSize(default,null) : Int = DEFAULT_MAX_MESSAGE_SIZE;
+	public var MaxFrameSize(default,null) : Int = DEFAULT_MAX_FRAME_SIZE;
+	public var RecursionLimit(default,null) : Int = DEFAULT_RECURSION_DEPTH;
+
+	// TODO(JensG): add connection and i/o timeouts
+	
+	public function new() {
+		// CTOR
+	}
+}
+
diff --git a/lib/haxe/src/org/apache/thrift/TException.hx b/lib/haxe/src/org/apache/thrift/TException.hx
index 54fa1ff..8bd9fcc 100644
--- a/lib/haxe/src/org/apache/thrift/TException.hx
+++ b/lib/haxe/src/org/apache/thrift/TException.hx
@@ -32,5 +32,10 @@
         errorMsg = msg;
     }
 
+	public function toString() : String {
+		var clsname = Type.getClassName( Type.getClass(this));
+		return '${clsname}: ${errorMsg} (code ${errorID})';
+	}
+	
 }
  
\ No newline at end of file
diff --git a/lib/haxe/src/org/apache/thrift/helper/Int64Map.hx b/lib/haxe/src/org/apache/thrift/helper/Int64Map.hx
index 8845fd0..a8e735f 100644
--- a/lib/haxe/src/org/apache/thrift/helper/Int64Map.hx
+++ b/lib/haxe/src/org/apache/thrift/helper/Int64Map.hx
@@ -137,6 +137,17 @@
         return lomap.exists( GetLowIndex(key));
     }
 
+    public function clear() : Void {
+		SubMaps.clear();
+    }
+
+    public function copy() : IMap< Int64, T> {
+		var retval = new Int64Map<T>();
+		for( key in this.keys())
+			retval.set( key, this.get(key));
+		return retval;
+    }
+
     /**
         Removes the mapping of `key` and returns true if such a mapping existed,
         false otherwise. If `key` is null, the result is unspecified.
@@ -172,6 +183,14 @@
     }
 
     /**
+        Returns an Iterator over the values of `this` Map.
+        The order of values is undefined.
+    **/
+    public function keyValueIterator() : KeyValueIterator<Int64, T> {
+        return new Int64KeyValueIterator<T>(SubMaps);
+    }
+
+    /**
         Returns a String representation of `this` Map.
         The exact representation depends on the platform and key-type.
     **/
@@ -246,7 +265,7 @@
 
 // internal helper class for Int64Map<T>
 // all class with matching methods can be used as iterator (duck typing)
-private class Int64KeyIterator<T>extends Int64MapIteratorBase<T> {
+private class Int64KeyIterator<T> extends Int64MapIteratorBase<T> {
 
     public function new( data : IntMap< IntMap< T>>) : Void {
         super(data);
@@ -270,6 +289,32 @@
 
 // internal helper class for Int64Map<T>
 // all class with matching methods can be used as iterator (duck typing)
+private class Int64KeyValueIterator<T> extends Int64MapIteratorBase<T> {
+
+    public function new( data : IntMap< IntMap< T>>) : Void {
+        super(data);
+    };
+
+    /**
+        Returns the current key/item pair and advances to the next one.
+
+        This method is not required to check hasNext() first. A call to this
+        method while hasNext() is false yields unspecified behavior.
+    **/
+    public function next() : {value:T,key:Int64} {
+        if( ! hasNext()) 
+            throw "no more elements";
+
+		return { 
+			key: Int64.make( CurrentHi, LoIterator.next()), 
+			value: SubMaps.get(CurrentHi).get(LoIterator.next())
+		};
+    }
+}
+
+
+// internal helper class for Int64Map<T>
+// all class with matching methods can be used as iterator (duck typing)
 private class Int64ValueIterator<T> extends Int64MapIteratorBase<T> {
 
     public function new( data : IntMap< IntMap< T>>) : Void {
diff --git a/lib/haxe/src/org/apache/thrift/protocol/TBinaryProtocol.hx b/lib/haxe/src/org/apache/thrift/protocol/TBinaryProtocol.hx
index 7ef291c..2cc254b 100644
--- a/lib/haxe/src/org/apache/thrift/protocol/TBinaryProtocol.hx
+++ b/lib/haxe/src/org/apache/thrift/protocol/TBinaryProtocol.hx
@@ -31,7 +31,7 @@
 /**
 * Binary protocol implementation for thrift.
 */
-class TBinaryProtocol extends TRecursionTracker implements TProtocol {
+class TBinaryProtocol extends TProtocolImplBase implements TProtocol {
 
     private static var ANONYMOUS_STRUCT:TStruct = new TStruct();
 
@@ -40,19 +40,14 @@
 
     private var strictRead_ : Bool = false;
     private var strictWrite_ : Bool = true;
-    private var trans_ : TTransport;
 
     /**
      * Constructor
      */
-    public function new(trans:TTransport, strictRead : Bool=false, strictWrite : Bool=true) {
-      trans_ = trans;
-      strictRead_ = strictRead;
-      strictWrite_ = strictWrite;
-    }
-
-    public function getTransport():TTransport {
-      return trans_;
+    public function new(transport:TTransport, strictRead : Bool = false, strictWrite : Bool = true) {
+		super(transport);
+		strictRead_ = strictRead;
+		strictWrite_ = strictWrite;
     }
 
     public function writeMessageBegin(message:TMessage) : Void {
@@ -116,21 +111,21 @@
         var out = new BytesOutput();
         out.bigEndian = true;
         out.writeByte(b);
-        trans_.write(out.getBytes(), 0, 1);
+        Transport.write(out.getBytes(), 0, 1);
     }
 
     public function writeI16(i16 : Int) : Void {
         var out = new BytesOutput();
         out.bigEndian = true;
         out.writeInt16(i16);
-        trans_.write(out.getBytes(), 0, 2);
+        Transport.write(out.getBytes(), 0, 2);
     }
 
     public function writeI32(i32 : Int) : Void {
         var out = new BytesOutput();
         out.bigEndian = true;
         out.writeInt32(i32);
-        trans_.write(out.getBytes(), 0, 4);
+        Transport.write(out.getBytes(), 0, 4);
     }
 
     public function writeI64(i64 : haxe.Int64) : Void {
@@ -145,14 +140,14 @@
         out.writeInt32(i64.high);
         out.writeInt32(i64.low);
         #end
-        trans_.write(out.getBytes(), 0, 8);
+        Transport.write(out.getBytes(), 0, 8);
     }
 
     public function writeDouble(dub:Float) : Void {
         var out = new BytesOutput();
         out.bigEndian = true;
         out.writeDouble(dub);
-        trans_.write(out.getBytes(), 0, 8);
+        Transport.write(out.getBytes(), 0, 8);
     }
 
     public function writeString(str : String) : Void {
@@ -161,12 +156,12 @@
         out.writeString(str);
         var bytes = out.getBytes();
         writeI32( bytes.length);
-        trans_.write( bytes, 0, bytes.length);
+        Transport.write( bytes, 0, bytes.length);
     }
 
     public function writeBinary(bin:Bytes) : Void {
         writeI32(bin.length);
-        trans_.write(bin, 0, bin.length);
+        Transport.write(bin, 0, bin.length);
     }
 
     /**
@@ -210,19 +205,25 @@
     public function readFieldEnd() : Void {}
 
     public function readMapBegin() : TMap {
-        return new TMap(readByte(), readByte(), readI32());
+        var map = new TMap(readByte(), readByte(), readI32());
+		CheckReadBytesAvailableMap(map);
+        return map;
     }
 
     public function readMapEnd() : Void {}
 
     public function readListBegin():TList {
-        return new TList(readByte(), readI32());
+        var list = new TList(readByte(), readI32());
+		CheckReadBytesAvailableList(list);
+		return list;
     }
 
     public function readListEnd() : Void {}
 
     public function readSetBegin() : TSet {
-      return new TSet(readByte(), readI32());
+		var set = new TSet(readByte(), readI32());
+		CheckReadBytesAvailableSet(set);
+		return set;
     }
 
     public function readSetEnd() : Void {}
@@ -234,7 +235,7 @@
 
     public function readByte() : Int {
         var buffer = new BytesBuffer();
-        var len = trans_.readAll( buffer, 0, 1);
+        var len = Transport.readAll( buffer, 0, 1);
         var inp = new BytesInput( buffer.getBytes(), 0, 1);
         inp.bigEndian = true;
         return inp.readByte();
@@ -242,7 +243,7 @@
 
     public function readI16() : Int {
         var buffer = new BytesBuffer();
-        var len = trans_.readAll( buffer, 0, 2);
+        var len = Transport.readAll( buffer, 0, 2);
         var inp = new BytesInput( buffer.getBytes(), 0, 2);
         inp.bigEndian = true;
         return inp.readInt16();
@@ -250,7 +251,7 @@
 
     public function readI32() : Int {
         var buffer = new BytesBuffer();
-        var len = trans_.readAll( buffer, 0, 4);
+        var len = Transport.readAll( buffer, 0, 4);
         var inp = new BytesInput( buffer.getBytes(), 0, 4);
         inp.bigEndian = true;
         return inp.readInt32();
@@ -258,7 +259,7 @@
 
     public function readI64() : haxe.Int64 {
         var buffer = new BytesBuffer();
-        var len = trans_.readAll( buffer, 0, 8);
+        var len = Transport.readAll( buffer, 0, 8);
         var inp = new BytesInput( buffer.getBytes(), 0, 8);
         inp.bigEndian = true;
         var hi = inp.readInt32();
@@ -268,7 +269,7 @@
 
     public function readDouble():Float {
         var buffer = new BytesBuffer();
-        var len = trans_.readAll( buffer, 0, 8);
+        var len = Transport.readAll( buffer, 0, 8);
         var inp = new BytesInput( buffer.getBytes(), 0, 8);
         inp.bigEndian = true;
         return inp.readDouble();
@@ -279,9 +280,10 @@
     }
 
     public function readStringBody(len : Int) : String {
+		Transport.CheckReadBytesAvailable(len);
         if( len > 0) {
             var buffer = new BytesBuffer();
-            trans_.readAll( buffer, 0, len);
+            Transport.readAll( buffer, 0, len);
             var inp = new BytesInput( buffer.getBytes(), 0, len);
             inp.bigEndian = true;
             return inp.readString(len);
@@ -292,10 +294,33 @@
 
     public function readBinary() : Bytes {
         var len : Int = readI32();
-        var buffer = new BytesBuffer();
-        trans_.readAll( buffer, 0, len);
+		Transport.CheckReadBytesAvailable(len);
+		var buffer = new BytesBuffer();
+        Transport.readAll( buffer, 0, len);
         return buffer.getBytes();
     }
 
+	// Return the minimum number of bytes a type will consume on the wire
+	public override function GetMinSerializedSize(type : TType) : Int
+	{
+		switch (type)
+		{
+			case TType.STOP: return 0;
+			case TType.VOID: return 0;
+			case TType.BOOL: return 1;
+			case TType.BYTE: return 1;
+			case TType.DOUBLE: return 8;
+			case TType.I16: return 2;
+			case TType.I32: return 4;
+			case TType.I64: return 8;
+			case TType.STRING: return 4;  // string length
+			case TType.STRUCT: return 0;  // empty struct
+			case TType.MAP: return 4;  // element count
+			case TType.SET: return 4;  // element count
+			case TType.LIST: return 4;  // element count
+			default: throw new TProtocolException(TProtocolException.NOT_IMPLEMENTED, "unrecognized type code");
+		}
+	}
+
 }
 
diff --git a/lib/haxe/src/org/apache/thrift/protocol/TCompactProtocol.hx b/lib/haxe/src/org/apache/thrift/protocol/TCompactProtocol.hx
index 03b13e2..ae626b5 100644
--- a/lib/haxe/src/org/apache/thrift/protocol/TCompactProtocol.hx
+++ b/lib/haxe/src/org/apache/thrift/protocol/TCompactProtocol.hx
@@ -23,10 +23,10 @@
 import haxe.io.BytesInput;
 import haxe.io.BytesOutput;
 import haxe.io.BytesBuffer;
+import haxe.io.Encoding;
 import haxe.ds.GenericStack;
 import haxe.Int32;
 import haxe.Int64;
-import haxe.Utf8;
 
 import org.apache.thrift.TException;
 import org.apache.thrift.transport.TTransport;
@@ -37,7 +37,7 @@
 /**
 * Compact protocol implementation for thrift.
 */
-class TCompactProtocol extends TRecursionTracker implements TProtocol {
+class TCompactProtocol extends TProtocolImplBase implements TProtocol {
 
     private static var ANONYMOUS_STRUCT : TStruct = new TStruct("");
     private static var TSTOP : TField = new TField("", TType.STOP, 0);
@@ -102,24 +102,11 @@
     private var boolValue_ : Null<Bool>;
 
 
-    // whether the underlying system holds Strings as UTF-8
-    // http://old.haxe.org/manual/encoding
-    private static var utf8Strings = haxe.Utf8.validate("Ç-ß-Æ-Ю-Ш");
-
-    // the transport used
-    public var trans(default,null) : TTransport;
-
-
     // TCompactProtocol Constructor
-    public function new( trans : TTransport) {
-        this.trans = trans;
+    public function new( transport : TTransport) {
+		super(transport);
     }
 
-    public function getTransport() : TTransport {
-      return trans;
-    }
-
-
     public function Reset() : Void{
         while ( ! lastField_.isEmpty()) {
             lastField_.pop();
@@ -135,7 +122,7 @@
     private function WriteByteDirect( b : Int) : Void {
         var buf = Bytes.alloc(1);
         buf.set( 0, b);
-        trans.write( buf, 0, 1);
+        Transport.write( buf, 0, 1);
     }
 
     /**
@@ -158,7 +145,7 @@
         }
 
         var tmp = i32buf.getBytes();
-        trans.write( tmp, 0, tmp.length);
+        Transport.write( tmp, 0, tmp.length);
     }
 
     /**
@@ -329,7 +316,7 @@
      */
     public function writeDouble( dub : Float) : Void {
         var data = BitConverter.fixedLongToBytes( BitConverter.DoubleToInt64Bits(dub));
-        trans.write( data, 0, data.length);
+        Transport.write( data, 0, data.length);
     }
 
     /**
@@ -337,10 +324,7 @@
      */
     public function writeString(str : String) : Void {
         var buf = new BytesBuffer();
-        if( utf8Strings)
-            buf.addString( str);  // no need to encode on UTF8 targets, the string is just fine
-        else
-            buf.addString( Utf8.encode( str));
+		buf.addString( str, Encoding.UTF8);
         var tmp = buf.getBytes();
         writeBinary( tmp);
     }
@@ -350,7 +334,7 @@
      */
     public function writeBinary( bin : Bytes) : Void {
         WriteVarint32( cast(bin.length,UInt));
-        trans.write( bin, 0, bin.length);
+        Transport.write( bin, 0, bin.length);
     }
 
 
@@ -408,7 +392,7 @@
             }
         }
         var tmp = varint64out.getBytes();
-        trans.write( tmp, 0, tmp.length);
+        Transport.write( tmp, 0, tmp.length);
     }
 
 
@@ -497,7 +481,9 @@
         var keyAndValueType : Int = ((size == 0)  ?  0  :  readByte());
         var key : Int = cast( getTType( (keyAndValueType & 0xF0) >> 4), Int);
         var val : Int = cast( getTType( keyAndValueType & 0x0F), Int);
-        return new TMap( key, val, size);
+        var map = new TMap( key, val, size);
+		CheckReadBytesAvailableMap(map);
+        return map;
     }
 
     /**
@@ -515,7 +501,9 @@
         }
 
         var type = getTType(size_and_type);
-        return new TList( type, size);
+        var list = new TList( type, size);
+		CheckReadBytesAvailableList(list);
+        return list;
     }
 
     /**
@@ -533,7 +521,9 @@
         }
 
         var type = getTType(size_and_type);
-        return new TSet( type, size);
+        var set = new TSet( type, size);
+		CheckReadBytesAvailableSet(set);
+        return set;
     }
 
     /**
@@ -556,7 +546,7 @@
      */
     public function readByte() : Int {
         var byteRawBuf = new BytesBuffer();
-        trans.readAll( byteRawBuf, 0, 1);
+        Transport.readAll( byteRawBuf, 0, 1);
         return byteRawBuf.getBytes().get(0);
     }
 
@@ -586,7 +576,7 @@
      */
     public function readDouble():Float {
         var longBits = new BytesBuffer();
-        trans.readAll( longBits, 0, 8);
+        Transport.readAll( longBits, 0, 8);
         return BitConverter.Int64BitsToDouble( BitConverter.bytesToLong( longBits.getBytes()));
     }
 
@@ -595,21 +585,19 @@
      */
     public function readString() : String {
         var length : Int = cast( ReadVarint32(), Int);
+		Transport.CheckReadBytesAvailable(length);
 
         if (length == 0) {
             return "";
         }
 
         var buf = new BytesBuffer();
-        trans.readAll( buf, 0, length);
+        Transport.readAll( buf, 0, length);
 
         length = buf.length;
         var inp = new BytesInput( buf.getBytes());
-        var str = inp.readString( length);
-        if( utf8Strings)
-            return str;  // no need to decode on UTF8 targets, the string is just fine
-        else
-            return Utf8.decode( str);
+        var str = inp.readString( length, Encoding.UTF8);
+        return str;  
     }
 
     /**
@@ -617,12 +605,13 @@
      */
     public function readBinary() : Bytes {
         var length : Int = cast( ReadVarint32(), Int);
+		Transport.CheckReadBytesAvailable(length);
         if (length == 0) {
             return Bytes.alloc(0);
         }
 
         var buf = new BytesBuffer();
-        trans.readAll( buf, 0, length);
+        Transport.readAll( buf, 0, length);
         return buf.getBytes();
     }
 
@@ -715,4 +704,27 @@
     {
         return cast( ttypeToCompactType[ttype], Int);
     }
+	
+	// Return the minimum number of bytes a type will consume on the wire
+	public override function GetMinSerializedSize(type : TType) : Int
+	{
+		switch (type)
+		{
+			case TType.STOP:    return 0;
+			case TType.VOID:    return 0;
+			case TType.BOOL:   return 1;
+			case TType.DOUBLE: return 8;  // uses fixedLongToBytes() which always writes 8 bytes
+			case TType.BYTE: return 1;
+			case TType.I16:     return 1;  // zigzag
+			case TType.I32:     return 1;  // zigzag
+			case TType.I64:     return 1;  // zigzag
+			case TType.STRING: return 1;  // string length
+			case TType.STRUCT:  return 0;             // empty struct
+			case TType.MAP:     return 1;  // element count
+			case TType.SET:    return 1;  // element count
+			case TType.LIST:    return 1;  // element count
+			default: throw new TProtocolException(TProtocolException.NOT_IMPLEMENTED, "unrecognized type code");
+		}
+	}
+
 }
diff --git a/lib/haxe/src/org/apache/thrift/protocol/TJSONProtocol.hx b/lib/haxe/src/org/apache/thrift/protocol/TJSONProtocol.hx
index e20ff33..145eab9 100644
--- a/lib/haxe/src/org/apache/thrift/protocol/TJSONProtocol.hx
+++ b/lib/haxe/src/org/apache/thrift/protocol/TJSONProtocol.hx
@@ -23,8 +23,8 @@
 import haxe.io.BytesInput;
 import haxe.io.BytesOutput;
 import haxe.io.BytesBuffer;
+import haxe.io.Encoding;
 import haxe.ds.GenericStack;
-import haxe.Utf8;
 import haxe.crypto.Base64;
 import haxe.Int64;
 
@@ -45,9 +45,7 @@
 *
 *  Adapted from the Java version.
 */
-class TJSONProtocol extends TRecursionTracker implements TProtocol {
-
-    public var trans(default,null) : TTransport;
+class TJSONProtocol extends TProtocolImplBase implements TProtocol {
 
     // Stack of nested contexts that we may be in
     private var contextStack : GenericStack<JSONBaseContext> = new GenericStack<JSONBaseContext>();
@@ -58,22 +56,14 @@
     // Reader that manages a 1-byte buffer
     private var reader : LookaheadReader;
 
-    // whether the underlying system holds Strings as UTF-8
-    // http://old.haxe.org/manual/encoding
-    private static var utf8Strings = haxe.Utf8.validate("Ç-ß-Æ-Ю-Ш");
-
     // TJSONProtocol Constructor
-    public function new( trans : TTransport)
+    public function new( transport : TTransport)
     {
-        this.trans = trans;
+		super(transport);
         this.context = new JSONBaseContext(this);
         this.reader = new LookaheadReader(this);
     }
 
-    public function getTransport() : TTransport {
-      return trans;
-    }
-
     public function writeMessageBegin(message:TMessage) : Void {
         WriteJSONArrayStart();
         WriteJSONInteger( JSONConstants.VERSION);
@@ -230,7 +220,8 @@
         ReadJSONObjectStart();
 
         var map = new TMap( KeyType, ValueType, Count);
-        return map;
+		CheckReadBytesAvailableMap(map);
+		return map;
     }
 
     public function readMapEnd() : Void {
@@ -244,6 +235,7 @@
         var Count : Int = ReadJSONInteger();
 
         var list = new TList( ElementType, Count);
+		CheckReadBytesAvailableList(list);
         return list;
     }
 
@@ -257,6 +249,7 @@
         var Count : Int = ReadJSONInteger();
 
         var set = new TSet( ElementType, Count);
+		CheckReadBytesAvailableSet(set);
         return set;
     }
 
@@ -313,7 +306,7 @@
         context.Write();
 
         var tmp = BytesFromString( JSONConstants.QUOTE);
-        trans.write( tmp, 0, tmp.length);
+        Transport.write( tmp, 0, tmp.length);
 
         for (i in 0 ... b.length) {
             var value = b.get(i);
@@ -323,11 +316,11 @@
                 if (String.fromCharCode(value) == JSONConstants.BACKSLASH.charAt(0))
                 {
                     tmp = BytesFromString( JSONConstants.BACKSLASH + JSONConstants.BACKSLASH);
-                    trans.write( tmp, 0, tmp.length);
+                    Transport.write( tmp, 0, tmp.length);
                 }
                 else
                 {
-                    trans.write( b, i, 1);
+                    Transport.write( b, i, 1);
                 }
             }
             else
@@ -335,7 +328,7 @@
                 var num = JSONConstants.JSON_CHAR_TABLE[value];
                 if (num == 1)
                 {
-                    trans.write( b, i, 1);
+                    Transport.write( b, i, 1);
                 }
                 else if (num > 1)
                 {
@@ -343,7 +336,7 @@
                     buf.addString( JSONConstants.BACKSLASH);
                     buf.addByte( num);
                     tmp = buf.getBytes();
-                    trans.write( tmp, 0, tmp.length);
+                    Transport.write( tmp, 0, tmp.length);
                 }
                 else
                 {
@@ -354,13 +347,13 @@
                     buf.addString( HexChar( (value & 0x0000FF00) >> 4));
                     buf.addString( HexChar( value & 0x000000FF));
                     tmp = buf.getBytes();
-                    trans.write( tmp, 0, tmp.length);
+                    Transport.write( tmp, 0, tmp.length);
                 }
             }
         }
 
         tmp = BytesFromString( JSONConstants.QUOTE);
-        trans.write( tmp, 0, tmp.length);
+        Transport.write( tmp, 0, tmp.length);
     }
 
     // Write out number as a JSON value. If the context dictates so,
@@ -382,7 +375,7 @@
         }
 
         var tmp = BytesFromString( str);
-        trans.write( tmp, 0, tmp.length);
+        Transport.write( tmp, 0, tmp.length);
     }
 
     // Write out number as a JSON value. If the context dictates so,
@@ -404,7 +397,7 @@
         }
 
         var tmp = BytesFromString( str);
-        trans.write( tmp, 0, tmp.length);
+        Transport.write( tmp, 0, tmp.length);
     }
 
     // Write out a double as a JSON value. If it is NaN or infinity or if the
@@ -441,7 +434,7 @@
         }
 
         var tmp = BytesFromString( str);
-        trans.write( tmp, 0, tmp.length);
+        Transport.write( tmp, 0, tmp.length);
     }
 
     // Write out contents of byte array b as a JSON string with base-64 encoded data
@@ -454,33 +447,33 @@
         buf.addString( JSONConstants.QUOTE);
 
         var tmp = buf.getBytes();
-        trans.write( tmp, 0, tmp.length);
+        Transport.write( tmp, 0, tmp.length);
     }
 
     private function WriteJSONObjectStart() : Void {
         context.Write();
         var tmp = BytesFromString( JSONConstants.LBRACE);
-        trans.write( tmp, 0, tmp.length);
+        Transport.write( tmp, 0, tmp.length);
         PushContext( new JSONPairContext(this));
     }
 
     private function WriteJSONObjectEnd() : Void {
         PopContext();
         var tmp = BytesFromString( JSONConstants.RBRACE);
-        trans.write( tmp, 0, tmp.length);
+        Transport.write( tmp, 0, tmp.length);
     }
 
     private function WriteJSONArrayStart() : Void {
         context.Write();
         var tmp = BytesFromString( JSONConstants.LBRACKET);
-        trans.write( tmp, 0, tmp.length);
+        Transport.write( tmp, 0, tmp.length);
         PushContext( new JSONListContext(this));
     }
 
     private function WriteJSONArrayEnd() : Void {
         PopContext();
         var tmp = BytesFromString( JSONConstants.RBRACKET);
-        trans.write( tmp, 0, tmp.length);
+        Transport.write( tmp, 0, tmp.length);
     }
 
 
@@ -545,7 +538,7 @@
 
             // it's \uXXXX
             var hexbuf = new BytesBuffer();
-            var hexlen = trans.readAll( hexbuf, 0, 4);
+            var hexlen = Transport.readAll( hexbuf, 0, 4);
             if( hexlen != 4)
             {
                 throw new TProtocolException( TProtocolException.INVALID_DATA, "Not enough data for \\uNNNN sequence");
@@ -756,10 +749,7 @@
 
     public static function BytesFromString( str : String) : Bytes {
         var buf = new BytesBuffer();
-        if( utf8Strings)
-            buf.addString( str);  // no need to encode on UTF8 targets, the string is just fine
-        else
-            buf.addString( Utf8.encode( str));
+        buf.addString( str, Encoding.UTF8);
         return buf.getBytes();
     }
 
@@ -767,11 +757,7 @@
         var inp = new BytesInput( buf);
         if( buf.length == 0)
             return "";  // readString() would return null in that case, which is wrong
-        var str = inp.readString( buf.length);
-        if( utf8Strings)
-            return str;  // no need to decode on UTF8 targets, the string is just fine
-        else
-            return Utf8.decode( str);
+        return inp.readString( buf.length, Encoding.UTF8);
     }
 
     // Convert a byte containing a hex char ('0'-'9' or 'a'-'f') into its corresponding hex value
@@ -790,6 +776,28 @@
     }
 
 
+	// Return the minimum number of bytes a type will consume on the wire
+	public override function GetMinSerializedSize(type : TType) : Int
+	{
+		switch (type)
+		{
+			case TType.STOP: return 0;
+			case TType.VOID: return 0;
+			case TType.BOOL: return 1;  // written as int  
+			case TType.BYTE: return 1;
+			case TType.DOUBLE: return 1;
+			case TType.I16: return 1;
+			case TType.I32: return 1;
+			case TType.I64: return 1;
+			case TType.STRING: return 2;  // empty string
+			case TType.STRUCT: return 2;  // empty struct
+			case TType.MAP: return 2;  // empty map
+			case TType.SET: return 2;  // empty set
+			case TType.LIST: return 2;  // empty list
+			default: throw new TProtocolException(TProtocolException.NOT_IMPLEMENTED, "unrecognized type code");
+		}
+	}
+
 }
 
 
@@ -971,7 +979,7 @@
             var buf = new BytesBuffer();
             buf.addString( JSONConstants.COMMA);
             var tmp = buf.getBytes();
-            proto.trans.write( tmp, 0, tmp.length);
+            proto.Transport.write( tmp, 0, tmp.length);
         }
     }
 
@@ -1014,7 +1022,7 @@
             var buf = new BytesBuffer();
             buf.addString( colon ? JSONConstants.COLON : JSONConstants.COMMA);
             var tmp = buf.getBytes();
-            proto.trans.write( tmp, 0, tmp.length);
+            proto.Transport.write( tmp, 0, tmp.length);
             colon = !colon;
         }
     }
@@ -1064,7 +1072,7 @@
     public function Peek() : Bytes {
         if (data == null) {
             var buf = new BytesBuffer();
-            proto.trans.readAll(buf, 0, 1);
+            proto.Transport.readAll(buf, 0, 1);
             data = buf.getBytes();
         }
         return data;
diff --git a/lib/haxe/src/org/apache/thrift/protocol/TProtocol.hx b/lib/haxe/src/org/apache/thrift/protocol/TProtocol.hx
index b7f3842..316067a 100644
--- a/lib/haxe/src/org/apache/thrift/protocol/TProtocol.hx
+++ b/lib/haxe/src/org/apache/thrift/protocol/TProtocol.hx
@@ -82,4 +82,7 @@
     // recursion tracking
     function IncrementRecursionDepth() : Void;
     function DecrementRecursionDepth() : Void;
+	
+	// message size
+	function GetMinSerializedSize(type : TType) : Int;
 }
diff --git a/lib/haxe/src/org/apache/thrift/protocol/TProtocolDecorator.hx b/lib/haxe/src/org/apache/thrift/protocol/TProtocolDecorator.hx
index 769e93c..011f42b 100644
--- a/lib/haxe/src/org/apache/thrift/protocol/TProtocolDecorator.hx
+++ b/lib/haxe/src/org/apache/thrift/protocol/TProtocolDecorator.hx
@@ -223,4 +223,10 @@
     public function DecrementRecursionDepth() : Void {
         return wrapped.DecrementRecursionDepth();
     }
+	
+	// Returns the minimum amount of bytes needed to store the smallest possible instance of TType.
+	public function GetMinSerializedSize(type : TType) : Int
+	{
+		return wrapped.GetMinSerializedSize(type);
+	}
 }
diff --git a/lib/haxe/src/org/apache/thrift/protocol/TProtocolImplBase.hx b/lib/haxe/src/org/apache/thrift/protocol/TProtocolImplBase.hx
new file mode 100644
index 0000000..60e4a1f
--- /dev/null
+++ b/lib/haxe/src/org/apache/thrift/protocol/TProtocolImplBase.hx
@@ -0,0 +1,86 @@
+/*
+ * 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.
+ */
+
+package org.apache.thrift.protocol;
+
+import org.apache.thrift.*;
+import org.apache.thrift.transport.TTransport;
+
+
+class TProtocolImplBase {
+
+	private var Configuration : TConfiguration;
+    public var Transport(default,null) : TTransport;
+	
+	public function new( transport : TTransport)
+	{
+		Transport = transport;
+		Configuration = (transport.Configuration != null) ? transport.Configuration : new TConfiguration();
+	}
+
+	
+    public function getTransport() : TTransport {
+		return Transport;
+    }
+
+	
+    // limit and actual value
+    public var recursionLimit(get,never) : Int;
+    private var recursionDepth : Int = 0;
+
+    public function get_recursionLimit() : Int
+	{
+		return Configuration.RecursionLimit;
+	}
+	
+	
+    public function IncrementRecursionDepth() : Void
+    {
+        if (recursionDepth < recursionLimit)
+            ++recursionDepth;
+        else
+            throw new TProtocolException(TProtocolException.DEPTH_LIMIT, "Depth limit exceeded");
+    }
+
+    public function DecrementRecursionDepth() : Void
+    {
+        --recursionDepth;
+    }
+
+
+	private function CheckReadBytesAvailableSet(set : TSet) : Void
+	{
+		Transport.CheckReadBytesAvailable(set.size * GetMinSerializedSize(set.elemType));
+	}
+
+	private function CheckReadBytesAvailableList(list : TList) : Void
+	{
+		Transport.CheckReadBytesAvailable(list.size * GetMinSerializedSize(list.elemType));
+	}
+
+	private function CheckReadBytesAvailableMap (map : TMap) : Void
+	{
+		var elmSize = GetMinSerializedSize(map.keyType) + GetMinSerializedSize(map.valueType);
+		Transport.CheckReadBytesAvailable(map.size * elmSize);
+	}
+
+	// Returns the minimum amount of bytes needed to store the smallest possible instance of TType.
+	public function GetMinSerializedSize(type : TType) : Int throw "abstract method called";
+
+}
diff --git a/lib/haxe/src/org/apache/thrift/protocol/TRecursionTracker.hx b/lib/haxe/src/org/apache/thrift/protocol/TRecursionTracker.hx
deleted file mode 100644
index cf0211b..0000000
--- a/lib/haxe/src/org/apache/thrift/protocol/TRecursionTracker.hx
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * 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.
- */
-
-package org.apache.thrift.protocol;
-
-import org.apache.thrift.*;
-
-
-class TRecursionTracker {
-
-    // default
-    private static inline var DEFAULT_RECURSION_DEPTH : Int = 64;
-
-    // limit and actual value
-    public var recursionLimit : Int = DEFAULT_RECURSION_DEPTH;
-    private var recursionDepth : Int = 0;
-
-    public function IncrementRecursionDepth() : Void
-    {
-        if (recursionDepth < recursionLimit)
-            ++recursionDepth;
-        else
-            throw new TProtocolException(TProtocolException.DEPTH_LIMIT, "Depth limit exceeded");
-    }
-
-    public function DecrementRecursionDepth() : Void
-    {
-        --recursionDepth;
-    }
-
-
-}
diff --git a/lib/haxe/src/org/apache/thrift/transport/TBufferedTransport.hx b/lib/haxe/src/org/apache/thrift/transport/TBufferedTransport.hx
index 4b33fcf..72ce921 100644
--- a/lib/haxe/src/org/apache/thrift/transport/TBufferedTransport.hx
+++ b/lib/haxe/src/org/apache/thrift/transport/TBufferedTransport.hx
@@ -21,6 +21,7 @@
 
 import org.apache.thrift.transport.*;
 
+import haxe.Int64;
 import haxe.io.Eof;
 import haxe.io.Bytes;
 import haxe.io.BytesBuffer;
@@ -28,16 +29,13 @@
 import haxe.io.BytesInput;
 
 
-class TBufferedTransport extends TTransport
+class TBufferedTransport extends TLayeredTransport
 {
     // constants
     public static inline var DEFAULT_BUFSIZE : Int = 0x1000;    // 4096 Bytes
     public static inline var MIN_BUFSIZE : Int = 0x100;         // 256 Bytes
     public static inline var MAX_BUFSIZE : Int = 0x100000;      // 1 MB
 
-    // Underlying transport
-    public var transport(default,null) :  TTransport = null;
-
     // Buffer for input/output
     private var readBuffer_ : BytesInput = null;
     private var writeBuffer_ : BytesOutput = null;
@@ -45,6 +43,7 @@
 
     // Constructor wraps around another transport
     public function new( transport : TTransport, bufSize : Int = DEFAULT_BUFSIZE) {
+		super(transport);
 
         // ensure buffer size is in the range
         if ( bufSize < MIN_BUFSIZE)
@@ -52,22 +51,21 @@
         else if( bufSize > MAX_BUFSIZE)
             bufSize = MAX_BUFSIZE;
 
-        this.transport = transport;
         this.bufSize = bufSize;
         this.writeBuffer_ = new BytesOutput();
         this.writeBuffer_.bigEndian = true;
     }
 
     public override function open() : Void {
-        transport.open();
+        InnerTransport.open();
     }
 
     public override function isOpen() : Bool {
-        return transport.isOpen();
+        return InnerTransport.isOpen();
     }
 
     public override function close() : Void {
-        transport.close();
+        InnerTransport.close();
     }
 
     public override function read(buf : BytesBuffer, off : Int, len : Int) : Int {
@@ -86,7 +84,7 @@
                 // there is no point in buffering whenever the
                 // remaining length exceeds the buffer size
                 if ( len >= bufSize) {
-                    var got = transport.read( buf, off, len);
+                    var got = InnerTransport.read( buf, off, len);
                     if (got > 0) {
                         buf.addBytes(data, 0, got);
                         return got;
@@ -109,7 +107,7 @@
         var size = bufSize;
         try {
             var buffer = new BytesBuffer();
-            size = transport.read( buffer, 0, size);
+            size = InnerTransport.read( buffer, 0, size);
             readBuffer_ = new BytesInput( buffer.getBytes(), 0, size);
             readBuffer_.bigEndian = true;
             return size;
@@ -125,7 +123,7 @@
                 var buf = writeBuffer_.getBytes();
                 writeBuffer_ = new BytesOutput();
                 writeBuffer_.bigEndian = true;
-                transport.write(buf, 0, buf.length);
+                InnerTransport.write(buf, 0, buf.length);
             }
         }
     }
@@ -141,7 +139,7 @@
         var write_thru : Bool = exceeds_buf && (writeBuffer_.length >= halfSize);
         if ( write_thru) {
             writeChunk(true); // force send whatever we have in there
-            transport.write(buf, off, len);  // write thru
+            InnerTransport.write(buf, off, len);  // write thru
         } else {
             writeBuffer_.writeBytes(buf, off, len);
             writeChunk(false);
@@ -150,6 +148,18 @@
 
     public override function flush( callback : Dynamic->Void =null) : Void {
         writeChunk(true);
-        transport.flush(callback);
+        InnerTransport.flush(callback);
     }
+	
+	public override function CheckReadBytesAvailable(numBytes : Int64) : Void
+	{
+		var buffered = readBuffer_.length - readBuffer_.position;
+		if (buffered < numBytes)
+		{
+			numBytes -= buffered;
+			InnerTransport.CheckReadBytesAvailable(numBytes);
+		}
+	}
+	
+	
 }
diff --git a/lib/haxe/src/org/apache/thrift/transport/TBufferedTransportFactory.hx b/lib/haxe/src/org/apache/thrift/transport/TBufferedTransportFactory.hx
index 539e720..11d1a72 100644
--- a/lib/haxe/src/org/apache/thrift/transport/TBufferedTransportFactory.hx
+++ b/lib/haxe/src/org/apache/thrift/transport/TBufferedTransportFactory.hx
@@ -27,7 +27,7 @@
     private var bufSize : Int;
 
     public function new(bufSize : Int = TBufferedTransport.DEFAULT_BUFSIZE) {
-        super();
+		super();
         this.bufSize = bufSize;
     }
 
diff --git a/lib/haxe/src/org/apache/thrift/transport/TEndpointTransport.hx b/lib/haxe/src/org/apache/thrift/transport/TEndpointTransport.hx
new file mode 100644
index 0000000..8c0d3ef
--- /dev/null
+++ b/lib/haxe/src/org/apache/thrift/transport/TEndpointTransport.hx
@@ -0,0 +1,95 @@
+// 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.
+package org.apache.thrift.transport;
+
+import haxe.Int64;
+import org.apache.thrift.TConfiguration;
+
+class TEndpointTransport extends TTransport
+{
+	private var MaxMessageSize(get, never) : Int64;
+	private var KnownMessageSize(default, null) : Int64 ;
+	private var RemainingMessageSize(default, null) : Int64 ;
+
+	private var _configuration(default,null) : TConfiguration;
+	
+	public override function get_Configuration() : TConfiguration {
+		return _configuration;
+	}
+	
+	private function get_MaxMessageSize() : Int64 {
+		return Configuration.MaxMessageSize; 
+	}
+	
+	
+	// private CTOR to prevent direct instantiation
+	// in other words, this class MUST be extended
+	private function new( config : TConfiguration)
+	{
+		_configuration = (config != null) ? config : new TConfiguration();
+		ResetConsumedMessageSize();
+	}
+
+	// Resets RemainingMessageSize to the configured maximum 
+	private function ResetConsumedMessageSize(?newSize : Int64) : Void
+	{
+		// full reset 
+		if (newSize == null)
+		{
+			KnownMessageSize = MaxMessageSize;
+			RemainingMessageSize = MaxMessageSize;
+			return;
+		}
+
+		// update only: message size can shrink, but not grow
+		if (newSize > KnownMessageSize)
+			throw new TTransportException(TTransportException.END_OF_FILE, "ResetConsumedMessageSize: MaxMessageSize reached");
+
+		KnownMessageSize = newSize;
+		RemainingMessageSize = newSize;
+	}
+
+	// Updates RemainingMessageSize to reflect then known real message size (e.g. framed transport).
+	// Will throw if we already consumed too many bytes or if the new size is larger than allowed.
+	public override function UpdateKnownMessageSize(size : Int64) : Void
+	{
+		var consumed = KnownMessageSize - RemainingMessageSize;
+		ResetConsumedMessageSize(size);
+		CountConsumedMessageBytes(consumed);
+	}
+
+	// Throws if there are not enough bytes in the input stream to satisfy a read of numBytes bytes of data
+	public override function CheckReadBytesAvailable(numBytes : Int64) : Void
+	{
+		if (RemainingMessageSize < numBytes)
+			throw new TTransportException(TTransportException.END_OF_FILE, 'CheckReadBytesAvailable(${numBytes}): MaxMessageSize reached, only ${RemainingMessageSize} bytes available');
+	}
+
+	// Consumes numBytes from the RemainingMessageSize.
+	private function CountConsumedMessageBytes(numBytes : Int64) : Void
+	{
+		if (RemainingMessageSize >= numBytes)
+		{
+			RemainingMessageSize -= numBytes;
+		}
+		else
+		{
+			RemainingMessageSize = 0;
+			throw new TTransportException(TTransportException.END_OF_FILE, 'CountConsumedMessageBytes(${numBytes}): MaxMessageSize reached');
+		}
+	}
+}
diff --git a/lib/haxe/src/org/apache/thrift/transport/TFramedTransport.hx b/lib/haxe/src/org/apache/thrift/transport/TFramedTransport.hx
index cef82ef..37e4959 100644
--- a/lib/haxe/src/org/apache/thrift/transport/TFramedTransport.hx
+++ b/lib/haxe/src/org/apache/thrift/transport/TFramedTransport.hx
@@ -21,6 +21,7 @@
 
 import org.apache.thrift.transport.*;
 
+import haxe.Int64;
 import haxe.io.Eof;
 import haxe.io.Bytes;
 import haxe.io.BytesBuffer;
@@ -32,16 +33,9 @@
  * TFramedTransport is a buffered TTransport that ensures a fully read message
  * every time by preceding messages with a 4-byte frame size.
  */
-class TFramedTransport extends TTransport
+class TFramedTransport extends TLayeredTransport
 {
-    public static inline var DEFAULT_MAX_LENGTH = 16384000;
-
-    var maxLength_ :  Int;
-
-    /**
-     * Underlying transport
-     */
-    var transport_ :  TTransport = null;
+	private static inline var HEADER_SIZE = 4;
 
     /**
      * Buffer for output
@@ -56,21 +50,20 @@
     /**
      * Constructor wraps around another transport
      */
-    public function new( transport : TTransport, maxLength : Int = DEFAULT_MAX_LENGTH) {
-        transport_ = transport;
-        maxLength_ = maxLength;
+    public function new( transport : TTransport) {
+		super(transport);
     }
 
     public override function open() : Void {
-        transport_.open();
+        InnerTransport.open();
     }
 
     public override function isOpen() : Bool {
-        return transport_.isOpen();
+        return InnerTransport.isOpen();
     }
 
     public override function close() : Void {
-        transport_.close();
+        InnerTransport.close();
     }
 
     public override function read(buf : BytesBuffer, off : Int, len : Int) : Int {
@@ -101,13 +94,13 @@
     function readFrameSize() : Int {
         try {
             var buffer = new BytesBuffer();
-            var len = transport_.readAll( buffer, 0, 4);
-            var inp = new BytesInput( buffer.getBytes(), 0, 4);
+            var len = InnerTransport.readAll( buffer, 0, HEADER_SIZE);
+            var inp = new BytesInput( buffer.getBytes(), 0, HEADER_SIZE);
             inp.bigEndian = true;
             return inp.readInt32();
         }
         catch(eof : Eof) {
-            throw new TTransportException(TTransportException.END_OF_FILE, 'Can\'t read 4 bytes!');
+            throw new TTransportException(TTransportException.END_OF_FILE, 'Can\'t read ${HEADER_SIZE} bytes!');
         }
     }
 
@@ -118,13 +111,14 @@
         if (size < 0) {
             throw new TTransportException(TTransportException.UNKNOWN, 'Read a negative frame size ($size)!');
         };
-        if (size > maxLength_) {
-            throw new TTransportException(TTransportException.UNKNOWN, 'Frame size ($size) larger than max length ($maxLength_)!');
+        if (size > Configuration.MaxFrameSize) {
+            throw new TTransportException(TTransportException.UNKNOWN, 'Frame size ($size) larger than max length ($Configuration.MaxFrameSize)!');
         };
 
+		UpdateKnownMessageSize(size + HEADER_SIZE);
         try {
             var buffer = new BytesBuffer();
-            size = transport_.readAll( buffer, 0, size);
+            size = InnerTransport.readAll( buffer, 0, size);
             readBuffer_ = new BytesInput( buffer.getBytes(), 0, size);
             readBuffer_.bigEndian = true;
         }
@@ -141,18 +135,31 @@
         var out = new BytesOutput();
         out.bigEndian = true;
         out.writeInt32(len);
-        transport_.write(out.getBytes(), 0, 4);
+        InnerTransport.write(out.getBytes(), 0, HEADER_SIZE);
     }
 
     public override function flush( callback : Dynamic->Void =null) : Void {
         var buf : Bytes = writeBuffer_.getBytes();
         var len : Int = buf.length;
         writeBuffer_ = new BytesOutput();
+		readBuffer_ = null;
 
         writeFrameSize(len);
-        transport_.write(buf, 0, len);
-        transport_.flush(callback);
+        InnerTransport.write(buf, 0, len);
+        InnerTransport.flush(callback);
     }
+	
+	
+	public override function CheckReadBytesAvailable(numBytes : Int64) : Void
+	{
+		var buffered = readBuffer_.length - readBuffer_.position;
+		if (buffered < numBytes)
+		{
+			numBytes -= buffered;
+			InnerTransport.CheckReadBytesAvailable(numBytes);
+		}
+	}
+	
 }
 
 
diff --git a/lib/haxe/src/org/apache/thrift/transport/TFramedTransportFactory.hx b/lib/haxe/src/org/apache/thrift/transport/TFramedTransportFactory.hx
index 8d45a64..ca04e7f 100644
--- a/lib/haxe/src/org/apache/thrift/transport/TFramedTransportFactory.hx
+++ b/lib/haxe/src/org/apache/thrift/transport/TFramedTransportFactory.hx
@@ -19,19 +19,17 @@
 
 package org.apache.thrift.transport;
 
+import org.apache.thrift.TConfiguration;
 import org.apache.thrift.transport.*;
 
 
 class TFramedTransportFactory extends TTransportFactory {
 
-    var maxLength_ : Int;
-
-    public function new(maxLength : Int = TFramedTransport.DEFAULT_MAX_LENGTH) {
-        super();
-        maxLength_ = maxLength;
+    public function new() {
+		super();
     }
 
     public override function getTransport(base : TTransport) : TTransport {
-        return new TFramedTransport(base, maxLength_);
+        return new TFramedTransport(base);
     }
 }
diff --git a/lib/haxe/src/org/apache/thrift/transport/TFullDuplexHttpClient.hx b/lib/haxe/src/org/apache/thrift/transport/TFullDuplexHttpClient.hx
index 1972853..cc34ec4 100644
--- a/lib/haxe/src/org/apache/thrift/transport/TFullDuplexHttpClient.hx
+++ b/lib/haxe/src/org/apache/thrift/transport/TFullDuplexHttpClient.hx
@@ -41,213 +41,217 @@
      * Unlike Http Client, it uses a single POST, and chunk-encoding to transfer all messages.
      */
 
-    public class TFullDuplexHttpClient extends TTransport
-    {
-        private var socket : Socket = null;
-        private var host  :  String;
-        private var port  :  Int;
-        private var resource  :  String;
-        private var stripped  :  Bool = false;
-        private var obuffer : Bytes = new Bytes();
-        private var input : IDataInput;
-        private var output : IDataOutput;
-        private var bytesInChunk  :  Int = 0;
-        private var CRLF : Bytes = new Bytes();
-        private var ioCallback : TException->Void = null;
-        private var eventDispatcher : EventDispatcher = new EventDispatcher();
+public class TFullDuplexHttpClient extends TEndpointTransport
+{
+	private var socket : Socket = null;
+	private var host  :  String;
+	private var port  :  Int;
+	private var resource  :  String;
+	private var stripped  :  Bool = false;
+	private var obuffer : Bytes = new Bytes();
+	private var input : IDataInput;
+	private var output : IDataOutput;
+	private var bytesInChunk  :  Int = 0;
+	private var CRLF : Bytes = new Bytes();
+	private var ioCallback : TException->Void = null;
+	private var eventDispatcher : EventDispatcher = new EventDispatcher();
 
-        public function new(host  :  String, port  :  Int, resource  :  String)  :  Void
-        {
-            CRLF.writeByte(13);
-            CRLF.writeByte(10);
-            this.host = host;
-            this.port = port;
-            this.resource = resource;
-        }
+	public function new(host  :  String, port  :  Int, resource  :  String, config : TConfiguration = null)  :  Void
+	{
+		super(config);		
+		CRLF.writeByte(13);
+		CRLF.writeByte(10);
+		this.host = host;
+		this.port = port;
+		this.resource = resource;
+	}
 
-        public override function close()  :  Void
-        {
-            this.input = null;
-            this.output = null;
-            this.stripped = false;
-            socket.close()
-        }
+	public override function close()  :  Void
+	{
+		this.input = null;
+		this.output = null;
+		this.stripped = false;
+		socket.close();
+		ResetConsumedMessageSize();
+	}
 
-        public override function peek()  :  Bool
-        {
-            if(socket.connected)
-            {
-                trace("Bytes remained:" + socket.bytesAvailable);
-                return socket.bytesAvailable>0;
-            }
-            return false;
-        }
+	public override function peek()  :  Bool
+	{
+		if(socket.connected)
+		{
+			trace("Bytes remaining:" + socket.bytesAvailable);
+			return socket.bytesAvailable>0;
+		}
+		return false;
+	}
 
-        public override function read(buf : Bytes, off  :  Int, len  :  Int)  :  Int
-        {
-            var n1  :  Int = 0, n2  :  Int = 0, n3  :  Int = 0, n4  :  Int = 0, cidx  :  Int = 2;
-            var chunkSize : Bytes = new Bytes();
+	public override function read(buf : Bytes, off  :  Int, len  :  Int)  :  Int
+	{
+		var n1  :  Int = 0, n2  :  Int = 0, n3  :  Int = 0, n4  :  Int = 0, cidx  :  Int = 2;
+		var chunkSize : Bytes = new Bytes();
 
-            try
-            {
-                while (!stripped)
-                {
-                    n1 = n2;
-                    n2 = n3;
-                    n3 = n4;
-                    n4 = input.readByte();
-                    if ((n1 == 13) && (n2 == 10) && (n3 == 13) && (n4 == 10))
-                    {
-                        stripped = true;
-                    }
-                }
+		try
+		{
+			while (!stripped)
+			{
+				n1 = n2;
+				n2 = n3;
+				n3 = n4;
+				n4 = input.readByte();
+				if ((n1 == 13) && (n2 == 10) && (n3 == 13) && (n4 == 10))
+				{
+					stripped = true;
+				}
+			}
 
-                // read chunk size
-                if (bytesInChunk == 0)
-                {
-                    n1 = input.readByte();
-                    n2 = input.readByte();
+			// read chunk size
+			if (bytesInChunk == 0)
+			{
+				n1 = input.readByte();
+				n2 = input.readByte();
 
-                    chunkSize.writeByte(n1);
-                    chunkSize.writeByte(n2);
+				chunkSize.writeByte(n1);
+				chunkSize.writeByte(n2);
 
-                    while (!((n1 == 13) && (n2 == 10)))
-                    {
-                        n1 = n2;
-                        n2 = input.readByte();
-                        chunkSize.writeByte(n2);
-                    }
+				while (!((n1 == 13) && (n2 == 10)))
+				{
+					n1 = n2;
+					n2 = input.readByte();
+					chunkSize.writeByte(n2);
+				}
 
-                    bytesInChunk = parseInt(chunkSize.toString(), 16);
-                }
+				bytesInChunk = parseInt(chunkSize.toString(), 16);
+			}
 
-                input.readBytes(buf, off, len);
-                debugBuffer(buf);
-                bytesInChunk -= len;
+			input.readBytes(buf, off, len);
+			debugBuffer(buf);
+			bytesInChunk -= len;
 
-                if (bytesInChunk == 0)
-                {
-                    // advance the  :  "\r\n"
-                    input.readUTFBytes(2);
-                }
-                return len;
-            }
-            catch (e : EOFError)
-            {
-                trace(e);
-                throw new TTransportException(TTransportException.UNKNOWN, "No more data available.");
-            }
-            catch (e : TException)
-            {
-                trace('TException $e');
-                throw e;
-            }
-            catch (e : Error)
-            {
-                trace(e);
-                throw new TTransportException(TTransportException.UNKNOWN, 'Bad IO error: $e');
-            }
-            catch (e : Dynamic)
-            {
-                trace(e);
-                throw new TTransportException(TTransportException.UNKNOWN, 'Bad IO error: $e');
-            }
-            return 0;
-        }
+			if (bytesInChunk == 0)
+			{
+				// advance the  :  "\r\n"
+				input.readUTFBytes(2);
+			}
+			
+			CountConsumedMessageBytes(len);
+			return len;
+		}
+		catch (e : EOFError)
+		{
+			trace(e);
+			throw new TTransportException(TTransportException.UNKNOWN, "No more data available.");
+		}
+		catch (e : TException)
+		{
+			trace('TException $e');
+			throw e;
+		}
+		catch (e : Error)
+		{
+			trace(e);
+			throw new TTransportException(TTransportException.UNKNOWN, 'Bad IO error: $e');
+		}
+		catch (e : Dynamic)
+		{
+			trace(e);
+			throw new TTransportException(TTransportException.UNKNOWN, 'Bad IO error: $e');
+		}
+		return 0;
+	}
 
-        public function debugBuffer(buf : Bytes)  :  Void
-        {
-            var debug  :  String = "BUFFER >>";
-            var i  :  Int;
-            for (i = 0; i < buf.length; i++)
-            {
-                debug += buf[i] as int;
-                debug += " ";
-            }
+	public function debugBuffer(buf : Bytes)  :  Void
+	{
+		var debug  :  String = "BUFFER >>";
+		var i  :  Int;
+		for (i = 0; i < buf.length; i++)
+		{
+			debug += buf[i] as int;
+			debug += " ";
+		}
 
-            trace(debug + "<<");
-        }
+		trace(debug + "<<");
+	}
 
-        public override function write(buf : Bytes, off  :  Int, len  :  Int)  :  Void
-        {
-            obuffer.writeBytes(buf, off, len);
-        }
+	public override function write(buf : Bytes, off  :  Int, len  :  Int)  :  Void
+	{
+		obuffer.writeBytes(buf, off, len);
+	}
 
-        public function addEventListener(type  :  String, listener : Function, useCapture  :  Bool = false, priority  :  Int = 0, useWeakReference  :  Bool = false)  :  Void
-        {
-            this.eventDispatcher.addEventListener(type, listener, useCapture, priority, useWeakReference);
-        }
+	public function addEventListener(type  :  String, listener : Function, useCapture  :  Bool = false, priority  :  Int = 0, useWeakReference  :  Bool = false)  :  Void
+	{
+		this.eventDispatcher.addEventListener(type, listener, useCapture, priority, useWeakReference);
+	}
 
-        public override function open()  :  Void
-        {
-            this.socket = new Socket();
-            this.socket.addEventListener(Event.CONNECT, socketConnected);
-            this.socket.addEventListener(IOErrorEvent.IO_ERROR, socketError);
-            this.socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, socketSecurityError);
-            this.socket.addEventListener(ProgressEvent.SOCKET_DATA, socketDataHandler);
-            this.socket.connect(host, port);
-        }
+	public override function open()  :  Void
+	{
+		this.socket = new Socket();
+		this.socket.addEventListener(Event.CONNECT, socketConnected);
+		this.socket.addEventListener(IOErrorEvent.IO_ERROR, socketError);
+		this.socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, socketSecurityError);
+		this.socket.addEventListener(ProgressEvent.SOCKET_DATA, socketDataHandler);
+		this.socket.connect(host, port);
+		ResetConsumedMessageSize();
+	}
 
-        public function socketConnected(event : Event)  :  Void
-        {
-            this.output = this.socket;
-            this.input = this.socket;
-            this.output.writeUTF( "CONNECT " + resource + " HTTP/1.1\n"
-                                + "Host :  " + host + ":" + port + "\r\n"
-                                + "User-Agent :  Thrift/Haxe\r\n"
-                                + "Transfer-Encoding :  chunked\r\n"
-                                + "content-type :  application/x-thrift\r\n"
-                                + "Accept :  */*\r\n"
-                                + "\r\n");
-            this.eventDispatcher.dispatchEvent(event);
-        }
+	public function socketConnected(event : Event)  :  Void
+	{
+		this.output = this.socket;
+		this.input = this.socket;
+		this.output.writeUTF( "CONNECT " + resource + " HTTP/1.1\n"
+							+ "Host :  " + host + ":" + port + "\r\n"
+							+ "User-Agent :  Thrift/Haxe\r\n"
+							+ "Transfer-Encoding :  chunked\r\n"
+							+ "Content-Type :  application/x-thrift\r\n"
+							+ "Accept :  */*\r\n"
+							+ "\r\n");
+		this.eventDispatcher.dispatchEvent(event);
+	}
 
-        public function socketError(event : IOErrorEvent)  :  Void
-        {
-            trace("Error Connecting:" + event);
-            this.close();
-            if (ioCallback == null)
-            {
-                return;
-            }
-            ioCallback(new TTransportException(TTransportException.UNKNOWN, "IOError :  " + event.text));
-            this.eventDispatcher.dispatchEvent(event);
-        }
+	public function socketError(event : IOErrorEvent)  :  Void
+	{
+		trace("Error Connecting:" + event);
+		this.close();
+		if (ioCallback == null)
+		{
+			return;
+		}
+		ioCallback(new TTransportException(TTransportException.UNKNOWN, "IOError :  " + event.text));
+		this.eventDispatcher.dispatchEvent(event);
+	}
 
-        public function socketSecurityError(event : SecurityErrorEvent)  :  Void
-        {
-            trace("Security Error Connecting:" + event);
-            this.close();
-            this.eventDispatcher.dispatchEvent(event);
-        }
+	public function socketSecurityError(event : SecurityErrorEvent)  :  Void
+	{
+		trace("Security Error Connecting:" + event);
+		this.close();
+		this.eventDispatcher.dispatchEvent(event);
+	}
 
-        public function socketDataHandler(event : ProgressEvent)  :  Void
-        {
-            trace("Got Data call:" +ioCallback);
-            if (ioCallback != null)
-            {
-                ioCallback(null);
-            };
-            this.eventDispatcher.dispatchEvent(event);
-        }
+	public function socketDataHandler(event : ProgressEvent)  :  Void
+	{
+		trace("Got Data call:" +ioCallback);
+		if (ioCallback != null)
+		{
+			ioCallback(null);
+		};
+		this.eventDispatcher.dispatchEvent(event);
+	}
 
-        public override function flush(callback : Error->Void = null)  :  Void
-        {
-            trace("set callback:" + callback);
-            this.ioCallback = callback;
-            this.output.writeUTF(this.obuffer.length.toString(16));
-            this.output.writeBytes(CRLF);
-            this.output.writeBytes(this.obuffer);
-            this.output.writeBytes(CRLF);
-            this.socket.flush();
-            // waiting for  new Flex sdk 3.5
-            //this.obuffer.clear();
-            this.obuffer = new Bytes();
-        }
+	public override function flush(callback : Error->Void = null)  :  Void
+	{
+		trace("set callback:" + callback);
+		this.ioCallback = callback;
+		this.output.writeUTF(this.obuffer.length.toString(16));
+		this.output.writeBytes(CRLF);
+		this.output.writeBytes(this.obuffer);
+		this.output.writeBytes(CRLF);
+		this.socket.flush();
+		this.obuffer = new Bytes();
+		ResetConsumedMessageSize();
+	}
 
-        public override function isOpen()  :  Bool
-        {
-            return (this.socket == null ? false  :  this.socket.connected);
-        }
+	public override function isOpen()  :  Bool
+	{
+		return (this.socket != null) && this.socket.connected;
+	}
 
 }
\ No newline at end of file
diff --git a/lib/haxe/src/org/apache/thrift/transport/THttpClient.hx b/lib/haxe/src/org/apache/thrift/transport/THttpClient.hx
index 79f8661..703dd81 100644
--- a/lib/haxe/src/org/apache/thrift/transport/THttpClient.hx
+++ b/lib/haxe/src/org/apache/thrift/transport/THttpClient.hx
@@ -20,6 +20,7 @@
 package org.apache.thrift.transport;
 
 
+import haxe.Timer;
 import haxe.io.Bytes;
 import haxe.io.BytesBuffer;
 import haxe.io.BytesOutput;
@@ -27,6 +28,9 @@
 
 import haxe.Http;
 
+#if js
+import js.lib.Promise;
+#end
 
 
 /**
@@ -34,7 +38,7 @@
 * Thrift web services implementation.
 */
 
-class THttpClient extends TTransport {
+class THttpClient extends TEndpointTransport {
 
     private var requestBuffer_  : BytesOutput = new BytesOutput();
     private var responseBuffer_ : BytesInput = null;
@@ -42,20 +46,23 @@
     private var request_        : Http = null;
 
 
-    public function new( requestUrl : String) : Void {
-          request_ = new Http(requestUrl);
-        request_.addHeader( "contentType", "application/x-thrift");
+    public function new( requestUrl : String, config : TConfiguration = null) : Void {
+		super(config);
+		
+		request_ = new Http(requestUrl);
+        request_.addHeader( "Content-Type", "application/x-thrift");
     }
 
 
     public override function open() : Void {
+		ResetConsumedMessageSize();
     }
 
     public override function close() : Void {
     }
 
     public override function isOpen() : Bool {
-      return true;
+		return true;
     }
 
     public override function read(buf:BytesBuffer, off : Int, len : Int) : Int {
@@ -66,6 +73,7 @@
         var data =Bytes.alloc(len);
         len = responseBuffer_.readBytes(data, off, len);
         buf.addBytes(data,0,len);
+        CountConsumedMessageBytes(len);
         return len;
     }
 
@@ -78,24 +86,36 @@
         var buffer = requestBuffer_;
         requestBuffer_ = new BytesOutput();
         responseBuffer_ = null;
+		ResetConsumedMessageSize();
 
+		/*
         request_.onData = function(data : String) {
-            var tmp = new BytesBuffer();
-            tmp.addString(data);
-            responseBuffer_ = new BytesInput(tmp.getBytes());
-            if( callback != null) {
-                callback(null);
-            }
+			var tmp = new BytesBuffer();
+			tmp.addString(data);
+			responseBuffer_ = new BytesInput(tmp.getBytes());
+			if( callback != null) {
+				callback(null);
         };
+		*/
 
-        request_.onError = function(msg : String) {
-            if( callback != null) {
-                callback(new TTransportException(TTransportException.UNKNOWN, "IOError: " + msg));
-            }
-        };
+		request_.onBytes = function(data : Bytes) {
+			responseBuffer_ = new BytesInput(data);
+			if( callback != null) {
+				callback(null);
+			}
+		};
 
-        request_.setPostData(buffer.getBytes().toString());
-        request_.request(true/*POST*/);
+		request_.onError = function(msg : String) {
+			if( callback != null) {
+				callback(new TTransportException(TTransportException.UNKNOWN, "IOError: " + msg));
+			}
+		};
+		
+		
+		// the request
+		request_.setPostBytes(buffer.getBytes());
+		request_.request(true/*POST*/);
+		
     }
 
 }
diff --git a/lib/haxe/src/org/apache/thrift/transport/TLayeredTransport.hx b/lib/haxe/src/org/apache/thrift/transport/TLayeredTransport.hx
new file mode 100644
index 0000000..161d91e
--- /dev/null
+++ b/lib/haxe/src/org/apache/thrift/transport/TLayeredTransport.hx
@@ -0,0 +1,50 @@
+// 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.
+
+package org.apache.thrift.transport;
+
+import haxe.Int64;
+import org.apache.thrift.TConfiguration;
+
+class TLayeredTransport extends TTransport
+{
+	private var InnerTransport : TTransport;
+
+	public override function get_Configuration() : TConfiguration {
+		return InnerTransport.Configuration;
+	}
+
+	// private CTOR to prevent direct instantiation
+	// in other words, this class MUST be extended
+	private function new(transport : TTransport)
+	{
+		if( transport != null)
+			InnerTransport = transport;
+		else
+			throw new TTransportException( TTransportException.UNKNOWN, "Inner transport must not be null");
+	}
+
+	public override function UpdateKnownMessageSize(size : Int64) : Void
+	{
+		InnerTransport.UpdateKnownMessageSize(size);
+	}
+
+	public override function CheckReadBytesAvailable(numBytes : Int64) : Void
+	{
+		InnerTransport.CheckReadBytesAvailable(numBytes);
+	}
+}
diff --git a/lib/haxe/src/org/apache/thrift/transport/TServerSocket.hx b/lib/haxe/src/org/apache/thrift/transport/TServerSocket.hx
index 4badb2a..e1ef5a1 100644
--- a/lib/haxe/src/org/apache/thrift/transport/TServerSocket.hx
+++ b/lib/haxe/src/org/apache/thrift/transport/TServerSocket.hx
@@ -19,7 +19,10 @@
 
 package org.apache.thrift.transport;
 
-import haxe.remoting.SocketProtocol;
+#if (cs || neko || cpp || java || macro || lua || php || python || hl)
+import sys.net.Socket;
+#end
+
 import haxe.io.Bytes;
 import haxe.io.BytesBuffer;
 import haxe.io.BytesInput;
@@ -27,9 +30,9 @@
 import haxe.io.Input;
 import haxe.io.Output;
 import haxe.io.Eof;
+import org.apache.thrift.TConfiguration;
 
-//import flash.net.ServerSocket; - not yet available on Haxe 3.1.3
-#if ! (flash || html5)
+#if ! (flash || html5 || js)
 
 import sys.net.Host;
 
@@ -46,8 +49,10 @@
     private var _useBufferedSockets : Bool = false;
 
 
-    public function new(?address : String = 'localhost',  port : Int, clientTimeout : Float = 5, useBufferedSockets : Bool = false)
+    public function new(?address : String = 'localhost',  port : Int, clientTimeout : Float = 5, useBufferedSockets : Bool = false, config : TConfiguration = null)
     {
+		super(config);
+
         _clientTimeout = clientTimeout;
         _useBufferedSockets = useBufferedSockets;
 
diff --git a/lib/haxe/src/org/apache/thrift/transport/TServerTransport.hx b/lib/haxe/src/org/apache/thrift/transport/TServerTransport.hx
index 2189981..16fa564 100644
--- a/lib/haxe/src/org/apache/thrift/transport/TServerTransport.hx
+++ b/lib/haxe/src/org/apache/thrift/transport/TServerTransport.hx
@@ -21,6 +21,15 @@
 
 class TServerTransport {
 
+	private var Configuration(default,null) : TConfiguration;
+
+	// private CTOR to prevent direct instantiation
+	// in other words, this class MUST be extended
+	private function new( config : TConfiguration)
+	{
+		Configuration = (config != null) ? config : new TConfiguration();
+	}
+
     public function Accept() : TTransport {
         var transport = AcceptImpl();
         if (transport == null) {
diff --git a/lib/haxe/src/org/apache/thrift/transport/TSocket.hx b/lib/haxe/src/org/apache/thrift/transport/TSocket.hx
index 7941ab9..a743543 100644
--- a/lib/haxe/src/org/apache/thrift/transport/TSocket.hx
+++ b/lib/haxe/src/org/apache/thrift/transport/TSocket.hx
@@ -19,12 +19,12 @@
 
 package org.apache.thrift.transport;
 
-#if flash
+#if (cs || neko || cpp || java || macro || lua || php || python || hl)
+import sys.net.Socket;
+#elseif flash
 import flash.net.Socket;
 #elseif js
 import js.html.WebSocket;
-#else
-import haxe.remoting.SocketProtocol;
 #end
 
 import haxe.io.Bytes;
@@ -34,6 +34,7 @@
 import haxe.io.Input;
 import haxe.io.Output;
 import haxe.io.Eof;
+import org.apache.thrift.TConfiguration;
 
 
 #if ! (flash || js)
@@ -46,7 +47,7 @@
    * Thrift Socket Server based implementations.
    */
 
-class TSocket extends TTransport  {
+class TSocket extends TEndpointTransport  {
 
     #if (flash || js)
     private var host  :  String;
@@ -79,7 +80,9 @@
     private var ioCallback : TException->Void = null;
     private var readCount : Int = 0;
 
-    public function new(host : String, port  :  Int)  :  Void  {
+    public function new(host : String, port :  Int, config : TConfiguration = null)  :  Void  {
+		super(config);
+
         #if (flash || js)
         this.host = host;
         #else
@@ -132,6 +135,7 @@
                 buf.addByte( input.readByte());
                 --remaining;
             }
+            CountConsumedMessageBytes(len);
             return len;
 
             #elseif js
@@ -144,6 +148,7 @@
                 buf.addByte( input.get(off+nr));
                 ++nr;
             }
+			CountConsumedMessageBytes(len);
             return len;
 
             #else
@@ -158,6 +163,7 @@
             var got = input.readBytes(data, 0, len);
             buf.addBytes( data, 0, got);
             readCount += got;
+			CountConsumedMessageBytes(got);
             return got;
 
             #end
@@ -223,6 +229,7 @@
         #end
 
         obuffer = new BytesOutput();
+		ResetConsumedMessageSize();
 
 
         ioCallback = callback;
@@ -262,7 +269,7 @@
     public override function open()  :  Void
     {
         #if js
-        var socket = new WebSocket();
+        var socket = new WebSocket(host);
         socket.onmessage = function( event : js.html.MessageEvent) {
             this.input = event.data;
         }
@@ -287,6 +294,7 @@
         #end
 
         assignSocket( socket);
+		ResetConsumedMessageSize();
     }
 
     #if js
@@ -308,11 +316,26 @@
         #end
     }
 
-    public function setTimeout( timeout : Float ) : Void {
+	#if (flash)
+	
+    public function setTimeout( timeout : UInt) : Void {
         if(isOpen()) {
-            socket.setTimeout(timeout);
+            socket.timeout = timeout;
         }
         this.timeout = timeout;
     }
 
+	#else
+	
+    public function setTimeout( timeout : Float ) : Void {
+        if(isOpen()) {
+			#if ! (js)
+			socket.setTimeout(timeout);
+			#end
+        }
+        this.timeout = timeout;
+    }
+
+	#end
+
 }
diff --git a/lib/haxe/src/org/apache/thrift/transport/TStreamTransport.hx b/lib/haxe/src/org/apache/thrift/transport/TStreamTransport.hx
index 31a7c14..59bef15 100644
--- a/lib/haxe/src/org/apache/thrift/transport/TStreamTransport.hx
+++ b/lib/haxe/src/org/apache/thrift/transport/TStreamTransport.hx
@@ -19,6 +19,7 @@
 
 package org.apache.thrift.transport;
 
+import org.apache.thrift.TConfiguration;
 import org.apache.thrift.transport.*;
 import org.apache.thrift.helper.*;
 
@@ -28,13 +29,15 @@
 import haxe.io.BytesInput;
 
 
-class TStreamTransport extends TTransport {
+class TStreamTransport extends TEndpointTransport {
 
     public var InputStream(default,null) : TStream;
     public var OutputStream(default,null) : TStream;
 
 
-    public function new( input : TStream, output : TStream) {
+    public function new( input : TStream, output : TStream, config : TConfiguration) {
+		super(config);
+
         this.InputStream = input;
         this.OutputStream = output;
     }
@@ -48,7 +51,7 @@
     }
 
     public override function open() : Void {
-    }
+	}
 
     public override function close() : Void {
         if (InputStream != null)
diff --git a/lib/haxe/src/org/apache/thrift/transport/TTransport.hx b/lib/haxe/src/org/apache/thrift/transport/TTransport.hx
index e6b3179..8d2b5b8 100644
--- a/lib/haxe/src/org/apache/thrift/transport/TTransport.hx
+++ b/lib/haxe/src/org/apache/thrift/transport/TTransport.hx
@@ -19,12 +19,18 @@
 
 package org.apache.thrift.transport;
 
+import haxe.Int64;
 import haxe.io.Eof;
 import haxe.io.Bytes;
 import haxe.io.BytesBuffer;
 import org.apache.thrift.AbstractMethodError;
 
 class TTransport {
+	
+	public var Configuration(get, never) : TConfiguration;
+	public function get_Configuration() : TConfiguration throw "abstract method called";
+	public function UpdateKnownMessageSize(size : Int64) : Void throw "abstract method called";
+	public function CheckReadBytesAvailable(numBytes : Int64) : Void  throw "abstract method called";
 
     /**
      * Queries whether the transport is open.
diff --git a/lib/haxe/src/org/apache/thrift/transport/TWrappingServerTransport.hx b/lib/haxe/src/org/apache/thrift/transport/TWrappingServerTransport.hx
index b2272f3..6da6e01 100644
--- a/lib/haxe/src/org/apache/thrift/transport/TWrappingServerTransport.hx
+++ b/lib/haxe/src/org/apache/thrift/transport/TWrappingServerTransport.hx
@@ -25,23 +25,25 @@
 */
 class TWrappingServerTransport extends TServerTransport {
 
-  private var transport(default,null) : TTransport;
+	private var transport(default,null) : TTransport;
 
-  public function new(transport : TTransport) {
-    this.transport = transport;
-  }
+	public function new(transport : TTransport) {
+		super(transport.Configuration);
 
-  public override function Listen() : Void
-  {
-  }
+		this.transport = transport;
+	}
 
-  private override function AcceptImpl() : TTransport
-  {
-    return transport;
-  }
+	public override function Listen() : Void
+	{
+	}
 
-  public override function Close() : Void
-  {
+	private override function AcceptImpl() : TTransport
+	{
+		return transport;
+	}
 
-  }
+	public override function Close() : Void
+	{
+
+	}
 }