You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@thrift.apache.org by je...@apache.org on 2013/05/08 18:48:37 UTC

[2/2] git commit: THRIFT-1901 C#: Support for Multiplexing Services on any Transport, Protocol and Server

THRIFT-1901 C#: Support for Multiplexing Services on any Transport, Protocol and Server

Patch: Jens Geyer


Project: http://git-wip-us.apache.org/repos/asf/thrift/repo
Commit: http://git-wip-us.apache.org/repos/asf/thrift/commit/7203424e
Tree: http://git-wip-us.apache.org/repos/asf/thrift/tree/7203424e
Diff: http://git-wip-us.apache.org/repos/asf/thrift/diff/7203424e

Branch: refs/heads/master
Commit: 7203424e96146e03e770bae7809d9e03cbecdcfc
Parents: f670181
Author: Jens Geyer <je...@apache.org>
Authored: Wed May 8 18:46:57 2013 +0200
Committer: Jens Geyer <je...@apache.org>
Committed: Wed May 8 18:46:57 2013 +0200

----------------------------------------------------------------------
 lib/csharp/Makefile.am                             |    3 +
 lib/csharp/src/Protocol/TMultiplexedProcessor.cs   |  169 ++++++++++
 lib/csharp/src/Protocol/TMultiplexedProtocol.cs    |  105 ++++++
 lib/csharp/src/Protocol/TProtocolDecorator.cs      |  262 +++++++++++++++
 lib/csharp/src/Thrift.WP7.csproj                   |    3 +
 lib/csharp/src/Thrift.csproj                       |    5 +-
 .../test/Multiplex/Client/Multiplex.Test.Client.cs |   87 +++++
 .../test/Multiplex/Client/MultiplexClient.csproj   |  148 ++++++++
 .../Multiplex/Client/Properties/AssemblyInfo.cs    |   55 +++
 lib/csharp/test/Multiplex/Multiplex.Test.Common.cs |   40 +++
 .../test/Multiplex/Server/Multiplex.Test.Server.cs |  131 +++++++
 .../test/Multiplex/Server/MultiplexServer.csproj   |  148 ++++++++
 .../Multiplex/Server/Properties/AssemblyInfo.cs    |   55 +++
 lib/csharp/test/Multiplex/maketest.sh              |   34 ++
 14 files changed, 1244 insertions(+), 1 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/thrift/blob/7203424e/lib/csharp/Makefile.am
----------------------------------------------------------------------
diff --git a/lib/csharp/Makefile.am b/lib/csharp/Makefile.am
index f13f90a..b785868 100644
--- a/lib/csharp/Makefile.am
+++ b/lib/csharp/Makefile.am
@@ -33,6 +33,9 @@ THRIFTCODE= \
             src/Protocol/TProtocolUtil.cs \
             src/Protocol/TMessageType.cs \
             src/Protocol/TProtocol.cs \
+            src/Protocol/TProtocolDecorator.cs \
+            src/Protocol/TMultiplexedProtocol.cs \
+            src/Protocol/TMultiplexedProcessor.cs \
             src/Protocol/TType.cs \
             src/Protocol/TField.cs \
             src/Protocol/TMessage.cs \

