THRIFT-2110 Erlang: Support for Multiplexing Services on any Transport, Protocol and Server
Client: Erlang
Patch: David Robakowski rebased by Nobuaki Sukegawa

Modification: Return value fix in thrift_client uncovered by added tests
diff --git a/lib/erl/src/thrift_client_util.erl b/lib/erl/src/thrift_client_util.erl
index 265c308..1dbe51e 100644
--- a/lib/erl/src/thrift_client_util.erl
+++ b/lib/erl/src/thrift_client_util.erl
@@ -20,6 +20,11 @@
 -module(thrift_client_util).
 
 -export([new/4]).
+-export([new_multiplexed/3, new_multiplexed/4]).
+
+-type service_name()            :: nonempty_string().
+-type service_module()          :: atom().
+-type multiplexed_service_map() :: [{ServiceName::service_name(), ServiceModule::service_module()}].
 
 %%
 %% Splits client options into client, protocol, and transport options
@@ -76,3 +81,32 @@
         {error, Error} ->
             {error, Error}
     end.
+
+-spec new_multiplexed(Host, Port, Services, Options) -> {ok, ServiceThriftClientList} when
+    Host        :: nonempty_string(),
+    Port        :: non_neg_integer(),
+    Services    :: multiplexed_service_map(),
+    Options     :: list(),
+    ServiceThriftClientList :: [{ServiceName::list(), ThriftClient::term()}].
+new_multiplexed(Host, Port, Services, Options) when is_integer(Port),
+                                                    is_list(Services),
+                                                    is_list(Options) ->
+    new_multiplexed(thrift_socket_transport:new_transport_factory(Host, Port, Options), Services, Options).
+
+-spec new_multiplexed(TransportFactoryTuple, Services, Options) -> {ok, ServiceThriftClientList} when
+    TransportFactoryTuple   :: {ok, TransportFactory::term()},
+    Services                :: multiplexed_service_map(),
+    Options                 :: list(),
+    ServiceThriftClientList :: [{ServiceName::service_name(), ThriftClient::term()}].
+new_multiplexed(TransportFactoryTuple, Services, Options) when is_list(Services),
+                                                               is_list(Options),
+                                                               is_tuple(TransportFactoryTuple) ->
+    {ProtoOpts, _} = split_options(Options),
+
+    {ok, TransportFactory} = TransportFactoryTuple,
+
+    {ok, ProtocolFactory} = thrift_binary_protocol:new_protocol_factory(TransportFactory, ProtoOpts),
+
+    {ok, Protocol} = ProtocolFactory(),
+
+    {ok, [{ServiceName, element(2, thrift_client:new(element(2, thrift_multiplexed_protocol:new(Protocol, ServiceName)), Service))} || {ServiceName, Service} <- Services]}.