You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@thrift.apache.org by jk...@apache.org on 2017/11/19 02:11:33 UTC

[1/3] thrift git commit: THRIFT-4329: multiplexed processor, client and server for c_glib Client: c_glib

Repository: thrift
Updated Branches:
  refs/heads/master 95d5fb3a1 -> 58402ff6a


http://git-wip-us.apache.org/repos/asf/thrift/blob/87ad2bca/lib/c_glib/test/testtransportsocket.c
----------------------------------------------------------------------
diff --git a/lib/c_glib/test/testtransportsocket.c b/lib/c_glib/test/testtransportsocket.c
index 8e96375..fedbad6 100755
--- a/lib/c_glib/test/testtransportsocket.c
+++ b/lib/c_glib/test/testtransportsocket.c
@@ -33,9 +33,9 @@ int
 my_socket(int domain, int type, int protocol)
 {
   if (socket_error == 0)
-  {
-    return socket (domain, type, protocol);
-  }
+    {
+      return socket (domain, type, protocol);
+    }
   return -1;
 }
 
@@ -44,9 +44,9 @@ ssize_t
 my_recv(int socket, void *buffer, size_t length, int flags)
 {
   if (recv_error == 0)
-  {
-    return recv (socket, buffer, length, flags);
-  }
+    {
+      return recv (socket, buffer, length, flags);
+    }
   return -1;
 }
 
@@ -55,9 +55,9 @@ ssize_t
 my_send(int socket, const void *buffer, size_t length, int flags)
 {
   if (send_error == 0)
-  {
-    return send (socket, buffer, length, flags);
-  }
+    {
+      return send (socket, buffer, length, flags);
+    }
   return -1;
 }
 
@@ -70,7 +70,7 @@ my_send(int socket, const void *buffer, size_t length, int flags)
 #undef send
 
 static void thrift_socket_server (const int port);
-
+static void thrift_socket_server_open (const int port, int times);
 /* test object creation and destruction */
 static void
 test_create_and_destroy(void)
@@ -93,82 +93,100 @@ test_open_and_close(void)
   ThriftSocket *tsocket = NULL;
   ThriftTransport *transport = NULL;
   GError *err = NULL;
+  int port = 51199;
+  pid_t pid;
+  int status;
 
-  /* open a connection and close it */
-  tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost",
-                          "port", 51188, NULL); 
-  transport = THRIFT_TRANSPORT (tsocket);
-  thrift_socket_open (transport, NULL);
-  g_assert (thrift_socket_is_open (transport) == TRUE);
-  thrift_socket_close (transport, NULL);
-  g_assert (thrift_socket_is_open (transport) == FALSE);
-
-  /* test close failure */
-  tsocket->sd = -1;
-  thrift_socket_close (transport, NULL);
-  g_object_unref (tsocket);
+  pid = fork ();
+  g_assert ( pid >= 0 );
 
-  /* try a hostname lookup failure */
-  tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost.broken",
-                          NULL);
-  transport = THRIFT_TRANSPORT (tsocket);
-  g_assert (thrift_socket_open (transport, &err) == FALSE);
-  g_object_unref (tsocket);
-  g_error_free (err);
-  err = NULL;
-
-  /* try an error call to socket() */
-  tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost", NULL);
-  transport = THRIFT_TRANSPORT (tsocket);
-  socket_error = 1;
-  g_assert (thrift_socket_open (transport, &err) == FALSE);
-  socket_error = 0;
-  g_object_unref (tsocket);
-  g_error_free (err);
+  if ( pid == 0 )
+    {
+      /* child listens */
+      thrift_socket_server_open (port, 1);
+      exit (0);
+    } else {
+	/* parent connects, wait a bit for the socket to be created */
+	sleep (1);
+
+	/* open a connection and close it */
+	tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost",
+				"port", port, NULL);
+	transport = THRIFT_TRANSPORT (tsocket);
+	thrift_socket_open (transport, NULL);
+	g_assert (thrift_socket_is_open (transport) == TRUE);
+	thrift_socket_close (transport, NULL);
+	g_assert (thrift_socket_is_open (transport) == FALSE);
+
+	/* test close failure */
+	tsocket->sd = -1;
+	thrift_socket_close (transport, NULL);
+	g_object_unref (tsocket);
+
+	/* try a hostname lookup failure */
+	tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost.broken",
+				NULL);
+	transport = THRIFT_TRANSPORT (tsocket);
+	g_assert (thrift_socket_open (transport, &err) == FALSE);
+	g_object_unref (tsocket);
+	g_error_free (err);
+	err = NULL;
+
+	/* try an error call to socket() */
+	tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost", NULL);
+	transport = THRIFT_TRANSPORT (tsocket);
+	socket_error = 1;
+	g_assert (thrift_socket_open (transport, &err) == FALSE);
+	socket_error = 0;
+	g_object_unref (tsocket);
+	g_error_free (err);
+	g_assert ( wait (&status) == pid );
+	g_assert ( status == 0 );
+    }
 }
 
 static void
 test_read_and_write(void)
 {
-  int status;
-  pid_t pid;
   ThriftSocket *tsocket = NULL;
   ThriftTransport *transport = NULL;
+  pid_t pid;
   int port = 51199;
+  int status;
   guchar buf[10] = TEST_DATA; /* a buffer */
 
   pid = fork ();
   g_assert ( pid >= 0 );
 
   if ( pid == 0 )
-  {
-    /* child listens */
-    thrift_socket_server (port);
-    exit (0);
-  } else {
-    /* parent connects, wait a bit for the socket to be created */
-    sleep (1);
-
-    tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost",
-                            "port", port, NULL);
-    transport = THRIFT_TRANSPORT (tsocket);
-    g_assert (thrift_socket_open (transport, NULL) == TRUE);
-    g_assert (thrift_socket_is_open (transport));
-    thrift_socket_write (transport, buf, 10, NULL);
-
-    /* write fail */
-    send_error = 1;
-    thrift_socket_write (transport, buf, 1, NULL);
-    send_error = 0;
-
-    thrift_socket_write_end (transport, NULL);
-    thrift_socket_flush (transport, NULL);
-    thrift_socket_close (transport, NULL);
-    g_object_unref (tsocket);
-
-    g_assert ( wait (&status) == pid );
-    g_assert ( status == 0 );
-  }
+    {
+      /* child listens */
+      thrift_socket_server (port);
+      exit (0);
+    } else {
+	/* parent connects, wait a bit for the socket to be created */
+	sleep (1);
+
+	tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost",
+				"port", port, NULL);
+	transport = THRIFT_TRANSPORT (tsocket);
+	g_assert (thrift_socket_open (transport, NULL) == TRUE);
+	g_assert (thrift_socket_is_open (transport));
+	thrift_socket_write (transport, buf, 10, NULL);
+
+	/* write fail */
+	send_error = 1;
+	thrift_socket_write (transport, buf, 1, NULL);
+	send_error = 0;
+
+	thrift_socket_write_end (transport, NULL);
+	thrift_socket_flush (transport, NULL);
+	thrift_socket_close (transport, NULL);
+	g_object_unref (tsocket);
+
+	g_assert ( wait (&status) == pid );
+	g_assert ( status == 0 );
+    }
 }
 
 /* test ThriftSocket's peek() implementation */
@@ -183,9 +201,9 @@ test_peek(void)
   GError *error = NULL;
 
   client_transport = g_object_new (THRIFT_TYPE_SOCKET,
-                                   "hostname", "localhost",
-                                   "port",     port,
-                                   NULL);
+				   "hostname", "localhost",
+				   "port",     port,
+				   NULL);
 
   /* thrift_transport_peek returns FALSE when the socket is closed */
   g_assert (thrift_transport_is_open (client_transport) == FALSE);
@@ -196,81 +214,105 @@ test_peek(void)
   g_assert (pid >= 0);
 
   if (pid == 0)
-  {
-    ThriftServerTransport *server_transport = NULL;
-
-    g_object_unref (client_transport);
-
-    /* child listens */
-    server_transport = g_object_new (THRIFT_TYPE_SERVER_SOCKET,
-                                     "port", port,
-                                     NULL);
-    g_assert (server_transport != NULL);
-
-    thrift_server_transport_listen (server_transport, &error);
-    g_assert (error == NULL);
-
-    client_transport = g_object_new
-      (THRIFT_TYPE_BUFFERED_TRANSPORT,
-       "transport",  thrift_server_transport_accept (server_transport, &error),
-       "r_buf_size", 0,
-       "w_buf_size", sizeof data,
-       NULL);
-    g_assert (error == NULL);
-    g_assert (client_transport != NULL);
-
-    /* write exactly one character to the client */
-    g_assert (thrift_transport_write (client_transport,
-                                      &data,
-                                      sizeof data,
-                                      &error) == TRUE);
-
-    thrift_transport_flush (client_transport, &error);
-    thrift_transport_write_end (client_transport, &error);
-    thrift_transport_close (client_transport, &error);
-
-    g_object_unref (client_transport);
-    g_object_unref (server_transport);
-
-    exit (0);
-  }
+    {
+      ThriftServerTransport *server_transport = NULL;
+
+      g_object_unref (client_transport);
+
+      /* child listens */
+      server_transport = g_object_new (THRIFT_TYPE_SERVER_SOCKET,
+				       "port", port,
+				       NULL);
+      g_assert (server_transport != NULL);
+
+      thrift_server_transport_listen (server_transport, &error);
+      g_assert (error == NULL);
+
+      client_transport = g_object_new
+	  (THRIFT_TYPE_BUFFERED_TRANSPORT,
+	   "transport",  thrift_server_transport_accept (server_transport, &error),
+	   "r_buf_size", 0,
+	   "w_buf_size", sizeof data,
+	   NULL);
+      g_assert (error == NULL);
+      g_assert (client_transport != NULL);
+
+      /* write exactly one character to the client */
+      g_assert (thrift_transport_write (client_transport,
+					&data,
+					sizeof data,
+					&error) == TRUE);
+
+      thrift_transport_flush (client_transport, &error);
+      thrift_transport_write_end (client_transport, &error);
+      thrift_transport_close (client_transport, &error);
+
+      g_object_unref (client_transport);
+      g_object_unref (server_transport);
+
+      exit (0);
+    }
   else {
-    /* parent connects, wait a bit for the socket to be created */
-    sleep (1);
+      /* parent connects, wait a bit for the socket to be created */
+      sleep (1);
 
-    /* connect to the child */
-    thrift_transport_open (client_transport, &error);
-    g_assert (error == NULL);
-    g_assert (thrift_transport_is_open (client_transport) == TRUE);
+      /* connect to the child */
+      thrift_transport_open (client_transport, &error);
+      g_assert (error == NULL);
+      g_assert (thrift_transport_is_open (client_transport) == TRUE);
 
-    /* thrift_transport_peek returns TRUE when the socket is open and there is
+      /* thrift_transport_peek returns TRUE when the socket is open and there is
        data available to be read */
-    g_assert (thrift_transport_peek (client_transport, &error) == TRUE);
-    g_assert (error == NULL);
+      g_assert (thrift_transport_peek (client_transport, &error) == TRUE);
+      g_assert (error == NULL);
 
-    /* read exactly one character from the server */
-    g_assert_cmpint (thrift_transport_read (client_transport,
-                                            &data,
-                                            sizeof data,
-                                            &error), ==, sizeof data);
+      /* read exactly one character from the server */
+      g_assert_cmpint (thrift_transport_read (client_transport,
+					      &data,
+					      sizeof data,
+					      &error), ==, sizeof data);
 
-    /* thrift_transport_peek returns FALSE when the socket is open but there is
+      /* thrift_transport_peek returns FALSE when the socket is open but there is
        no (more) data available to be read */
-    g_assert (thrift_transport_is_open (client_transport) == TRUE);
-    g_assert (thrift_transport_peek (client_transport, &error) == FALSE);
-    g_assert (error == NULL);
+      g_assert (thrift_transport_is_open (client_transport) == TRUE);
+      g_assert (thrift_transport_peek (client_transport, &error) == FALSE);
+      g_assert (error == NULL);
 
-    thrift_transport_read_end (client_transport, &error);
-    thrift_transport_close (client_transport, &error);
+      thrift_transport_read_end (client_transport, &error);
+      thrift_transport_close (client_transport, &error);
 
-    g_object_unref (client_transport);
+      g_object_unref (client_transport);
 
-    g_assert (wait (&status) == pid);
-    g_assert (status == 0);
+      g_assert (wait (&status) == pid);
+      g_assert (status == 0);
   }
 }
 
 static void
+thrift_socket_server_open (const int port, int times)
+{
+  int bytes = 0;
+  ThriftServerTransport *transport = NULL;
+  ThriftTransport *client = NULL;
+  guchar buf[10]; /* a buffer */
+  guchar match[10] = TEST_DATA;
+  int i;
+  ThriftServerSocket *tsocket = g_object_new (THRIFT_TYPE_SERVER_SOCKET,
+					      "port", port, NULL);
+
+  transport = THRIFT_SERVER_TRANSPORT (tsocket);
+  thrift_server_transport_listen (transport, NULL);
+  for(i=0;i<times;i++){
+      client = thrift_server_transport_accept (transport, NULL);
+      g_assert (client != NULL);
+      thrift_socket_close (client, NULL);
+      g_object_unref (client);
+  }
+  g_object_unref (tsocket);
+}
+
+
+static void
 thrift_socket_server (const int port)
 {
   int bytes = 0;
@@ -280,7 +322,7 @@ thrift_socket_server (const int port)
   guchar match[10] = TEST_DATA;
 
   ThriftServerSocket *tsocket = g_object_new (THRIFT_TYPE_SERVER_SOCKET,
-                                              "port", port, NULL);
+					      "port", port, NULL);
 
   transport = THRIFT_SERVER_TRANSPORT (tsocket);
   thrift_server_transport_listen (transport, NULL);

http://git-wip-us.apache.org/repos/asf/thrift/blob/87ad2bca/lib/c_glib/test/testtransportsslsocket.c
----------------------------------------------------------------------
diff --git a/lib/c_glib/test/testtransportsslsocket.c b/lib/c_glib/test/testtransportsslsocket.c
index f2f56f8..3c2644d 100644
--- a/lib/c_glib/test/testtransportsslsocket.c
+++ b/lib/c_glib/test/testtransportsslsocket.c
@@ -16,13 +16,14 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+#define _POSIX_C_SOURCE 200112L /* https://stackoverflow.com/questions/37541985/storage-size-of-addrinfo-isnt-known */
+
 
-#include <netdb.h>
 #include <sys/wait.h>
+#include <arpa/inet.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <netdb.h>
-#include <arpa/inet.h>
 
 #include <thrift/c_glib/transport/thrift_transport.h>
 #include <thrift/c_glib/transport/thrift_buffered_transport.h>
@@ -30,7 +31,7 @@
 #include <thrift/c_glib/transport/thrift_server_socket.h>
 #include <thrift/c_glib/transport/thrift_ssl_socket.h>
 
-//#define TEST_DATA { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j' }
+/* #define TEST_DATA { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j' } */
 #define TEST_DATA { "GET / HTTP/1.1\n\n" }
 
 
@@ -40,9 +41,9 @@ int
 my_socket(int domain, int type, int protocol)
 {
   if (socket_error == 0)
-  {
-    return socket (domain, type, protocol);
-  }
+    {
+      return socket (domain, type, protocol);
+    }
   return -1;
 }
 
@@ -51,9 +52,9 @@ ssize_t
 my_recv(int socket, void *buffer, size_t length, int flags)
 {
   if (recv_error == 0)
-  {
-    return recv (socket, buffer, length, flags);
-  }
+    {
+      return recv (socket, buffer, length, flags);
+    }
   return -1;
 }
 
@@ -62,9 +63,9 @@ ssize_t
 my_send(int socket, const void *buffer, size_t length, int flags)
 {
   if (send_error == 0)
-  {
-    return send (socket, buffer, length, flags);
-  }
+    {
+      return send (socket, buffer, length, flags);
+    }
   return -1;
 }
 
@@ -76,7 +77,7 @@ my_send(int socket, const void *buffer, size_t length, int flags)
 #undef recv
 #undef send
 
-static void thrift_ssl_socket_server (const int port);
+static void thrift_socket_server (const int port);
 
 /* test object creation and destruction */
 static void
@@ -111,18 +112,90 @@ test_ssl_create_and_set_properties(void)
 }
 
 static void
-test_ssl_open_and_close(void)
+test_ssl_open_and_close_non_ssl_server(void)
 {
   ThriftSSLSocket *tSSLSocket = NULL;
   ThriftTransport *transport = NULL;
   GError *error=NULL;
+  pid_t pid;
+  int non_ssl_port = 51198;
+  char errormsg[255];
+
+
+  pid = fork ();
+  g_assert ( pid >= 0 );
+
+  if ( pid == 0 )
+    {
+      /* child listens */
+      /* This is a non SSL server */
+      thrift_socket_server (non_ssl_port);
+      exit (0);
+    } else {
+	/* parent connects, wait a bit for the socket to be created */
+	sleep (1);
+
+	/* open a connection and close it */
+	tSSLSocket = thrift_ssl_socket_new_with_host(SSLTLS, "localhost", non_ssl_port, &error);
+
+	transport = THRIFT_TRANSPORT (tSSLSocket);
+	g_assert (thrift_ssl_socket_open (transport, &error) == FALSE);
+	g_assert_cmpstr(error->message, == ,"Error while connect/bind: 68 -> Connection reset by peer");
+	g_clear_error (&error);
+	g_assert (thrift_ssl_socket_is_open (transport) == FALSE);
+	thrift_ssl_socket_close (transport, NULL);
+	g_assert (thrift_ssl_socket_is_open (transport) == FALSE);
+
+	/* test close failure */
+	THRIFT_SOCKET(tSSLSocket)->sd = -1;
+	thrift_ssl_socket_close (transport, NULL);
+	g_object_unref (tSSLSocket);
+
+	/* try a hostname lookup failure */
+	tSSLSocket = thrift_ssl_socket_new_with_host(SSLTLS, "localhost.broken", non_ssl_port, &error);
+	transport = THRIFT_TRANSPORT (tSSLSocket);
+	g_assert (thrift_ssl_socket_open (transport, &error) == FALSE);
+	snprintf(errormsg, 255, "host lookup failed for localhost.broken:%d - Unknown host", non_ssl_port);
+	g_assert_cmpstr(error->message, ==, errormsg);
+	g_clear_error (&error);
+	g_object_unref (tSSLSocket);
+	error = NULL;
+
+		/* try an error call to socket() */
+	/*
+		tSSLSocket = thrift_ssl_socket_new_with_host(SSLTLS, "localhost", port, &error);
+		transport = THRIFT_TRANSPORT (tSSLSocket);
+		socket_error = 1;
+		assert (thrift_ssl_socket_open (transport, &error) == FALSE);
+		socket_error = 0;
+		g_object_unref (tSSLSocket);
+		g_error_free (error);
+	 */
+    }
+}
+
+static void
+test_ssl_write_invalid_socket(void)
+{
+  ThriftSSLSocket *tSSLSocket = NULL;
+  ThriftTransport *transport = NULL;
+  GError *error=NULL;
+  char buffer[] = "this must not break";
 
   /* open a connection and close it */
-  tSSLSocket = thrift_ssl_socket_new_with_host(SSLTLS, "localhost", 51188, &error);
+  tSSLSocket = thrift_ssl_socket_new_with_host(SSLTLS, "localhost", 51188+1, &error);
 
   transport = THRIFT_TRANSPORT (tSSLSocket);
-  thrift_ssl_socket_open (transport, NULL);
-  g_assert (thrift_ssl_socket_is_open (transport) == TRUE);
+  g_assert (thrift_ssl_socket_open (transport, NULL) == FALSE);
+  g_assert (thrift_ssl_socket_is_open (transport) == FALSE);
+
+  /* FIXME This must be tested but since the assertion inside thrift_ssl_socket_write breaks the test unit
+   it's disabled. They idea is to disable trap/coredump during this test
+  g_assert (thrift_ssl_socket_write(transport, buffer, sizeof(buffer), &error) == FALSE);
+  g_message ("write_failed_with_error: %s",
+	     error != NULL ? error->message : "No");
+  g_clear_error (&error);
+  */
   thrift_ssl_socket_close (transport, NULL);
   g_assert (thrift_ssl_socket_is_open (transport) == FALSE);
 
@@ -130,23 +203,6 @@ test_ssl_open_and_close(void)
   THRIFT_SOCKET(tSSLSocket)->sd = -1;
   thrift_ssl_socket_close (transport, NULL);
   g_object_unref (tSSLSocket);
-
-  /* try a hostname lookup failure */
-  tSSLSocket = thrift_ssl_socket_new_with_host(SSLTLS, "localhost.broken", 51188, &error);
-  transport = THRIFT_TRANSPORT (tSSLSocket);
-  g_assert (thrift_ssl_socket_open (transport, &error) == FALSE);
-  g_object_unref (tSSLSocket);
-  g_error_free (error);
-  error = NULL;
-
-  /* try an error call to socket() */
-  tSSLSocket = thrift_ssl_socket_new_with_host(SSLTLS, "localhost", 51188, &error);
-  transport = THRIFT_TRANSPORT (tSSLSocket);
-  socket_error = 1;
-  g_assert (thrift_ssl_socket_open (transport, &error) == FALSE);
-  socket_error = 0;
-  g_object_unref (tSSLSocket);
-  g_error_free (error);
 }
 
 
@@ -160,22 +216,22 @@ unsigned char * get_cn_name(X509_NAME* const name)
   unsigned char *utf8 = NULL;
 
   do
-  {
-    if(!name) break; /* failed */
+    {
+      if(!name) break; /* failed */
 
-    idx = X509_NAME_get_index_by_NID(name, NID_commonName, -1);
-    if(!(idx > -1))  break; /* failed */
+      idx = X509_NAME_get_index_by_NID(name, NID_commonName, -1);
+      if(!(idx > -1))  break; /* failed */
 
-    X509_NAME_ENTRY* entry = X509_NAME_get_entry(name, idx);
-    if(!entry) break; /* failed */
+      X509_NAME_ENTRY* entry = X509_NAME_get_entry(name, idx);
+      if(!entry) break; /* failed */
 
-    ASN1_STRING* data = X509_NAME_ENTRY_get_data(entry);
-    if(!data) break; /* failed */
+      ASN1_STRING* data = X509_NAME_ENTRY_get_data(entry);
+      if(!data) break; /* failed */
 
-    int length = ASN1_STRING_to_UTF8(&utf8, data);
-    if(!utf8 || !(length > 0))  break; /* failed */
+      int length = ASN1_STRING_to_UTF8(&utf8, data);
+      if(!utf8 || !(length > 0))  break; /* failed */
 
-  } while (0);
+    } while (0);
   return utf8;
 }
 
@@ -197,34 +253,34 @@ int verify_ip(char * hostname, struct sockaddr_storage *addr)
   int retval = 0;
 
 
-  memset(&hints, 0, sizeof hints);
-  hints.ai_family = AF_UNSPEC; // use AF_INET6 to force IPv6
+  memset(&hints, 0, sizeof (struct addrinfo));
+  hints.ai_family = AF_UNSPEC; /* use AF_INET6 to force IPv6 */
   hints.ai_socktype = SOCK_STREAM;
 
 
   if ( (res = getaddrinfo(hostname, NULL, &hints, &addr_info) ) != 0)
