You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@thrift.apache.org by je...@apache.org on 2017/12/03 01:03:04 UTC

[34/50] [abbrv] thrift git commit: THRIFT-4329: multiplexed processor, client and server for c_glib Client: c_glib

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/0.11.0
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 */