first commit
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..5717c99
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,18 @@
+_*
+.eunit
+*.o
+*.beam
+*.plt
+*.swp
+*.swo
+.erlang.cookie
+ebin
+log
+erl_crash.dump
+.rebar
+logs
+_build
+.idea
+.rebar
+target
+*.iml
diff --git a/Developer.md b/Developer.md
new file mode 100644
index 0000000..7fb83d3
--- /dev/null
+++ b/Developer.md
@@ -0,0 +1,45 @@
+## 开发
+
+```
+    ./rebar3 eunit -m dubbo_zookeeper_tests
+
+    dubbo_zookeeper:register_consumer(<<"com.ifcoder.demo.facade.User">>,[]).
+    
+    iProcessData:call_object().
+    
+    
+    scherdule:call_object().
+
+
+    ./rebar3 shell --apps "testdubboerl"
+    dubboerl:init().
+    
+```
+### eunit Test
+	./rebar3 eunit -m dubbo_zookeeper_tests
+	./rebar3 eunit -m de_codec_tests
+
+## 服务注册流程
+
+### 消费者注册
+
+
+
+### 生产者注册
+
+
+
+### 消费者调用
+
+```
+    Option=[
+        sync,
+        {timeout,5000}
+        {attachments,[{<<"a">>,<<"b">>}]}
+    ]
+```
+
+
+
+
+## Develop Log
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..63002bc
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2018 Dlive
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..6099b6b
--- /dev/null
+++ b/README.md
@@ -0,0 +1,67 @@
+dubboerl
+=====
+A Erlang framework for dubbo.
+
+Feature
+-----
+
+* 支持Zookeeper注册中心
+* 支持Hession serialize
+* 支持Consumer
+* 支持Provider
+* sync invoker
+* async invoker
+
+Start
+-----
+
+参考demo [dubboerl_demo](https://github.com/DLive/dubboerl_demo)
+
+#### Step1
+Transfer java facede t
+o erlang lib and add to you project dir.
+
+#### Step2
+
+configure dubbo refernce
+
+```
+{dubboerl,[
+	{zookeeper_list,[{"127.0.0.1",2181}]},
+	{application,<<"testdubboerl">>},
+	{consumer,[
+		{<<"me.dlive.dubboservice.service.IProcessData">>,[]}
+	]},
+	{provider,[
+		{scherdule_impl,scherdule_behaviour,<<"me.dlive.dubboservice.service.Scherdule">>,[]}
+	]}
+	
+]}
+``` 
+#### Step4
+Init dubboerl application context
+
+	dubboerl:init().
+
+#### Step5
+Do your interface method invoker.
+
+```
+RequestPara = #testReq{name = <<"nameinfo">>,nick = <<"nickinfo">>,age = 10},
+iProcessData:queryinfo(Info,[]).
+```
+	
+
+
+Build
+-----
+
+    $ rebar3 compile
+
+
+release
+	
+	$ ./rebar3 as dubboerl release -n dubboerl
+
+
+	
diff --git a/config/sys.config b/config/sys.config
new file mode 100644
index 0000000..8d62088
--- /dev/null
+++ b/config/sys.config
@@ -0,0 +1,34 @@
+[
+ 	%% SASL config    {file, "log/sasl-error.log"}
+ 	{sasl, [
+         {sasl_error_logger, false},
+         {errlog_type, error},
+         {error_logger_mf_dir, "log/sasl-error.log"},      % Log directory
+         {error_logger_mf_maxbytes, 104857600},   % 100 MB max file size
+         {error_logger_mf_maxfiles, 5}           % 5 files max
+        ]},
+    {emysql,[
+      {lock_timeout,900000},
+      {default_timeout, 900000}
+
+      ]},
+    {lager, [
+        {log_root, "./logs"},
+        {handlers, [
+            {lager_console_backend, debug},
+            {lager_file_backend, [{file, "error.log"}, {level, error}]},
+            {lager_file_backend, [{file, "console.log"}, {level, info}]}
+        ]}
+    ]},
+    {dubboerl,[
+        {zookeeper_list,[{"127.0.0.1",2181}]},
+        {application,<<"testdubboerl">>},
+        {consumer,[
+            {<<"com.ifcoder.demo.facade.User">>,[]}
+        ]},
+        {provider,[
+            {user_impl,user_behaviour,<<"com.ifcoder.demo.facade.User">>,[]}
+        ]}
+        
+    ]}
+].
diff --git a/config/vm.args b/config/vm.args
new file mode 100644
index 0000000..7134fa4
--- /dev/null
+++ b/config/vm.args
@@ -0,0 +1,36 @@
+## Name of the node
+##需要定义 -name android_connecion_1@logic1.mpush.paf
+-name dubboerl@127.0.0.1
+
+## Cookie for distributed erlang
+-setcookie fb65338cf25a2d68a2da5207f718cdfa
+
+## Heartbeat management; auto-restarts VM if it dies or becomes unresponsive
+## (Disabled by default..use with caution!)
+##-heart
+
+## Enable kernel poll and a few async threads
++K true
+##+A 5
+
+## Increase number of concurrent ports/sockets
+-env ERL_MAX_PORTS 10240000
+
+## too many db tables
+-env ERL_MAX_ETS_TABLES 125535
+
++P 3000000
+
+## Tweak GC to run more often
+-env ERL_FULLSWEEP_AFTER 30000
+
+
+## +S 2
+
+## erlang 端口上退 默认65535
++Q 2000000
+
+-kernel inet_dist_listen_min 4370 inet_dist_listen_max 4388
+
+## 调度类型
+-sub true
\ No newline at end of file
diff --git a/include/common.hrl b/include/common.hrl
new file mode 100644
index 0000000..70768b7
--- /dev/null
+++ b/include/common.hrl
@@ -0,0 +1,15 @@
+%%%-------------------------------------------------------------------
+%%% @author dlive
+%%% @copyright (C) 2016, <COMPANY>
+%%% @doc
+%%%
+%%% @end
+%%% Created : 14. 十月 2016 下午4:29
+%%%-------------------------------------------------------------------
+-author("dlive").
+
+-ifdef(DEBUG).
+-define(RELOADER,true).
+-else.
+-define(RELOADER,false).
+-endif.
\ No newline at end of file
diff --git a/include/dubbo.hrl b/include/dubbo.hrl
new file mode 100644
index 0000000..016a7a0
--- /dev/null
+++ b/include/dubbo.hrl
@@ -0,0 +1,98 @@
+%%%-------------------------------------------------------------------
+%%% @author dlive
+%%% @copyright (C) 2016, <COMPANY>
+%%% @doc
+%%%
+%%% @end
+%%% Created : 16. 十月 2016 下午11:38
+%%%-------------------------------------------------------------------
+-author("dlive").
+
+-include("hessian.hrl").
+
+-define(DUBBO_VERSION,<<"2.6.0">>).
+-define(DUBBO_MEGIC, -9541). %% new version 16#dabb
+-define(DUBBO_MEGIC_HIGH, 16#da). %% new version 16#da
+-define(DUBBO_MEGIC_LOW, 16#bb). %% new version 16#bb
+
+%% 序列化类型
+-define(SERIALIZATION_HESSIAN,2).
+-define(SERIALIZATION_FASTJSON,6).
+-define(SERIALIZATION_KRYO,8).
+
+-define(RESPONSE_WITH_EXCEPTION,0).
+-define(RESPONSE_VALUE,1).
+-define(RESPONSE_NULL_VALUE,2).
+
+
+-define(RESPONSE_STATE_OK,20).
+
+-define(REQUEST_TIME_OUT,5000).
+
+-define(LINE_SEPERATOR,<<"\n"/utf8>>).
+
+-record(dubbo_request,{
+    serialize_type = 2      ::integer(),
+    is_event = true         ::boolean(),
+    is_twoway = false       ::boolean(),
+    data                    ::null|dubbo_rpc_invocation,
+    mid                     ::integer(),
+    mversion                ::string(),
+    error_msg               ::string(),
+    state                   ::byte(),
+    decode_state
+}).
+
+-record(dubbo_response,{
+    serialize_type = 2      ::integer(),
+    is_event = true         ::boolean(),
+    is_twoway = false       ::boolean(),
+    data                    ::null|dubbo_rpc_invocation,
+    mid                     ::integer(),
+    mversion                ::string(),
+    error_msg               ::string(),
+    state                   ::byte(),
+    decode_state
+}).
+
+-record(dubbo_rpc_invocation,{
+    serialVersionUID = -4355285085441097045,
+    className               ::string(),
+    classVersion            ::string(),
+    methodName              ::string(),
+    parameterDesc           ::string(),
+    parameterTypes=[]       ::[#type_def{}],
+    parameters=[]           ::[term()],
+    attachments=[]          ::[term()]
+}).
+
+-record(consumer_config,{
+    interface,
+    application = <<"NoName">> ::binary(),
+    category = <<"consumers">> ::binary(),
+    check=false                ::boolean(),
+    default_timeout=500        ::integer(),
+    dubbo_version= <<"2.5.3">>         ::binary(),
+    methods=[]                 ::list(),
+    revision= <<"">>           ::binary(),
+    side= <<"consumers">>      ::binary()
+}).
+
+-record(provider_config,{
+    protocol,
+    host,
+    port,
+    interface,
+    anyhost=true,
+    executes=1,
+    application,
+    dubbo= <<"2.5.3">>,
+    methods=[],
+    side= <<"provider">>
+}).
+
+
+
+-record(interface_list,{interface,pid,connection_info}).
+-record(provider_node_list,{host_flag,connection_info}).
+-record(connection_info,{connection_id,pid,weight,host_flag}).
\ No newline at end of file
diff --git a/include/dubbo_type.hrl b/include/dubbo_type.hrl
new file mode 100644
index 0000000..f01d969
--- /dev/null
+++ b/include/dubbo_type.hrl
@@ -0,0 +1,12 @@
+%%%-------------------------------------------------------------------
+%%% @author dlive
+%%% @copyright (C) 2018, <COMPANY>
+%%% @doc
+%%%
+%%% @end
+%%% Created : 15. Apr 2018 9:10 PM
+%%%-------------------------------------------------------------------
+-author("dlive").
+
+
+-type response_content() :: binary().
\ No newline at end of file
diff --git a/include/dubboerl.hrl b/include/dubboerl.hrl
new file mode 100644
index 0000000..baf4c25
--- /dev/null
+++ b/include/dubboerl.hrl
@@ -0,0 +1,16 @@
+%%%-------------------------------------------------------------------
+%%% @author dlive
+%%% @copyright (C) 2018, <COMPANY>
+%%% @doc
+%%%
+%%% @end
+%%% Created : 22. Mar 2018 6:53 PM
+%%%-------------------------------------------------------------------
+-author("dlive").
+
+
+-define(PROVIDER_IMPL_TABLE,provider_impl_table).
+
+-define(PROVIDER_WORKER,provider_worker).
+
+-define(TRAFFIC_CONTROL,traffic_control).
\ No newline at end of file
diff --git a/include/hessian.hrl b/include/hessian.hrl
new file mode 100755
index 0000000..46ea79e
--- /dev/null
+++ b/include/hessian.hrl
@@ -0,0 +1,46 @@
+-ifndef(HESSIAN_H).
+-define(HESSIAN_H,1).
+
+-define(M, 2).
+-define(m, 0).
+
+-define(CHUNK_SIZE, 1024).
+
+-define(MegaSeconds, 1000000000).
+-define(Seconds, 1000).
+-define(MicroSeconds, 1000).
+-define(UnixEpoch, 62167219200).
+
+%% Equivalents: type_def and class
+-record(type_def,{defineNo=-1,native_type, foreign_type, fieldnames}).
+-record(class, {typeNo=-1, encoded=false, name=[], fields=[]}).
+
+-record(list, {refNo=-1, len=-1, type=untyped, values=[]}).
+-record(map, {refNo=-1, type=untyped, dict=dict:new()}).
+-record(object, {refNo=-1, typeRef=-1, class=auto, values=[]}).
+
+-record(set, {ref=-1, value=[]}).
+
+-ifdef(DEBUG).
+% Application Logging
+-define(LOG(Msg), io:format("{~p:~p}: ~p~n", [?MODULE, ?LINE, Msg])).
+-define(ERROR(Error,Reason), io:format("Error @ ~p:~p: ~p (Reason: ~p)~n", [?MODULE, ?LINE,Error,Reason])).
+% Protocol Logging
+-define(START(Msg,Value), io:format("~s -> ~p~n", [Msg,Value])).
+-define(METHOD(Value), io:format("\tMethod -> ~p~n", [ binary_to_list(Value) ] )).
+-define(VALUE(Value), io:format("\t\tValue -> ~p~n", [ Value ] )).
+-define(TYPEDEF(Value), io:format("\t\tTypeDef -> ~p~n", [ Value ] )).
+-define(INSTANCE(Value), io:format("\t\tInstance -> ~p~n", [ Value ] )).
+-else.
+% Application Logging
+-define(LOG(Msg), true).
+-define(ERROR(Msg), true).
+% Protocol Logging
+-define(START(Msg,Value), true).
+-define(METHOD(Value), true).
+-define(VALUE(Value), true).
+-define(TYPEDEF(Value), true).
+-define(INSTANCE(Value), true).
+-endif.
+
+-endif.
\ No newline at end of file
diff --git a/include/hessian_test.hrl b/include/hessian_test.hrl
new file mode 100644
index 0000000..ed6b8cb
--- /dev/null
+++ b/include/hessian_test.hrl
@@ -0,0 +1,34 @@
+% ---------------------------------------------------------------------------
+%   Copyright (C) 2008 0x6e6562
+%
+%   Licensed 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.
+% ---------------------------------------------------------------------------
+
+% This is for simple tests
+-record(pair, {first, second}).
+
+% These are used in the kitchen sink tests
+-record(kitchen_sink,  {color, 
+                        plug_hole,
+                        delivery_date,
+                        cost,
+                        type,
+                        deluxe}).
+-record(plug_hole, {diameter}).
+-record(specification, {customer_name, 
+                        plug_hole,
+                        color,
+                        total,
+                        type,
+                        order_date,
+                        deluxe}).
\ No newline at end of file
diff --git a/include/java_type.hrl b/include/java_type.hrl
new file mode 100644
index 0000000..e85e3a7
--- /dev/null
+++ b/include/java_type.hrl
@@ -0,0 +1,13 @@
+%%%-------------------------------------------------------------------
+%%% @author dlive
+%%% @copyright (C) 2018, <COMPANY>
+%%% @doc
+%%%
+%%% @end
+%%% Created : 09. Mar 2018 11:10 PM
+%%%-------------------------------------------------------------------
+-author("dlive").
+
+-record(null_pointer_exception,{detailMessage,cause,stackTrace,suppressedExceptions}).
+
+-record(stack_stack_trace_element,{declaringClass,methodName,fileName,lineNumber}).
\ No newline at end of file
diff --git a/rebar.config b/rebar.config
new file mode 100644
index 0000000..81b3d5f
--- /dev/null
+++ b/rebar.config
@@ -0,0 +1,19 @@
+{erl_opts, [debug_info,
+    {parse_transform, lager_transform}
+    ]}.
+
+{lib_dirs, []}.
+{base_dir, "_build"}.
+{root_dir, "."}.
+{project_app_dirs, ["."]}.
+{extra_src_dirs, ["test"]}.
+{ct_opts, []}.
+
+
+{deps, [
+    {erlzk, ".*", {git, "git@github.com:huaban/erlzk.git", {tag, "v0.6.2"}}},
+    {lager, ".*", {git, "git@github.com:basho/lager.git", {tag, "3.2.4"}}},
+    {ranch, ".*",  {git, "https://github.com/ninenines/ranch.git", {tag, "1.4.0"}}},
+    {poolboy, ".*",  {git, "https://github.com/devinus/poolboy.git", {tag, "1.5.1"}}},
+    {jiffy, "0.15.1"}
+]}.
\ No newline at end of file
diff --git a/rebar3 b/rebar3
new file mode 100755
index 0000000..9463ef6
--- /dev/null
+++ b/rebar3
Binary files differ
diff --git a/src/de_codec.erl b/src/de_codec.erl
new file mode 100644
index 0000000..8cc4136
--- /dev/null
+++ b/src/de_codec.erl
@@ -0,0 +1,284 @@
+%%%-------------------------------------------------------------------
+%%% @author dlive
+%%% @copyright (C) 2016, <COMPANY>
+%%% @doc
+%%%
+%%% @end
+%%% Created : 20. 十月 2016 下午6:21
+%%%-------------------------------------------------------------------
+-module(de_codec).
+-author("dlive").
+
+-include("dubbo.hrl").
+-include("hessian.hrl").
+
+-ifdef(TEST).
+-compile(export_all).
+-endif.
+%% API
+-export([encode_request/1,encode_response/1]).
+
+-export([decode_header/1]).
+-export([decode_response/2]).
+-export([decode_request/2]).
+
+
+
+-spec encode_request(#dubbo_request{})->{ok,binary()} | {error,term()}.
+encode_request(Request)->
+%%    lager:debug("encode request ~p",[Request]),
+    {ok,RequestData} = encode_request_data(Request#dubbo_request.serialize_type,Request),
+    Size = byte_size(RequestData),
+    Header = encode_header(Request,Size,0),
+    RequestContent = <<Header/binary,RequestData/binary>>,
+    {ok,RequestContent}.
+
+encode_header(Request,DataLen,RequestState)->
+    Header2=-128 bor Request#dubbo_request.serialize_type,
+    Header21=case Request#dubbo_request.is_twoway of
+        true -> Header2 bor 64;
+        false-> Header2
+    end,
+    Header22=case Request#dubbo_request.is_event of
+                 true -> Header21 bor 32;
+                 false-> Header21
+             end,
+    RequestId = Request#dubbo_request.mid,
+    Header = << ?DUBBO_MEGIC:16,Header22:8,RequestState:8,RequestId:64,DataLen:32>>,
+    Header.
+encode_request_data(?SERIALIZATION_FASTJSON,Request)->
+    dubbo_serializa_fastjson:encode_request_data(Request);
+
+encode_request_data(?SERIALIZATION_HESSIAN,Request)->
+    State=type_encoding:init(),
+    DataType =case Request#dubbo_request.is_event of
+                 true->
+                    dubbo_event;
+                 false->
+                    case Request#dubbo_request.data of
+                       #dubbo_rpc_invocation{} ->
+                           dubbo_rpc_invocation;
+                       _ ->
+                           unknow
+                    end
+             end,
+    {ok,Bin} = encode_request_data(DataType,Request,Request#dubbo_request.data,State),
+    {ok,Bin}.
+
+encode_request_data(dubbo_event,Request,Data,State) ->
+    Bin = hessianEncode:encode(Data,State),
+    {ok,Bin};
+encode_request_data(dubbo_rpc_invocation,Request,Data,State) ->
+    METHOD_NAME = Data#dubbo_rpc_invocation.methodName,
+    METHOD_ARGS_TYPES = Data#dubbo_rpc_invocation.parameterDesc,
+    RequestList = [
+        hessianEncode:encode(?DUBBO_VERSION, State), %% dubbo version
+        hessianEncode:encode(Data#dubbo_rpc_invocation.className, State),
+        hessianEncode:encode(Data#dubbo_rpc_invocation.classVersion, State),
+        hessianEncode:encode(METHOD_NAME, State),
+        hessianEncode:encode(METHOD_ARGS_TYPES, State)
+    ],
+    {ArgsBin,State2} = encode_arguments(Data,State),
+    AttachDict = dict:from_list(Data#dubbo_rpc_invocation.attachments),
+    AttachMaps = #map{dict = AttachDict },
+    {AttachBinay,_} = hessianEncode:encode(AttachMaps, State2),
+    RequestData = erlang:iolist_to_binary(RequestList ++ [ArgsBin,AttachBinay]),
+    {ok,RequestData}.
+
+-spec encode_response(#dubbo_response{})-> {ok,term()}.
+encode_response(Response)->
+    {ok,ResponseData} = encode_response_data(Response),
+    Size = byte_size(ResponseData),
+    Header = encode_response_header(Response,Size,?RESPONSE_STATE_OK),
+    ResponseContent = <<Header/binary,ResponseData/binary>>,
+    {ok, ResponseContent}.
+
+encode_response_data(Response)->
+    State=type_encoding:init(),
+    DataType =case Response#dubbo_response.is_event of
+                  true->
+                      dubbo_event;
+                  false->
+                      case Response#dubbo_response.data of
+                          #dubbo_rpc_invocation{} ->
+                              dubbo_rpc_invocation;
+                          _ ->
+                              unknow
+                      end
+              end,
+    {ok,Bin} = encode_response_data(DataType,Response,Response#dubbo_response.data,State),
+    {ok,Bin}.
+encode_response_data(dubbo_event,Response,Data,State) ->
+    Bin = hessianEncode:encode(Data,State),
+    {ok,Bin};
+encode_response_data(dubbo_rpc_invocation,Response,Data,State) ->
+    Result = case Data of
+        null ->
+            [
+                hessianEncode:encode(?RESPONSE_NULL_VALUE, State)
+            ];
+        _ ->
+            {ArgsBin,_State2} = encode_arguments(Data,State),
+            [
+                hessianEncode:encode(?RESPONSE_VALUE, State),
+                ArgsBin
+            ]
+    end,
+    ResponseData = erlang:iolist_to_binary(Result),
+    {ok,ResponseData}.
+
+encode_response_header(Response,DataLen, ResponseState)->
+    Header2= Response#dubbo_response.serialize_type,
+    Header21=case Response#dubbo_response.is_twoway of
+                 true -> Header2 bor 64;
+                 false-> Header2
+             end,
+    Header22=case Response#dubbo_response.is_event of
+                 true -> Header21 bor 32;
+                 false-> Header21
+             end,
+    RequestId = Response#dubbo_response.mid,
+    Header = << ?DUBBO_MEGIC:16,Header22:8, ResponseState:8,RequestId:64,DataLen:32>>,
+    Header.
+encode_arguments(Data,State)->
+    {StateNew} = lists:foldl(fun(X,{StateTmp})->
+        StateTmpNew = type_encoding:enlist(X,StateTmp),
+        {StateTmpNew} end,
+        {State},Data#dubbo_rpc_invocation.parameterTypes),
+    {Bin,State2} = lists:foldl(fun(X,{BinTmp,StateTmp2})->
+        case hessianEncode:encode(X, StateTmp2) of
+            {ArgsBin,StateTmpNew} ->
+                {<<BinTmp/binary,ArgsBin/binary>>, StateTmpNew};
+            ArgsBin2 ->
+                {<<BinTmp/binary,ArgsBin2/binary>>, StateTmp2}
+        end end,
+        {<<>>,StateNew},Data#dubbo_rpc_invocation.parameters),
+    {Bin,State2}.
+
+-spec decode_header(binary())-> {State::ok|error,Type::request|response,Data::#dubbo_response{}|#dubbo_request{}}.
+decode_header(Header)->
+    <<?DUBBO_MEGIC_HIGH,?DUBBO_MEGIC_LOW,Flag:8,State:8,Mid:64,DataLen:32>> = Header,
+    if
+        (Flag band 16#80) == 0 ->
+            {DecodeState,Res} = decode_header(response,Flag,State,Mid,DataLen),
+            {DecodeState,response,Res};
+        true ->
+            {DecodeState,Req} = decode_header(request,Flag,State,Mid,DataLen),
+            {DecodeState,request,Req}
+    end.
+decode_header(request,Flag,State,Mid,DataLen)->
+    SerializeType = Flag band 16#1f,
+    IsTwoWay = if
+                   (Flag band 16#40) /=0 -> true;
+                   true -> false
+    end,
+    IsEvent = if
+                  (Flag band 16#20) /=0 -> true;
+                  true -> false
+              end,
+    Req = #dubbo_request{
+        is_event = IsEvent,
+        is_twoway = IsTwoWay,
+        mid = Mid,
+        mversion = <<"2.0.0">>,
+        serialize_type = SerializeType
+    },
+    {ok,Req};
+decode_header(response,Flag,State,Mid,DataLen)->
+    SerializeType = Flag band 16#1f,
+    IsEvent = if
+        (Flag band 16#20) /= 0 -> true;
+        true -> false
+    end,
+    Res = #dubbo_response{is_event = IsEvent,
+        serialize_type = SerializeType,
+        state = State,
+        mid = Mid
+    },
+    {ok,Res}.
+
+-spec decode_response(#dubbo_response{},binary())-> {ok,#dubbo_response{}}.
+decode_response(Res,Data)->
+    case Res#dubbo_response.serialize_type of
+        ?SERIALIZATION_FASTJSON ->
+            dubbo_serializa_fastjson:decode_response(Res,Data);
+        ?SERIALIZATION_HESSIAN ->
+            dubbo_serializa_hession:decode_response(Res,Data)
+    end.
+
+%%decode_response(?SERIALIZATION_FASTJSON,dubbo_rpc_invocation,Res,Data)->
+%%    dubbo_serializa_fastjson:decode_response(dubbo_rpc_invocation,Res,Data);
+%%
+%%decode_response(?SERIALIZATION_HESSIAN,dubbo_rpc_invocation,Res,Data)->
+%%    {Rest,Type,State} = hessianDecode2:decode(Data,hessianDecode2:init()),
+%%    case Type of
+%%        1 ->
+%%            {_,Object,DecodeState} = hessianDecode2:decode(Rest,State),
+%%            {ok,Res#dubbo_response{data = Object,decode_state = DecodeState}};
+%%        2 ->
+%%            {ok,Res#dubbo_response{data = null,decode_state = State}};
+%%        _->
+%%            lager:warning("decode unkonw type ~p ~p",[Type,Rest]),
+%%            {Rest2,Object2,DecodeState2} = hessianDecode2:decode(Rest,State),
+%%            lager:warning("decode unkonw type2 ~p ~p",[Object2,Rest2]),
+%%            {ok,Res#dubbo_response{data = Object2,decode_state = DecodeState2}}
+%%    end;
+%%decode_response(?SERIALIZATION_HESSIAN,dubbo_event,Res,Data)->
+%%    {_Rest,undefined,_NewState} = hessianDecode2:decode(Data,hessianDecode2:init()),
+%%    {ok,Res#dubbo_response{data = undefined}}.
+
+-spec decode_request(#dubbo_request{},binary())-> {ok,#dubbo_request{}}.
+decode_request(Req,Data)->
+    case Req#dubbo_request.serialize_type of
+        ?SERIALIZATION_FASTJSON ->
+            dubbo_serializa_fastjson:decode_request(Req,Data);
+        ?SERIALIZATION_HESSIAN ->
+            dubbo_serializa_hession:decode_request(Req,Data)
+    end.
+
+%%decode_request(dubbo_rpc_invocation,Req,Data)->
+%%    {ResultList,NewState,RestData} = decode_request_body(Data,hessianDecode2:init(),[dubbo,path,version,method_name,desc_and_args,attachments]),
+%%    [DubboVersion,Path,Version,MethodName,Desc,ArgsObj,Attachments]=ResultList,
+%%    RpcData = #dubbo_rpc_invocation{className = Path,classVersion = Version,methodName = MethodName,parameterDesc = Data,parameters = ArgsObj,attachments = Attachments},
+%%    Req2 = Req#dubbo_request{data = RpcData},
+%%    {ok,Req2};
+%%
+%%decode_request(dubbo_event,Req,Data)->
+%%    {_Rest,undefined,_NewState} = hessianDecode2:decode(Data,hessianDecode2:init()),
+%%    {ok,Req#dubbo_request{data = undefined}}.
+%%
+%%decode_request_body(Data,State,List)->
+%%    {ResultList,NewState,RestData} = decode_request_body(List,Data,State,[]),
+%%    {lists:reverse(ResultList),NewState,RestData}.
+%%decode_request_body([ParseType|List],Data,State,ResultList)
+%%    when ParseType==dubbo;ParseType==path;ParseType==version;ParseType==method_name ->
+%%    {Rest,Result,NewState } = hessianDecode2:decode(Data,State),
+%%    decode_request_body(List,Rest,NewState, [Result] ++ ResultList);
+%%decode_request_body([desc_and_args| List],Data,State,ResultList)->
+%%    {Rest,ParameterDesc,State1 } = hessianDecode2:decode(Data,State),
+%%    if
+%%        size(ParameterDesc) == 0 ->
+%%            decode_request_body(List,Rest,State1, [ [],[] ]++ ResultList);
+%%        true ->
+%%            ParameterDescArray = binary:split(ParameterDesc,<<";">>),
+%%            {ArgsObjList,NewState,RestData} = decode_request_body_args(ParameterDescArray,Rest,State1,[]),
+%%            decode_request_body(List,RestData,NewState, [ArgsObjList,ParameterDesc]++ ResultList)
+%%    end;
+%%decode_request_body([attachments|List],Data,State,ResultList)->
+%%    {Rest,Attachments,State1 } = hessianDecode2:decode(Data,State),
+%%    AttachmentsList = dict:to_list(Attachments#map.dict),
+%%    decode_request_body(List,Rest,State1,[AttachmentsList] ++ ResultList);
+%%decode_request_body([_Type1|List],Data,State,ResultList)->
+%%    lager:warning("decode_request_body unknow type"),
+%%    decode_request_body(List,Data,State, ResultList);
+%%decode_request_body([],Data,State,ResultList)->
+%%    {ResultList,State,Data}.
+%%
+%%decode_request_body_args([],Data,State,ArgsObjList)->
+%%    {ArgsObjList,State,Data};
+%%decode_request_body_args([ArgsType|RestList],Data,State,ArgsObjList) when ArgsType== <<>> ->
+%%    decode_request_body_args(RestList,Data,State,ArgsObjList);
+%%decode_request_body_args([_ArgsType|RestList],Data,State,ArgsObjList) ->
+%%    {Rest,ArgObj,NewState } = hessianDecode2:decode(Data,State),
+%%    ArgObj2 = de_type_transfer:classobj_to_native(ArgObj,NewState),
+%%    decode_request_body_args(RestList,Rest,NewState,ArgsObjList++[ArgObj2]).
\ No newline at end of file
diff --git a/src/de_common_fun.erl b/src/de_common_fun.erl
new file mode 100644
index 0000000..31eb143
--- /dev/null
+++ b/src/de_common_fun.erl
@@ -0,0 +1,24 @@
+%%%-------------------------------------------------------------------
+%%% @author dlive
+%%% @copyright (C) 2017, <COMPANY>
+%%% @doc
+%%%
+%%% @end
+%%% Created : 27. Dec 2017 3:01 PM
+%%%-------------------------------------------------------------------
+-module(de_common_fun).
+-author("dlive").
+
+%% API
+-export([local_ip_v4/0,local_ip_v4_str/0]).
+
+local_ip_v4() ->
+    {ok, Addrs} = inet:getifaddrs(),
+    hd([
+        Addr || {_, Opts} <- Addrs, {addr, Addr} <- Opts,
+        size(Addr) == 4, Addr =/= {127,0,0,1}
+    ]).
+
+local_ip_v4_str()->
+    {V1,V2,V3,V4} =local_ip_v4(),
+    list_to_binary(io_lib:format("~p.~p.~p.~p",[V1,V2,V3,V4])).
diff --git a/src/de_heartbeat.erl b/src/de_heartbeat.erl
new file mode 100644
index 0000000..b6da7cb
--- /dev/null
+++ b/src/de_heartbeat.erl
@@ -0,0 +1,21 @@
+%%%-------------------------------------------------------------------
+%%% @author dlive
+%%% @copyright (C) 2016, <COMPANY>
+%%% @doc
+%%%
+%%% @end
+%%% Created : 20. 十月 2016 下午5:55
+%%%-------------------------------------------------------------------
+-module(de_heartbeat).
+-author("dlive").
+
+-include("dubbo.hrl").
+%% API
+-export([generate_request/2]).
+generate_request(undefined,NeedResponse)->
+    RequestId = de_id_count:gen_id(),
+    generate_request(RequestId,NeedResponse);
+generate_request(RequestId,NeedResponse)->
+    Req = #dubbo_request{is_event = true,is_twoway = true,mid = RequestId,data = undefined,mversion= <<"2.0.0">>},
+    {ok,Bin} = de_codec:encode_request(Req),
+    {ok,Bin}.
\ No newline at end of file
diff --git a/src/de_id_count.erl b/src/de_id_count.erl
new file mode 100644
index 0000000..be07d1b
--- /dev/null
+++ b/src/de_id_count.erl
@@ -0,0 +1,177 @@
+%%%-------------------------------------------------------------------
+%%% @author dlive
+%%% @copyright (C) 2016, <COMPANY>
+%%% @doc
+%%%
+%%% @end
+%%% Created : 17. 十月 2016 上午11:12
+%%%-------------------------------------------------------------------
+-module(de_id_count).
+-author("dlive").
+
+-behaviour(gen_server).
+
+%% API
+-export([start_link/0]).
+
+%% gen_server callbacks
+-export([init/1,
+    handle_call/3,
+    handle_cast/2,
+    handle_info/2,
+    terminate/2,
+    code_change/3]).
+-export([gen_id/0,get_index/2]).
+
+-define(SERVER, ?MODULE).
+-define(INDEX_ETS_TABLE,de_id_count_table).
+-define(MAX_NUM,9223372036854775807).
+-record(state, {}).
+
+%%%===================================================================
+%%% API
+%%%===================================================================
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Starts the server
+%%
+%% @end
+%%--------------------------------------------------------------------
+-spec(start_link() ->
+    {ok, Pid :: pid()} | ignore | {error, Reason :: term()}).
+start_link() ->
+    gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).
+
+%%%===================================================================
+%%% gen_server callbacks
+%%%===================================================================
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Initializes the server
+%%
+%% @spec init(Args) -> {ok, State} |
+%%                     {ok, State, Timeout} |
+%%                     ignore |
+%%                     {stop, Reason}
+%% @end
+%%--------------------------------------------------------------------
+-spec(init(Args :: term()) ->
+    {ok, State :: #state{}} | {ok, State :: #state{}, timeout() | hibernate} |
+    {stop, Reason :: term()} | ignore).
+init([]) ->
+    init_table(),
+    {ok, #state{}}.
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Handling call messages
+%%
+%% @end
+%%--------------------------------------------------------------------
+-spec(handle_call(Request :: term(), From :: {pid(), Tag :: term()},
+    State :: #state{}) ->
+    {reply, Reply :: term(), NewState :: #state{}} |
+    {reply, Reply :: term(), NewState :: #state{}, timeout() | hibernate} |
+    {noreply, NewState :: #state{}} |
+    {noreply, NewState :: #state{}, timeout() | hibernate} |
+    {stop, Reason :: term(), Reply :: term(), NewState :: #state{}} |
+    {stop, Reason :: term(), NewState :: #state{}}).
+handle_call(_Request, _From, State) ->
+    {reply, ok, State}.
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Handling cast messages
+%%
+%% @end
+%%--------------------------------------------------------------------
+-spec(handle_cast(Request :: term(), State :: #state{}) ->
+    {noreply, NewState :: #state{}} |
+    {noreply, NewState :: #state{}, timeout() | hibernate} |
+    {stop, Reason :: term(), NewState :: #state{}}).
+handle_cast(_Request, State) ->
+    {noreply, State}.
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Handling all non call/cast messages
+%%
+%% @spec handle_info(Info, State) -> {noreply, State} |
+%%                                   {noreply, State, Timeout} |
+%%                                   {stop, Reason, State}
+%% @end
+%%--------------------------------------------------------------------
+-spec(handle_info(Info :: timeout() | term(), State :: #state{}) ->
+    {noreply, NewState :: #state{}} |
+    {noreply, NewState :: #state{}, timeout() | hibernate} |
+    {stop, Reason :: term(), NewState :: #state{}}).
+handle_info(_Info, State) ->
+    {noreply, State}.
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% This function is called by a gen_server when it is about to
+%% terminate. It should be the opposite of Module:init/1 and do any
+%% necessary cleaning up. When it returns, the gen_server terminates
+%% with Reason. The return value is ignored.
+%%
+%% @spec terminate(Reason, State) -> void()
+%% @end
+%%--------------------------------------------------------------------
+-spec(terminate(Reason :: (normal | shutdown | {shutdown, term()} | term()),
+    State :: #state{}) -> term()).
+terminate(_Reason, _State) ->
+    ok.
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Convert process state when code is changed
+%%
+%% @spec code_change(OldVsn, State, Extra) -> {ok, NewState}
+%% @end
+%%--------------------------------------------------------------------
+-spec(code_change(OldVsn :: term() | {down, term()}, State :: #state{},
+    Extra :: term()) ->
+    {ok, NewState :: #state{}} | {error, Reason :: term()}).
+code_change(_OldVsn, State, _Extra) ->
+    {ok, State}.
+
+gen_id()->
+    try ets:update_counter(?INDEX_ETS_TABLE,cur_index,{2,1,?MAX_NUM,1}) of
+        NewCount ->
+            NewCount
+    catch
+        _Type:_Reason ->
+            (catch ets:insert(?INDEX_ETS_TABLE,{cur_index,1})),
+            ets:update_counter(?INDEX_ETS_TABLE,cur_index,{2,1,?MAX_NUM,1})
+    end.
+
+get_index(Type,Max)->
+    try ets:update_counter(?INDEX_ETS_TABLE,Type,{2,1,Max,1}) of
+        NewCount ->
+            NewCount
+    catch
+        _Type:_Reason ->
+            (catch ets:insert(?INDEX_ETS_TABLE,{Type,1})),
+            ets:update_counter(?INDEX_ETS_TABLE,Type,{2,1,Max,1})
+    end.
+%%%===================================================================
+%%% Internal functions
+%%%===================================================================
+init_table()->
+    try ets:new(de_id_count_table, [public,named_table]) of
+        de_id_count_table ->
+            ets:insert(?INDEX_ETS_TABLE,{cur_index,1}),
+            ok
+    catch
+        _Type:Reason ->
+            io:format("error init auto inc table reason:~p~n",[Reason])
+    end.
\ No newline at end of file
diff --git a/src/de_network_tools.erl b/src/de_network_tools.erl
new file mode 100644
index 0000000..7527885
--- /dev/null
+++ b/src/de_network_tools.erl
@@ -0,0 +1,28 @@
+%%%-------------------------------------------------------------------
+%%% @author dlive
+%%% @copyright (C) 2018, <COMPANY>
+%%% @doc
+%%%
+%%% @end
+%%% Created : 21. Mar 2018 4:07 PM
+%%%-------------------------------------------------------------------
+-module(de_network_tools).
+-author("dlive").
+
+%% API
+-export([local_ip_v4/0,local_ipv4/0,local_ipv4_binary/0]).
+
+
+local_ip_v4() ->
+    {ok, Addrs} = inet:getifaddrs(),
+    hd([
+        Addr || {_, Opts} <- Addrs, {addr, Addr} <- Opts,
+        size(Addr) == 4, Addr =/= {127,0,0,1}
+    ]).
+
+local_ipv4_binary()->
+    {I1,I2,I3,I4}=local_ip_v4(),
+    list_to_binary(io_lib:format("~p.~p.~p.~p",[I1,I2,I3,I4])).
+local_ipv4()->
+    {I1,I2,I3,I4}=local_ip_v4(),
+    lists:flatten(io_lib:format("~p.~p.~p.~p",[I1,I2,I3,I4])).
diff --git a/src/de_type_transfer.erl b/src/de_type_transfer.erl
new file mode 100644
index 0000000..5d89dcc
--- /dev/null
+++ b/src/de_type_transfer.erl
@@ -0,0 +1,104 @@
+%%%-------------------------------------------------------------------
+%%% @author dlive
+%%% @copyright (C) 2016, <COMPANY>
+%%% @doc
+%%%
+%%% @end
+%%% Created : 27. 十月 2016 下午8:28
+%%%-------------------------------------------------------------------
+-module(de_type_transfer).
+-author("dlive").
+
+-include("hessian.hrl").
+-include("dubbo.hrl").
+
+%% API
+-export([java_to_native/2,pre_process_typedef/3,response_to_native/1,classobj_to_native/2]).
+
+
+response_to_native(Response)->
+    java_to_native(Response#dubbo_response.data,Response#dubbo_response.decode_state).
+
+
+classobj_to_native(Data,DecodeState)->
+    java_to_native(Data,DecodeState).
+
+java_to_native(#object{values = ForeignData}=Data,State)->
+    ForeignDataNew = [java_to_native(ValueItem,State) || ValueItem <-ForeignData ],
+
+    case hessianDecode2:get_deftype(Data#object.typeRef,State) of
+        #type_def{fieldnames = ObjectFields,foreign_type = ForeignType } ->
+            case get_deftype(ForeignType) of
+                false->
+                    error;
+                #type_def{fieldnames = NativeFields,native_type = NativeTupeName}->
+                    AsDict = dict:from_list(lists:zip(ObjectFields,ForeignDataNew)),
+                    NativeData = [dict:fetch(atom_to_binary(Key,utf8),AsDict) || Key <- NativeFields],
+                    list_to_tuple( [NativeTupeName] ++ NativeData)
+            end;
+        Info ->
+            lager:warning("java_to_native error:~p",[Info]),
+            error
+    end;
+java_to_native(#list{values = ForeignData}=Data,State)->
+    ForeignDataNew = [java_to_native(ValueItem,State) || ValueItem <-ForeignData ],
+    ForeignDataNew;
+%%    case hessianDecode2:get_deftype(Data#list.refNo,State) of
+%%        #type_def{fieldnames = ObjectFields,foreign_type = ForeignType } ->
+%%            case get_deftype(ForeignType) of
+%%                false->
+%%                    error;
+%%                #type_def{fieldnames = NativeFields,native_type = NativeTupeName}->
+%%                    lager:debug("test ForeignType ~p NativeTupeName ~p",[ForeignType,NativeTupeName]),
+%%%%                    AsDict = dict:from_list(lists:zip(ObjectFields,ForeignDataNew)),
+%%%%                    NativeData = [dict:fetch(atom_to_binary(Key,utf8),AsDict) || Key <- NativeFields],
+%%%%                    list_to_tuple( [NativeTupeName] ++ NativeData)
+%%                    ForeignDataNew
+%%            end;
+%%        Info ->
+%%            lager:warning("java_to_native list error:~p",[Info]),
+%%            error
+%%    end;
+java_to_native(Data,_)->
+    lager:debug("java_to_native unkonw type ~p",[Data]),
+    Data.
+
+%%get_deftype([Item |DefTypeList],ForeignType)->
+%%    if
+%%        Item#type_def.foreign_type == ForeignType -> Item;
+%%        true ->
+%%            get_deftype(DefTypeList,ForeignType)
+%%    end;
+%%get_deftype([],_ForeignType)->
+%%    false.
+
+get_deftype(ForeignType)->
+
+    case type_register:lookup_foreign_type(ForeignType) of
+        undefined->
+            lager:debug("get deftype undefined ~p",[ForeignType]),
+            false;
+        #type_def{}=TypeDef->
+            lager:debug("get deftype success ~p",[ForeignType]),
+            TypeDef;
+        _->
+            lager:debug("get deftype  undefined ~p",[ForeignType]),
+            false
+    end.
+
+pre_process_typedef(NativeType,ForeignType,FieldsNames)->
+    Type = #type_def{native_type = NativeType,foreign_type = ForeignType,fieldnames = FieldsNames},
+%%            Type2=type_decoding:hash_store(Type),
+    type_register:regiest_foreign_native(Type),
+    lager:debug("pre_process_typedef ~p,~p",[NativeType,ForeignType]).
+%%    case type_decoding:resolve_native_type(ForeignType) of
+%%        undefined ->
+%%%%            Type = #type_def{native_type = NativeType, foreign_type = ForeignType, fieldnames = record_info(fields,NativeType)},
+%%            Type = #type_def{native_type = NativeType,foreign_type = ForeignType,fieldnames = FieldsNames},
+%%            Type2=type_decoding:hash_store(Type),
+%%
+%%            lager:debug("pre_process_typedef ~p,~p",[NativeType,ForeignType]);
+%%            type_decoding:store_typepool(Type2);
+%%        _->
+%%            ok
+%%    end.
\ No newline at end of file
diff --git a/src/dubbo_agent.erl b/src/dubbo_agent.erl
new file mode 100644
index 0000000..15e557a
--- /dev/null
+++ b/src/dubbo_agent.erl
@@ -0,0 +1,20 @@
+%%%-------------------------------------------------------------------
+%%% @author dlive
+%%% @copyright (C) 2018, <COMPANY>
+%%% @doc
+%%%
+%%% @end
+%%% Created : 11. May 2018 12:15 AM
+%%%-------------------------------------------------------------------
+-module(dubbo_agent).
+-author("dlive").
+
+%% API
+-export([register_consumer/1]).
+
+register_consumer(Interface)->
+    ProviderList=[
+        "dubbo%3a%2f%2f127.0.0.1%3a20880%2fcom.alibaba.dubbo.performance.demo.provider.IHelloService%3fanyhost%3dtrue%26application%3dmesh-provider%26dubbo%3d2.6%26executes%3d30%26interface%3dcom.alibaba.dubbo.performance.demo.provider.IHelloService%26methods%3dhash%26pid%3d26029%26side%3dprovider%26timestamp%3d1514615143388"
+    ],
+    dubbo_consumer_pool:start_consumer(Interface,ProviderList),
+    ok.
diff --git a/src/dubbo_common.erl b/src/dubbo_common.erl
new file mode 100644
index 0000000..11abb42
--- /dev/null
+++ b/src/dubbo_common.erl
@@ -0,0 +1,13 @@
+%%%-------------------------------------------------------------------
+%%% @author dlive
+%%% @copyright (C) 2016, <COMPANY>
+%%% @doc
+%%%
+%%% @end
+%%% Created : 17. 十月 2016 上午12:23
+%%%-------------------------------------------------------------------
+-module(dubbo_common).
+-author("dlive").
+
+%% API
+-export([]).
diff --git a/src/dubbo_config_util.erl b/src/dubbo_config_util.erl
new file mode 100644
index 0000000..c27f694
--- /dev/null
+++ b/src/dubbo_config_util.erl
@@ -0,0 +1,43 @@
+%%%-------------------------------------------------------------------
+%%% @author dlive
+%%% @copyright (C) 2018, <COMPANY>
+%%% @doc
+%%%
+%%% @end
+%%% Created : 05. Jan 2018 12:21 AM
+%%%-------------------------------------------------------------------
+-module(dubbo_config_util).
+-author("dlive").
+
+-include("dubbo.hrl").
+%% API
+-export([gen_consumer/3,gen_provider/5]).
+
+
+gen_consumer(Application,Interface,Option)->
+    #consumer_config{
+        interface = Interface,
+        application = Application,
+        category = <<"consumers">> ,
+        check=false,
+        default_timeout = proplists:get_value(default_timeout,Option,500),
+        dubbo_version= proplists:get_value(dubbo_version,Option,?DUBBO_VERSION),
+        methods=[],
+        revision= <<"">>,
+        side= <<"consumers">>
+    }.
+
+gen_provider(Application,Port,Interface,MethodList,Option)->
+    Host = de_network_tools:local_ipv4_binary(),
+    MethodList2= [atom_to_binary(Item,utf8) || Item <- MethodList ],
+    #provider_config{
+        protocol= <<"dubbo">>,
+        host= Host,
+        port = Port,
+        interface=Interface,
+        anyhost=true,
+        executes=10,
+        application=Application,
+        methods = MethodList2,
+        side= <<"provider">>
+    }.
\ No newline at end of file
diff --git a/src/dubbo_consumer_pool.erl b/src/dubbo_consumer_pool.erl
new file mode 100644
index 0000000..70e4538
--- /dev/null
+++ b/src/dubbo_consumer_pool.erl
@@ -0,0 +1,287 @@
+%%%-------------------------------------------------------------------
+%%% @author dlive
+%%% @copyright (C) 2017, <COMPANY>
+%%% @doc
+%%%
+%%% @end
+%%% Created : 28. Dec 2017 7:34 PM
+%%%-------------------------------------------------------------------
+-module(dubbo_consumer_pool).
+-author("dlive").
+
+-behaviour(gen_server).
+
+%% API
+-export([start_link/0, start_consumer/2]).
+
+%% gen_server callbacks
+-export([init/1,
+    handle_call/3,
+    handle_cast/2,
+    handle_info/2,
+    terminate/2,
+    code_change/3]).
+
+-export([select_connection/1,select_connection/2]).
+
+-include("dubbo.hrl").
+-define(SERVER, ?MODULE).
+
+-define(INTERFCE_LIST_TABLE,interface_list).
+-define(PROVIDER_NODE_LIST_TABLE,provider_node_list).
+
+-record(state, {}).
+
+
+
+%%%===================================================================
+%%% API
+%%%===================================================================
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Starts the server
+%%
+%% @end
+%%--------------------------------------------------------------------
+-spec(start_link() ->
+    {ok, Pid :: pid()} | ignore | {error, Reason :: term()}).
+start_link() ->
+    gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).
+
+%%%===================================================================
+%%% gen_server callbacks
+%%%===================================================================
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Initializes the server
+%%
+%% @spec init(Args) -> {ok, State} |
+%%                     {ok, State, Timeout} |
+%%                     ignore |
+%%                     {stop, Reason}
+%% @end
+%%--------------------------------------------------------------------
+-spec(init(Args :: term()) ->
+    {ok, State :: #state{}} | {ok, State :: #state{}, timeout() | hibernate} |
+    {stop, Reason :: term()} | ignore).
+init([]) ->
+    init_ets_table(),
+    {ok, #state{}}.
+init_ets_table()->
+    try ets:new(?INTERFCE_LIST_TABLE, [bag,public,named_table,{keypos,2}]) of
+        ?INTERFCE_LIST_TABLE ->
+            ok
+    catch
+        _Type:Reason ->
+            lager:error("new ets table error ~p",[Reason]),
+            error
+    end,
+    try ets:new(?PROVIDER_NODE_LIST_TABLE, [bag,public,named_table,{keypos,2}]) of
+        ?PROVIDER_NODE_LIST_TABLE ->
+            ok
+    catch
+        _Type1:Reason1 ->
+            lager:error("new ets table error ~p",[Reason1]),
+            error
+    end,
+    ok.
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Handling call messages
+%%
+%% @end
+%%--------------------------------------------------------------------
+-spec(handle_call(Request :: term(), From :: {pid(), Tag :: term()},
+    State :: #state{}) ->
+    {reply, Reply :: term(), NewState :: #state{}} |
+    {reply, Reply :: term(), NewState :: #state{}, timeout() | hibernate} |
+    {noreply, NewState :: #state{}} |
+    {noreply, NewState :: #state{}, timeout() | hibernate} |
+    {stop, Reason :: term(), Reply :: term(), NewState :: #state{}} |
+    {stop, Reason :: term(), NewState :: #state{}}).
+
+handle_call({add_consumer,Interface,ProviderNodeList}, _From, State) ->
+
+    OldProviderList = get_interface_provider_node(Interface),
+    NewProviderList = add_consumer(ProviderNodeList,[]),
+    DeleteProverList = OldProviderList -- NewProviderList,
+    clean_invalid_provider(DeleteProverList),
+    {reply, ok, State};
+handle_call(_Request, _From, State) ->
+    {reply, ok, State}.
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Handling cast messages
+%%
+%% @end
+%%--------------------------------------------------------------------
+-spec(handle_cast(Request :: term(), State :: #state{}) ->
+    {noreply, NewState :: #state{}} |
+    {noreply, NewState :: #state{}, timeout() | hibernate} |
+    {stop, Reason :: term(), NewState :: #state{}}).
+handle_cast(_Request, State) ->
+    {noreply, State}.
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Handling all non call/cast messages
+%%
+%% @spec handle_info(Info, State) -> {noreply, State} |
+%%                                   {noreply, State, Timeout} |
+%%                                   {stop, Reason, State}
+%% @end
+%%--------------------------------------------------------------------
+-spec(handle_info(Info :: timeout() | term(), State :: #state{}) ->
+    {noreply, NewState :: #state{}} |
+    {noreply, NewState :: #state{}, timeout() | hibernate} |
+    {stop, Reason :: term(), NewState :: #state{}}).
+handle_info(_Info, State) ->
+    {noreply, State}.
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% This function is called by a gen_se  rver when it is about to
+%% terminate. It should be the opposite of Module:init/1 and do any
+%% necessary cleaning up. When it returns, the gen_server terminates
+%% with Reason. The return value is ignored.
+%%
+%% @spec terminate(Reason, State) -> void()
+%% @end
+%%--------------------------------------------------------------------
+-spec(terminate(Reason :: (normal | shutdown | {shutdown, term()} | term()),
+    State :: #state{}) -> term()).
+terminate(_Reason, _State) ->
+    ok.
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Convert process state when code is changed
+%%
+%% @spec code_change(OldVsn, State, Extra) -> {ok, NewState}
+%% @end
+%%--------------------------------------------------------------------
+-spec(code_change(OldVsn :: term() | {down, term()}, State :: #state{},
+    Extra :: term()) ->
+    {ok, NewState :: #state{}} | {error, Reason :: term()}).
+code_change(_OldVsn, State, _Extra) ->
+    {ok, State}.
+
+start_consumer(Interface,ProviderNodeInfo)->
+    gen_server:call(?SERVER,{add_consumer,Interface,ProviderNodeInfo}).
+
+
+%%%===================================================================
+%%% Internal functions
+%%%===================================================================
+add_consumer([],RegisterList)->
+    RegisterList;
+add_consumer([ProviderNodeInfo|ProviderList],RegisterList)->
+    case dubbo_node_config_util:parse_provider_info(ProviderNodeInfo) of
+        {ok,ProviderConfig} ->
+            HostFlag=get_host_flag(ProviderConfig),
+            case ets:lookup(?PROVIDER_NODE_LIST_TABLE,HostFlag) of
+                []->
+                    ConnectionList = start_provider_process(HostFlag,30,ProviderConfig),
+                    ok = update_connection_info(ProviderConfig#provider_config.interface,HostFlag,ConnectionList,true),
+                    ok;
+                List ->
+                    List2 = lists:map(fun(#provider_node_list{connection_info = ConnectionItem })->
+                        ConnectionItem
+                        end,List),
+                    ok = update_connection_info(ProviderConfig#provider_config.interface,HostFlag,List2,false),
+                    ok
+            end,
+            add_consumer(ProviderList,[HostFlag]++RegisterList);
+        {error,R1} ->
+            lager:error("parse provider info error reason ~p",[R1]),
+            add_consumer(ProviderList,RegisterList)
+    end.
+
+start_provider_process(HostFlag,Weight,ProviderConfig) ->
+    ExecutesList=lists:seq(1,ProviderConfig#provider_config.executes),
+    ConnectionList= lists:map(fun(Item) ->
+        ConnectionFlag= << HostFlag/binary,(integer_to_binary(Item))/binary >>,
+        ConnectionFlagTerm= binary_to_atom(ConnectionFlag,utf8),
+        AChild = {ConnectionFlagTerm,{dubbo_netty_client, start_link, [ConnectionFlagTerm,HostFlag,ProviderConfig,Item]}, permanent, 2000, worker, [dubbo_netty_client]},
+        {ok,Pid} = dubbo_consumer_pool_sup:add_children(AChild),
+        lager:info("start provider ~p pid info ~p~n",[HostFlag,Pid]),
+        #connection_info{connection_id = ConnectionFlagTerm,pid = Pid,weight = Weight,host_flag = HostFlag}
+        end,ExecutesList),
+    ConnectionList.
+get_host_flag(ProviderConfig)->
+    HostFlag= << (list_to_binary(ProviderConfig#provider_config.host))/binary,<<"_">>/binary,(integer_to_binary(ProviderConfig#provider_config.port))/binary>>,
+    HostFlag.
+
+update_connection_info(Interface,HostFlag,ConnectionList,IsUpdateProvideNode)->
+    lists:map(fun(Item) ->
+        I1 = ets:insert(?INTERFCE_LIST_TABLE,#interface_list{interface = Interface,connection_info = Item}),
+        lager:debug("save INTERFCE_LIST_TABLE ~p info:~p",[Interface,I1]),
+        case IsUpdateProvideNode of
+            true->
+                I2 = ets:insert(?PROVIDER_NODE_LIST_TABLE,#provider_node_list{host_flag = HostFlag,connection_info = Item }),
+                lager:debug("save PROVIDER_NODE_LIST_TABLE ~p info:~p",[HostFlag,I2]);
+            false->
+                ok
+        end,
+        ok
+              end,ConnectionList),
+    ok.
+
+get_interface_provider_node(Interface)->
+    case ets:lookup(?INTERFCE_LIST_TABLE,Interface) of
+        []->
+            [];
+        List->
+            ListRet = [Item#interface_list.connection_info#connection_info.host_flag || Item <- List],
+            lists_util:del_duplicate(ListRet)
+    end.
+
+select_connection(Interface)->
+    RandNum = rand:uniform(2048),
+    select_connection(Interface,RandNum).
+select_connection(Interface,RandNum)->
+    case ets:lookup(?INTERFCE_LIST_TABLE,Interface) of
+        []->
+            {error,none};
+        List->
+            Len = length(List),
+            RemNum = (RandNum rem Len)+1,
+%%            RandNum2 = if
+%%                           RandNum==Len -> RandNum-1;
+%%                           true->RandNum
+%%                       end,
+            InterfaceListItem = lists:nth(RemNum,List),
+            {ok,InterfaceListItem#interface_list.connection_info}
+    end.
+
+clean_invalid_provider([])->
+    ok;
+clean_invalid_provider([HostFlag | DeleteProverList])->
+    case ets:lookup(?PROVIDER_NODE_LIST_TABLE,HostFlag) of
+        []->
+            ok;
+        ProviderNodeList->
+            io:format("ConnectionList ~p~n",[ProviderNodeList]),
+            ProviderNodeList1 = lists_util:del_duplicate(ProviderNodeList),
+            clean_connection_info(ProviderNodeList1)
+    end,
+    clean_invalid_provider(DeleteProverList).
+
+clean_connection_info(ProviderNodeList)->
+    lists:map(fun(Item)->
+        Pid=Item#provider_node_list.connection_info#connection_info.pid,
+        ConnectionId=Item#provider_node_list.connection_info#connection_info.connection_id,
+        Pattern=#interface_list{pid=Pid,_='_'},
+        ets:delete_object(?INTERFCE_LIST_TABLE,Pattern),
+        dubbo_consumer_pool_sup:stop_children(ConnectionId)
+              end,ProviderNodeList),
+    ok.
\ No newline at end of file
diff --git a/src/dubbo_consumer_pool_sup.erl b/src/dubbo_consumer_pool_sup.erl
new file mode 100644
index 0000000..a1ce87e
--- /dev/null
+++ b/src/dubbo_consumer_pool_sup.erl
@@ -0,0 +1,80 @@
+%%%-------------------------------------------------------------------
+%%% @author dlive
+%%% @copyright (C) 2017, <COMPANY>
+%%% @doc
+%%%
+%%% @end
+%%% Created : 30. Dec 2017 9:58 AM
+%%%-------------------------------------------------------------------
+-module(dubbo_consumer_pool_sup).
+-author("dlive").
+
+-behaviour(supervisor).
+
+%% API
+-export([start_link/0,add_children/1,stop_children/1]).
+
+%% Supervisor callbacks
+-export([init/1]).
+
+-define(SERVER, ?MODULE).
+
+%%%===================================================================
+%%% API functions
+%%%===================================================================
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Starts the supervisor
+%%
+%% @end
+%%--------------------------------------------------------------------
+-spec(start_link() ->
+    {ok, Pid :: pid()} | ignore | {error, Reason :: term()}).
+start_link() ->
+    supervisor:start_link({local, ?SERVER}, ?MODULE, []).
+
+%%%===================================================================
+%%% Supervisor callbacks
+%%%===================================================================
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Whenever a supervisor is started using supervisor:start_link/[2,3],
+%% this function is called by the new process to find out about
+%% restart strategy, maximum restart frequency and child
+%% specifications.
+%%
+%% @end
+%%--------------------------------------------------------------------
+-spec(init(Args :: term()) ->
+    {ok, {SupFlags :: {RestartStrategy :: supervisor:strategy(),
+        MaxR :: non_neg_integer(), MaxT :: non_neg_integer()},
+        [ChildSpec :: supervisor:child_spec()]
+    }} |
+    ignore |
+    {error, Reason :: term()}).
+init([]) ->
+    RestartStrategy = one_for_one,
+    MaxRestarts = 1000,
+    MaxSecondsBetweenRestarts = 3600,
+
+    SupFlags = {RestartStrategy, MaxRestarts, MaxSecondsBetweenRestarts},
+
+    Restart = permanent,
+    Shutdown = 2000,
+    Type = worker,
+
+%%    AChild = {'AName', {'AModule', start_link, []}, Restart, Shutdown, Type, ['AModule']},
+
+    {ok, {SupFlags, []}}.
+
+
+add_children(ChildSpec)->
+    supervisor:start_child(?SERVER,ChildSpec).
+stop_children(ChildID)->
+    supervisor:terminate_child(?SERVER,ChildID).
+%%%===================================================================
+%%% Internal functions
+%%%===================================================================
diff --git a/src/dubbo_directory.erl b/src/dubbo_directory.erl
new file mode 100644
index 0000000..7551d2f
--- /dev/null
+++ b/src/dubbo_directory.erl
@@ -0,0 +1,146 @@
+%%%-------------------------------------------------------------------
+%%% @author dlive
+%%% @copyright (C) 2017, <COMPANY>
+%%% @doc
+%%%
+%%% @end
+%%% Created : 26. Feb 2017 10:27 PM
+%%%-------------------------------------------------------------------
+-module(dubbo_directory).
+-author("dlive").
+
+-behaviour(gen_server).
+
+%% API
+-export([start_link/0]).
+
+%% gen_server callbacks
+-export([init/1,
+    handle_call/3,
+    handle_cast/2,
+    handle_info/2,
+    terminate/2,
+    code_change/3]).
+
+-define(SERVER, ?MODULE).
+
+-record(state, {}).
+
+%%%===================================================================
+%%% API
+%%%===================================================================
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Starts the server
+%%
+%% @end
+%%--------------------------------------------------------------------
+-spec(start_link() ->
+    {ok, Pid :: pid()} | ignore | {error, Reason :: term()}).
+start_link() ->
+    gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).
+
+%%%===================================================================
+%%% gen_server callbacks
+%%%===================================================================
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Initializes the server
+%%
+%% @spec init(Args) -> {ok, State} |
+%%                     {ok, State, Timeout} |
+%%                     ignore |
+%%                     {stop, Reason}
+%% @end
+%%--------------------------------------------------------------------
+-spec(init(Args :: term()) ->
+    {ok, State :: #state{}} | {ok, State :: #state{}, timeout() | hibernate} |
+    {stop, Reason :: term()} | ignore).
+init([]) ->
+    {ok, #state{}}.
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Handling call messages
+%%
+%% @end
+%%--------------------------------------------------------------------
+-spec(handle_call(Request :: term(), From :: {pid(), Tag :: term()},
+    State :: #state{}) ->
+    {reply, Reply :: term(), NewState :: #state{}} |
+    {reply, Reply :: term(), NewState :: #state{}, timeout() | hibernate} |
+    {noreply, NewState :: #state{}} |
+    {noreply, NewState :: #state{}, timeout() | hibernate} |
+    {stop, Reason :: term(), Reply :: term(), NewState :: #state{}} |
+    {stop, Reason :: term(), NewState :: #state{}}).
+handle_call(_Request, _From, State) ->
+    {reply, ok, State}.
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Handling cast messages
+%%
+%% @end
+%%--------------------------------------------------------------------
+-spec(handle_cast(Request :: term(), State :: #state{}) ->
+    {noreply, NewState :: #state{}} |
+    {noreply, NewState :: #state{}, timeout() | hibernate} |
+    {stop, Reason :: term(), NewState :: #state{}}).
+handle_cast(_Request, State) ->
+    {noreply, State}.
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Handling all non call/cast messages
+%%
+%% @spec handle_info(Info, State) -> {noreply, State} |
+%%                                   {noreply, State, Timeout} |
+%%                                   {stop, Reason, State}
+%% @end
+%%--------------------------------------------------------------------
+-spec(handle_info(Info :: timeout() | term(), State :: #state{}) ->
+    {noreply, NewState :: #state{}} |
+    {noreply, NewState :: #state{}, timeout() | hibernate} |
+    {stop, Reason :: term(), NewState :: #state{}}).
+handle_info(_Info, State) ->
+    {noreply, State}.
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% This function is called by a gen_server when it is about to
+%% terminate. It should be the opposite of Module:init/1 and do any
+%% necessary cleaning up. When it returns, the gen_server terminates
+%% with Reason. The return value is ignored.
+%%
+%% @spec terminate(Reason, State) -> void()
+%% @end
+%%--------------------------------------------------------------------
+-spec(terminate(Reason :: (normal | shutdown | {shutdown, term()} | term()),
+    State :: #state{}) -> term()).
+terminate(_Reason, _State) ->
+    ok.
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Convert process state when code is changed
+%%
+%% @spec code_change(OldVsn, State, Extra) -> {ok, NewState}
+%% @end
+%%--------------------------------------------------------------------
+-spec(code_change(OldVsn :: term() | {down, term()}, State :: #state{},
+    Extra :: term()) ->
+    {ok, NewState :: #state{}} | {error, Reason :: term()}).
+code_change(_OldVsn, State, _Extra) ->
+    {ok, State}.
+
+%%%===================================================================
+%%% Internal functions
+%%%===================================================================
diff --git a/src/dubbo_invoker.erl b/src/dubbo_invoker.erl
new file mode 100644
index 0000000..fa4821a
--- /dev/null
+++ b/src/dubbo_invoker.erl
@@ -0,0 +1,96 @@
+%%%-------------------------------------------------------------------
+%%% @author dlive
+%%% @copyright (C) 2018, <COMPANY>
+%%% @doc
+%%%
+%%% @end
+%%% Created : 06. Mar 2018 12:17 AM
+%%%-------------------------------------------------------------------
+-module(dubbo_invoker).
+-author("dlive").
+
+-include("dubbo.hrl").
+%% API
+-export([invoke_request/2,invoke_request/5]).
+
+-spec invoke_request(Interface::binary(),Request::#dubbo_request{})->
+    {ok,reference()}|
+    {ok,reference(),Data::any(),RpcContent::list()}|
+    {error,Reason::timeout|no_provider|any()}.
+invoke_request(Interface,Request)->
+    invoke_request(Interface,Request,[],#{},self()).
+
+-spec invoke_request(Interface::binary(),Request::#dubbo_request{},RpcContext::list(),RequestState::map(),CallBackPid::pid())->
+    {ok,reference()}|
+    {ok,reference(),Data::any(),RpcContent::list()}|
+    {error,Reason::timeout|no_provider|request_full|any()}.
+invoke_request(Interface,Request,RpcContext,RequestState,CallBackPid)->
+    case dubbo_consumer_pool:select_connection(Interface,Request#dubbo_request.mid) of
+        {ok,#connection_info{pid=Pid,host_flag = HostFlag}} ->
+            case dubbo_traffic_control:check_goon(HostFlag,199) of
+                ok ->
+                    Request2 = merge_attachments(Request,RpcContext),
+                    {ok,RequestData} = de_codec:encode_request(Request2),
+                    Ref=get_ref(RequestState),
+                    RequestState2 = request_context:update(<<"t_agent_e">>,RequestState),
+                    gen_server:cast(Pid,{send_request,Ref,Request2,RequestData,CallBackPid,RequestState2}),
+                    case is_sync(RequestState) of
+                        true->
+                            sync_receive(Ref,get_timeout(RequestState));
+                        false-> {ok, Ref}
+                    end;
+                full ->
+                    {error,request_full}
+            end;
+        {error,none}->
+            lager:error("[INVOKE] ~p error Reason no_provider",[Interface]),
+            {error,no_provider};
+        {error,R1}->
+            lager:error("[INVOKE] ~p error Reason ~p",[Interface,R1]),
+            {error,R1}
+    end.
+
+
+is_sync(Option)->
+    maps:is_key(sync,Option).
+%%    lists:member(sync,Option).
+get_ref(Option)->
+    maps:get(ref,Option,make_ref()).
+%%    case maps:is_key(ref,Option) of
+%%        true->
+%%
+%%    end,
+%%    case proplists:get_value(ref,Option) of
+%%        undefined->
+%%            make_ref();
+%%        Ref->
+%%            Ref
+%%    end.
+
+get_timeout(Option)->
+    maps:get(timeout,Option,?REQUEST_TIME_OUT).
+
+
+sync_receive(Ref,TimeOut)->
+    receive
+        {'$gen_cast',{msg_back,Ref,Response,RpcContent}}->
+            {ok,Ref,Response,RpcContent}
+    after
+        TimeOut ->
+            {error,timeout}
+    end.
+
+merge_attachments(Request,Option)->
+    Attachements= Request#dubbo_request.data#dubbo_rpc_invocation.attachments,
+    case lists:keyfind(attachments,1,Option) of
+        false->OptionAttachments=[];
+        {attachments,OptionAttachments}->
+            OptionAttachments
+    end,
+    List=[
+        {<<"version">>, <<"0.0.0">>},
+        {<<"timeout">>, <<"500">>}
+    ],
+    Attachements2= lists:merge3(Attachements,OptionAttachments,List),
+    Data2=Request#dubbo_request.data#dubbo_rpc_invocation{attachments = Attachements2},
+    Request#dubbo_request{data = Data2}.
diff --git a/src/dubbo_netty_client.erl b/src/dubbo_netty_client.erl
new file mode 100644
index 0000000..d5ba464
--- /dev/null
+++ b/src/dubbo_netty_client.erl
@@ -0,0 +1,452 @@
+%%%-------------------------------------------------------------------
+%%% @author dlive
+%%% @copyright (C) 2016, <COMPANY>
+%%% @doc
+%%%
+%%% @end
+%%% Created : 14. 十月 2016 下午3:31
+%%%-------------------------------------------------------------------
+-module(dubbo_netty_client).
+-author("dlive").
+
+-behaviour(gen_server).
+
+-include("dubbo.hrl").
+%% API
+-export([start_link/4]).
+
+%% gen_server callbacks
+-export([init/1,
+    handle_call/3,
+    handle_cast/2,
+    handle_info/2,
+    terminate/2,
+    code_change/3]).
+-export([check_recv_data/2]).
+
+-define(SERVER, ?MODULE).
+
+-record(heartbeat,{last_write=0,last_read=0,timeout=60000,max_timeout=61000}).
+-record(state, {provider_config,socket =undefined,
+    heartbeat=#heartbeat{},
+    recv_buffer= <<>> ,         %%从服务端接收的数据
+    host_flag
+}).
+
+%%%===================================================================
+%%% API
+%%%===================================================================
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Starts the server
+%%
+%% @end
+%%--------------------------------------------------------------------
+-spec(start_link(Name::binary(),HostFlag::binary(),ProviderConfig::#provider_config{},integer()) ->
+    {ok, Pid :: pid()} | ignore | {error, Reason :: term()}).
+start_link(Name,HostFlag,ProviderConfig,Index) ->
+    gen_server:start_link({local, Name}, ?MODULE, [HostFlag,ProviderConfig,Index], []).
+
+%%%===================================================================
+%%% gen_server callbacks
+%%%===================================================================
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Initializes the server
+%%
+%% @spec init(Args) -> {ok, State} |
+%%                     {ok, State, Timeout} |
+%%                     ignore |
+%%                     {stop, Reason}
+%% @end
+%%--------------------------------------------------------------------
+-spec(init(Args :: term()) ->
+    {ok, State :: #state{}} | {ok, State :: #state{}, timeout() | hibernate} |
+    {stop, Reason :: term()} | ignore).
+init([HostFlag,ProviderConfig,Index]) ->
+    erlang:process_flag(min_bin_vheap_size, 1024*1024),
+%%    erlang:process_flag(min_heap_size, 1024*1024),
+%%    BindScheduler = (Index rem erlang:system_info(schedulers_online))+1,
+%%    lager:info("will bind to scheduler ~p",[BindScheduler]),
+%%    erlang:process_flag(scheduler, BindScheduler),
+%%    erlang:process_flag(priority, high),
+
+    #provider_config{host = Host,port = Port}=ProviderConfig,
+    State = case open(Host,Port) of
+                {ok,Socket} ->
+                    #state{socket = Socket};
+                {error}->
+                    #state{}
+    end,
+    NowStamp = time_util:timestamp_ms(),
+    HeartBeatInfo = #heartbeat{last_read = NowStamp,last_write = NowStamp},
+    lager:info("netty client start ~p",[HostFlag]),
+%%    start_heartbeat_timer(HeartBeatInfo),
+    {ok, State#state{provider_config=ProviderConfig,heartbeat=HeartBeatInfo,host_flag = HostFlag}}.
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Handling call messages
+%%
+%% @end
+%%--------------------------------------------------------------------
+-spec(handle_call(Request :: term(), From :: {pid(), Tag :: term()},
+    State :: #state{}) ->
+    {reply, Reply :: term(), NewState :: #state{}} |
+    {reply, Reply :: term(), NewState :: #state{}, timeout() | hibernate} |
+    {noreply, NewState :: #state{}} |
+    {noreply, NewState :: #state{}, timeout() | hibernate} |
+    {stop, Reason :: term(), Reply :: term(), NewState :: #state{}} |
+    {stop, Reason :: term(), NewState :: #state{}}).
+handle_call(_Request, _From, State) ->
+    {reply, ok, State}.
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Handling cast messages
+%%
+%% @end
+%%--------------------------------------------------------------------
+-spec(handle_cast(Request :: term(), State :: #state{}) ->
+    {noreply, NewState :: #state{}} |
+    {noreply, NewState :: #state{}, timeout() | hibernate} |
+    {stop, Reason :: term(), NewState :: #state{}}).
+
+handle_cast({send_request,Ref,Request,Data,SourcePid,RequestState}, State) ->
+    RequestState2 = request_context:update(<<"t_net_b">>,RequestState),
+    lager:debug("[send_request begin] send data to provider consumer mid ~p pid ~p sourcePid ~p",[Request#dubbo_request.mid,self(),SourcePid]),
+    NewState = case send_msg(Data,State) of
+        ok->
+            save_request_info(Request,SourcePid,Ref,RequestState2),
+            lager:debug("[send_request end] send data to provider consumer pid ~p state ok",[self()]),
+            State;
+        {error,closed}->
+            State2 = reconnect(State),
+            State2;
+        {error,R1}->
+            lager:error("[send_request end] send data to provider consumer pid error ~p ~p",[self(),R1]),
+            State
+    end,
+    HeartbeatInfo =update_heartbeat(write,NewState#state.heartbeat),
+    {noreply, NewState#state{heartbeat = HeartbeatInfo}};
+
+handle_cast(_Request, State) ->
+    {noreply, State}.
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Handling all non call/cast messages
+%%
+%% @spec handle_info(Info, State) -> {noreply, State} |
+%%                                   {noreply, State, Timeout} |
+%%                                   {stop, Reason, State}
+%% @end
+%%--------------------------------------------------------------------
+-spec(handle_info(Info :: timeout() | term(), State :: #state{}) ->
+    {noreply, NewState :: #state{}} |
+    {noreply, NewState :: #state{}, timeout() | hibernate} |
+    {stop, Reason :: term(), NewState :: #state{}}).
+
+
+handle_info({tcp,_Port,Data}, #state{recv_buffer = RecvBuffer} = State) ->
+%%    inet:setopts(State#state.socket, [{active, once}]),
+%%    lager:debug("[INFO] recv one data ~w",[Data]),
+    {ok,NextBuffer,NewState} = case check_recv_data(<< RecvBuffer/binary,Data/binary >>,State) of
+                          {next_buffer,NextBuffer2,State3}->
+                              lager:debug("[INFO] recv one data state wait next_buffer"),
+                              {ok,NextBuffer2,State3}
+                      end,
+%%    HeartbeatInfo =update_heartbeat(write,NewState#state.heartbeat),
+    {noreply, NewState#state{recv_buffer = NextBuffer}};
+handle_info({tcp_closed,Port},State)->
+    NewState=reconnect(State),
+    {noreply, NewState};
+handle_info({timeout, _TimerRef, {reconnect}},State)->
+    NewState=reconnect(State),
+    {noreply, NewState};
+handle_info({timeout, _TimerRef, {heartbeat_timer}},State) ->
+    {ok,NewState} = case check_heartbeat_state(State) of
+                        {normal}-> {ok,State};
+                        {send_heart}->
+%% @todo            send_heartbeat_msg(undefined,true,State);
+                            {ok,State};
+                        {reconnect} ->
+                            %% @todo reconnect
+                            {ok,State}
+                    end,
+    HeartbeatInfo = update_heartbeat(write,NewState#state.heartbeat),
+    start_heartbeat_timer(HeartbeatInfo),
+    {noreply,NewState#state{heartbeat = HeartbeatInfo}};
+handle_info(_Info,State) ->
+    lager:warning("[INFO] get one info:~p",[_Info]),
+%%    inet:setopts(State#state.socket, [{active, once}]),
+%%    case State#state.tmp_pid of
+%%        undefined  ->ok;
+%%        Pid ->
+%%            gen_server:cast(Pid,{msg_back})
+%%    end,
+    HeartbeatInfo =update_heartbeat(write,State#state.heartbeat),
+    {noreply, State#state{heartbeat = HeartbeatInfo}}.
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% This function is called by a gen_server when it is about to
+%% terminate. It should be the opposite of Module:init/1 and do any
+%% necessary cleaning up. When it returns, the gen_server terminates
+%% with Reason. The return value is ignored.
+%%
+%% @spec terminate(Reason, State) -> void()
+%% @end
+%%--------------------------------------------------------------------
+-spec(terminate(Reason :: (normal | shutdown | {shutdown, term()} | term()),
+    State :: #state{}) -> term()).
+terminate(_Reason, _State) ->
+    lager:warning("terminate reason:~p",[_Reason]),
+    ok.
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Convert process state when code is changed
+%%
+%% @spec code_change(OldVsn, State, Extra) -> {ok, NewState}
+%% @end
+%%--------------------------------------------------------------------
+-spec(code_change(OldVsn :: term() | {down, term()}, State :: #state{},
+    Extra :: term()) ->
+    {ok, NewState :: #state{}} | {error, Reason :: term()}).
+code_change(_OldVsn, State, _Extra) ->
+    {ok, State}.
+
+%%%===================================================================
+%%% Internal functions
+%%%===================================================================
+
+open(Host,Port)->
+    lager:debug("will connect to provider ~p ~p",[Host,Port]),
+    %
+    case gen_tcp:connect(Host,Port,[
+        binary,
+        {packet,0},{active, false},
+        {reuseaddr,true},
+        {delay_send, true},
+        {nodelay, true},
+        {high_watermark, 512 * 1024},
+        {low_watermark, 256 * 1024},
+%%        {high_msgq_watermark,128 * 1024},
+%%        {low_msgq_watermark,64 * 1024},
+        {sndbuf, 512 * 1024},
+        {recbuf, 512 * 1024}
+        ]) of
+        {ok,Sockets} ->
+%%            inet:setopts(Sockets, [{active, once}]),
+            inet:setopts(Sockets, [{active, true}]),
+            {ok,Sockets};
+        Info ->
+            lager:error("start netty client ~p~n",[Info]),
+            {error,Info}
+    end.
+
+reconnect(State)->
+    #provider_config{host = Host,port = Port} = State#state.provider_config,
+    case State#state.socket of
+        undefined ->ok;
+        Socket->
+            gen_tcp:close(Socket)
+    end,
+    case open(Host,Port) of
+        {ok,Socket2}->
+            State#state{socket = Socket2,recv_buffer = <<>>};
+        {error,_Info}->
+            erlang:start_timer(2000,self(),{reconnect}),
+            State#state{socket = undefined}
+    end.
+
+send_msg(Msg,State) ->
+    case State#state.socket of
+        undefined->
+            {error,closed};
+        Socket ->
+            case gen_tcp:send(Socket,Msg) of
+                ok->
+                    ok;
+                {error,Reason}->
+                    lager:error("send to server error,reason:~p",[Reason]),
+                    {error,Reason}
+            end
+    end.
+
+%%%=================================================================
+%%% 心跳检测
+%%%=================================================================
+start_heartbeat_timer(HeartbeatInfo)->
+    erlang:start_timer(HeartbeatInfo#heartbeat.timeout, self() , {heartbeat_timer}),
+    ok.
+update_heartbeat(write,Info)->
+    Info#heartbeat{last_write = time_util:timestamp_ms()};
+update_heartbeat(read,Info)->
+    Info#heartbeat{last_read = time_util:timestamp_ms()}.
+
+
+check_heartbeat_state(#state{heartbeat = HeartBeatInfo}=_State)->
+    Now = time_util:timestamp_ms(),
+    #heartbeat{last_read = LastRead,last_write = LastWrite,timeout = Timeout,max_timeout = MaxTimeout} = HeartBeatInfo,
+    if
+        (Now - LastRead) > Timeout ->
+            {send_heart};
+        (Now - LastWrite) > Timeout ->
+            {send_heart};
+        (Now - LastRead) > MaxTimeout ->
+            {reconnect};
+        true->
+            {normal}
+    end.
+
+
+send_heartbeat_msg(Mid,NeedResponse,State)->
+    {ok,Bin} = de_heartbeat:generate_request(Mid,NeedResponse),
+    NewState = case send_msg(Bin,State) of
+        ok ->
+            lager:info("send one heartbeat msg to server"),
+            State;
+        {error,_Reason} ->
+            State2 = reconnect(State),
+            State2
+    end,
+    {ok,NewState}.
+
+%%%=================================================================
+%%% 接收数据处理
+%%%=================================================================
+-spec check_recv_data(Data::binary(),State::#state{})->{ready,ReadyData::binary()} | {ready,ReadyData::binary(),NextBuffer::binary()}.
+check_recv_data(<<?DUBBO_MEGIC_HIGH,?DUBBO_MEGIC_LOW,Rest/binary>> = Data,State) when byte_size(Rest)<14 ->
+    {next_buffer,Data,State};
+check_recv_data(<<?DUBBO_MEGIC_HIGH,?DUBBO_MEGIC_LOW,_OtherFlag:80,DataLen:32,Rest/binary>> = Data,State) ->
+    RestSize = byte_size(Rest),
+    if
+        DataLen==RestSize ->
+            {ok,State2} = process_data(Data,State),
+            {next_buffer,<<>>,State2};
+        DataLen>RestSize ->
+            lager:warning("need wait next buffer data ~p",[Data]),
+            {next_buffer,Data,State};
+        DataLen<RestSize ->
+            <<ReadyData:DataLen/binary,NextBuffer/binary>> = Rest,
+            OneData = <<?DUBBO_MEGIC_HIGH:8,?DUBBO_MEGIC_LOW:8,_OtherFlag:80,DataLen:32,ReadyData/binary>>,
+            {ok,State3} = process_data(OneData,State),
+%%            lager:warning("recevi more data ~w ",[NextBuffer]),
+            check_recv_data(NextBuffer,State3)
+    end;
+check_recv_data(<<Error/integer,Data/binary>>,State)->
+    lager:error("recv bad header data,Begin Byte:~p",[Error]),
+    check_recv_data(Data,State);
+check_recv_data(<<>>,State)->
+    {next_buffer,<<>>,State}.
+
+
+process_data(Data,State)->
+    TmpTime = time_util:timestamp_ms(),
+    <<Header:16/binary,RestData/binary>> = Data,
+    case de_codec:decode_header(Header) of
+        {ok,response,ResponseInfo}->
+            %%心跳包的回应,是否会造成错误
+            dubbo_traffic_control:decr_count(State#state.host_flag),
+            case get_earse_request_info(ResponseInfo#dubbo_response.mid) of
+                undefined->
+                    lager:error("dubbo response can't find request data,response ~p",[ResponseInfo]);
+                {SourcePid,Ref,RequestState} ->
+%%                    RequestState2 = request_context:update(<<"t_net_b">>,TmpTime,RequestState),
+                    RequestState3 = request_context:update(<<"t_net_e">>,RequestState),
+
+                    {ok,Res} = de_codec:decode_response(ResponseInfo,RestData),
+
+                    %%从另一条路返回
+%%                    case Res#dubbo_response.is_event of
+%%                        false ->
+%%                            mesh_agent_invoker:response(Ref,Res#dubbo_response.data,RequestState3);
+%%                        _->
+%%                            ok
+%%                    end
+
+            %% 从原路返回
+                    case Res#dubbo_response.is_event of
+                        false ->
+                            gen_server:cast(SourcePid,{response_process,Ref,RequestState3,Res#dubbo_response.data});
+                        _->
+                            ok
+                    end
+%%                    gen_server:cast(SourcePid,{response_process,Ref,ResponseInfo,RestData,RequestState3})
+
+%%            lager:debug("will cast mid ~p to source process SourcePid ~p",[Response#dubbo_response.mid,SourcePid]),
+%%                    RpcContent=[],
+%%            ResponseData = de_type_transfer:response_to_native(Response),
+%%            lager:debug("one response ~p",[Response]),
+%%                    gen_server:cast(SourcePid,{msg_back,Ref,Response,RpcContent,RequestState3})
+            end,
+
+
+
+%%            {ok,Res} = de_codec:decode_response(ResponseInfo,RestData),
+%%            lager:info("get one response mid ~p, is_event ~p state ~p",[Res#dubbo_response.mid,Res#dubbo_response.is_event,Res#dubbo_response.state]),
+%%            {ok,State3} =process_response(Res#dubbo_response.is_event,Res,State,TmpTime),
+            {ok,State};
+        {ok,request,RequestInfo}->
+            {ok,Req} = de_codec:decode_request(RequestInfo,RestData),
+            lager:info("get one request mid ~p, is_event ~p",[Req#dubbo_request.mid,Req#dubbo_request.is_event]),
+            {ok,State2} = process_request(Req#dubbo_request.is_event,Req,State),
+            {ok,State2};
+        {error,Type,RelData}->
+            lager:error("process_data error type ~p RelData ~p",[Type,RelData]),
+            {ok,State}
+    end.
+
+
+%% @doc process event
+-spec process_response(IsEvent::boolean(),#dubbo_response{},#state{},term())->ok.
+process_response(false,Response,State,TmpTime)->
+    dubbo_traffic_control:decr_count(State#state.host_flag),
+    case get_earse_request_info(Response#dubbo_response.mid) of
+        undefined->
+            lager:error("dubbo response can't find request data,response ~p",[Response]);
+        {SourcePid,Ref,RequestState} ->
+%%            RequestState2 = request_context:update(<<"t_net_b">>,TmpTime,RequestState),
+            RequestState3 = request_context:update(<<"t_net_e">>,RequestState),
+%%            lager:debug("will cast mid ~p to source process SourcePid ~p",[Response#dubbo_response.mid,SourcePid]),
+            RpcContent=[],
+%%            ResponseData = de_type_transfer:response_to_native(Response),
+%%            lager:debug("one response ~p",[Response]),
+            gen_server:cast(SourcePid,{msg_back,Ref,Response,RpcContent,RequestState3})
+    end,
+    {ok,State};
+process_response(true,Response,State,TmpTime)->
+
+    {ok,State}.
+
+process_request(true,Request,State)->
+    {ok,NewState} = send_heartbeat_msg(Request#dubbo_request.mid,false,State),
+    {ok,NewState};
+process_request(false,Request,State)->
+    {ok,State}.
+
+
+save_request_info(Request,SourcePid,Ref,RequestState)->
+%%    SaveFlag = get_request_flag(),
+
+    put(Request#dubbo_request.mid,{SourcePid,Ref,RequestState}).
+get_earse_request_info(Mid)->
+%%    Flag=get_request_flag(Mid),
+    erase(Mid).
+
+
+
+
+get_request_flag(Mid)->
+    Mid.
+%%    list_to_binary(io_lib:format(<<"request_~p">>,[Mid])).
\ No newline at end of file
diff --git a/src/dubbo_node_config_util.erl b/src/dubbo_node_config_util.erl
new file mode 100644
index 0000000..f0636e2
--- /dev/null
+++ b/src/dubbo_node_config_util.erl
@@ -0,0 +1,102 @@
+%%%-------------------------------------------------------------------
+%%% @author dlive
+%%% @copyright (C) 2017, <COMPANY>
+%%% @doc
+%%%
+%%% @end
+%%% Created : 30. Dec 2017 2:27 PM
+%%%-------------------------------------------------------------------
+-module(dubbo_node_config_util).
+-author("dlive").
+
+-include("dubbo.hrl").
+%% API
+-export([parse_provider_info/1,gen_provider_info/1]).
+
+%%
+parse_provider_info(ProviderStr)->
+    case http_uri:parse(http_uri:decode(ProviderStr),[{scheme_defaults,[{dubbo,20880}]}]) of
+        {ok, {Scheme, UserInfo, Host, Port, Path, Query}} ->
+            QueryStr = case lists:prefix("?",Query) of
+                true ->
+                    [_|Query2] = Query,
+                    Query2;
+                false->
+                    Query
+            end,
+            QueryListTmp = string:tokens(QueryStr,"&"),
+            ProviderConfig = parse_parameter(QueryListTmp,#provider_config{protocol=Scheme,host=Host,port = Port}),
+            lager:debug("parse provider info string ~p,result: ~p",[ProviderStr,ProviderConfig]),
+            {ok,ProviderConfig};
+        {error,R1} ->
+            lager:debug("parse provider error string ~p, error ~p",[ProviderStr,R1]),
+            {error,R1}
+    end.
+%%    PrivoderInfo =list_to_binary(http_uri:decode(binary_to_list(PrivoderStr))),
+%%    [{ProtocolEndPos,3},{HostEndPos,1},{InterfaceEndPos,1} ] = binary:matches(PrivoderInfo,[<<"://">>,<<"/">>,<<"?">>],[]),
+%%    HostLength=HostEndPos - ProtocolEndPos-3,
+%%    InterfaceLenth=InterfaceEndPos-HostEndPos-1,
+%%    << Protocol:5/binary,_:3/binary,Host:HostLength/binary,_:1/binary,Interface:InterfaceLenth/binary,_:1/binary,Parameter/binary>> = PrivoderInfo,
+%%    [HostName,Port]=binary:split(Host,<<":">>),
+%%    ParameterList = binary:split(Parameter,<<"&">>),
+
+%%    io:format(user,"protocol end Pos ~p~n protocol:~p~n Host:~p~n Interface:~p~n",[ProtocolEndPos,Protocol,Host,Interface]),
+
+parse_parameter([],Config)->
+    Config;
+parse_parameter([Item|Rest],Config)->
+    case string:tokens(Item,"=") of
+        KeyPair when length(KeyPair) ==2 ->
+            [Key,Value] = KeyPair,
+            ConfigNew = parse_parameter(Key,Value,Config),
+            parse_parameter(Rest,ConfigNew);
+        KeyPair2 ->
+            lager:error("parse parameter error, keypair ~p",[KeyPair2]),
+            parse_parameter(Rest,Config)
+    end.
+parse_parameter("anyhost",Value,Config)->
+    Config#provider_config{anyhost = list_to_atom(Value)};
+parse_parameter("application",Value,Config)->
+    Config#provider_config{application = list_to_binary(Value)};
+parse_parameter("dubbo",Value,Config)->
+    Config#provider_config{dubbo = list_to_binary(Value)};
+parse_parameter("executes",Value,Config)->
+    Config#provider_config{executes = list_to_integer(Value)};
+parse_parameter("interface",Value,Config)->
+    Config#provider_config{interface = list_to_binary(Value)};
+parse_parameter("methods",Value,Config)->
+    MethodList= string:tokens(Value,","),
+    MethodList2 = [list_to_binary(Item) || Item <- MethodList],
+    Config#provider_config{methods = MethodList2};
+parse_parameter("side",Value,Config)->
+    Config#provider_config{side = list_to_binary(Value)};
+parse_parameter("interface",Value,Config)->
+    Config#provider_config{interface = list_to_binary(Value)};
+parse_parameter(_,_,Config)->
+    Config.
+
+gen_provider_info(ProviderConfig)->
+    Parameter=gen_provider_parameter(ProviderConfig),
+    Info = io_lib:format("dubbo://~s:~p/~s?~s",[
+        ProviderConfig#provider_config.host,
+        ProviderConfig#provider_config.port,
+        ProviderConfig#provider_config.interface,
+        Parameter
+    ]),
+    list_to_binary(http_uri:encode(Info)).
+
+gen_provider_parameter(Providerconfig) ->
+    Method= [binary_to_list(Item) || Item <- Providerconfig#provider_config.methods],
+    Method2= list_to_binary(string:join(Method,",")),
+    List=[
+        {<<"interface">>,Providerconfig#provider_config.interface},
+        {<<"application">>,Providerconfig#provider_config.application},
+        {<<"anyhost">>, <<"true">>},
+        {<<"dubbo">>,Providerconfig#provider_config.dubbo},
+        {<<"executes">>,integer_to_binary(Providerconfig#provider_config.executes)},
+        {<<"methods">>,Method2},
+        {<<"side">>,Providerconfig#provider_config.side},
+        {<<"timestamp">>,integer_to_binary(time_util:timestamp_ms())}
+    ],
+    List2 = [io_lib:format("~ts=~ts",[Key,Value]) || {Key,Value} <- List],
+    lists:flatten(string:join(List2,"&")).
\ No newline at end of file
diff --git a/src/dubbo_provider_protocol.erl b/src/dubbo_provider_protocol.erl
new file mode 100644
index 0000000..ad6074d
--- /dev/null
+++ b/src/dubbo_provider_protocol.erl
@@ -0,0 +1,200 @@
+%%%-------------------------------------------------------------------
+%%% @author dlive
+%%% @copyright (C) 2018, <COMPANY>
+%%% @doc
+%%%
+%%% @end
+%%% Created : 20. Mar 2018 7:19 PM
+%%%-------------------------------------------------------------------
+-module(dubbo_provider_protocol).
+-author("dlive").
+
+-behaviour(gen_server).
+-behaviour(ranch_protocol).
+-include("dubboerl.hrl").
+-include("dubbo.hrl").
+
+
+%% API
+-export([start_link/4,register_impl_provider/3, select_impl_provider/1]).
+
+%% gen_server callbacks
+-export([init/1,
+    handle_call/3,
+    handle_cast/2,
+    handle_info/2,
+    terminate/2,
+    code_change/3]).
+
+-define(SERVER, ?MODULE).
+
+-define(TIMEOUT, 5000).
+
+-record(heartbeat,{last_write=0,last_read=0,timeout=50000,max_timeout=9000}).
+
+-record(state, {transport,provider_config,socket =undefined,
+    heartbeat=#heartbeat{},
+    recv_buffer= <<>>          %%从客户端接收的数据
+}).
+
+%%%===================================================================
+%%% API
+%%%===================================================================
+
+
+start_link(Ref, Socket, Transport, Opts) ->
+    {ok, proc_lib:spawn_link(?MODULE, init, [{Ref, Socket, Transport, Opts}])}.
+
+%% gen_server.
+
+%% This function is never called. We only define it so that
+%% we can use the -behaviour(gen_server) attribute.
+%init([]) -> {ok, undefined}.
+
+init({Ref, Socket, Transport, _Opts = []}) ->
+    lager:info("provider connected"),
+    ok = ranch:accept_ack(Ref),
+    ok = Transport:setopts(Socket, [{active, once}]),
+    gen_server:enter_loop(?MODULE, [],
+        #state{socket=Socket, transport=Transport},
+        ?TIMEOUT).
+
+handle_info({tcp,_Port,Data}, #state{recv_buffer = RecvBuffer,socket=Socket, transport=Transport} = State) ->
+    Transport:setopts(Socket, [{active, once}]),
+    NowBuffer = << RecvBuffer/binary,Data/binary >>,
+
+    {ok,NextBuffer,NewState} = case check_recv_data(NowBuffer,State) of
+                                   {next_buffer,<<>>,State2} ->
+                                       {ok,<<>>,State2};
+                                   {next_buffer,NextBuffer2,State3}->
+                                       lager:debug("[INFO] recv one data state wait next_buffer"),
+                                       {ok,NextBuffer2,State3}
+                               end,
+%%    HeartbeatInfo =update_heartbeat(write,NewState#state.heartbeat),
+    {noreply, NewState#state{recv_buffer = NextBuffer}};
+handle_info({tcp_closed,Port},State)->
+%%    NewState=reconnect(State),
+    {noreply, State};
+%%handle_info({timeout, _TimerRef, {reconnect}},State)->
+%%    NewState=reconnect(State),
+%%    {noreply, NewState};
+
+handle_info({tcp_closed, _Socket}, State) ->
+    {stop, normal, State};
+handle_info({tcp_error, _, Reason}, State) ->
+    {stop, Reason, State};
+handle_info(timeout, State) ->
+    {stop, normal, State};
+handle_info(_Info, State) ->
+    {stop, normal, State}.
+
+handle_call(_Request, _From, State) ->
+    {reply, ok, State}.
+
+handle_cast({send_response,Data}, #state{socket = Socket} = State) ->
+    case gen_tcp:send(Socket,Data) of
+        ok ->
+            ok;
+        Other ->
+            lager:warning("response error ~p",[Other])
+    end,
+    {noreply, State};
+handle_cast(_Msg, State) ->
+    {noreply, State}.
+
+terminate(_Reason, _State) ->
+    ok.
+
+code_change(_OldVsn, State, _Extra) ->
+    {ok, State}.
+
+
+register_impl_provider(Interface,ImplModuleName,ModuleName)->
+    ets:insert(?PROVIDER_IMPL_TABLE,{Interface,ImplModuleName,ModuleName}),
+    ok.
+
+-spec select_impl_provider(Interface::binary()) ->{ok,binary()} | {error,term()}.
+select_impl_provider(Interface) ->
+    case ets:lookup(?PROVIDER_IMPL_TABLE,Interface) of
+        []->
+            {error,no_provider};
+        [{Interface,ImplModuleName,ModuleName}] ->
+            {ok,ImplModuleName}
+    end.
+
+
+
+%%%=================================================================
+%%% 接收数据处理
+%%%=================================================================
+-spec check_recv_data(Data::binary(),State::#state{})->{ready,ReadyData::binary()} | {ready,ReadyData::binary(),NextBuffer::binary()}.
+check_recv_data(<<?DUBBO_MEGIC_HIGH,?DUBBO_MEGIC_LOW,Rest/binary>> = Data,State) when byte_size(Rest)<14 ->
+    {next_buffer,Data,State};
+check_recv_data(<<?DUBBO_MEGIC_HIGH,?DUBBO_MEGIC_LOW,_OtherFlag:80,DataLen:32,Rest/binary>> = Data,State) ->
+    RestSize = byte_size(Rest),
+    if
+        DataLen==RestSize ->
+            {ok,State2} = process_data(Data,State),
+            {next_buffer,<<>>,State2};
+        DataLen>RestSize ->
+            lager:warning("need wait next buffer data ~p",[Data]),
+            {next_buffer,Data,State};
+        DataLen<RestSize ->
+            <<ReadyData:DataLen/binary,NextBuffer/binary>> = Rest,
+            OneData = <<?DUBBO_MEGIC_HIGH:8,?DUBBO_MEGIC_LOW:8,_OtherFlag:80,DataLen:32,ReadyData/binary>>,
+            {ok,State3} = process_data(OneData,State),
+            lager:warning("recevi more data ~w ",[NextBuffer]),
+            check_recv_data(NextBuffer,State3)
+    end;
+check_recv_data(<<Error/integer,Data/binary>>,State)->
+    lager:error("recv bad header data,Begin Byte:~p",[Error]),
+    check_recv_data(Data,State);
+check_recv_data(<<>>,State)->
+    {next_buffer,<<>>,State}.
+
+
+process_data(Data,State)->
+    <<Header:16/binary,RestData/binary>> = Data,
+    case de_codec:decode_header(Header) of
+        {ok,request,RequestInfo}->
+            {ok,Req} = de_codec:decode_request(RequestInfo,RestData),
+            lager:info("get one request mid ~p, is_event ~p",[Req#dubbo_request.mid,Req#dubbo_request.is_event]),
+            {ok,State2} = process_request(Req#dubbo_request.is_event,Req,State),
+            {ok,State2};
+        {ok,response,ResponseInfo}->
+            {ok,Res} = de_codec:decode_response(ResponseInfo,RestData),
+            lager:info("get one response mid ~p, is_event ~p state ~p",[Res#dubbo_response.mid,Res#dubbo_response.is_event,Res#dubbo_response.state]),
+            {ok,State3} =process_response(Res#dubbo_response.is_event,Res,State),
+            {ok,State3};
+        {error,Type,RelData}->
+            lager:error("process_data error type ~p RelData ~p",[Type,RelData]),
+            {ok,State}
+    end.
+
+
+%% @doc process event
+-spec process_response(IsEvent::boolean(),#dubbo_response{},#state{})->ok.
+process_response(true,Response,State)->
+
+    {ok,State};
+
+process_response(false,Response,State)->
+%%    case get_earse_request_info(Response#dubbo_response.mid) of
+%%        undefined->
+%%            lager:error("dubbo response can't find request data,response ~p",[Response]);
+%%        {SourcePid,Ref,Request} ->
+%%            lager:debug("will cast mid ~p to source process SourcePid ~p",[Response#dubbo_response.mid,SourcePid]),
+%%            RpcContent=[],
+%%            ResponseData = de_type_transfer:response_to_native(Response),
+%%            gen_server:cast(SourcePid,{msg_back,Ref,ResponseData,RpcContent})
+%%    end,
+    {ok,State}.
+
+process_request(true,Request,State)->
+%%    {ok,NewState} = send_heartbeat_msg(Request#dubbo_request.mid,State),
+    lager:info("process request event ~p",[Request]),
+    {ok,State};
+process_request(false,Request,State)->
+    lager:info("process request ~p",[Request]),
+    dubbo_provider_worker:process_request(Request,self()),
+    {ok,State}.
\ No newline at end of file
diff --git a/src/dubbo_provider_worker.erl b/src/dubbo_provider_worker.erl
new file mode 100644
index 0000000..00d299e
--- /dev/null
+++ b/src/dubbo_provider_worker.erl
@@ -0,0 +1,198 @@
+%%%-------------------------------------------------------------------
+%%% @author dlive
+%%% @copyright (C) 2018, <COMPANY>
+%%% @doc
+%%%
+%%% @end
+%%% Created : 11. Mar 2018 8:08 PM
+%%%-------------------------------------------------------------------
+-module(dubbo_provider_worker).
+-author("dlive").
+
+-behaviour(gen_server).
+
+%% API
+-export([start_link/1,process_request/2]).
+
+%% gen_server callbacks
+-export([init/1,
+    handle_call/3,
+    handle_cast/2,
+    handle_info/2,
+    terminate/2,
+    code_change/3]).
+
+-define(SERVER, ?MODULE).
+-include("dubbo.hrl").
+-include("dubboerl.hrl").
+-include("dubbo_type.hrl").
+
+-record(heartbeat,{last_write=0,last_read=0,timeout=50000,max_timeout=9000}).
+-record(state, {provider_config,socket =undefined,
+    heartbeat=#heartbeat{},
+    recv_buffer= <<>>          %%从客户端接收的数据
+}).
+
+%%%===================================================================
+%%% API
+%%%===================================================================
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Starts the server
+%%
+%% @end
+%%--------------------------------------------------------------------
+-spec(start_link(term()) ->
+    {ok, Pid :: pid()} | ignore | {error, Reason :: term()}).
+start_link(Args) ->
+    gen_server:start_link(?MODULE, Args, []).
+
+%%%===================================================================
+%%% gen_server callbacks
+%%%===================================================================
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Initializes the server
+%%
+%% @spec init(Args) -> {ok, State} |
+%%                     {ok, State, Timeout} |
+%%                     ignore |
+%%                     {stop, Reason}
+%% @end
+%%--------------------------------------------------------------------
+-spec(init(Args :: term()) ->
+    {ok, State :: #state{}} | {ok, State :: #state{}, timeout() | hibernate} |
+    {stop, Reason :: term()} | ignore).
+init(Args) ->
+    process_flag(trap_exit, true),
+    {ok, #state{}}.
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Handling call messages
+%%
+%% @end
+%%--------------------------------------------------------------------
+-spec(handle_call(Request :: term(), From :: {pid(), Tag :: term()},
+    State :: #state{}) ->
+    {reply, Reply :: term(), NewState :: #state{}} |
+    {reply, Reply :: term(), NewState :: #state{}, timeout() | hibernate} |
+    {noreply, NewState :: #state{}} |
+    {noreply, NewState :: #state{}, timeout() | hibernate} |
+    {stop, Reason :: term(), Reply :: term(), NewState :: #state{}} |
+    {stop, Reason :: term(), NewState :: #state{}}).
+handle_call(_Request, _From, State) ->
+    {reply, ok, State}.
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Handling cast messages
+%%
+%% @end
+%%--------------------------------------------------------------------
+-spec(handle_cast(Request :: term(), State :: #state{}) ->
+    {noreply, NewState :: #state{}} |
+    {noreply, NewState :: #state{}, timeout() | hibernate} |
+    {stop, Reason :: term(), NewState :: #state{}}).
+handle_cast({request,Request,SourcePid},State)->
+%%    #dubbo_request{mid=Mid} = Request,
+
+%%    Data = #databaseOperateResponse{databaseOperateRsp = "ha-ha"},
+%%    Data2 =#dubbo_rpc_invocation{parameters = [Data]},
+%%    {ok,Content }= de_codec:encode_response(#dubbo_response{mid=Mid,is_event = false,data= Data2}),
+    {ok,Content} = invoker_implement(Request),
+    gen_server:cast(SourcePid,{send_response,Content}),
+
+    {noreply, State};
+handle_cast(_Request, State) ->
+    {noreply, State}.
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Handling all non call/cast messages
+%%
+%% @spec handle_info(Info, State) -> {noreply, State} |
+%%                                   {noreply, State, Timeout} |
+%%                                   {stop, Reason, State}
+%% @end
+%%--------------------------------------------------------------------
+-spec(handle_info(Info :: timeout() | term(), State :: #state{}) ->
+    {noreply, NewState :: #state{}} |
+    {noreply, NewState :: #state{}, timeout() | hibernate} |
+    {stop, Reason :: term(), NewState :: #state{}}).
+
+
+handle_info(_Info, State) ->
+    {noreply, State}.
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% This function is called by a gen_server when it is about to
+%% terminate. It should be the opposite of Module:init/1 and do any
+%% necessary cleaning up. When it returns, the gen_server terminates
+%% with Reason. The return value is ignored.
+%%
+%% @spec terminate(Reason, State) -> void()
+%% @end
+%%--------------------------------------------------------------------
+-spec(terminate(Reason :: (normal | shutdown | {shutdown, term()} | term()),
+    State :: #state{}) -> term()).
+terminate(_Reason, _State) ->
+    ok.
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Convert process state when code is changed
+%%
+%% @spec code_change(OldVsn, State, Extra) -> {ok, NewState}
+%% @end
+%%--------------------------------------------------------------------
+-spec(code_change(OldVsn :: term() | {down, term()}, State :: #state{},
+    Extra :: term()) ->
+    {ok, NewState :: #state{}} | {error, Reason :: term()}).
+code_change(_OldVsn, State, _Extra) ->
+    {ok, State}.
+
+
+process_request(Request,SourcePid)->
+    Worker = poolboy:checkout(?PROVIDER_WORKER),
+    try
+        gen_server:cast(Worker,{request,Request,SourcePid})
+    after
+        ok = poolboy:checkin(?PROVIDER_WORKER, Worker)
+    end.
+
+%%%===================================================================
+%%% Internal functions
+%%%===================================================================
+
+-spec invoker_implement(#dubbo_request{})-> {ok,response_content()}.
+invoker_implement(Request)->
+    #dubbo_rpc_invocation{className = Interface,methodName = MethodName,parameters = Parameters} = Request#dubbo_request.data,
+    case dubbo_provider_protocol:select_impl_provider(Interface) of
+        {ok,ImplModule}->
+            case apply(ImplModule,binary_to_atom(MethodName,latin1),Parameters) of
+                {error}->
+                    ok;
+                #dubbo_rpc_invocation{}=ResultInvoca ->
+                    #dubbo_request{mid = Mid} = Request,
+                    {ok,Content }= de_codec:encode_response(#dubbo_response{mid=Mid,is_event = false,data= ResultInvoca}),
+                    {ok,Content};
+                ResultObj->
+%%                    Data = #databaseOperateResponse{databaseOperateRsp = "ha-ha"},
+                    #dubbo_request{mid = Mid} = Request,
+                    Data2 =#dubbo_rpc_invocation{parameters = [ResultObj]},
+                    {ok,Content }= de_codec:encode_response(#dubbo_response{mid=Mid,is_event = false,data= Data2}),
+                    {ok,Content}
+            end;
+        {error,Reason}  ->
+            {error,Reason}
+    end.
\ No newline at end of file
diff --git a/src/dubbo_provider_worker_sup.erl b/src/dubbo_provider_worker_sup.erl
new file mode 100644
index 0000000..0b5708f
--- /dev/null
+++ b/src/dubbo_provider_worker_sup.erl
@@ -0,0 +1,85 @@
+%%%-------------------------------------------------------------------
+%%% @author dlive
+%%% @copyright (C) 2018, <COMPANY>
+%%% @doc
+%%%
+%%% @end
+%%% Created : 11. Mar 2018 8:04 PM
+%%%-------------------------------------------------------------------
+-module(dubbo_provider_worker_sup).
+-author("dlive").
+
+-behaviour(supervisor).
+
+%% API
+-export([start_link/0]).
+
+%% Supervisor callbacks
+-export([init/1]).
+-define(SERVER, ?MODULE).
+
+%%%===================================================================
+%%% API functions
+%%%===================================================================
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Starts the supervisor
+%%
+%% @end
+%%--------------------------------------------------------------------
+-spec(start_link() ->
+    {ok, Pid :: pid()} | ignore | {error, Reason :: term()}).
+start_link() ->
+    supervisor:start_link({local, ?SERVER}, ?MODULE, []).
+
+%%%===================================================================
+%%% Supervisor callbacks
+%%%===================================================================
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Whenever a supervisor is started using supervisor:start_link/[2,3],
+%% this function is called by the new process to find out about
+%% restart strategy, maximum restart frequency and child
+%% specifications.
+%%
+%% @end
+%%--------------------------------------------------------------------
+-spec(init(Args :: term()) ->
+    {ok, {SupFlags :: {RestartStrategy :: supervisor:strategy(),
+        MaxR :: non_neg_integer(), MaxT :: non_neg_integer()},
+        [ChildSpec :: supervisor:child_spec()]
+    }} |
+    ignore |
+    {error, Reason :: term()}).
+init([]) ->
+    RestartStrategy = one_for_one,
+    MaxRestarts = 1000,
+    MaxSecondsBetweenRestarts = 3600,
+
+    SupFlags = {RestartStrategy, MaxRestarts, MaxSecondsBetweenRestarts},
+
+    Restart = permanent,
+    Shutdown = 2000,
+    Type = worker,
+
+    AChild = {'AName', {'AModule', start_link, []},
+        Restart, Shutdown, Type, ['AModule']},
+
+    PoolArgs = [{name, {local, provider_worker}},
+        {worker_module, dubbo_provider_worker},
+        {size, 5},
+        {max_overflow, 100}
+    ],
+    WorkerPool = poolboy:child_spec(provider_worker, PoolArgs, []),
+    {ok, {SupFlags, [WorkerPool]}}.
+
+%%%===================================================================
+%%% Internal functions
+%%%===================================================================
+%%start_child(InterfaceList)->
+%%    ChildSpec = {dubbo_provider_server,{dubbo_provider_server,start_link,[InterfaceList]},permanent,2000,worker},
+%%    supervisor:start_child(?SERVER,ChildSpec),
+%%    ok.
\ No newline at end of file
diff --git a/src/dubbo_serializa_fastjson.erl b/src/dubbo_serializa_fastjson.erl
new file mode 100644
index 0000000..819a118
--- /dev/null
+++ b/src/dubbo_serializa_fastjson.erl
@@ -0,0 +1,295 @@
+%%%-------------------------------------------------------------------
+%%% @author dlive
+%%% @copyright (C) 2018, <COMPANY>
+%%% @doc
+%%%
+%%% @end
+%%% Created : 11. May 2018 10:07 AM
+%%%-------------------------------------------------------------------
+-module(dubbo_serializa_fastjson).
+-author("dlive").
+
+-include("dubbo.hrl").
+%% API
+-export([encode_request_data/1,decode_response/2,decode_request/2]).
+
+-export([decode_header/1]).
+-export([decode_request/2]).
+
+encode_request_data(Request)->
+    DataType =case Request#dubbo_request.is_event of
+                  false->
+                      case Request#dubbo_request.data of
+                          #dubbo_rpc_invocation{} ->
+                              dubbo_rpc_invocation;
+                          _ ->
+                              unknow
+                      end;
+                  true->
+                      dubbo_event
+              end,
+    {ok,Bin} = encode_request_data(DataType,Request,Request#dubbo_request.data,[]),
+    {ok,Bin}.
+
+
+encode_request_data(dubbo_rpc_invocation,Request,Data,State) ->
+%%    METHOD_NAME = Data#dubbo_rpc_invocation.methodName,
+%%    METHOD_ARGS_TYPES = Data#dubbo_rpc_invocation.parameterDesc,
+    RequestList = [
+%%        jiffy:encode(?DUBBO_VERSION,[]),
+        string_encode(?DUBBO_VERSION),
+        ?LINE_SEPERATOR,
+%%        jiffy:encode(Data#dubbo_rpc_invocation.className,[]),
+        string_encode(Data#dubbo_rpc_invocation.className),
+        ?LINE_SEPERATOR,
+%%        jiffy:encode(Data#dubbo_rpc_invocation.classVersion,[]),
+        string_encode(Data#dubbo_rpc_invocation.classVersion),
+        ?LINE_SEPERATOR,
+%%        jiffy:encode(Data#dubbo_rpc_invocation.methodName,[]),
+        string_encode(Data#dubbo_rpc_invocation.methodName),
+        ?LINE_SEPERATOR,
+%%        jiffy:encode(Data#dubbo_rpc_invocation.parameterDesc,[]),
+        string_encode(Data#dubbo_rpc_invocation.parameterDesc),
+        ?LINE_SEPERATOR
+%%
+%%        hessianEncode:encode(?DUBBO_VERSION, State), %% dubbo version
+%%        hessianEncode:encode(Data#dubbo_rpc_invocation.className, State),
+%%        hessianEncode:encode(Data#dubbo_rpc_invocation.classVersion, State),
+%%        hessianEncode:encode(METHOD_NAME, State),
+%%        hessianEncode:encode(METHOD_ARGS_TYPES, State)
+    ],
+    {ArgsBin,_} = encode_arguments(Data,State),
+%%    AttachDict = dict:from_list(Data#dubbo_rpc_invocation.attachments),
+%%    AttachMaps = #map{dict = AttachDict },
+%%    AttachBinay = hessianEncode:encode(AttachMaps, State2),
+    AttachBinay = jiffy:encode({Data#dubbo_rpc_invocation.attachments},[]),
+    RequestData = erlang:iolist_to_binary(RequestList ++ [ArgsBin,AttachBinay,?LINE_SEPERATOR]),
+    {ok,RequestData};
+encode_request_data(dubbo_event,Request,Data,State) ->
+    %% @todo 确认该数据类型
+    Bin =  jiffy:encode(Data),
+%%    Bin = hessianEncode:encode(Data,State),
+    {ok,Bin}.
+
+
+-spec encode_response(#dubbo_response{})-> {ok,term()}.
+encode_response(Response)->
+    {ok,ResponseData} = encode_response_data(Response),
+    Size = byte_size(ResponseData),
+    Header = encode_response_header(Response,Size,?RESPONSE_STATE_OK),
+    ResponseContent = <<Header/binary,ResponseData/binary>>,
+    {ok, ResponseContent}.
+
+encode_response_data(Response)->
+    State=type_encoding:init(),
+    DataType =case Response#dubbo_response.is_event of
+                  true->
+                      dubbo_event;
+                  false->
+                      case Response#dubbo_response.data of
+                          #dubbo_rpc_invocation{} ->
+                              dubbo_rpc_invocation;
+                          _ ->
+                              unknow
+                      end
+              end,
+    {ok,Bin} = encode_response_data(DataType,Response,Response#dubbo_response.data,State),
+    {ok,Bin}.
+encode_response_data(dubbo_event,Response,Data,State) ->
+    Bin = hessianEncode:encode(Data,State),
+    {ok,Bin};
+encode_response_data(dubbo_rpc_invocation,Response,Data,State) ->
+    Result = case Data of
+                 null ->
+                     [
+                         hessianEncode:encode(?RESPONSE_NULL_VALUE, State)
+                     ];
+                 _ ->
+                     {ArgsBin,_State2} = encode_arguments(Data,State),
+                     [
+                         hessianEncode:encode(?RESPONSE_VALUE, State),
+                         ArgsBin
+                     ]
+             end,
+    ResponseData = erlang:iolist_to_binary(Result),
+    {ok,ResponseData}.
+
+encode_response_header(Response,DataLen, ResponseState)->
+    Header2= Response#dubbo_response.serialize_type,
+    Header21=case Response#dubbo_response.is_twoway of
+                 true -> Header2 bor 64;
+                 false-> Header2
+             end,
+    Header22=case Response#dubbo_response.is_event of
+                 true -> Header21 bor 32;
+                 false-> Header21
+             end,
+    RequestId = Response#dubbo_response.mid,
+    Header = << ?DUBBO_MEGIC:16,Header22:8, ResponseState:8,RequestId:64,DataLen:32>>,
+    Header.
+encode_arguments(Data,State)->
+    {Bin} = lists:foldl(
+        fun(X,{BinTmp})->
+            ArgsBin = string_encode(X),
+            {<<BinTmp/binary,ArgsBin/binary ,?LINE_SEPERATOR/binary>>}
+        end,
+        {<<>>},Data#dubbo_rpc_invocation.parameters),
+    {Bin,State}.
+
+-spec decode_header(binary())-> {State::ok|error,Type::request|response,Data::#dubbo_response{}|#dubbo_request{}}.
+decode_header(Header)->
+    <<?DUBBO_MEGIC_HIGH,?DUBBO_MEGIC_LOW,Flag:8,State:8,Mid:64,DataLen:32>> = Header,
+    if
+        (Flag band 16#80) == 0 ->
+            {DecodeState,Res} = decode_header(response,Flag,State,Mid,DataLen),
+            {DecodeState,response,Res};
+        true ->
+            {DecodeState,Req} = decode_header(request,Flag,State,Mid,DataLen),
+            {DecodeState,request,Req}
+    end.
+decode_header(request,Flag,State,Mid,DataLen)->
+    SerializeType = Flag band 16#1f,
+    IsTwoWay = if
+                   (Flag band 16#40) /=0 -> true;
+                   true -> false
+               end,
+    IsEvent = if
+                  (Flag band 16#20) /=0 -> true;
+                  true -> false
+              end,
+    Req = #dubbo_request{
+        is_event = IsEvent,
+        is_twoway = IsTwoWay,
+        mid = Mid,
+        mversion = <<"2.0.0">>,
+        serialize_type = SerializeType
+    },
+    {ok,Req};
+decode_header(response,Flag,State,Mid,DataLen)->
+    SerializeType = Flag band 16#1f,
+    IsEvent = if
+                  (Flag band 16#20) /= 0 -> true;
+                  true -> false
+              end,
+    Res = #dubbo_response{is_event = IsEvent,
+        serialize_type = SerializeType,
+        state = State,
+        mid = Mid
+    },
+    {ok,Res}.
+
+-spec decode_response(#dubbo_response{},binary())-> {ok,#dubbo_response{}}.
+decode_response(Res,Data)->
+    if
+        Res#dubbo_response.is_event == true ->
+            decode_response(dubbo_event,Res,Data);
+        true ->
+            decode_response(dubbo_rpc_invocation,Res,Data)
+    end.
+decode_response(dubbo_rpc_invocation,Res,Data)->
+    DataList = binary:split(Data,<<"\n">>),
+    [TypeBin | DataList1] = DataList,
+%%    {Rest,Type,State} = hessianDecode2:decode(Data,hessianDecode2:init()),
+    Type = jiffy:decode(TypeBin),
+
+    case Type of
+        ?RESPONSE_VALUE ->
+%%            {_,Object,DecodeState} = hessianDecode2:decode(Rest,State),
+            [Value | _] = DataList1,
+            Object = jiffy:decode(Value),
+            {ok,Res#dubbo_response{data = Object}};
+        ?RESPONSE_NULL_VALUE ->
+            {ok,Res#dubbo_response{data = null}};
+        ?RESPONSE_WITH_EXCEPTION ->
+            [ExceptionValue | _] = DataList1,
+            ExceptionObject = jiffy:decode(ExceptionValue),
+%%            lager:warning("decode unkonw type ~p ~p",[Type,Rest]),
+%%            {Rest2,Object2,DecodeState2} = hessianDecode2:decode(Rest,State),
+%%            lager:warning("decode unkonw type2 ~p ~p",[Object2,Rest2]),
+            {ok,Res#dubbo_response{data = ExceptionObject}};
+        Other ->
+            lager:error("server response unkonw info ~p",[Other]),
+            {ok,Res#dubbo_response{data = <<"server pool exhausted">>}}
+
+    end;
+decode_response(dubbo_event,Res,Data)->
+%%    {_Rest,undefined,_NewState} = hessianDecode2:decode(Data,hessianDecode2:init()),
+    {ok,Res#dubbo_response{data = null}}.
+
+-spec decode_request(#dubbo_request{},binary())-> {ok,#dubbo_request{}}.
+decode_request(Req,Data)->
+    if
+        Req#dubbo_request.is_event == true ->
+            decode_request(dubbo_event,Req,Data);
+        true ->
+            decode_request(dubbo_rpc_invocation,Req,Data)
+    end.
+
+decode_request(dubbo_rpc_invocation,Req,Data)->
+    {ResultList,NewState,RestData} = decode_request_body(Data,hessianDecode2:init(),[dubbo,path,version,method_name,desc_and_args,attachments]),
+    [DubboVersion,Path,Version,MethodName,Desc,ArgsObj,Attachments]=ResultList,
+    RpcData = #dubbo_rpc_invocation{className = Path,classVersion = Version,methodName = MethodName,parameterDesc = Data,parameters = ArgsObj,attachments = Attachments},
+    Req2 = Req#dubbo_request{data = RpcData},
+    {ok,Req2};
+%%    {Rest,Dubbo,State} = hessianDecode2:decode(Data,hessianDecode2:init()),
+%%    {Rest1,ClassName,State1} = hessianDecode2:decode(Data,State),
+%%    {Rest2,ClassName,State2} = hessianDecode2:decode(Rest1,State1),
+%%    case Type of
+%%        1 ->
+%%            {_,Object,DecodeState} = hessianDecode2:decode(Rest,State),
+%%            {ok,Req#dubbo_request{data = Object,decode_state = DecodeState}};
+%%        2 ->
+%%            {ok,Req#dubbo_request{data = null,decode_state = State}};
+%%        _->
+%%            lager:warning("decode unkonw type ~p ~p",[Type,Rest]),
+%%            {Rest2,Object2,DecodeState2} = hessianDecode2:decode(Rest,State),
+%%            lager:warning("decode unkonw type2 ~p ~p",[Object2,Rest2]),
+%%            {ok,Req#dubbo_request{data = Object2,decode_state = DecodeState2}}
+%%    end;
+decode_request(dubbo_event,Req,Data)->
+%%    DataList = binary:split(Data,<<"\n">>),
+    lager:debug("dubbo_event datalist ~w",[Data]),
+    Result = jiffy:decode(Data,[]),
+%%    {_Rest,undefined,_NewState} = hessianDecode2:decode(Data,hessianDecode2:init()),
+    {ok,Req#dubbo_request{data = Result}}.
+
+decode_request_body(Data,State,List)->
+    {ResultList,NewState,RestData} = decode_request_body(List,Data,State,[]),
+    {lists:reverse(ResultList),NewState,RestData}.
+decode_request_body([ParseType|List],Data,State,ResultList)
+    when ParseType==dubbo;ParseType==path;ParseType==version;ParseType==method_name ->
+    {Rest,Result,NewState } = hessianDecode2:decode(Data,State),
+    decode_request_body(List,Rest,NewState, [Result] ++ ResultList);
+decode_request_body([desc_and_args| List],Data,State,ResultList)->
+    {Rest,ParameterDesc,State1 } = hessianDecode2:decode(Data,State),
+    if
+        size(ParameterDesc) == 0 ->
+            decode_request_body(List,Rest,State1, [ [],[] ]++ ResultList);
+        true ->
+            ParameterDescArray = binary:split(ParameterDesc,<<";">>),
+            {ArgsObjList,NewState,RestData} = decode_request_body_args(ParameterDescArray,Rest,State1,[]),
+            decode_request_body(List,RestData,NewState, [ArgsObjList,ParameterDesc]++ ResultList)
+    end;
+decode_request_body([attachments|List],Data,State,ResultList)->
+    {Rest,Attachments,State1 } = hessianDecode2:decode(Data,State),
+    AttachmentsList = dict:to_list(Attachments#map.dict),
+    decode_request_body(List,Rest,State1,[AttachmentsList] ++ ResultList);
+decode_request_body([_Type1|List],Data,State,ResultList)->
+    lager:warning("decode_request_body unknow type"),
+    decode_request_body(List,Data,State, ResultList);
+decode_request_body([],Data,State,ResultList)->
+    {ResultList,State,Data}.
+
+decode_request_body_args([],Data,State,ArgsObjList)->
+    {ArgsObjList,State,Data};
+decode_request_body_args([ArgsType|RestList],Data,State,ArgsObjList) when ArgsType== <<>> ->
+    decode_request_body_args(RestList,Data,State,ArgsObjList);
+decode_request_body_args([_ArgsType|RestList],Data,State,ArgsObjList) ->
+    {Rest,ArgObj,NewState } = hessianDecode2:decode(Data,State),
+    ArgObj2 = de_type_transfer:classobj_to_native(ArgObj,NewState),
+    decode_request_body_args(RestList,Rest,NewState,ArgsObjList++[ArgObj2]).
+
+string_encode(Data) when is_binary(Data)->
+    << <<"\"">>/binary,Data/binary,<<"\"">>/binary >>;
+string_encode(Data)->
+    jiffy:encode(Data).
diff --git a/src/dubbo_serializa_hession.erl b/src/dubbo_serializa_hession.erl
new file mode 100644
index 0000000..1e622fb
--- /dev/null
+++ b/src/dubbo_serializa_hession.erl
@@ -0,0 +1,246 @@
+%%%-------------------------------------------------------------------
+%%% @author dlive
+%%% @copyright (C) 2018, <COMPANY>
+%%% @doc
+%%%
+%%% @end
+%%% Created : 11. May 2018 4:12 PM
+%%%-------------------------------------------------------------------
+-module(dubbo_serializa_hession).
+-author("dlive").
+
+-include("dubbo.hrl").
+%% API
+-export([decode_header/1]).
+-export([decode_response/2]).
+-export([decode_request/2]).
+
+
+encode_request_data(dubbo_event,Request,Data,State) ->
+    Bin = hessianEncode:encode(Data,State),
+    {ok,Bin};
+encode_request_data(dubbo_rpc_invocation,Request,Data,State) ->
+    METHOD_NAME = Data#dubbo_rpc_invocation.methodName,
+    METHOD_ARGS_TYPES = Data#dubbo_rpc_invocation.parameterDesc,
+    RequestList = [
+        hessianEncode:encode(?DUBBO_VERSION, State), %% dubbo version
+        hessianEncode:encode(Data#dubbo_rpc_invocation.className, State),
+        hessianEncode:encode(Data#dubbo_rpc_invocation.classVersion, State),
+        hessianEncode:encode(METHOD_NAME, State),
+        hessianEncode:encode(METHOD_ARGS_TYPES, State)
+    ],
+    {ArgsBin,State2} = encode_arguments(Data,State),
+    AttachDict = dict:from_list(Data#dubbo_rpc_invocation.attachments),
+    AttachMaps = #map{dict = AttachDict },
+    {AttachBinay,_} = hessianEncode:encode(AttachMaps, State2),
+    RequestData = erlang:iolist_to_binary(RequestList ++ [ArgsBin,AttachBinay]),
+    {ok,RequestData}.
+
+-spec encode_response(#dubbo_response{})-> {ok,term()}.
+encode_response(Response)->
+    {ok,ResponseData} = encode_response_data(Response),
+    Size = byte_size(ResponseData),
+    Header = encode_response_header(Response,Size,?RESPONSE_STATE_OK),
+    ResponseContent = <<Header/binary,ResponseData/binary>>,
+    {ok, ResponseContent}.
+
+encode_response_data(Response)->
+    State=type_encoding:init(),
+    DataType =case Response#dubbo_response.is_event of
+                  true->
+                      dubbo_event;
+                  false->
+                      case Response#dubbo_response.data of
+                          #dubbo_rpc_invocation{} ->
+                              dubbo_rpc_invocation;
+                          _ ->
+                              unknow
+                      end
+              end,
+    {ok,Bin} = encode_response_data(DataType,Response,Response#dubbo_response.data,State),
+    {ok,Bin}.
+encode_response_data(dubbo_event,Response,Data,State) ->
+    Bin = hessianEncode:encode(Data,State),
+    {ok,Bin};
+encode_response_data(dubbo_rpc_invocation,Response,Data,State) ->
+    Result = case Data of
+                 null ->
+                     [
+                         hessianEncode:encode(?RESPONSE_NULL_VALUE, State)
+                     ];
+                 _ ->
+                     {ArgsBin,_State2} = encode_arguments(Data,State),
+                     [
+                         hessianEncode:encode(?RESPONSE_VALUE, State),
+                         ArgsBin
+                     ]
+             end,
+    ResponseData = erlang:iolist_to_binary(Result),
+    {ok,ResponseData}.
+
+encode_response_header(Response,DataLen, ResponseState)->
+    Header2= Response#dubbo_response.serialize_type,
+    Header21=case Response#dubbo_response.is_twoway of
+                 true -> Header2 bor 64;
+                 false-> Header2
+             end,
+    Header22=case Response#dubbo_response.is_event of
+                 true -> Header21 bor 32;
+                 false-> Header21
+             end,
+    RequestId = Response#dubbo_response.mid,
+    Header = << ?DUBBO_MEGIC:16,Header22:8, ResponseState:8,RequestId:64,DataLen:32>>,
+    Header.
+encode_arguments(Data,State)->
+    {StateNew} = lists:foldl(fun(X,{StateTmp})->
+        StateTmpNew = type_encoding:enlist(X,StateTmp),
+        {StateTmpNew} end,
+        {State},Data#dubbo_rpc_invocation.parameterTypes),
+    {Bin,State2} = lists:foldl(fun(X,{BinTmp,StateTmp2})->
+        case hessianEncode:encode(X, StateTmp2) of
+            {ArgsBin,StateTmpNew} ->
+                {<<BinTmp/binary,ArgsBin/binary>>, StateTmpNew};
+            ArgsBin2 ->
+                {<<BinTmp/binary,ArgsBin2/binary>>, StateTmp2}
+        end end,
+        {<<>>,StateNew},Data#dubbo_rpc_invocation.parameters),
+    {Bin,State2}.
+
+-spec decode_header(binary())-> {State::ok|error,Type::request|response,Data::#dubbo_response{}|#dubbo_request{}}.
+decode_header(Header)->
+    <<?DUBBO_MEGIC_HIGH,?DUBBO_MEGIC_LOW,Flag:8,State:8,Mid:64,DataLen:32>> = Header,
+    if
+        (Flag band 16#80) == 0 ->
+            {DecodeState,Res} = decode_header(response,Flag,State,Mid,DataLen),
+            {DecodeState,response,Res};
+        true ->
+            {DecodeState,Req} = decode_header(request,Flag,State,Mid,DataLen),
+            {DecodeState,request,Req}
+    end.
+decode_header(request,Flag,State,Mid,DataLen)->
+    SerializeType = Flag band 16#1f,
+    IsTwoWay = if
+                   (Flag band 16#40) /=0 -> true;
+                   true -> false
+               end,
+    IsEvent = if
+                  (Flag band 16#20) /=0 -> true;
+                  true -> false
+              end,
+    Req = #dubbo_request{
+        is_event = IsEvent,
+        is_twoway = IsTwoWay,
+        mid = Mid,
+        mversion = <<"2.0.0">>,
+        serialize_type = SerializeType
+    },
+    {ok,Req};
+decode_header(response,Flag,State,Mid,DataLen)->
+    SerializeType = Flag band 16#1f,
+    IsEvent = if
+                  (Flag band 16#20) /= 0 -> true;
+                  true -> false
+              end,
+    Res = #dubbo_response{is_event = IsEvent,
+        serialize_type = SerializeType,
+        state = State,
+        mid = Mid
+    },
+    {ok,Res}.
+
+-spec decode_response(#dubbo_response{},binary())-> {ok,#dubbo_response{}}.
+decode_response(Res,Data)->
+    if
+        Res#dubbo_response.is_event == true ->
+            decode_response(dubbo_event,Res,Data);
+        true ->
+            decode_response(dubbo_rpc_invocation,Res,Data)
+    end.
+
+decode_response(dubbo_rpc_invocation,Res,Data)->
+    {Rest,Type,State} = hessianDecode2:decode(Data,hessianDecode2:init()),
+    case Type of
+        1 ->
+            {_,Object,DecodeState} = hessianDecode2:decode(Rest,State),
+            {ok,Res#dubbo_response{data = Object,decode_state = DecodeState}};
+        2 ->
+            {ok,Res#dubbo_response{data = null,decode_state = State}};
+        _->
+            lager:warning("decode unkonw type ~p ~p",[Type,Rest]),
+            {Rest2,Object2,DecodeState2} = hessianDecode2:decode(Rest,State),
+            lager:warning("decode unkonw type2 ~p ~p",[Object2,Rest2]),
+            {ok,Res#dubbo_response{data = Object2,decode_state = DecodeState2}}
+    end;
+decode_response(dubbo_event,Res,Data)->
+    {_Rest,undefined,_NewState} = hessianDecode2:decode(Data,hessianDecode2:init()),
+    {ok,Res#dubbo_response{data = undefined}}.
+
+-spec decode_request(#dubbo_request{},binary())-> {ok,#dubbo_request{}}.
+decode_request(Req,Data)->
+    if
+        Req#dubbo_request.is_event == true ->
+            decode_request(dubbo_event,Req,Data);
+        true ->
+            decode_request(dubbo_rpc_invocation,Req,Data)
+    end.
+
+decode_request(dubbo_rpc_invocation,Req,Data)->
+    {ResultList,NewState,RestData} = decode_request_body(Data,hessianDecode2:init(),[dubbo,path,version,method_name,desc_and_args,attachments]),
+    [DubboVersion,Path,Version,MethodName,Desc,ArgsObj,Attachments]=ResultList,
+    RpcData = #dubbo_rpc_invocation{className = Path,classVersion = Version,methodName = MethodName,parameterDesc = Data,parameters = ArgsObj,attachments = Attachments},
+    Req2 = Req#dubbo_request{data = RpcData},
+    {ok,Req2};
+%%    {Rest,Dubbo,State} = hessianDecode2:decode(Data,hessianDecode2:init()),
+%%    {Rest1,ClassName,State1} = hessianDecode2:decode(Data,State),
+%%    {Rest2,ClassName,State2} = hessianDecode2:decode(Rest1,State1),
+%%    case Type of
+%%        1 ->
+%%            {_,Object,DecodeState} = hessianDecode2:decode(Rest,State),
+%%            {ok,Req#dubbo_request{data = Object,decode_state = DecodeState}};
+%%        2 ->
+%%            {ok,Req#dubbo_request{data = null,decode_state = State}};
+%%        _->
+%%            lager:warning("decode unkonw type ~p ~p",[Type,Rest]),
+%%            {Rest2,Object2,DecodeState2} = hessianDecode2:decode(Rest,State),
+%%            lager:warning("decode unkonw type2 ~p ~p",[Object2,Rest2]),
+%%            {ok,Req#dubbo_request{data = Object2,decode_state = DecodeState2}}
+%%    end;
+decode_request(dubbo_event,Req,Data)->
+    {_Rest,undefined,_NewState} = hessianDecode2:decode(Data,hessianDecode2:init()),
+    {ok,Req#dubbo_request{data = undefined}}.
+
+decode_request_body(Data,State,List)->
+    {ResultList,NewState,RestData} = decode_request_body(List,Data,State,[]),
+    {lists:reverse(ResultList),NewState,RestData}.
+decode_request_body([ParseType|List],Data,State,ResultList)
+    when ParseType==dubbo;ParseType==path;ParseType==version;ParseType==method_name ->
+    {Rest,Result,NewState } = hessianDecode2:decode(Data,State),
+    decode_request_body(List,Rest,NewState, [Result] ++ ResultList);
+decode_request_body([desc_and_args| List],Data,State,ResultList)->
+    {Rest,ParameterDesc,State1 } = hessianDecode2:decode(Data,State),
+    if
+        size(ParameterDesc) == 0 ->
+            decode_request_body(List,Rest,State1, [ [],[] ]++ ResultList);
+        true ->
+            ParameterDescArray = binary:split(ParameterDesc,<<";">>),
+            {ArgsObjList,NewState,RestData} = decode_request_body_args(ParameterDescArray,Rest,State1,[]),
+            decode_request_body(List,RestData,NewState, [ArgsObjList,ParameterDesc]++ ResultList)
+    end;
+decode_request_body([attachments|List],Data,State,ResultList)->
+    {Rest,Attachments,State1 } = hessianDecode2:decode(Data,State),
+    AttachmentsList = dict:to_list(Attachments#map.dict),
+    decode_request_body(List,Rest,State1,[AttachmentsList] ++ ResultList);
+decode_request_body([_Type1|List],Data,State,ResultList)->
+    lager:warning("decode_request_body unknow type"),
+    decode_request_body(List,Data,State, ResultList);
+decode_request_body([],Data,State,ResultList)->
+    {ResultList,State,Data}.
+
+decode_request_body_args([],Data,State,ArgsObjList)->
+    {ArgsObjList,State,Data};
+decode_request_body_args([ArgsType|RestList],Data,State,ArgsObjList) when ArgsType== <<>> ->
+    decode_request_body_args(RestList,Data,State,ArgsObjList);
+decode_request_body_args([_ArgsType|RestList],Data,State,ArgsObjList) ->
+    {Rest,ArgObj,NewState } = hessianDecode2:decode(Data,State),
+    ArgObj2 = de_type_transfer:classobj_to_native(ArgObj,NewState),
+    decode_request_body_args(RestList,Rest,NewState,ArgsObjList++[ArgObj2]).
\ No newline at end of file
diff --git a/src/dubbo_traffic_control.erl b/src/dubbo_traffic_control.erl
new file mode 100644
index 0000000..d7b6fcb
--- /dev/null
+++ b/src/dubbo_traffic_control.erl
@@ -0,0 +1,52 @@
+%%%-------------------------------------------------------------------
+%%% @author dlive
+%%% @copyright (C) 2018, <COMPANY>
+%%% @doc
+%%%
+%%% @end
+%%% Created : 22. May 2018 1:58 PM
+%%%-------------------------------------------------------------------
+-module(dubbo_traffic_control).
+-author("dlive").
+-include("dubboerl.hrl").
+%% API
+-export([init/0,check_goon/2,decr_count/1]).
+
+
+init()->
+    case ets:info(?TRAFFIC_CONTROL) of
+        undefined ->
+            io:format("init decoding TRAFFIC_CONTROL table pid ~p~n",[self()]),
+            ets:new(?TRAFFIC_CONTROL,[public,named_table, {write_concurrency, true}]); %% public
+        _ ->
+            ets:delete(?TRAFFIC_CONTROL),
+            ets:new(?TRAFFIC_CONTROL,[public,named_table, {write_concurrency, true}])
+    end,
+    ok.
+
+
+check_goon(Key,Max)->
+    try ets:update_counter(?TRAFFIC_CONTROL,Key,1) of
+        Value when Value > Max ->
+            ets:update_counter(?TRAFFIC_CONTROL,Key,-1),
+            full;
+        _V ->
+%%            lager:debug("check traffic incr value ~p",[V]),
+            ok
+
+    catch
+        _T:_R->
+            ets:insert(?TRAFFIC_CONTROL,{Key,1}),
+            ok
+    end.
+
+decr_count(Key)->
+    try ets:update_counter(?TRAFFIC_CONTROL,Key,-1) of
+        _V ->
+%%            lager:debug("check traffic decr value ~p",[V]),
+            ok
+    catch
+        _T:_R->
+            ets:insert(?TRAFFIC_CONTROL,{Key,0}),
+            ok
+    end.
\ No newline at end of file
diff --git a/src/dubbo_zookeeper.erl b/src/dubbo_zookeeper.erl
new file mode 100644
index 0000000..f0016a8
--- /dev/null
+++ b/src/dubbo_zookeeper.erl
@@ -0,0 +1,270 @@
+%%%-------------------------------------------------------------------
+%%% @author dlive
+%%% @copyright (C) 2016, <COMPANY>
+%%% @doc
+%%%
+%%% @end
+%%% Created : 29. 十月 2016 上午9:56
+%%%-------------------------------------------------------------------
+-module(dubbo_zookeeper).
+-author("dlive").
+
+-behaviour(gen_server).
+
+-include("dubbo.hrl").
+%% API
+-export([start_link/0,register_consumer/1,register_consumer/2,gen_consumer_node_info/1,register_provider/1,provider_watcher/1]).
+
+%% gen_server callbacks
+-export([init/1,
+    handle_call/3,
+    handle_cast/2,
+    handle_info/2,
+    terminate/2,
+    code_change/3]).
+
+-define(SERVER, ?MODULE).
+
+-record(state, {zk_pid}).
+
+%%%===================================================================
+%%% API
+%%%===================================================================
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Starts the server
+%%
+%% @end
+%%--------------------------------------------------------------------
+-spec(start_link() ->
+    {ok, Pid :: pid()} | ignore | {error, Reason :: term()}).
+start_link() ->
+    gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).
+
+%%%===================================================================
+%%% gen_server callbacks
+%%%===================================================================
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Initializes the server
+%%
+%% @spec init(Args) -> {ok, State} |
+%%                     {ok, State, Timeout} |
+%%                     ignore |
+%%                     {stop, Reason}
+%% @end
+%%--------------------------------------------------------------------
+-spec(init(Args :: term()) ->
+    {ok, State :: #state{}} | {ok, State :: #state{}, timeout() | hibernate} |
+    {stop, Reason :: term()} | ignore).
+init([]) ->
+    {ok,Pid} = connection(),
+    {ok, #state{zk_pid = Pid}}.
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Handling call messages
+%%
+%% @end
+%%--------------------------------------------------------------------
+-spec(handle_call(Request :: term(), From :: {pid(), Tag :: term()},
+    State :: #state{}) ->
+    {reply, Reply :: term(), NewState :: #state{}} |
+    {reply, Reply :: term(), NewState :: #state{}, timeout() | hibernate} |
+    {noreply, NewState :: #state{}} |
+    {noreply, NewState :: #state{}, timeout() | hibernate} |
+    {stop, Reason :: term(), Reply :: term(), NewState :: #state{}} |
+    {stop, Reason :: term(), NewState :: #state{}}).
+
+handle_call({add_consumer,Consumer}, _From, State) ->
+    add_consumer(Consumer,State),
+    {reply, ok, State};
+handle_call({add_provider,Provider}, _From, State) ->
+    register_provider_path(Provider,State),
+    {reply, ok, State};
+handle_call(_Request, _From, State) ->
+    {reply, ok, State}.
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Handling cast messages
+%%
+%% @end
+%%--------------------------------------------------------------------
+-spec(handle_cast(Request :: term(), State :: #state{}) ->
+    {noreply, NewState :: #state{}} |
+    {noreply, NewState :: #state{}, timeout() | hibernate} |
+    {stop, Reason :: term(), NewState :: #state{}}).
+handle_cast({provider_node_change,Interface,Path}, #state{zk_pid = Pid}=State) ->
+    get_provider_and_start(Pid,Interface,Path),
+    {noreply, State};
+handle_cast(_Request, State) ->
+    {noreply, State}.
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Handling all non call/cast messages
+%%
+%% @spec handle_info(Info, State) -> {noreply, State} |
+%%                                   {noreply, State, Timeout} |
+%%                                   {stop, Reason, State}
+%% @end
+%%--------------------------------------------------------------------
+-spec(handle_info(Info :: timeout() | term(), State :: #state{}) ->
+    {noreply, NewState :: #state{}} |
+    {noreply, NewState :: #state{}, timeout() | hibernate} |
+    {stop, Reason :: term(), NewState :: #state{}}).
+handle_info(_Info, State) ->
+    lager:info("zk server recv msg:~p",[_Info]),
+    {noreply, State}.
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% This function is called by a gen_server when it is about to
+%% terminate. It should be the opposite of Module:init/1 and do any
+%% necessary cleaning up. When it returns, the gen_server terminates
+%% with Reason. The return value is ignored.
+%%
+%% @spec terminate(Reason, State) -> void()
+%% @end
+%%--------------------------------------------------------------------
+-spec(terminate(Reason :: (normal | shutdown | {shutdown, term()} | term()),
+    State :: #state{}) -> term()).
+terminate(_Reason, _State) ->
+    ok.
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Convert process state when code is changed
+%%
+%% @spec code_change(OldVsn, State, Extra) -> {ok, NewState}
+%% @end
+%%--------------------------------------------------------------------
+-spec(code_change(OldVsn :: term() | {down, term()}, State :: #state{},
+    Extra :: term()) ->
+    {ok, NewState :: #state{}} | {error, Reason :: term()}).
+code_change(_OldVsn, State, _Extra) ->
+    {ok, State}.
+
+
+register_consumer(Consumer) ->
+    gen_server:call(?SERVER,{add_consumer,Consumer}),
+    ok.
+register_consumer(Name,Option)->
+    Consumer=#consumer_config{interface = Name,methods = [<<"testa">>,<<"testb">>]},
+    register_consumer(Consumer),
+    ok.
+register_provider(Provider)->
+    gen_server:call(?SERVER,{add_provider,Provider}),
+    ok.
+
+%%%===================================================================
+%%% Internal functions
+%%%===================================================================
+
+connection()->
+    {ok,List} = application:get_env(dubboerl,zookeeper_list),
+    {ok, Pid} = erlzk:connect(List, 30000, [
+        {chroot, "/"},
+        {monitor, self()}]),
+    {ok,Pid}.
+
+add_consumer(Consumer,State)->
+    Pid= State#state.zk_pid,
+%%    InterfacePath= << <<"/dubbo/">>/binary,Name/binary ,<<"consumers">>/binary >>,
+    ConsumerNode = gen_consumer_node_info(Consumer),
+    ConsumerNode2= list_to_binary(edoc_lib:escape_uri(binary_to_list(ConsumerNode))),
+    check_and_create_path(Pid,<<"">>,[{<<"dubbo">>,p},{Consumer#consumer_config.interface,p},{<<"consumers">>,p},{ConsumerNode2,e} ]),
+    get_provider_list(Consumer,State),
+    ok.
+register_provider_path(Provider,State)->
+    #state{zk_pid = Pid}=State,
+    ProviderNode = dubbo_node_config_util:gen_provider_info(Provider),
+    check_and_create_path(Pid,<<"">>,[{<<"dubbo">>,p},{Provider#provider_config.interface,p},{<<"providers">>,p},{ProviderNode,e}]),
+    ok.
+
+
+get_provider_list(Consumer,State)->
+    Pid= State#state.zk_pid,
+    InterfacePath= << <<"/dubbo/">>/binary,(Consumer#consumer_config.interface)/binary ,<<"/providers">>/binary >>,
+    get_provider_and_start(Pid,Consumer#consumer_config.interface,InterfacePath),
+    ok.
+get_provider_and_start(Pid,Interface,Path)->
+    case erlzk:get_children(Pid,Path,spawn(dubbo_zookeeper,provider_watcher,[Interface])) of
+        {ok,ChildList} ->
+            lager:debug("get provider list ~p",[ChildList]),
+            start_provider_process(Interface,ChildList),
+            ok;
+        {error,R1} ->
+            lager:debug("[add_consumer] get_provider_list error ~p ~p",[R1]),
+            ok
+    end.
+
+provider_watcher(Interface)->
+    receive
+        {node_children_changed,Path} ->
+            gen_server:cast(?SERVER,{provider_node_change,Interface,Path}),
+            lager:debug("provider_watcher get event ~p ~p",[node_children_changed,Path]);
+        {Event, Path} ->
+%%            Path = "/a",
+%%            Event = node_created
+            lager:debug("provider_watcher get event ~p ~p",[Event,Path])
+    end,
+    ok.
+
+
+create_path(Pid,Path,CreateType)->
+    case erlzk:create(Pid,Path,CreateType) of
+        {ok,ActualPath}->
+            lager:debug("[add_consumer] create zk path  success ~p",[ActualPath]),
+            ok;
+        {error,R1}->
+            lager:debug("[add_consumer] create zk path error ~p ~p",[Path,R1])
+    end,
+    ok.
+check_and_create_path(_Pid,_RootPath,[]) ->
+    ok;
+check_and_create_path(Pid,RootPath,[{Item,CreateType}|Rst])->
+    CheckPath= << RootPath/binary,<<"/">>/binary,Item/binary >>,
+    case erlzk:exists(Pid,CheckPath) of
+        {ok,Stat} ->
+            check_and_create_path(Pid,CheckPath,Rst);
+        {error,no_node}->
+            lager:debug("[add_consumer] check_and_create_path unexist no_node ~p",[CheckPath]),
+            create_path(Pid,CheckPath,CreateType),
+            check_and_create_path(Pid,CheckPath,Rst);
+        {error,R1} ->
+            lager:debug("[add_consumer] check_and_create_path unexist ~p",[R1]),
+            check_and_create_path(Pid,CheckPath,Rst)
+    end.
+
+gen_consumer_node_info(Consumer)->
+    %% revision参数字段的作用是什么? 暂时不添加
+    Methods=lists_util:join(Consumer#consumer_config.methods,<<",">>),
+    Value=io_lib:format(<<"consumer://~s/~s?application=~s&category=~s&check=~p&default.timeout=~p&dubbo=~s&interface=~s&methods=~s&side=~s&timestamp=~p">>,
+        [de_common_fun:local_ip_v4_str(),
+            Consumer#consumer_config.interface,
+            Consumer#consumer_config.application,
+            Consumer#consumer_config.category,
+            Consumer#consumer_config.check,
+            Consumer#consumer_config.default_timeout,
+            Consumer#consumer_config.dubbo_version,
+            Consumer#consumer_config.interface,
+            Methods,
+            Consumer#consumer_config.side,
+            time_util:timestamp_ms()
+            ]),
+    list_to_binary(Value).
+
+%%dubbo_zookeeper:register_consumer(<<"com.ifcoder.abcd">>,[]).
+start_provider_process(Interface,ProviderList)->
+    dubbo_consumer_pool:start_consumer(Interface,ProviderList).
+
diff --git a/src/dubboerl.app.src b/src/dubboerl.app.src
new file mode 100644
index 0000000..4998bf0
--- /dev/null
+++ b/src/dubboerl.app.src
@@ -0,0 +1,16 @@
+{application, dubboerl,
+ [{description, "An OTP application"},
+  {vsn, "0.1.0"},
+  {registered, []},
+  {mod, { dubboerl_app, []}},
+  {applications,
+   [kernel,
+    stdlib,xmerl,eunit,erlzk,lager,poolboy,inets
+   ]},
+  {env,[]},
+  {modules, []},
+
+  {maintainers, []},
+  {licenses, []},
+  {links, []}
+ ]}.
diff --git a/src/dubboerl.erl b/src/dubboerl.erl
new file mode 100644
index 0000000..8d841bd
--- /dev/null
+++ b/src/dubboerl.erl
@@ -0,0 +1,54 @@
+%%%-------------------------------------------------------------------
+%%% @author dlive
+%%% @copyright (C) 2017, <COMPANY>
+%%% @doc
+%%%
+%%% @end
+%%% Created : 22. Dec 2017 11:54 PM
+%%%-------------------------------------------------------------------
+-module(dubboerl).
+-author("dlive").
+
+-include("dubboerl.hrl").
+%% API
+-export([init/0,start_consumer/0,start_provider/0]).
+
+init()->
+    start_consumer(),
+    start_provider(),
+    ok.
+
+
+start_consumer()->
+    ConsumerList = application:get_env(dubboerl,consumer,[]),
+    ApplicationName = application:get_env(dubboerl,application,<<"defaultApplication">>),
+    lists:map(fun({Interface,Option})->
+        ConsumerInfo = dubbo_config_util:gen_consumer(ApplicationName,Interface,Option),
+        dubbo_zookeeper:register_consumer(ConsumerInfo),
+        lager:info("register consumer success ~p",[Interface])
+        end,ConsumerList),
+    ok.
+
+start_provider()->
+    ProviderList = application:get_env(dubboerl,provider,[]),
+    ApplicationName = application:get_env(dubboerl,application,<<"defaultApplication">>),
+    DubboServerPort = application:get_env(dubboerl,port,20881),
+    start_provider_listen(DubboServerPort),
+    lists:map(fun({ImplModuleName,BehaviourModuleName,Interface,Option})->
+        ok = dubbo_provider_protocol:register_impl_provider(Interface,ImplModuleName,BehaviourModuleName),
+        MethodList= apply(BehaviourModuleName,get_method_999_list,[]),
+        ProviderInfo = dubbo_config_util:gen_provider(ApplicationName,DubboServerPort,Interface,MethodList,Option),
+        dubbo_zookeeper:register_provider(ProviderInfo),
+        lager:info("register provider success ~p ~p",[ImplModuleName,Interface])
+        end,ProviderList),
+    ok.
+
+start_provider_listen(Port)->
+    ets:new(?PROVIDER_IMPL_TABLE,[public,named_table]),
+    {ok, _} = ranch:start_listener(tcp_reverse,
+        ranch_tcp, [{port, Port}], dubbo_provider_protocol, []),
+    ok.
+
+
+
+
diff --git a/src/dubboerl_app.erl b/src/dubboerl_app.erl
new file mode 100644
index 0000000..fb3a1a2
--- /dev/null
+++ b/src/dubboerl_app.erl
@@ -0,0 +1,42 @@
+%%%-------------------------------------------------------------------
+%% @doc dubboerl public API
+%% @end
+%%%-------------------------------------------------------------------
+
+-module(dubboerl_app).
+
+-behaviour(application).
+
+%% Application callbacks
+-export([start/2, stop/1,env_init/0]).
+
+%%====================================================================
+%% API
+%%====================================================================
+
+start(_StartType, _StartArgs) ->
+    io:format("[START] server start~n"),
+    env_init(),
+    dubboerl_sup:start_link().
+
+%%--------------------------------------------------------------------
+stop(_State) ->
+    ok.
+
+%%====================================================================
+%% Internal functions
+%%====================================================================
+env_init()->
+    dubbo_traffic_control:init(),
+    type_register:init(),
+    register_type_list().
+%%    type_decoding:init().
+
+
+register_type_list()->
+    List = java_type_defined:get_list(),
+    lists:map(
+        fun({NativeType,ForeignType,Fields}) ->
+            de_type_transfer:pre_process_typedef(NativeType,ForeignType,Fields)
+        end,List),
+    ok.
\ No newline at end of file
diff --git a/src/dubboerl_sup.erl b/src/dubboerl_sup.erl
new file mode 100644
index 0000000..4e42308
--- /dev/null
+++ b/src/dubboerl_sup.erl
@@ -0,0 +1,57 @@
+%%%-------------------------------------------------------------------
+%% @doc dubboerl top level supervisor.
+%% @end
+%%%-------------------------------------------------------------------
+
+-module(dubboerl_sup).
+
+-behaviour(supervisor).
+
+-include("common.hrl").
+%% API
+-export([start_link/0]).
+
+%% Supervisor callbacks
+-export([init/1]).
+
+-define(SERVER, ?MODULE).
+
+%%====================================================================
+%% API functions
+%%====================================================================
+
+start_link() ->
+    supervisor:start_link({local, ?SERVER}, ?MODULE, []).
+
+%%====================================================================
+%% Supervisor callbacks
+%%====================================================================
+
+%% Child :: {Id,StartFunc,Restart,Shutdown,Type,Modules}
+init([]) ->
+    ZK = {dubbo_zookeeper,{dubbo_zookeeper, start_link, []},transient,5000,worker,[dubbo_zookeeper]},
+%%    NettySer = {dubbo_netty_client,{dubbo_netty_client, start_link, []},transient,5000,worker,[dubbo_netty_client]},
+    Id_count = {de_id_count,{de_id_count, start_link, []},transient,5000,worker,[de_id_count]},
+    ProviderPoolSup = {dubbo_provider_worker_sup,{dubbo_provider_worker_sup, start_link, []},transient,5000,supervisor,[dubbo_provider_worker_sup]},
+    ConsumerPoolSup = {dubbo_consumer_pool_sup,{dubbo_consumer_pool_sup, start_link, []},transient,5000,supervisor,[dubbo_consumer_pool_sup]},
+    ConsumerPool = {dubbo_consumer_pool,{dubbo_consumer_pool, start_link, []},transient,5000,worker,[dubbo_consumer_pool]},
+%%    Reloader = {push_reloader,{push_reloader, start_link, []},transient,5000,worker,[push_reloader]},
+%%    List = case ?RELOADER of
+%%               true ->
+%%                   io:format("[START] will start push_reloader service2222~n"),
+%%                   [Reloader];
+%%               _->[]
+%%           end,
+    ListNew1=
+        case application:get_env(dubboerl,registry,false) of
+            true ->
+                [ZK];
+            false->
+                []
+        end,
+    ListNew = ListNew1 ++ [Id_count,ConsumerPool,ConsumerPoolSup,ProviderPoolSup],
+    {ok, { {one_for_one, 60, 10}, ListNew} }.
+
+%%====================================================================
+%% Internal functions
+%%====================================================================
diff --git a/src/encode_test.erl b/src/encode_test.erl
new file mode 100644
index 0000000..e806784
--- /dev/null
+++ b/src/encode_test.erl
@@ -0,0 +1,53 @@
+%%%-------------------------------------------------------------------
+%%% @author dlive
+%%% @copyright (C) 2016, <COMPANY>
+%%% @doc
+%%%
+%%% @end
+%%% Created : 18. 十月 2016 上午10:46
+%%%-------------------------------------------------------------------
+-module(encode_test).
+-author("dlive").
+
+-include("hessian.hrl").
+%% API
+-export([object_test/0,de_object/0]).
+
+-record(de_TestReq, {name, nick,age}).
+-record(de_reg2, {reqinfo,age}).
+
+object_test()->
+    ForeignTypeA = <<"com.ifcoder.demo.bean.UserInfoRequest">>,
+    TypeDefA = #type_def{foreign_type = ForeignTypeA,
+        native_type = de_TestReq,
+        fieldnames = record_info(fields,de_TestReq)},
+    EncodingState0 = type_encoding:enlist(TypeDefA),
+    io:format("state:~p~n",[EncodingState0]),
+    RequestArg0 = #de_TestReq{name = <<"nameinfo">>, nick = <<"nickname">> ,age=10 },
+%%    Object = #object{values = [RequestArg0] },
+%%    io:format("Object:~p~n",[Object]),
+    {Bin, State0} = hessianEncode:encode(RequestArg0, EncodingState0),
+    file:write_file("/tmp/object_erl.data",Bin),
+%%    ?assertMatch(Expected, Bin),
+    %% This test is asymmetric because decode($O,Rest/bin)
+    %% will only consume the outer class definition,
+    %% in normal circumstances, the calling decode/2 function will recursively
+    %% consume all object definitions.
+%%    {Rest, TypeDef, State1} = hessian:decode(Bin, DecodingState),
+%%    ?assertMatch(TypeDefA, TypeDef),
+%%    [Function|Arguments] = hessian:decode(<<99,2,0,109,0,1,97,Bin/binary>>, DecodingState),
+%%    ?assertMatch([[A]], Arguments).
+
+    ok.
+
+de_object()->
+    ForeignTypeA = <<"com.ifcoder.demo.bean.UserInfoRequest">>,
+    TypeDefA = #type_def{foreign_type = ForeignTypeA,
+        native_type = de_TestReq,
+        fieldnames = record_info(fields,de_TestReq)},
+    EncodingState0 = hessianDecode2:enlist(TypeDefA),
+    {ok,Bin} = file:read_file("/tmp/object_erl.data"), %% /tmp/objectencode.data
+    Info = hessianDecode2:decode(Bin,EncodingState0),
+    io:format("info:~p~n",[Info]),
+    ok.
+
diff --git a/src/hessian.erl b/src/hessian.erl
new file mode 100644
index 0000000..b877b97
--- /dev/null
+++ b/src/hessian.erl
@@ -0,0 +1,590 @@
+% ---------------------------------------------------------------------------
+%   Copyright (C) 2008 0x6e6562
+%
+%   Licensed 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.
+% ---------------------------------------------------------------------------
+
+-module(hessian).
+
+-include("hessian.hrl").
+
+-export([call/5]).
+-export([invoke/4]).
+-export([decode/2]).
+-export([encode/2, encode/3, encode/4, encode/5]).
+%% TODO Move the e2cc function to encoding module
+-export([erlang_to_camel_case/1]).
+
+%---------------------------------------------------------------------------
+% Decoding
+%---------------------------------------------------------------------------
+
+% Binaries
+decode(<<16#20,Rest/binary>>, State) -> {Rest, <<>>, State};
+decode(<<Len:8/unsigned,Rest/binary>>, State) when Len =< 16#2f, 16#20 < Len ->
+    _Len = Len - 16#20,
+    <<Bin:_Len/binary,_Rest/binary>> = Rest,
+    {_Rest, Bin, State};
+decode(<<$B,Len:16/unsigned,Bin:Len/binary,Rest/binary>>, State) -> {Rest, Bin, State};
+decode(<<$b,Rest/binary>>,State) -> decode(<<$b,Rest/binary>>, [], State);
+%% Booleans
+decode(<<$T,Rest/binary>>, State) -> {Rest, true, State};
+decode(<<$F,Rest/binary>>, State) -> {Rest, false, State};
+%% Dates
+decode(<<$d,Date:64/unsigned,Rest/binary>>, State) ->
+    MegaSecs = Date div ?MegaSeconds,
+    Secs = (Date - MegaSecs * ?MegaSeconds) div ?Seconds,
+    MicroSecs = (Date - MegaSecs * ?MegaSeconds - Secs * ?Seconds) * ?MicroSeconds,
+    {Rest, {MegaSecs, Secs, MicroSecs}, State};
+%% Doubles
+decode(<<16#67,Rest/binary>>, State)-> {Rest, 0.0, State};
+decode(<<16#68,Rest/binary>>, State)-> {Rest, 1.0, State};
+decode(<<16#69,Int:8/signed,Rest/binary>>, State)-> {Rest, float(Int), State};
+decode(<<16#6a,Int:16/signed,Rest/binary>>, State)-> {Rest, float(Int), State};
+%% TODO ask erlang-questions about not being able to match a 32bit float
+decode(<<16#6b,Int:32/signed,Rest/binary>>, State)->
+    <<Double:64/float>> = <<Int:32,0,0,0,0>>,
+    {Rest, Double, State};
+decode(<<$D,Double:64/float,Rest/binary>>, State)-> {Rest, Double, State};
+%% Ints
+decode(<<$I,Int:32/unsigned,Rest/binary>>, State)-> {Rest, Int, State};
+decode(<<Int:8,Rest/binary>>, State) when Int >= 16#80, Int =< 16#bf -> {Rest, Int - 16#90, State};
+decode(<<B2:8,B1:8,B0:8,Rest/binary>>, State) when B2 >= 16#d0, B2 =< 16#d7 -> {Rest, ((B2 - 16#d4) bsl 16) + (B1 bsl 8) + B0, State};
+decode(<<B1:8,B0:8,Rest/binary>>, State) when B1 >= 16#c0, B1 =< 16#cf -> {Rest, ((B1 - 16#c8) bsl 8) + B0, State};
+%% Longs
+decode(<<$L,Long:64/unsigned,Rest/binary>>, State)-> {Rest, Long, State};
+decode(<<16#77,Long:32,Rest/binary>>, State) -> {Rest, Long, State};
+decode(<<Long:8,Rest/binary>>, State) when Long >= 16#d8, Long =< 16#ef -> {Rest, Long - 16#e0, State};
+decode(<<B2:8,B1:8,B0:8,Rest/binary>>, State) when B2 >= 16#38, B2 =< 16#3f -> {Rest, ((B2 - 16#3c) bsl 16) + (B1 bsl 8) + B0, State};
+decode(<<B1:8,B0:8,Rest/binary>>, State) when B1 >= 16#f0, B1 =< 16#ff -> {Rest, ((B1 - 16#f8) bsl 8) + B0, State};
+%% Strings
+decode(<<0,Rest/binary>>, State) -> {Rest, <<>>, State};
+decode(<<Len:8,String:Len/binary,Rest/binary>>, State) when Len < 32 -> {Rest, list_to_binary(xmerl_ucs:from_utf8(String)), State};
+decode(<<$S,Len:16/unsigned,String:Len/binary,Rest/binary>>, State) -> {Rest, list_to_binary(xmerl_ucs:from_utf8(String)), State};
+decode(<<$s,Rest/binary>>, State) -> decode(<<$s,Rest/binary>>,[], State);
+%% Nulls
+decode(<<$N,Rest/binary>>, State) -> {Rest, undefined, State};
+%% References
+decode(<<$R,Ref:32/unsigned,Rest/binary>>, State)-> {ref, Rest, Ref, State};
+%% Maps
+decode(<<$M,$t,L:16/unsigned,Type:L/binary,Map/binary>>, State) -> decode(map, Map, dict:store(fqn, Type, dict:new()), State);
+decode(<<$M,Map/binary>>, State) -> decode(map, Map, dict:new(), State);
+%%list ::= V type? length? value* z
+%%     ::= v int int value*
+%%length     ::= 'l' b3 b2 b1 b0
+%%           ::= x6e int
+%% Lists
+decode(<<$V,$t,L1:16/unsigned,T:L1/binary,$l,L2:32/unsigned,Bin/binary>>, State) -> decode(list, Bin, [], State);
+decode(<<$V,$l,L1:32/unsigned,Bin/binary>>, State) -> decode(list, Bin, [], State);
+decode(<<$V,16#6e,L1:8,Bin/binary>>, State) -> decode(list, Bin, [], State);
+decode(<<$V,16#6e,L1:16,Bin/binary>>, State) -> decode(list, Bin, [], State);
+decode(<<$V,$t,L1:16/unsigned,T:L1/binary,Bin/binary>>, State) -> decode(list, Bin, [], State);
+decode(<<$V,Bin/binary>>, State) -> decode(list, Bin, [], State);
+decode(<<$O,?M,?m,Hash:32/unsigned,$u,$z>>, State0) -> {peer_cannot_resolve,Hash};
+decode(<<$O,Hash:32/unsigned,$t,L:16/unsigned,Type:L/binary,Bin/binary>>, State0) ->
+    {Rest, TypeDef, State} = decode(type_definition,Type,Bin,State0),
+    NewState = type_decoding:hash_store(Hash,TypeDef,State),
+    {Rest, {Hash,TypeDef}, NewState};
+decode(<<$O,Hash:32/unsigned,Bin/binary>>, State) ->
+    ?TYPEDEF(Hash),
+    case type_decoding:hash_lookup(Hash, State) of
+        {not_found, Hash} ->
+            %?LOG(Hash),
+            {Bin, {not_found, Hash}, State};
+        TypeDef ->
+            %?LOG(TypeDef),
+            NewState = type_decoding:visit(TypeDef,State),
+            {Bin,TypeDef,NewState}
+    end;
+decode(<<$o,Bin/binary>>, State) ->
+    {Rest,Ref,_State} = decode(Bin, State),
+    ?INSTANCE(Ref),
+    ForeignView = type_decoding:lookup_reference(Ref, _State),
+    #type_def{native_type = NativeType,
+              foreign_type = ForeignType,
+              fieldnames = ForeignFieldNames} = ForeignView,
+    NativeView = type_decoding:resolve_native_type(ForeignType,_State),
+    Count = count_fields(ForeignView),
+    case decode(field, Rest, Count,[], _State) of
+        {not_found,Hash} ->
+            {not_found,Hash};
+        {_Rest,FieldValues, NewState} ->
+            Object = type_decoding:project_native_view(ForeignFieldNames,FieldValues,NativeView),
+            {_Rest, Object, NewState}
+    end;        
+%---------------------------------------------------------------------------
+% Call and reply decoding
+%---------------------------------------------------------------------------
+decode(<<$c,?M,?m,$m,L1:16/unsigned,Function:L1/binary,Bin/binary>>, State) ->
+    ?START(c, [?M,?m]),
+    ?METHOD(Function),
+    case decode(list, Bin,[], State) of
+        {error, Encoded} ->
+            {error, Encoded};
+        {not_found, Hash} ->
+            {not_found, Hash};    
+        {Rest, Arguments, NewState} ->
+            [type_decoding:camel_case_to_erlang(Function), Arguments]
+    end;
+decode(<<$r,?M,?m,$N,$z>>, State) -> ok;
+%% TODO The string decoding in the fault decoding is a bit dodgy
+%% Also, have a look at the way it is being encoded
+decode(<<$r,?M,?m,$f,
+         4,"code",L1:8,Code:L1/binary,
+         7,"message",L2:8,Message:L2/binary,
+         6,"detail",L3:8,Detail:L3/binary,$z>>, State) ->
+    {error, list_to_atom(binary_to_list(Message)) };
+decode(<<$r,?M,?m,Args/binary>>, State) ->
+    case decode(Args,[], State) of
+        {<<>>, Decoded,_State} ->
+            case lists:dropwhile(fun is_type_def/1, Decoded) of
+                [Value] ->
+                    Value;
+                [H|T] ->
+                    [H|T]
+            end;
+        {error, Encoded} ->
+            {error, Encoded}
+    end;
+%% Type queries
+decode(<<$q,?M,?m,Hash:32/unsigned,$z>>, State) ->
+    ?START(q, [?M,?m]),
+    ?VALUE(<<Hash:32>>),
+    case type_decoding:hash_lookup(Hash, State) of
+        {not_found, Hash} ->
+            {error, encode(fault, <<"ProtocolException">>, unknown_hash, Hash, State) };
+        TypeDef ->
+            {Hash,TypeDef, State}
+    end;
+decode(<<$y,?M,?m,Hash:32/unsigned,$z>>, State) ->
+    {type_query_ack, Hash};
+%% Anything else
+decode(<<Unexpected/binary>>, State) ->
+    {error, encode(fault, <<"ProtocolException">>, unexpected_byte_sequence, Unexpected, State) }.
+%----------------------------------
+decode(<<$b,Len:16/unsigned,Bin:Len/binary,$b,Rest/binary>>, Acc, State) ->
+    decode(<<$b,Rest/binary>>,Acc ++ [Bin], State);
+decode(<<$b,Len:16/unsigned,Bin:Len/binary,$B,Rest/binary>>, Acc, State) ->
+    _Acc = Acc ++ [Bin],
+    {_Rest,_Bin, State} = decode(<<$B,Rest/binary>>, State),
+    {_Rest, list_to_binary(_Acc ++ [_Bin]), State};
+decode(<<$s,Len:16,String:Len/binary,$s,Rest/binary>>,Acc, State) ->
+    _String = list_to_binary(xmerl_ucs:from_utf8(String)),
+    decode(<<$s,Rest/binary>>,Acc ++ [_String], State);
+decode(<<$s,Len:16,String:Len/binary,$S,Rest/binary>>,Acc, State) ->
+    _String = list_to_binary(xmerl_ucs:from_utf8(String)),
+    _Acc = Acc ++ [_String],
+    {_Rest,_Bin, _State} = decode(<<$S,Rest/binary>>, State),
+    {_Rest, list_to_binary(_Acc ++ [_Bin]), _State};
+decode(<<>>, List, State) -> {<<>>, List, State};
+decode(<<$z>>, List, State) -> {<<>>, List, State};
+decode(Args, List, State) ->
+    case decode(Args,State) of
+        {Rest, [H|T], _State} ->
+            decode(Rest, List ++ [H|T], _State);
+        {Rest, Result, _State} ->
+            decode(Rest, List ++ [Result], _State);
+        {ref, Rest, Ref, _State} ->
+            _Ref = lists:nth(Ref + 1, List),
+            decode(Rest, [List,[_Ref]] , _State);
+        {error, Encoded} ->
+            {error, Encoded}
+    end.
+decode(map, <<$z>>, Dict, State) -> {Dict, State};
+decode(map, <<$z,Rest/binary>>, Dict, State) -> {Rest,Dict, State};
+decode(map, Bin, Dict, State) ->
+    {_Rest, Key, _State} = decode(Bin, State),
+    case decode(_Rest, _State) of
+        {Rest, Value, __State} ->
+            decode(map, Rest, dict:store(Key, Value, Dict), __State);
+        {ref, Rest, Ref, __State} ->
+            %Value = lists:nth(Ref + 1, List),
+            Value = Ref,
+            decode(map, Rest, dict:store(Key, Value, Dict), __State)
+    end;
+decode(list, <<>>, List, State) -> {<<>>,List, State};
+decode(list, <<$z>>, List, State) -> {<<>>,List, State};
+decode(list, <<$z,Rest/binary>>, List, State) -> {Rest, List, State};
+decode(list, Bin, List, State) ->
+    case decode(Bin, State) of
+        {error, Encoded} ->
+            {error, Encoded};
+        {Rest, {type_def,_,_,_}, _State} ->
+            decode(list, Rest, List, _State);
+        {not_found,Hash} ->
+            {not_found, Hash};    
+        {Rest, {not_found, Hash}, _State} ->
+            {not_found, Hash};    
+        {Rest, Value, _State} ->
+            ?VALUE(Value),
+            decode(list, Rest, List ++ [Value], _State)
+    end;
+decode(type_definition, ForeignType, Bin, State) ->
+    {Rest,Count, _State} = decode(Bin, State),
+    {NewRest,FieldNames, NewState} = decode(field, Rest, Count, [], _State),
+    TypeDef = type_decoding:build_foreign_view(ForeignType,FieldNames,NewState),
+    {NewRest, TypeDef, NewState}.
+decode(field, <<$z,Rest/binary>>, Count, Acc, State) -> {Rest, Acc, State};
+decode(field, Rest, 0, Acc, State) -> {Rest, Acc, State};
+decode(field, Bin, Count, Acc, State) ->
+    {Rest,Field, _State} = decode(Bin, State),
+    case Field of
+        {not_found,Hash} ->
+            {not_found,Hash};
+        {type_def,_,_,_} ->
+            {_Rest, Object, __State} = decode(Rest, _State),
+            decode(field, _Rest, Count - 1, Acc ++ [Object], __State);
+        _ ->
+            decode(field, Rest, Count - 1, Acc ++ [Field], _State)
+    end.
+
+%---------------------------------------------------------------------------
+% Encoding
+%---------------------------------------------------------------------------
+
+encode(type_query, Hash) -> 
+    ?START(q,[?M,?m]),
+    ?VALUE(<<Hash:32>>),
+    <<$q,?M,?m,Hash:32/unsigned,$z>>;
+encode(type_query_ok, Hash) -> <<$y,?M,?m,Hash:32/unsigned,$z>>;
+encode(type_information, TypeDef = #type_def{fieldnames = FieldNames,
+                                             foreign_type = ForeignType}) ->
+    Size = size(ForeignType),
+    Count = count_fields(TypeDef),
+    Int = encode(int, Count, []),
+    _FieldNames = lists:map(fun erlang_to_camel_case/1,FieldNames),
+    {AccOut, _} = lists:foldl(fun encode/2,{<<>>, []},_FieldNames),
+    Hash = erlang:phash2(TypeDef),
+    <<$O,Hash:32/unsigned,$t,Size:16/unsigned,ForeignType/binary,Int/binary,AccOut/binary,$z>>;
+
+encode(Value, {Acc,State}) ->
+    case encode(Value, State) of
+        {ValueBin, _State} ->
+            {<<Acc/binary,ValueBin/binary>>,_State};
+        ValueBin ->
+            {<<Acc/binary,ValueBin/binary>>,State}
+    end;
+
+% Null
+encode(undefined, State) -> <<$N>>;
+
+encode(Value, State) when is_integer(Value) -> encode(int, Value, State);
+encode(Value, State) when is_float(Value) -> encode(double, Value, State);
+encode(Value, State) when is_boolean(Value) -> encode(boolean, Value, State);
+encode(Value, State) when is_atom(Value) -> encode(string, atom_to_list(Value), State);
+encode(Value, State) when is_list(Value) -> encode(list, Value, State);
+encode(Value, State) when is_pid(Value) -> throw("Erlang Pid encoding not supported");
+%% Assume that a binary is a string
+%% TODO what about encapsulating binary-data????
+encode(Value, State) when is_binary(Value) -> encode(string, Value, State);
+%% TODO The order of this is_tuple guard worries me a bit, needs further attention.
+encode(Value, State) when is_tuple(Value) -> encode(object, Value, State).
+
+% x20               # zero-length binary data
+% x23 x01 x02 x03   # 3 octet data
+% B x10 x00 ....    # 4k final chunk of data
+% b x04 x00 ....    # 1k non-final chunk of data
+encode(binary, <<>>, State) -> <<16#20>>;
+encode(binary, Value, State) when size(Value) < 15 ->
+    Size = 16#20 + size(Value),
+    <<Size:8/unsigned,Value/binary>>;
+encode(binary, Value, State) -> encode(binary, Value, <<>>, State);
+encode(boolean, true, State) -> <<$T>>;
+encode(boolean, false, State) -> <<$F>>;
+encode(timestamp, {MegaSecs, Secs, MicroSecs}, State) ->
+    Date = MegaSecs * ?MegaSeconds + Secs * ?Seconds + MicroSecs div ?MicroSeconds,
+    <<$d,Date:64/unsigned>>;
+encode(localtime, DateTime={{Year,Month,Day},{Hour,Min,Sec}}, State) ->
+    [Universal] = calendar:local_time_to_universal_time_dst(DateTime),
+    Seconds = calendar:datetime_to_gregorian_seconds(Universal),
+    MilliSeconds = (Seconds - ?UnixEpoch) * 1000,
+    <<$d,MilliSeconds:64/unsigned>>;
+encode(double, 0.0, State) -> <<16#67>>;
+encode(double, 1.0, State) -> <<16#68>>;
+encode(double, Double, State) when Double >= -128.0, Double =< 127.0, Double == round(Double) ->
+    Byte = round(Double),
+    <<16#69, Byte/signed>>;
+encode(double, Double, State) when Double >= -32768.0, Double =< 32767.0, Double == round(Double) ->
+    Byte = round(Double),
+    <<16#6a, Byte:16/signed>>;
+encode(double, Double, State) ->
+    case <<Double/float>> of
+        <<B24,B16,B8,B0,0,0,0,0>> ->
+            <<16#6b,B24,B16,B8,B0>>;
+        Other ->
+            <<$D,Other/binary>>
+    end;
+encode(int, Int, State) when Int >= -16, Int =< 47 ->
+    _Int = Int + 16#90,
+    <<_Int:8>>;
+encode(int, Int, State) when Int >= -2048, Int =< 2047 ->
+    <<B1:8,B0:8>> = <<Int:16>>,
+    _B1 = B1 + 16#c8,
+    <<_B1,B0>>;
+encode(int, Int, State) when Int >= -262144, Int =< 262143 ->
+    <<B2:8,B1:8,B0:8>> = <<Int:24>>,
+    _B2 = B2 + 16#d4,
+    <<_B2,B1,B0>>;
+encode(int, Int, State) when Int > 16#100000000 -> <<$L,Int:64/unsigned>>;
+encode(int, Int, State) -> <<$I,Int:32/unsigned>>;
+encode(long, Long, State) when Long >= -8, Long =< 15 ->
+    _Long = Long + 16#e0,
+    <<_Long:8>>;
+encode(long, Long, State) when Long >= -2048, Long =< 2047 ->
+    <<B1:8,B0:8>> = <<Long:16>>,
+    _B1 = B1 + 16#f8,
+    <<_B1,B0>>;
+encode(long, Long, State) when Long >= -262144, Long =< 262143 ->
+    <<B2:8,B1:8,B0:8>> = <<Long:24>>,
+    _B2 = B2 + 16#3c,
+    <<_B2,B1,B0>>;
+encode(long, Long, State) when Long >= -16#100000000, Long =< 16#100000000 -> <<16#77,Long:32>>;
+encode(long, Long, State) -> <<$L,Long:64/unsigned>>;
+encode(string, <<>>, State) -> <<0>>;
+encode(string, [], State) -> <<0>>;
+encode(string, String, State) when is_binary(String)-> encode(string, binary_to_list(String), State);
+encode(string, String, State) when is_list(String)->
+    UTF8 = case catch xmerl_ucs:is_incharset(String,'utf-8') of
+               true ->
+                   String;
+               _ ->
+                   xmerl_ucs:to_utf8(String)
+           end,
+    %% There is a question pending on the hessian list as to whether the length
+    %% refers to the UTF-8 or the native length
+    %Length = length(String),
+    Length = length(UTF8),
+    if
+        Length < 32 ->
+            Bin = list_to_binary(UTF8),
+            <<Length:8,Bin/binary>>;
+        true ->
+            encode(string, list_to_binary(String), <<>>, State)
+    end;
+encode(dictionary, Dict, State) ->
+    Encoder = fun(Key, Value, AccIn) ->
+                KeyBin = encode(Key, State),
+                ValueBin = encode(Value, State),
+                <<AccIn/binary,KeyBin/binary,ValueBin/binary>> end,
+    AccOut = dict:fold(Encoder, <<$M>>, Dict),
+    <<AccOut/binary,$z>>;
+%% Length
+%::= 'l' b3 b2 b1 b0
+%::= x6e int
+encode(length, List, State) ->
+    Length = length(List),
+    case encode(int, Length, State) of
+        <<$I,Int/binary>> ->
+            <<$l,Int/binary>>;
+        Other ->
+            <<16#6e,Other/binary>>
+    end;
+%% Lists
+encode(list, List, State) ->
+    Length = encode(length, List, State),
+    encode(list, List, <<$V,Length/binary>>, State);
+encode(method, Method, State) when is_atom(Method) ->
+    String = atom_to_list(Method),
+    encode(method, String, State);
+encode(method, Method, State) when is_binary(Method) ->
+    _Method = erlang_to_camel_case(Method),
+    Size = size(_Method),
+    <<$m,Size:16/unsigned,_Method/binary>>;
+%---------------------------------------------------
+% TODO I don't think this ever gets called
+encode(method, String, State) when is_list(String) ->
+    _String = erlang_to_camel_case(String),
+    Length = string:len(_String),
+    Bin = list_to_binary(_String),
+    <<$m,Length:16/unsigned,Bin/binary>>;
+%---------------------------------------------------
+encode(type, FullyQualifiedName, State) when is_list(FullyQualifiedName) ->
+    Bin = list_to_binary(FullyQualifiedName),
+    encode(type,Bin, State);
+encode(type, FullyQualifiedName, State) when is_binary(FullyQualifiedName) ->
+    Length = size(FullyQualifiedName),
+    <<$t,Length:16,FullyQualifiedName/binary>>;
+%% TODO implement header
+%% reply   ::= r x01 x00 header* object z
+%%         ::= r x01 x00 header* fault z
+encode(reply, ok, State) -> <<$r,?M,?m,$N,$z>>;
+encode(reply, {ok, Object}, State) -> encode(reply, Object, State);
+encode(reply, {error, {Error, Reason} }, State) -> encode(fault, Error, Reason, State);
+encode(reply, Object, State) ->
+    ?START(r,[?M,?m]),
+    Bin = case encode(Object, State) of
+              {_Bin, NewState} ->
+                    _Bin;
+              _Bin ->
+                  _Bin
+          end,
+    <<$r,?M,?m,Bin/binary,$z>>;
+encode(object, DateTime = {MegaSecs, Secs, MicroSecs}, State) 
+    when is_integer(MegaSecs), is_integer(Secs), is_integer(MicroSecs)->
+    ?LOG("Employing date heuristic"),
+    encode(timestamp,DateTime,State);    
+encode(object, Object, State) when is_tuple(Object) ->
+    [NativeType|Values] = tuple_to_list(Object),
+    {TypeEncoding, EncodedRef, NewState} =
+        case type_encoding:visit(NativeType,State) of
+            {ref, Ref} ->
+                encode(type_information, {ref, Ref}, State);
+            {hash, Hash, Ref, State0} ->
+                encode(type_information, {hash, Hash, Ref}, State0)
+        end,        
+    {AccOut, _NewState} = lists:foldl(fun encode/2,{<<>>, NewState},Values),
+    {<<TypeEncoding/binary,$o,EncodedRef/binary,AccOut/binary>>, _NewState};
+encode(type_information, {ref, Ref}, State) ->
+    {<<>>, encode(int, Ref, State), State};
+encode(type_information, {hash, Hash, Ref}, State) ->
+    EncodedRef = encode(int, Ref, State),
+    {<<$O,Hash:32/unsigned>>, EncodedRef, State}.
+encode(binary, Value, <<>>, State) when size(Value) =< ?CHUNK_SIZE ->
+    Size = size(Value),
+    <<$B,Size:16,Value/binary>>;
+encode(binary, Value, Acc, State) when size(Value) =< ?CHUNK_SIZE ->
+    Size = size(Value),
+    <<Acc/binary,$B,Size:16,Value/binary>>;
+encode(binary, Value, <<>>, State) ->
+    <<Chunk:?CHUNK_SIZE/binary,Rest/binary>> = Value,
+    encode(binary, Rest, <<$b,?CHUNK_SIZE:16,Chunk/binary>>, State);
+encode(binary, Value, Acc, State) ->
+    <<Chunk:?CHUNK_SIZE/binary,Rest/binary>> = Value,
+    encode(binary, Rest, <<Acc/binary,$b,?CHUNK_SIZE:16,Chunk/binary>>, State);
+encode(string, Value, Acc, State) when size(Value) =< ?CHUNK_SIZE ->
+    Size = size(Value),
+    <<Acc/binary,$S,Size:16,Value/binary>>;
+encode(string, Value, <<>>, State) ->
+    <<Chunk:?CHUNK_SIZE/binary,Rest/binary>> = Value,
+    encode(string, Rest, <<$s,?CHUNK_SIZE:16,Chunk/binary>>, State);
+encode(string, Value, Acc, State) ->
+    <<Chunk:?CHUNK_SIZE/binary,Rest/binary>> = Value,
+    encode(string, Rest, <<Acc/binary,$s,?CHUNK_SIZE:16,Chunk/binary>>, State);
+%---------------------------------------------------------------------------
+% List Encoding
+%---------------------------------------------------------------------------
+encode(list, Type, List, State) when is_binary(Type) ->
+    TypeLength = size(Type),
+    ListLength = length(List),
+    encode(list, List, <<$V,$t,TypeLength:16/unsigned,Type/binary,$l,ListLength:32/unsigned>>, State);
+encode(list, List, Acc0, State) when is_binary(Acc0) ->
+    {AccOut, State} = lists:foldl(fun encode_accumulate/2, {Acc0,State}, List),
+    <<AccOut/binary,$z>>;
+%---------------------------------------------------------------------------
+% Call and Reply Encoding
+%---------------------------------------------------------------------------
+%% TODO implement header call    ::= c x01 x00 header* method object* z
+encode(call, Method, Args, State) ->
+    encode(call, Method, Args, fun encode_accumulate/2, State);
+encode(fault, _Error, _Reason, State) ->
+    encode(fault, <<"ServiceException">>, _Error, _Reason, State).
+encode(fault, Code, _Error, _Reason, State) ->
+    EncodedCode = encode(string,Code, State),
+    <<131,100,L2:16/unsigned,Error/binary>> = term_to_binary(_Error),
+    EncodedError = encode(string,Error, State),
+    <<$r,?M,?m,$f,
+      4,"code",EncodedCode/binary,
+      7,"message",EncodedError/binary,
+      6,"detail",31,"Stack trace not yet implemented",
+      $z>>;
+encode(call, Method, Args, Fun, State) when is_function(Fun) ->
+    MethodBin = encode(method,Method, State),
+    {Bin, NewState} = lists:foldl(Fun, {<<>>, State}, Args),
+    <<$c,?M,?m,MethodBin/binary,Bin/binary,$z>>.
+
+%---------------------------------------------------------------------------
+% Invocation
+%---------------------------------------------------------------------------
+
+invoke(Module,Bin,DecodingState,EncodingState) ->
+    case decode(Bin,DecodingState) of 
+        {error, Reason} ->
+            encode(fault, decoding_error, Reason, EncodingState);
+        {not_found, Hash} ->
+            encode(type_query,Hash);
+        {peer_cannot_resolve,Hash} ->
+            %% TODO what should happen here? Is this good enough?
+            encode(reply,ok,[]);    
+        {type_query_ack, Hash} ->
+            %% TODO This has not been implemented yet
+            ok;    
+        %% Don't know if I like this weakly typed differentiation,
+        %% it seems a bit brittle    
+        {_,{Hash,TypeDef},_} ->
+            encode(type_query_ok, Hash);
+        %% TODO look into whether this 2nd branch for type_query_ok is needed,
+        %% or whether to refactor the corresponding return value from the
+        %% decode function
+        {_,TypeDef,_} ->
+            encode(type_information, TypeDef);        
+        [Function,Args] ->
+            Result = apply(Module,Function,Args),
+            encode(reply,Result,EncodingState)
+    end.
+
+%% This is used for synchronous transports that can respond
+%% to a type query    
+call(Dispatcher,Method,Args,DecodingState,EncodingState) ->
+    Bin = encode(call,Method,Args,EncodingState),
+    Response0 = apply(Dispatcher,[Bin]),
+    case decode(Response0,DecodingState) of
+        {Hash,TypeDef,_} ->
+            ok = send_type_negotiation(Dispatcher,TypeDef,DecodingState),
+            Response = apply(Dispatcher,[Bin]),
+            decode(Response,DecodingState);    
+        Other ->
+            Other             
+    end.
+    
+send_type_negotiation(Dispatcher,TypeDef,DecodingState) ->
+    TypeDefBin = hessian:encode(type_information, TypeDef),
+    Response = apply(Dispatcher,[TypeDefBin]),
+    case hessian:decode(Response,DecodingState) of
+        ok ->
+            ok;    
+        Error ->
+            throw({type_negotiation_error,Error})             
+    end.    
+        
+%---------------------------------------------------------------------------
+% Utility methods
+%---------------------------------------------------------------------------
+erlang_to_camel_case(String) when is_binary(String) ->
+    AsList = binary_to_list(String),
+    AsCamel = lists:foldl(fun camelize/2,[],AsList),
+    list_to_binary(AsCamel);
+erlang_to_camel_case(String) when is_atom(String) ->
+    AsList = atom_to_list(String),
+    AsCamel = lists:foldl(fun camelize/2,[],AsList),
+    list_to_binary(AsCamel).    
+        
+camelize(Element,Acc) when Element == $_ -> [$_|Acc];
+camelize(Element,[$_|Acc]) -> lists:append(Acc,[Element - 16#20]);
+camelize(Element,Acc) -> lists:append(Acc,[Element]).
+    
+
+%% May want to take another look at this:
+%% All of the primitive encoding functions do not return the state.
+%% Maybe they should to avoid differentiations like this.
+encode_accumulate(Value, {Acc, State}) ->
+    case encode(Value, State) of 
+        {Encoded,NewState} ->
+             {<<Acc/binary,Encoded/binary>>,NewState};
+        Encoded ->
+            {<<Acc/binary,Encoded/binary>>,State}
+    end.
+
+is_type_def(#type_def{}) -> true;
+is_type_def(_) -> false.
+
+count_fields(#type_def{fieldnames = FieldNames}) -> length(FieldNames).
diff --git a/src/hessianDecode.erl b/src/hessianDecode.erl
new file mode 100755
index 0000000..adc06fe
--- /dev/null
+++ b/src/hessianDecode.erl
@@ -0,0 +1,347 @@
+-module(hessianDecode).
+
+-include("hessian.hrl").
+
+-export([decode/2]).
+%%-export([init/0]).
+
+%%-record(decoding_state,{type_pool = dict:new(), reference_pool = dict:new()}).
+-record(decoding_state,{type_pool = dict:new(), reference_pool = dict:new(),obj_define_no=0}).
+%---------------------------------------------------------------------------
+% Decoding
+%---------------------------------------------------------------------------
+decode_str(Rest, 0, R) ->
+	{list_to_binary(xmerl_ucs:to_utf8(lists:reverse(R))), Rest}; 
+decode_str(<<C/utf8, Rest/binary>>, N, R) ->
+	decode_str(Rest, N-1, [C|R]).
+
+% Call
+decode(<<$H,?M,?m,$C,Bin/binary>>, State) ->
+	{Rest, Function, _State} = decode(Bin,State),
+	{Rest2, Count, __State} = decode(Rest,_State),
+	case decode(list, Rest2,Count,[], __State) of
+		{error, Encoded} ->
+			{error, Encoded};
+		{not_found, Hash} ->
+			{not_found, Hash};    
+		{_Rest, Arguments, _NewState} ->
+			[Function, Arguments]
+	end;
+% Fault
+decode(<<$H,?M,?m,$F,
+		 Rest/binary>>, State) ->
+	{_Rest,#map{dict=Dict},_State} = decode(Rest, State),
+	{ok, Message} = dict:find(<<"message">>, Dict),
+	{error, Message};
+% Reply
+decode(<<$H,?M,?m,$R,Args/binary>>, State) ->
+	case decode(Args,[], State) of
+		{<<>>, Decoded,_State} ->
+			TypeSet = get_type_set(_State),
+			case Decoded of
+				[Value] ->
+					{Value,TypeSet};
+				[H|T] ->
+					{[H|T],TypeSet}
+			end;
+		{error, Encoded} ->
+			{error, Encoded}
+	end;
+% Binaries
+decode(<<16#20,Rest/binary>>, State) -> {Rest, <<>>, State};
+decode(<<Len:8/unsigned,Rest/binary>>, State) when Len =< 16#2f, 16#20 < Len ->
+	_Len = Len - 16#20,
+	<<Bin:_Len/binary,_Rest/binary>> = Rest,
+	{_Rest, Bin, State};
+decode(<<$B,Len:16/unsigned,Bin:Len/binary,Rest/binary>>, State) -> {Rest, Bin, State};
+decode(<<$b,Rest/binary>>,State) -> decode(<<$b,Rest/binary>>, [], State);
+%% Booleans
+decode(<<$T,Rest/binary>>, State) -> {Rest, true, State};
+decode(<<$F,Rest/binary>>, State) -> {Rest, false, State};
+%% Dates
+decode(<<16#4a,Date:64/unsigned,Rest/binary>>, State) ->
+	MegaSecs = Date div ?MegaSeconds,
+	Secs = (Date - MegaSecs * ?MegaSeconds) div ?Seconds,
+	MicroSecs = (Date - MegaSecs * ?MegaSeconds - Secs * ?Seconds) * ?MicroSeconds,
+	{Rest, {MegaSecs, Secs, MicroSecs}, State};
+decode(<<16#4b,Date:32/unsigned,Rest/binary>>, State) ->
+	MegaSecs = (Date * 60000) div ?MegaSeconds,
+	Secs = (Date * 60000 - MegaSecs * ?MegaSeconds) div ?Seconds,
+	{Rest, {MegaSecs, Secs, 0}, State};
+%% Doubles
+decode(<<16#5b,Rest/binary>>, State)-> {Rest, 0.0, State};
+decode(<<16#5c,Rest/binary>>, State)-> {Rest, 1.0, State};
+decode(<<16#5d,Int:8/signed,Rest/binary>>, State)-> {Rest, float(Int), State};
+decode(<<16#5e,Int:16/signed,Rest/binary>>, State)-> {Rest, float(Int), State};
+decode(<<16#5f,Int:32/signed,Rest/binary>>, State)->
+	<<Double:64/float>> = <<Int:32,0,0,0,0>>,
+	{Rest, Double, State};
+decode(<<$D,Double:64/float,Rest/binary>>, State)-> {Rest, Double, State};
+%% Ints
+decode(<<$I,Int:32/signed,Rest/binary>>, State)-> {Rest, Int, State};
+decode(<<Int:8,Rest/binary>>, State) when Int >= 16#80, Int =< 16#bf -> {Rest, Int - 16#90, State};
+decode(<<B2:8,B1:8,B0:8,Rest/binary>>, State) when B2 >= 16#d0, B2 =< 16#d7 -> {Rest, ((B2 - 16#d4) bsl 16) + (B1 bsl 8) + B0, State};
+decode(<<B1:8,B0:8,Rest/binary>>, State) when B1 >= 16#c0, B1 =< 16#cf -> {Rest, ((B1 - 16#c8) bsl 8) + B0, State};
+%% Longs
+decode(<<$L,Long:64/signed,Rest/binary>>, State)-> {Rest, Long, State};
+decode(<<16#59,Long:32/signed,Rest/binary>>, State) -> {Rest, Long, State};
+decode(<<Long:8,Rest/binary>>, State) when Long >= 16#d8, Long =< 16#ef -> {Rest, Long - 16#e0, State};
+decode(<<B2:8,B1:8,B0:8,Rest/binary>>, State) when B2 >= 16#38, B2 =< 16#3f -> {Rest, ((B2 - 16#3c) bsl 16) + (B1 bsl 8) + B0, State};
+decode(<<B1:8,B0:8,Rest/binary>>, State) when B1 >= 16#f0, B1 =< 16#ff -> {Rest, ((B1 - 16#f8) bsl 8) + B0, State};
+%% Strings
+decode(<<0,Rest/binary>>, State) -> {Rest, <<>>, State};
+decode(<<Len:8,Rest/binary>>, State) when Len < 32 -> 
+	{String, NewRest} = decode_str(Rest, Len, []),
+	{NewRest, String, State};
+decode(<<B1:8,B0:8,Rest/binary>>, State) when B1 =< 16#33,B1 >= 16#30 -> 
+	Len = ((B1 - 16#30) bsl 8) + B0,
+	{String, NewRest} = decode_str(Rest, Len, []),
+	{NewRest, String, State};
+decode(<<$S,Len:16/unsigned,Rest/binary>>, State) -> 
+	{String, NewRest} = decode_str(Rest, Len, []),
+	{NewRest, String, State};
+decode(<<$R,Rest/binary>>, State) -> decode(<<$R,Rest/binary>>,[], State);
+%% Nulls
+decode(<<$N,Rest/binary>>, State) -> {Rest, undefined, State};
+%% References
+decode(<<$Q,Bin/binary>>, State)-> 
+	{Rest, IntRef, _State} = decode(Bin,State),
+	{Rest, {ref, IntRef}, _State};
+%% Maps
+decode(<<$M,Map/binary>>, State) -> 
+	{Rest,Type,_State} = decode(Map, State),
+	{_Refnum,__State} = visit(#type_def{foreign_type = map},_State),
+	{_Rest,Dict, NewState} = decode(map, Rest, dict:new(), __State),
+	{_Rest,#map{refNo=_Refnum,type=Type,dict=Dict},NewState};
+decode(<<$H,Map/binary>>, State) -> 
+	{_Refnum,_State} = visit(#type_def{foreign_type = map},State),
+	{_Rest,Dict, NewState} = decode(map, Map, dict:new(), _State),
+	{_Rest,#map{refNo=_Refnum,dict=Dict},NewState};
+%% Lists
+% 'V' type int value*   # fixed-length list
+decode(<<$V,Bin/binary>>, State) -> 
+	{Rest1,_Type,_State1} = decode(Bin,State),
+	{_Refnum,__State} = visit(#type_def{foreign_type = list},_State1),
+	{Rest2,Len,_State2} = decode(Rest1,__State),
+	{NewRest,List,NewState} = decode(list, Rest2, Len, [], _State2),
+	{NewRest,#list{refNo=_Refnum,len=Len,type=_Type,values=List},NewState};
+% 'X' int value*        # fixed-length untyped list
+decode(<<$X,Bin/binary>>, State) ->
+	{Rest1,Len,_State} = decode(Bin,State),
+	{_Refnum,__State} = visit(#type_def{foreign_type = list},_State),
+	{NewRest,List,NewState} = decode(list, Rest1, Len, [], __State),
+	{NewRest,#list{refNo=_Refnum,len=Len,values=List},NewState};
+% [x70-77] type value*  # fixed-length typed list
+decode(<<H:5,Len:3,Bin/binary>>, State) when H == 14 ->
+	{Rest1,_Type,_State} = decode(Bin,State),
+	{_Refnum,__State} = visit(#type_def{foreign_type = list},_State),
+	{NewRest,List,NewState} = decode(list, Rest1, Len, [], __State),
+	{NewRest,#list{refNo=_Refnum,len=Len,type=_Type,values=List},NewState};
+% [x78-7f] value*       # fixed-length untyped list
+decode(<<H:5,Len:3,Bin/binary>>, State) when H == 15 ->
+	{_Refnum,_State} = visit(#type_def{foreign_type = list},State),
+	{NewRest,List,NewState} = decode(list, Bin, Len, [], _State),
+	{NewRest,#list{refNo=_Refnum,len=Len,values=List},NewState};
+% 'U' type value* 'Z'   # variable-length list
+decode(<<$U,Bin/binary>>, State) ->
+	{Rest1,_Type,_State} = decode(Bin,State),
+	{_Refnum,__State} = visit(#type_def{foreign_type = list},_State),
+	{NewRest,List,NewState} = decode(list, Rest1, [], __State),
+	{NewRest,#list{refNo=_Refnum,type=_Type,values=List},NewState};
+% 'W' value* 'Z'        # variable-length untyped list
+decode(<<$W,Bin/binary>>, State) ->
+	{_Refnum,_State} = visit(#type_def{foreign_type = list},State),
+	{NewRest,List,NewState} = decode(list, Bin, [], _State),
+	{NewRest,#list{refNo=_Refnum,values=List},NewState};
+decode(<<$C,Bin/binary>>, State0) ->
+	{Rest1,Type,State1} = decode(Bin,State0), %% Rest1 剩余字节码, Type 对象类型
+	{Rest, TypeDef, State} = decode(type_definition,Type,Rest1,State1),
+	NewState = type_decoding:hash_store(TypeDef,State),
+	decode(Rest,NewState);
+decode(<<$O,Bin/binary>>, State) ->
+	{Rest,Ref,_State} = decode(Bin, State),
+	case type_decoding:hash_lookup(Ref, _State) of
+		{not_found, Ref} ->
+			{Rest, {not_found, Ref}, _State};
+		ForeignView ->
+			#type_def{fieldnames = ForeignFieldNames} = ForeignView,
+			{_Refnum,__State} = type_decoding:visit(ForeignView,_State),
+			Count = count_fields(ForeignView),
+			case decode(field, Rest, Count,[], __State) of
+				{not_found,Hash} ->
+					{not_found,Hash};
+				{_Rest,FieldValues, NewState} ->
+					Object = type_decoding:project_native_view(ForeignFieldNames,FieldValues,ForeignView),
+%%					{_Rest, #object{refNo=_Refnum, typeRef=Ref,values=Object}, NewState}
+					{_Rest, Object, NewState}
+			end
+	end;      
+decode(<<H:4,Ref:4,Rest/binary>>, _State) when H == 6 ->
+	case type_decoding:hash_lookup(Ref, _State) of
+		{not_found, Ref} ->
+			{Rest, {not_found, Ref}, _State};
+		ForeignView ->
+			#type_def{fieldnames = ForeignFieldNames} = ForeignView,
+			{_Refnum,__State} = visit(ForeignView,_State),
+			Count = count_fields(ForeignView),
+			case decode(field, Rest, Count,[], __State) of
+				{not_found,Hash} ->
+					{not_found,Hash};
+				{_Rest,FieldValues, NewState} ->
+					Object = type_decoding:project_native_view(ForeignFieldNames,FieldValues,ForeignView),
+					%%{_Rest, #object{refNo =_Refnum, typeRef=Ref,values=Object}, NewState}
+					{_Rest, Object, NewState}
+			end
+	end;
+%% Anything else
+decode(<<Unexpected/binary>>, State) ->
+	{error, hessianEncode:encode(fault, <<"ProtocolException">>, unexpected_byte_sequence, Unexpected, State) }.
+decode(<<$b,Len:16/unsigned,Bin:Len/binary,$b,Rest/binary>>, Acc, State) ->
+	decode(<<$b,Rest/binary>>,Acc ++ [Bin], State);
+decode(<<$b,Len:16/unsigned,Bin:Len/binary,$B,Rest/binary>>, Acc, State) ->
+	_Acc = Acc ++ [Bin],
+	{_Rest,_Bin, State} = decode(<<$B,Rest/binary>>, State),
+	{_Rest, list_to_binary(_Acc ++ [_Bin]), State};
+decode(<<$R,Len:16/unsigned,Rest/binary>>,Acc, State) ->
+	{_String, NewRest} = decode_str(Rest, Len, []),
+	<<H:8,_/binary>> = NewRest,
+	case H of 
+		$R -> decode(NewRest,list_to_binary([Acc|[_String]]), State);
+		$S -> {_Rest,_Bin, _State} = decode(NewRest, State),
+			  _Acc2 =[Acc |[_String]],
+			  {_Rest, list_to_binary(_Acc2 ++ [_Bin]), _State}
+	end;
+decode(<<>>, List, State) -> {<<>>, List, State};
+decode(<<$Z>>, List, State) -> {<<>>, List, State};
+decode(Args, List, State) ->
+	case decode(Args,State) of
+		{Rest,{ref, Ref}, _State} ->
+			decode(Rest, List ++ [{ref, Ref}] , _State);
+		{Rest, [H|T], _State} ->
+			decode(Rest, List ++ [H|T], _State);
+		{Rest, Result, _State} ->
+			decode(Rest, List ++ [Result], _State);
+		{error, Encoded} ->
+			{error, Encoded}
+	end.
+decode(map, <<$Z>>, Dict, State) -> {<<>>,Dict, State};
+decode(map, <<$Z,Rest/binary>>, Dict, State) -> {Rest,Dict, State};
+decode(map, Bin, Dict, State) ->
+	{_Rest, Key, _State} = decode(Bin, State),
+	case decode(_Rest, _State) of
+		{Rest, {ref, Ref}, __State} ->
+			%Value = lists:nth(Ref + 1, List),
+			Value = Ref,
+			decode(map, Rest, dict:store(Key, {ref, Value}, Dict), __State);
+		{Rest, Value, __State} ->
+			decode(map, Rest, dict:store(Key, Value, Dict), __State)
+	end;
+decode(list, <<>>, List, State) -> {<<>>,lists:reverse(List), State};
+decode(list, <<$Z>>, List, State) -> {<<>>,lists:reverse(List), State};
+decode(list, <<$Z,Rest/binary>>, List, State) -> {Rest, lists:reverse(List), State};
+decode(list, Bin, List, State) ->
+	case decode(Bin, State) of
+		{error, Encoded} ->
+			{error, Encoded};
+		{not_found,Hash} ->
+			{not_found, Hash};    
+		{_Rest, {not_found, Hash}, _State} ->
+			{not_found, Hash};    
+		{Rest, Value, _State} ->
+            decode(list, Rest, [Value|List], _State)
+	end;
+decode(type_definition, ForeignType, Bin, State) ->
+	{Rest,Count, _State} = decode(Bin, State),
+	{NewRest,FieldNames, NewState} = decode(field, Rest, Count, [], _State),
+	%% change 用回之前的 build_foreign_view NewState 不变
+	{TypeDef,NewState2} = type_decoding:build_foreign_view(ForeignType,FieldNames,NewState),
+	{NewRest, TypeDef, NewState2}.
+decode(list, Bin, 0, List, State) -> {Bin, lists:reverse(List), State};
+decode(list, Bin, Len, List, State) ->
+    case decode(Bin, State) of
+        {error, Encoded} ->
+            {error, Encoded};
+        {not_found,Hash} ->
+            {not_found, Hash};    
+        {_Rest, {not_found, Hash}, _State} ->
+            {not_found, Hash};    
+        {Rest, Value, _State} ->
+            decode(list, Rest, Len - 1, [Value|List], _State)
+    end;
+decode(field, Rest, 0, Acc, State) -> {Rest, Acc, State};
+decode(field, <<$Z,Rest/binary>>, _Count, Acc, State) -> {Rest, Acc, State};
+decode(field, Bin, Count, Acc, State) ->
+	{Rest,Field, _State} = decode(Bin, State),
+	case Field of
+		{not_found,Hash} ->
+			{not_found,Hash};
+		_ ->
+			decode(field, Rest, Count - 1, Acc ++ [Field], _State)
+	end.
+
+get_type_set(#decoding_state{type_pool = Pool}) ->
+	case dict:to_list(Pool) of 
+		[] -> [];
+		Data -> [Value || {_Key,Value} <- Data]
+	end.
+
+build_foreign_view(ForeignType,FieldNames,State) ->
+	ForeignView = FieldNames,
+	#decoding_state{type_pool = OldPool} = State,
+	Native = dict:size(OldPool),
+	NewPool = dict:store(Native, 
+						 #type_def{native_type = Native,
+								   foreign_type = ForeignType,
+								   fieldnames = ForeignView}, 
+						 OldPool),
+	{
+	 #type_def{native_type = Native,
+			   foreign_type = ForeignType,
+			   fieldnames = ForeignView},
+	 State#decoding_state{type_pool = NewPool}
+	}.
+
+project_native_view(ForeignView,ForeignData,
+                    #type_def{native_type = _NativeType, foreign_type = _ForeignType, fieldnames = NativeView}) ->
+    AsDict = dict:from_list(lists:zip(ForeignView,ForeignData)),
+    NativeData = [dict:fetch(Key,AsDict) || Key <- NativeView],
+	NativeData.
+
+visit(TypeDef, State = #decoding_state{reference_pool = OldPool}) ->
+    Size = dict:size(OldPool),
+    NewPool = dict:store(Size, TypeDef, OldPool),
+    {Size,State#decoding_state{reference_pool = NewPool}}.
+
+%%hash_lookup(Hash,_State) ->
+%%    init(false),
+%%    case ets:lookup(hashes, Hash) of
+%%        [] ->
+%%            {not_found, Hash};
+%%        [{Hash,TypeDef}] ->
+%%            TypeDef
+%%    end.
+
+%%hash_store(TypeDef = #type_def{native_type = Hash}, State) ->
+%%    init(false),
+%%    ets:insert(hashes,{Hash,TypeDef}),
+%%    State.
+%%
+%%init() -> init(true).
+%%
+%%init(Delete) when is_boolean(Delete) ->
+%%    case ets:info(hashes) of
+%%        undefined ->
+%%            ets:new(hashes,[public,named_table]);
+%%        _ ->
+%%            if
+%%                Delete ->
+%%                    ets:delete(hashes),
+%%                    ets:new(hashes,[public,named_table]);
+%%                true ->
+%%                    ok
+%%            end
+%%    end,
+%%    #decoding_state{}.
+
+count_fields(#type_def{fieldnames = FieldNames}) -> length(FieldNames).
+
diff --git a/src/hessianDecode2.erl b/src/hessianDecode2.erl
new file mode 100644
index 0000000..93c8173
--- /dev/null
+++ b/src/hessianDecode2.erl
@@ -0,0 +1,361 @@
+-module(hessianDecode2).
+
+-include("hessian.hrl").
+
+-export([decode/2]).
+-export([init/0]).
+-export([get_deftype/2]).
+-record(decoding_state,{type_pool = dict:new(), reference_pool = dict:new(),hash_pool = dict:new()}).
+
+%---------------------------------------------------------------------------
+% Decoding
+%---------------------------------------------------------------------------
+decode_str(Rest, 0, R) ->
+    {list_to_binary(xmerl_ucs:to_utf8(lists:reverse(R))), Rest};
+decode_str(<<C/utf8, Rest/binary>>, N, R) ->
+    decode_str(Rest, N-1, [C|R]).
+
+% Call
+decode(<<$H,?M,?m,$C,Bin/binary>>, State) ->
+    {Rest, Function, _State} = decode(Bin,State),
+    {Rest2, Count, __State} = decode(Rest,_State),
+    case decode(list, Rest2,Count,[], __State) of
+        {error, Encoded} ->
+            {error, Encoded};
+        {not_found, Hash} ->
+            {not_found, Hash};
+        {_Rest, Arguments, _NewState} ->
+            [Function, Arguments]
+    end;
+% Fault
+decode(<<$H,?M,?m,$F,
+    Rest/binary>>, State) ->
+    {_Rest,#map{dict=Dict},_State} = decode(Rest, State),
+    {ok, Message} = dict:find(<<"message">>, Dict),
+    {error, Message};
+% Reply
+decode(<<$H,?M,?m,$R,Args/binary>>, State) ->
+    case decode(Args,[], State) of
+        {<<>>, Decoded,_State} ->
+            TypeSet = get_type_set(_State),
+            case Decoded of
+                [Value] ->
+                    {Value,TypeSet};
+                [H|T] ->
+                    {[H|T],TypeSet}
+            end;
+        {error, Encoded} ->
+            {error, Encoded}
+    end;
+% Binaries
+decode(<<16#20,Rest/binary>>, State) -> {Rest, <<>>, State};
+decode(<<Len:8/unsigned,Rest/binary>>, State) when Len =< 16#2f, 16#20 < Len ->
+    _Len = Len - 16#20,
+    <<Bin:_Len/binary,_Rest/binary>> = Rest,
+    {_Rest, Bin, State};
+decode(<<$B,Len:16/unsigned,Bin:Len/binary,Rest/binary>>, State) -> {Rest, Bin, State};
+decode(<<$b,Rest/binary>>,State) -> decode(<<$b,Rest/binary>>, [], State);
+%% Booleans
+decode(<<$T,Rest/binary>>, State) -> {Rest, true, State};
+decode(<<$F,Rest/binary>>, State) -> {Rest, false, State};
+%% Dates
+decode(<<16#4a,Date:64/unsigned,Rest/binary>>, State) ->
+    MegaSecs = Date div ?MegaSeconds,
+    Secs = (Date - MegaSecs * ?MegaSeconds) div ?Seconds,
+    MicroSecs = (Date - MegaSecs * ?MegaSeconds - Secs * ?Seconds) * ?MicroSeconds,
+    {Rest, {MegaSecs, Secs, MicroSecs}, State};
+decode(<<16#4b,Date:32/unsigned,Rest/binary>>, State) ->
+    MegaSecs = (Date * 60000) div ?MegaSeconds,
+    Secs = (Date * 60000 - MegaSecs * ?MegaSeconds) div ?Seconds,
+    {Rest, {MegaSecs, Secs, 0}, State};
+%% Doubles
+decode(<<16#5b,Rest/binary>>, State)-> {Rest, 0.0, State};
+decode(<<16#5c,Rest/binary>>, State)-> {Rest, 1.0, State};
+decode(<<16#5d,Int:8/signed,Rest/binary>>, State)-> {Rest, float(Int), State};
+decode(<<16#5e,Int:16/signed,Rest/binary>>, State)-> {Rest, float(Int), State};
+decode(<<16#5f,Int:32/signed,Rest/binary>>, State)->
+    <<Double:64/float>> = <<Int:32,0,0,0,0>>,
+    {Rest, Double, State};
+decode(<<$D,Double:64/float,Rest/binary>>, State)-> {Rest, Double, State};
+%% Ints
+decode(<<$I,Int:32/signed,Rest/binary>>, State)-> {Rest, Int, State};
+decode(<<Int:8,Rest/binary>>, State) when Int >= 16#80, Int =< 16#bf -> {Rest, Int - 16#90, State};
+decode(<<B2:8,B1:8,B0:8,Rest/binary>>, State) when B2 >= 16#d0, B2 =< 16#d7 -> {Rest, ((B2 - 16#d4) bsl 16) + (B1 bsl 8) + B0, State};
+decode(<<B1:8,B0:8,Rest/binary>>, State) when B1 >= 16#c0, B1 =< 16#cf -> {Rest, ((B1 - 16#c8) bsl 8) + B0, State};
+%% Longs
+decode(<<$L,Long:64/signed,Rest/binary>>, State)-> {Rest, Long, State};
+decode(<<16#59,Long:32/signed,Rest/binary>>, State) -> {Rest, Long, State};
+decode(<<Long:8,Rest/binary>>, State) when Long >= 16#d8, Long =< 16#ef -> {Rest, Long - 16#e0, State};
+decode(<<B2:8,B1:8,B0:8,Rest/binary>>, State) when B2 >= 16#38, B2 =< 16#3f -> {Rest, ((B2 - 16#3c) bsl 16) + (B1 bsl 8) + B0, State};
+decode(<<B1:8,B0:8,Rest/binary>>, State) when B1 >= 16#f0, B1 =< 16#ff -> {Rest, ((B1 - 16#f8) bsl 8) + B0, State};
+%% Strings
+decode(<<0,Rest/binary>>, State) -> {Rest, <<>>, State};
+decode(<<Len:8,Rest/binary>>, State) when Len < 32 ->
+    {String, NewRest} = decode_str(Rest, Len, []),
+    {NewRest, String, State};
+decode(<<B1:8,B0:8,Rest/binary>>, State) when B1 =< 16#33,B1 >= 16#30 ->
+    Len = ((B1 - 16#30) bsl 8) + B0,
+    {String, NewRest} = decode_str(Rest, Len, []),
+    {NewRest, String, State};
+decode(<<$S,Len:16/unsigned,Rest/binary>>, State) ->
+    {String, NewRest} = decode_str(Rest, Len, []),
+    {NewRest, String, State};
+decode(<<$R,Rest/binary>>, State) -> decode(<<$R,Rest/binary>>,[], State);
+%% Nulls
+decode(<<$N,Rest/binary>>, State) -> {Rest, undefined, State};
+%% References
+decode(<<$Q,Bin/binary>>, State)->
+    {Rest, IntRef, _State} = decode(Bin,State),
+    {Rest, {ref, IntRef}, _State};
+%% Maps
+decode(<<$M,Map/binary>>, State) ->
+    {Rest,Type,_State} = decode(Map, State),
+    {_Refnum,__State} = visit(#type_def{foreign_type = map},_State),
+    {_Rest,Dict, NewState} = decode(map, Rest, dict:new(), __State),
+    {_Rest,#map{refNo=_Refnum,type=Type,dict=Dict},NewState};
+decode(<<$H,Map/binary>>, State) ->
+    {_Refnum,_State} = visit(#type_def{foreign_type = map},State),
+    {_Rest,Dict, NewState} = decode(map, Map, dict:new(), _State),
+    {_Rest,#map{refNo=_Refnum,dict=Dict},NewState};
+%% Lists
+% 'V' type int value*   # fixed-length list
+decode(<<$V,Bin/binary>>, State) ->
+    {Rest1,_Type,_State1} = decode(Bin,State),
+    {_Refnum,__State} = visit(#type_def{foreign_type = list},_State1),
+    {Rest2,Len,_State2} = decode(Rest1,__State),
+    {NewRest,List,NewState} = decode(list, Rest2, Len, [], _State2),
+    {NewRest,#list{refNo=_Refnum,len=Len,type=_Type,values=List},NewState};
+% 'X' int value*        # fixed-length untyped list
+decode(<<$X,Bin/binary>>, State) ->
+    {Rest1,Len,_State} = decode(Bin,State),
+    {_Refnum,__State} = visit(#type_def{foreign_type = list},_State),
+    {NewRest,List,NewState} = decode(list, Rest1, Len, [], __State),
+    {NewRest,#list{refNo=_Refnum,len=Len,values=List},NewState};
+% [x70-77] type value*  # fixed-length typed list
+decode(<<H:5,Len:3,Bin/binary>>, State) when H == 14 ->
+    {Rest1,_Type,_State} = decode(Bin,State),
+    {_Refnum,__State} = visit(#type_def{foreign_type = list},_State),
+    {NewRest,List,NewState} = decode(list, Rest1, Len, [], __State),
+    {NewRest,#list{refNo=_Refnum,len=Len,type=_Type,values=List},NewState};
+% [x78-7f] value*       # fixed-length untyped list
+decode(<<H:5,Len:3,Bin/binary>>, State) when H == 15 ->
+    {_Refnum,_State} = visit(#type_def{foreign_type = list},State),
+    {NewRest,List,NewState} = decode(list, Bin, Len, [], _State),
+    {NewRest,#list{refNo=_Refnum,len=Len,values=List},NewState};
+% 'U' type value* 'Z'   # variable-length list
+decode(<<$U,Bin/binary>>, State) ->
+    {Rest1,_Type,_State} = decode(Bin,State),
+    {_Refnum,__State} = visit(#type_def{foreign_type = list},_State),
+    {NewRest,List,NewState} = decode(list, Rest1, [], __State),
+    {NewRest,#list{refNo=_Refnum,type=_Type,values=List},NewState};
+% 'W' value* 'Z'        # variable-length untyped list
+decode(<<$W,Bin/binary>>, State) ->
+    {_Refnum,_State} = visit(#type_def{foreign_type = list},State),
+    {NewRest,List,NewState} = decode(list, Bin, [], _State),
+    {NewRest,#list{refNo=_Refnum,values=List},NewState};
+decode(<<$C,Bin/binary>>, State0) ->
+    {Rest1,Type,State1} = decode(Bin,State0),
+    {Rest, TypeDef, State} = decode(type_definition,Type,Rest1,State1),
+    NewState = hash_store(TypeDef,State),
+    decode(Rest,NewState);
+decode(<<$O,Bin/binary>>, State) ->
+    {Rest,Ref,_State} = decode(Bin, State),
+    case hash_lookup(Ref, _State) of
+        {not_found, Ref} ->
+            {Rest, {not_found, Ref}, _State};
+        ForeignView ->
+            #type_def{fieldnames = ForeignFieldNames} = ForeignView,
+            {_Refnum,__State} = visit(ForeignView,_State),
+            Count = count_fields(ForeignView),
+            case decode(field, Rest, Count,[], __State) of
+                {not_found,Hash} ->
+                    {not_found,Hash};
+                {_Rest,FieldValues, NewState} ->
+                    Object = project_native_view(ForeignFieldNames,FieldValues,ForeignView),
+                    {_Rest, #object{refNo=_Refnum, typeRef=Ref,values=Object}, NewState}
+            end
+    end;
+decode(<<H:4,Ref:4,Rest/binary>>, _State) when H == 6 ->
+    lager:debug("decode data find ref ~p",[Ref]),
+    case hash_lookup(Ref, _State) of
+        {not_found, Ref} ->
+            {Rest, {not_found, Ref}, _State};
+        ForeignView ->
+            #type_def{fieldnames = ForeignFieldNames} = ForeignView,
+            {_Refnum,__State} = visit(ForeignView,_State),
+            Count = count_fields(ForeignView),
+            case decode(field, Rest, Count,[], __State) of
+                {not_found,Hash} ->
+                    {not_found,Hash};
+                {_Rest,FieldValues, NewState} ->
+                    Object = project_native_view(ForeignFieldNames,FieldValues,ForeignView),
+                    {_Rest, #object{refNo=_Refnum, typeRef=Ref,values=Object}, NewState}
+            end
+    end;
+%% Anything else
+decode(<<Unexpected/binary>>, State) ->
+    {error, hessianEncode:encode(fault, <<"ProtocolException">>, unexpected_byte_sequence, Unexpected, State) }.
+decode(<<$b,Len:16/unsigned,Bin:Len/binary,$b,Rest/binary>>, Acc, State) ->
+    decode(<<$b,Rest/binary>>,Acc ++ [Bin], State);
+decode(<<$b,Len:16/unsigned,Bin:Len/binary,$B,Rest/binary>>, Acc, State) ->
+    _Acc = Acc ++ [Bin],
+    {_Rest,_Bin, State} = decode(<<$B,Rest/binary>>, State),
+    {_Rest, list_to_binary(_Acc ++ [_Bin]), State};
+decode(<<$R,Len:16/unsigned,Rest/binary>>,Acc, State) ->
+    {_String, NewRest} = decode_str(Rest, Len, []),
+    <<H:8,_/binary>> = NewRest,
+    case H of
+        $R -> decode(NewRest,list_to_binary([Acc|[_String]]), State);
+        $S -> {_Rest,_Bin, _State} = decode(NewRest, State),
+            _Acc2 =[Acc |[_String]],
+            {_Rest, list_to_binary(_Acc2 ++ [_Bin]), _State}
+    end;
+decode(<<>>, List, State) -> {<<>>, List, State};
+decode(<<$Z>>, List, State) -> {<<>>, List, State};
+decode(Args, List, State) ->
+    case decode(Args,State) of
+        {Rest,{ref, Ref}, _State} ->
+            decode(Rest, List ++ [{ref, Ref}] , _State);
+        {Rest, [H|T], _State} ->
+            decode(Rest, List ++ [H|T], _State);
+        {Rest, Result, _State} ->
+            decode(Rest, List ++ [Result], _State);
+        {error, Encoded} ->
+            {error, Encoded}
+    end.
+decode(map, <<$Z>>, Dict, State) -> {<<>>,Dict, State};
+decode(map, <<$Z,Rest/binary>>, Dict, State) -> {Rest,Dict, State};
+decode(map, Bin, Dict, State) ->
+    {_Rest, Key, _State} = decode(Bin, State),
+    case decode(_Rest, _State) of
+        {Rest, {ref, Ref}, __State} ->
+            %Value = lists:nth(Ref + 1, List),
+            Value = Ref,
+            decode(map, Rest, dict:store(Key, {ref, Value}, Dict), __State);
+        {Rest, Value, __State} ->
+            decode(map, Rest, dict:store(Key, Value, Dict), __State)
+    end;
+decode(list, <<>>, List, State) -> {<<>>,lists:reverse(List), State};
+decode(list, <<$Z>>, List, State) -> {<<>>,lists:reverse(List), State};
+decode(list, <<$Z,Rest/binary>>, List, State) -> {Rest, lists:reverse(List), State};
+decode(list, Bin, List, State) ->
+    case decode(Bin, State) of
+        {error, Encoded} ->
+            {error, Encoded};
+        {not_found,Hash} ->
+            {not_found, Hash};
+        {_Rest, {not_found, Hash}, _State} ->
+            {not_found, Hash};
+        {Rest, Value, _State} ->
+            decode(list, Rest, [Value|List], _State)
+    end;
+decode(type_definition, ForeignType, Bin, State) ->
+    {Rest,Count, _State} = decode(Bin, State),
+    {NewRest,FieldNames, NewState} = decode(field, Rest, Count, [], _State),
+    {TypeDef,NewState2} = build_foreign_view(ForeignType,FieldNames,NewState),
+    {NewRest, TypeDef, NewState2}.
+decode(list, Bin, 0, List, State) -> {Bin, lists:reverse(List), State};
+decode(list, Bin, Len, List, State) ->
+    case decode(Bin, State) of
+        {error, Encoded} ->
+            {error, Encoded};
+        {not_found,Hash} ->
+            {not_found, Hash};
+        {_Rest, {not_found, Hash}, _State} ->
+            {not_found, Hash};
+        {Rest, Value, _State} ->
+            decode(list, Rest, Len - 1, [Value|List], _State)
+    end;
+decode(field, Rest, 0, Acc, State) -> {Rest, Acc, State};
+decode(field, <<$Z,Rest/binary>>, _Count, Acc, State) -> {Rest, Acc, State};
+decode(field, Bin, Count, Acc, State) ->
+    {Rest,Field, _State} = decode(Bin, State),
+    case Field of
+        {not_found,Hash} ->
+            {not_found,Hash};
+        _ ->
+            decode(field, Rest, Count - 1, Acc ++ [Field], _State)
+    end.
+
+get_type_set(#decoding_state{type_pool = Pool}) ->
+    case dict:to_list(Pool) of
+        [] -> [];
+        Data -> [Value || {_Key,Value} <- Data]
+    end.
+
+build_foreign_view(ForeignType,FieldNames,State) ->
+    lager:debug("[DECODE] build_foreign_view ForeignType ~p FieldNames ~p",[ForeignType,FieldNames]),
+    ForeignView = FieldNames,
+    #decoding_state{type_pool = OldPool} = State,
+    Native = dict:size(OldPool),
+    NewPool = dict:store(Native,
+        #type_def{
+            defineNo = Native,
+%%            native_type = Native,
+            foreign_type = ForeignType,
+            fieldnames = ForeignView},
+        OldPool),
+    {
+        #type_def{defineNo = Native,
+%%            native_type = Native,
+            foreign_type = ForeignType,
+            fieldnames = ForeignView},
+        State#decoding_state{type_pool = NewPool}
+    }.
+
+project_native_view(ForeignView,ForeignData,
+    #type_def{native_type = _NativeType, foreign_type = _ForeignType, fieldnames = NativeView}) ->
+    AsDict = dict:from_list(lists:zip(ForeignView,ForeignData)),
+    NativeData = [dict:fetch(Key,AsDict) || Key <- NativeView],
+    NativeData.
+
+visit(TypeDef, State = #decoding_state{reference_pool = OldPool}) ->
+    lager:debug("[DECODE] visit typedef ~p",[TypeDef]),
+    Size = dict:size(OldPool),
+    NewPool = dict:store(Size, TypeDef, OldPool),
+    {Size,State#decoding_state{reference_pool = NewPool}}.
+
+hash_lookup(Hash,#decoding_state{hash_pool = HashPool} = State) ->
+    case dict:find(Hash,HashPool) of
+        error->
+            {not_found, Hash};
+        {ok,TypeDef}->
+            TypeDef
+    end.
+%%    init(false),
+%%    case ets:lookup(hashes, Hash) of
+%%        [] ->
+%%            {not_found, Hash};
+%%        [{Hash,TypeDef}] ->
+%%            TypeDef
+%%    end.
+
+hash_store(TypeDef = #type_def{defineNo = Hash}, #decoding_state{hash_pool = HashPool} = State) ->
+%%    init(false),
+%%    ets:insert(hashes,{Hash,TypeDef}),
+    lager:debug("[DECODE] hash store typedef ~p",[TypeDef]),
+    NewPool = dict:store(Hash,TypeDef,HashPool),
+    State#decoding_state{hash_pool = NewPool}.
+
+init() -> init(true).
+
+init(Delete) when is_boolean(Delete) ->
+%%    case ets:info(hashes) of
+%%        undefined ->
+%%            ets:new(hashes,[private,named_table]);
+%%        _ ->
+%%            if
+%%                Delete ->
+%%                    ets:delete(hashes),
+%%                    ets:new(hashes,[private,named_table]);
+%%                true ->
+%%                    ok
+%%            end
+%%    end,
+    #decoding_state{}.
+
+count_fields(#type_def{fieldnames = FieldNames}) -> length(FieldNames).
+
+%% extend func
+get_deftype(Ref,#decoding_state{type_pool = Pool})->
+    dict:fetch(Ref,Pool).
\ No newline at end of file
diff --git a/src/hessianEncode.erl b/src/hessianEncode.erl
new file mode 100755
index 0000000..0b29a9e
--- /dev/null
+++ b/src/hessianEncode.erl
@@ -0,0 +1,577 @@
+-module(hessianEncode).
+
+-include("hessian.hrl").
+
+-export([encode/2, encode/3, encode/4, encode/5]).
+-export([get_value/3, get_value/4]).
+-export([wrap_class/1, encode_for_decode/2,encode_object/3]).
+
+%---------------------------------------------------------------------------
+% Encoding
+%---------------------------------------------------------------------------
+encode_for_decode(Value, [{set,SetInfo},ClassList]) when is_tuple(Value) -> encode(struct, Value, [{set,SetInfo},wrap_class(ClassList)]);
+encode_for_decode(Value, State) when is_tuple(Value) -> encode(struct, Value, wrap_class(State)).
+%---------------------------------------------------------------------------
+% encode/2	<--	** Entry **
+%---------------------------------------------------------------------------
+
+encode(undefined, _State) -> <<$N>>;
+encode(null, _State) -> <<$N>>;
+encode(true, _State) -> <<$T>>;
+encode(false, _State) -> <<$F>>;
+encode(Value, State) when is_integer(Value) -> encode(int, Value, State);
+encode(Value, State) when is_atom(Value) -> encode(string, erlang:atom_to_binary(Value,utf8), State);
+encode(Value, State) when is_float(Value) -> encode(double, Value, State);
+encode(Value, State) when is_list(Value) -> encode(string, Value, State);
+encode(Value, State) when is_binary(Value) -> encode(string, Value, State);
+encode(Value, State) when is_tuple(Value) -> encode(struct, Value, State).
+%---------------------------------------------------------------------------
+% encode/3
+%---------------------------------------------------------------------------
+encode(struct, Input, State) ->
+	case Input of
+		#list{} -> encode(list, Input, State);
+		#map{} -> encode(map, Input, State);
+		#object{} -> encode(object, Input, State);
+		#class{} -> encode(class_store, Input, State);
+		{binary, Bin} -> encode(binary, Bin, State);
+		{date, Timestamp} -> encode(date, Timestamp, State);
+		{ref, Index} ->
+			IndexBin = encode(int, Index, State),
+			<<$Q, IndexBin/binary>>;
+		_Object ->
+            lager:debug("[encode] object ~p",[Input]),
+			encode(class_object, Input, State);
+%%			{<<>>,State};
+		{K, V} ->
+			{BK,SK} = encode(K, State),
+			{BV,SV} = encode(V, SK),
+			{<<BK/binary, BV/binary>>, SV}
+	end;
+encode(int, Int, _State) when Int >= -16, Int =< 47 ->
+	_Int = Int + 16#90,
+	<<_Int:8>>;
+encode(int, Int, _State) when Int >= -2048, Int =< 2047 ->
+	<<B1:8,B0:8>> = <<Int:16>>,
+	_B1 = B1 + 16#c8,
+	<<_B1,B0>>;
+encode(int, Int, _State) when Int >= -262144, Int =< 262143 ->
+	<<B2:8,B1:8,B0:8>> = <<Int:24>>,
+	_B2 = B2 + 16#d4,
+	<<_B2,B1,B0>>;
+encode(int, Int, _State) when Int > -16#80000001, Int < 16#80000000 ->
+	<<$I,Int:32/signed>>;
+encode(int, Int, State) ->
+	encode(long, Int, State);
+encode(long, Long, _State) when Long >= -8, Long =< 15 ->
+	_Long = Long + 16#e0,
+	<<_Long:8>>;
+encode(long, Long, _State) when Long >= -2048, Long =< 2047 ->
+	<<B1:8,B0:8>> = <<Long:16>>,
+	_B1 = B1 + 16#f8,
+	<<_B1,B0>>;
+encode(long, Long, _State) when Long >= -262144, Long =< 262143 ->
+	<<B2:8,B1:8,B0:8>> = <<Long:24>>,
+	_B2 = B2 + 16#3c,
+	<<_B2,B1,B0>>;
+encode(long, Long, _State) when Long > -16#80000001, Long < 16#80000000 ->
+	<<16#59,Long:32/signed>>;
+encode(long, Long, _State) ->
+	<<$L,Long:64/signed>>;
+encode(double, 0.0, _State) ->
+	<<16#5b>>;
+encode(double, 1.0, _State) ->
+	<<16#5c>>;
+encode(double, Double, _State) when Double >= -128.0, Double =< 127.0, Double == round(Double) ->
+	Byte = round(Double),
+	<<16#5d, Byte/signed>>;
+encode(double, Double, _State) when Double >= -32768.0, Double =< 32767.0, Double == round(Double) ->
+	Byte = round(Double),
+	<<16#5e, Byte:16/signed>>;
+encode(double, Double, _State) ->
+	case <<Double/float>> of
+		<<B24,B16,B8,B0,0,0,0,0>> -> <<16#5f,B24,B16,B8,B0>>;
+		Other -> <<$D,Other/binary>>
+	end;
+encode(string, <<>>, _State) ->
+	<<0>>;
+encode(string, [], _State) ->
+	<<0>>;
+encode(string, String, State) when is_list(String)->
+	UTF8 = xmerl_ucs:from_utf8(String),
+	Length = length(UTF8),
+	encode(sub, Length, String, [UTF8|State]);
+encode(string, String, State) when is_binary(String)->
+	encode(string, binary_to_list(String), State);
+encode(binary, <<>>, _State) ->
+	<<16#20>>;
+encode(binary, Value, _State) when size(Value) < 15 ->
+	Size = 16#20 + size(Value),
+	<<Size:8/unsigned,Value/binary>>;
+encode(binary, Value, State) ->
+	encode(binary, Value, <<>>, State);
+encode(date, {MegaSeconds,Seconds,MicroSeconds}, State) ->
+	MilliSeconds = MegaSeconds * ?MegaSeconds + Seconds * ?Seconds + MicroSeconds div ?MicroSeconds,
+	encode(date, MilliSeconds, State);
+encode(date, MilliSeconds, _State) ->
+	MinuteRemain = MilliSeconds rem (?Seconds * 60),
+	case MinuteRemain of
+		0 ->
+			Minutes = MilliSeconds div (?Seconds * 60),
+			<<16#4b,Minutes:32/unsigned>>;
+		_ -> <<16#4a,MilliSeconds:64/unsigned>>
+	end;
+encode(list, Input, [{set,SetInfo},_T]=State) when is_record(Input, list) ->
+	case find_set_info(Input#list.refNo, SetInfo) of
+		not_found -> encode(list, Input#list.len, Input#list.type, Input#list.values, State);
+		List -> encode(list, List#list.len, List#list.type, List#list.values, State)
+	end;
+encode(list, Input, State) when is_record(Input, list) ->
+	encode(list, Input#list.len, Input#list.type, Input#list.values, State);
+encode(list, List, State) ->
+	ListLength = length(List),
+	encode(fixedlist, ListLength, List, State);
+encode(vlist, List, State) ->
+	case List of
+		[] -> <<$W,$Z>>;
+		_ -> encode(vlist, List, <<$W>>, State)
+	end;
+encode(map, Input, [{set,SetInfo},_T]=State) when is_record(Input, map) ->
+	case find_set_info(Input#map.refNo, Input#map.type, SetInfo) of
+		not_found -> encode(map, Input#map.dict, State);
+		Map -> encode(map, Map#map.dict, State)
+	end;
+encode(map, Input, State) when is_record(Input, map) ->
+	encode(map, Input#map.dict, State);
+encode(map, Dict, State) ->
+	List = dict:to_list(Dict),
+	Encoder = fun({Key, Value}, {AccIn, StateIn}) ->
+		% Key
+		RK = encode(Key, StateIn),
+		{KeyBin, NewStateKey} = case RK of
+			{_, _} -> RK;
+			KeyB -> {KeyB, StateIn}
+		end,
+		% Value
+		RV = encode(Value, NewStateKey),
+		{ValueBin, NewStateValue} = case RV of
+			{_, _} -> RV;
+			ValueB -> {ValueB, NewStateKey}
+		end,
+		% Acc Out
+		{<<AccIn/binary,KeyBin/binary,ValueBin/binary>>, NewStateValue}
+	end,
+	{AccOut, NewState} = lists:foldl(Encoder, {<<$H>>, State}, List),
+	{<<AccOut/binary,$Z>>, NewState};
+encode(class, #class{name=Name, fields=Fields}, State) ->
+	% type
+	NameBin = encode(Name, State),
+	% fields length
+	FieldsLen = length(Fields),
+	FieldsLenBin = encode(int, FieldsLen, State),
+	% fields
+	encode(list, Fields, <<$C,NameBin/binary,FieldsLenBin/binary>>, State);
+encode(class_store, Input, [{set,SetInfo},ClassList]=State) ->
+	{Bin, _} = encode(class, Input, State),
+	{Bin, [{set,SetInfo},[Input#class{encoded=true}|ClassList]]};
+encode(class_store, Input, State) ->
+	{Bin, _} = encode(class, Input, State),
+%%	{Bin, [Input#class{encoded=true}|State]};
+	{Bin, State};
+encode(object, Input, [{set,SetInfo},T]=State) when is_record(Input, object) ->
+	ClassRes = class(Input#object.typeRef, Input#object.class, [], T),
+	{BaseBin, TypeNum, C, NewState} = case ClassRes of
+		{encoded, Class, TypeNo} -> {<<>>, TypeNo, Class, State};
+		{Class, TypeNo, NewST} ->
+			{Bin, NewClassST} = encode(class, Class, NewST),
+			{Bin, TypeNo, Class, [{set,SetInfo},NewClassST]}
+	end,
+	case find_set_info(Input#object.refNo, C#class.name, SetInfo) of
+		not_found -> encode(object, BaseBin, TypeNum, Input#object.values, NewState);
+		Obj -> encode(object, BaseBin, TypeNum, Obj#object.values, NewState)
+	end;
+encode(object, Input, State) when is_record(Input, object) ->
+	ClassRes = class(Input#object.typeRef, Input#object.class, [], State),
+
+	{BaseBin, TypeNum, NewState} = case ClassRes of
+		{encoded, _Class, TypeNo} -> {<<>>, TypeNo, State};
+		{Class, TypeNo, NewST} ->
+			{Bin, NewClassST} = encode(class, Class, NewST),
+			{Bin, TypeNo, NewClassST}
+	end,
+	encode(object, BaseBin, TypeNum, Input#object.values, NewState);
+encode(class_object,Input,State)->
+	[NativeType|Values] = tuple_to_list(Input),
+	{ClassEncodingBin, EncodedRef, NewState} =
+		case type_encoding:visit(NativeType,State) of
+			{ref, Ref} ->
+%%				encode_object(type_information, {ref, Ref}, State);
+				%% todo 还未验证
+				{<<>>,Ref,State};
+			{hash, Ref, Typedef , State0} ->
+				Class = typedef_to_class(Typedef,Ref),
+				{Bin,NewStateClass} = encode(class_store,Class,State0),
+				{Bin,Ref,NewStateClass}
+%%				encode(type_information, {hash, Ref,Typedef }, State0)
+		end,
+	encode(object, ClassEncodingBin, EncodedRef, Values, NewState);
+%%	{AccOut, _NewState} = lists:foldl(fun encode/2,{<<>>, NewState},Values),
+%%	{<<ClassEncodingBin/binary,$o,EncodedRef/binary,AccOut/binary>>, _NewState};
+
+encode(method, Method, State) when is_atom(Method) ->
+	String = atom_to_list(Method),
+	encode(method, String, State);
+encode(method, Method, _State) when is_binary(Method) ->
+	CamMethod = erlang_to_camel_case(Method),
+	Size = size(CamMethod),
+	<<$m,Size:16/unsigned,CamMethod/binary>>;
+encode(method, String, _State) when is_list(String) ->
+	CamString = erlang_to_camel_case(String),
+	Length = string:len(CamString),
+	Bin = list_to_binary(CamString),
+	<<$m,Length:16/unsigned,Bin/binary>>;
+encode(reply, ok, _State) -> 
+	<<$H,16#02,16#00,$R,16#01,$N>>;
+encode(reply, {ok, Object}, State) ->
+	encode(reply, Object, State);
+encode(reply, {error, {Error, Reason} }, State) ->
+	encode(fault, Error, Reason, State);
+encode(reply, Object, State) ->
+	case encode(Object, State) of
+		{Bin, _NewState} -> Bin;
+		Bin -> Bin
+	end,
+	<<$H,16#02,16#00,$R,Bin/binary>>.
+%---------------------------------------------------------------------------
+% encode/4
+%---------------------------------------------------------------------------
+encode(sub, Length, String, _State) when Length < 32 ->
+	Bin = list_to_binary(String),
+	<<Length:8,Bin/binary>>;
+encode(sub, Length, String, _State) when Length < 256 ->
+	Bin = list_to_binary(String),
+	<<16#30,Length:8,Bin/binary>>;
+encode(sub, Length, String, _State) when Length < 512 ->
+	Bin = list_to_binary(String),
+	<<16#31,(Length-256):8,Bin/binary>>;
+encode(sub, Length, String, _State) when Length < 768 ->
+	Bin = list_to_binary(String),
+	<<16#32,(Length-512):8,Bin/binary>>;
+encode(sub, Length, String, _State) when Length < ?CHUNK_SIZE ->
+	Bin = list_to_binary(String),
+	<<16#33,(Length-768):8,Bin/binary>>;
+encode(sub, Length, String, _State) when Length =:= ?CHUNK_SIZE ->
+	Bin = list_to_binary(String),
+	<<$S,Length:16,Bin/binary>>;
+encode(sub, Length, _String, [UTF8|State]) ->
+	encode(string, Length, UTF8, <<>>, State);
+encode(binary, Value, <<>>, _State) when size(Value) =< ?CHUNK_SIZE ->
+	Size = size(Value),
+	<<$B,Size:16,Value/binary>>;
+encode(binary, Value, Acc, _State) when size(Value) =< ?CHUNK_SIZE ->
+	Size = size(Value),
+	<<Acc/binary,$B,Size:16,Value/binary>>;
+encode(binary, Value, <<>>, State) ->
+	<<Chunk:?CHUNK_SIZE/binary,Rest/binary>> = Value,
+encode(binary, Rest, <<$b,?CHUNK_SIZE:16,Chunk/binary>>, State);
+encode(binary, Value, Acc, State) ->
+	<<Chunk:?CHUNK_SIZE/binary,Rest/binary>> = Value,
+	encode(binary, Rest, <<Acc/binary,$b,?CHUNK_SIZE:16,Chunk/binary>>, State);
+encode(list, List, Acc0, State) when is_binary(Acc0) ->
+	lists:foldl(fun encode_accumulate/2, {Acc0,State}, List);
+encode(list, Type, List, State) ->
+	ListLength = length(List),
+	encode(list, ListLength, Type, List, State);
+encode(vlist, List, Acc0, State) when is_binary(Acc0) ->
+	{AccOut, NewState} = lists:foldl(fun encode_accumulate/2, {Acc0,State}, List),
+	{<<AccOut/binary,$Z>>, NewState};
+encode(vlist, Type, List, State) ->
+	TypeBin = encode(Type, State),
+	case List of
+		[] -> <<$U,TypeBin/binary,$Z>>;
+		_ -> encode(vlist, List, <<$U,TypeBin/binary>>, State)
+	end;
+encode(fixedlist, ListLength, List, State) ->
+	case ListLength < 8 of
+		true ->
+			ListLengthFlag = 16#78 + ListLength,
+			case List of
+				[] -> <<ListLengthFlag:8>>;
+				_ -> encode(list, List, <<ListLengthFlag:8>>, State)
+			end;
+		false ->
+			ListLengthBin = encode(int, ListLength, State),
+			encode(list, List, <<$X,ListLengthBin/binary>>, State)
+	end;
+encode(fault, _Error, _Reason, State) ->
+	encode(fault, <<"ServiceException">>, _Error, _Reason, State);
+encode(call, Method, Args, State) ->
+	encode(call, Method, Args, fun encode_accumulate/2, State).
+%---------------------------------------------------------------------------
+% encode/5
+%---------------------------------------------------------------------------
+encode(string, Length, UTF8, Acc, _State) when Length =< ?CHUNK_SIZE ->
+	Bin = list_to_binary(xmerl_ucs:to_utf8(UTF8)),
+	<<Acc/binary,$S,Length:16,Bin/binary>>;
+encode(string, Length, UTF8, Acc, State) ->
+	{Chunk, Rest} = lists:split(?CHUNK_SIZE, UTF8),
+	ChunkBin = list_to_binary(xmerl_ucs:to_utf8(Chunk)),
+	encode(string, (Length-?CHUNK_SIZE), Rest, <<Acc/binary,$R,?CHUNK_SIZE:16,ChunkBin/binary>>, State);
+encode(list, -1, untyped, List, State) ->
+	encode(vlist, List, State);
+encode(list, -1, Type, List, State) ->
+	encode(vlist, Type, List, State);
+encode(list, Len, untyped, List, State) ->
+	encode(fixedlist, Len, List, State);
+encode(list, Len, Type, List, State) ->
+	TypeBin = encode(Type, State),
+	if
+		Len < 8 ->
+			ListLengthFlag = 16#70 + Len,
+			case List of
+				[] -> <<ListLengthFlag:8,TypeBin/binary>>;
+				_ -> encode(list, List, <<ListLengthFlag:8,TypeBin/binary>>, State)
+			end;
+		true ->
+			ListLengthBin = encode(int, Len, State),
+			encode(list, List, <<$V,TypeBin/binary,ListLengthBin/binary>>, State)
+	end;
+encode(object, BaseBin, TypeNo, Values, State) ->
+	IndexBin = if
+		TypeNo < 16 ->
+			lager:debug("[encode] encode object TypeNo ~p",[TypeNo]),
+			IndexWrap = TypeNo + 16#60,
+			<<IndexWrap:8>>;
+		true ->
+			IndexWrap = encode(int, TypeNo, State),
+			<<$O, IndexWrap/binary>>
+	end,
+	{Bin, NewState} = encode(list, Values, IndexBin, State),
+	{<<BaseBin/binary,Bin/binary>>, NewState};
+encode(call, Method, Args, Fun, State) when is_function(Fun) ->
+	MethodBin = encode(string, Method, State),
+	ArgsCount = encode(int, erlang:length(Args), State),
+	{Bin, _NewState} = lists:foldl(Fun, {<<>>, State}, Args),
+	<<$H,2,0,$C,MethodBin/binary,ArgsCount/binary,Bin/binary>>;
+encode(fault, Code, _Error, _Reason, State) ->
+	EncodedCode = encode(string,Code, State),
+	<<131,100,_L2:16/unsigned,Error/binary>> = term_to_binary(_Error),
+	EncodedError = encode(string,Error, State),
+	<<$H,16#02,16#00,$F,$H,4,"code",EncodedCode/binary,7,"message",EncodedError/binary,6,"detail",31,"Stack trace not yet implemented",$Z>>.
+
+%---------------------------------------------------------------------------
+% Utility methods
+%---------------------------------------------------------------------------
+erlang_to_camel_case(String) when is_binary(String) ->
+	AsList = binary_to_list(String),
+	AsCamel = lists:foldl(fun camelize/2,[],AsList),
+	list_to_binary(AsCamel);
+erlang_to_camel_case(String) when is_atom(String) ->
+	AsList = atom_to_list(String),
+	AsCamel = lists:foldl(fun camelize/2,[],AsList),
+	list_to_binary(AsCamel).    
+
+camelize(Element,Acc) when Element == $_ -> [$_|Acc];
+camelize(Element,[$_|Acc]) -> lists:append(Acc,[Element - 16#20]);
+camelize(Element,Acc) -> lists:append(Acc,[Element]).
+
+encode_accumulate(Value, {Acc, State}) ->
+    lager:debug("[encode] encode_accumulate value ~p",[Value]),
+	case encode(Value, State) of 
+		{Encoded,NewState} -> {<<Acc/binary,Encoded/binary>>,NewState};
+		Encoded -> {<<Acc/binary,Encoded/binary>>,State}
+	end.
+
+find_set_info(RefNo, SetInfo) ->
+	find_set_info(RefNo, untyped, SetInfo).
+find_set_info(_RefNo, _Type, []) ->
+	not_found;
+find_set_info(RefNo, Type, [Set|SetInfo]) ->
+	if
+		RefNo =:= Set#set.ref -> Set#set.value;
+		true ->
+			case equal(Type, Set#set.ref) of
+				true -> Set#set.value;
+				false -> find_set_info(RefNo, Type, SetInfo)
+			end
+	end.
+
+type_index(Type, [CurrentType|RestTypes]) when is_record(Type, class) ->
+	case equal(Type#class.name, CurrentType#class.name) of
+		true -> length(RestTypes);
+		false -> type_index(Type, RestTypes)
+	end;
+type_index(Type, [CurrentType|RestTypes]) ->
+	case equal(Type, CurrentType#class.name) of
+		true -> length(RestTypes);
+		false -> type_index(Type, RestTypes)
+	end.
+
+get_class(Where, ClassList) ->
+	SortClassList = lists:reverse(ClassList),
+	case Where#object.typeRef of
+		-1 ->
+			if
+			Where#object.class =:= auto -> hd(ClassList);
+			true ->
+				Index = type_index(Where#object.class, ClassList),
+				lists:nth(Index+1, SortClassList)
+			end;
+		TypeRef ->
+			lists:nth(TypeRef+1, SortClassList)
+	end.
+
+get_type_no(C, RestClasses) when is_record(C, class) ->
+	case C#class.typeNo of
+		-1 -> length(RestClasses);
+		_ -> C#class.typeNo
+	end.
+
+get_type(CListH, C, CListE) when is_record(C, class) ->
+	TypeNo = get_type_no(C, CListE),
+	case C#class.encoded of
+		true -> {encoded, C, TypeNo};
+		false -> {C, TypeNo, CListH++[C#class{encoded=true}|CListE]}
+	end.
+
+class(-1, auto, [], [C|CListE]) ->
+	get_type([], C, CListE);
+class(-1, Class, CListH, [C|CListE]) when is_record(Class, class) ->
+	case Class#class.name of
+		auto ->
+			case CListH of
+				[] -> get_type([], C, CListE);
+				[H|T] ->get_type([], H, T++[C|CListE])
+			end;
+		_ ->
+			case equal(Class#class.name, C#class.name) of
+				true -> get_type(CListH, C, CListE);
+				false -> class(-1, Class, CListH++[C], CListE)
+			end
+	end;
+class(-1, Class, CListH, [C|CListE]) ->
+	case equal(Class, C#class.name) of
+		true -> get_type(CListH, C, CListE);
+		false -> class(-1, Class, CListH++[C], CListE)
+	end;
+class(RefNo, _Class, CListH, [C|CListE]) ->
+	if
+		RefNo =:= length(CListE) -> get_type(CListH, C, CListE);
+		true -> class(RefNo, _Class, CListH++[C], CListE)
+	end.
+
+equal(S1, S2) when is_binary(S1) ->
+	if
+		S1 =:= S2 -> true;
+		true ->
+			S1List = binary_to_list(S1),
+			if
+				S1List =:= S2 -> true;
+				true -> false
+			end
+	end;
+equal(S1, S2) when is_list(S1) ->
+	if
+		S1 =:= S2 -> true;
+		true ->
+			S1Binary = list_to_binary(S1),
+			if
+				S1Binary =:= S2 -> true;
+				true -> false
+			end
+	end;
+equal(_S1, _S2) ->
+	false.
+
+wrap_class(ClassList) ->
+	Fun = fun(OldClass, AccIn) -> 
+		[#class{typeNo=OldClass#type_def.native_type, name=OldClass#type_def.foreign_type, fields=OldClass#type_def.fieldnames}|AccIn]
+	end,
+	lists:foldl(Fun, [], ClassList).
+
+get_value(Where, Ref, Field) ->
+	get_value(Where, Ref, Field, [], []).
+get_value(Where, Ref, Field, ClassList) ->
+	get_value(Where, Ref, Field, wrap_class(ClassList), []).
+get_value(Where, Ref, Field, ClassList, ObjVlues) when is_record(Where, list) ->
+	get_value(Where#list.values, Ref, Field, ClassList, ObjVlues);
+get_value(Where, Ref, Field, ClassList, _ObjVlues) when is_record(Where, map) ->
+	List = dict:to_list(Where#map.dict),
+	get_value(List, Ref, Field, ClassList, Where#map.refNo);
+get_value(Where, _Ref, _Field, ClassList, _ObjVlues) when is_record(Where, type_def) ->
+	{class, [#class{typeNo=Where#type_def.native_type, name=Where#type_def.foreign_type, fields=Where#type_def.fieldnames}|ClassList]};
+get_value(Where, _Ref, _Field, ClassList, _ObjVlues) when is_record(Where, class) ->
+	{class, [Where|ClassList]};
+get_value(Where, Ref, Field, ClassList, _ObjVlues) when is_record(Where, object) ->
+	Class = get_class(Where, ClassList),
+	if
+		Where#object.refNo =:= Ref -> get_value(Class#class.fields, Ref, Field, ClassList, Where#object.values);
+		Class =:= Ref -> get_value(Class#class.fields, Ref, Field, ClassList, Where#object.values);
+		true ->
+			case equal(Class#class.name, Ref) of
+				true -> get_value(Class#class.fields, Ref, Field, ClassList, Where#object.values);
+				false -> get_value(Where#object.values, Ref, Field, ClassList, skip)
+			end
+	end;
+get_value(Where, _RefNo, _Field, _ClassList, skip) when is_binary(Where) ->
+	next;
+get_value(Where, _RefNo, Field, _ClassList, Value) when is_binary(Where) ->
+	case equal(Where, Field) of
+		true -> {return, Value};
+		false -> next
+	end;
+get_value(Where, _RefNo, _Field, _ClassList, _Value) when is_atom(Where) ->
+	next;
+get_value(Where, _RefNo, _Field, _ClassList, _Value) when is_integer(Where) ->
+	next;
+get_value({ref, _No}, _RefNo, _Field, _ClassList, _ObjVlues) ->
+	next;
+get_value({K, V}, RefNo, Field, ClassList, MapRefNo) ->
+	case is_binary(K) of
+		true ->
+			if
+				RefNo =/= MapRefNo -> R = next;
+				true -> R = get_value(K, RefNo, Field, ClassList, V)
+			end;
+		false -> R = get_value(K, RefNo, Field, ClassList, [])
+	end,
+	case R of
+		next -> get_value(V, RefNo, Field, ClassList, []);
+		_ -> R
+	end;
+get_value([], _RefNo, _Field, _ClassList, _ObjVlues) ->
+	not_found;
+get_value([CurrentField|Fields], RefNo, Field, ClassList, [Value|Values]) ->
+	R = get_value(CurrentField, RefNo, Field, ClassList, Value),
+	case R of
+		{return, _} -> R;
+		{class, NewClassList} -> get_value(Fields, RefNo, Field, NewClassList, Values);
+		_ -> get_value(Fields, RefNo, Field, ClassList, Values)
+	end;
+get_value([Item|T], RefNo, Field, ClassList, Option)->
+	R = get_value(Item, RefNo, Field, ClassList, Option),
+	case R of
+		{return, _} -> R;
+		{class, NewClassList} -> get_value(T, RefNo, Field, NewClassList, Option);
+		_ -> get_value(T, RefNo, Field, ClassList, Option)
+	end.
+
+encode_object(object, Object, State) when is_tuple(Object) ->
+	[NativeType|Values] = tuple_to_list(Object),
+	{TypeEncoding, EncodedRef, NewState} =
+		case type_encoding:visit(NativeType,State) of
+			{ref, Ref} ->
+				encode_object(type_information, {ref, Ref}, State);
+			{hash, Hash, Ref, State0} ->
+				encode(type_information, {hash, Hash, Ref}, State0)
+		end,
+	{AccOut, _NewState} = lists:foldl(fun encode/2,{<<>>, NewState},Values),
+	{<<TypeEncoding/binary,$o,EncodedRef/binary,AccOut/binary>>, _NewState};
+encode_object(type_information, {ref, Ref}, State) ->
+	{<<>>, encode(int, Ref, State), State};
+encode_object(type_information, {hash, Hash, Ref}, State) ->
+	EncodedRef = encode(int, Ref, State),
+	{<<$O,Hash:32/unsigned>>, EncodedRef, State}.
+
+typedef_to_class(Typedef,DefineNo)->
+	#class{typeNo=DefineNo, name=Typedef#type_def.foreign_type, fields=Typedef#type_def.fieldnames}.
\ No newline at end of file
diff --git a/src/java_type_defined.erl b/src/java_type_defined.erl
new file mode 100644
index 0000000..b4eda9e
--- /dev/null
+++ b/src/java_type_defined.erl
@@ -0,0 +1,21 @@
+%%%-------------------------------------------------------------------
+%%% @author dlive
+%%% @copyright (C) 2018, <COMPANY>
+%%% @doc
+%%%
+%%% @end
+%%% Created : 09. Mar 2018 11:06 PM
+%%%-------------------------------------------------------------------
+-module(java_type_defined).
+-author("dlive").
+
+-include("java_type.hrl").
+%% API
+-export([get_list/0]).
+
+
+get_list()->
+    [
+        {null_pointer_exception,<<"java.lang.NullPointerException">>,record_info(fields,null_pointer_exception)},
+        {stack_stack_trace_element,<<"java.lang.StackTraceElement">>,record_info(fields,stack_stack_trace_element)}
+    ].
\ No newline at end of file
diff --git a/src/lists_util.erl b/src/lists_util.erl
new file mode 100644
index 0000000..fec6cf0
--- /dev/null
+++ b/src/lists_util.erl
@@ -0,0 +1,43 @@
+%%%-------------------------------------------------------------------
+%%% @author dlive
+%%% @copyright (C) 2017, <COMPANY>
+%%% @doc
+%%%
+%%% @end
+%%% Created : 27. Dec 2017 6:09 PM
+%%%-------------------------------------------------------------------
+-module(lists_util).
+-author("dlive").
+
+%% API
+-export([join/2,del_duplicate/1]).
+
+-spec(join(List :: list(), Separator :: binary()) -> binary()).
+join(List, _Separator) when length(List) == 0 ->
+    <<"">>;
+join(List, Separator) ->
+    [First | Rst] = List,
+    Acc2 = lists:foldl(fun(Item, Acc) ->
+        if
+            is_binary(Item) ->
+                <<Acc/binary, Separator/binary, Item/binary>>;
+            is_list(Item) ->
+                Item2 = list_to_binary(Item),
+                <<Acc/binary, Separator/binary, Item2/binary>>;
+            true ->
+                Acc
+        end
+                       end, First, Rst),
+    Acc2.
+
+
+del_duplicate(List) ->
+    lists:foldl(
+        fun(X, List2) ->
+            case lists:member(X, List2) of
+                true ->
+                    List2;
+                _ ->
+                    [X]++ List2
+            end
+        end, [], List).
diff --git a/src/request_context.erl b/src/request_context.erl
new file mode 100644
index 0000000..ea9da32
--- /dev/null
+++ b/src/request_context.erl
@@ -0,0 +1,117 @@
+%%%-------------------------------------------------------------------
+%%% @author dlive
+%%% @copyright (C) 2018, <COMPANY>
+%%% @doc
+%%%
+%%% @end
+%%% Created : 23. May 2018 4:28 PM
+%%%-------------------------------------------------------------------
+-module(request_context).
+-author("dlive").
+
+%%-define(PER_LOG,true).
+-define(PER_LOG,false).
+
+%% API
+-export([init/0,init/1,update/2,update/3,to_log/1,test/0,trace/1,trace_end/1]).
+
+init()->
+    case ?PER_LOG of
+        true->
+            #{<<"t_b">> => time_util:timestamp_ms()};
+        _->
+            #{}
+    end.
+init(ID)->
+    case ?PER_LOG of
+        true->
+            #{<<"id">> =>ID,<<"t_b">> => time_util:timestamp_ms()};
+        _->
+            #{<<"id">> =>ID}
+    end.
+
+update(Key,Map)->
+    case ?PER_LOG of
+        true->
+            Map#{Key=>time_util:timestamp_ms()};
+        _->
+            Map
+    end.
+
+update(Key,Value,Map)->
+    Map#{Key=>Value}.
+
+to_log(Map)->
+    case ?PER_LOG of
+        true->
+            to_log2(Map);
+        _->
+            ok
+    end.
+
+to_log2(Map)->
+
+    #{
+        <<"t_b">> := Begin,
+        <<"t_lb">> := LoadBalance,
+        <<"t_send_agent">> := SendAgent,
+        <<"t_agent_b">> := AgentBegin,
+        <<"t_agent_e">> := AgentEnd,
+        <<"t_net_b">> := NetBegin,
+%%        <<"t_net_bd">> := NetBeginDecode,
+        <<"t_net_e">> := NetEnd,
+        <<"t_backer_b">> := BackerBegin,
+        <<"t_backer_e1">> := BackerGet,
+        <<"t_backer_e">> := BackerEnd,
+        <<"t_gate_back">> := GateWayBack,
+%%      <<"t_e">> := End,
+        <<"t_nd">> :=Node
+    } = Map,
+    Total=GateWayBack-Begin,
+    if
+        Total > 90 ->
+            performance:warning("total ~-5.10B lb ~-5.10B to_send ~-5.10B agent_b ~-5.10B agent_e ~-5.10B net_b ~-5.10B net_e ~-5.10B backer_b ~-5.10B backer_e1 ~-5.10B backer_e ~-5.10B gw_b ~-5.10B ~p",
+                [
+                    Total,
+                    LoadBalance - Begin,
+                    SendAgent-Begin,
+                    AgentBegin-SendAgent,
+                    AgentEnd-AgentBegin,
+                    NetBegin-AgentEnd,
+                    NetEnd-NetBegin,
+                    BackerBegin-NetEnd,
+                    BackerGet-BackerBegin,
+                    BackerEnd-BackerBegin,
+                    GateWayBack-BackerEnd,
+%%                    End-GateWayBack,
+                    Node
+                ]);
+        true->
+            performance:info("total ~-5.10B lb ~-5.10B to_send ~-5.10B agent_b ~-5.10B agent_e ~-5.10B net_b ~-5.10B net_e ~-5.10B backer_b ~-5.10B backer_e1 ~-5.10B backer_e ~-5.10B gw_b ~-5.10B ~p",
+                [
+                    Total,
+                    LoadBalance - Begin,
+                    SendAgent-Begin,
+                    AgentBegin-SendAgent,
+                    AgentEnd-AgentBegin,
+                    NetBegin-AgentEnd,
+                    NetEnd-NetBegin,
+                    BackerBegin-NetEnd,
+                    BackerGet-BackerBegin,
+                    BackerEnd-BackerBegin,
+                    GateWayBack-BackerEnd,
+%%                    End-GateWayBack,
+                    Node
+                ])
+    end.
+
+trace(Info)->
+%%    gen_server:cast({monitor_trace,'monitor@agent_monitor.me'},{trace,Info}).
+    ok.
+
+trace_end(Info)->
+%%    gen_server:cast({monitor_trace,'monitor@agent_monitor.me'},{trace_end,Info}).
+    ok.
+
+test()->
+    lager:error("a~-10.5sb",[123]).
\ No newline at end of file
diff --git a/src/time_util.erl b/src/time_util.erl
new file mode 100644
index 0000000..b6bda7a
--- /dev/null
+++ b/src/time_util.erl
@@ -0,0 +1,154 @@
+
+
+
+-module(time_util).
+
+-include_lib("kernel/include/file.hrl").
+
+
+-export([
+	get_cur_time/0,get_cur_time/1,
+	format_time_to_str/1,
+	timestamp/0,timestamp_ms/0,
+	timestamp_to_datetime/1,
+	timestamp_to_local_datetime/1,
+	get_cur_date/0,
+	datetime_to_timestamp/1,
+	datetime_string_to_timestamp/1,get_curdate_timestamp/0]).
+
+
+get_cur_time()->
+	{{Year,Month,Day},{Hour,Min,Second}}=calendar:now_to_local_time(os:timestamp()),
+	io_lib:format("~4..0w-~2..0w-~2..0w ~2..0w:~2..0w:~2..0w",[Year, Month, Day, Hour,Min,Second]).
+
+get_cur_date()->
+	{{Year,Month,Day},{Hour,Min,Second}}=calendar:now_to_local_time(os:timestamp()),
+	io_lib:format("~4..0w-~2..0w-~2..0w",[Year, Month, Day]).
+
+get_cur_time({{Year,Month,Day},{Hour,Min,Second}})->
+	io_lib:format("~4..0w-~2..0w-~2..0w ~2..0w:~2..0w:~2..0w",[Year, Month, Day, Hour,Min,Second]).
+
+format_time_to_str({{Year,Month,Day},{Hour,Min,Second}})->
+	io_lib:format("~4..0w-~2..0w-~2..0w ~2..0w:~2..0w:~2..0w",[Year, Month, Day, Hour,Min,Second]).
+
+timestamp() ->  
+    {M, S, _} = os:timestamp(),  
+    M * 1000000 + S.
+timestamp_ms()->
+    {M,S,W} = os:timestamp(),
+    M*1000000000+S*1000+(W div 1000).
+
+timestamp_to_datetime(Timestamp) ->
+    calendar:gregorian_seconds_to_datetime(Timestamp +  
+      calendar:datetime_to_gregorian_seconds({{1970,1,1}, {0,0,0}})).
+timestamp_to_local_datetime(Timestamp) ->
+    Date=calendar:gregorian_seconds_to_datetime(Timestamp +  
+      calendar:datetime_to_gregorian_seconds({{1970,1,1}, {0,0,0}})),
+    calendar:universal_time_to_local_time(Date).
+
+%% @doc 时间转时间戳
+datetime_to_timestamp(Date)->
+	[{D,T}]=calendar:local_time_to_universal_time_dst(Date),
+	S = calendar:datetime_to_gregorian_seconds({D, T}),
+    S1 = calendar:datetime_to_gregorian_seconds({{1970, 1, 1}, {0, 0, 0}}),
+    Seconds = (S - S1).
+    % {Seconds div 1000000, Seconds rem 1000000, MS}.
+
+%% @doc 时间字符串转 时间戳
+datetime_string_to_timestamp(TimeStr) ->
+    case catch parse_datetime(TimeStr) of
+    {'EXIT', _Err} ->
+        undefined;
+    TimeStamp ->
+        TimeStamp
+    end.
+
+parse_datetime(TimeStr) ->
+    [Date, Time] = string:tokens(TimeStr, "T"),
+    D = parse_date(Date),
+    {T, MS, TZH, TZM} = parse_time(Time),
+    S = calendar:datetime_to_gregorian_seconds({D, T}),
+    S1 = calendar:datetime_to_gregorian_seconds({{1970, 1, 1}, {0, 0, 0}}),
+    Seconds = (S - S1) - TZH * 60 * 60 - TZM * 60,
+    {Seconds div 1000000, Seconds rem 1000000, MS}.
+
+% yyyy-mm-dd
+parse_date(Date) ->
+    [Y, M, D] = string:tokens(Date, "-"),
+    Date1 = {list_to_integer(Y), list_to_integer(M), list_to_integer(D)},
+    case calendar:valid_date(Date1) of
+    true ->
+        Date1;
+    _ ->
+        false
+    end.
+
+% hh:mm:ss[.sss]TZD
+parse_time(Time) ->
+    case string:str(Time, "Z") of
+    0 ->
+        parse_time_with_timezone(Time);
+    _ ->
+        [T | _] = string:tokens(Time, "Z"),
+        {TT, MS} = parse_time1(T),
+        {TT, MS, 0, 0}
+    end.
+
+parse_time_with_timezone(Time) ->
+    case string:str(Time, "+") of
+    0 ->
+        case string:str(Time, "-") of
+        0 ->
+            false;
+        _ ->
+            parse_time_with_timezone(Time, "-")
+        end;
+    _ ->
+        parse_time_with_timezone(Time, "+")
+    end.
+
+parse_time_with_timezone(Time, Delim) ->
+    [T, TZ] = string:tokens(Time, Delim),
+    {TZH, TZM} = parse_timezone(TZ),
+    {TT, MS} = parse_time1(T),
+    case Delim of
+    "-" ->
+        {TT, MS, -TZH, -TZM};
+    "+" ->
+        {TT, MS, TZH, TZM}
+    end.
+
+parse_timezone(TZ) ->
+    [H, M] = string:tokens(TZ, ":"),
+    {[H1, M1], true} = check_list([{H, 12}, {M, 60}]),
+    {H1, M1}.
+
+parse_time1(Time) ->
+    [HMS | T] =  string:tokens(Time, "."),
+    MS = case T of
+         [] ->
+         0;
+         [Val] ->
+         list_to_integer(string:left(Val, 6, $0))
+     end,
+    [H, M, S] = string:tokens(HMS, ":"),
+    {[H1, M1, S1], true} = check_list([{H, 24}, {M, 60}, {S, 60}]),
+    {{H1, M1, S1}, MS}.
+
+check_list(List) ->
+    lists:mapfoldl(
+      fun({L, N}, B)->
+      V = list_to_integer(L),
+      if
+          (V >= 0) and (V =< N) ->
+          {V, B};
+          true ->
+          {false, false}
+      end
+      end, true, List).
+%% @doc 获取当天零点时间戳
+get_curdate_timestamp()->
+    {M, S, T} = os:timestamp(),
+    TimestampTmp = M * 1000000 + S,
+    {{Year,Month,Day},{Hour,Min,Second}}=calendar:now_to_local_time({M, S, T}),
+    TimestampTmp - Second -(Hour*60+Min)*60.
\ No newline at end of file
diff --git a/src/type_decoding.erl b/src/type_decoding.erl
new file mode 100644
index 0000000..343725e
--- /dev/null
+++ b/src/type_decoding.erl
@@ -0,0 +1,214 @@
+% ---------------------------------------------------------------------------
+%   Copyright (C) 2008 0x6e6562
+%
+%   Licensed 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.
+% ---------------------------------------------------------------------------
+
+-module(type_decoding).
+-include("hessian.hrl").
+
+%% The encoding state contains all of the statically known tuple types.
+%% When a tuple is to be decoded at run-time, a lookup is performed against
+%% the hash value that the sender passes in.
+%% This must resolve to some type definition,
+%% otherwise no instance of the decoded type can be created.
+-record(decoding_state,{type_pool = dict:new(), reference_pool = dict:new(),obj_define_no=0}).
+
+-export([init/0,init/1]).
+-export([lookup_reference/2]).
+-export([enlist/1,enlist/2]).
+-export([hash_lookup/2,hash_store/2,hash_store/1,store_typepool/1]).
+-export([visit/2]).
+-export([resolve_native_type/2,resolve_native_type/1]).
+-export([camel_case_to_erlang/1]).
+-export([build_foreign_view/3]).
+-export([project_native_view/3]).
+
+-define(TYPEPOOL_TABLE,type_pool).
+-define(REFERENCEPOOL_TABLE,reference_pool).
+
+camel_case_to_erlang(String) when is_binary(String) ->
+    AsList = binary_to_list(String),
+    AsErlang = lists:foldl(fun decamelize/2,[],AsList),
+    list_to_atom(AsErlang).
+
+decamelize(Element,Acc) when Element >= $A, Element =< $Z ->
+    lists:append(Acc,[$_,(Element + 16#20)] );
+decamelize(Element,Acc) -> lists:append(Acc,[Element]).
+
+%% Facility to register a particular type to the pool of known types.
+%% Adds the type to the pool of known types if it doesn't already exist.
+enlist(TypeDef) -> enlist(TypeDef,init()).
+enlist(TypeDef = #type_def{foreign_type = Key},
+    State = #decoding_state{type_pool = OldPool}) ->
+    ets:insert(?TYPEPOOL_TABLE,{Key,TypeDef}),
+    State.
+
+store_typepool(TypeDef = #type_def{foreign_type = Key}) ->
+    ets:insert(?TYPEPOOL_TABLE,{Key,TypeDef}),
+    TypeDef.
+
+
+
+build_foreign_view(ForeignType,FieldNames,State) ->
+    #type_def{native_type = Native} = resolve_native_type(ForeignType,State),
+    ForeignView = [camel_case_to_erlang(Fieldname) || Fieldname <- FieldNames],
+    DefineNo = State#decoding_state.obj_define_no,
+    {#type_def{
+        defineNo = State#decoding_state.obj_define_no,
+        native_type = Native,
+        foreign_type = ForeignType,
+        fieldnames = ForeignView}, State#decoding_state{obj_define_no = DefineNo}}.
+
+% Projects the native view over tuples that in foreign order
+project_native_view(ForeignView,ForeignData,
+                    #type_def{native_type = NativeType, fieldnames = NativeView}) ->
+    AsDict = dict:from_list(lists:zip(ForeignView,ForeignData)),
+    NativeData = [dict:fetch(Key,AsDict) || Key <- NativeView],
+    list_to_tuple( [NativeType] ++ NativeData).
+
+resolve_native_type(ForeignType, #decoding_state{type_pool = Pool}) ->
+    case ets:lookup(?TYPEPOOL_TABLE,ForeignType) of
+        []->
+            throw({cannot_resolve_type,ForeignType});
+        [{ForeignType,TypeDef}]->
+            TypeDef
+    end.
+resolve_native_type(ForeignType) ->
+    case ets:lookup(?TYPEPOOL_TABLE,ForeignType) of
+        []->
+            undefined;
+        [{ForeignType,TypeDef}]->
+            TypeDef
+    end.
+%%    case dict:fetch(ForeignType,Pool) of
+%%        error ->
+%%            throw({cannot_resolve_type,ForeignType});
+%%        TypeDef ->
+%%            TypeDef
+%%    end.
+
+%% Creates a reference for a type def that is unique within the
+%% current invocation context
+visit(TypeDef, State = #decoding_state{reference_pool = OldPool}) ->
+    Size=ets:info(?REFERENCEPOOL_TABLE,size),
+    ets:insert(?REFERENCEPOOL_TABLE,{Size,TypeDef#type_def{defineNo = Size}}),
+    State.
+%%    Size = dict:size(OldPool),
+%%    NewPool = dict:store(Size, TypeDef, OldPool),
+%%    State#decoding_state{reference_pool = NewPool}.
+
+%% Resolves a type def based on a reference that must be have set
+%% with the current invocation context
+lookup_reference(Ref, #decoding_state{reference_pool = Pool}) ->
+    case ets:lookup(?REFERENCEPOOL_TABLE,Ref) of
+        []->
+            throw("Lookup of unknown reference");
+        [{Ref,TypeDef}]->
+            TypeDef
+    end.
+    %?LOG(Pool),
+    %?LOG(Ref),
+%%    case dict:fetch(Ref,Pool) of
+%%        error ->
+%%%%            ?ERROR(Ref, Pool),
+%%            throw("Lookup of unknown reference");
+%%        TypeDef ->
+%%            TypeDef
+%%    end.
+
+%% Does what it says on the tin.
+hash_lookup(Hash,_State) ->
+%%    init(false),
+    case ets:lookup(?REFERENCEPOOL_TABLE, Hash) of
+        [] ->
+            {not_found, Hash};
+        [{Hash,TypeDef}] ->
+            TypeDef
+    end.
+
+%% Does what it says on the tin.
+hash_store(#type_def{defineNo = Hash} = TypeDef, State) ->
+%%    init(false),
+    case Hash of
+        -1->
+            Size=ets:info(?REFERENCEPOOL_TABLE,size),
+            ets:insert(?REFERENCEPOOL_TABLE,{Size,TypeDef#type_def{defineNo = Size}});
+        _ ->
+            ets:insert(?REFERENCEPOOL_TABLE,{Hash,TypeDef})
+    end,
+    State.
+hash_store(#type_def{defineNo = Hash} = TypeDef) ->
+%%    init(false),
+    NewTypeDef=case Hash of
+        -1->
+            Size=ets:info(?REFERENCEPOOL_TABLE,size),
+            TypeDef2=TypeDef#type_def{defineNo = Size},
+            TypeDef2;
+        _ ->
+            TypeDef
+    end,
+    ets:insert(?REFERENCEPOOL_TABLE,{NewTypeDef#type_def.defineNo,NewTypeDef}),
+    NewTypeDef.
+
+init() -> init(false).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Non-API functions
+
+
+%% This creates a new ETS table for the types that have been received by
+%% this instance of Hessian
+init(Delete) when is_boolean(Delete) ->
+%%    case ets:info(hashes) of
+%%        undefined ->
+%%            io:format("init decoding table pid ~p~n",[self()]),
+%%            ets:new(hashes,[public,named_table]); %% public
+%%        EtsInfo ->
+%%%%            io:format("type decoding etsinfo ~p~n",[EtsInfo]),
+%%            if
+%%                Delete == true ->
+%%                    ets:delete(hashes),
+%%                    ets:new(hashes,[public,named_table]);
+%%                true ->
+%%                    ok
+%%            end
+%%    end,
+    case ets:info(?TYPEPOOL_TABLE) of
+        undefined ->
+            io:format("init decoding type_pool table pid ~p~n",[self()]),
+            ets:new(?TYPEPOOL_TABLE,[public,named_table]); %% public
+        _ ->
+%%            io:format("type decoding etsinfo ~p~n",[EtsInfo]),
+            if
+                Delete == true ->
+                    ets:delete(?TYPEPOOL_TABLE),
+                    ets:new(?TYPEPOOL_TABLE,[public,named_table]);
+                true ->
+                    ok
+            end
+    end,
+    case ets:info(?REFERENCEPOOL_TABLE) of
+        undefined ->
+            io:format("init decoding REFERENCEPOOL_TABLE table pid ~p~n",[self()]),
+            ets:new(?REFERENCEPOOL_TABLE,[public,named_table]); %% public
+        _ ->
+            if
+                Delete == true ->
+                    ets:delete(?REFERENCEPOOL_TABLE),
+                    ets:new(?REFERENCEPOOL_TABLE,[public,named_table]);
+                true ->
+                    ok
+            end
+    end,
+    #decoding_state{}.
\ No newline at end of file
diff --git a/src/type_encoding.erl b/src/type_encoding.erl
new file mode 100644
index 0000000..6105ab3
--- /dev/null
+++ b/src/type_encoding.erl
@@ -0,0 +1,91 @@
+% ---------------------------------------------------------------------------
+%   Copyright (C) 2008 0x6e6562
+%
+%   Licensed 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.
+% ---------------------------------------------------------------------------
+
+-module(type_encoding).
+
+-include("hessian.hrl").
+
+%% The encoding state contains all of the statically known tuple types.
+%% When a tuple is to be encoded at run-time, a lookup is performed against
+%% the type tag. This must resolve to some type definition,
+%% otherwise no type information can be encoded into the output stream.
+-record(encoding_state,{pool = dict:new(), count = -1}).
+
+-export([init/0]).
+-export([enlist/1,enlist/2]).
+-export([visit/2]).
+
+%% Facility to register a particular type to the pool of known types.
+%% Adds the type to the pool of known types if it doesn't already exist.
+init()->
+    #encoding_state{}.
+
+enlist(TypeDef) -> enlist(TypeDef,#encoding_state{}).
+enlist(TypeDef = #type_def{native_type = Key},
+         State = #encoding_state{pool = OldPool}) ->
+    case dict:is_key(Key,OldPool) of
+        true ->
+            State;
+        false ->
+            NewPool = dict:store(Key, {-1, TypeDef}, OldPool),
+            State#encoding_state{pool = NewPool}
+    end.
+
+%% Facility to record the fact that an instance of a type is about to be
+%% encoded into the stream. This needs to decide whether the hash of the
+%% type def has already been written or not.
+%%
+%% If not, a reference to this needs to be generated for future instances
+%% and the hash value of the type def needs to be written out.
+%%
+%% If it already has been written out, it must be back-referenced.
+visit(NativeType, State = #encoding_state{pool = Pool}) ->
+    lager:debug("[encode] visit ~p",[NativeType]),
+    case dict:find(NativeType,Pool) of
+        {ok,{-1, TypeDef}} ->
+            %% The type needs hashing and it's reference needs updating
+            {Ref,NewTypeDef,NewState} = assign_reference(TypeDef, State),
+%%            Hash = erlang:phash2(TypeDef),
+            %%%%%%%%%%%%%%%%%%%%%%%%%%
+            %% LOOK INTO THIS DEPENDENCY, MAYBE EXTRACT IT OUT
+%%            type_decoding:hash_store(NewTypeDef,NewState),  %% 貌似这个没用,可以去掉.
+            %%%%%%%%%%%%%%%%%%%%%%%%%%
+            {hash, Ref,NewTypeDef , NewState};
+        {ok,{Ref, TypeDef} } ->
+            {ref, Ref};
+        error ->
+            case get_deftype_public_pool(NativeType) of
+                undefined ->
+                    throw("unkonw native type "++ atom_to_list(NativeType));
+                TypeDefTmp ->
+                    State2 = enlist(TypeDefTmp,State),
+                    visit(NativeType,State2)
+            end
+    end.
+
+%% This increments the reference count for the current scope and updates the
+%% reference in the pool of known types
+assign_reference(TypeDef = #type_def{native_type = Key},
+                 #encoding_state{pool = OldPool, count = Count}) ->
+    NewCount = Count + 1,
+    NewTypeDef = TypeDef#type_def{defineNo = NewCount},
+    Value = {NewCount, NewTypeDef},
+    NewPool = dict:store(Key, Value, OldPool),
+    lager:debug("[encode] assign_reference type ~p definedNo ~p",[Key,NewCount]),
+    {NewCount,NewTypeDef,#encoding_state{pool = NewPool, count = NewCount}}.
+
+get_deftype_public_pool(NativeType)->
+    type_register:lookup_native_type(NativeType).
\ No newline at end of file
diff --git a/src/type_register.erl b/src/type_register.erl
new file mode 100644
index 0000000..6912cf2
--- /dev/null
+++ b/src/type_register.erl
@@ -0,0 +1,57 @@
+%%%-------------------------------------------------------------------
+%%% @author dlive
+%%% @copyright (C) 2018, <COMPANY>
+%%% @doc
+%%%
+%%% @end
+%%% Created : 05. Mar 2018 2:06 PM
+%%%-------------------------------------------------------------------
+-module(type_register).
+-author("dlive").
+%% API
+-export([init/0,regiest_foreign_native/1,lookup_foreign_type/1,lookup_native_type/1]).
+-include("hessian.hrl").
+-define(FOREIGN_NATIVE_TABLE,foreign_native_table).
+-define(NATIVE_FOREIGN_TABLE,native_foreign_table).
+
+init()->
+    case ets:info(?FOREIGN_NATIVE_TABLE) of
+        undefined ->
+            io:format("init decoding foreign_native_table table pid ~p~n",[self()]),
+            ets:new(?FOREIGN_NATIVE_TABLE,[public,named_table]); %% public
+        _ ->
+            ets:delete(?FOREIGN_NATIVE_TABLE),
+            ets:new(?FOREIGN_NATIVE_TABLE,[public,named_table])
+    end,
+    case ets:info(?NATIVE_FOREIGN_TABLE) of
+        undefined ->
+            io:format("init decoding foreign_native_table table pid ~p~n",[self()]),
+            ets:new(?NATIVE_FOREIGN_TABLE,[public,named_table]); %% public
+        _ ->
+            ets:delete(?NATIVE_FOREIGN_TABLE),
+            ets:new(?NATIVE_FOREIGN_TABLE,[public,named_table])
+    end,
+    ok.
+
+
+regiest_foreign_native(TypeDef)->
+    lager:debug("regiest foreign info ~p",[TypeDef]),
+    ets:insert(?FOREIGN_NATIVE_TABLE,{TypeDef#type_def.foreign_type,TypeDef}),
+    ets:insert(?NATIVE_FOREIGN_TABLE,{TypeDef#type_def.native_type,TypeDef}).
+
+
+lookup_foreign_type(ForeignType)->
+    case ets:lookup(?FOREIGN_NATIVE_TABLE,ForeignType) of
+        []->
+            undefined;
+        [{_,TypeDef}] ->
+            TypeDef
+    end.
+
+lookup_native_type(NativeType)->
+    case ets:lookup(?NATIVE_FOREIGN_TABLE,NativeType) of
+        []->
+            undefined;
+        [{_,TypeDef}] ->
+            TypeDef
+    end.
\ No newline at end of file
diff --git a/test/de_codec_tests.erl b/test/de_codec_tests.erl
new file mode 100644
index 0000000..5cf1e04
--- /dev/null
+++ b/test/de_codec_tests.erl
@@ -0,0 +1,20 @@
+%%%-------------------------------------------------------------------
+%%% @author dlive
+%%% @copyright (C) 2018, <COMPANY>
+%%% @doc
+%%%
+%%% @end
+%%% Created : 06. Apr 2018 4:49 PM
+%%%-------------------------------------------------------------------
+-module(de_codec_tests).
+-author("dlive").
+
+-include_lib("eunit/include/eunit.hrl").
+-include("dubbo.hrl").
+
+-record(databaseOperateRequest,{
+    param}).
+
+
+simple_test() ->
+    ?assert(true).
diff --git a/test/dubbo_config_parser_tests.erl b/test/dubbo_config_parser_tests.erl
new file mode 100644
index 0000000..3bbf79f
--- /dev/null
+++ b/test/dubbo_config_parser_tests.erl
@@ -0,0 +1,22 @@
+%%%-------------------------------------------------------------------
+%%% @author dlive
+%%% @copyright (C) 2017, <COMPANY>
+%%% @doc
+%%%
+%%% @end
+%%% Created : 30. Dec 2017 2:52 PM
+%%%-------------------------------------------------------------------
+-module(dubbo_config_parser_tests).
+-author("dlive").
+
+-include_lib("eunit/include/eunit.hrl").
+-include("dubbo.hrl").
+
+simple_test() ->
+    {ok,ProviderConfig} = dubbo_node_config_util:parse_provider_info("..."),
+%%    io:format(user,"parse config result ~p~n",[ProviderConfig]),
+    ?assertEqual(ProviderConfig#provider_config.protocol,dubbo),
+    ?assertEqual(ProviderConfig#provider_config.host,"192.168.1.6"),
+    ?assertEqual(ProviderConfig#provider_config.port,20880),
+    ?assertEqual(ProviderConfig#provider_config.interface,<<"...">>),
+    ?assert(true).
diff --git a/test/dubbo_zookeeper_tests.erl b/test/dubbo_zookeeper_tests.erl
new file mode 100644
index 0000000..b67248d
--- /dev/null
+++ b/test/dubbo_zookeeper_tests.erl
@@ -0,0 +1,19 @@
+%%%-------------------------------------------------------------------
+%%% @author dlive
+%%% @copyright (C) 2017, <COMPANY>
+%%% @doc
+%%%
+%%% @end
+%%% Created : 26. Dec 2017 4:55 PM
+%%%-------------------------------------------------------------------
+-module(dubbo_zookeeper_tests).
+-author("dlive").
+
+-include_lib("eunit/include/eunit.hrl").
+-include("dubbo.hrl").
+exist_test() ->
+    Consumer=#consumer_config{interface = <<"com.ifcoder.demo.facade.User">>,
+        methods = [<<"a">>,<<"b">>]},
+    V= dubbo_zookeeper:gen_consumer_node_info(Consumer),
+    io:format(user,"gen consumer info:~p~n",[V]),
+    ?assert(true).