-  {
-    // get the host info
-    g_error("Cannot get the host address");
-    return retval;
-  }
-  // loop through all the results and connect to the first we can
-  char dnshost[INET6_ADDRSTRLEN]; // bigger addr supported IPV6
+    {
+      /* get the host info */
+      g_error("Cannot get the host address");
+      return retval;
+    }
+  /* loop through all the results and connect to the first we can */
+  char dnshost[INET6_ADDRSTRLEN]; /* bigger addr supported IPV6 */
   char socket_ip[INET6_ADDRSTRLEN];
   if(inet_ntop(addr->ss_family, get_in_addr(addr), socket_ip, INET6_ADDRSTRLEN)==socket_ip){
-    g_debug("We are connected to host %s checking against certificate...", socket_ip);
-    int sizeip = socket_ip!=NULL ? strlen(socket_ip) : 0;
-    for(p = addr_info; p != NULL; p = p->ai_next) {
-      if(inet_ntop(p->ai_family, get_in_addr((struct sockaddr *)p->ai_addr), dnshost, INET6_ADDRSTRLEN)==dnshost){
-        if(dnshost!=NULL){
-          g_info("DNS address [%i -> %s]", p->ai_addr, dnshost);
-          if(!strncmp(dnshost, socket_ip, sizeip)){
-            retval=1;
-            break; // if we get here, we must have connected successfully
-          }
-        }
+      g_debug("We are connected to host %s checking against certificate...", socket_ip);
+      int sizeip = socket_ip!=NULL ? strlen(socket_ip) : 0;
+      for(p = addr_info; p != NULL; p = p->ai_next) {
+	  if(inet_ntop(p->ai_family, get_in_addr((struct sockaddr *)p->ai_addr), dnshost, INET6_ADDRSTRLEN)==dnshost){
+	      if(dnshost!=NULL){
+		  g_info("DNS address [%i -> %s]", p->ai_addr, dnshost);
+		  if(!strncmp(dnshost, socket_ip, sizeip)){
+		      retval=1;
+		      break; /* if we get here, we must have connected successfully */
+		  }
+	      }
+	  }
       }
-    }
   }
 
   if(addr_info)
@@ -236,25 +292,25 @@ int verify_ip(char * hostname, struct sockaddr_storage *addr)
 static void
 read_from_file(char *buffer, long size, const char *file_name)
 {
-     char ch;
-     long index=0;
-     FILE *fp;
+  char ch;
+  long index=0;
+  FILE *fp;
 
-     fp = fopen(file_name,"r"); // read mode
+  fp = fopen(file_name,"r"); /* read mode */
 
-     if( fp == NULL )
-     {
-        perror("Error while opening the file.\n");
-        exit(EXIT_FAILURE);
-     }
+  if( fp == NULL )
+    {
+      perror("Error while opening the file.\n");
+      exit(EXIT_FAILURE);
+    }
 
-     printf("The contents of %s file are :\n", file_name);
+  printf("The contents of %s file are :\n", file_name);
 
-     while(index<size && ( ch = fgetc(fp) ) != EOF ){
-       buffer[index++] = ch;
-     }
+  while(index<size && ( ch = fgetc(fp) ) != EOF ){
+      buffer[index++] = ch;
+  }
 
-     fclose(fp);
+  fclose(fp);
 }
 
 #define ISSUER_CN_PINNING "The Apache Software Foundation"
@@ -269,25 +325,27 @@ gboolean verify_certificate_sn(X509 *cert, const unsigned char *serial_number)
 
   BIGNUM *bn = ASN1_INTEGER_to_BN(serial, NULL);
   if (!bn) {
-    fprintf(stderr, "unable to convert ASN1INTEGER to BN\n");
-    return EXIT_FAILURE;
+      fprintf(stderr, "unable to convert ASN1INTEGER to BN\n");
+      return EXIT_FAILURE;
   }
   char *tmp = BN_bn2dec(bn);
   if (!tmp) {
-    g_warning(stderr, "unable to convert BN to decimal string.\n");
-    BN_free(bn);
-    return EXIT_FAILURE;
+      g_warning(stderr, "unable to convert BN to decimal string.\n");
+      BN_free(bn);
+      return EXIT_FAILURE;
   }
-//  if (strlen(tmp) >= len) {
-//    g_warn(stderr, "buffer length shorter than serial number\n");
-//    BN_free(bn);
-//    OPENSSL_free(tmp);
-//    return EXIT_FAILURE;
-//  }
+  /*
+    if (strlen(tmp) >= len) {
+      g_warn(stderr, "buffer length shorter than serial number\n");
+      BN_free(bn);
+      OPENSSL_free(tmp);
+      return EXIT_FAILURE;
+    }
+  */
   if(!strncmp(serial_number, tmp, strlen(serial_number))){
-    retval=TRUE;
+      retval=TRUE;
   }else{
-    g_warning("Serial number is not valid");
+      g_warning("Serial number is not valid");
   }
 
   BN_free(bn);
@@ -306,52 +364,52 @@ gboolean my_access_manager(ThriftTransport * transport, X509 *cert, struct socka
   /* Issuer is the authority we trust that warrants nothing useful */
   const unsigned char * issuer = get_cn_name(iname);
   if(issuer){
-    gboolean valid = TRUE;
-    g_info("Issuer (cn) %s", issuer);
+      gboolean valid = TRUE;
+      g_info("Issuer (cn) %s", issuer);
 
-    // Issuer pinning
-    if(strncmp(ISSUER_CN_PINNING, issuer, strlen(ISSUER_CN_PINNING))){
-      g_warning("The Issuer of the certificate is not valid");
-      valid=FALSE;
-    }
-    OPENSSL_free(issuer);
-    if(!valid)
-      return valid;
+      /* Issuer pinning */
+      if(strncmp(ISSUER_CN_PINNING, issuer, strlen(ISSUER_CN_PINNING))){
+	  g_warning("The Issuer of the certificate is not valid");
+	  valid=FALSE;
+      }
+      OPENSSL_free(issuer);
+      if(!valid)
+	return valid;
   }
 
 
   /* Subject is who the certificate is issued to by the authority  */
   const unsigned char * subject = get_cn_name(sname);
   if(subject){
-    g_info("Subject (cn) %s", subject);
-    gboolean valid = TRUE;
+      g_info("Subject (cn) %s", subject);
+      gboolean valid = TRUE;
 
-    // Subject pinning
-    if(strncmp(SUBJECT_CN_PINNING, subject, strlen(SUBJECT_CN_PINNING))){
-      g_warning("The subject of the certificate is not valid");
-      valid=FALSE;
-    }
+      /* Subject pinning */
+      if(strncmp(SUBJECT_CN_PINNING, subject, strlen(SUBJECT_CN_PINNING))){
+	  g_warning("The subject of the certificate is not valid");
+	  valid=FALSE;
+      }
 
-    if(!valid)
-      return valid;
+      if(!valid)
+	return valid;
 
-    // Host pinning
-    if(verify_ip(subject, addr)){
-      g_info("Verified subject");
-    }else{
-      g_info("Cannot verify subject");
-      valid=FALSE;
-    }
-    OPENSSL_free(subject);
+      /* Host pinning       */
+      if(verify_ip(subject, addr)){
+	  g_info("Verified subject");
+      }else{
+	  g_info("Cannot verify subject");
+	  valid=FALSE;
+      }
+      OPENSSL_free(subject);
 
-    if(!valid)
-      return valid;
+      if(!valid)
+	return valid;
   }
 
   if(!verify_certificate_sn(cert, CERT_SERIAL_NUMBER)){
-    return FALSE;
+      return FALSE;
   }else{
-    g_info("Verified serial number");
+      g_info("Verified serial number");
   }
 
   return TRUE;
@@ -369,32 +427,33 @@ test_ssl_authorization_manager(void)
   pid_t pid;
   ThriftSSLSocket *tSSLsocket = NULL;
   ThriftTransport *transport = NULL;
-  //  int port = 51199;
+  /*  int port = 51199; */
   int port = 443;
   GError *error=NULL;
 
   guchar buf[17] = TEST_DATA; /* a buffer */
 
-  //  pid = fork ();
-  //  g_assert ( pid >= 0 );
-  //
-  //  if ( pid == 0 )
-  //  {
-  //    /* child listens */
-  //    thrift_ssl_socket_server (port);
-  //    exit (0);
-  //  } else {
+/*
+  pid = fork ();
+    g_assert ( pid >= 0 );
+
+    if ( pid == 0 )
+    {
+      thrift_ssl_socket_server (port);
+      exit (0);
+    } else {
+	*/
   /* parent connects, wait a bit for the socket to be created */
   sleep (1);
 
-  // Test against level2 owncloud certificate
+  /* Test against level2 owncloud certificate */
   tSSLsocket = thrift_ssl_socket_new_with_host(SSLTLS, "localhost", port, &error);
-  thrift_ssl_socket_set_manager(tSSLsocket, my_access_manager);           // Install pinning manager
-  //thrift_ssl_load_cert_from_file(tSSLsocket, "./owncloud.level2crm.pem");
+  thrift_ssl_socket_set_manager(tSSLsocket, my_access_manager);           /* Install pinning manager */
+  /* thrift_ssl_load_cert_from_file(tSSLsocket, "./owncloud.level2crm.pem"); */
   unsigned char cert_buffer[65534];
   read_from_file(cert_buffer, 65534, "../../keys/client.pem");
   if(!thrift_ssl_load_cert_from_buffer(tSSLsocket, cert_buffer)){
-    g_warning("Certificates cannot be loaded!");
+      g_warning("Certificates cannot be loaded!");
   }
 
   transport = THRIFT_TRANSPORT (tSSLsocket);
@@ -405,122 +464,24 @@ test_ssl_authorization_manager(void)
 
   /* write fail */
   send_error = 1;
-  //    thrift_ssl_socket_write (transport, buf, 1, NULL);
-  //   send_error = 0;
-
-  //    thrift_ssl_socket_write_end (transport, NULL);
-  //    thrift_ssl_socket_flush (transport, NULL);
+  /*
+      thrift_ssl_socket_write (transport, buf, 1, NULL);
+     send_error = 0;
+      thrift_ssl_socket_write_end (transport, NULL);
+      thrift_ssl_socket_flush (transport, NULL);
+      */
   thrift_ssl_socket_close (transport, NULL);
   g_object_unref (tSSLsocket);
 
-  //    g_assert ( wait (&status) == pid );
+  /*    g_assert ( wait (&status) == pid ); */
   g_assert ( status == 0 );
-  //  }
+  /*  } */
 }
 #endif
 
 
-/* test ThriftSocket's peek() implementation */
-//static void
-//test_ssl_peek(void)
-//{
-//  gint status;
-//  pid_t pid;
-//  guint port = 51199;
-//  gchar data = 'A';
-//  ThriftTransport *client_transport;
-//  GError *error = NULL;
-//
-//  client_transport = g_object_new (THRIFT_TYPE_SSL_SOCKET,
-//                                   "hostname", "localhost",
-//                                   "port",     port,
-//                                   NULL);
-//
-//  /* thrift_transport_peek returns FALSE when the socket is closed */
-//  g_assert (thrift_transport_is_open (client_transport) == FALSE);
-//  g_assert (thrift_transport_peek (client_transport, &error) == FALSE);
-//  g_assert (error == NULL);
-//
-//  pid = fork ();
-//  g_assert (pid >= 0);
-//
-//  if (pid == 0)
-//  {
-//    ThriftServerTransport *server_transport = NULL;
-//
-//    g_object_unref (client_transport);
-//
-//    /* child listens */
-//    server_transport = g_object_new (THRIFT_TYPE_SERVER_SOCKET,
-//                                     "port", port,
-//                                     NULL);
-//    g_assert (server_transport != NULL);
-//
-//    thrift_server_transport_listen (server_transport, &error);
-//    g_assert (error == NULL);
-//
-//    client_transport = g_object_new
-//      (THRIFT_TYPE_BUFFERED_TRANSPORT,
-//       "transport",  thrift_server_transport_accept (server_transport, &error),
-//       "r_buf_size", 0,
-//       "w_buf_size", sizeof data,
-//       NULL);
-//    g_assert (error == NULL);
-//    g_assert (client_transport != NULL);
-//
-//    /* write exactly one character to the client */
-//    g_assert (thrift_transport_write (client_transport,
-//                                      &data,
-//                                      sizeof data,
-//                                      &error) == TRUE);
-//
-//    thrift_transport_flush (client_transport, &error);
-//    thrift_transport_write_end (client_transport, &error);
-//    thrift_transport_close (client_transport, &error);
-//
-//    g_object_unref (client_transport);
-//    g_object_unref (server_transport);
-//
-//    exit (0);
-//  }
-//  else {
-//    /* parent connects, wait a bit for the socket to be created */
-//    sleep (1);
-//
-//    /* connect to the child */
-//    thrift_transport_open (client_transport, &error);
-//    g_assert (error == NULL);
-//    g_assert (thrift_transport_is_open (client_transport) == TRUE);
-//
-//    /* thrift_transport_peek returns TRUE when the socket is open and there is
-//       data available to be read */
-//    g_assert (thrift_transport_peek (client_transport, &error) == TRUE);
-//    g_assert (error == NULL);
-//
-//    /* read exactly one character from the server */
-//    g_assert_cmpint (thrift_transport_read (client_transport,
-//                                            &data,
-//                                            sizeof data,
-//                                            &error), ==, sizeof data);
-//
-//    /* thrift_transport_peek returns FALSE when the socket is open but there is
-//       no (more) data available to be read */
-//    g_assert (thrift_transport_is_open (client_transport) == TRUE);
-//    g_assert (thrift_transport_peek (client_transport, &error) == FALSE);
-//    g_assert (error == NULL);
-//
-//    thrift_transport_read_end (client_transport, &error);
-//    thrift_transport_close (client_transport, &error);
-//
-//    g_object_unref (client_transport);
-//
-//    g_assert (wait (&status) == pid);
-//    g_assert (status == 0);
-//  }
-//}
-
 static void
-thrift_ssl_socket_server (const int port)
+thrift_socket_server (const int port)
 {
   int bytes = 0;
   ThriftServerTransport *transport = NULL;
@@ -529,7 +490,7 @@ thrift_ssl_socket_server (const int port)
   guchar match[10] = TEST_DATA;
 
   ThriftServerSocket *tsocket = g_object_new (THRIFT_TYPE_SERVER_SOCKET,
-      "port", port, NULL);
+					      "port", port, NULL);
 
   transport = THRIFT_SERVER_TRANSPORT (tsocket);
   thrift_server_transport_listen (transport, NULL);
@@ -566,10 +527,11 @@ main(int argc, char *argv[])
 
   g_test_add_func ("/testtransportsslsocket/CreateAndDestroy", test_ssl_create_and_destroy);
   g_test_add_func ("/testtransportsslsocket/CreateAndSetProperties", test_ssl_create_and_set_properties);
-  g_test_add_func ("/testtransportsslsocket/OpenAndClose", test_ssl_open_and_close);
-  // This test is disabled because server is not ready
-  // g_test_add_func ("/testtransportsslsocket/AuthorizationManagerPinning", test_ssl_authorization_manager);
-  //  g_test_add_func ("/testtransportsslsocket/Peek", test_ssl_peek);
+  g_test_add_func ("/testtransportsslsocket/OpenAndCloseNonSSLServer", test_ssl_open_and_close_non_ssl_server);
+  g_test_add_func ("/testtransportsslsocket/OpenAndWriteInvalidSocket", test_ssl_write_invalid_socket);
+
+
+
 
   retval = g_test_run ();
 

http://git-wip-us.apache.org/repos/asf/thrift/blob/87ad2bca/test/c_glib/Makefile.am
----------------------------------------------------------------------
diff --git a/test/c_glib/Makefile.am b/test/c_glib/Makefile.am
index 0c478f9..4a03d29 100755
--- a/test/c_glib/Makefile.am
+++ b/test/c_glib/Makefile.am
@@ -45,6 +45,8 @@ test_client_LDADD = \
 test_server_SOURCES = \
 	src/thrift_test_handler.c \
 	src/thrift_test_handler.h \
+	src/thrift_second_service_handler.c \
+	src/thrift_second_service_handler.h \
 	src/test_server.c
 
 test_server_LDADD = \

http://git-wip-us.apache.org/repos/asf/thrift/blob/87ad2bca/test/c_glib/src/test_client.c
----------------------------------------------------------------------
diff --git a/test/c_glib/src/test_client.c b/test/c_glib/src/test_client.c
index deff4e1..ef24ab7 100644
--- a/test/c_glib/src/test_client.c
+++ b/test/c_glib/src/test_client.c
@@ -412,7 +412,7 @@ main (int argc, char **argv)
                                                         "2nd",
                                                         &error)) {
           printf (" = \"%s\"\n", string);
-          if (strncmp (string, "testString(\"2nd\")", 18) != 0) {
+          if (strcmp (string, "testString(\"2nd\")") != 0) {
             ++fail_count;
           }
 

http://git-wip-us.apache.org/repos/asf/thrift/blob/87ad2bca/test/c_glib/src/test_server.c
----------------------------------------------------------------------
diff --git a/test/c_glib/src/test_server.c b/test/c_glib/src/test_server.c
index 7f41d3f..2d716ec 100644
--- a/test/c_glib/src/test_server.c
+++ b/test/c_glib/src/test_server.c
@@ -23,6 +23,7 @@
 #include <string.h>
 
 #include <thrift/c_glib/thrift.h>
+#include <thrift/c_glib/processor/thrift_multiplexed_processor.h>
 #include <thrift/c_glib/protocol/thrift_binary_protocol_factory.h>
 #include <thrift/c_glib/protocol/thrift_compact_protocol_factory.h>
 #include <thrift/c_glib/server/thrift_server.h>
@@ -37,8 +38,10 @@
 #include <thrift/c_glib/transport/thrift_transport_factory.h>
 
 #include "../gen-c_glib/t_test_thrift_test.h"
+#include "../gen-c_glib/t_test_second_service.h"
 
 #include "thrift_test_handler.h"
+#include "thrift_second_service_handler.h"
 
 /* Our server object, declared globally so it is accessible within the SIGINT
    signal handler */
@@ -96,7 +99,10 @@ main (int argc, char **argv)
   GType  protocol_factory_type  = THRIFT_TYPE_BINARY_PROTOCOL_FACTORY;
 
   TTestThriftTestHandler *handler;
+  TTestThriftTestHandler *handler_second_service = NULL;
   ThriftProcessor        *processor;
+  ThriftProcessor        *processor_test = NULL;
+  ThriftProcessor        *processor_second_service = NULL;
   ThriftServerTransport  *server_transport;
   ThriftTransportFactory *transport_factory;
   ThriftProtocolFactory  *protocol_factory;
@@ -138,6 +144,13 @@ main (int argc, char **argv)
       protocol_factory_type = THRIFT_TYPE_COMPACT_PROTOCOL_FACTORY;
       protocol_name = "compact";
     }
+    else if (strncmp (protocol_option, "multi", 6) == 0) {
+	protocol_name = "binary:multi";
+    }
+    else if (strncmp (protocol_option, "multic", 7) == 0) {
+	protocol_factory_type = THRIFT_TYPE_COMPACT_PROTOCOL_FACTORY;
+	protocol_name = "compact:multic";
+    }
     else if (strncmp (protocol_option, "binary", 7) != 0) {
       fprintf (stderr, "Unknown protocol type %s\n", protocol_option);
       options_valid = FALSE;
@@ -161,16 +174,57 @@ main (int argc, char **argv)
   /* Establish all our connection objects */
   handler           = g_object_new (TYPE_THRIFT_TEST_HANDLER,
                                     NULL);
-  processor         = g_object_new (T_TEST_TYPE_THRIFT_TEST_PROCESSOR,
-                                    "handler", handler,
-                                    NULL);
+
+
+
+  if(strstr(protocol_name, ":multi")){
+      /* When a multiplexed processor is involved the handler is not
+         registered as usual. We create the processor and the real
+         processor is registered. Multiple processors can be registered
+         at once. This is why we don't have a constructor property */
+      processor = g_object_new (THRIFT_TYPE_MULTIPLEXED_PROCESSOR,
+					 NULL);
+
+      handler_second_service = g_object_new (TYPE_SECOND_SERVICE_HANDLER,
+     	                                    NULL);
+
+      processor_test = g_object_new (T_TEST_TYPE_THRIFT_TEST_PROCESSOR,
+				    "handler", handler,
+				    NULL);
+      processor_second_service =   g_object_new (T_TEST_TYPE_SECOND_SERVICE_PROCESSOR,
+				    "handler", handler_second_service,
+				    NULL);
+
+      /* We register a test processor with Multiplexed name ThriftTest */
+      if(!thrift_multiplexed_processor_register_processor(processor,
+						      "ThriftTest", processor_test,
+						      &error)){
+	    g_message ("thrift_server_serve: %s",
+	               error != NULL ? error->message : "(null)");
+	    g_clear_error (&error);
+      }
+      /* We register a second test processor with Multiplexed name SecondService
+       * we are responsible of freeing the processor when it's not used anymore */
+      if(!thrift_multiplexed_processor_register_processor(processor,
+						      "SecondService", processor_second_service,
+						      &error)){
+	    g_message ("thrift_server_serve: %s",
+	               error != NULL ? error->message : "(null)");
+	    g_clear_error (&error);
+      }
+
+  }else{
+      processor = g_object_new (T_TEST_TYPE_THRIFT_TEST_PROCESSOR,
+                                        "handler", handler,
+                                        NULL);
+  }
   server_transport  = g_object_new (THRIFT_TYPE_SERVER_SOCKET,
                                     "port", port,
                                     NULL);
   transport_factory = g_object_new (transport_factory_type,
                                     NULL);
 
-  if (strncmp (protocol_name, "compact", 8) == 0) {
+  if (strstr (protocol_name, "compact") != NULL) {
     protocol_factory  = g_object_new (protocol_factory_type,
                                       "string_limit", string_limit,
                                       "container_limit", container_limit,
@@ -222,6 +276,15 @@ main (int argc, char **argv)
   g_object_unref (server_transport);
   g_object_unref (processor);
   g_object_unref (handler);
+  if(handler_second_service){
+      g_object_unref (handler_second_service);
+  }
+  if(processor_test){
+      g_object_unref (processor_test);
+  }
+  if(processor_second_service){
+      g_object_unref (processor_second_service);
+  }
 
   return 0;
 }

http://git-wip-us.apache.org/repos/asf/thrift/blob/87ad2bca/test/c_glib/src/thrift_second_service_handler.c
----------------------------------------------------------------------
diff --git a/test/c_glib/src/thrift_second_service_handler.c b/test/c_glib/src/thrift_second_service_handler.c
new file mode 100644
index 0000000..c464372
--- /dev/null
+++ b/test/c_glib/src/thrift_second_service_handler.c
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+
+#include <inttypes.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <thrift/c_glib/thrift.h>
+#include <thrift/c_glib/thrift_application_exception.h>
+
+#include "thrift_second_service_handler.h"
+
+/* A handler that implements the TTestSecondServiceIf interface */
+
+G_DEFINE_TYPE (SecondServiceHandler,
+               second_service_handler,
+	       T_TEST_TYPE_SECOND_SERVICE_HANDLER);
+
+
+gboolean
+second_service_handler_secondtest_string (TTestSecondServiceIf  *iface,
+                                 gchar             **_return,
+                                 const gchar        *thing,
+                                 GError            **error)
+{
+  THRIFT_UNUSED_VAR (iface);
+  THRIFT_UNUSED_VAR (error);
+  gchar buffer[256];
+
+  printf ("testSecondServiceMultiplexSecondTestString(\"%s\")\n", thing);
+  snprintf(buffer, 255, "testString(\"%s\")", thing);
+  *_return = g_strdup (buffer);
+
+  return TRUE;
+}
+
+gboolean
+second_service_handler_blah_blah (TTestSecondServiceIf *iface, GError **error)
+{
+  THRIFT_UNUSED_VAR (iface);
+  THRIFT_UNUSED_VAR (error);
+
+  printf ("blahBlah()\n");
+
+  return TRUE;
+}
+
+static void
+second_service_handler_init (SecondServiceHandler *self)
+{
+  THRIFT_UNUSED_VAR (self);
+}
+
+static void
+second_service_handler_class_init (SecondServiceHandlerClass *klass)
+{
+  TTestSecondServiceHandlerClass *base_class =
+      T_TEST_SECOND_SERVICE_HANDLER_CLASS (klass);
+
+
+  base_class->secondtest_string =
+      second_service_handler_secondtest_string;
+  base_class->blah_blah =
+      second_service_handler_blah_blah;
+
+}

http://git-wip-us.apache.org/repos/asf/thrift/blob/87ad2bca/test/c_glib/src/thrift_second_service_handler.h
----------------------------------------------------------------------
diff --git a/test/c_glib/src/thrift_second_service_handler.h b/test/c_glib/src/thrift_second_service_handler.h
new file mode 100644
index 0000000..bbe048c
--- /dev/null
+++ b/test/c_glib/src/thrift_second_service_handler.h
@@ -0,0 +1,73 @@
+/*
+ * 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.
+ */
+
+#ifndef _SECOND_SERVICE_HANDLER_H
+#define _SECOND_SERVICE_HANDLER_H
+
+#include <glib-object.h>
+#include <stdio.h>
+
+#include "../gen-c_glib/t_test_second_service.h"
+
+G_BEGIN_DECLS
+
+/* A handler that implements the TTestSecondServiceIf interface */
+
+#define TYPE_SECOND_SERVICE_HANDLER (second_service_handler_get_type ())
+
+#define SECOND_SERVICE_HANDLER(obj)                                \
+  (G_TYPE_CHECK_INSTANCE_CAST ((obj),                           \
+                               TYPE_SECOND_SERVICE_HANDLER,        \
+                               SecondServiceHandler))
+#define IS_SECOND_SERVICE_HANDLER(obj)                             \
+  (G_TYPE_CHECK_INSTANCE_TYPE ((obj),                           \
+                               TYPE_SECOND_SERVICE_HANDLER))
+#define SECOND_SERVICE_HANDLER_CLASS(c)                    \
+  (G_TYPE_CHECK_CLASS_CAST ((c),                        \
+                            TYPE_SECOND_SERVICE_HANDLER,   \
+                            SecondServiceHandlerClass))
+#define IS_SECOND_SERVICE_HANDLER_CLASS(c)                 \
+  (G_TYPE_CHECK_CLASS_TYPE ((c),                        \
+                            TYPE_SECOND_SERVICE_HANDLER))
+#define SECOND_SERVICE_HANDLER_GET_CLASS(obj)              \
+  (G_TYPE_INSTANCE_GET_CLASS ((obj),                    \
+                              TYPE_SECOND_SERVICE_HANDLER, \
+                              SecondServiceHandlerClass))
+
+typedef struct _SecondServiceHandler SecondServiceHandler;
+typedef struct _SecondServiceHandlerClass SecondServiceHandlerClass;
+
+struct _SecondServiceHandler {
+  TTestSecondServiceHandler parent;
+};
+
+struct _SecondServiceHandlerClass {
+  TTestSecondServiceHandlerClass parent;
+
+};
+
+/* Used by SECOND_SERVICE_HANDLER_GET_TYPE */
+GType second_service_handler_get_type (void);
+
+gboolean second_service_handler_blah_blah (TTestSecondServiceIf *iface, GError **error);
+gboolean second_service_handler_secondtest_string          (TTestSecondServiceIf *iface, gchar ** _return, const gchar * thing, GError **error);
+
+G_END_DECLS
+
+#endif /* _SECOND_SERVICE_HANDLER_H */

http://git-wip-us.apache.org/repos/asf/thrift/blob/87ad2bca/test/features/tests.json
----------------------------------------------------------------------
diff --git a/test/features/tests.json b/test/features/tests.json
index 3ab3b68..41e07d7 100644
--- a/test/features/tests.json
+++ b/test/features/tests.json
@@ -66,7 +66,6 @@
       "--string-limit=50"
     ],
     "protocols": [
-      "binary",
       "compact"
     ],
     "transports": ["buffered"],
@@ -84,7 +83,6 @@
       "--container-limit=50"
     ],
     "protocols": [
-      "binary",
       "compact"
     ],
     "transports": ["buffered"],

http://git-wip-us.apache.org/repos/asf/thrift/blob/87ad2bca/test/tests.json
----------------------------------------------------------------------
diff --git a/test/tests.json b/test/tests.json
index e62af24..c1c3155 100644
--- a/test/tests.json
+++ b/test/tests.json
@@ -8,6 +8,12 @@
       "command": [
         "test_server",
         "--lt-debug"
+      ],
+      "protocols": [
+        "binary:multi",
+        "compact:multic",
+        "multi",
+        "multic"
       ]
     },
     "client": {


[3/3] thrift git commit: THRIFT-2013: add multiplex server and client test support to cpp language add multiplex client test support to csharp and java languages fix a bug in the server-side header protocol factory fix a bug in the cpp SSL server socket

Posted by jk...@apache.org.
THRIFT-2013: add multiplex server and client test support to cpp language
add multiplex client test support to csharp and java languages
fix a bug in the server-side header protocol factory
fix a bug in the cpp SSL server socket implementation
remove unnecessary sleep in cpp server testOneway

This closes #1414


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

Branch: refs/heads/master
Commit: 58402ff6a71f00f9d61a9676bdabd3e5bbe9ea3f
Parents: 87ad2bc
Author: James E. King, III <jk...@apache.org>
Authored: Fri Nov 17 14:41:46 2017 -0500
Committer: James E. King, III <jk...@apache.org>
Committed: Sat Nov 18 21:10:40 2017 -0500

----------------------------------------------------------------------
 README.md                                       |   2 +-
 .../thrift/processor/TMultiplexedProcessor.h    | 111 +++++++++++--------
 lib/cpp/src/thrift/protocol/THeaderProtocol.h   |   2 +-
 lib/cpp/src/thrift/transport/TSSLSocket.cpp     |  51 +++++----
 .../ThriftMVCTest/Controllers/HomeController.cs |   8 +-
 .../test/ThriftMVCTest/SecondServiceImpl.cs     |  14 +--
 lib/erl/test/thrift_test_test.erl               |  12 --
 .../test/org/apache/thrift/test/TestClient.java |  34 +++++-
 .../test/org/apache/thrift/test/TestServer.java |   4 -
 lib/nodejs/test/client.js                       |   2 +-
 lib/nodejs/test/server.js                       |   4 +-
 test/ThriftTest.thrift                          |   3 +-
 test/c_glib/src/thrift_second_service_handler.c |  13 ---
 test/cpp/CMakeLists.txt                         |   5 +-
 test/cpp/Makefile.am                            |   6 +-
 test/cpp/src/TestClient.cpp                     | 108 ++++++++++++------
 test/cpp/src/TestServer.cpp                     |  65 +++++++----
 test/csharp/TestClient.cs                       |  41 +++++--
 test/features/known_failures_Linux.json         |  12 +-
 test/known_failures_Linux.json                  |  90 ++++++++++++---
 test/rs/src/bin/test_client.rs                  |  12 --
 test/rs/src/bin/test_server.rs                  |   4 -
 test/tests.json                                 |  69 +++++++++---
 23 files changed, 431 insertions(+), 241 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/thrift/blob/58402ff6/README.md
----------------------------------------------------------------------
diff --git a/README.md b/README.md
index 2ef9a5e..5435041 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
 Apache Thrift
 =============
 
-Last Modified: 2017--10
+Last Modified: 2017-11-10
 
 License
 =======

http://git-wip-us.apache.org/repos/asf/thrift/blob/58402ff6/lib/cpp/src/thrift/processor/TMultiplexedProcessor.h
----------------------------------------------------------------------
diff --git a/lib/cpp/src/thrift/processor/TMultiplexedProcessor.h b/lib/cpp/src/thrift/processor/TMultiplexedProcessor.h
index 13b09bb..aa3d49f 100644
--- a/lib/cpp/src/thrift/processor/TMultiplexedProcessor.h
+++ b/lib/cpp/src/thrift/processor/TMultiplexedProcessor.h
@@ -27,8 +27,6 @@
 
 namespace apache {
 namespace thrift {
-using stdcxx::shared_ptr;
-
 namespace protocol {
 
 /**
@@ -38,7 +36,7 @@ namespace protocol {
  */
 class StoredMessageProtocol : public TProtocolDecorator {
 public:
-  StoredMessageProtocol(shared_ptr<protocol::TProtocol> _protocol,
+  StoredMessageProtocol(stdcxx::shared_ptr<protocol::TProtocol> _protocol,
                         const std::string& _name,
                         const TMessageType _type,
                         const int32_t _seqid)
@@ -67,19 +65,19 @@ public:
  * processors with it, as shown in the following example:</p>
  *
  * <blockquote><code>
- *     shared_ptr<TMultiplexedProcessor> processor(new TMultiplexedProcessor());
+ *     stdcxx::shared_ptr<TMultiplexedProcessor> processor(new TMultiplexedProcessor());
  *
  *     processor->registerProcessor(
  *         "Calculator",
- *         shared_ptr<TProcessor>( new CalculatorProcessor(
- *             shared_ptr<CalculatorHandler>( new CalculatorHandler()))));
+ *         stdcxx::shared_ptr<TProcessor>( new CalculatorProcessor(
+ *             stdcxx::shared_ptr<CalculatorHandler>( new CalculatorHandler()))));
  *
  *     processor->registerProcessor(
  *         "WeatherReport",
- *         shared_ptr<TProcessor>( new WeatherReportProcessor(
- *             shared_ptr<WeatherReportHandler>( new WeatherReportHandler()))));
+ *         stdcxx::shared_ptr<TProcessor>( new WeatherReportProcessor(
+ *             stdcxx::shared_ptr<WeatherReportHandler>( new WeatherReportHandler()))));
  *
- *     shared_ptr<TServerTransport> transport(new TServerSocket(9090));
+ *     stdcxx::shared_ptr<TServerTransport> transport(new TServerSocket(9090));
  *     TSimpleServer server(processor, transport);
  *
  *     server.serve();
@@ -87,7 +85,7 @@ public:
  */
 class TMultiplexedProcessor : public TProcessor {
 public:
-  typedef std::map<std::string, shared_ptr<TProcessor> > services_t;
+  typedef std::map<std::string, stdcxx::shared_ptr<TProcessor> > services_t;
 
   /**
     * 'Register' a service with this <code>TMultiplexedProcessor</code>.  This
@@ -100,11 +98,41 @@ public:
     *                         as "handlers", e.g. WeatherReportHandler,
     *                         implementing WeatherReportIf interface.
     */
-  void registerProcessor(const std::string& serviceName, shared_ptr<TProcessor> processor) {
+  void registerProcessor(const std::string& serviceName, stdcxx::shared_ptr<TProcessor> processor) {
     services[serviceName] = processor;
   }
 
   /**
+   * Register a service to be called to process queries without service name
+   * \param [in] processor   Implementation of a service.
+   */
+  void registerDefault(const stdcxx::shared_ptr<TProcessor>& processor) {
+    defaultProcessor = processor;
+  }
+
+  /**
+   * Chew up invalid input and return an exception to throw.
+   */
+  TException protocol_error(stdcxx::shared_ptr<protocol::TProtocol> in,
+                            stdcxx::shared_ptr<protocol::TProtocol> out,
+                            const std::string& name, 
+                            int32_t seqid, 
+                            const std::string& msg) const {
+    in->skip(::apache::thrift::protocol::T_STRUCT);
+    in->readMessageEnd();
+    in->getTransport()->readEnd();
+    ::apache::thrift::TApplicationException
+      x(::apache::thrift::TApplicationException::PROTOCOL_ERROR,
+        "TMultiplexedProcessor: " + msg);
+    out->writeMessageBegin(name, ::apache::thrift::protocol::T_EXCEPTION, seqid);
+    x.write(out.get());
+    out->writeMessageEnd();
+    out->getTransport()->writeEnd();
+    out->getTransport()->flush();
+    return TException(msg);
+}
+   
+  /**
    * This implementation of <code>process</code> performs the following steps:
    *
    * <ol>
@@ -119,8 +147,8 @@ public:
    * the service name was not found in the message, or if the service
    * name was not found in the service map.
    */
-  bool process(shared_ptr<protocol::TProtocol> in,
-               shared_ptr<protocol::TProtocol> out,
+  bool process(stdcxx::shared_ptr<protocol::TProtocol> in,
+               stdcxx::shared_ptr<protocol::TProtocol> out,
                void* connectionContext) {
     std::string name;
     protocol::TMessageType type;
@@ -133,22 +161,10 @@ public:
 
     if (type != protocol::T_CALL && type != protocol::T_ONEWAY) {
       // Unexpected message type.
-      in->skip(::apache::thrift::protocol::T_STRUCT);
-      in->readMessageEnd();
-      in->getTransport()->readEnd();
-      const std::string msg("TMultiplexedProcessor: Unexpected message type");
-      ::apache::thrift::TApplicationException
-          x(::apache::thrift::TApplicationException::PROTOCOL_ERROR, msg);
-      out->writeMessageBegin(name, ::apache::thrift::protocol::T_EXCEPTION, seqid);
-      x.write(out.get());
-      out->writeMessageEnd();
-      out->getTransport()->writeEnd();
-      out->getTransport()->flush();
-      throw TException(msg);
+      throw protocol_error(in, out, name, seqid, "Unexpected message type");
     }
 
     // Extract the service name
-
     boost::tokenizer<boost::char_separator<char> > tok(name, boost::char_separator<char>(":"));
 
     std::vector<std::string> tokens;
@@ -161,39 +177,46 @@ public:
       services_t::iterator it = services.find(tokens[0]);
 
       if (it != services.end()) {
-        shared_ptr<TProcessor> processor = it->second;
+        stdcxx::shared_ptr<TProcessor> processor = it->second;
         // Let the processor registered for this service name
         // process the message.
         return processor
-            ->process(shared_ptr<protocol::TProtocol>(
+            ->process(stdcxx::shared_ptr<protocol::TProtocol>(
                           new protocol::StoredMessageProtocol(in, tokens[1], type, seqid)),
                       out,
                       connectionContext);
       } else {
         // Unknown service.
-        in->skip(::apache::thrift::protocol::T_STRUCT);
-        in->readMessageEnd();
-        in->getTransport()->readEnd();
-
-        std::string msg("TMultiplexedProcessor: Unknown service: ");
-        msg += tokens[0];
-        ::apache::thrift::TApplicationException
-            x(::apache::thrift::TApplicationException::PROTOCOL_ERROR, msg);
-        out->writeMessageBegin(name, ::apache::thrift::protocol::T_EXCEPTION, seqid);
-        x.write(out.get());
-        out->writeMessageEnd();
-        out->getTransport()->writeEnd();
-        out->getTransport()->flush();
-        msg += ". Did you forget to call registerProcessor()?";
-        throw TException(msg);
+        throw protocol_error(in, out, name, seqid, 
+            "Unknown service: " + tokens[0] +
+				". Did you forget to call registerProcessor()?");
       }
+    } else if (tokens.size() == 1) {
+	  if (defaultProcessor) {
+        // non-multiplexed client forwards to default processor
+        return defaultProcessor            
+            ->process(stdcxx::shared_ptr<protocol::TProtocol>(
+                          new protocol::StoredMessageProtocol(in, tokens[0], type, seqid)),
+                      out,
+                      connectionContext);
+	  } else {
+		throw protocol_error(in, out, name, seqid,
+			"Non-multiplexed client request dropped. "
+			"Did you forget to call defaultProcessor()?");
+	  }
+    } else {
+		throw protocol_error(in, out, name, seqid,
+		    "Wrong number of tokens.");
     }
-    return false;
   }
 
 private:
   /** Map of service processor objects, indexed by service names. */
   services_t services;
+  
+  //! If a non-multi client requests something, it goes to the
+  //! default processor (if one is defined) for backwards compatibility.
+  stdcxx::shared_ptr<TProcessor> defaultProcessor;
 };
 }
 }

http://git-wip-us.apache.org/repos/asf/thrift/blob/58402ff6/lib/cpp/src/thrift/protocol/THeaderProtocol.h
----------------------------------------------------------------------
diff --git a/lib/cpp/src/thrift/protocol/THeaderProtocol.h b/lib/cpp/src/thrift/protocol/THeaderProtocol.h
index 0b3997c..8cd5017 100644
--- a/lib/cpp/src/thrift/protocol/THeaderProtocol.h
+++ b/lib/cpp/src/thrift/protocol/THeaderProtocol.h
@@ -192,7 +192,7 @@ class THeaderProtocolFactory : public TProtocolFactory {
 public:
   virtual stdcxx::shared_ptr<TProtocol> getProtocol(stdcxx::shared_ptr<transport::TTransport> trans) {
     THeaderProtocol* headerProtocol
-        = new THeaderProtocol(trans, stdcxx::shared_ptr<transport::TTransport>(), T_BINARY_PROTOCOL);
+        = new THeaderProtocol(trans, trans, T_BINARY_PROTOCOL);
     return stdcxx::shared_ptr<TProtocol>(headerProtocol);
   }
 

http://git-wip-us.apache.org/repos/asf/thrift/blob/58402ff6/lib/cpp/src/thrift/transport/TSSLSocket.cpp
----------------------------------------------------------------------
diff --git a/lib/cpp/src/thrift/transport/TSSLSocket.cpp b/lib/cpp/src/thrift/transport/TSSLSocket.cpp
index ddefb34..3f0e28e 100644
--- a/lib/cpp/src/thrift/transport/TSSLSocket.cpp
+++ b/lib/cpp/src/thrift/transport/TSSLSocket.cpp
@@ -157,7 +157,7 @@ void cleanupOpenSSL() {
   mutexes.reset();
 }
 
-static void buildErrors(string& message, int error = 0);
+static void buildErrors(string& message, int errno_copy = 0, int sslerrno = 0);
 static bool matchName(const char* host, const char* pattern, int size);
 static char uppercase(char c);
 
@@ -301,7 +301,7 @@ bool TSSLSocket::peek() {
         default:;// do nothing
       }
       string errors;
-      buildErrors(errors, errno_copy);
+      buildErrors(errors, errno_copy, error);
       throw TSSLException("SSL_peek: " + errors);
     } else if (rc == 0) {
       ERR_clear_error();
@@ -325,12 +325,14 @@ void TSSLSocket::close() {
   if (ssl_ != NULL) {
     try {
       int rc;
+      int errno_copy = 0;
+      int error = 0;
 
       do {
         rc = SSL_shutdown(ssl_);
         if (rc <= 0) {
-          int errno_copy = THRIFT_GET_SOCKET_ERROR;
-          int error = SSL_get_error(ssl_, rc);
+          errno_copy = THRIFT_GET_SOCKET_ERROR;
+          error = SSL_get_error(ssl_, rc);
           switch (error) {
             case SSL_ERROR_SYSCALL:
               if ((errno_copy != THRIFT_EINTR)
@@ -348,9 +350,8 @@ void TSSLSocket::close() {
       } while (rc == 2);
 
       if (rc < 0) {
-        int errno_copy = THRIFT_GET_SOCKET_ERROR;
         string errors;
-        buildErrors(errors, errno_copy);
+        buildErrors(errors, errno_copy, error);
         GlobalOutput(("SSL_shutdown: " + errors).c_str());
       }
     } catch (TTransportException& te) {
@@ -380,17 +381,19 @@ uint32_t TSSLSocket::read(uint8_t* buf, uint32_t len) {
     throw TTransportException(TTransportException::UNKNOWN, "retry again");
   int32_t bytes = 0;
   while (readRetryCount_ < maxRecvRetries_) {
-    ERR_clear_error();
     bytes = SSL_read(ssl_, buf, len);
+    int32_t errno_copy = THRIFT_GET_SOCKET_ERROR;
     int32_t error = SSL_get_error(ssl_, bytes);
     readRetryCount_++;
-    if (bytes >= 0 && error == 0) {
+    if (error == SSL_ERROR_NONE) {
       readRetryCount_ = 0;
       break;
     }
-    int32_t errno_copy = THRIFT_GET_SOCKET_ERROR;
     unsigned int waitEventReturn;
     switch (error) {
+      case SSL_ERROR_ZERO_RETURN:
+        throw TTransportException(TTransportException::END_OF_FILE, "client disconnected");
+
       case SSL_ERROR_SYSCALL:
         if ((errno_copy != THRIFT_EINTR)
             && (errno_copy != THRIFT_EAGAIN)) {
@@ -422,9 +425,9 @@ uint32_t TSSLSocket::read(uint8_t* buf, uint32_t len) {
           throw TTransportException(TTransportException::INTERNAL_ERROR, "too much recv retries");
         }
         else if (waitEventReturn == TSSL_DATA) {
-            // in case of SSL and huge thrift packets, there may be a number of 
-            // socket operations, before any data becomes available by SSL_read(). 
-            // Therefore the number of retries should not be increased and 
+            // in case of SSL and huge thrift packets, there may be a number of
+            // socket operations, before any data becomes available by SSL_read().
+            // Therefore the number of retries should not be increased and
             // the operation should be repeated.
             readRetryCount_--;
             continue;
@@ -433,7 +436,7 @@ uint32_t TSSLSocket::read(uint8_t* buf, uint32_t len) {
       default:;// do nothing
     }
     string errors;
-    buildErrors(errors, errno_copy);
+    buildErrors(errors, errno_copy, error);
     throw TSSLException("SSL_read: " + errors);
   }
   return bytes;
@@ -470,7 +473,7 @@ void TSSLSocket::write(const uint8_t* buf, uint32_t len) {
         default:;// do nothing
       }
       string errors;
-      buildErrors(errors, errno_copy);
+      buildErrors(errors, errno_copy, error);
       throw TSSLException("SSL_write: " + errors);
     }
     written += bytes;
@@ -514,7 +517,7 @@ uint32_t TSSLSocket::write_partial(const uint8_t* buf, uint32_t len) {
         default:;// do nothing
       }
       string errors;
-      buildErrors(errors, errno_copy);
+      buildErrors(errors, errno_copy, error);
       throw TSSLException("SSL_write: " + errors);
     }
     written += bytes;
@@ -574,12 +577,14 @@ void TSSLSocket::initializeHandshake() {
   }
 
   int rc;
+  int errno_copy = 0;
+  int error = 0;
   if (server()) {
     do {
       rc = SSL_accept(ssl_);
       if (rc <= 0) {
-        int errno_copy = THRIFT_GET_SOCKET_ERROR;
-        int error = SSL_get_error(ssl_, rc);
+        errno_copy = THRIFT_GET_SOCKET_ERROR;
+        error = SSL_get_error(ssl_, rc);
         switch (error) {
           case SSL_ERROR_SYSCALL:
             if ((errno_copy != THRIFT_EINTR)
@@ -610,8 +615,8 @@ void TSSLSocket::initializeHandshake() {
     do {
       rc = SSL_connect(ssl_);
       if (rc <= 0) {
-        int errno_copy = THRIFT_GET_SOCKET_ERROR;
-        int error = SSL_get_error(ssl_, rc);
+        errno_copy = THRIFT_GET_SOCKET_ERROR;
+        error = SSL_get_error(ssl_, rc);
         switch (error) {
           case SSL_ERROR_SYSCALL:
             if ((errno_copy != THRIFT_EINTR)
@@ -635,10 +640,9 @@ void TSSLSocket::initializeHandshake() {
     } while (rc == 2);
   }
   if (rc <= 0) {
-    int errno_copy = THRIFT_GET_SOCKET_ERROR;
     string fname(server() ? "SSL_accept" : "SSL_connect");
     string errors;
-    buildErrors(errors, errno_copy);
+    buildErrors(errors, errno_copy, error);
     throw TSSLException(fname + ": " + errors);
   }
   authorize();
@@ -975,7 +979,7 @@ int TSSLSocketFactory::passwordCallback(char* password, int size, int, void* dat
 }
 
 // extract error messages from error queue
-void buildErrors(string& errors, int errno_copy) {
+void buildErrors(string& errors, int errno_copy, int sslerrno) {
   unsigned long errorCode;
   char message[256];
 
@@ -999,6 +1003,9 @@ void buildErrors(string& errors, int errno_copy) {
   if (errors.empty()) {
     errors = "error code: " + to_string(errno_copy);
   }
+  if (sslerrno) {
+    errors += " (SSL_error_code = " + to_string(sslerrno) + ")";
+  }
 }
 
 /**

http://git-wip-us.apache.org/repos/asf/thrift/blob/58402ff6/lib/csharp/test/ThriftMVCTest/Controllers/HomeController.cs
----------------------------------------------------------------------
diff --git a/lib/csharp/test/ThriftMVCTest/Controllers/HomeController.cs b/lib/csharp/test/ThriftMVCTest/Controllers/HomeController.cs
index ab9eada..c9a1ec4 100644
--- a/lib/csharp/test/ThriftMVCTest/Controllers/HomeController.cs
+++ b/lib/csharp/test/ThriftMVCTest/Controllers/HomeController.cs
@@ -41,9 +41,8 @@ namespace ThriftMVCTest.Controllers
             SecondService.IAsync asyncService =
                 new SecondService.Client(new TBinaryProtocol(new THttpClient(new Uri(baseUri, "Async.thrift"))));
 
-            await asyncService.blahBlahAsync();
             var result = await asyncService.secondtestStringAsync("TestString");
-            if (result != "TestString")
+            if (result != "testString(\"TestString\")")
             {
                 throw new Exception("The wrong result was returned");
             }
@@ -59,9 +58,8 @@ namespace ThriftMVCTest.Controllers
             SecondService.ISync service =
                 new SecondService.Client(new TBinaryProtocol(new THttpClient(new Uri(baseUri, "Sync.thrift"))));
 
-            service.blahBlah();
             var result = service.secondtestString("TestString");
-            if (result != "TestString")
+            if (result != "testString(\"TestString\")")
             {
                 throw new Exception("The wrong result was returned");
             }
@@ -69,4 +67,4 @@ namespace ThriftMVCTest.Controllers
             return RedirectToAction("Index");
         }
     }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/thrift/blob/58402ff6/lib/csharp/test/ThriftMVCTest/SecondServiceImpl.cs
----------------------------------------------------------------------
diff --git a/lib/csharp/test/ThriftMVCTest/SecondServiceImpl.cs b/lib/csharp/test/ThriftMVCTest/SecondServiceImpl.cs
index dce0148..fad301a 100644
--- a/lib/csharp/test/ThriftMVCTest/SecondServiceImpl.cs
+++ b/lib/csharp/test/ThriftMVCTest/SecondServiceImpl.cs
@@ -24,24 +24,14 @@ namespace ThriftMVCTest
 {
     public class SecondServiceImpl : SecondService.IAsync, SecondService.ISync
     {
-        public Task blahBlahAsync()
-        {
-            return Task.FromResult(0);
-        }
-
         public Task<string> secondtestStringAsync(string thing)
         {
             return Task.FromResult(thing);
         }
 
-        public void blahBlah()
-        {
-
-        }
-
         public string secondtestString(string thing)
         {
-            return thing;
+            return "testString(\"" + thing + "\")";
         }
     }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/thrift/blob/58402ff6/lib/erl/test/thrift_test_test.erl
----------------------------------------------------------------------
diff --git a/lib/erl/test/thrift_test_test.erl b/lib/erl/test/thrift_test_test.erl
index ae20f31..77df61d 100644
--- a/lib/erl/test/thrift_test_test.erl
+++ b/lib/erl/test/thrift_test_test.erl
@@ -628,18 +628,6 @@ service_info_test_() ->
       {struct, []},
       thrift_test_thrift:function_info(testOneway, exceptions)
     )},
-    {"blahBlah params", ?_assertEqual(
-      {struct, []},
-      second_service_thrift:function_info(blahBlah, params_type)
-    )},
-    {"blahBlah reply", ?_assertEqual(
-      {struct, []},
-      second_service_thrift:function_info(blahBlah, reply_type)
-    )},
-    {"blahBlah exceptions", ?_assertEqual(
-      {struct, []},
-      second_service_thrift:function_info(blahBlah, exceptions)
-    )},
     {"secondtestString params", ?_assertEqual(
       {struct, [{1, string}]},
       second_service_thrift:function_info(secondtestString, params_type)

http://git-wip-us.apache.org/repos/asf/thrift/blob/58402ff6/lib/java/test/org/apache/thrift/test/TestClient.java
----------------------------------------------------------------------
diff --git a/lib/java/test/org/apache/thrift/test/TestClient.java b/lib/java/test/org/apache/thrift/test/TestClient.java
index b2ce1e6..feaa972 100644
--- a/lib/java/test/org/apache/thrift/test/TestClient.java
+++ b/lib/java/test/org/apache/thrift/test/TestClient.java
@@ -33,6 +33,7 @@ import org.apache.thrift.TSerializer;
 import org.apache.thrift.protocol.TBinaryProtocol;
 import org.apache.thrift.protocol.TCompactProtocol;
 import org.apache.thrift.protocol.TJSONProtocol;
+import org.apache.thrift.protocol.TMultiplexedProtocol;
 import org.apache.thrift.protocol.TProtocol;
 import org.apache.thrift.protocol.TSimpleJSONProtocol;
 import org.apache.thrift.transport.TFastFramedTransport;
@@ -46,6 +47,7 @@ import org.apache.thrift.transport.TTransportException;
 // Generated code
 import thrift.test.Insanity;
 import thrift.test.Numberz;
+import thrift.test.SecondService;
 import thrift.test.ThriftTest;
 import thrift.test.Xception;
 import thrift.test.Xception2;
@@ -64,6 +66,7 @@ public class TestClient {
   private static int ERR_STRUCTS = 2;
   private static int ERR_CONTAINERS = 4;
   private static int ERR_EXCEPTIONS = 8;
+  private static int ERR_PROTOCOLS = 16;
   private static int ERR_UNKNOWN = 64;
 
   public static void main(String [] args) {
@@ -102,7 +105,7 @@ public class TestClient {
           System.out.println("  --host=arg (=" + host + ")\tHost to connect");
           System.out.println("  --port=arg (=" + port + ")\tPort number to connect");
           System.out.println("  --transport=arg (=" + transport_type + ")\n\t\t\t\tTransport: buffered, framed, fastframed, http");
-          System.out.println("  --protocol=arg (=" + protocol_type + ")\tProtocol: binary, json, compact");
+          System.out.println("  --protocol=arg (=" + protocol_type + ")\tProtocol: binary, compact, json, multi, multic, multij");
           System.out.println("  --ssl\t\t\tEncrypted Transport using SSL");
           System.out.println("  --testloops[--n]=arg (=" + numTests + ")\tNumber of Tests");
           System.exit(0);
@@ -117,6 +120,9 @@ public class TestClient {
       if (protocol_type.equals("binary")) {
       } else if (protocol_type.equals("compact")) {
       } else if (protocol_type.equals("json")) {
+      } else if (protocol_type.equals("multi")) {
+      } else if (protocol_type.equals("multic")) {
+      } else if (protocol_type.equals("multij")) {
       } else {
         throw new Exception("Unknown protocol type! " + protocol_type);
       }
@@ -163,16 +169,21 @@ public class TestClient {
     }
 
     TProtocol tProtocol = null;
-    if (protocol_type.equals("json")) {
+    TProtocol tProtocol2 = null;
+    if (protocol_type.equals("json") || protocol_type.equals("multij")) {
       tProtocol = new TJSONProtocol(transport);
-    } else if (protocol_type.equals("compact")) {
+    } else if (protocol_type.equals("compact") || protocol_type.equals("multic")) {
       tProtocol = new TCompactProtocol(transport);
     } else {
       tProtocol = new TBinaryProtocol(transport);
     }
 
-    ThriftTest.Client testClient =
-      new ThriftTest.Client(tProtocol);
+    if (protocol_type.startsWith("multi")) {
+      tProtocol2 = new TMultiplexedProtocol(tProtocol, "SecondService");
+      tProtocol = new TMultiplexedProtocol(tProtocol, "ThriftTest");
+    }
+
+    ThriftTest.Client testClient = new ThriftTest.Client(tProtocol);
     Insanity insane = new Insanity();
 
     long timeMin = 0;
@@ -223,6 +234,19 @@ public class TestClient {
         }
 
         /**
+         * Multiplexed test
+         */
+        if (protocol_type.startsWith("multi")) {
+          SecondService.Client secondClient = new SecondService.Client(tProtocol2);
+          System.out.print("secondtestString(\"Test2\")");
+          s = secondClient.secondtestString("Test2");
+          System.out.print(" = \"" + s + "\"\n");
+          if (!s.equals("testString(\"Test2\")")) {
+            returnCode |= ERR_PROTOCOLS;
+            System.out.println("*** FAILURE ***\n");
+          }
+        }
+        /**
          * BYTE TEST
          */
         System.out.print("testByte(1)");

http://git-wip-us.apache.org/repos/asf/thrift/blob/58402ff6/lib/java/test/org/apache/thrift/test/TestServer.java
----------------------------------------------------------------------
diff --git a/lib/java/test/org/apache/thrift/test/TestServer.java b/lib/java/test/org/apache/thrift/test/TestServer.java
index 71b86c3..1f3e555 100644
--- a/lib/java/test/org/apache/thrift/test/TestServer.java
+++ b/lib/java/test/org/apache/thrift/test/TestServer.java
@@ -73,10 +73,6 @@ public class TestServer {
   static class SecondHandler implements thrift.test.SecondService.Iface {
 
     @Override
-    public void blahBlah() throws org.apache.thrift.TException
-    { throw new org.apache.thrift.TException("blahBlah"); }
-
-    @Override
     public java.lang.String secondtestString(java.lang.String thing) throws org.apache.thrift.TException
     { return "testString(\"" + thing + "\")"; }
 

http://git-wip-us.apache.org/repos/asf/thrift/blob/58402ff6/lib/nodejs/test/client.js
----------------------------------------------------------------------
diff --git a/lib/nodejs/test/client.js b/lib/nodejs/test/client.js
index 9609518..006fad2 100644
--- a/lib/nodejs/test/client.js
+++ b/lib/nodejs/test/client.js
@@ -108,7 +108,7 @@ if (type === 'tcp') {
   connection.on('connect', function() {
     secondclient.secondtestString("Test", function(err, response) {
       assert(!err);
-      assert.equal("Test", response);
+      assert.equal("testString(\"Test\")", response);
     });
 
     runTests();

http://git-wip-us.apache.org/repos/asf/thrift/blob/58402ff6/lib/nodejs/test/server.js
----------------------------------------------------------------------
diff --git a/lib/nodejs/test/server.js b/lib/nodejs/test/server.js
index bad3b17..8f2e06b 100644
--- a/lib/nodejs/test/server.js
+++ b/lib/nodejs/test/server.js
@@ -72,8 +72,8 @@ if (type === 'http' || type ==='websocket') {
 if (type === 'multiplex') {
   var SecondServiceHandler = {
     secondtestString: function(thing, result) {
-      console.log('testString(\'' + thing + '\')');
-      result(null, thing);
+      console.log('testString("' + thing + '")');
+      result(null, 'testString("' + thing + '")');
     }
   };
 

http://git-wip-us.apache.org/repos/asf/thrift/blob/58402ff6/test/ThriftTest.thrift
----------------------------------------------------------------------
diff --git a/test/ThriftTest.thrift b/test/ThriftTest.thrift
index c56f571..24dcbb9 100644
--- a/test/ThriftTest.thrift
+++ b/test/ThriftTest.thrift
@@ -321,13 +321,12 @@ service ThriftTest
 
 service SecondService
 {
-  void blahBlah()
   /**
    * Prints 'testString("%s")' with thing as '%s'
    * @param string thing - the string to print
    * @return string - returns the string 'thing'
    */
-  string       secondtestString(1: string thing),
+  string secondtestString(1: string thing)
 }
 
 struct VersioningTestV1 {

http://git-wip-us.apache.org/repos/asf/thrift/blob/58402ff6/test/c_glib/src/thrift_second_service_handler.c
----------------------------------------------------------------------
diff --git a/test/c_glib/src/thrift_second_service_handler.c b/test/c_glib/src/thrift_second_service_handler.c
index c464372..66ac7bc 100644
--- a/test/c_glib/src/thrift_second_service_handler.c
+++ b/test/c_glib/src/thrift_second_service_handler.c
@@ -50,17 +50,6 @@ second_service_handler_secondtest_string (TTestSecondServiceIf  *iface,
   return TRUE;
 }
 
-gboolean
-second_service_handler_blah_blah (TTestSecondServiceIf *iface, GError **error)
-{
-  THRIFT_UNUSED_VAR (iface);
-  THRIFT_UNUSED_VAR (error);
-
-  printf ("blahBlah()\n");
-
-  return TRUE;
-}
-
 static void
 second_service_handler_init (SecondServiceHandler *self)
 {
@@ -76,7 +65,5 @@ second_service_handler_class_init (SecondServiceHandlerClass *klass)
 
   base_class->secondtest_string =
       second_service_handler_secondtest_string;
-  base_class->blah_blah =
-      second_service_handler_blah_blah;
 
 }

http://git-wip-us.apache.org/repos/asf/thrift/blob/58402ff6/test/cpp/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/test/cpp/CMakeLists.txt b/test/cpp/CMakeLists.txt
index 1facfa4..cdd63db 100755
--- a/test/cpp/CMakeLists.txt
+++ b/test/cpp/CMakeLists.txt
@@ -34,6 +34,7 @@ include_directories("${CMAKE_CURRENT_BINARY_DIR}/gen-cpp")
 include_directories("${PROJECT_SOURCE_DIR}/lib/cpp/src")
 
 set(crosstestgencpp_SOURCES
+    gen-cpp/SecondService.cpp
     gen-cpp/ThriftTest.cpp
     gen-cpp/ThriftTest_types.cpp
     gen-cpp/ThriftTest_constants.cpp
@@ -44,7 +45,7 @@ LINK_AGAINST_THRIFT_LIBRARY(crosstestgencpp thrift)
 
 set(crossstressgencpp_SOURCES
     gen-cpp/Service.cpp
-    #gen-cpp/StressTest_types.cpp #basically empty, so omitting
+    gen-cpp/StressTest_types.cpp
     gen-cpp/StressTest_constants.cpp
 )
 add_library(crossstressgencpp STATIC ${crossstressgencpp_SOURCES})
@@ -79,7 +80,7 @@ add_test(NAME StressTestNonBlocking COMMAND StressTestNonBlocking)
 # Common thrift code generation rules
 #
 
-add_custom_command(OUTPUT gen-cpp/ThriftTest.cpp gen-cpp/ThriftTest_types.cpp gen-cpp/ThriftTest_constants.cpp
+add_custom_command(OUTPUT gen-cpp/SecondService.cpp gen-cpp/SecondService.h gen-cpp/ThriftTest.cpp gen-cpp/ThriftTest.h gen-cpp/ThriftTest_types.cpp gen-cpp/ThriftTest_constants.cpp
     COMMAND ${THRIFT_COMPILER} --gen cpp:templates,cob_style -r ${PROJECT_SOURCE_DIR}/test/ThriftTest.thrift
 )
 

http://git-wip-us.apache.org/repos/asf/thrift/blob/58402ff6/test/cpp/Makefile.am
----------------------------------------------------------------------
diff --git a/test/cpp/Makefile.am b/test/cpp/Makefile.am
index 359e7e6..e8be80a 100755
--- a/test/cpp/Makefile.am
+++ b/test/cpp/Makefile.am
@@ -21,12 +21,16 @@ AUTOMAKE_OPTIONS = subdir-objects serial-tests
 BUILT_SOURCES = gen-cpp/ThriftTest.cpp \
                 gen-cpp/ThriftTest_types.cpp \
                 gen-cpp/ThriftTest_constants.cpp \
+                gen-cpp/SecondService.cpp \
                 gen-cpp/StressTest_types.cpp \
                 gen-cpp/StressTest_constants.cpp \
                 gen-cpp/Service.cpp
 
 noinst_LTLIBRARIES = libtestgencpp.la libstresstestgencpp.la
 nodist_libtestgencpp_la_SOURCES = \
+	gen-cpp/SecondService.cpp \
+	gen-cpp/SecondService.h \
+	gen-cpp/SecondService.tcc \
 	gen-cpp/ThriftTest_constants.cpp \
 	gen-cpp/ThriftTest_constants.h \
 	gen-cpp/ThriftTest_types.cpp \
@@ -98,7 +102,7 @@ StressTestNonBlocking_LDADD = \
 #
 # Common thrift code generation rules
 #
-gen-cpp/ThriftTest.cpp gen-cpp/ThriftTest_types.cpp gen-cpp/ThriftTest_constants.cpp: $(top_srcdir)/test/ThriftTest.thrift $(THRIFT)
+gen-cpp/ThriftTest.cpp gen-cpp/ThriftTest_types.cpp gen-cpp/ThriftTest_constants.cpp gen-cpp/SecondService.cpp gen-cpp/SecondService.h gen-cpp/SecondService.tcc: $(top_srcdir)/test/ThriftTest.thrift $(THRIFT)
 	$(THRIFT) --gen cpp:templates,cob_style -r $<
 
 gen-cpp/StressTest_types.cpp gen-cpp/StressTest_constants.cpp gen-cpp/Service.cpp: $(top_srcdir)/test/StressTest.thrift $(THRIFT)

http://git-wip-us.apache.org/repos/asf/thrift/blob/58402ff6/test/cpp/src/TestClient.cpp
----------------------------------------------------------------------
diff --git a/test/cpp/src/TestClient.cpp b/test/cpp/src/TestClient.cpp
index 6b2e731..6e7ff8e 100644
--- a/test/cpp/src/TestClient.cpp
+++ b/test/cpp/src/TestClient.cpp
@@ -26,6 +26,7 @@
 #include <thrift/protocol/TCompactProtocol.h>
 #include <thrift/protocol/THeaderProtocol.h>
 #include <thrift/protocol/TJSONProtocol.h>
+#include <thrift/protocol/TMultiplexedProtocol.h>
 #include <thrift/transport/THttpClient.h>
 #include <thrift/transport/TTransportUtils.h>
 #include <thrift/transport/TSocket.h>
@@ -40,13 +41,15 @@
 #include <inttypes.h>
 #endif
 
-#include <boost/program_options.hpp>
+#include <boost/algorithm/string.hpp>
 #include <boost/filesystem.hpp>
+#include <boost/program_options.hpp>
 #include <thrift/stdcxx.h>
 #if _WIN32
 #include <thrift/windows/TWinsockSingleton.h>
 #endif
 
+#include "SecondService.h"
 #include "ThriftTest.h"
 
 using namespace std;
@@ -156,28 +159,33 @@ int main(int argc, char** argv) {
   int return_code = 0;
 
   boost::program_options::options_description desc("Allowed options");
-  desc.add_options()("help,h",
-                     "produce help message")("host",
-                                             boost::program_options::value<string>(&host)
-                                                 ->default_value(host),
-                                             "Host to connect")("port",
-                                                                boost::program_options::value<int>(
-                                                                    &port)->default_value(port),
-                                                                "Port number to connect")(
-      "domain-socket",
-      boost::program_options::value<string>(&domain_socket)->default_value(domain_socket),
-      "Domain Socket (e.g. /tmp/ThriftTest.thrift), instead of host and port")(
-      "abstract-namespace",
-      "Look for the domain socket in the Abstract Namespace (no connection with filesystem pathnames)")(
-      "transport",
-      boost::program_options::value<string>(&transport_type)->default_value(transport_type),
-      "Transport: buffered, framed, http, evhttp")(
-      "protocol",
-      boost::program_options::value<string>(&protocol_type)->default_value(protocol_type),
-      "Protocol: binary, header, compact, json")("ssl", "Encrypted Transport using SSL")(
-      "testloops,n",
-      boost::program_options::value<int>(&numTests)->default_value(numTests),
-      "Number of Tests")("noinsane", "Do not run insanity test");
+  desc.add_options()
+      ("help,h", "produce help message")
+      ("host", 
+          boost::program_options::value<string>(&host)->default_value(host), 
+          "Host to connect")
+      ("port", 
+          boost::program_options::value<int>(&port)->default_value(port), 
+          "Port number to connect")
+      ("domain-socket", 
+          boost::program_options::value<string>(&domain_socket)->default_value(domain_socket),
+          "Domain Socket (e.g. /tmp/ThriftTest.thrift), instead of host and port")
+      ("abstract-namespace",
+          "Look for the domain socket in the Abstract Namespace"
+          " (no connection with filesystem pathnames)")
+      ("transport",
+          boost::program_options::value<string>(&transport_type)->default_value(transport_type),
+          "Transport: buffered, framed, http, evhttp")
+      ("protocol",
+          boost::program_options::value<string>(&protocol_type)->default_value(protocol_type),
+          "Protocol: binary, compact, header, json, multi, multic, multih, multij")
+      ("ssl", 
+          "Encrypted Transport using SSL")
+      ("testloops,n",
+          boost::program_options::value<int>(&numTests)->default_value(numTests),
+          "Number of Tests")
+      ("noinsane",
+          "Do not run insanity test");
 
   boost::program_options::variables_map vm;
   boost::program_options::store(boost::program_options::parse_command_line(argc, argv, desc), vm);
@@ -194,6 +202,10 @@ int main(int argc, char** argv) {
       } else if (protocol_type == "compact") {
       } else if (protocol_type == "header") {
       } else if (protocol_type == "json") {
+      } else if (protocol_type == "multi") {
+      } else if (protocol_type == "multic") {
+      } else if (protocol_type == "multih") {
+      } else if (protocol_type == "multij") {
       } else {
         throw invalid_argument("Unknown protocol type " + protocol_type);
       }
@@ -232,6 +244,7 @@ int main(int argc, char** argv) {
   stdcxx::shared_ptr<TSocket> socket;
   stdcxx::shared_ptr<TTransport> transport;
   stdcxx::shared_ptr<TProtocol> protocol;
+  stdcxx::shared_ptr<TProtocol> protocol2;	// SecondService for multiplexed
 
   if (ssl) {
     cout << "Client Certificate File: " << certPath << endl;
@@ -271,18 +284,20 @@ int main(int argc, char** argv) {
     transport = bufferedSocket;
   }
 
-  if (protocol_type.compare("json") == 0) {
-    stdcxx::shared_ptr<TProtocol> jsonProtocol(new TJSONProtocol(transport));
-    protocol = jsonProtocol;
-  } else if (protocol_type.compare("compact") == 0) {
-    stdcxx::shared_ptr<TProtocol> compactProtocol(new TCompactProtocol(transport));
-    protocol = compactProtocol;
-  } else if (protocol_type == "header") {
-    stdcxx::shared_ptr<TProtocol> headerProtocol(new THeaderProtocol(transport));
-    protocol = headerProtocol;
+  if (protocol_type == "json" || protocol_type == "multij") {
+    protocol = stdcxx::make_shared<TJSONProtocol>(transport);
+  } else if (protocol_type == "compact" || protocol_type == "multic") {
+    protocol = stdcxx::make_shared<TCompactProtocol>(transport);
+  } else if (protocol_type == "header" || protocol_type == "multih") {
+    protocol = stdcxx::make_shared<THeaderProtocol>(transport);
   } else {
-    stdcxx::shared_ptr<TBinaryProtocol> binaryProtocol(new TBinaryProtocol(transport));
-    protocol = binaryProtocol;
+    protocol = stdcxx::make_shared<TBinaryProtocol>(transport);
+  }
+
+  if (boost::starts_with(protocol_type, "multi")) {
+	protocol2 = stdcxx::make_shared<TMultiplexedProtocol>(protocol, "SecondService");
+	// we don't need access to the original protocol any more, so...
+	protocol = stdcxx::make_shared<TMultiplexedProtocol>(protocol, "ThriftTest");
   }
 
   // Connection info
@@ -367,6 +382,25 @@ int main(int argc, char** argv) {
       return_code |= ERR_BASETYPES;
     }
 
+    //
+    // Multiplexed protocol - call another service method
+    // in the middle of the ThriftTest
+    //
+    if (boost::starts_with(protocol_type, "multi")) {
+		SecondServiceClient ssc(protocol2);
+		// transport is already open...
+		  
+        try {
+          cout << "secondService.secondTestString(\"foo\") => " << flush;
+	  	  std::string result;
+		  ssc.secondtestString(result, "foo");
+		  cout << "{" << result << "}" << endl;
+	    } catch (std::exception& e) {
+		  cout << "  *** FAILED *** " << e.what() << endl;
+		  return_code |= ERR_EXCEPTIONS;
+		}
+    }
+
     try {
 #ifdef _MSC_VER
 #pragma warning( push )
@@ -1096,12 +1130,14 @@ int main(int argc, char** argv) {
     /**
      * I32 TEST
      */
-    cout << "re-test testI32(-1)";
+    cout << "re-test testI32(-1)" << flush;
     int i32 = testClient.testI32(-1);
     cout << " = " << i32 << endl;
     if (i32 != -1)
       return_code |= ERR_BASETYPES;
 
+    cout << endl << "All tests done." << endl << flush;
+    
     uint64_t stop = now();
     uint64_t tot = stop - start;
 
@@ -1115,10 +1151,10 @@ int main(int argc, char** argv) {
       time_max = tot;
     }
 
+    cout << flush;
     transport->close();
   }
 
-  cout << endl << "All tests done." << endl;
 
   uint64_t time_avg = time_tot / numTests;
 

http://git-wip-us.apache.org/repos/asf/thrift/blob/58402ff6/test/cpp/src/TestServer.cpp
----------------------------------------------------------------------
diff --git a/test/cpp/src/TestServer.cpp b/test/cpp/src/TestServer.cpp
index 37d0eb6..744a86c 100644
--- a/test/cpp/src/TestServer.cpp
+++ b/test/cpp/src/TestServer.cpp
@@ -17,26 +17,29 @@
  * under the License.
  */
 
-#include <thrift/concurrency/ThreadManager.h>
+#include <thrift/async/TAsyncBufferProcessor.h>
+#include <thrift/async/TAsyncProtocolProcessor.h>
+#include <thrift/async/TEvhttpServer.h>
 #include <thrift/concurrency/PlatformThreadFactory.h>
+#include <thrift/concurrency/ThreadManager.h>
+#include <thrift/processor/TMultiplexedProcessor.h>
 #include <thrift/protocol/TBinaryProtocol.h>
 #include <thrift/protocol/TCompactProtocol.h>
 #include <thrift/protocol/THeaderProtocol.h>
 #include <thrift/protocol/TJSONProtocol.h>
+#include <thrift/server/TNonblockingServer.h>
 #include <thrift/server/TSimpleServer.h>
-#include <thrift/server/TThreadedServer.h>
 #include <thrift/server/TThreadPoolServer.h>
-#include <thrift/async/TEvhttpServer.h>
-#include <thrift/async/TAsyncBufferProcessor.h>
-#include <thrift/async/TAsyncProtocolProcessor.h>
-#include <thrift/server/TNonblockingServer.h>
-#include <thrift/transport/TServerSocket.h>
-#include <thrift/transport/TSSLServerSocket.h>
-#include <thrift/transport/TSSLSocket.h>
-#include <thrift/transport/TNonblockingServerSocket.h>
+#include <thrift/server/TThreadedServer.h>
 #include <thrift/transport/THttpServer.h>
 #include <thrift/transport/THttpTransport.h>
+#include <thrift/transport/TNonblockingServerSocket.h>
+#include <thrift/transport/TSSLServerSocket.h>
+#include <thrift/transport/TSSLSocket.h>
+#include <thrift/transport/TServerSocket.h>
 #include <thrift/transport/TTransportUtils.h>
+
+#include "SecondService.h"
 #include "ThriftTest.h"
 
 #ifdef HAVE_STDINT_H
@@ -50,6 +53,7 @@
 #include <stdexcept>
 #include <sstream>
 
+#include <boost/algorithm/string.hpp>
 #include <boost/program_options.hpp>
 #include <boost/filesystem.hpp>
 #include <thrift/stdcxx.h>
@@ -331,13 +335,18 @@ public:
     }
   }
 
-  void testOneway(const int32_t sleepFor) {
-    printf("testOneway(%d): Sleeping...\n", sleepFor);
-    THRIFT_SLEEP_SEC(sleepFor);
-    printf("testOneway(%d): done sleeping!\n", sleepFor);
+  void testOneway(const int32_t aNum) {
+    printf("testOneway(%d): call received\n", aNum);
   }
 };
 
+class SecondHandler : public SecondServiceIf
+{
+  public:
+    void secondtestString(std::string& result, const std::string& thing)
+    { result = "testString(\"" + thing + "\")"; }
+};	
+
 class TestProcessorEventHandler : public TProcessorEventHandler {
   virtual void* getContext(const char* fn_name, void* serverContext) {
     (void)serverContext;
@@ -565,7 +574,7 @@ int main(int argc, char** argv) {
     ("abstract-namespace", "Create the domain socket in the Abstract Namespace (no connection with filesystem pathnames)")
     ("server-type", po::value<string>(&server_type)->default_value(server_type), "type of server, \"simple\", \"thread-pool\", \"threaded\", or \"nonblocking\"")
     ("transport", po::value<string>(&transport_type)->default_value(transport_type), "transport: buffered, framed, http")
-    ("protocol", po::value<string>(&protocol_type)->default_value(protocol_type), "protocol: binary, compact, header, json")
+    ("protocol", po::value<string>(&protocol_type)->default_value(protocol_type), "protocol: binary, compact, header, json, multi, multic, multih, multij")
     ("ssl", "Encrypted Transport using SSL")
     ("processor-events", "processor-events")
     ("workers,n", po::value<size_t>(&workers)->default_value(workers), "Number of thread pools workers. Only valid for thread-pool server type")
@@ -597,6 +606,10 @@ int main(int argc, char** argv) {
       } else if (protocol_type == "compact") {
       } else if (protocol_type == "json") {
       } else if (protocol_type == "header") {
+      } else if (protocol_type == "multi") {	// multiplexed binary
+      } else if (protocol_type == "multic") {	// multiplexed compact
+      } else if (protocol_type == "multih") {	// multiplexed header
+      } else if (protocol_type == "multij") {	// multiplexed json
       } else {
         throw invalid_argument("Unknown protocol type " + protocol_type);
       }
@@ -627,15 +640,15 @@ int main(int argc, char** argv) {
 
   // Dispatcher
   stdcxx::shared_ptr<TProtocolFactory> protocolFactory;
-  if (protocol_type == "json") {
+  if (protocol_type == "json" || protocol_type == "multij") {
     stdcxx::shared_ptr<TProtocolFactory> jsonProtocolFactory(new TJSONProtocolFactory());
     protocolFactory = jsonProtocolFactory;
-  } else if (protocol_type == "compact") {
+  } else if (protocol_type == "compact" || protocol_type == "multic") {
     TCompactProtocolFactoryT<TBufferBase> *compactProtocolFactory = new TCompactProtocolFactoryT<TBufferBase>();
     compactProtocolFactory->setContainerSizeLimit(container_limit);
     compactProtocolFactory->setStringSizeLimit(string_limit);
     protocolFactory.reset(compactProtocolFactory);
-  } else if (protocol_type == "header") {
+  } else if (protocol_type == "header" || protocol_type == "multih") {
     stdcxx::shared_ptr<TProtocolFactory> headerProtocolFactory(new THeaderProtocolFactory());
     protocolFactory = headerProtocolFactory;
   } else {
@@ -645,9 +658,9 @@ int main(int argc, char** argv) {
     protocolFactory.reset(binaryProtocolFactory);
   }
 
-  // Processor
+  // Processors
   stdcxx::shared_ptr<TestHandler> testHandler(new TestHandler());
-  stdcxx::shared_ptr<ThriftTestProcessor> testProcessor(new ThriftTestProcessor(testHandler));
+  stdcxx::shared_ptr<TProcessor> testProcessor(new ThriftTestProcessor(testHandler));
 
   if (vm.count("processor-events")) {
     testProcessor->setEventHandler(
@@ -706,6 +719,18 @@ int main(int argc, char** argv) {
   }
   cout << endl;
 
+  // Multiplexed Processor if needed
+  if (boost::starts_with(protocol_type, "multi")) {
+    stdcxx::shared_ptr<SecondHandler> secondHandler(new SecondHandler());
+    stdcxx::shared_ptr<SecondServiceProcessor> secondProcessor(new SecondServiceProcessor(secondHandler));
+
+    stdcxx::shared_ptr<TMultiplexedProcessor> multiplexedProcessor(new TMultiplexedProcessor());
+    multiplexedProcessor->registerDefault(testProcessor); // non-multi clients go to the default processor (multi:binary, multic:compact, ...)
+    multiplexedProcessor->registerProcessor("ThriftTest", testProcessor);
+    multiplexedProcessor->registerProcessor("SecondService", secondProcessor);
+    testProcessor = stdcxx::dynamic_pointer_cast<TProcessor>(multiplexedProcessor);
+  }
+
   // Server
   stdcxx::shared_ptr<apache::thrift::server::TServer> server;
 

http://git-wip-us.apache.org/repos/asf/thrift/blob/58402ff6/test/csharp/TestClient.cs
----------------------------------------------------------------------
diff --git a/test/csharp/TestClient.cs b/test/csharp/TestClient.cs
index fad1057..17e5978 100644
--- a/test/csharp/TestClient.cs
+++ b/test/csharp/TestClient.cs
@@ -33,7 +33,7 @@ namespace Test
 {
     public class TestClient
     {
-        private class TestParams
+        public class TestParams
         {
             public int numIterations = 1;
             public string host = "localhost";
@@ -44,6 +44,7 @@ namespace Test
             public bool framed;
             public string protocol;
             public bool encrypted = false;
+            public bool multiplexed = false;
             protected bool _isFirstTransport = true;
 
 
@@ -105,21 +106,30 @@ namespace Test
         private const int ErrorStructs = 2;
         private const int ErrorContainers = 4;
         private const int ErrorExceptions = 8;
+        private const int ErrorProtocol = 16;
         private const int ErrorUnknown = 64;
 
         private class ClientTest
         {
+            private readonly TestParams param;
             private readonly TTransport transport;
+            private readonly SecondService.Client second;
             private readonly ThriftTest.Client client;
             private readonly int numIterations;
             private bool done;
 
             public int ReturnCode { get; set; }
 
-            public ClientTest(TestParams param)
+            public ClientTest(TestParams paramin)
             {
+                param = paramin;
                 transport = param.CreateTransport();
-                client = new ThriftTest.Client(param.CreateProtocol(transport));
+                TProtocol protocol = param.CreateProtocol(transport);
+                if (param.multiplexed)
+                {
+                    second = new SecondService.Client(new TMultiplexedProtocol(protocol, "SecondService"));
+                }
+                client = new ThriftTest.Client(protocol);
                 numIterations = param.numIterations;
             }
             public void Execute()
@@ -148,7 +158,7 @@ namespace Test
 
                     try
                     {
-                        ReturnCode |= ExecuteClientTest(client);
+                        ReturnCode |= ExecuteClientTest(client, second, param);
                     }
                     catch (Exception ex)
                     {
@@ -215,12 +225,12 @@ namespace Test
                         {
                             numThreads = Convert.ToInt32(args[++i]);
                         }
-                        else if (args[i] == "--compact" || args[i] == "--protocol=compact")
+                        else if (args[i] == "--compact" || args[i] == "--protocol=compact" || args[i] == "--protocol=multic")
                         {
                             param.protocol = "compact";
                             Console.WriteLine("Using compact protocol");
                         }
-                        else if (args[i] == "--json" || args[i] == "--protocol=json")
+                        else if (args[i] == "--json" || args[i] == "--protocol=json" || args[i] == "--protocol=multij")
                         {
                             param.protocol = "json";
                             Console.WriteLine("Using JSON protocol");
@@ -230,6 +240,11 @@ namespace Test
                             param.encrypted = true;
                             Console.WriteLine("Using encrypted transport");
                         }
+
+                        if (args[i].StartsWith("--protocol=multi"))
+                        {
+                            param.multiplexed = true;
+                        }
                     }
                 }
                 catch (Exception ex)
@@ -296,7 +311,7 @@ namespace Test
             return retval;
         }
 
-        public static int ExecuteClientTest(ThriftTest.Client client)
+        public static int ExecuteClientTest(ThriftTest.Client client, SecondService.Client second, TestParams param)
         {
             int returnCode = 0;
 
@@ -313,6 +328,18 @@ namespace Test
                 returnCode |= ErrorBaseTypes;
             }
 
+            if (param.multiplexed)
+            {
+                Console.WriteLine("secondTestString(\"Test2\")");
+                s = second.secondtestString("Test2");
+              Console.WriteLine(" = \"" + s + "\"");
+              if ("testString(\"Test2\")" != s)
+              {
+                  Console.WriteLine("*** FAILED ***");
+                  returnCode |= ErrorProtocol;
+              }
+            }
+
             Console.Write("testBool(true)");
             bool t = client.testBool((bool)true);
             Console.WriteLine(" = " + t);

http://git-wip-us.apache.org/repos/asf/thrift/blob/58402ff6/test/features/known_failures_Linux.json
----------------------------------------------------------------------
diff --git a/test/features/known_failures_Linux.json b/test/features/known_failures_Linux.json
index e3575f9..f96356d 100644
--- a/test/features/known_failures_Linux.json
+++ b/test/features/known_failures_Linux.json
@@ -1,6 +1,10 @@
 [
   "c_glib-limit_container_length_binary_buffered-ip",
   "c_glib-limit_string_length_binary_buffered-ip",
+  "cpp-theader_framed_binary_multih-header_buffered-ip",
+  "cpp-theader_framed_compact_multih-header_buffered-ip",
+  "cpp-theader_unframed_binary_multih-header_buffered-ip",
+  "cpp-theader_unframed_compact_multih-header_buffered-ip",
   "csharp-limit_container_length_binary_buffered-ip",
   "csharp-limit_container_length_compact_buffered-ip",
   "csharp-limit_string_length_binary_buffered-ip",
@@ -33,8 +37,10 @@
   "rb-limit_string_length_accel-binary_buffered-ip",
   "rb-limit_string_length_binary_buffered-ip",
   "rb-limit_string_length_compact_buffered-ip",
+  "rs-limit_container_length_binary_buffered-ip",
+  "rs-limit_container_length_compact_buffered-ip",
+  "rs-limit_container_length_multic-compact_buffered-ip",
   "rs-limit_string_length_binary_buffered-ip",
   "rs-limit_string_length_compact_buffered-ip",
-  "rs-limit_container_length_binary_buffered-ip",
-  "rs-limit_container_length_compact_buffered-ip"
-]
+  "rs-limit_string_length_multic-compact_buffered-ip"
+]
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/thrift/blob/58402ff6/test/known_failures_Linux.json
----------------------------------------------------------------------
diff --git a/test/known_failures_Linux.json b/test/known_failures_Linux.json
index eda5df0..ea194a1 100644
--- a/test/known_failures_Linux.json
+++ b/test/known_failures_Linux.json
@@ -1,38 +1,90 @@
 [
-  "cpp-cpp_binary_buffered-ip-ssl",
-  "cpp-cpp_binary_framed-ip-ssl",
+  "c_glib-csharp_multi-binary_buffered-ip",
+  "c_glib-csharp_multi-binary_framed-ip",
+  "c_glib-csharp_multi_buffered-ip",
+  "c_glib-csharp_multi_framed-ip",
+  "c_glib-csharp_multic_buffered-ip",
+  "c_glib-csharp_multic-compact_buffered-ip",
+  "c_glib-csharp_multic-compact_framed-ip",
+  "c_glib-csharp_multic_framed-ip",
+  "c_glib-rs_multi_buffered-ip",
+  "c_glib-rs_multi_framed-ip",
+  "c_glib-rs_multic_buffered-ip",
+  "c_glib-rs_multic_framed-ip",
   "cpp-cpp_binary_http-domain",
-  "cpp-cpp_binary_http-ip-ssl",
-  "cpp-cpp_compact_buffered-ip-ssl",
-  "cpp-cpp_compact_framed-ip-ssl",
-  "cpp-cpp_compact_http-ip-ssl",
-  "cpp-cpp_header_buffered-ip-ssl",
-  "cpp-cpp_header_framed-ip-ssl",
-  "cpp-cpp_header_http-ip-ssl",
-  "cpp-cpp_json_buffered-ip-ssl",
-  "cpp-cpp_json_framed-ip-ssl",
-  "cpp-cpp_json_http-ip-ssl",
+  "cpp-cpp_compact_http-domain",
+  "cpp-cpp_compact_http-ip",
+  "cpp-cpp_header_http-domain",
+  "cpp-cpp_json_http-domain",
+  "cpp-cpp_json_http-ip",
+  "cpp-cpp_multi-binary_http-domain",
+  "cpp-cpp_multi-binary_http-ip",
+  "cpp-cpp_multi_http-domain",
+  "cpp-cpp_multi_http-ip",
+  "cpp-cpp_multic-compact_http-domain",
+  "cpp-cpp_multic-compact_http-ip",
+  "cpp-cpp_multic_http-domain",
+  "cpp-cpp_multic_http-ip",
+  "cpp-cpp_multih-header_http-domain",
+  "cpp-cpp_multih-header_http-ip",
+  "cpp-cpp_multih_http-domain",
+  "cpp-cpp_multih_http-ip",
+  "cpp-cpp_multij-json_http-domain",
+  "cpp-cpp_multij-json_http-ip",
+  "cpp-cpp_multij_http-domain",
+  "cpp-cpp_multij_http-ip",
   "cpp-dart_binary_http-ip",
   "cpp-dart_compact_http-ip",
   "cpp-dart_json_http-ip",
+  "cpp-dart_multi-binary_http-ip",
+  "cpp-dart_multic-compact_http-ip",
+  "cpp-dart_multij-json_http-ip",
   "cpp-go_binary_http-ip",
   "cpp-go_binary_http-ip-ssl",
   "cpp-go_compact_http-ip",
   "cpp-go_compact_http-ip-ssl",
   "cpp-go_json_http-ip",
   "cpp-go_json_http-ip-ssl",
+  "cpp-go_multi-binary_http-ip",
+  "cpp-go_multi-binary_http-ip-ssl",
+  "cpp-go_multic-compact_http-ip",
+  "cpp-go_multic-compact_http-ip-ssl",
+  "cpp-go_multij-json_http-ip",
+  "cpp-go_multij-json_http-ip-ssl",
   "cpp-java_binary_http-ip",
   "cpp-java_binary_http-ip-ssl",
   "cpp-java_compact_http-ip",
   "cpp-java_compact_http-ip-ssl",
   "cpp-java_json_http-ip",
   "cpp-java_json_http-ip-ssl",
+  "cpp-java_multi-binary_http-ip",
+  "cpp-java_multi-binary_http-ip-ssl",
+  "cpp-java_multi_http-ip",
+  "cpp-java_multi_http-ip-ssl",
+  "cpp-java_multic-compact_http-ip",
+  "cpp-java_multic-compact_http-ip-ssl",
+  "cpp-java_multic_http-ip",
+  "cpp-java_multic_http-ip-ssl",
+  "cpp-java_multij-json_http-ip",
+  "cpp-java_multij-json_http-ip-ssl",
+  "cpp-java_multij_http-ip",
+  "cpp-java_multij_http-ip-ssl",
   "cpp-nodejs_binary_http-ip",
   "cpp-nodejs_binary_http-ip-ssl",
   "cpp-nodejs_compact_http-ip",
   "cpp-nodejs_compact_http-ip-ssl",
   "cpp-nodejs_json_http-ip",
   "cpp-nodejs_json_http-ip-ssl",
+  "cpp-nodejs_multi-binary_http-ip",
+  "cpp-nodejs_multi-binary_http-ip-ssl",
+  "cpp-nodejs_multic-compact_http-ip",
+  "cpp-nodejs_multic-compact_http-ip-ssl",
+  "cpp-nodejs_multij-json_http-ip",
+  "cpp-nodejs_multij-json_http-ip-ssl",
+  "cpp-rs_multi_buffered-ip",
+  "cpp-rs_multi_framed-ip",
+  "cpp-rs_multic_buffered-ip",
+  "cpp-rs_multic_framed-ip",
   "csharp-d_binary_buffered-ip-ssl",
   "csharp-d_binary_framed-ip-ssl",
   "csharp-d_compact_buffered-ip-ssl",
@@ -246,9 +298,19 @@
   "nodejs-netcore_json_framed-ip",
   "nodejs-netcore_json_framed-ip-ssl",
   "rs-csharp_binary_buffered-ip",
-  "rs-csharp_compact_buffered-ip",
   "rs-csharp_binary_framed-ip",
+  "rs-csharp_compact_buffered-ip",
   "rs-csharp_compact_framed-ip",
+  "rs-csharp_multi-binary_buffered-ip",
+  "rs-csharp_multi-binary_framed-ip",
+  "rs-csharp_multi_buffered-ip",
+  "rs-csharp_multi_framed-ip",
+  "rs-csharp_multic-compact_buffered-ip",
+  "rs-csharp_multic-compact_framed-ip",
+  "rs-csharp_multic_buffered-ip",
+  "rs-csharp_multic_framed-ip",
   "rs-dart_binary_framed-ip",
-  "rs-dart_compact_framed-ip"
+  "rs-dart_compact_framed-ip",
+  "rs-dart_multi-binary_framed-ip",
+  "rs-dart_multic-compact_framed-ip"
 ]

http://git-wip-us.apache.org/repos/asf/thrift/blob/58402ff6/test/rs/src/bin/test_client.rs
----------------------------------------------------------------------
diff --git a/test/rs/src/bin/test_client.rs b/test/rs/src/bin/test_client.rs
index d720313..7c11ad5 100644
--- a/test/rs/src/bin/test_client.rs
+++ b/test/rs/src/bin/test_client.rs
@@ -287,18 +287,6 @@ fn make_thrift_calls(
 
     // do the multiplexed calls while making the main ThriftTest calls
     if let Some(ref mut client) = second_service_client.as_mut() {
-        info!("SecondService blahBlah");
-        {
-            let r = client.blah_blah();
-            match r {
-                Err(thrift::Error::Application(ref e)) => {
-                    info!("received an {:?}", e);
-                    Ok(())
-                }
-                _ => Err(thrift::Error::User("did not get exception".into())),
-            }?;
-        }
-
         info!("SecondService secondtestString");
         {
             verify_expected_result(

http://git-wip-us.apache.org/repos/asf/thrift/blob/58402ff6/test/rs/src/bin/test_server.rs
----------------------------------------------------------------------
diff --git a/test/rs/src/bin/test_server.rs b/test/rs/src/bin/test_server.rs
index a32e938..81a2ad8 100644
--- a/test/rs/src/bin/test_server.rs
+++ b/test/rs/src/bin/test_server.rs
@@ -390,10 +390,6 @@ impl ThriftTestSyncHandler for ThriftTestSyncHandlerImpl {
 
 struct SecondServiceSyncHandlerImpl;
 impl SecondServiceSyncHandler for SecondServiceSyncHandlerImpl {
-    fn handle_blah_blah(&self) -> thrift::Result<()> {
-        Err(thrift::new_application_error(thrift::ApplicationErrorKind::Unknown, "blahBlah"),)
-    }
-
     fn handle_secondtest_string(&self, thing: String) -> thrift::Result<String> {
         info!("testString({})", &thing);
         let ret = format!("testString(\"{}\")", &thing);

http://git-wip-us.apache.org/repos/asf/thrift/blob/58402ff6/test/tests.json
----------------------------------------------------------------------
diff --git a/test/tests.json b/test/tests.json
index c1c3155..bde9014 100644
--- a/test/tests.json
+++ b/test/tests.json
@@ -11,9 +11,7 @@
       ],
       "protocols": [
         "binary:multi",
-        "compact:multic",
-        "multi",
-        "multic"
+        "compact:multic"
       ]
     },
     "client": {
@@ -22,8 +20,6 @@
         "--lt-debug"
       ],
       "protocols": [
-        "multi",
-        "multic",
         "multi:binary",
         "multic:compact"
       ],
@@ -40,7 +36,9 @@
     ],
     "protocols": [
       "binary",
-      "compact"
+      "compact",
+      "multi",
+      "multic"
     ],
     "workdir": "c_glib"
   },
@@ -124,10 +122,7 @@
       "protocols": [
         "binary:multi",
         "compact:multic",
-        "json:multij",
-        "multi",
-        "multic",
-        "multij"
+        "json:multij"
       ]
     },
     "client": {
@@ -135,6 +130,11 @@
       "extra_args": ["run-testclient"],
       "transports": [
         "http"
+      ],
+      "protocols": [
+        "multi:binary",
+        "multic:compact",
+        "multij:json"
       ]
     },
     "transports": [
@@ -149,7 +149,10 @@
     "protocols": [
       "binary",
       "compact",
-      "json"
+      "json",
+      "multi",
+      "multic",
+      "multij"
     ],
     "workdir": "../lib/java"
   },
@@ -298,12 +301,24 @@
     "server": {
       "command": [
         "TestServer"
+      ],
+      "protocols": [
+        "binary:multi",
+        "compact:multic",
+        "header:multih",
+        "json:multij"
       ]
     },
     "client": {
       "timeout": 8,
       "command": [
         "TestClient"
+      ],
+      "protocols": [
+        "multi:binary",
+        "multic:compact",
+        "multih:header",
+        "multij:json"
       ]
     },
     "transports": [
@@ -320,7 +335,11 @@
       "compact",
       "binary",
       "json",
-      "header"
+      "header",
+      "multi",
+      "multic",
+      "multih",
+      "multij"
     ],
     "workdir": "cpp"
   },
@@ -385,6 +404,12 @@
         "mono",
         "TestClientServer.exe",
         "client"
+      ],
+      "protocols": [
+        "multi",
+        "multic",
+        "multi:binary",
+        "multic:compact"
       ]
     },
     "workdir": "csharp"
@@ -408,9 +433,9 @@
       "command": [
         "dotnet",
         "run",
-	"--no-build",
-	"--no-restore",
-	"--",
+  "--no-build",
+  "--no-restore",
+  "--",
         "server"
       ]
     },
@@ -419,9 +444,9 @@
       "command": [
         "dotnet",
         "run",
-	"--no-build",
-	"--no-restore",
-	"--",
+  "--no-build",
+  "--no-restore",
+  "--",
         "client"
       ]
     },
@@ -622,12 +647,20 @@
     "server": {
       "command": [
         "test_server"
+      ],
+      "protocols": [
+        "binary:multi",
+        "compact:multic"
       ]
     },
     "client": {
       "timeout": 6,
       "command": [
         "test_client"
+      ],
+      "protocols": [
+        "multi:binary",
+        "multic:compact"
       ]
     },
     "sockets": [


[2/3] thrift git commit: THRIFT-4329: multiplexed processor, client and server for c_glib Client: c_glib

Posted by jk...@apache.org.
THRIFT-4329: multiplexed processor, client and server for c_glib
Client: c_glib

This closes #1361


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

Branch: refs/heads/master
Commit: 87ad2bcaaa5a9fe224ad7a9826b676ca9721ddd1
Parents: 95d5fb3
Author: Gonzalo Aguilar Delgado <ga...@level2crm.com>
Authored: Fri Sep 15 12:26:02 2017 +0200
Committer: James E. King, III <jk...@apache.org>
Committed: Sat Nov 18 21:10:18 2017 -0500

----------------------------------------------------------------------
 lib/c_glib/CMakeLists.txt                       |   3 +
 lib/c_glib/Makefile.am                          |   9 +-
 .../processor/thrift_multiplexed_processor.c    | 346 ++++++++++++++
 .../processor/thrift_multiplexed_processor.h    | 114 +++++
 .../protocol/thrift_multiplexed_protocol.c      |   2 +-
 .../c_glib/protocol/thrift_protocol_decorator.c |   3 -
 .../protocol/thrift_stored_message_protocol.c   | 192 ++++++++
 .../protocol/thrift_stored_message_protocol.h   |  78 ++++
 .../c_glib/transport/thrift_platform_socket.h   |  12 +-
 .../src/thrift/c_glib/transport/thrift_socket.c |  41 +-
 .../thrift/c_glib/transport/thrift_ssl_socket.c | 234 ++++++----
 .../thrift/c_glib/transport/thrift_ssl_socket.h |  16 +-
 lib/c_glib/test/CMakeLists.txt                  |   2 +
 lib/c_glib/test/testbufferedtransport.c         | 318 +++++++------
 lib/c_glib/test/testframedtransport.c           | 311 +++++++------
 lib/c_glib/test/testtransportsocket.c           | 312 +++++++------
 lib/c_glib/test/testtransportsslsocket.c        | 462 +++++++++----------
 test/c_glib/Makefile.am                         |   2 +
 test/c_glib/src/test_client.c                   |   2 +-
 test/c_glib/src/test_server.c                   |  71 ++-
 test/c_glib/src/thrift_second_service_handler.c |  82 ++++
 test/c_glib/src/thrift_second_service_handler.h |  73 +++
 test/features/tests.json                        |   2 -
 test/tests.json                                 |   6 +
 24 files changed, 1896 insertions(+), 797 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/thrift/blob/87ad2bca/lib/c_glib/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/lib/c_glib/CMakeLists.txt b/lib/c_glib/CMakeLists.txt
index 5e277f0..3743a68 100644
--- a/lib/c_glib/CMakeLists.txt
+++ b/lib/c_glib/CMakeLists.txt
@@ -33,9 +33,12 @@ set(thrift_c_glib_SOURCES
     src/thrift/c_glib/thrift_application_exception.c
     src/thrift/c_glib/processor/thrift_processor.c
     src/thrift/c_glib/processor/thrift_dispatch_processor.c
+    src/thrift/c_glib/processor/thrift_multiplexed_processor.c
     src/thrift/c_glib/protocol/thrift_protocol.c
     src/thrift/c_glib/protocol/thrift_protocol_factory.c
+    src/thrift/c_glib/protocol/thrift_protocol_decorator.c
     src/thrift/c_glib/protocol/thrift_binary_protocol.c
+    src/thrift/c_glib/protocol/thrift_stored_message_protocol.c
     src/thrift/c_glib/protocol/thrift_binary_protocol_factory.c
     src/thrift/c_glib/protocol/thrift_compact_protocol.c
     src/thrift/c_glib/protocol/thrift_compact_protocol_factory.c

http://git-wip-us.apache.org/repos/asf/thrift/blob/87ad2bca/lib/c_glib/Makefile.am
----------------------------------------------------------------------
diff --git a/lib/c_glib/Makefile.am b/lib/c_glib/Makefile.am
index 871766b..49b5b23 100755
--- a/lib/c_glib/Makefile.am
+++ b/lib/c_glib/Makefile.am
@@ -34,10 +34,12 @@ libthrift_c_glib_la_SOURCES = src/thrift/c_glib/thrift.c \
                               src/thrift/c_glib/thrift_application_exception.c \
                               src/thrift/c_glib/processor/thrift_processor.c \
                               src/thrift/c_glib/processor/thrift_dispatch_processor.c \
+                              src/thrift/c_glib/processor/thrift_multiplexed_processor.c \
                               src/thrift/c_glib/protocol/thrift_protocol.c \
                               src/thrift/c_glib/protocol/thrift_protocol_decorator.c \
                               src/thrift/c_glib/protocol/thrift_protocol_factory.c \
                               src/thrift/c_glib/protocol/thrift_binary_protocol.c \
+                              src/thrift/c_glib/protocol/thrift_stored_message_protocol.c \
                               src/thrift/c_glib/protocol/thrift_multiplexed_protocol.c \
                               src/thrift/c_glib/protocol/thrift_binary_protocol_factory.c \
                               src/thrift/c_glib/protocol/thrift_compact_protocol.c \
@@ -75,7 +77,9 @@ include_protocol_HEADERS = src/thrift/c_glib/protocol/thrift_protocol.h \
                            src/thrift/c_glib/protocol/thrift_binary_protocol_factory.h \
                            src/thrift/c_glib/protocol/thrift_compact_protocol.h \
                            src/thrift/c_glib/protocol/thrift_compact_protocol_factory.h \
-                           src/thrift/c_glib/protocol/thrift_multiplexed_protocol.h 
+                           src/thrift/c_glib/protocol/thrift_multiplexed_protocol.h \
+                           src/thrift/c_glib/protocol/thrift_stored_message_protocol.h
+                           
 
 include_transportdir = $(include_thriftdir)/transport
 include_transport_HEADERS = src/thrift/c_glib/transport/thrift_buffered_transport.h \
@@ -98,7 +102,8 @@ include_server_HEADERS = src/thrift/c_glib/server/thrift_server.h \
 
 include_processordir = $(include_thriftdir)/processor
 include_processor_HEADERS = src/thrift/c_glib/processor/thrift_processor.h \
-                            src/thrift/c_glib/processor/thrift_dispatch_processor.h
+                            src/thrift/c_glib/processor/thrift_dispatch_processor.h \
+                            src/thrift/c_glib/processor/thrift_multiplexed_processor.h
 
 
 EXTRA_DIST = \

http://git-wip-us.apache.org/repos/asf/thrift/blob/87ad2bca/lib/c_glib/src/thrift/c_glib/processor/thrift_multiplexed_processor.c
----------------------------------------------------------------------
diff --git a/lib/c_glib/src/thrift/c_glib/processor/thrift_multiplexed_processor.c b/lib/c_glib/src/thrift/c_glib/processor/thrift_multiplexed_processor.c
new file mode 100644
index 0000000..68a0f4d
--- /dev/null
+++ b/lib/c_glib/src/thrift/c_glib/processor/thrift_multiplexed_processor.c
@@ -0,0 +1,346 @@
+/*
+ * 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.
+ */
+#include <string.h>
+#include <stdio.h>
+
+#include <thrift/c_glib/thrift.h>
+#include <thrift/c_glib/processor/thrift_processor.h>
+#include <thrift/c_glib/processor/thrift_multiplexed_processor.h>
+#include <thrift/c_glib/protocol/thrift_multiplexed_protocol.h>
+#include <thrift/c_glib/protocol/thrift_stored_message_protocol.h>
+#include <thrift/c_glib/thrift_application_exception.h>
+
+G_DEFINE_TYPE(ThriftMultiplexedProcessor, thrift_multiplexed_processor, THRIFT_TYPE_PROCESSOR)
+
+
+enum
+{
+  PROP_THRIFT_MULTIPLEXED_PROCESSOR_DEFAULT_SERVICE_NAME = 1,
+  PROP_THRIFT_MULTIPLEXED_PROCESSOR_END
+};
+
+static GParamSpec *thrift_multiplexed_processor_obj_properties[PROP_THRIFT_MULTIPLEXED_PROCESSOR_END] = { NULL, };
+
+
+static gboolean
+thrift_multiplexed_processor_register_processor_impl(ThriftProcessor *processor, const gchar * multiplexed_processor_name, ThriftProcessor * multiplexed_processor , GError **error)
+{
+  ThriftMultiplexedProcessor *self = THRIFT_MULTIPLEXED_PROCESSOR(processor);
+  g_hash_table_replace(self->multiplexed_services,
+		       g_strdup(multiplexed_processor_name),
+		       g_object_ref (multiplexed_processor));
+
+  /* Make first registered become default */
+  if(!self->default_processor_name){
+      self->default_processor_name = g_strdup(multiplexed_processor_name);
+  }
+  return TRUE;
+}
+
+
+static gboolean
+thrift_multiplexed_processor_process_impl (ThriftProcessor *processor, ThriftProtocol *in,
+					   ThriftProtocol *out, GError **error)
+{
+  gboolean retval = FALSE;
+  gboolean token_error = FALSE;
+  ThriftApplicationException *xception;
+  ThriftStoredMessageProtocol *stored_message_protocol = NULL;
+  ThriftMessageType message_type;
+  ThriftMultiplexedProcessor *self = THRIFT_MULTIPLEXED_PROCESSOR(processor);
+  ThriftProcessor *multiplexed_processor = NULL;
+  ThriftTransport *transport;
+  char *token=NULL;
+  int token_index=0;
+  char *state=NULL;
+  gchar *fname=NULL;
+  gint32 seqid, result;
+
+  /* FIXME It seems that previous processor is not managing error correctly */
+  if(*error!=NULL) {
+      g_debug ("thrift_multiplexed_processor: last error not removed: %s",
+      		   *error != NULL ? (*error)->message : "(null)");
+      g_clear_error (error);
+  }
+
+
+  THRIFT_PROTOCOL_GET_CLASS(in)->read_message_begin(in, &fname, &message_type, &seqid, error);
+
+  if(!(message_type == T_CALL || message_type == T_ONEWAY)) {
+      g_set_error (error,
+		   THRIFT_MULTIPLEXED_PROCESSOR_ERROR,
+		   THRIFT_MULTIPLEXED_PROCESSOR_ERROR_MESSAGE_TYPE,
+		   "message type invalid for this processor");
+  }else{
+      /* Split by the token */
+      for (token = strtok_r(fname, THRIFT_MULTIPLEXED_PROTOCOL_DEFAULT_SEPARATOR, &state),
+	  token_index=0;
+	  token != NULL && !token_error;
+	  token = strtok_r(NULL, THRIFT_MULTIPLEXED_PROTOCOL_DEFAULT_SEPARATOR, &state),
+	      token_index++)
+	{
+	  switch(token_index){
+	    case 0:
+	      /* It should be the service name */
+	      multiplexed_processor = g_hash_table_lookup(self->multiplexed_services, token);
+	      if(multiplexed_processor==NULL){
+		  token_error=TRUE;
+	      }
+	      break;
+	    case 1:
+	      /* It should be the function name */
+	      stored_message_protocol = g_object_new (THRIFT_TYPE_STORED_MESSAGE_PROTOCOL,
+						      "protocol", in,
+						      "name", token,
+						      "type", message_type,
+						      "seqid", seqid,
+						      NULL);
+	      break;
+	    default:
+	      g_set_error (error,
+			   THRIFT_MULTIPLEXED_PROCESSOR_ERROR,
+			   THRIFT_MULTIPLEXED_PROCESSOR_ERROR_MESSAGE_WRONGLY_MULTIPLEXED,
+			   "the message has more tokens than expected!");
+	      token_error=TRUE;
+	      break;
+	  }
+	}
+      /* Set default */
+      if(!stored_message_protocol &&
+	  !multiplexed_processor &&
+	  token_index==1 && self->default_processor_name){
+	  /* It should be the service name */
+	  multiplexed_processor = g_hash_table_lookup(self->multiplexed_services, self->default_processor_name);
+	  if(multiplexed_processor==NULL){
+	      g_set_error (error,
+			   THRIFT_MULTIPLEXED_PROCESSOR_ERROR,
+			   THRIFT_MULTIPLEXED_PROCESSOR_ERROR_SERVICE_UNAVAILABLE,
+			   "service %s not available on this processor",
+			   self->default_processor_name);
+	  }else{
+	      /* Set the message name to the original name */
+	      stored_message_protocol = g_object_new (THRIFT_TYPE_STORED_MESSAGE_PROTOCOL,
+						      "protocol", in,
+						      "name", fname,
+						      "type", message_type,
+						      "seqid", seqid,
+						      NULL);
+	  }
+
+      }
+
+      if(stored_message_protocol!=NULL && multiplexed_processor!=NULL){
+	  retval = THRIFT_PROCESSOR_GET_CLASS (multiplexed_processor)->process (multiplexed_processor, (ThriftProtocol *) stored_message_protocol, out, error) ;
+      }else{
+	  if(!error)
+	  g_set_error (error,
+		       THRIFT_MULTIPLEXED_PROCESSOR_ERROR,
+		       THRIFT_MULTIPLEXED_PROCESSOR_ERROR_SERVICE_UNAVAILABLE,
+		       "service %s is not multiplexed in this processor",
+		       fname);
+      }
+
+
+  }
+
+  if(!retval){
+      /* By default, return an application exception to the client indicating the
+          method name is not recognized. */
+      /* Copied from dispach processor */
+
+      if ((thrift_protocol_skip (in, T_STRUCT, error) < 0) ||
+	  (thrift_protocol_read_message_end (in, error) < 0))
+	return retval;
+
+      g_object_get (in, "transport", &transport, NULL);
+      result = thrift_transport_read_end (transport, error);
+      g_object_unref (transport);
+      if (result < 0) {
+	  /* We must free fname */
+	  g_free(fname);
+	  return retval;
+      }
+
+      if (thrift_protocol_write_message_begin (out,
+					       fname,
+					       T_EXCEPTION,
+					       seqid,
+					       error) < 0){
+	  /* We must free fname */
+	  g_free(fname);
+
+	  return retval;
+      }
+
+
+      xception =
+	  g_object_new (THRIFT_TYPE_APPLICATION_EXCEPTION,
+			"type",    THRIFT_APPLICATION_EXCEPTION_ERROR_UNKNOWN_METHOD,
+			"message", (*error)->message,
+			NULL);
+      result = thrift_struct_write (THRIFT_STRUCT (xception),
+				    out,
+				    error);
+      g_object_unref (xception);
+      if ((result < 0) ||
+	  (thrift_protocol_write_message_end (out, error) < 0))
+	return retval;
+
+      g_object_get (out, "transport", &transport, NULL);
+      retval =
+	  ((thrift_transport_write_end (transport, error) >= 0) &&
+	      (thrift_transport_flush (transport, error) >= 0));
+      g_object_unref (transport);
+  }else{
+      /* The protocol now has a copy we can free it */
+      g_free(fname);
+
+  }
+
+  /*
+  FIXME This makes everything fail, I don't know why.
+  if(stored_message_protocol!=NULL){
+	  // After its use we must free it
+	  g_object_unref(stored_message_protocol);
+  }
+  */
+  return retval;
+}
+
+/* define the GError domain for Thrift transports */
+GQuark
+thrift_multiplexed_processor_error_quark (void)
+{
+  return g_quark_from_static_string (THRIFT_MULTIPLEXED_PROCESSOR_ERROR_DOMAIN);
+}
+
+
+static void
+thrift_multiplexed_processor_set_property (GObject      *object,
+    guint         property_id,
+    const GValue *value,
+    GParamSpec   *pspec)
+{
+  ThriftMultiplexedProcessor *self = THRIFT_MULTIPLEXED_PROCESSOR (object);
+
+  switch (property_id)
+  {
+  case PROP_THRIFT_MULTIPLEXED_PROCESSOR_DEFAULT_SERVICE_NAME:
+    self->default_processor_name = g_value_dup_string (value);
+    break;
+
+  default:
+    /* We don't have any other property... */
+    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+    break;
+  }
+}
+
+static void
+thrift_multiplexed_processor_get_property (GObject    *object,
+    guint       property_id,
+    GValue     *value,
+    GParamSpec *pspec)
+{
+  ThriftMultiplexedProcessor *self = THRIFT_MULTIPLEXED_PROCESSOR (object);
+
+  switch (property_id)
+  {
+  case PROP_THRIFT_MULTIPLEXED_PROCESSOR_DEFAULT_SERVICE_NAME:
+    g_value_set_string (value, self->default_processor_name);
+    break;
+
+  default:
+    /* We don't have any other property... */
+    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+    break;
+  }
+}
+
+/* destructor */
+static void
+thrift_multiplexed_processor_finalize (GObject *object)
+{
+  ThriftMultiplexedProcessor *self = THRIFT_MULTIPLEXED_PROCESSOR(object);
+
+  /* Free our multiplexed hash table */
+  g_hash_table_unref (self->multiplexed_services);
+  self->multiplexed_services = NULL;
+
+  if(self->default_processor_name){
+      g_free(self->default_processor_name);
+      self->default_processor_name=NULL;
+  }
+
+  /* Chain up to parent */
+  if (G_OBJECT_CLASS (thrift_multiplexed_processor_parent_class)->finalize)
+    (*G_OBJECT_CLASS (thrift_multiplexed_processor_parent_class)->finalize) (object);
+}
+
+/* class initializer for ThriftMultiplexedProcessor */
+static void
+thrift_multiplexed_processor_class_init (ThriftMultiplexedProcessorClass *cls)
+{
+  /* Override */
+  THRIFT_PROCESSOR_CLASS(cls)->process = thrift_multiplexed_processor_process_impl;
+  GObjectClass *gobject_class = G_OBJECT_CLASS (cls);
+
+  /* Object methods */
+  gobject_class->set_property = thrift_multiplexed_processor_set_property;
+  gobject_class->get_property = thrift_multiplexed_processor_get_property;
+  gobject_class->finalize = thrift_multiplexed_processor_finalize;
+
+  /* Class methods */
+  cls->register_processor = thrift_multiplexed_processor_register_processor_impl;
+
+
+  thrift_multiplexed_processor_obj_properties[PROP_THRIFT_MULTIPLEXED_PROCESSOR_DEFAULT_SERVICE_NAME] =
+      g_param_spec_string ("default",
+          "Default service name the protocol points to where no multiplexed client used",
+          "Set the default service name",
+          NULL,
+          (G_PARAM_READWRITE));
+
+  g_object_class_install_properties (gobject_class,
+				     PROP_THRIFT_MULTIPLEXED_PROCESSOR_END,
+      thrift_multiplexed_processor_obj_properties);
+
+}
+
+static void
+thrift_multiplexed_processor_init (ThriftMultiplexedProcessor *self)
+{
+
+  /* Create our multiplexed services hash table */
+  self->multiplexed_services = g_hash_table_new_full (
+      g_str_hash,
+      g_str_equal,
+      g_free,
+      g_object_unref);
+  self->default_processor_name = NULL;
+}
+
+
+gboolean
+thrift_multiplexed_processor_register_processor(ThriftProcessor *processor, const gchar * multiplexed_processor_name, ThriftProcessor * multiplexed_processor , GError **error)
+{
+  return THRIFT_MULTIPLEXED_PROCESSOR_GET_CLASS(processor)->register_processor(processor, multiplexed_processor_name, multiplexed_processor, error);
+}
+
+

http://git-wip-us.apache.org/repos/asf/thrift/blob/87ad2bca/lib/c_glib/src/thrift/c_glib/processor/thrift_multiplexed_processor.h
----------------------------------------------------------------------
diff --git a/lib/c_glib/src/thrift/c_glib/processor/thrift_multiplexed_processor.h b/lib/c_glib/src/thrift/c_glib/processor/thrift_multiplexed_processor.h
new file mode 100644
index 0000000..6406616
--- /dev/null
+++ b/lib/c_glib/src/thrift/c_glib/processor/thrift_multiplexed_processor.h
@@ -0,0 +1,114 @@
+/*
+ * thrift_multiplexed_processor.h
+ *
+ *  Created on: 14 sept. 2017
+ *      Author: gaguilar
+ */
+
+#ifndef _THRIFT_MULTIPLEXED_MULTIPLEXED_PROCESSOR_H_
+#define _THRIFT_MULTIPLEXED_MULTIPLEXED_PROCESSOR_H_
+
+
+#include <glib-object.h>
+
+#include <thrift/c_glib/processor/thrift_processor.h>
+
+
+G_BEGIN_DECLS
+
+/*! \file thrift_multiplexed_processor.h
+ *  \brief The multiplexed processor for c_glib.
+ */
+
+/* type macros */
+#define THRIFT_TYPE_MULTIPLEXED_PROCESSOR (thrift_multiplexed_processor_get_type ())
+#define THRIFT_MULTIPLEXED_PROCESSOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THRIFT_TYPE_MULTIPLEXED_PROCESSOR, ThriftMultiplexedProcessor))
+#define THRIFT_IS_MULTIPLEXED_PROCESSOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THRIFT_TYPE_MULTIPLEXED_PROCESSOR))
+#define THRIFT_MULTIPLEXED_PROCESSOR_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), THRIFT_TYPE_MULTIPLEXED_PROCESSOR, ThriftMultiplexedProcessorClass))
+#define THRIFT_IS_MULTIPLEXED_PROCESSOR_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), THRIFT_TYPE_MULTIPLEXED_PROCESSOR))
+#define THRIFT_MULTIPLEXED_PROCESSOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THRIFT_TYPE_MULTIPLEXED_PROCESSOR, ThriftMultiplexedProcessorClass))
+
+/* define the GError domain string */
+#define THRIFT_MULTIPLEXED_PROCESSOR_ERROR_DOMAIN "thrift-multiplexed-processor-error-quark"
+
+
+/*!
+ * Thrift MultiplexedProcessor object
+ */
+struct _ThriftMultiplexedProcessor
+{
+  ThriftProcessor parent;
+
+  /* private */
+  gchar * default_processor_name;
+  GHashTable *multiplexed_services;
+};
+typedef struct _ThriftMultiplexedProcessor ThriftMultiplexedProcessor;
+
+/*!
+ * Thrift MultiplexedProcessor class
+ */
+struct _ThriftMultiplexedProcessorClass
+{
+  ThriftProcessorClass parent;
+
+  gboolean (* register_processor) (ThriftProcessor *self, const gchar * multiplexed_processor_name, ThriftProcessor * multiplexed_processor , GError **error);
+
+};
+typedef struct _ThriftMultiplexedProcessorClass ThriftMultiplexedProcessorClass;
+
+/* used by THRIFT_TYPE_MULTIPLEXED_PROCESSOR */
+GType thrift_multiplexed_processor_get_type (void);
+
+/*!
+ * Processes the request.
+ * \public \memberof ThriftMultiplexedProcessorClass
+ */
+gboolean thrift_multiplexed_processor_process (ThriftMultiplexedProcessor *processor,
+                                   ThriftProtocol *in, ThriftProtocol *out,
+                                   GError **error);
+
+
+/* Public API */
+
+/**
+ * @brief Registers a processor in the multiplexed processor under its name. It
+ * will take a reference to the processor so refcount will be incremented.
+ * It will also be decremented on object destruction.
+ *
+ * The first registered processor becomes default. But you can override it with
+ * "default" property.
+ *
+ * It returns a compliant error if it cannot be registered.
+ *
+ * @param processor Pointer to the multiplexed processor.
+ * @param multiplexed_processor_name Name of the processor you want to register
+ * @param multiplexed_processor Pointer to implemented processor you want multiplex.
+ * @param error Error object where we should store errors.
+ *
+ * @see https://developer.gnome.org/glib/stable/glib-Error-Reporting.html#g-set-error
+ */
+gboolean thrift_multiplexed_processor_register_processor(ThriftProcessor *processor, const gchar * multiplexed_processor_name, ThriftProcessor * multiplexed_processor , GError **error);
+
+
+/* define error/exception types */
+typedef enum
+{
+  THRIFT_MULTIPLEXED_PROCESSOR_ERROR_UNKNOWN,
+  THRIFT_MULTIPLEXED_PROCESSOR_ERROR_SERVICE_UNAVAILABLE,
+  THRIFT_MULTIPLEXED_PROCESSOR_ERROR_MESSAGE_TYPE,
+  THRIFT_MULTIPLEXED_PROCESSOR_ERROR_MESSAGE_WRONGLY_MULTIPLEXED,
+  THRIFT_MULTIPLEXED_PROCESSOR_ERROR_SEND,
+  THRIFT_MULTIPLEXED_PROCESSOR_ERROR_RECEIVE,
+  THRIFT_MULTIPLEXED_PROCESSOR_ERROR_CLOSE
+} ThriftMultiplexedProcessorError;
+
+
+GQuark thrift_multiplexed_processor_error_quark (void);
+#define THRIFT_MULTIPLEXED_PROCESSOR_ERROR (thrift_multiplexed_processor_error_quark ())
+
+
+G_END_DECLS
+
+
+#endif /* _THRIFT_MULTIPLEXED_MULTIPLEXED_PROCESSOR_H_ */

http://git-wip-us.apache.org/repos/asf/thrift/blob/87ad2bca/lib/c_glib/src/thrift/c_glib/protocol/thrift_multiplexed_protocol.c
----------------------------------------------------------------------
diff --git a/lib/c_glib/src/thrift/c_glib/protocol/thrift_multiplexed_protocol.c b/lib/c_glib/src/thrift/c_glib/protocol/thrift_multiplexed_protocol.c
index c74f048..727f4a8 100644
--- a/lib/c_glib/src/thrift/c_glib/protocol/thrift_multiplexed_protocol.c
+++ b/lib/c_glib/src/thrift/c_glib/protocol/thrift_multiplexed_protocol.c
@@ -57,7 +57,7 @@ thrift_multiplexed_protocol_write_message_begin (ThriftMultiplexedProtocol *prot
     service_name = g_strdup(name);
   }
 
-  // relay to the protocol_decorator
+  /* relay to the protocol_decorator */
   ret = thrift_protocol_decorator_write_message_begin(protocol, service_name, message_type, seqid, error);
 
   g_free(service_name);

http://git-wip-us.apache.org/repos/asf/thrift/blob/87ad2bca/lib/c_glib/src/thrift/c_glib/protocol/thrift_protocol_decorator.c
----------------------------------------------------------------------
diff --git a/lib/c_glib/src/thrift/c_glib/protocol/thrift_protocol_decorator.c b/lib/c_glib/src/thrift/c_glib/protocol/thrift_protocol_decorator.c
index 1feec34..03f9420 100644
--- a/lib/c_glib/src/thrift/c_glib/protocol/thrift_protocol_decorator.c
+++ b/lib/c_glib/src/thrift/c_glib/protocol/thrift_protocol_decorator.c
@@ -486,13 +486,11 @@ thrift_protocol_decorator_set_property (GObject      *object,
     GParamSpec   *pspec)
 {
   ThriftProtocolDecorator *self = THRIFT_PROTOCOL_DECORATOR (object);
-  g_debug("Is protocol decorator %i", THRIFT_IS_PROTOCOL_DECORATOR(object));
 
   switch (property_id)
   {
   case PROP_THRIFT_TYPE_PROTOCOL_DECORATOR_CONCRETE_PROTOCOL:
     self->concrete_protocol = g_value_dup_object (value);
-    g_debug("Setting concrete protocol %p to %p in %s", (void *)self, (void *)self->concrete_protocol, g_type_name(G_TYPE_FROM_INSTANCE(object)));
     break;
 
   default:
@@ -509,7 +507,6 @@ thrift_protocol_decorator_get_property (GObject    *object,
     GParamSpec *pspec)
 {
   ThriftProtocolDecorator *self = THRIFT_PROTOCOL_DECORATOR (object);
-  g_debug("Is protocol decorator %i", THRIFT_IS_PROTOCOL_DECORATOR(object));
 
   switch (property_id)
   {

http://git-wip-us.apache.org/repos/asf/thrift/blob/87ad2bca/lib/c_glib/src/thrift/c_glib/protocol/thrift_stored_message_protocol.c
----------------------------------------------------------------------
diff --git a/lib/c_glib/src/thrift/c_glib/protocol/thrift_stored_message_protocol.c b/lib/c_glib/src/thrift/c_glib/protocol/thrift_stored_message_protocol.c
new file mode 100644
index 0000000..a0d560b
--- /dev/null
+++ b/lib/c_glib/src/thrift/c_glib/protocol/thrift_stored_message_protocol.c
@@ -0,0 +1,192 @@
+/*
+ * 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.
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <glib.h>
+#include <glib-object.h>
+
+#include <thrift/c_glib/thrift.h>
+#include <thrift/c_glib/protocol/thrift_protocol.h>
+#include <thrift/c_glib/protocol/thrift_protocol_decorator.h>
+#include <thrift/c_glib/protocol/thrift_stored_message_protocol.h>
+
+
+enum
+{
+  PROP_THRIFT_STORED_MESSAGE_PROTOCOL_MESSAGE_NAME = 1,
+  PROP_THRIFT_STORED_MESSAGE_PROTOCOL_MESSAGE_TYPE,
+  PROP_THRIFT_STORED_MESSAGE_PROTOCOL_SEQUENCE_ID,
+  PROP_THRIFT_STORED_MESSAGE_PROTOCOL_TRANSPORT, /* TODO ugly hack */
+  PROP_THRIFT_STORED_MESSAGE_PROTOCOL_END
+};
+
+G_DEFINE_TYPE(ThriftStoredMessageProtocol, thrift_stored_message_protocol, THRIFT_TYPE_PROTOCOL_DECORATOR)
+
+
+static GParamSpec *thrift_stored_message_protocol_obj_properties[PROP_THRIFT_STORED_MESSAGE_PROTOCOL_END] = { NULL, };
+
+gint32
+thrift_stored_message_protocol_read_message_begin (ThriftProtocol *protocol,
+					   gchar **name,
+					   ThriftMessageType *message_type,
+					   gint32 *seqid, GError **error)
+{
+  gint32 ret = 0;
+  g_return_val_if_fail (THRIFT_IS_STORED_MESSAGE_PROTOCOL (protocol), -1);
+  THRIFT_UNUSED_VAR (error);
+
+  ThriftStoredMessageProtocol *self = THRIFT_STORED_MESSAGE_PROTOCOL (protocol);
+
+  /* We return the stored values on construction */
+  *name = self->name;
+  *message_type = self->mtype;
+  *seqid = self->seqid;
+
+  return ret;
+}
+
+
+static void
+thrift_stored_message_protocol_set_property (GObject      *object,
+					     guint         property_id,
+					     const GValue *value,
+					     GParamSpec   *pspec)
+{
+  ThriftStoredMessageProtocol *self = THRIFT_STORED_MESSAGE_PROTOCOL (object);
+
+  switch (property_id)
+  {
+    case PROP_THRIFT_STORED_MESSAGE_PROTOCOL_MESSAGE_NAME:
+      self->name = g_value_dup_string (value);
+      break;
+    case PROP_THRIFT_STORED_MESSAGE_PROTOCOL_MESSAGE_TYPE:
+      self->mtype = g_value_get_int (value);
+      break;
+    case PROP_THRIFT_STORED_MESSAGE_PROTOCOL_SEQUENCE_ID:
+      self->seqid = g_value_get_int (value);
+      break;
+
+    default:
+      /* We don't have any other property... */
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+  }
+}
+
+static void
+thrift_stored_message_protocol_get_property (GObject    *object,
+					     guint       property_id,
+					     GValue     *value,
+					     GParamSpec *pspec)
+{
+  ThriftStoredMessageProtocol *self = THRIFT_STORED_MESSAGE_PROTOCOL (object);
+  ThriftProtocolDecorator *decorator = THRIFT_PROTOCOL_DECORATOR (object);
+  ThriftTransport *transport=NULL;
+  switch (property_id)
+  {
+    case PROP_THRIFT_STORED_MESSAGE_PROTOCOL_MESSAGE_NAME:
+      g_value_set_string (value, self->name);
+      break;
+    case PROP_THRIFT_STORED_MESSAGE_PROTOCOL_TRANSPORT:
+      /* FIXME Since we don't override properties in the decorator as it should
+         we just override the properties that we know are used */
+      g_object_get(decorator->concrete_protocol,pspec->name, &transport, NULL);
+      g_value_set_pointer (value, transport);
+      break;
+
+    default:
+      /* We don't have any other property... */
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+  }
+}
+
+
+static void
+thrift_stored_message_protocol_init (ThriftStoredMessageProtocol *protocol)
+{
+  protocol->name = NULL;
+}
+
+static void
+thrift_stored_message_protocol_finalize (GObject *gobject)
+{
+  ThriftStoredMessageProtocol *self = THRIFT_STORED_MESSAGE_PROTOCOL (gobject);
+
+  if (self->name) {
+      g_free(self->name);
+      self->name = NULL;
+  }
+
+  /* Always chain up to the parent class; as with dispose(), finalize()
+   * is guaranteed to exist on the parent's class virtual function table
+   */
+  G_OBJECT_CLASS (thrift_stored_message_protocol_parent_class)->finalize(gobject);
+}
+
+
+/* initialize the class */
+static void
+thrift_stored_message_protocol_class_init (ThriftStoredMessageProtocolClass *klass)
+{
+  ThriftProtocolClass *cls = THRIFT_PROTOCOL_CLASS (klass);
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  cls->read_message_begin = thrift_stored_message_protocol_read_message_begin;
+
+  object_class->set_property = thrift_stored_message_protocol_set_property;
+  object_class->get_property = thrift_stored_message_protocol_get_property;
+  object_class->finalize = thrift_stored_message_protocol_finalize;
+
+  thrift_stored_message_protocol_obj_properties[PROP_THRIFT_STORED_MESSAGE_PROTOCOL_MESSAGE_NAME] =
+      g_param_spec_string ("name",
+			   "Service name the protocol points to",
+			   "Set the service name",
+			   NULL,
+			   (G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
+  thrift_stored_message_protocol_obj_properties[PROP_THRIFT_STORED_MESSAGE_PROTOCOL_MESSAGE_TYPE] =
+      g_param_spec_int ("type",
+			"Message type in the wire",
+			"Set the message type in the wire",
+			T_CALL, T_ONEWAY,
+			T_CALL,
+			(G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
+  thrift_stored_message_protocol_obj_properties[PROP_THRIFT_STORED_MESSAGE_PROTOCOL_SEQUENCE_ID] =
+      g_param_spec_int ("seqid",
+			"Sequence id type in the wire",
+			"Set the Sequence id in the wire",
+			0, G_MAXINT,
+			0,
+			(G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
+
+  /* TODO Ugly hack, in theory we must override all properties from underlaying
+     protocol */
+  thrift_stored_message_protocol_obj_properties[PROP_THRIFT_STORED_MESSAGE_PROTOCOL_TRANSPORT] =
+      g_param_spec_pointer ("transport",
+			"Transport on the underlaying implementation",
+			"Transport of decorated protocol",
+			G_PARAM_READABLE);
+
+
+
+  g_object_class_install_properties (object_class,
+				     PROP_THRIFT_STORED_MESSAGE_PROTOCOL_END,
+				     thrift_stored_message_protocol_obj_properties);
+}

http://git-wip-us.apache.org/repos/asf/thrift/blob/87ad2bca/lib/c_glib/src/thrift/c_glib/protocol/thrift_stored_message_protocol.h
----------------------------------------------------------------------
diff --git a/lib/c_glib/src/thrift/c_glib/protocol/thrift_stored_message_protocol.h b/lib/c_glib/src/thrift/c_glib/protocol/thrift_stored_message_protocol.h
new file mode 100644
index 0000000..88782ac
--- /dev/null
+++ b/lib/c_glib/src/thrift/c_glib/protocol/thrift_stored_message_protocol.h
@@ -0,0 +1,78 @@
+/*
+ * 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.
+ */
+
+#ifndef _THRIFT_STORED_MESSAGE_PROTOCOL_H
+#define _THRIFT_STORED_MESSAGE_PROTOCOL_H
+
+#include <glib-object.h>
+
+#include <thrift/c_glib/protocol/thrift_protocol.h>
+#include <thrift/c_glib/protocol/thrift_protocol_decorator.h>
+#include <thrift/c_glib/transport/thrift_transport.h>
+
+G_BEGIN_DECLS
+
+/*! \file thrift_stored_message_protocol.h
+ *  \brief StoredMessage protocol implementation of a pre-stored message header
+ *  on Thrift protocol.  Implements the ThriftProtocol interface.
+ */
+
+/* type macros */
+#define THRIFT_TYPE_STORED_MESSAGE_PROTOCOL (thrift_stored_message_protocol_get_type ())
+#define THRIFT_STORED_MESSAGE_PROTOCOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THRIFT_TYPE_STORED_MESSAGE_PROTOCOL, ThriftStoredMessageProtocol))
+#define THRIFT_IS_STORED_MESSAGE_PROTOCOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THRIFT_TYPE_STORED_MESSAGE_PROTOCOL))
+#define THRIFT_STORED_MESSAGE_PROTOCOL_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), THRIFT_TYPE_STORED_MESSAGE_PROTOCOL, ThriftStoredMessageProtocolClass))
+#define THRIFT_IS_STORED_MESSAGE_PROTOCOL_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), THRIFT_TYPE_STORED_MESSAGE_PROTOCOL))
+#define THRIFT_STORED_MESSAGE_PROTOCOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THRIFT_TYPE_STORED_MESSAGE_PROTOCOL, ThriftStoredMessageProtocolClass))
+
+/* constant */
+#define THRIFT_STORED_MESSAGE_PROTOCOL_DEFAULT_SEPARATOR ":"
+
+typedef struct _ThriftStoredMessageProtocol ThriftStoredMessageProtocol;
+
+
+
+/*!
+ * Thrift StoredMessage Protocol instance.
+ */
+struct _ThriftStoredMessageProtocol
+{
+  ThriftProtocolDecorator parent;
+
+  gchar *name;
+  ThriftMessageType mtype;
+  gint32 seqid;
+};
+
+typedef struct _ThriftStoredMessageProtocolClass ThriftStoredMessageProtocolClass;
+
+/*!
+ * Thrift StoredMessage Protocol class.
+ */
+struct _ThriftStoredMessageProtocolClass
+{
+  ThriftProtocolDecoratorClass parent;
+};
+
+/* used by THRIFT_TYPE_STORED_MESSAGE_PROTOCOL */
+GType thrift_stored_message_protocol_get_type (void);
+
+G_END_DECLS
+
+#endif /* _THRIFT_STORED_MESSAGE_PROTOCOL_H */

http://git-wip-us.apache.org/repos/asf/thrift/blob/87ad2bca/lib/c_glib/src/thrift/c_glib/transport/thrift_platform_socket.h
----------------------------------------------------------------------
diff --git a/lib/c_glib/src/thrift/c_glib/transport/thrift_platform_socket.h b/lib/c_glib/src/thrift/c_glib/transport/thrift_platform_socket.h
index ef4f00d..ede60f1 100644
--- a/lib/c_glib/src/thrift/c_glib/transport/thrift_platform_socket.h
+++ b/lib/c_glib/src/thrift/c_glib/transport/thrift_platform_socket.h
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-// clang-format off
+/* clang-format off */
 
 #ifndef _THRIFT_TRANSPORT_PLATFORM_SOCKET_H_
 #  define _THRIFT_TRANSPORT_PLATFORM_SOCKET_H_
@@ -63,17 +63,17 @@
 #  define THRIFT_TIMESPEC thrift_timespec
 #  define THRIFT_CTIME_R thrift_ctime_r
 #  define THRIFT_POLL thrift_poll
-#  if WINVER <= 0x0502 //XP, Server2003
+#  if WINVER <= 0x0502 /* XP, Server2003 */
 #    define THRIFT_POLLFD  thrift_pollfd
 #    define THRIFT_POLLIN  0x0300
 #    define THRIFT_POLLOUT 0x0010
-#  else //Vista, Win7...
+#  else /* Vista, Win7... */
 #    define THRIFT_POLLFD  pollfd
 #    define THRIFT_POLLIN  POLLIN
 #    define THRIFT_POLLOUT POLLOUT
-#  endif //WINVER
+#  endif /* WINVER */
 #  define THRIFT_SHUT_RDWR SD_BOTH
-#else //not _WIN32
+#else /* not _WIN32 */
 #  include <errno.h>
 #  define THRIFT_GET_SOCKET_ERROR errno
 #  define THRIFT_ERRNO errno
@@ -117,4 +117,4 @@
 #  define THRIFT_SHUT_RDWR SHUT_RDWR
 #endif
 
-#endif // _THRIFT_TRANSPORT_PLATFORM_SOCKET_H_
+#endif /* _THRIFT_TRANSPORT_PLATFORM_SOCKET_H_ */

http://git-wip-us.apache.org/repos/asf/thrift/blob/87ad2bca/lib/c_glib/src/thrift/c_glib/transport/thrift_socket.c
----------------------------------------------------------------------
diff --git a/lib/c_glib/src/thrift/c_glib/transport/thrift_socket.c b/lib/c_glib/src/thrift/c_glib/transport/thrift_socket.c
index ce6b344..6dd0f0d 100644
--- a/lib/c_glib/src/thrift/c_glib/transport/thrift_socket.c
+++ b/lib/c_glib/src/thrift/c_glib/transport/thrift_socket.c
@@ -95,6 +95,25 @@ thrift_socket_peek (ThriftTransport *transport, GError **error)
   return result;
 }
 
+
+/* implements thrift_transport_close */
+gboolean
+thrift_socket_close (ThriftTransport *transport, GError **error)
+{
+  ThriftSocket *socket = THRIFT_SOCKET (transport);
+
+  if (close (socket->sd) == -1)
+  {
+    g_set_error (error, THRIFT_TRANSPORT_ERROR, THRIFT_TRANSPORT_ERROR_CLOSE,
+                 "unable to close socket - %s",
+                 strerror(errno));
+    return FALSE;
+  }
+
+  socket->sd = THRIFT_INVALID_SOCKET;
+  return TRUE;
+}
+
 /* implements thrift_transport_open */
 gboolean
 thrift_socket_open (ThriftTransport *transport, GError **error)
@@ -128,7 +147,7 @@ thrift_socket_open (ThriftTransport *transport, GError **error)
   /* create a socket structure */
   memset (&pin, 0, sizeof(pin));
   pin.sin_family = AF_INET;
-  pin.sin_addr.s_addr = ((struct in_addr *) (hp->h_addr))->s_addr;
+  pin.sin_addr.s_addr = ((struct in_addr *) (hp->h_addr_list[0]))->s_addr;
   pin.sin_port = htons (tsocket->port);
 
   /* create the socket */
@@ -144,7 +163,8 @@ thrift_socket_open (ThriftTransport *transport, GError **error)
   /* open a connection */
   if (connect (tsocket->sd, (struct sockaddr *) &pin, sizeof(pin)) == -1)
   {
-    g_set_error (error, THRIFT_TRANSPORT_ERROR, THRIFT_TRANSPORT_ERROR_CONNECT,
+      thrift_socket_close(tsocket, NULL);
+      g_set_error (error, THRIFT_TRANSPORT_ERROR, THRIFT_TRANSPORT_ERROR_CONNECT,
                  "failed to connect to host %s:%d - %s",
                  tsocket->hostname, tsocket->port, strerror(errno));
     return FALSE;
@@ -153,23 +173,6 @@ thrift_socket_open (ThriftTransport *transport, GError **error)
   return TRUE;
 }
 
-/* implements thrift_transport_close */
-gboolean
-thrift_socket_close (ThriftTransport *transport, GError **error)
-{
-  ThriftSocket *socket = THRIFT_SOCKET (transport);
-
-  if (close (socket->sd) == -1)
-  {
-    g_set_error (error, THRIFT_TRANSPORT_ERROR, THRIFT_TRANSPORT_ERROR_CLOSE,
-                 "unable to close socket - %s",
-                 strerror(errno));
-    return FALSE;
-  }
-
-  socket->sd = THRIFT_INVALID_SOCKET;
-  return TRUE;
-}
 
 /* implements thrift_transport_read */
 gint32

http://git-wip-us.apache.org/repos/asf/thrift/blob/87ad2bca/lib/c_glib/src/thrift/c_glib/transport/thrift_ssl_socket.c
----------------------------------------------------------------------
diff --git a/lib/c_glib/src/thrift/c_glib/transport/thrift_ssl_socket.c b/lib/c_glib/src/thrift/c_glib/transport/thrift_ssl_socket.c
index 4abeb93..ee55406 100644
--- a/lib/c_glib/src/thrift/c_glib/transport/thrift_ssl_socket.c
+++ b/lib/c_glib/src/thrift/c_glib/transport/thrift_ssl_socket.c
@@ -140,6 +140,84 @@ static void thrift_ssl_socket_dyn_lock_destroy_callback(void* lock, const char*
 G_DEFINE_TYPE(ThriftSSLSocket, thrift_ssl_socket, THRIFT_TYPE_SOCKET)
 
 
+
+/**
+ * When there's a thread context attached, we pass the SSL socket context so it
+ * can check if the error is outside SSL, on I/O for example
+ * @param socket
+ * @param error_msg
+ * @param thrift_error_no
+ * @param ssl_error
+ * @param error
+ */
+static
+void thrift_ssl_socket_get_ssl_error(ThriftSSLSocket *socket, const guchar *error_msg, guint thrift_error_no, int ssl_error, GError **error)
+{
+  unsigned long error_code;
+  char buffer[1024];
+  int buffer_size=1024;
+  gboolean first_error = TRUE;
+  int ssl_error_type = SSL_get_error(socket->ssl, ssl_error);
+  if(ssl_error_type>0){
+      switch(ssl_error_type){
+	case SSL_ERROR_SSL:
+	  buffer_size-=snprintf(buffer, buffer_size, "SSL %s: ", error_msg);
+	  while ((error_code = ERR_get_error()) != 0 && buffer_size>1) {
+	      const char* reason = ERR_reason_error_string(error_code);
+	      if(reason!=NULL){
+		  if(!first_error) {
+		      buffer_size-=snprintf(buffer+(1024-buffer_size), buffer_size, "\n\t");
+		      first_error=FALSE;
+		  }
+		  buffer_size-=snprintf(buffer+(1024-buffer_size), buffer_size, "%lX(%s) -> %s", error_code, reason, SSL_state_string(socket->ssl));
+	      }
+	  }
+	  break;
+	case SSL_ERROR_SYSCALL:
+	  buffer_size-=snprintf(buffer, buffer_size, "%s: ", error_msg);
+	  buffer_size-=snprintf(buffer+(1024-buffer_size), buffer_size, "%lX -> %s", errno, strerror(errno));
+	  break;
+	case SSL_ERROR_WANT_READ:
+	  buffer_size-=snprintf(buffer, buffer_size, "%s: ", error_msg);
+	  buffer_size-=snprintf(buffer+(1024-buffer_size), buffer_size, "%lX -> %s", ssl_error_type, "Error while reading from underlaying layer");
+	  break;
+	case SSL_ERROR_WANT_WRITE:
+	  buffer_size-=snprintf(buffer, buffer_size, "%s: ", error_msg);
+	  buffer_size-=snprintf(buffer+(1024-buffer_size), buffer_size, "%lX -> %s", ssl_error_type, "Error while writting to underlaying layer");
+	  break;
+
+      }
+      g_set_error (error, THRIFT_TRANSPORT_ERROR,
+		   thrift_error_no, "%s", buffer);
+  }
+}
+
+/**
+ * For global SSL errors
+ * @param error_msg
+ * @param thrift_error_no
+ * @param error
+ */
+static
+void thrift_ssl_socket_get_error(const guchar *error_msg, guint thrift_error_no, GError **error)
+{
+  unsigned long error_code;
+  while ((error_code = ERR_get_error()) != 0) {
+      const char* reason = ERR_reason_error_string(error_code);
+      if (reason == NULL) {
+	  g_set_error (error, THRIFT_TRANSPORT_ERROR,
+		       thrift_error_no,
+		       "SSL error %lX: %s", error_code, error_msg);
+      }else{
+	  g_set_error (error, THRIFT_TRANSPORT_ERROR,
+		       thrift_error_no,
+		       "SSL error %lX %s: %s", error_code,reason, error_msg);
+      }
+  }
+}
+
+
+
 /* implements thrift_transport_is_open */
 gboolean
 thrift_ssl_socket_is_open (ThriftTransport *transport)
@@ -159,10 +237,8 @@ thrift_ssl_socket_peek (ThriftTransport *transport, GError **error)
       gchar byte;
       rc = SSL_peek(ssl_socket->ssl, &byte, 1);
       if (rc < 0) {
-	        g_set_error (error,
-		       THRIFT_TRANSPORT_ERROR,
-		       THRIFT_SSL_SOCKET_ERROR_SSL,
-		       "failed to peek at socket - id?");
+	  thrift_ssl_socket_get_ssl_error(ssl_socket, "Check socket data",
+					  THRIFT_SSL_SOCKET_ERROR_SSL, rc, error);
       }
       if (rc == 0) {
 	  ERR_clear_error();
@@ -176,13 +252,14 @@ thrift_ssl_socket_peek (ThriftTransport *transport, GError **error)
 gboolean
 thrift_ssl_socket_open (ThriftTransport *transport, GError **error)
 {
+  ERR_clear_error();
+
   if (!thrift_socket_open(transport, error)) {
       return FALSE;
   }
 
   if (!THRIFT_SSL_SOCKET_GET_CLASS(transport)->handle_handshake(transport, error)) {
-      GError *tmperr;
-      thrift_socket_close(transport, &tmperr);
+      thrift_ssl_socket_close(transport, NULL);
       return FALSE;
   }
 
@@ -194,13 +271,14 @@ gboolean
 thrift_ssl_socket_close (ThriftTransport *transport, GError **error)
 {
   gboolean retval = FALSE;
-  if(THRIFT_SSL_SOCKET(transport)->ssl) {
-      int rc = SSL_shutdown(THRIFT_SSL_SOCKET(transport)->ssl);
-      if (rc < 0) {
+  ThriftSSLSocket *ssl_socket = THRIFT_SSL_SOCKET(transport);
+  if(ssl_socket!=NULL && ssl_socket->ssl) {
+      int rc = SSL_shutdown(ssl_socket->ssl);
+/*      if (rc < 0) {
 	  int errno_copy = THRIFT_SSL_SOCKET_ERROR_SSL;
-      }
-      SSL_free(THRIFT_SSL_SOCKET(transport)->ssl);
-      THRIFT_SSL_SOCKET(transport)->ssl = NULL;
+      }*/
+      SSL_free(ssl_socket->ssl);
+      ssl_socket->ssl = NULL;
       ERR_remove_state(0);
   }
   return thrift_socket_close(transport, error);
@@ -216,9 +294,9 @@ thrift_ssl_socket_read (ThriftTransport *transport, gpointer buf,
   guint bytes = 0;
   guint retries = 0;
   ThriftSocket *socket = THRIFT_SOCKET (transport);
-  g_return_val_if_fail (socket->sd != THRIFT_INVALID_SOCKET, FALSE);
+  g_return_val_if_fail (socket->sd != THRIFT_INVALID_SOCKET && ssl_socket->ssl!=NULL, FALSE);
 
-    for (retries=0; retries < maxRecvRetries_; retries++) {
+  for (retries=0; retries < maxRecvRetries_; retries++) {
       bytes = SSL_read(ssl_socket->ssl, buf, len);
       if (bytes >= 0)
 	break;
@@ -227,10 +305,11 @@ thrift_ssl_socket_read (ThriftTransport *transport, gpointer buf,
 	  if (ERR_get_error() == 0 && errno_copy == THRIFT_EINTR) {
 	      continue;
 	  }
+      }else{
+	  thrift_ssl_socket_get_ssl_error(ssl_socket, "Receive error",
+					  THRIFT_SSL_SOCKET_ERROR_SSL, bytes, error);
+
       }
-      g_set_error (error, THRIFT_TRANSPORT_ERROR,
-		   THRIFT_TRANSPORT_ERROR_RECEIVE,
-		   "failed to read %d bytes - %s", len, strerror(errno));
       return -1;
   }
   return bytes;
@@ -256,16 +335,15 @@ thrift_ssl_socket_write (ThriftTransport *transport, const gpointer buf,
   gint ret = 0;
   guint sent = 0;
   ThriftSocket *socket = THRIFT_SOCKET (transport);
-  g_return_val_if_fail (socket->sd != THRIFT_INVALID_SOCKET, FALSE);
+  g_return_val_if_fail (socket->sd != THRIFT_INVALID_SOCKET && ssl_socket->ssl!=NULL, FALSE);
 
   while (sent < len)
     {
       ret = SSL_write (ssl_socket->ssl, (guint8 *)buf + sent, len - sent);
       if (ret < 0)
 	{
-	  g_set_error (error, THRIFT_TRANSPORT_ERROR,
-		       THRIFT_TRANSPORT_ERROR_SEND,
-		       "failed to send %d bytes - %s", len, strerror(errno));
+	  thrift_ssl_socket_get_ssl_error(ssl_socket, "Send error",
+					  THRIFT_SSL_SOCKET_ERROR_SSL, ret, error);
 	  return FALSE;
 	}
       sent += ret;
@@ -295,7 +373,7 @@ thrift_ssl_socket_flush (ThriftTransport *transport, GError **error)
   guint sent = 0;
 
   ThriftSocket *socket = THRIFT_SOCKET (transport);
-  g_return_val_if_fail (socket->sd != THRIFT_INVALID_SOCKET, FALSE);
+  g_return_val_if_fail (socket->sd != THRIFT_INVALID_SOCKET && ssl_socket->ssl!=NULL, FALSE);
 
   BIO* bio = SSL_get_wbio(ssl_socket->ssl);
   if (bio == NULL) {
@@ -331,8 +409,7 @@ thrift_ssl_socket_handle_handshake(ThriftTransport * transport, GError **error)
 	  rc = SSL_connect(ssl_socket->ssl);
       }
       if (rc <= 0) {
-	  fprintf(stderr,"The error returned was %d\n", SSL_get_error(ssl_socket->ssl, rc));
-	  thrift_ssl_socket_get_error(error, "Not possible to connect", THRIFT_SSL_SOCKET_ERROR_CIPHER_NOT_AVAILABLE);
+	  thrift_ssl_socket_get_ssl_error(ssl_socket, "Error while connect/bind", THRIFT_SSL_SOCKET_ERROR_CONNECT_BIND, rc, error);
 	  return FALSE;
       }
   }else
@@ -390,16 +467,16 @@ gboolean thrift_ssl_load_cert_from_buffer(ThriftSSLSocket *ssl_socket, const cha
   X509_STORE *cert_store = SSL_CTX_get_cert_store(ssl_socket->ctx);
 
   if(cert_store!=NULL){
-    int index = 0;
-    while ((cacert = PEM_read_bio_X509(mem, NULL, 0, NULL))!=NULL) {
-      if(cacert) {
-        X509_STORE_add_cert(cert_store, cacert);
-        X509_free(cacert);
-        cacert=NULL;
-      } /* Free immediately */
-      index++;
-    }
-    retval=TRUE;
+      int index = 0;
+      while ((cacert = PEM_read_bio_X509(mem, NULL, 0, NULL))!=NULL) {
+	  if(cacert) {
+	      X509_STORE_add_cert(cert_store, cacert);
+	      X509_free(cacert);
+	      cacert=NULL;
+	  } /* Free immediately */
+	  index++;
+      }
+      retval=TRUE;
   }
   BIO_free(mem);
   return retval;
@@ -416,46 +493,46 @@ thrift_ssl_socket_authorize(ThriftTransport * transport, GError **error)
   if(cls!=NULL && ssl_socket->ssl!=NULL){
       int rc = SSL_get_verify_result(ssl_socket->ssl);
       if (rc != X509_V_OK) { /* verify authentication result */
-	      if (rc == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT && ssl_socket->allow_selfsigned) {
-	          g_debug("The certificate is a self-signed certificate and configuration allows it");
-	      } else {
-          	g_set_error (error,
-              THRIFT_TRANSPORT_ERROR,
-		          THRIFT_SSL_SOCKET_ERROR_SSL_CERT_VALIDATION_FAILED,
-		          "The certificate verification failed: %s (%d)", X509_verify_cert_error_string(rc), rc);
-	          return FALSE;
-	      }
+	  if (rc == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT && ssl_socket->allow_selfsigned) {
+	      g_debug("The certificate is a self-signed certificate and configuration allows it");
+	  } else {
+	      g_set_error (error,
+			   THRIFT_TRANSPORT_ERROR,
+			   THRIFT_SSL_SOCKET_ERROR_SSL_CERT_VALIDATION_FAILED,
+			   "The certificate verification failed: %s (%d)", X509_verify_cert_error_string(rc), rc);
+	      return FALSE;
+	  }
       }
 
       X509* cert = SSL_get_peer_certificate(ssl_socket->ssl);
       if (cert == NULL) {
-	      if (SSL_get_verify_mode(ssl_socket->ssl) & SSL_VERIFY_FAIL_IF_NO_PEER_CERT) {
-          	g_set_error (error,
-              THRIFT_TRANSPORT_ERROR,
-		          THRIFT_SSL_SOCKET_ERROR_SSL_CERT_VALIDATION_FAILED,
-		          "No certificate present. Are you connecting SSL server?");
-	          return FALSE;
-	      }
-	      g_debug("No certificate required");
-	      return TRUE;
+	  if (SSL_get_verify_mode(ssl_socket->ssl) & SSL_VERIFY_FAIL_IF_NO_PEER_CERT) {
+	      g_set_error (error,
+			   THRIFT_TRANSPORT_ERROR,
+			   THRIFT_SSL_SOCKET_ERROR_SSL_CERT_VALIDATION_FAILED,
+			   "No certificate present. Are you connecting SSL server?");
+	      return FALSE;
+	  }
+	  g_debug("No certificate required");
+	  return TRUE;
       }
 
       /* certificate is present, since we don't support access manager we are done */
       if (cls->authorize_peer == NULL) {
-	      X509_free(cert);
-	      g_debug("Certificate presented but we're not checking it");
-	      return TRUE;
+	  X509_free(cert);
+	  g_debug("Certificate presented but we're not checking it");
+	  return TRUE;
       } else {
-	      /* both certificate and access manager are present */
-	      struct sockaddr_storage sa;
-	      socklen_t saLength = sizeof(struct sockaddr_storage);
-        if (getpeername(socket->sd, (struct sockaddr*)&sa, &saLength) != 0) {
-            sa.ss_family = AF_UNSPEC;
-        }
-	      authorization_result = cls->authorize_peer(transport, cert, &sa, error);
+	  /* both certificate and access manager are present */
+	  struct sockaddr_storage sa;
+	  socklen_t saLength = sizeof(struct sockaddr_storage);
+	  if (getpeername(socket->sd, (struct sockaddr*)&sa, &saLength) != 0) {
+	      sa.ss_family = AF_UNSPEC;
+	  }
+	  authorization_result = cls->authorize_peer(transport, cert, &sa, error);
       }
       if(cert != NULL) {
-        X509_free(cert);
+	  X509_free(cert);
       }
   }
 
@@ -499,8 +576,8 @@ thrift_ssl_socket_finalize (GObject *object)
       if(socket->ctx!=NULL){
 	  g_debug("Freeing the context for the instance");
 	  SSL_CTX_free(socket->ctx);
+	  socket->ctx=NULL;
       }
-      socket->ctx=NULL;
   }
 
   if (G_OBJECT_CLASS (thrift_ssl_socket_parent_class)->finalize)
@@ -538,7 +615,7 @@ thrift_ssl_socket_set_property (GObject *object, guint property_id,
 	  g_debug("Freeing the context since we are setting a new one");
 	  SSL_CTX_free(socket->ctx);
       }
-      socket->ctx = g_value_get_pointer(value); // We copy the context
+      socket->ctx = g_value_get_pointer(value); /* We copy the context */
       break;
 
     case PROP_THRIFT_SSL_SELF_SIGNED:
@@ -664,7 +741,7 @@ thrift_ssl_socket_new_with_host(ThriftSSLSocketProtocol ssl_protocol, gchar *hos
   SSL_CTX *ssl_context = NULL;
   /* Create the context */
   if((ssl_context=thrift_ssl_socket_context_initialize(ssl_protocol, error))==NULL){
-      // FIXME Do error control
+      /* FIXME Do error control */
       return thriftSSLSocket;
   }
   /* FIXME if the protocol is different? */
@@ -712,35 +789,18 @@ thrift_ssl_socket_context_initialize(ThriftSSLSocketProtocol ssl_protocol, GErro
   }
 
   if (context == NULL) {
-      thrift_ssl_socket_get_error(error, "No cipher overlay", THRIFT_SSL_SOCKET_ERROR_CIPHER_NOT_AVAILABLE);
+      thrift_ssl_socket_get_error("No cipher overlay", THRIFT_SSL_SOCKET_ERROR_CIPHER_NOT_AVAILABLE, error);
       return NULL;
   }
   SSL_CTX_set_mode(context, SSL_MODE_AUTO_RETRY);
 
-  // Disable horribly insecure SSLv2 and SSLv3 protocols but allow a handshake
-  // with older clients so they get a graceful denial.
+  /* Disable horribly insecure SSLv2 and SSLv3 protocols but allow a handshake
+     with older clients so they get a graceful denial. */
   if (ssl_protocol == SSLTLS) {
       SSL_CTX_set_options(context, SSL_OP_NO_SSLv2);
-      SSL_CTX_set_options(context, SSL_OP_NO_SSLv3);   // THRIFT-3164
+      SSL_CTX_set_options(context, SSL_OP_NO_SSLv3);   /* THRIFT-3164 */
   }
 
   return context;
 }
 
-void thrift_ssl_socket_get_error(GError **error, const guchar *error_msg, guint thrift_error_no)
-{
-  unsigned long error_code;
-  while ((error_code = ERR_get_error()) != 0) {
-      const char* reason = ERR_reason_error_string(error_code);
-      if (reason == NULL) {
-	  g_set_error (error, THRIFT_TRANSPORT_ERROR,
-		       thrift_error_no,
-		       "SSL error %lX: %s", error_code, error_msg);
-      }else{
-	  g_set_error (error, THRIFT_TRANSPORT_ERROR,
-		       thrift_error_no,
-		       "SSL error %lX %s: %s", error_code,reason, error_msg);
-      }
-  }
-}
-

http://git-wip-us.apache.org/repos/asf/thrift/blob/87ad2bca/lib/c_glib/src/thrift/c_glib/transport/thrift_ssl_socket.h
----------------------------------------------------------------------
diff --git a/lib/c_glib/src/thrift/c_glib/transport/thrift_ssl_socket.h b/lib/c_glib/src/thrift/c_glib/transport/thrift_ssl_socket.h
index 659c88d..0ca465a 100644
--- a/lib/c_glib/src/thrift/c_glib/transport/thrift_ssl_socket.h
+++ b/lib/c_glib/src/thrift/c_glib/transport/thrift_ssl_socket.h
@@ -53,6 +53,7 @@ G_BEGIN_DECLS
 typedef enum
 {
   THRIFT_SSL_SOCKET_ERROR_TRANSPORT=7,
+  THRIFT_SSL_SOCKET_ERROR_CONNECT_BIND,
   THRIFT_SSL_SOCKET_ERROR_CIPHER_NOT_AVAILABLE,
   THRIFT_SSL_SOCKET_ERROR_SSL,
   THRIFT_SSL_SOCKET_ERROR_SSL_CERT_VALIDATION_FAILED
@@ -117,21 +118,6 @@ GType thrift_ssl_socket_get_type (void);
 /* Public API */
 
 /**
- * @brief Returns a error message for a defined error code.
- *
- * It uses gobject error functionality to get the error code of the last error
- * produced by this API.
- *
- * @param error Pointer to the error message.
- * @param error_msg Adds this message to the error that will be added to the
- * code.
- * @param thrift_error_no number of the error triggered.
- *
- * @see https://developer.gnome.org/glib/stable/glib-Error-Reporting.html#g-set-error
- */
-void thrift_ssl_socket_get_error(GError **error, const guchar *error_msg, guint thrift_error_no);
-
-/**
  * @brief Set a pinning manager instead of the default one.
  *
  * The pinning manager will be used during the SSL handshake to check certificate

http://git-wip-us.apache.org/repos/asf/thrift/blob/87ad2bca/lib/c_glib/test/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/lib/c_glib/test/CMakeLists.txt b/lib/c_glib/test/CMakeLists.txt
index 2c87dbc..fb3e41c 100644
--- a/lib/c_glib/test/CMakeLists.txt
+++ b/lib/c_glib/test/CMakeLists.txt
@@ -111,6 +111,8 @@ include_directories("${PROJECT_SOURCE_DIR}/test/c_glib/src" "${CMAKE_CURRENT_BIN
 add_executable(testthrifttest testthrifttest.c
     ${PROJECT_SOURCE_DIR}/test/c_glib/src/thrift_test_handler.c
     ${PROJECT_SOURCE_DIR}/test/c_glib/src/thrift_test_handler.h
+    ${PROJECT_SOURCE_DIR}/test/c_glib/src/thrift_second_service_handler.c
+    ${PROJECT_SOURCE_DIR}/test/c_glib/src/thrift_second_service_handler.h
     gen-c_glib/t_test_thrift_test_types.h)
 target_link_libraries(testthrifttest testgenc)
 add_test(NAME testthrifttest COMMAND testthrifttest)

http://git-wip-us.apache.org/repos/asf/thrift/blob/87ad2bca/lib/c_glib/test/testbufferedtransport.c
----------------------------------------------------------------------
diff --git a/lib/c_glib/test/testbufferedtransport.c b/lib/c_glib/test/testbufferedtransport.c
index 1c15ef2..c6e6b58 100755
--- a/lib/c_glib/test/testbufferedtransport.c
+++ b/lib/c_glib/test/testbufferedtransport.c
@@ -31,6 +31,7 @@
 #include "../src/thrift/c_glib/transport/thrift_buffered_transport.c"
 
 static void thrift_server (const int port);
+static void thrift_socket_server_open (const int port, int times);
 
 /* test object creation and destruction */
 static void
@@ -44,8 +45,8 @@ test_create_and_destroy(void)
   object = g_object_new (THRIFT_TYPE_BUFFERED_TRANSPORT, NULL);
   g_assert (object != NULL);
   g_object_get (G_OBJECT (object), "transport", &transport,
-                "r_buf_size", &r_buf_size,
-                "w_buf_size", &w_buf_size, NULL);
+		"r_buf_size", &r_buf_size,
+		"w_buf_size", &w_buf_size, NULL);
   g_object_unref (object);
 }
 
@@ -55,35 +56,52 @@ test_open_and_close(void)
   ThriftSocket *tsocket = NULL;
   ThriftTransport *transport = NULL;
   GError *err = NULL;
+  pid_t pid;
+  int port = 51199;
+  int status;
 
-  /* create a ThriftSocket */
-  tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost",
-                          "port", 51188, NULL); 
-
-  /* create a BufferedTransport wrapper of the Socket */
-  transport = g_object_new (THRIFT_TYPE_BUFFERED_TRANSPORT,
-                            "transport", THRIFT_TRANSPORT (tsocket), NULL);
-
-  /* this shouldn't work */
-  g_assert (thrift_buffered_transport_open (transport, NULL) == FALSE);
-  g_assert (thrift_buffered_transport_is_open (transport) == TRUE);
-  g_assert (thrift_buffered_transport_close (transport, NULL) == TRUE);
-  g_object_unref (transport);
-  g_object_unref (tsocket);
-
-  /* try and underlying socket failure */
-  tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost.broken",
-                          NULL);
-
-  /* create a BufferedTransport wrapper of the Socket */
-  transport = g_object_new (THRIFT_TYPE_BUFFERED_TRANSPORT,
-                            "transport", THRIFT_TRANSPORT (tsocket), NULL);
+  pid = fork ();
+  g_assert ( pid >= 0 );
 
-  g_assert (thrift_buffered_transport_open (transport, &err) == FALSE);
-  g_object_unref (transport);
-  g_object_unref (tsocket);
-  g_error_free (err);
-  err = NULL;
+  if ( pid == 0 )
+    {
+      /* child listens */
+      thrift_socket_server_open (port,1);
+      exit (0);
+    } else {
+	/* parent connects, wait a bit for the socket to be created */
+	sleep (1);
+	/* create a ThriftSocket */
+	tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost",
+				"port", port, NULL);
+
+	/* create a BufferedTransport wrapper of the Socket */
+	transport = g_object_new (THRIFT_TYPE_BUFFERED_TRANSPORT,
+				  "transport", THRIFT_TRANSPORT (tsocket), NULL);
+
+	/* this shouldn't work */
+	g_assert (thrift_buffered_transport_open (transport, NULL) == TRUE);
+	g_assert (thrift_buffered_transport_is_open (transport) == TRUE);
+	g_assert (thrift_buffered_transport_close (transport, NULL) == TRUE);
+	g_object_unref (transport);
+	g_object_unref (tsocket);
+
+	/* try and underlying socket failure */
+	tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost.broken",
+				NULL);
+
+	/* create a BufferedTransport wrapper of the Socket */
+	transport = g_object_new (THRIFT_TYPE_BUFFERED_TRANSPORT,
+				  "transport", THRIFT_TRANSPORT (tsocket), NULL);
+
+	g_assert (thrift_buffered_transport_open (transport, &err) == FALSE);
+	g_object_unref (transport);
+	g_object_unref (tsocket);
+	g_error_free (err);
+	err = NULL;
+	g_assert ( wait (&status) == pid );
+	g_assert ( status == 0 );
+    }
 }
 
 static void
@@ -100,57 +118,81 @@ test_read_and_write(void)
   g_assert ( pid >= 0 );
 
   if ( pid == 0 )
-  {
-    /* child listens */
-    thrift_server (port);
-    exit (0);
-  } else {
-    /* parent connects, wait a bit for the socket to be created */
-    sleep (1);
-
-    tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost",
-                            "port", port, NULL);
-    transport = g_object_new (THRIFT_TYPE_BUFFERED_TRANSPORT,
-                              "transport", THRIFT_TRANSPORT (tsocket),
-                              "w_buf_size", 4, NULL);
-
-    g_assert (thrift_buffered_transport_open (transport, NULL) == TRUE);
-    g_assert (thrift_buffered_transport_is_open (transport));
-
-    /* write 10 bytes */
-    thrift_buffered_transport_write (transport, buf, 10, NULL);
-
-    /* write 1 byte at a time */
-    thrift_buffered_transport_write (transport, buf, 1, NULL);
-    thrift_buffered_transport_write (transport, buf, 1, NULL);
-    thrift_buffered_transport_write (transport, buf, 1, NULL);
-
-    /* overflow the buffer */
-    thrift_buffered_transport_write (transport, buf, 2, NULL);
-    thrift_buffered_transport_write (transport, buf, 1, NULL);
-    thrift_buffered_transport_flush (transport, NULL);
-
-    /* write 1 byte and flush */
-    thrift_buffered_transport_write (transport, buf, 1, NULL);
-    thrift_buffered_transport_flush (transport, NULL);
-
-    /* write and overflow buffer with 2 system calls */
-    thrift_buffered_transport_write (transport, buf, 1, NULL);
-    thrift_buffered_transport_write (transport, buf, 3, NULL);
-
-    /* write 10 bytes */
-    thrift_buffered_transport_write (transport, buf, 10, NULL);
-
-    thrift_buffered_transport_write_end (transport, NULL);
-    thrift_buffered_transport_flush (transport, NULL);
-    thrift_buffered_transport_close (transport, NULL);
-
-    g_object_unref (transport);
-    g_object_unref (tsocket);
-
-    g_assert ( wait (&status) == pid );
-    g_assert ( status == 0 );
+    {
+      /* child listens */
+      thrift_server (port);
+      exit (0);
+    } else {
+	/* parent connects, wait a bit for the socket to be created */
+	sleep (1);
+
+	tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost",
+				"port", port, NULL);
+	transport = g_object_new (THRIFT_TYPE_BUFFERED_TRANSPORT,
+				  "transport", THRIFT_TRANSPORT (tsocket),
+				  "w_buf_size", 4, NULL);
+
+	g_assert (thrift_buffered_transport_open (transport, NULL) == TRUE);
+	g_assert (thrift_buffered_transport_is_open (transport));
+
+	/* write 10 bytes */
+	thrift_buffered_transport_write (transport, buf, 10, NULL);
+
+	/* write 1 byte at a time */
+	thrift_buffered_transport_write (transport, buf, 1, NULL);
+	thrift_buffered_transport_write (transport, buf, 1, NULL);
+	thrift_buffered_transport_write (transport, buf, 1, NULL);
+
+	/* overflow the buffer */
+	thrift_buffered_transport_write (transport, buf, 2, NULL);
+	thrift_buffered_transport_write (transport, buf, 1, NULL);
+	thrift_buffered_transport_flush (transport, NULL);
+
+	/* write 1 byte and flush */
+	thrift_buffered_transport_write (transport, buf, 1, NULL);
+	thrift_buffered_transport_flush (transport, NULL);
+
+	/* write and overflow buffer with 2 system calls */
+	thrift_buffered_transport_write (transport, buf, 1, NULL);
+	thrift_buffered_transport_write (transport, buf, 3, NULL);
+
+	/* write 10 bytes */
+	thrift_buffered_transport_write (transport, buf, 10, NULL);
+
+	thrift_buffered_transport_write_end (transport, NULL);
+	thrift_buffered_transport_flush (transport, NULL);
+	thrift_buffered_transport_close (transport, NULL);
+
+	g_object_unref (transport);
+	g_object_unref (tsocket);
+
+	g_assert ( wait (&status) == pid );
+	g_assert ( status == 0 );
+    }
+}
+
+
+static void
+thrift_socket_server_open (const int port, int times)
+{
+  int bytes = 0;
+  ThriftServerTransport *transport = NULL;
+  ThriftTransport *client = NULL;
+  guchar buf[10]; /* a buffer */
+  guchar match[10] = TEST_DATA;
+  int i;
+  ThriftServerSocket *tsocket = g_object_new (THRIFT_TYPE_SERVER_SOCKET,
+					      "port", port, NULL);
+
+  transport = THRIFT_SERVER_TRANSPORT (tsocket);
+  thrift_server_transport_listen (transport, NULL);
+  for(i=0;i<times;i++){
+      client = thrift_server_transport_accept (transport, NULL);
+      g_assert (client != NULL);
+      thrift_socket_close (client, NULL);
+      g_object_unref (client);
   }
+  g_object_unref (tsocket);
 }
 
 static void
@@ -163,15 +205,15 @@ thrift_server (const int port)
   guchar match[10] = TEST_DATA;
 
   ThriftServerSocket *tsocket = g_object_new (THRIFT_TYPE_SERVER_SOCKET,
-                                              "port", port, NULL);
+					      "port", port, NULL);
 
   transport = THRIFT_SERVER_TRANSPORT (tsocket);
   thrift_server_transport_listen (transport, NULL);
 
   /* wrap the client in a BufferedTransport */
   client = g_object_new (THRIFT_TYPE_BUFFERED_TRANSPORT, "transport",
-                         thrift_server_transport_accept (transport, NULL),
-                         "r_buf_size", 5, NULL);
+			 thrift_server_transport_accept (transport, NULL),
+			 "r_buf_size", 5, NULL);
   g_assert (client != NULL);
 
   /* read 10 bytes */
@@ -209,62 +251,62 @@ test_write_fail(void)
   g_assert ( pid >= 0 );
 
   if ( pid == 0 )
-  {
-    /* child listens */
-    ThriftServerTransport *transport = NULL;
-    ThriftTransport *client = NULL;
-
-    ThriftServerSocket *tsocket = g_object_new (THRIFT_TYPE_SERVER_SOCKET,
-        "port", port, NULL);
-
-    transport = THRIFT_SERVER_TRANSPORT (tsocket);
-    thrift_server_transport_listen (transport, NULL);
-
-    /* wrap the client in a BufferedTransport */
-    client = g_object_new (THRIFT_TYPE_BUFFERED_TRANSPORT, "transport",
-        thrift_server_transport_accept (transport, NULL),
-        "r_buf_size", 5, NULL);
-    g_assert (client != NULL);
-
-    /* just close socket */
-    thrift_buffered_transport_close (client, NULL);
-    g_object_unref (client);
-    g_object_unref (tsocket);
-    exit (0);
-  } else {
-    /* parent connects, wait a bit for the socket to be created */
-    sleep (1);
-
-    tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost",
-                            "port", port, NULL);
-    transport = g_object_new (THRIFT_TYPE_BUFFERED_TRANSPORT,
-                              "transport", THRIFT_TRANSPORT (tsocket),
-                              "w_buf_size", 4, NULL);
-
-
-    g_assert (thrift_buffered_transport_open (transport, NULL) == TRUE);
-    g_assert (thrift_buffered_transport_is_open (transport));
-
-    /* recognize disconnection */
-    sleep(1);
-    g_assert (thrift_buffered_transport_write (transport, buf, 10, NULL) == TRUE);
-    g_assert (thrift_buffered_transport_write (transport, buf, 10, NULL) == FALSE);
-
-    /* write and overflow buffer */
-    g_assert (thrift_buffered_transport_write (transport, buf, 10, NULL) == FALSE);
-
-    /* write 1 and flush */
-    g_assert (thrift_buffered_transport_write (transport, buf, 1, NULL) == TRUE);
-    g_assert (thrift_buffered_transport_flush (transport, NULL) == FALSE);
-
-    thrift_buffered_transport_close (transport, NULL);
-
-    g_object_unref (transport);
-    g_object_unref (tsocket);
-
-    g_assert ( wait (&status) == pid );
-    g_assert ( status == 0 );
-  }
+    {
+      /* child listens */
+      ThriftServerTransport *transport = NULL;
+      ThriftTransport *client = NULL;
+
+      ThriftServerSocket *tsocket = g_object_new (THRIFT_TYPE_SERVER_SOCKET,
+						  "port", port, NULL);
+
+      transport = THRIFT_SERVER_TRANSPORT (tsocket);
+      thrift_server_transport_listen (transport, NULL);
+
+      /* wrap the client in a BufferedTransport */
+      client = g_object_new (THRIFT_TYPE_BUFFERED_TRANSPORT, "transport",
+			     thrift_server_transport_accept (transport, NULL),
+			     "r_buf_size", 5, NULL);
+      g_assert (client != NULL);
+
+      /* just close socket */
+      thrift_buffered_transport_close (client, NULL);
+      g_object_unref (client);
+      g_object_unref (tsocket);
+      exit (0);
+    } else {
+	/* parent connects, wait a bit for the socket to be created */
+	sleep (1);
+
+	tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost",
+				"port", port, NULL);
+	transport = g_object_new (THRIFT_TYPE_BUFFERED_TRANSPORT,
+				  "transport", THRIFT_TRANSPORT (tsocket),
+				  "w_buf_size", 4, NULL);
+
+
+	g_assert (thrift_buffered_transport_open (transport, NULL) == TRUE);
+	g_assert (thrift_buffered_transport_is_open (transport));
+
+	/* recognize disconnection */
+	sleep(1);
+	g_assert (thrift_buffered_transport_write (transport, buf, 10, NULL) == TRUE);
+	g_assert (thrift_buffered_transport_write (transport, buf, 10, NULL) == FALSE);
+
+	/* write and overflow buffer */
+	g_assert (thrift_buffered_transport_write (transport, buf, 10, NULL) == FALSE);
+
+	/* write 1 and flush */
+	g_assert (thrift_buffered_transport_write (transport, buf, 1, NULL) == TRUE);
+	g_assert (thrift_buffered_transport_flush (transport, NULL) == FALSE);
+
+	thrift_buffered_transport_close (transport, NULL);
+
+	g_object_unref (transport);
+	g_object_unref (tsocket);
+
+	g_assert ( wait (&status) == pid );
+	g_assert ( status == 0 );
+    }
 }
 
 int

http://git-wip-us.apache.org/repos/asf/thrift/blob/87ad2bca/lib/c_glib/test/testframedtransport.c
----------------------------------------------------------------------
diff --git a/lib/c_glib/test/testframedtransport.c b/lib/c_glib/test/testframedtransport.c
index 0328737..45397ce 100755
--- a/lib/c_glib/test/testframedtransport.c
+++ b/lib/c_glib/test/testframedtransport.c
@@ -30,6 +30,7 @@
 #include "../src/thrift/c_glib/transport/thrift_framed_transport.c"
 
 static void thrift_server (const int port);
+static void thrift_socket_server_open (const int port, int times);
 
 /* test object creation and destruction */
 static void
@@ -43,8 +44,8 @@ test_create_and_destroy(void)
   object = g_object_new (THRIFT_TYPE_FRAMED_TRANSPORT, NULL);
   g_assert (object != NULL);
   g_object_get (G_OBJECT (object), "transport", &transport,
-                "r_buf_size", &r_buf_size,
-                "w_buf_size", &w_buf_size, NULL);
+		"r_buf_size", &r_buf_size,
+		"w_buf_size", &w_buf_size, NULL);
   g_object_unref (object);
 }
 
@@ -54,35 +55,53 @@ test_open_and_close(void)
   ThriftSocket *tsocket = NULL;
   ThriftTransport *transport = NULL;
   GError *err = NULL;
+  pid_t pid;
+  int port = 51199;
+  int status;
 
-  /* create a ThriftSocket */
-  tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost",
-                          "port", 51188, NULL); 
-
-  /* create a BufferedTransport wrapper of the Socket */
-  transport = g_object_new (THRIFT_TYPE_FRAMED_TRANSPORT,
-                            "transport", THRIFT_TRANSPORT (tsocket), NULL);
-
-  /* this shouldn't work */
-  g_assert (thrift_framed_transport_open (transport, NULL) == FALSE);
-  g_assert (thrift_framed_transport_is_open (transport) == TRUE);
-  g_assert (thrift_framed_transport_close (transport, NULL) == TRUE);
-  g_object_unref (transport);
-  g_object_unref (tsocket);
-
-  /* try and underlying socket failure */
-  tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost.broken",
-                          NULL);
-
-  /* create a BufferedTransport wrapper of the Socket */
-  transport = g_object_new (THRIFT_TYPE_FRAMED_TRANSPORT,
-                            "transport", THRIFT_TRANSPORT (tsocket), NULL);
+  pid = fork ();
+  g_assert ( pid >= 0 );
 
-  g_assert (thrift_framed_transport_open (transport, &err) == FALSE);
-  g_object_unref (transport);
-  g_object_unref (tsocket);
-  g_error_free (err);
-  err = NULL;
+  if ( pid == 0 )
+    {
+      /* child listens */
+      thrift_socket_server_open (port,1);
+      exit (0);
+    } else {
+	/* parent connects, wait a bit for the socket to be created */
+	sleep (1);
+	/* create a ThriftSocket */
+	tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost",
+				"port", port, NULL);
+
+	/* create a BufferedTransport wrapper of the Socket */
+	transport = g_object_new (THRIFT_TYPE_FRAMED_TRANSPORT,
+				  "transport", THRIFT_TRANSPORT (tsocket), NULL);
+
+	/* this shouldn't work */
+	g_assert (thrift_framed_transport_open (transport, NULL) == TRUE);
+	g_assert (thrift_framed_transport_is_open (transport) == TRUE);
+	g_assert (thrift_framed_transport_close (transport, NULL) == TRUE);
+	g_object_unref (transport);
+	g_object_unref (tsocket);
+
+	/* try and underlying socket failure */
+	tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost.broken",
+				NULL);
+
+	/* create a BufferedTransport wrapper of the Socket */
+	transport = g_object_new (THRIFT_TYPE_FRAMED_TRANSPORT,
+				  "transport", THRIFT_TRANSPORT (tsocket), NULL);
+
+	g_assert (thrift_framed_transport_open (transport, &err) == FALSE);
+	g_object_unref (transport);
+	g_object_unref (tsocket);
+	g_error_free (err);
+	err = NULL;
+
+	g_assert ( wait (&status) == pid );
+	g_assert ( status == 0 );
+    }
 }
 
 static void
@@ -99,46 +118,46 @@ test_read_and_write(void)
   g_assert ( pid >= 0 );
 
   if ( pid == 0 )
-  {
-    /* child listens */
-    thrift_server (port);
-    exit (0);
-  } else {
-    /* parent connects, wait a bit for the socket to be created */
-    sleep (1);
-
-    tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost",
-                            "port", port, NULL);
-    transport = g_object_new (THRIFT_TYPE_FRAMED_TRANSPORT,
-                              "transport", THRIFT_TRANSPORT (tsocket),
-                              "w_buf_size", 4, NULL);
-
-    g_assert (thrift_framed_transport_open (transport, NULL) == TRUE);
-    g_assert (thrift_framed_transport_is_open (transport));
-
-    /* write 10 bytes */
-    thrift_framed_transport_write (transport, buf, 10, NULL);
-    thrift_framed_transport_flush (transport, NULL);
-
-    thrift_framed_transport_write (transport, buf, 1, NULL);
-    thrift_framed_transport_flush (transport, NULL);
-
-    thrift_framed_transport_write (transport, buf, 10, NULL);
-    thrift_framed_transport_flush (transport, NULL);
-
-    thrift_framed_transport_write (transport, buf, 10, NULL);
-    thrift_framed_transport_flush (transport, NULL);
-
-    thrift_framed_transport_write_end (transport, NULL);
-    thrift_framed_transport_flush (transport, NULL);
-    thrift_framed_transport_close (transport, NULL);
-
-    g_object_unref (transport);
-    g_object_unref (tsocket);
-
-    g_assert ( wait (&status) == pid );
-    g_assert ( status == 0 );
-  }
+    {
+      /* child listens */
+      thrift_server (port);
+      exit (0);
+    } else {
+	/* parent connects, wait a bit for the socket to be created */
+	sleep (1);
+
+	tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost",
+				"port", port, NULL);
+	transport = g_object_new (THRIFT_TYPE_FRAMED_TRANSPORT,
+				  "transport", THRIFT_TRANSPORT (tsocket),
+				  "w_buf_size", 4, NULL);
+
+	g_assert (thrift_framed_transport_open (transport, NULL) == TRUE);
+	g_assert (thrift_framed_transport_is_open (transport));
+
+	/* write 10 bytes */
+	thrift_framed_transport_write (transport, buf, 10, NULL);
+	thrift_framed_transport_flush (transport, NULL);
+
+	thrift_framed_transport_write (transport, buf, 1, NULL);
+	thrift_framed_transport_flush (transport, NULL);
+
+	thrift_framed_transport_write (transport, buf, 10, NULL);
+	thrift_framed_transport_flush (transport, NULL);
+
+	thrift_framed_transport_write (transport, buf, 10, NULL);
+	thrift_framed_transport_flush (transport, NULL);
+
+	thrift_framed_transport_write_end (transport, NULL);
+	thrift_framed_transport_flush (transport, NULL);
+	thrift_framed_transport_close (transport, NULL);
+
+	g_object_unref (transport);
+	g_object_unref (tsocket);
+
+	g_assert ( wait (&status) == pid );
+	g_assert ( status == 0 );
+    }
 }
 
 /* test reading from the transport after the peer has unexpectedly
@@ -155,76 +174,100 @@ test_read_after_peer_close(void)
   g_assert (pid >= 0);
 
   if (pid == 0)
-  {
-    ThriftServerTransport *server_transport = NULL;
-    ThriftTransport *client_transport = NULL;
-
-    /* child listens */
-    server_transport = g_object_new (THRIFT_TYPE_SERVER_SOCKET,
-                                     "port", port,
-                                     NULL);
-    g_assert (server_transport != NULL);
-
-    thrift_server_transport_listen (server_transport, &err);
-    g_assert (err == NULL);
-
-    /* wrap the client transport in a ThriftFramedTransport */
-    client_transport = g_object_new
-      (THRIFT_TYPE_FRAMED_TRANSPORT,
-       "transport",  thrift_server_transport_accept (server_transport, &err),
-       "r_buf_size", 0,
-       NULL);
-    g_assert (err == NULL);
-    g_assert (client_transport != NULL);
-
-    /* close the connection immediately after the client connects */
-    thrift_transport_close (client_transport, NULL);
-
-    g_object_unref (client_transport);
-    g_object_unref (server_transport);
-
-    exit (0);
-  } else {
-    ThriftSocket *tsocket = NULL;
-    ThriftTransport *transport = NULL;
-    guchar buf[10]; /* a buffer */
-
-    /* parent connects, wait a bit for the socket to be created */
-    sleep (1);
-
-    tsocket = g_object_new (THRIFT_TYPE_SOCKET,
-                            "hostname", "localhost",
-                            "port",     port,
-                            NULL);
-    transport = g_object_new (THRIFT_TYPE_FRAMED_TRANSPORT,
-                              "transport",  THRIFT_TRANSPORT (tsocket),
-                              "w_buf_size", 0,
-                              NULL);
-
-    g_assert (thrift_transport_open (transport, NULL) == TRUE);
-    g_assert (thrift_transport_is_open (transport));
-
-    /* attempting to read from the transport after the peer has closed
+    {
+      ThriftServerTransport *server_transport = NULL;
+      ThriftTransport *client_transport = NULL;
+
+      /* child listens */
+      server_transport = g_object_new (THRIFT_TYPE_SERVER_SOCKET,
+				       "port", port,
+				       NULL);
+      g_assert (server_transport != NULL);
+
+      thrift_server_transport_listen (server_transport, &err);
+      g_assert (err == NULL);
+
+      /* wrap the client transport in a ThriftFramedTransport */
+      client_transport = g_object_new
+	  (THRIFT_TYPE_FRAMED_TRANSPORT,
+	   "transport",  thrift_server_transport_accept (server_transport, &err),
+	   "r_buf_size", 0,
+	   NULL);
+      g_assert (err == NULL);
+      g_assert (client_transport != NULL);
+
+      /* close the connection immediately after the client connects */
+      thrift_transport_close (client_transport, NULL);
+
+      g_object_unref (client_transport);
+      g_object_unref (server_transport);
+
+      exit (0);
+    } else {
+	ThriftSocket *tsocket = NULL;
+	ThriftTransport *transport = NULL;
+	guchar buf[10]; /* a buffer */
+
+	/* parent connects, wait a bit for the socket to be created */
+	sleep (1);
+
+	tsocket = g_object_new (THRIFT_TYPE_SOCKET,
+				"hostname", "localhost",
+				"port",     port,
+				NULL);
+	transport = g_object_new (THRIFT_TYPE_FRAMED_TRANSPORT,
+				  "transport",  THRIFT_TRANSPORT (tsocket),
+				  "w_buf_size", 0,
+				  NULL);
+
+	g_assert (thrift_transport_open (transport, NULL) == TRUE);
+	g_assert (thrift_transport_is_open (transport));
+
+	/* attempting to read from the transport after the peer has closed
        the connection fails gracefully without generating a critical
        warning or segmentation fault */
-    thrift_transport_read (transport, buf, 10, &err);
-    g_assert (err != NULL);
+	thrift_transport_read (transport, buf, 10, &err);
+	g_assert (err != NULL);
+
+	g_error_free (err);
+	err = NULL;
 
-    g_error_free (err);
-    err = NULL;
+	thrift_transport_read_end (transport, &err);
+	g_assert (err == NULL);
 
-    thrift_transport_read_end (transport, &err);
-    g_assert (err == NULL);
+	thrift_transport_close (transport, &err);
+	g_assert (err == NULL);
 
-    thrift_transport_close (transport, &err);
-    g_assert (err == NULL);
+	g_object_unref (transport);
+	g_object_unref (tsocket);
+
+	g_assert (wait (&status) == pid);
+	g_assert (status == 0);
+    }
+}
+
+static void
+thrift_socket_server_open (const int port, int times)
+{
+  int bytes = 0;
+  ThriftServerTransport *transport = NULL;
+  ThriftTransport *client = NULL;
+  guchar buf[10]; /* a buffer */
+  guchar match[10] = TEST_DATA;
+  int i;
 
-    g_object_unref (transport);
-    g_object_unref (tsocket);
+  ThriftServerSocket *tsocket = g_object_new (THRIFT_TYPE_SERVER_SOCKET,
+					      "port", port, NULL);
 
-    g_assert (wait (&status) == pid);
-    g_assert (status == 0);
+  transport = THRIFT_SERVER_TRANSPORT (tsocket);
+  thrift_server_transport_listen (transport, NULL);
+  for(i=0;i<times;i++){
+      client = thrift_server_transport_accept (transport, NULL);
+      g_assert (client != NULL);
+      thrift_socket_close (client, NULL);
+      g_object_unref (client);
   }
+  g_object_unref (tsocket);
 }
 
 static void
@@ -237,15 +280,15 @@ thrift_server (const int port)
   guchar match[10] = TEST_DATA;
 
   ThriftServerSocket *tsocket = g_object_new (THRIFT_TYPE_SERVER_SOCKET,
-                                              "port", port, NULL);
+					      "port", port, NULL);
 
   transport = THRIFT_SERVER_TRANSPORT (tsocket);
   thrift_server_transport_listen (transport, NULL);
 
   /* wrap the client in a BufferedTransport */
   client = g_object_new (THRIFT_TYPE_FRAMED_TRANSPORT, "transport",
-                         thrift_server_transport_accept (transport, NULL),
-                         "r_buf_size", 5, NULL);
+			 thrift_server_transport_accept (transport, NULL),
+			 "r_buf_size", 5, NULL);
   g_assert (client != NULL);
 
   /* read 10 bytes */