http://git-wip-us.apache.org/repos/asf/thrift/blob/7203424e/lib/csharp/src/Protocol/TMultiplexedProcessor.cs
----------------------------------------------------------------------
diff --git a/lib/csharp/src/Protocol/TMultiplexedProcessor.cs b/lib/csharp/src/Protocol/TMultiplexedProcessor.cs
new file mode 100644
index 0000000..29fac9e
--- /dev/null
+++ b/lib/csharp/src/Protocol/TMultiplexedProcessor.cs
@@ -0,0 +1,169 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ * Contains some contributions under the Thrift Software License.
+ * Please see doc/old-thrift-license.txt in the Thrift distribution for
+ * details.
+ */
+
+using System;
+using System.Text;
+using Thrift.Transport;
+using System.Collections.Generic;
+
+namespace Thrift.Protocol 
+{
+
+    /**
+     * TMultiplexedProcessor is a TProcessor allowing a single TServer to provide multiple services.
+     * To do so, you instantiate the processor and then register additional processors with it, 
+     * as shown in the following example:
+     *
+     *     TMultiplexedProcessor processor = new TMultiplexedProcessor();
+     *
+     *     processor.registerProcessor(
+     *         "Calculator",
+     *         new Calculator.Processor(new CalculatorHandler()));
+     *
+     *     processor.registerProcessor(
+     *         "WeatherReport",
+     *         new WeatherReport.Processor(new WeatherReportHandler()));
+     *
+     *     TServerTransport t = new TServerSocket(9090);
+     *     TSimpleServer server = new TSimpleServer(processor, t);
+     *
+     *     server.serve();
+     */
+    public class TMultiplexedProcessor : TProcessor 
+    {
+        private Dictionary<String,TProcessor> ServiceProcessorMap = new Dictionary<String,TProcessor>();
+
+        /**
+         * 'Register' a service with this TMultiplexedProcessor. This allows us to broker 
+         * requests to individual services by using the service name to select them at request time.
+         *
+         * Args: 
+         * - serviceName    Name of a service, has to be identical to the name
+         *                  declared in the Thrift IDL, e.g. "WeatherReport".
+         * - processor      Implementation of a service, ususally referred to as "handlers", 
+         *                  e.g. WeatherReportHandler implementing WeatherReport.Iface.
+         */
+        public void RegisterProcessor(String serviceName, TProcessor processor) 
+        {
+            ServiceProcessorMap.Add(serviceName, processor);
+        }
+
+        
+        private void Fail( TProtocol oprot, TMessage message, TApplicationException.ExceptionType extype, string etxt)
+        {
+            TApplicationException appex = new TApplicationException( extype, etxt);
+
+            TMessage newMessage = new TMessage(message.Name, TMessageType.Exception, message.SeqID);
+
+            oprot.WriteMessageBegin(newMessage);
+            appex.Write( oprot);
+            oprot.WriteMessageEnd();
+            oprot.Transport.Flush();
+        }
+            
+        
+        /**
+         * This implementation of process performs the following steps:
+         *
+         * - Read the beginning of the message.
+         * - Extract the service name from the message.
+         * - Using the service name to locate the appropriate processor.
+         * - Dispatch to the processor, with a decorated instance of TProtocol
+         *    that allows readMessageBegin() to return the original TMessage.
+         *  
+         * Throws an exception if 
+         * - the message type is not CALL or ONEWAY, 
+         * - the service name was not found in the message, or 
+         * - the service name has not been RegisterProcessor()ed.  
+         */
+        public bool Process(TProtocol iprot, TProtocol oprot)
+        {
+            /*  Use the actual underlying protocol (e.g. TBinaryProtocol) to read the
+                message header.  This pulls the message "off the wire", which we'll
+                deal with at the end of this method. */
+
+            TMessage message = iprot.ReadMessageBegin();
+
+            if ((message.Type != TMessageType.Call) && (message.Type != TMessageType.Oneway)) 
+            {
+                Fail( oprot, message, 
+                      TApplicationException.ExceptionType.InvalidMessageType, 
+                      "Message type CALL or ONEWAY expected");
+                return false;
+            }
+
+            // Extract the service name
+            int index = message.Name.IndexOf(TMultiplexedProtocol.SEPARATOR);
+            if (index < 0) {
+                Fail( oprot, message, 
+                      TApplicationException.ExceptionType.InvalidProtocol,
+                      "Service name not found in message name: " + message.Name + ". "+
+                      "Did you forget to use a TMultiplexProtocol in your client?");
+                return false;
+            }
+
+            // Create a new TMessage, something that can be consumed by any TProtocol
+            string serviceName = message.Name.Substring(0, index);
+            TProcessor actualProcessor;
+            if( ! ServiceProcessorMap.TryGetValue(serviceName, out actualProcessor))
+            {
+                Fail( oprot, message, 
+                      TApplicationException.ExceptionType.InternalError,
+                      "Service name not found: " + serviceName + ". "+ 
+                      "Did you forget to call RegisterProcessor()?");
+                return false;
+            }
+
+            // Create a new TMessage, removing the service name
+            TMessage newMessage = new TMessage(
+                    message.Name.Substring(serviceName.Length + TMultiplexedProtocol.SEPARATOR.Length),
+                    message.Type,
+                    message.SeqID);
+
+            // Dispatch processing to the stored processor
+            return actualProcessor.Process(new StoredMessageProtocol(iprot, newMessage), oprot);
+        }
+
+        /**
+         *  Our goal was to work with any protocol.  In order to do that, we needed
+         *  to allow them to call readMessageBegin() and get a TMessage in exactly
+         *  the standard format, without the service name prepended to TMessage.name.
+         */
+        private class StoredMessageProtocol : TProtocolDecorator 
+        {
+            TMessage MsgBegin;
+
+            public StoredMessageProtocol(TProtocol protocol, TMessage messageBegin) 
+                :base(protocol)
+            {
+                this.MsgBegin = messageBegin;
+            }
+
+            public override TMessage ReadMessageBegin()  
+            {
+                return MsgBegin;
+            }
+        }
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/thrift/blob/7203424e/lib/csharp/src/Protocol/TMultiplexedProtocol.cs
----------------------------------------------------------------------
diff --git a/lib/csharp/src/Protocol/TMultiplexedProtocol.cs b/lib/csharp/src/Protocol/TMultiplexedProtocol.cs
new file mode 100644
index 0000000..ccd7fcf
--- /dev/null
+++ b/lib/csharp/src/Protocol/TMultiplexedProtocol.cs
@@ -0,0 +1,105 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ * Contains some contributions under the Thrift Software License.
+ * Please see doc/old-thrift-license.txt in the Thrift distribution for
+ * details.
+ */
+
+using System;
+using System.Text;
+using Thrift.Transport;
+using System.Collections.Generic;
+
+namespace Thrift.Protocol 
+{
+
+    /**
+     * TMultiplexedProtocol is a protocol-independent concrete decorator that allows a Thrift 
+     * client to communicate with a multiplexing Thrift server, by prepending the service name 
+     * to the function name during function calls.
+     *
+     * NOTE: THIS IS NOT TO BE USED BY SERVERS.  
+     * On the server, use TMultiplexedProcessor to handle requests from a multiplexing client.
+     *
+     * This example uses a single socket transport to invoke two services:
+     *
+     *     TSocket transport = new TSocket("localhost", 9090);
+     *     transport.open();
+     *     
+     *     TBinaryProtocol protocol = new TBinaryProtocol(transport);
+     *
+     *     TMultiplexedProtocol mp = new TMultiplexedProtocol(protocol, "Calculator");
+     *     Calculator.Client service = new Calculator.Client(mp);
+     *
+     *     TMultiplexedProtocol mp2 = new TMultiplexedProtocol(protocol, "WeatherReport");
+     *     WeatherReport.Client service2 = new WeatherReport.Client(mp2);
+     *
+     *     System.out.println(service.add(2,2));
+     *     System.out.println(service2.getTemperature());
+     *
+     */
+    public class TMultiplexedProtocol : TProtocolDecorator 
+    {
+
+        /** Used to delimit the service name from the function name */
+        public static String SEPARATOR = ":";
+
+        private String ServiceName;
+
+        /**
+         * Wrap the specified protocol, allowing it to be used to communicate with a
+         * multiplexing server.  The <code>serviceName</code> is required as it is
+         * prepended to the message header so that the multiplexing server can broker
+         * the function call to the proper service.
+         *
+         * Args:
+         *  protocol        Your communication protocol of choice, e.g. TBinaryProtocol
+         *  serviceName     The service name of the service communicating via this protocol.
+         */
+        public TMultiplexedProtocol(TProtocol protocol, String serviceName) 
+            : base(protocol)
+        {
+            ServiceName = serviceName;
+        }
+
+        /**
+         * Prepends the service name to the function name, separated by TMultiplexedProtocol.SEPARATOR.
+         * Args:
+         *   tMessage     The original message.
+         */
+        public override void WriteMessageBegin(TMessage tMessage) 
+        {
+            switch(tMessage.Type)
+            {
+                case TMessageType.Call:
+                case TMessageType.Oneway:
+                    base.WriteMessageBegin(new TMessage(
+                        ServiceName + SEPARATOR + tMessage.Name,
+                        tMessage.Type,
+                        tMessage.SeqID));
+                    break;
+
+                default:
+                    base.WriteMessageBegin(tMessage);
+                    break;
+            }
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/thrift/blob/7203424e/lib/csharp/src/Protocol/TProtocolDecorator.cs
----------------------------------------------------------------------
diff --git a/lib/csharp/src/Protocol/TProtocolDecorator.cs b/lib/csharp/src/Protocol/TProtocolDecorator.cs
new file mode 100644
index 0000000..e1977f5
--- /dev/null
+++ b/lib/csharp/src/Protocol/TProtocolDecorator.cs
@@ -0,0 +1,262 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ * Contains some contributions under the Thrift Software License.
+ * Please see doc/old-thrift-license.txt in the Thrift distribution for
+ * details.
+ */
+
+using System;
+using System.Text;
+using Thrift.Transport;
+using System.Collections.Generic;
+
+namespace Thrift.Protocol 
+{
+
+    /**
+     * TProtocolDecorator forwards all requests to an enclosed TProtocol instance, 
+     * providing a way to author concise concrete decorator subclasses.  While it has 
+     * no abstract methods, it is marked abstract as a reminder that by itself, 
+     * it does not modify the behaviour of the enclosed TProtocol.
+     *
+     * See p.175 of Design Patterns (by Gamma et al.)
+     * See TMultiplexedProtocol
+     */
+    public abstract class TProtocolDecorator : TProtocol 
+    {
+        private TProtocol WrappedProtocol;
+
+        /**
+         * Encloses the specified protocol.
+         * @param protocol All operations will be forward to this protocol.  Must be non-null.
+         */
+        public TProtocolDecorator(TProtocol protocol) 
+            : base( protocol.Transport)
+        {
+            
+            WrappedProtocol = protocol;
+        }
+
+        public override void WriteMessageBegin(TMessage tMessage) 
+        {
+            WrappedProtocol.WriteMessageBegin(tMessage);
+        }
+
+        public override void WriteMessageEnd()
+        {
+            WrappedProtocol.WriteMessageEnd();
+        }
+
+        public override void WriteStructBegin(TStruct tStruct)
+        {
+            WrappedProtocol.WriteStructBegin(tStruct);
+        }
+
+        public override void WriteStructEnd()
+        {
+            WrappedProtocol.WriteStructEnd();
+        }
+
+        public override void WriteFieldBegin(TField tField)
+        {
+            WrappedProtocol.WriteFieldBegin(tField);
+        }
+
+        public override void WriteFieldEnd()
+        {
+            WrappedProtocol.WriteFieldEnd();
+        }
+
+        public override void WriteFieldStop()
+        {
+            WrappedProtocol.WriteFieldStop();
+        }
+
+        public override void WriteMapBegin(TMap tMap) 
+        {
+            WrappedProtocol.WriteMapBegin(tMap);
+        }
+
+        public override void WriteMapEnd()
+        {
+            WrappedProtocol.WriteMapEnd();
+        }
+
+        public override void WriteListBegin(TList tList)  
+        {
+            WrappedProtocol.WriteListBegin(tList);
+        }
+
+        public override void WriteListEnd()
+{
+            WrappedProtocol.WriteListEnd();
+        }
+
+        public override void WriteSetBegin(TSet tSet)  
+        {
+            WrappedProtocol.WriteSetBegin(tSet);
+        }
+
+        public override void WriteSetEnd()
+        {
+            WrappedProtocol.WriteSetEnd();
+        }
+
+        public override void WriteBool(bool b)  
+        {
+            WrappedProtocol.WriteBool(b);
+        }
+
+        public override void WriteByte(sbyte b)
+        {
+            WrappedProtocol.WriteByte(b);
+        }
+
+        public override void WriteI16(short i)
+        {
+            WrappedProtocol.WriteI16(i);
+        }
+
+        public override void WriteI32(int i)
+        {
+            WrappedProtocol.WriteI32(i);
+        }
+
+        public override void WriteI64(long l)
+        {
+            WrappedProtocol.WriteI64(l);
+        }
+
+        public override void WriteDouble(double v)
+        {
+            WrappedProtocol.WriteDouble(v);
+        }
+
+        public override void WriteString(String s)
+        {
+            WrappedProtocol.WriteString(s);
+        }
+
+        public override void WriteBinary(byte[] bytes)
+        {
+            WrappedProtocol.WriteBinary(bytes);
+        }
+
+        public override TMessage ReadMessageBegin()
+        {
+            return WrappedProtocol.ReadMessageBegin();
+        }
+
+        public override void ReadMessageEnd()
+        {
+            WrappedProtocol.ReadMessageEnd();
+        }
+
+        public override TStruct ReadStructBegin()
+        {
+            return WrappedProtocol.ReadStructBegin();
+        }
+
+        public override void ReadStructEnd()
+        {
+            WrappedProtocol.ReadStructEnd();
+        }
+
+        public override TField ReadFieldBegin()
+        {
+            return WrappedProtocol.ReadFieldBegin();
+        }
+
+        public override void ReadFieldEnd()
+        {
+            WrappedProtocol.ReadFieldEnd();
+        }
+
+        public override TMap ReadMapBegin()
+        {
+            return WrappedProtocol.ReadMapBegin();
+        }
+
+        public override void ReadMapEnd()
+        {
+            WrappedProtocol.ReadMapEnd();
+        }
+
+        public override TList ReadListBegin()
+        {
+            return WrappedProtocol.ReadListBegin();
+        }
+
+        public override void ReadListEnd()
+        {
+            WrappedProtocol.ReadListEnd();
+        }
+
+        public override TSet ReadSetBegin()
+        {
+            return WrappedProtocol.ReadSetBegin();
+        }
+
+        public override void ReadSetEnd()
+        {
+            WrappedProtocol.ReadSetEnd();
+        }
+
+        public override bool ReadBool()
+        {
+            return WrappedProtocol.ReadBool();
+        }
+
+        public override sbyte ReadByte()
+        {
+            return WrappedProtocol.ReadByte();
+        }
+
+        public override short ReadI16()
+        {
+            return WrappedProtocol.ReadI16();
+        }
+
+        public override int ReadI32()
+        {
+            return WrappedProtocol.ReadI32();
+        }
+
+        public override long ReadI64()
+        {
+            return WrappedProtocol.ReadI64();
+        }
+
+        public override double ReadDouble()
+        {
+            return WrappedProtocol.ReadDouble();
+        }
+
+        public override String ReadString()
+        {
+            return WrappedProtocol.ReadString();
+        }
+
+        public override byte[] ReadBinary()
+        {
+            return WrappedProtocol.ReadBinary();
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/thrift/blob/7203424e/lib/csharp/src/Thrift.WP7.csproj
----------------------------------------------------------------------
diff --git a/lib/csharp/src/Thrift.WP7.csproj b/lib/csharp/src/Thrift.WP7.csproj
index eaaf300..e9dc494 100644
--- a/lib/csharp/src/Thrift.WP7.csproj
+++ b/lib/csharp/src/Thrift.WP7.csproj
@@ -83,7 +83,10 @@
     <Compile Include="Protocol\TMap.cs" />
     <Compile Include="Protocol\TMessage.cs" />
     <Compile Include="Protocol\TMessageType.cs" />
+    <Compile Include="Protocol\TMultiplexedProcessor.cs" />
+    <Compile Include="Protocol\TMultiplexedProtocol.cs" />
     <Compile Include="Protocol\TProtocol.cs" />
+    <Compile Include="Protocol\TProtocolDecorator.cs" />
     <Compile Include="Protocol\TProtocolException.cs" />
     <Compile Include="Protocol\TProtocolFactory.cs" />
     <Compile Include="Protocol\TProtocolUtil.cs" />

http://git-wip-us.apache.org/repos/asf/thrift/blob/7203424e/lib/csharp/src/Thrift.csproj
----------------------------------------------------------------------
diff --git a/lib/csharp/src/Thrift.csproj b/lib/csharp/src/Thrift.csproj
index 0722c18..cb264c8 100644
--- a/lib/csharp/src/Thrift.csproj
+++ b/lib/csharp/src/Thrift.csproj
@@ -91,7 +91,10 @@
     <Compile Include="Protocol\TMap.cs" />
     <Compile Include="Protocol\TMessage.cs" />
     <Compile Include="Protocol\TMessageType.cs" />
+    <Compile Include="Protocol\TMultiplexedProcessor.cs" />
+    <Compile Include="Protocol\TMultiplexedProtocol.cs" />
     <Compile Include="Protocol\TProtocol.cs" />
+    <Compile Include="Protocol\TProtocolDecorator.cs" />
     <Compile Include="Protocol\TProtocolException.cs" />
     <Compile Include="Protocol\TProtocolFactory.cs" />
     <Compile Include="Protocol\TProtocolUtil.cs" />
@@ -138,4 +141,4 @@
   <ProjectExtensions>
     <VisualStudio AllowExistingFolder="true" />
   </ProjectExtensions>
-</Project>
+</Project>

http://git-wip-us.apache.org/repos/asf/thrift/blob/7203424e/lib/csharp/test/Multiplex/Client/Multiplex.Test.Client.cs
----------------------------------------------------------------------
diff --git a/lib/csharp/test/Multiplex/Client/Multiplex.Test.Client.cs b/lib/csharp/test/Multiplex/Client/Multiplex.Test.Client.cs
new file mode 100644
index 0000000..95ba5a4
--- /dev/null
+++ b/lib/csharp/test/Multiplex/Client/Multiplex.Test.Client.cs
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+using System;
+using System.Collections.Generic;
+using Thrift.Collections;
+using Thrift.Transport;
+using Thrift.Protocol;
+using Thrift.Server;
+using Thrift;
+using Test.Multiplex;
+
+
+namespace Test.Multiplex.Client
+{
+	public class TestClient
+	{
+        private void Run()
+        {
+            try
+            {
+                TTransport trans;
+                trans = new TSocket("localhost", 9090);
+                trans = new TFramedTransport(trans);
+                trans.Open();
+
+                TProtocol Protocol = new TBinaryProtocol(trans, true, true);
+
+                TMultiplexedProtocol multiplex;
+
+                multiplex = new TMultiplexedProtocol( Protocol, Constants.NAME_BENCHMARKSERVICE);
+                BenchmarkService.Iface bench = new BenchmarkService.Client( multiplex);
+
+                multiplex = new TMultiplexedProtocol( Protocol, Constants.NAME_AGGR);
+                Aggr.Iface aggr = new Aggr.Client( multiplex);
+                
+                sbyte i;
+                for( i = 1; 10 >= i; ++i)
+                {
+                    aggr.addValue( bench.fibonacci(i));
+                }
+
+                foreach( int k in aggr.getValues())
+                {
+                    Console.Write(k.ToString()+" ");
+                    Console.WriteLine("");
+                }
+            }
+            catch( Exception e)
+            {
+                Console.WriteLine( e.Message);
+            }
+        }
+
+
+        public static void Execute()
+        {
+            TestClient client = new TestClient();
+            client.Run();
+        }
+
+        static void Main(string[] args)
+        {
+            Execute();
+            Console.WriteLine("done.");
+            Console.ReadLine();
+        }
+
+    }
+}
+

http://git-wip-us.apache.org/repos/asf/thrift/blob/7203424e/lib/csharp/test/Multiplex/Client/MultiplexClient.csproj
----------------------------------------------------------------------
diff --git a/lib/csharp/test/Multiplex/Client/MultiplexClient.csproj b/lib/csharp/test/Multiplex/Client/MultiplexClient.csproj
new file mode 100644
index 0000000..6221e14
--- /dev/null
+++ b/lib/csharp/test/Multiplex/Client/MultiplexClient.csproj
@@ -0,0 +1,148 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements. See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership. The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License. You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied. See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>9.0.21022</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{5E91DA17-E548-415F-8C9F-9E84EDF8EE06}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>MultiplexClient</RootNamespace>
+    <AssemblyName>MultiplexClient</AssemblyName>
+    <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <IsWebBootstrapper>false</IsWebBootstrapper>
+    <FileUpgradeFlags>
+    </FileUpgradeFlags>
+    <OldToolsVersion>3.5</OldToolsVersion>
+    <UpgradeBackupLocation />
+    <PublishUrl>publish\</PublishUrl>
+    <Install>true</Install>
+    <InstallFrom>Disk</InstallFrom>
+    <UpdateEnabled>false</UpdateEnabled>
+    <UpdateMode>Foreground</UpdateMode>
+    <UpdateInterval>7</UpdateInterval>
+    <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+    <UpdatePeriodically>false</UpdatePeriodically>
+    <UpdateRequired>false</UpdateRequired>
+    <MapFileExtensions>true</MapFileExtensions>
+    <ApplicationRevision>0</ApplicationRevision>
+    <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+    <UseApplicationTrust>false</UseApplicationTrust>
+    <BootstrapperEnabled>true</BootstrapperEnabled>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>..\bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>..\bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="..\Multiplex.Test.Common.cs">
+      <Link>Multiplex.Test.Common.cs</Link>
+    </Compile>
+    <Compile Include="..\gen-csharp\Aggr.cs" />
+    <Compile Include="..\gen-csharp\BenchmarkService.cs" />
+    <Compile Include="..\gen-csharp\Error.cs" />
+    <Compile Include="Multiplex.Test.Client.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
+      <Install>false</Install>
+    </BootstrapperPackage>
+    <BootstrapperPackage Include="Microsoft.Net.Framework.2.0">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 2.0 %28x86%29</ProductName>
+      <Install>false</Install>
+    </BootstrapperPackage>
+    <BootstrapperPackage Include="Microsoft.Net.Framework.3.0">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 3.0 %28x86%29</ProductName>
+      <Install>false</Install>
+    </BootstrapperPackage>
+    <BootstrapperPackage Include="Microsoft.Net.Framework.3.5">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 3.5</ProductName>
+      <Install>true</Install>
+    </BootstrapperPackage>
+    <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 3.5 SP1</ProductName>
+      <Install>false</Install>
+    </BootstrapperPackage>
+    <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
+      <Visible>False</Visible>
+      <ProductName>Windows Installer 3.1</ProductName>
+      <Install>true</Install>
+    </BootstrapperPackage>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\..\src\Thrift.csproj">
+      <Project>{499EB63C-D74C-47E8-AE48-A2FC94538E9D}</Project>
+      <Name>Thrift</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+  <PropertyGroup>
+    <PreBuildEvent>rmdir /s /q "$(ProjectDir)gen-csharp"
+del /f /q "$(ProjectDir)ThriftImpl.dll"
+SET OUTPUT_DIR=$(ProjectDir)
+
+SET THRIFT_FILE=$(ProjectDir)\..\..\..\..\..\contrib\async-test\aggr.thrift
+for %25%25I in ("%25OUTPUT_DIR%25") do set SHORT_DIR=%25%25~fsI
+for %25%25I in ("%25THRIFT_FILE%25") do set THRIFT_SHORT=%25%25~fsI
+"$(ProjectDir)\..\..\..\..\..\compiler\cpp\thrift.exe" --gen csharp -o %25SHORT_DIR%25 %25THRIFT_SHORT%25
+
+SET THRIFT_FILE=$(ProjectDir)\..\..\..\..\..\lib\rb\benchmark\Benchmark.thrift
+for %25%25I in ("%25OUTPUT_DIR%25") do set SHORT_DIR=%25%25~fsI
+for %25%25I in ("%25THRIFT_FILE%25") do set THRIFT_SHORT=%25%25~fsI
+"$(ProjectDir)\..\..\..\..\..\compiler\cpp\thrift.exe" --gen csharp -o %25SHORT_DIR%25 %25THRIFT_SHORT%25
+
+</PreBuildEvent>
+  </PropertyGroup>
+</Project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/thrift/blob/7203424e/lib/csharp/test/Multiplex/Client/Properties/AssemblyInfo.cs
----------------------------------------------------------------------
diff --git a/lib/csharp/test/Multiplex/Client/Properties/AssemblyInfo.cs b/lib/csharp/test/Multiplex/Client/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..ee234bf
--- /dev/null
+++ b/lib/csharp/test/Multiplex/Client/Properties/AssemblyInfo.cs
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("MultiplexClient")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("MultiplexClient")]
+[assembly: AssemblyCopyright("Copyright © 2013 The Apache Software Foundation")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components.  If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("66FC61E5-420B-4b56-8012-D6D6CE22537F")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]

http://git-wip-us.apache.org/repos/asf/thrift/blob/7203424e/lib/csharp/test/Multiplex/Multiplex.Test.Common.cs
----------------------------------------------------------------------
diff --git a/lib/csharp/test/Multiplex/Multiplex.Test.Common.cs b/lib/csharp/test/Multiplex/Multiplex.Test.Common.cs
new file mode 100644
index 0000000..5296b68
--- /dev/null
+++ b/lib/csharp/test/Multiplex/Multiplex.Test.Common.cs
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// Distributed under the Thrift Software License
+//
+// See accompanying file LICENSE or visit the Thrift site at:
+// http://developers.facebook.com/thrift/
+using System;
+using System.Collections.Generic;
+using Thrift.Collections;
+using Thrift.Transport;
+using Thrift.Protocol;
+using Thrift.Server;
+
+namespace Test.Multiplex
+{
+	public class Constants
+	{
+        public const string NAME_BENCHMARKSERVICE = "BenchmarkService";
+        public const string NAME_AGGR             = "Aggr";
+    }
+}
+
+

http://git-wip-us.apache.org/repos/asf/thrift/blob/7203424e/lib/csharp/test/Multiplex/Server/Multiplex.Test.Server.cs
----------------------------------------------------------------------
diff --git a/lib/csharp/test/Multiplex/Server/Multiplex.Test.Server.cs b/lib/csharp/test/Multiplex/Server/Multiplex.Test.Server.cs
new file mode 100644
index 0000000..fbec1b7
--- /dev/null
+++ b/lib/csharp/test/Multiplex/Server/Multiplex.Test.Server.cs
@@ -0,0 +1,131 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+using System;
+using System.Collections.Generic;
+using Thrift.Collections;
+using Thrift.Transport;
+using Thrift.Protocol;
+using Thrift.Server;
+using Thrift;
+using Test.Multiplex;
+
+namespace Test.Multiplex.Server
+{
+	public class TestServer
+	{
+        public interface ITestHandler
+        {
+            void SetServer( TServer aServer);
+        }
+
+        protected class TestHandlerImpl : ITestHandler
+        {
+            private TServer Server;
+    
+            public void SetServer( TServer aServer)
+            {
+                Server = aServer;
+            }
+        }
+
+
+        protected class BenchmarkServiceImpl : TestHandlerImpl, BenchmarkService.Iface
+        {
+            public int fibonacci(sbyte n)
+            {
+                int prev, next, result;
+                prev   = 0;
+                result = 1;
+                while( n > 0) 
+                {
+                    next   = result + prev;
+                    prev   = result;
+                    result = next;
+                    --n;
+                }
+                return result;
+            }
+        }
+
+
+        protected class AggrServiceImpl : TestHandlerImpl,  Aggr.Iface
+        {
+            List<int> values = new List<int>();
+
+            public void addValue(int value)
+            {
+                values.Add( value);
+            }
+
+            public List<int> getValues()
+            {
+                return values;
+            }
+        }
+
+       static void Execute()
+       {
+           try
+           {
+               // create protocol factory, default to BinaryProtocol
+               TProtocolFactory ProtocolFactory = new TBinaryProtocol.Factory(true,true);
+               TServerTransport servertrans     = new TServerSocket( 9090, 0, false);
+               TTransportFactory TransportFactory = new TFramedTransport.Factory();
+
+               BenchmarkService.Iface benchHandler = new BenchmarkServiceImpl();
+               TProcessor benchProcessor = new BenchmarkService.Processor( benchHandler);
+
+               Aggr.Iface aggrHandler = new AggrServiceImpl();
+               TProcessor aggrProcessor = new Aggr.Processor( aggrHandler);
+
+               TMultiplexedProcessor multiplex = new TMultiplexedProcessor();
+               multiplex.RegisterProcessor(Constants.NAME_BENCHMARKSERVICE, benchProcessor);
+               multiplex.RegisterProcessor(Constants.NAME_AGGR, aggrProcessor);
+
+               TServer ServerEngine = new TSimpleServer( multiplex, servertrans, TransportFactory, ProtocolFactory);
+
+               (benchHandler as ITestHandler).SetServer( ServerEngine);
+               (aggrHandler as ITestHandler).SetServer( ServerEngine);
+
+               Console.WriteLine("Starting the server ...");
+               ServerEngine.Serve();
+
+               (benchHandler as ITestHandler).SetServer(null);
+               (aggrHandler as ITestHandler).SetServer(null);
+
+           } 
+           catch( Exception e)
+           {
+               Console.WriteLine( e.Message);
+           }
+           Console.WriteLine( "done.");
+       }
+
+        
+       static void Main(string[] args)
+       {
+           Execute();
+       }
+    }
+
+
+
+}
+

http://git-wip-us.apache.org/repos/asf/thrift/blob/7203424e/lib/csharp/test/Multiplex/Server/MultiplexServer.csproj
----------------------------------------------------------------------
diff --git a/lib/csharp/test/Multiplex/Server/MultiplexServer.csproj b/lib/csharp/test/Multiplex/Server/MultiplexServer.csproj
new file mode 100644
index 0000000..dc1d123
--- /dev/null
+++ b/lib/csharp/test/Multiplex/Server/MultiplexServer.csproj
@@ -0,0 +1,148 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements. See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership. The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License. You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied. See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>9.0.21022</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{D592BDF3-0DCE-48FB-890F-E4AE1D9CE7CD}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>MultiplexServer</RootNamespace>
+    <AssemblyName>MultiplexServer</AssemblyName>
+    <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <IsWebBootstrapper>false</IsWebBootstrapper>
+    <FileUpgradeFlags>
+    </FileUpgradeFlags>
+    <OldToolsVersion>3.5</OldToolsVersion>
+    <UpgradeBackupLocation />
+    <PublishUrl>publish\</PublishUrl>
+    <Install>true</Install>
+    <InstallFrom>Disk</InstallFrom>
+    <UpdateEnabled>false</UpdateEnabled>
+    <UpdateMode>Foreground</UpdateMode>
+    <UpdateInterval>7</UpdateInterval>
+    <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+    <UpdatePeriodically>false</UpdatePeriodically>
+    <UpdateRequired>false</UpdateRequired>
+    <MapFileExtensions>true</MapFileExtensions>
+    <ApplicationRevision>0</ApplicationRevision>
+    <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+    <UseApplicationTrust>false</UseApplicationTrust>
+    <BootstrapperEnabled>true</BootstrapperEnabled>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>..\bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>..\bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="..\Multiplex.Test.Common.cs">
+      <Link>Multiplex.Test.Common.cs</Link>
+    </Compile>
+    <Compile Include="..\gen-csharp\Aggr.cs" />
+    <Compile Include="..\gen-csharp\BenchmarkService.cs" />
+    <Compile Include="..\gen-csharp\Error.cs" />
+    <Compile Include="Multiplex.Test.Server.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
+      <Install>false</Install>
+    </BootstrapperPackage>
+    <BootstrapperPackage Include="Microsoft.Net.Framework.2.0">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 2.0 %28x86%29</ProductName>
+      <Install>false</Install>
+    </BootstrapperPackage>
+    <BootstrapperPackage Include="Microsoft.Net.Framework.3.0">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 3.0 %28x86%29</ProductName>
+      <Install>false</Install>
+    </BootstrapperPackage>
+    <BootstrapperPackage Include="Microsoft.Net.Framework.3.5">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 3.5</ProductName>
+      <Install>true</Install>
+    </BootstrapperPackage>
+    <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 3.5 SP1</ProductName>
+      <Install>false</Install>
+    </BootstrapperPackage>
+    <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
+      <Visible>False</Visible>
+      <ProductName>Windows Installer 3.1</ProductName>
+      <Install>true</Install>
+    </BootstrapperPackage>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\..\src\Thrift.csproj">
+      <Project>{499EB63C-D74C-47E8-AE48-A2FC94538E9D}</Project>
+      <Name>Thrift</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+  <PropertyGroup>
+    <PreBuildEvent>rmdir /s /q "$(ProjectDir)gen-csharp"
+del /f /q "$(ProjectDir)ThriftImpl.dll"
+SET OUTPUT_DIR=$(ProjectDir)
+
+SET THRIFT_FILE=$(ProjectDir)\..\..\..\..\..\contrib\async-test\aggr.thrift
+for %25%25I in ("%25OUTPUT_DIR%25") do set SHORT_DIR=%25%25~fsI
+for %25%25I in ("%25THRIFT_FILE%25") do set THRIFT_SHORT=%25%25~fsI
+"$(ProjectDir)\..\..\..\..\..\compiler\cpp\thrift.exe" --gen csharp -o %25SHORT_DIR%25 %25THRIFT_SHORT%25
+
+SET THRIFT_FILE=$(ProjectDir)\..\..\..\..\..\lib\rb\benchmark\Benchmark.thrift
+for %25%25I in ("%25OUTPUT_DIR%25") do set SHORT_DIR=%25%25~fsI
+for %25%25I in ("%25THRIFT_FILE%25") do set THRIFT_SHORT=%25%25~fsI
+"$(ProjectDir)\..\..\..\..\..\compiler\cpp\thrift.exe" --gen csharp -o %25SHORT_DIR%25 %25THRIFT_SHORT%25
+
+</PreBuildEvent>
+  </PropertyGroup>
+</Project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/thrift/blob/7203424e/lib/csharp/test/Multiplex/Server/Properties/AssemblyInfo.cs
----------------------------------------------------------------------
diff --git a/lib/csharp/test/Multiplex/Server/Properties/AssemblyInfo.cs b/lib/csharp/test/Multiplex/Server/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..9b9dd6f
--- /dev/null
+++ b/lib/csharp/test/Multiplex/Server/Properties/AssemblyInfo.cs
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("MultiplexServer")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("MultiplexServer")]
+[assembly: AssemblyCopyright("Copyright © 2013 The Apache Software Foundation")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components.  If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("F2F436C1-3D4F-411a-ADC3-B98848476A8E")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]

http://git-wip-us.apache.org/repos/asf/thrift/blob/7203424e/lib/csharp/test/Multiplex/maketest.sh
----------------------------------------------------------------------
diff --git a/lib/csharp/test/Multiplex/maketest.sh b/lib/csharp/test/Multiplex/maketest.sh
new file mode 100644
index 0000000..a2bcde4
--- /dev/null
+++ b/lib/csharp/test/Multiplex/maketest.sh
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+../../../../compiler/cpp/thrift --gen csharp  ../../../../contrib/async-test/aggr.thrift
+../../../../compiler/cpp/thrift --gen csharp  ../../../rb/benchmark/Benchmark.thrift
+gmcs /t:library /out:./ThriftImpl.dll /recurse:./gen-csharp/* /reference:../../Thrift.dll Multiplex.Test.Common.cs
+gmcs  /out:MultiplexClient.exe /reference:../../Thrift.dll /reference:ThriftImpl.dll Client/Multiplex.Test.Client.cs  
+gmcs  /out:MultiplexServer.exe /reference:../../Thrift.dll /reference:ThriftImpl.dll Server/Multiplex.Test.Server.cs  
+
+
+
+export MONO_PATH=../../
+
+timeout 120 ./MultiplexServer.exe & 
+sleep 3;
+./MultiplexClient.exe