THRIFT-3369 Provide SSL/TLS client for c_glib
Client: c_glib
Patch: Gonzalo Aguilar Delgado <gaguilar@level2crm.com>

This closes #1185
diff --git a/.gitignore b/.gitignore
index 0a98a13..288f1b2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -150,6 +150,7 @@
 /lib/c_glib/test/testframedtransport
 /lib/c_glib/test/testmemorybuffer
 /lib/c_glib/test/testoptionalrequired
+/lib/c_glib/test/testtransportsslsocket
 /lib/c_glib/test/testsimpleserver
 /lib/c_glib/test/teststruct
 /lib/c_glib/test/testthrifttest
@@ -215,6 +216,8 @@
 /lib/haxe/test/bin
 /lib/hs/dist
 /lib/java/build
+/lib/js/dist
+/lib/js/doc
 /lib/js/test/build
 /lib/netcore/**/.vs
 /lib/netcore/**/bin
diff --git a/configure.ac b/configure.ac
index 8a15ede..09c6d9e 100755
--- a/configure.ac
+++ b/configure.ac
@@ -132,7 +132,6 @@
   with_rs="no"
 fi
 
-
 AX_THRIFT_LIB(cpp, [C++], yes)
 have_cpp=no
 if test "$with_cpp" = "yes";  then
@@ -147,8 +146,6 @@
     have_cpp="yes"
   fi
 
-  AX_CHECK_OPENSSL()
-
   AX_LIB_EVENT([1.0])
   have_libevent=$success
 
@@ -199,6 +196,12 @@
 fi
 AM_CONDITIONAL(WITH_C_GLIB, [test "$have_glib2" = "yes" -a "$have_gobject2" = "yes"])
 
+echo "OpenSSL check"
+if test "$have_cpp" = "yes" -o "$have_c_glib" = "yes";  then
+	echo "Have cpp or c so we check for OpenSSL"
+	AX_CHECK_OPENSSL()
+fi
+
 AX_THRIFT_LIB(csharp, [C#], yes)
 if test "$with_csharp" = "yes";  then
   PKG_CHECK_MODULES(MONO, mono >= 2.11.0, mono_2_11=yes, mono_2_11=no)
diff --git a/lib/c_glib/CMakeLists.txt b/lib/c_glib/CMakeLists.txt
index dd9892c..5e277f0 100644
--- a/lib/c_glib/CMakeLists.txt
+++ b/lib/c_glib/CMakeLists.txt
@@ -54,6 +54,17 @@
     src/thrift/c_glib/server/thrift_simple_server.c
 )
 
+# If OpenSSL is not found just ignore the OpenSSL stuff
+find_package(OpenSSL)
+if(OPENSSL_FOUND AND WITH_OPENSSL)
+    list( APPEND thriftcpp_SOURCES
+	    src/thrift/c_glib/transport/thrift_ssl_socket.c
+    )
+    include_directories(SYSTEM "${OPENSSL_INCLUDE_DIR}")
+    list(APPEND SYSLIBS "${OPENSSL_LIBRARIES}")
+endif()
+
+
 # Contains the thrift specific ADD_LIBRARY_THRIFT and TARGET_LINK_LIBRARIES_THRIFT
 include(ThriftMacros)
 
diff --git a/lib/c_glib/Makefile.am b/lib/c_glib/Makefile.am
index 452f6a4..b66c89b 100755
--- a/lib/c_glib/Makefile.am
+++ b/lib/c_glib/Makefile.am
@@ -45,6 +45,7 @@
                               src/thrift/c_glib/transport/thrift_buffered_transport_factory.c \
                               src/thrift/c_glib/transport/thrift_framed_transport_factory.c \
                               src/thrift/c_glib/transport/thrift_socket.c \
+                              src/thrift/c_glib/transport/thrift_ssl_socket.c \
                               src/thrift/c_glib/transport/thrift_server_transport.c \
                               src/thrift/c_glib/transport/thrift_server_socket.c \
                               src/thrift/c_glib/transport/thrift_buffered_transport.c \
@@ -54,7 +55,8 @@
                               src/thrift/c_glib/server/thrift_server.c \
                               src/thrift/c_glib/server/thrift_simple_server.c
 
-libthrift_c_glib_la_CFLAGS = $(AM_CFLAGS) $(GLIB_CFLAGS)
+libthrift_c_glib_la_CFLAGS = $(AM_CFLAGS) $(GLIB_CFLAGS) $(GOBJECT_CFLAGS) $(OPENSSL_INCLUDES)
+libthrift_c_glib_la_LDFLAGS = $(AM_LDFLAGS)  $(OPENSSL_LDFLAGS) $(OPENSSL_LIBS)
 
 include_thriftdir = $(includedir)/thrift/c_glib
 include_thrift_HEADERS = \
@@ -79,6 +81,8 @@
                             src/thrift/c_glib/transport/thrift_server_socket.h \
                             src/thrift/c_glib/transport/thrift_server_transport.h \
                             src/thrift/c_glib/transport/thrift_socket.h \
+                            src/thrift/c_glib/transport/thrift_platform_socket.h \
+                            src/thrift/c_glib/transport/thrift_ssl_socket.h \
                             src/thrift/c_glib/transport/thrift_transport.h \
                             src/thrift/c_glib/transport/thrift_transport_factory.h \
                             src/thrift/c_glib/transport/thrift_buffered_transport_factory.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
new file mode 100644
index 0000000..ef4f00d
--- /dev/null
+++ b/lib/c_glib/src/thrift/c_glib/transport/thrift_platform_socket.h
@@ -0,0 +1,120 @@
+/*
+ * 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.
+ */
+
+// clang-format off
+
+#ifndef _THRIFT_TRANSPORT_PLATFORM_SOCKET_H_
+#  define _THRIFT_TRANSPORT_PLATFORM_SOCKET_H_
+
+#ifdef _WIN32
+#  define THRIFT_GET_SOCKET_ERROR ::WSAGetLastError()
+#  define THRIFT_ERRNO (*_errno())
+#  define THRIFT_EINPROGRESS WSAEINPROGRESS
+#  define THRIFT_EAGAIN WSAEWOULDBLOCK
+#  define THRIFT_EINTR WSAEINTR
+#  define THRIFT_ECONNRESET WSAECONNRESET
+#  define THRIFT_ENOTCONN WSAENOTCONN
+#  define THRIFT_ETIMEDOUT WSAETIMEDOUT
+#  define THRIFT_EWOULDBLOCK WSAEWOULDBLOCK
+#  define THRIFT_EPIPE WSAECONNRESET
+#  define THRIFT_NO_SOCKET_CACHING SO_EXCLUSIVEADDRUSE
+#  define THRIFT_INVALID_SOCKET INVALID_SOCKET
+#  define THRIFT_SOCKETPAIR thrift_socketpair
+#  define THRIFT_FCNTL thrift_fcntl
+#  define THRIFT_O_NONBLOCK 1
+#  define THRIFT_F_GETFL 0
+#  define THRIFT_F_SETFL 1
+#  define THRIFT_GETTIMEOFDAY thrift_gettimeofday
+#  define THRIFT_CLOSESOCKET closesocket
+#  define THRIFT_CLOSE _close
+#  define THRIFT_OPEN _open
+#  define THRIFT_FTRUNCATE _chsize_s
+#  define THRIFT_FSYNC _commit
+#  define THRIFT_LSEEK _lseek
+#  define THRIFT_WRITE _write
+#  define THRIFT_READ _read
+#  define THRIFT_FSTAT _fstat
+#  define THRIFT_STAT _stat
+#  ifdef _WIN32_WCE
+#    define THRIFT_GAI_STRERROR(...) thrift_wstr2str(gai_strerrorW(__VA_ARGS__))
+#  else
+#    define THRIFT_GAI_STRERROR gai_strerrorA
+#  endif
+#  define THRIFT_SSIZET ptrdiff_t
+#  define THRIFT_SNPRINTF _snprintf
+#  define THRIFT_SLEEP_SEC thrift_sleep
+#  define THRIFT_SLEEP_USEC thrift_usleep
+#  define THRIFT_TIMESPEC thrift_timespec
+#  define THRIFT_CTIME_R thrift_ctime_r
+#  define THRIFT_POLL thrift_poll
+#  if WINVER <= 0x0502 //XP, Server2003
+#    define THRIFT_POLLFD  thrift_pollfd
+#    define THRIFT_POLLIN  0x0300
+#    define THRIFT_POLLOUT 0x0010
+#  else //Vista, Win7...
+#    define THRIFT_POLLFD  pollfd
+#    define THRIFT_POLLIN  POLLIN
+#    define THRIFT_POLLOUT POLLOUT
+#  endif //WINVER
+#  define THRIFT_SHUT_RDWR SD_BOTH
+#else //not _WIN32
+#  include <errno.h>
+#  define THRIFT_GET_SOCKET_ERROR errno
+#  define THRIFT_ERRNO errno
+#  define THRIFT_EINTR       EINTR
+#  define THRIFT_EINPROGRESS EINPROGRESS
+#  define THRIFT_ECONNRESET  ECONNRESET
+#  define THRIFT_ENOTCONN    ENOTCONN
+#  define THRIFT_ETIMEDOUT   ETIMEDOUT
+#  define THRIFT_EWOULDBLOCK EWOULDBLOCK
+#  define THRIFT_EAGAIN      EAGAIN
+#  define THRIFT_EPIPE       EPIPE
+#  define THRIFT_NO_SOCKET_CACHING SO_REUSEADDR
+#  define THRIFT_INVALID_SOCKET (-1)
+#  define THRIFT_SOCKETPAIR socketpair
+#  define THRIFT_FCNTL fcntl
+#  define THRIFT_O_NONBLOCK O_NONBLOCK
+#  define THRIFT_F_GETFL F_GETFL
+#  define THRIFT_F_SETFL F_SETFL
+#  define THRIFT_GETTIMEOFDAY gettimeofday
+#  define THRIFT_CLOSESOCKET close
+#  define THRIFT_CLOSE close
+#  define THRIFT_OPEN open
+#  define THRIFT_FTRUNCATE ftruncate
+#  define THRIFT_FSYNC fsync
+#  define THRIFT_LSEEK lseek
+#  define THRIFT_WRITE write
+#  define THRIFT_READ read
+#  define THRIFT_STAT stat
+#  define THRIFT_FSTAT fstat
+#  define THRIFT_GAI_STRERROR gai_strerror
+#  define THRIFT_SSIZET ssize_t
+#  define THRIFT_SNPRINTF snprintf
+#  define THRIFT_SLEEP_SEC sleep
+#  define THRIFT_SLEEP_USEC usleep
+#  define THRIFT_TIMESPEC timespec
+#  define THRIFT_CTIME_R ctime_r
+#  define THRIFT_POLL poll
+#  define THRIFT_POLLFD  pollfd
+#  define THRIFT_POLLIN  POLLIN
+#  define THRIFT_POLLOUT POLLOUT
+#  define THRIFT_SHUT_RDWR SHUT_RDWR
+#endif
+
+#endif // _THRIFT_TRANSPORT_PLATFORM_SOCKET_H_
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
new file mode 100644
index 0000000..f7c42cc
--- /dev/null
+++ b/lib/c_glib/src/thrift/c_glib/transport/thrift_ssl_socket.c
@@ -0,0 +1,770 @@
+/*
+ * 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 <errno.h>
+#include <netdb.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <openssl/ssl.h>
+#include <pthread.h>
+
+#include <thrift/c_glib/thrift.h>
+#include <thrift/c_glib/transport/thrift_transport.h>
+#include <thrift/c_glib/transport/thrift_socket.h>
+#include <thrift/c_glib/transport/thrift_ssl_socket.h>
+
+#if defined(WIN32)
+#define MUTEX_TYPE            HANDLE
+#define MUTEX_SETUP(x)        (x) = CreateMutex(NULL, FALSE, NULL)
+#define MUTEX_CLEANUP(x)      CloseHandle(x)
+#define MUTEX_LOCK(x)         WaitForSingleObject((x), INFINITE)
+#define MUTEX_UNLOCK(x)       ReleaseMutex(x)
+#else
+#define MUTEX_TYPE            pthread_mutex_t
+#define MUTEX_SETUP(x)        pthread_mutex_init(&(x), NULL)
+#define MUTEX_CLEANUP(x)      pthread_mutex_destroy(&(x))
+#define MUTEX_LOCK(x)         pthread_mutex_lock(&(x))
+#define MUTEX_UNLOCK(x)       pthread_mutex_unlock(&(x))
+#endif
+
+#define OPENSSL_VERSION_NO_THREAD_ID 0x10000000L
+
+
+/* object properties */
+enum _ThriftSSLSocketProperties
+{
+  PROP_THRIFT_SSL_SOCKET_CONTEXT = 3,
+  PROP_THRIFT_SSL_SELF_SIGNED
+};
+
+/* To hold a global state management of openssl for all instances */
+static gboolean thrift_ssl_socket_openssl_initialized=FALSE;
+/* Should this be keept at class level? */
+static SSL_CTX* thrift_ssl_socket_global_context=NULL;
+/* This array will store all of the mutexes available to OpenSSL. */
+static MUTEX_TYPE *thrift_ssl_socket_global_mutex_buf=NULL;
+
+
+/**
+ * OpenSSL uniq id function.
+ *
+ * @return    thread id
+ */
+static unsigned long thrift_ssl_socket_static_id_function(void)
+{
+#if defined(WIN32)
+  return GetCurrentThreadId();
+#else
+  return ((unsigned long) pthread_self());
+#endif
+}
+
+static void thrift_ssl_socket_static_locking_callback(int mode, int n, const char* unk, int id) {
+  if (mode & CRYPTO_LOCK)
+    MUTEX_LOCK(thrift_ssl_socket_global_mutex_buf[n]);
+  else
+    MUTEX_UNLOCK(thrift_ssl_socket_global_mutex_buf[n]);
+}
+
+static int thrift_ssl_socket_static_thread_setup(void)
+{
+  int i;
+
+  thrift_ssl_socket_global_mutex_buf = malloc(CRYPTO_num_locks() * sizeof(MUTEX_TYPE));
+  if (!thrift_ssl_socket_global_mutex_buf)
+    return 0;
+  for (i = 0;  i < CRYPTO_num_locks(  );  i++)
+    MUTEX_SETUP(thrift_ssl_socket_global_mutex_buf[i]);
+  CRYPTO_set_id_callback(thrift_ssl_socket_static_id_function);
+  CRYPTO_set_locking_callback(thrift_ssl_socket_static_locking_callback);
+  return 1;
+}
+
+static int thrift_ssl_socket_static_thread_cleanup(void)
+{
+  int i;
+  if (!thrift_ssl_socket_global_mutex_buf)
+    return 0;
+  CRYPTO_set_id_callback(NULL);
+  CRYPTO_set_locking_callback(NULL);
+  for (i = 0;  i < CRYPTO_num_locks(  );  i++)
+    MUTEX_CLEANUP(thrift_ssl_socket_global_mutex_buf[i]);
+  free(thrift_ssl_socket_global_mutex_buf);
+  thrift_ssl_socket_global_mutex_buf = NULL;
+  return 1;
+}
+
+/*
+static void* thrift_ssl_socket_dyn_lock_create_callback(const char* unk, int id) {
+  g_print("We should create a lock\n");
+  return NULL;
+}
+
+static void thrift_ssl_socket_dyn_lock_callback(int mode, void* lock, const char* unk, int id) {
+  if (lock != NULL) {
+    if (mode & CRYPTO_LOCK) {
+      g_printf("We should lock thread %d\n");
+    } else {
+      g_printf("We should unlock thread %d\n");
+    }
+  }
+}
+
+static void thrift_ssl_socket_dyn_lock_destroy_callback(void* lock, const char* unk, int id) {
+  g_printf("We must destroy the lock\n");
+}
+ */
+
+
+G_DEFINE_TYPE(ThriftSSLSocket, thrift_ssl_socket, THRIFT_TYPE_SOCKET)
+
+
+/* implements thrift_transport_is_open */
+gboolean
+thrift_ssl_socket_is_open (ThriftTransport *transport)
+{
+  return thrift_socket_is_open(transport);
+}
+
+/* overrides thrift_transport_peek */
+gboolean
+thrift_ssl_socket_peek (ThriftTransport *transport, GError **error)
+{
+  gboolean retval = FALSE;
+  ThriftSSLSocket *ssl_socket = THRIFT_SSL_SOCKET (transport);
+  if (thrift_ssl_socket_is_open (transport))
+  {
+    int rc;
+    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?");
+    }
+    if (rc == 0) {
+        ERR_clear_error();
+    }
+    retval = (rc > 0);
+  }
+  return retval;
+}
+
+/* implements thrift_transport_open */
+gboolean
+thrift_ssl_socket_open (ThriftTransport *transport, GError **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);
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+/* implements thrift_transport_close */
+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) {
+    int errno_copy = THRIFT_SSL_SOCKET_ERROR_SSL;
+      }
+      SSL_free(THRIFT_SSL_SOCKET(transport)->ssl);
+      THRIFT_SSL_SOCKET(transport)->ssl = NULL;
+      ERR_remove_state(0);
+  }
+  return thrift_socket_close(transport, error);
+}
+
+/* implements thrift_transport_read */
+gint32
+thrift_ssl_socket_read (ThriftTransport *transport, gpointer buf,
+      guint32 len, GError **error)
+{
+  guint maxRecvRetries_ = 10;
+  ThriftSSLSocket *ssl_socket = THRIFT_SSL_SOCKET (transport);
+  guint bytes = 0;
+  guint retries = 0;
+  for (retries=0; retries < maxRecvRetries_; retries++) {
+    bytes = SSL_read(ssl_socket->ssl, buf, len);
+    if (bytes >= 0)
+      break;
+    int errno_copy = THRIFT_GET_SOCKET_ERROR;
+    if (SSL_get_error(ssl_socket->ssl, bytes) == SSL_ERROR_SYSCALL) {
+        if (ERR_get_error() == 0 && errno_copy == THRIFT_EINTR) {
+      continue;
+        }
+    }
+    g_set_error (error, THRIFT_TRANSPORT_ERROR,
+           THRIFT_TRANSPORT_ERROR_RECEIVE,
+           "failed to read %d bytes - %s", len, strerror(errno));
+    return -1;
+  }
+  return bytes;
+}
+
+/* implements thrift_transport_read_end
+ * called when write is complete.  nothing to do on our end. */
+gboolean
+thrift_ssl_socket_read_end (ThriftTransport *transport, GError **error)
+{
+  /* satisfy -Wall */
+  THRIFT_UNUSED_VAR (transport);
+  THRIFT_UNUSED_VAR (error);
+  return TRUE;
+}
+
+/* implements thrift_transport_write */
+gboolean
+thrift_ssl_socket_write (ThriftTransport *transport, const gpointer buf,
+       const guint32 len, GError **error)
+{
+  ThriftSSLSocket *ssl_socket = THRIFT_SSL_SOCKET (transport);
+  gint ret = 0;
+  guint sent = 0;
+  ThriftSocket *socket = THRIFT_SSL_SOCKET (transport);
+  g_return_val_if_fail (socket->sd != THRIFT_INVALID_SOCKET, 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));
+        return FALSE;
+      }
+    sent += ret;
+  }
+
+  return sent==len;
+}
+
+/* implements thrift_transport_write_end
+ * called when write is complete.  nothing to do on our end. */
+gboolean
+thrift_ssl_socket_write_end (ThriftTransport *transport, GError **error)
+{
+  /* satisfy -Wall */
+  THRIFT_UNUSED_VAR (transport);
+  THRIFT_UNUSED_VAR (error);
+  return TRUE;
+}
+
+/* implements thrift_transport_flush
+ * flush pending data.  since we are not buffered, this is a no-op */
+gboolean
+thrift_ssl_socket_flush (ThriftTransport *transport, GError **error)
+{
+  ThriftSSLSocket *ssl_socket = THRIFT_SSL_SOCKET (transport);
+  gint ret = 0;
+  guint sent = 0;
+  BIO* bio = SSL_get_wbio(ssl_socket->ssl);
+  if (bio == NULL) {
+    g_set_error (error, THRIFT_TRANSPORT_ERROR,
+           THRIFT_TRANSPORT_ERROR_SEND,
+           "failed to flush, wbio returned null");
+    return FALSE;
+      }
+      if (BIO_flush(bio) != 1) {
+    g_set_error (error, THRIFT_TRANSPORT_ERROR,
+           THRIFT_TRANSPORT_ERROR_SEND,
+           "failed to flush it returned error");
+    return FALSE;
+  }
+  return TRUE;
+}
+
+
+gboolean
+thrift_ssl_socket_handle_handshake(ThriftTransport * transport, GError **error)
+{
+  ThriftSSLSocket *ssl_socket = THRIFT_SSL_SOCKET (transport);
+  ThriftSocket *socket = THRIFT_SOCKET (transport);
+  g_return_val_if_fail (thrift_transport_is_open (transport), FALSE);
+
+  if(THRIFT_SSL_SOCKET_GET_CLASS(ssl_socket)->create_ssl_context(transport, error)){
+      /*Context created*/
+      SSL_set_fd(ssl_socket->ssl, socket->sd);
+      int rc;
+      if(ssl_socket->server){
+    rc = SSL_accept(ssl_socket->ssl);
+      }else{
+    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);
+    return FALSE;
+      }
+  }else
+    return FALSE;
+
+  return thrift_ssl_socket_authorize(transport, error);
+}
+
+gboolean
+thrift_ssl_socket_create_ssl_context(ThriftTransport * transport, GError **error)
+{
+  ThriftSSLSocket *socket = THRIFT_SSL_SOCKET (transport);
+
+  if(socket->ctx!=NULL){
+      if(socket->ssl!=NULL) {
+    return TRUE;
+      }
+
+      socket->ssl = SSL_new(socket->ctx);
+      if (socket->ssl == NULL) {
+    g_set_error (error, THRIFT_TRANSPORT_ERROR,
+           THRIFT_SSL_SOCKET_ERROR_TRANSPORT,
+           "Unable to create SSL context");
+    return FALSE;
+      }
+  }
+
+  return TRUE;
+}
+
+/**
+ *
+ * @param ssl_socket The ssl socket
+ * @param file_name The file name of the PEM certificate chain
+ * @return
+ */
+gboolean thrift_ssl_load_cert_from_file(ThriftSSLSocket *ssl_socket, const char *file_name)
+{
+  char error_buffer[255];
+  if (!thrift_ssl_socket_openssl_initialized) {
+      g_error("OpenSSL is not initialized yet");
+      return FALSE;
+  }
+  int rc = SSL_CTX_load_verify_locations(ssl_socket->ctx, file_name, NULL);
+  if (rc != 1) { /*verify authentication result*/
+      ERR_error_string_n(ERR_get_error(), error_buffer, 254);
+      g_warning("Load of certificates failed: %s!", error_buffer);
+      return FALSE;
+  }
+  return TRUE;
+}
+
+/**
+ * Load a certificate chain from memory
+ * @param ssl_socket the ssl socket
+ * @param chain_certs the buffer to load PEM from
+ * @return
+ */
+gboolean thrift_ssl_load_cert_from_buffer(ThriftSSLSocket *ssl_socket, const char chain_certs[])
+{
+  gboolean retval = FALSE;
+  /* Load chain of certs*/
+  X509 *cacert=NULL;
+  BIO *mem = BIO_new_mem_buf(chain_certs,strlen(chain_certs));
+  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) {
+        g_debug("Our certificate name is %s", cacert->name);
+        X509_STORE_add_cert(cert_store, cacert);
+        X509_free(cacert);
+        cacert=NULL;
+    } /* Free immediately */
+    index++;
+      }
+      retval=TRUE;
+  }
+  BIO_free(mem);
+  return retval;
+}
+
+gboolean
+thrift_ssl_socket_authorize(ThriftTransport * transport, GError **error)
+{
+  ThriftSocket *socket = THRIFT_SOCKET (transport);
+  ThriftSSLSocket *ssl_socket = THRIFT_SSL_SOCKET (transport);
+  ThriftSSLSocketClass *cls = THRIFT_SSL_SOCKET_GET_CLASS(ssl_socket);
+  gboolean authorization_result = FALSE;
+
+  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_error("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_error("No certificate present");
+        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;
+    } 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);
+    }
+
+    if(cert != NULL) {
+      X509_free(cert);
+    }
+  }
+
+  return authorization_result;
+}
+
+
+/* initializes the instance */
+static void
+thrift_ssl_socket_init (ThriftSSLSocket *socket)
+{
+  GError *error = NULL;
+  socket->ssl = NULL;
+  socket->ctx = thrift_ssl_socket_context_initialize(SSLTLS, &error);
+  if(socket->ctx == NULL) {
+      g_info("The SSL context was not automatically initialized with protocol %d", SSLTLS);
+      if(error!=NULL){
+    g_info("Reported reason %s", error->message);
+    g_error_free (error);
+      }
+  }
+  socket->server = FALSE;
+  socket->allow_selfsigned = FALSE;
+
+}
+
+/* destructor */
+static void
+thrift_ssl_socket_finalize (GObject *object)
+{
+  ThriftSSLSocket *socket = THRIFT_SSL_SOCKET (object);
+  GError *error=NULL;
+  g_debug("Instance %p destroyed",object);
+  if(socket->ssl != NULL)
+    {
+      thrift_ssl_socket_close(THRIFT_TRANSPORT(object), &error);
+      socket->ssl=NULL;
+    }
+
+  if(socket->ctx!=NULL){
+      g_debug("Freeing the context for the instance");
+      SSL_CTX_free(socket->ctx);
+  }
+  socket->ctx=NULL;
+
+
+  if (G_OBJECT_CLASS (thrift_ssl_socket_parent_class)->finalize)
+    (*G_OBJECT_CLASS (thrift_ssl_socket_parent_class)->finalize) (object);
+}
+
+/* property accessor */
+void
+thrift_ssl_socket_get_property (GObject *object, guint property_id,
+        GValue *value, GParamSpec *pspec)
+{
+  ThriftSSLSocket *socket = THRIFT_SSL_SOCKET (object);
+  THRIFT_UNUSED_VAR (pspec);
+
+  switch (property_id)
+  {
+    case PROP_THRIFT_SSL_SOCKET_CONTEXT:
+      g_value_set_pointer (value, socket->ctx);
+      break;
+  }
+}
+
+/* property mutator */
+void
+thrift_ssl_socket_set_property (GObject *object, guint property_id,
+        const GValue *value, GParamSpec *pspec)
+{
+  ThriftSSLSocket *socket = THRIFT_SSL_SOCKET (object);
+
+  THRIFT_UNUSED_VAR (pspec);
+  switch (property_id)
+  {
+    case PROP_THRIFT_SSL_SOCKET_CONTEXT:
+      if(socket->ctx!=NULL){
+    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
+      break;
+
+    case PROP_THRIFT_SSL_SELF_SIGNED:
+      socket->allow_selfsigned = g_value_get_boolean(value);
+      break;
+    default:
+      g_warning("Trying to set property %i that doesn't exists!", property_id);
+      /*    thrift_socket_set_property(object, property_id, value, pspec); */
+      break;
+  }
+}
+
+void
+thrift_ssl_socket_initialize_openssl(void)
+{
+  if(thrift_ssl_socket_openssl_initialized){
+      return;
+  }
+  thrift_ssl_socket_openssl_initialized=TRUE;
+  SSL_library_init();
+  ERR_load_crypto_strings();
+  SSL_load_error_strings();
+  ERR_load_BIO_strings();
+
+  /* Setup locking */
+  g_debug("We setup %d threads locks", thrift_ssl_socket_static_thread_setup());
+
+  /* dynamic locking
+  CRYPTO_set_dynlock_create_callback(thrift_ssl_socket_dyn_lock_create_callback);
+  CRYPTO_set_dynlock_lock_callback(thrift_ssl_socket_dyn_lock_callback);
+  CRYPTO_set_dynlock_destroy_callback(thrift_ssl_socket_dyn_lock_destroy_callback);
+   */
+}
+
+
+void thrift_ssl_socket_finalize_openssl(void)
+{
+
+  /* FIXME This should not be here */
+  if (thrift_ssl_socket_global_context != NULL) {
+      SSL_CTX_free(thrift_ssl_socket_global_context);
+      thrift_ssl_socket_global_context = NULL;
+  }
+
+  if (!thrift_ssl_socket_openssl_initialized) {
+      return;
+  }
+  thrift_ssl_socket_openssl_initialized = FALSE;
+
+  g_debug("We cleared %d threads locks", thrift_ssl_socket_static_thread_cleanup());
+  /* Not supported
+  CRYPTO_set_locking_callback(NULL);
+  CRYPTO_set_dynlock_create_callback(NULL);
+  CRYPTO_set_dynlock_lock_callback(NULL);
+  CRYPTO_set_dynlock_destroy_callback(NULL);
+   */
+  ERR_free_strings();
+  EVP_cleanup();
+  CRYPTO_cleanup_all_ex_data();
+  ERR_remove_state(0);
+}
+
+
+/* initializes the class */
+static void
+thrift_ssl_socket_class_init (ThriftSSLSocketClass *cls)
+{
+  ThriftTransportClass *ttc = THRIFT_TRANSPORT_CLASS (cls);
+  GObjectClass *gobject_class = G_OBJECT_CLASS (cls);
+  GParamSpec *param_spec = NULL;
+
+  g_debug("Initialization of ThriftSSLSocketClass");
+  /* setup accessors and mutators */
+  gobject_class->get_property = thrift_ssl_socket_get_property;
+  gobject_class->set_property = thrift_ssl_socket_set_property;
+  param_spec = g_param_spec_pointer ("ssl_context",
+             "SSLContext",
+             "Set the SSL context for handshake with the remote host",
+             G_PARAM_READWRITE);
+  g_object_class_install_property (gobject_class, PROP_THRIFT_SSL_SOCKET_CONTEXT,
+           param_spec);
+  param_spec = g_param_spec_boolean ("ssl_accept_selfsigned",
+             "Accept Self Signed",
+             "Whether or not accept self signed certificate",
+             FALSE,
+             G_PARAM_READWRITE);
+  g_object_class_install_property (gobject_class, PROP_THRIFT_SSL_SELF_SIGNED,
+           param_spec);
+
+  // This must be supported in future
+  //  param_spec = g_param_spec_uint ("port",
+  //                                  "port (construct)",
+  //                                  "Set the port of the remote host",
+  //                                  0, /* min */
+  //                                  65534, /* max */
+  //                                  9090, /* default by convention */
+  //                                  G_PARAM_CONSTRUCT_ONLY |
+  //                                  G_PARAM_READWRITE);
+  //  g_object_class_install_property (gobject_class, PROP_THRIFT_SSL_SOCKET_PORT,
+  //                                   param_spec);
+
+
+
+  /* Class methods */
+  cls->handle_handshake = thrift_ssl_socket_handle_handshake;
+  cls->create_ssl_context = thrift_ssl_socket_create_ssl_context;
+
+  /* Override */
+  gobject_class->finalize = thrift_ssl_socket_finalize;
+  ttc->is_open = thrift_ssl_socket_is_open;
+  ttc->peek = thrift_ssl_socket_peek;
+  ttc->open = thrift_ssl_socket_open;
+  ttc->close = thrift_ssl_socket_close;
+  ttc->read = thrift_ssl_socket_read;
+  ttc->read_end = thrift_ssl_socket_read_end;
+  ttc->write = thrift_ssl_socket_write;
+  ttc->write_end = thrift_ssl_socket_write_end;
+  ttc->flush = thrift_ssl_socket_flush;
+}
+
+
+/*
+ * Public API
+ */
+ThriftSSLSocket*
+thrift_ssl_socket_new(ThriftSSLSocketProtocol ssl_protocol, GError **error)
+{
+  ThriftSSLSocket *thriftSSLSocket = NULL;
+  /* Create the context */
+  if(thrift_ssl_socket_global_context==NULL){
+      if((thrift_ssl_socket_global_context=thrift_ssl_socket_context_initialize(ssl_protocol, error))==NULL){
+    // FIXME Do error control
+    return thriftSSLSocket;
+      }
+  }
+
+  /* FIXME if the protocol is different? */
+  thriftSSLSocket = g_object_new (THRIFT_TYPE_SSL_SOCKET, "ssl_context", thrift_ssl_socket_global_context, NULL);
+  return thriftSSLSocket;
+}
+
+void thrift_ssl_socket_set_manager(ThriftSSLSocket *ssl_socket, AUTHORIZATION_MANAGER_CALLBACK callback)
+{
+  ThriftSSLSocketClass *sslSocketClass = THRIFT_SSL_SOCKET_GET_CLASS (ssl_socket);
+  if(sslSocketClass){
+      sslSocketClass->authorize_peer = callback;
+  }
+}
+
+
+ThriftSSLSocket*
+thrift_ssl_socket_new_with_host(ThriftSSLSocketProtocol ssl_protocol, gchar *hostname, guint port, GError **error)
+{
+  ThriftSSLSocket *thriftSSLSocket = NULL;
+  /* Create the context */
+  if(thrift_ssl_socket_global_context==NULL){
+      if((thrift_ssl_socket_global_context=thrift_ssl_socket_context_initialize(ssl_protocol, error))==NULL){
+    // FIXME Do error control
+    return thriftSSLSocket;
+      }
+  }
+  /* FIXME if the protocol is different? */
+  thriftSSLSocket = g_object_new (THRIFT_TYPE_SSL_SOCKET, "ssl_context", thrift_ssl_socket_global_context, "hostname", hostname, "port", port, NULL);
+  return thriftSSLSocket;
+}
+
+
+SSL_CTX*
+thrift_ssl_socket_context_initialize(ThriftSSLSocketProtocol ssl_protocol, GError **error)
+{
+  SSL_CTX* context = NULL;
+  switch(ssl_protocol){
+    case SSLTLS:
+      context = SSL_CTX_new(SSLv23_method());
+      break;
+#ifndef OPENSSL_NO_SSL3
+    case SSLv3:
+      context = SSL_CTX_new(SSLv3_method());
+      break;
+#endif
+    case TLSv1_0:
+      context = SSL_CTX_new(TLSv1_method());
+      break;
+    case TLSv1_1:
+      context = SSL_CTX_new(TLSv1_1_method());
+      break;
+    case TLSv1_2:
+      context = SSL_CTX_new(TLSv1_2_method());
+      break;
+    default:
+      g_set_error (error, THRIFT_TRANSPORT_ERROR,
+       THRIFT_SSL_SOCKET_ERROR_CIPHER_NOT_AVAILABLE,
+       "The SSL protocol is unknown for %d", ssl_protocol);
+      return NULL;
+      break;
+  }
+
+  if (context == NULL) {
+      thrift_ssl_socket_get_error(error, "No cipher overlay", THRIFT_SSL_SOCKET_ERROR_CIPHER_NOT_AVAILABLE);
+      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.
+  if (ssl_protocol == SSLTLS) {
+      SSL_CTX_set_options(context, SSL_OP_NO_SSLv2);
+      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);
+      }
+  }
+}
+
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
new file mode 100644
index 0000000..0153495
--- /dev/null
+++ b/lib/c_glib/src/thrift/c_glib/transport/thrift_ssl_socket.h
@@ -0,0 +1,181 @@
+/*
+ * 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_SSL_SOCKET_H
+#define _THRIFT_SSL_SOCKET_H
+
+#include <glib-object.h>
+#include <glib.h>
+#include <openssl/err.h>
+#include <openssl/rand.h>
+#include <openssl/ssl.h>
+#include <openssl/x509v3.h>
+#include <sys/socket.h>
+
+#include <thrift/c_glib/transport/thrift_transport.h>
+#include <thrift/c_glib/transport/thrift_socket.h>
+#include <thrift/c_glib/transport/thrift_platform_socket.h>
+
+G_BEGIN_DECLS
+
+/*! \file thrift_ssl_socket.h
+ *  \brief SSL Socket implementation of a Thrift transport.  Subclasses the
+ *         ThriftSocket class. Based on plain openssl.
+ *         In the future we should take a look to https://issues.apache.org/jira/browse/THRIFT-1016
+ */
+
+/* type macros */
+#define THRIFT_TYPE_SSL_SOCKET (thrift_ssl_socket_get_type ())
+#define THRIFT_SSL_SOCKET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THRIFT_TYPE_SSL_SOCKET, ThriftSSLSocket))
+#define THRIFT_IS_SSL_SOCKET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THRIFT_TYPE_SSL_SOCKET))
+#define THRIFT_SSL_SOCKET_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), THRIFT_TYPE_SSL_SOCKET, ThriftSSLSocketClass))
+#define THRIFT_IS_SSL_SOCKET_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), THRIFT_TYPE_SSL_SOCKET))
+#define THRIFT_SSL_SOCKET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THRIFT_TYPE_SSL_SOCKET, ThriftSSLSocketClass))
+
+
+/* define error/exception types */
+typedef enum
+{
+  THRIFT_SSL_SOCKET_ERROR_TRANSPORT=7,
+  THRIFT_SSL_SOCKET_ERROR_CIPHER_NOT_AVAILABLE,
+  THRIFT_SSL_SOCKET_ERROR_SSL
+} ThriftSSLSocketError;
+
+
+typedef struct _ThriftSSLSocket ThriftSSLSocket;
+
+/*!
+ * Thrift SSL Socket instance.
+ */
+struct _ThriftSSLSocket
+{
+  ThriftSocket parent;
+
+  /* private */
+  SSL *ssl;
+  SSL_CTX* ctx;
+  gboolean server;
+  gboolean allow_selfsigned;
+};
+
+typedef struct _ThriftSSLSocketClass ThriftSSLSocketClass;
+typedef gboolean (* AUTHORIZATION_MANAGER_CALLBACK) (ThriftTransport * transport, X509 *cert, struct sockaddr_storage *addr, GError **error);
+
+/*!
+ * Thrift Socket class.
+ */
+struct _ThriftSSLSocketClass
+{
+  ThriftSocketClass parent;
+
+  gboolean (* handle_handshake) (ThriftTransport * transport, GError **error);
+  gboolean (* create_ssl_context) (ThriftTransport * transport, GError **error);
+  gboolean (* authorize_peer) (ThriftTransport * transport, X509 *cert, struct sockaddr_storage *addr, GError **error);
+
+  /* Padding to allow adding up to 12 new virtual functions without
+   * breaking ABI. */
+  gpointer padding[12];
+};
+
+enum _ThriftSSLSocketProtocol {
+  SSLTLS  = 0,  /* Supports SSLv2 and SSLv3 handshake but only negotiates at TLSv1_0 or later. */
+/*SSLv2   = 1,   HORRIBLY INSECURE! */
+  SSLv3   = 2,  /* Supports SSLv3 only - also horribly insecure! */
+  TLSv1_0 = 3,  /* Supports TLSv1_0 or later. */
+  TLSv1_1 = 4,  /* Supports TLSv1_1 or later. */
+  TLSv1_2 = 5,  /* Supports TLSv1_2 or later. */
+  LATEST  = TLSv1_2
+};
+typedef enum _ThriftSSLSocketProtocol ThriftSSLSocketProtocol;
+
+
+/* Internal functions */
+SSL_CTX*
+thrift_ssl_socket_context_initialize(ThriftSSLSocketProtocol ssl_protocol, GError **error);
+
+
+/* used by THRIFT_TYPE_SSL_SOCKET */
+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
+ * and pinning parameters.
+ *
+ * @param ssl_socket SSL Socket to operate on.
+ * @param callback function that will take the control while validating pinning
+ *
+ */
+void thrift_ssl_socket_set_manager(ThriftSSLSocket *ssl_socket, AUTHORIZATION_MANAGER_CALLBACK callback);
+
+/* This is the SSL API */
+ThriftSSLSocket*
+thrift_ssl_socket_new_with_host(ThriftSSLSocketProtocol ssl_protocol, gchar *hostname, guint port, GError **error);
+ThriftSSLSocket*
+thrift_ssl_socket_new(ThriftSSLSocketProtocol ssl_protocol, GError **error);
+gboolean
+thrift_ssl_load_cert_from_file(ThriftSSLSocket *ssl_socket, const char *file_name);
+gboolean
+thrift_ssl_load_cert_from_buffer(ThriftSSLSocket *ssl_socket, const char chain_certs[]);
+
+/**
+ * @brief Initialization function
+ *
+ * It will initialize OpenSSL function. This initialization will be done app
+ * wide. So if you want to initialize it by yourself you should not call it.
+ * But it means you must handle OpenSSL initialization and handle locking.
+ *
+ * It should be called before anything else.
+ *
+ *
+ */
+void
+thrift_ssl_socket_initialize_openssl(void);
+/**
+ * @brief Finalization function
+ *
+ * It clears all resources initialized in initialize function.
+ *
+ * It should be called after anything else.
+ *
+ *
+ */
+void
+thrift_ssl_socket_finalize_openssl(void);
+
+G_END_DECLS
+#endif
diff --git a/lib/c_glib/test/Makefile.am b/lib/c_glib/test/Makefile.am
index 3dc5418..8c6c48d 100755
--- a/lib/c_glib/test/Makefile.am
+++ b/lib/c_glib/test/Makefile.am
@@ -37,16 +37,17 @@
         gen-c_glib/t_test_thrift_test_types.h
 
 AM_CPPFLAGS = -I../src -I./gen-c_glib
-AM_CFLAGS = -g -Wall -Wextra -pedantic $(GLIB_CFLAGS) $(GOBJECT_CFLAGS) \
+AM_CFLAGS = -g -Wall -Wextra -pedantic $(GLIB_CFLAGS) $(GOBJECT_CFLAGS) $(OPENSSL_INCLUDES) \
 	@GCOV_CFLAGS@
 AM_CXXFLAGS = $(AM_CFLAGS)
-AM_LDFLAGS = $(GLIB_LIBS) $(GOBJECT_LIBS) @GCOV_LDFLAGS@
+AM_LDFLAGS = $(GLIB_LIBS) $(GOBJECT_LIBS) $(OPENSSL_LIBS) @GCOV_LDFLAGS@
 
 check_PROGRAMS = \
   testserialization \
   testapplicationexception \
   testcontainertest \
   testtransportsocket \
+  testtransportsslsocket \
   testbinaryprotocol \
   testcompactprotocol \
   testbufferedtransport \
@@ -100,6 +101,16 @@
     $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_server_transport.o \
     $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_server_socket.o
 
+
+testtransportsslsocket_SOURCES = testtransportsslsocket.c
+testtransportsslsocket_LDADD = \
+    $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_transport.o \
+    $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_socket.o \
+    $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_buffered_transport.o \
+    $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_server_transport.o \
+    $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_server_socket.o
+
+
 testbinaryprotocol_SOURCES = testbinaryprotocol.c
 testbinaryprotocol_LDADD = \
     $(top_builddir)/lib/c_glib/src/thrift/c_glib/protocol/libthrift_c_glib_la-thrift_protocol.o \
diff --git a/lib/c_glib/test/testtransportsslsocket.c b/lib/c_glib/test/testtransportsslsocket.c
new file mode 100644
index 0000000..b4688f9
--- /dev/null
+++ b/lib/c_glib/test/testtransportsslsocket.c
@@ -0,0 +1,581 @@
+/*
+ * 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 <assert.h>
+#include <netdb.h>
+#include <sys/wait.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>
+#include <thrift/c_glib/transport/thrift_server_transport.h>
+#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 { "GET / HTTP/1.1\n\n" }
+
+
+/* substituted functions to test failures of system and library calls */
+static int socket_error = 0;
+int
+my_socket(int domain, int type, int protocol)
+{
+	if (socket_error == 0)
+	{
+		return socket (domain, type, protocol);
+	}
+	return -1;
+}
+
+static int recv_error = 0;
+ssize_t
+my_recv(int socket, void *buffer, size_t length, int flags)
+{
+	if (recv_error == 0)
+	{
+		return recv (socket, buffer, length, flags);
+	}
+	return -1;
+}
+
+static int send_error = 0;
+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 -1;
+}
+
+#define socket my_socket
+#define recv my_recv
+#define send my_send
+#include "../src/thrift/c_glib/transport/thrift_ssl_socket.c"
+#undef socket
+#undef recv
+#undef send
+
+static void thrift_ssl_socket_server (const int port);
+
+/* test object creation and destruction */
+static void
+test_ssl_create_and_destroy(void)
+{
+	gchar *hostname = NULL;
+	guint port = 0;
+
+	GObject *object = NULL;
+	object = g_object_new (THRIFT_TYPE_SSL_SOCKET, NULL);
+	assert (object != NULL);
+	g_object_get (G_OBJECT(object), "hostname", &hostname, "port", &port, NULL);
+	g_free (hostname);
+	g_object_unref (object);
+}
+
+static void
+test_ssl_create_and_set_properties(void)
+{
+	gchar *hostname = NULL;
+	guint port = 0;
+	SSL_CTX* ssl_ctx= NULL;
+	GError *error=NULL;
+
+	GObject *object = NULL;
+	object = thrift_ssl_socket_new(SSLTLS, &error);
+	g_object_get (G_OBJECT(object), "hostname", &hostname, "port", &port, "ssl_context", &ssl_ctx, NULL);
+	assert (ssl_ctx!=NULL);
+
+	g_free (hostname);
+	g_object_unref (object);
+}
+
+static void
+test_ssl_open_and_close(void)
+{
+	ThriftSSLSocket *tSSLSocket = NULL;
+	ThriftTransport *transport = NULL;
+	GError *error=NULL;
+
+	/* open a connection and close it */
+	tSSLSocket = thrift_ssl_socket_new_with_host(SSLTLS, "localhost", 51188, &error);
+
+	transport = THRIFT_TRANSPORT (tSSLSocket);
+	thrift_ssl_socket_open (transport, NULL);
+	assert (thrift_ssl_socket_is_open (transport) == TRUE);
+	thrift_ssl_socket_close (transport, NULL);
+	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", 51188, &error);
+	transport = THRIFT_TRANSPORT (tSSLSocket);
+	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;
+	assert (thrift_ssl_socket_open (transport, &error) == FALSE);
+	socket_error = 0;
+	g_object_unref (tSSLSocket);
+	g_error_free (error);
+}
+
+
+
+/**
+ * Print the common name of certificate
+ */
+unsigned char * get_cn_name(X509_NAME* const name)
+{
+	int idx = -1;
+	unsigned char *utf8 = NULL;
+
+	do
+	{
+		if(!name) 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 */
+
+		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 */
+
+	} while (0);
+	return utf8;
+}
+
+/*
+ * Handle IPV4 and IPV6 addr
+ */
+void *get_in_addr(struct sockaddr *sa)
+{
+	if (sa->sa_family == AF_INET)
+		return &(((struct sockaddr_in*)sa)->sin_addr);
+	return &(((struct sockaddr_in6*)sa)->sin6_addr);
+}
+
+int verify_ip(char * hostname, struct sockaddr_storage *addr)
+{
+	struct addrinfo *addr_info,*p;
+	struct addrinfo hints;
+	int res;
+	int retval = 0;
+
+
+	memset(&hints, 0, sizeof hints);
+	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
+	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
+					}
+				}
+			}
+		}
+	}
+
+	if(addr_info)
+		freeaddrinfo(addr_info);
+
+	return retval;
+}
+
+static void
+read_from_file(char *buffer, long size, const char *file_name)
+{
+	   char ch;
+	   long index=0;
+	   FILE *fp;
+
+	   fp = fopen(file_name,"r"); // read mode
+
+	   if( fp == NULL )
+	   {
+	      perror("Error while opening the file.\n");
+	      exit(EXIT_FAILURE);
+	   }
+
+	   printf("The contents of %s file are :\n", file_name);
+
+	   while(index<size && ( ch = fgetc(fp) ) != EOF ){
+		   buffer[index++] = ch;
+	   }
+
+	   fclose(fp);
+}
+
+#define ISSUER_CN_PINNING "The Apache Software Foundation"
+#define SUBJECT_CN_PINNING "localhost"
+#define CERT_SERIAL_NUMBER "1"
+
+gboolean verify_certificate_sn(X509 *cert, const unsigned char *serial_number)
+{
+	gboolean retval = FALSE;
+
+	ASN1_INTEGER *serial = X509_get_serialNumber(cert);
+
+	BIGNUM *bn = ASN1_INTEGER_to_BN(serial, NULL);
+	if (!bn) {
+		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;
+	}
+//	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;
+	}else{
+		g_warning("Serial number is not valid");
+	}
+
+	BN_free(bn);
+	OPENSSL_free(tmp);
+	return retval;
+}
+
+gboolean my_access_manager(ThriftTransport * transport, X509 *cert, struct sockaddr_storage *addr, GError **error)
+{
+	ThriftSSLSocket *sslSocket = THRIFT_SSL_SOCKET (transport);
+
+	g_info("Processing access to the server");
+	X509_NAME* iname = cert ? X509_get_issuer_name(cert) : NULL;
+	X509_NAME* sname = cert ? X509_get_subject_name(cert) : NULL;
+
+	/* 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);
+
+		// 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;
+
+		// 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;
+
+		// 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(!verify_certificate_sn(cert, CERT_SERIAL_NUMBER)){
+		return FALSE;
+	}else{
+		g_info("Verified serial number");
+	}
+
+	return TRUE;
+
+}
+
+
+
+
+#ifdef BUILD_SERVER
+static void
+test_ssl_authorization_manager(void)
+{
+	int status=0;
+	pid_t pid;
+	ThriftSSLSocket *tSSLsocket = NULL;
+	ThriftTransport *transport = NULL;
+	//  int port = 51199;
+	int port = 443;
+	GError *error=NULL;
+
+	guchar buf[17] = TEST_DATA; /* a buffer */
+
+	//  pid = fork ();
+	//  assert ( pid >= 0 );
+	//
+	//  if ( pid == 0 )
+	//  {
+	//    /* child listens */
+	//    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
+	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");
+	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!");
+	}
+
+	transport = THRIFT_TRANSPORT (tSSLsocket);
+	assert (thrift_ssl_socket_open (transport, NULL) == TRUE);
+	assert (thrift_ssl_socket_is_open (transport));
+
+	thrift_ssl_socket_write (transport, buf, 17, NULL);
+
+	/* 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_close (transport, NULL);
+	g_object_unref (tSSLsocket);
+
+	//    assert ( wait (&status) == pid );
+	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)
+{
+	int bytes = 0;
+	ThriftServerTransport *transport = NULL;
+	ThriftTransport *client = NULL;
+	guchar buf[10]; /* a buffer */
+	guchar match[10] = TEST_DATA;
+
+	ThriftServerSocket *tsocket = g_object_new (THRIFT_TYPE_SERVER_SOCKET,
+			"port", port, NULL);
+
+	transport = THRIFT_SERVER_TRANSPORT (tsocket);
+	thrift_server_transport_listen (transport, NULL);
+	client = thrift_server_transport_accept (transport, NULL);
+	assert (client != NULL);
+
+	/* read 10 bytes */
+	bytes = thrift_ssl_socket_read (client, buf, 10, NULL);
+	assert (bytes == 10); /* make sure we've read 10 bytes */
+	assert ( memcmp(buf, match, 10) == 0 ); /* make sure what we got matches */
+
+	/* failed read */
+	recv_error = 1;
+	thrift_ssl_socket_read (client, buf, 1, NULL);
+	recv_error = 0;
+
+	thrift_ssl_socket_read_end (client, NULL);
+	thrift_ssl_socket_close (client, NULL);
+	g_object_unref (tsocket);
+	g_object_unref (client);
+}
+
+int
+main(int argc, char *argv[])
+{
+	int retval;
+#if (!GLIB_CHECK_VERSION (2, 36, 0))
+	g_type_init();
+#endif
+
+	g_test_init (&argc, &argv, NULL);
+
+	thrift_ssl_socket_initialize_openssl();
+
+	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);
+
+	retval = g_test_run ();
+
+	thrift_ssl_socket_finalize_openssl();
+
+	return retval;
+}
+
diff --git a/lib/py/src/transport/TSSLSocket.py b/lib/py/src/transport/TSSLSocket.py
index 0f7d45e..bf4689a 100644
--- a/lib/py/src/transport/TSSLSocket.py
+++ b/lib/py/src/transport/TSSLSocket.py
@@ -40,10 +40,10 @@
     # ciphers argument is not available for Python < 2.7.0
     _has_ciphers = sys.hexversion >= 0x020700F0
 
-    # For pythoon >= 2.7.9, use latest TLS that both client and server
+    # For python >= 2.7.9, use latest TLS that both client and server
     # supports.
     # SSL 2.0 and 3.0 are disabled via ssl.OP_NO_SSLv2 and ssl.OP_NO_SSLv3.
-    # For pythoon < 2.7.9, use TLS 1.0 since TLSv1_X nor OP_NO_SSLvX is
+    # For python < 2.7.9, use TLS 1.0 since TLSv1_X nor OP_NO_SSLvX is
     # unavailable.
     _default_protocol = ssl.PROTOCOL_SSLv23 if _has_ssl_context else \
         ssl.PROTOCOL_TLSv1
diff --git a/test/c_glib/src/test_client.c b/test/c_glib/src/test_client.c
index 3ae9325..9713e8c 100644
--- a/test/c_glib/src/test_client.c
+++ b/test/c_glib/src/test_client.c
@@ -30,6 +30,7 @@
 #include <thrift/c_glib/protocol/thrift_compact_protocol.h>
 #include <thrift/c_glib/transport/thrift_buffered_transport.h>
 #include <thrift/c_glib/transport/thrift_framed_transport.h>
+#include <thrift/c_glib/transport/thrift_ssl_socket.h>
 #include <thrift/c_glib/transport/thrift_socket.h>
 #include <thrift/c_glib/transport/thrift_transport.h>
 
@@ -75,29 +76,34 @@
 int
 main (int argc, char **argv)
 {
-  static gchar *host = NULL;
-  static gint   port = 9090;
-  static gchar *transport_option = NULL;
-  static gchar *protocol_option = NULL;
-  static gint   num_tests = 1;
+  static gchar *  host = NULL;
+  static gint     port = 9090;
+  static gboolean ssl  = FALSE;
+  static gchar *  transport_option = NULL;
+  static gchar *  protocol_option = NULL;
+  static gint     num_tests = 1;
 
   static
     GOptionEntry option_entries[] ={
-    { "host",            0, 0, G_OPTION_ARG_STRING,   &host,
+    { "host",            'h', 0, G_OPTION_ARG_STRING,   &host,
       "Host to connect (=localhost)", NULL },
-    { "port",            0, 0, G_OPTION_ARG_INT,      &port,
+    { "port",            'p', 0, G_OPTION_ARG_INT,      &port,
       "Port number to connect (=9090)", NULL },
-    { "transport",       0, 0, G_OPTION_ARG_STRING,   &transport_option,
+    { "ssl",             's', 0, G_OPTION_ARG_NONE,     &ssl,
+      "Enable SSL", NULL },
+    { "transport",       't', 0, G_OPTION_ARG_STRING,   &transport_option,
       "Transport: buffered, framed (=buffered)", NULL },
-    { "protocol",        0, 0, G_OPTION_ARG_STRING,   &protocol_option,
+    { "protocol",        'r', 0, G_OPTION_ARG_STRING,   &protocol_option,
       "Protocol: binary, compact (=binary)", NULL },
-    { "testloops",     'n', 0, G_OPTION_ARG_INT,      &num_tests,
+    { "testloops",       'n', 0, G_OPTION_ARG_INT,      &num_tests,
       "Number of tests (=1)", NULL },
     { NULL }
   };
 
   struct sigaction sigpipe_action;
 
+  GType  socket_type    = THRIFT_TYPE_SOCKET;
+  gchar *socket_name    = "ip";
   GType  transport_type = THRIFT_TYPE_BUFFERED_TRANSPORT;
   gchar *transport_name = "buffered";
   GType  protocol_type  = THRIFT_TYPE_BINARY_PROTOCOL;
@@ -164,12 +170,19 @@
     }
   }
 
+  if (ssl) {
+    socket_type = THRIFT_TYPE_SSL_SOCKET;
+    socket_name = "ip-ssl";
+    printf("Type name %s\n", g_type_name (socket_type));
+  }
+
   if (!options_valid)
     return 254;
 
-  printf ("Connecting (%s/%s) to: %s:%d\n",
+  printf ("Connecting (%s/%s) to: %s/%s:%d\n",
           transport_name,
           protocol_name,
+          socket_name,
           host,
           port);
 
@@ -181,11 +194,22 @@
   sigpipe_action.sa_flags = SA_RESETHAND;
   sigaction (SIGPIPE, &sigpipe_action, NULL);
 
+  if (ssl) {
+    thrift_ssl_socket_initialize_openssl();
+  }
+
   /* Establish all our connection objects */
-  socket = g_object_new (THRIFT_TYPE_SOCKET,
+  socket = g_object_new (socket_type,
                          "hostname", host,
                          "port",     port,
                          NULL);
+
+  if (ssl && !thrift_ssl_load_cert_from_file(THRIFT_SSL_SOCKET(socket), "../keys/CA.pem")) {
+    fprintf(stderr, "Unable to load validation certificate ../keys/CA.pem - did you run in the test/c_glib directory?\n");
+    g_object_unref (socket);
+    return 253;
+  }
+
   transport = g_object_new (transport_type,
                             "transport", socket,
                             NULL);
@@ -277,10 +301,11 @@
         printf (" = void\n");
       }
       else {
+  if(error!=NULL){
         printf ("%s\n", error->message);
-        g_error_free (error);
-        error = NULL;
-
+    g_error_free (error);
+    error = NULL;
+  }
         fail_count++;
       }
 
@@ -439,8 +464,8 @@
         fail_count++;
       }
 
-      // TODO: add testBinary() 	  
-	  
+      // TODO: add testBinary()
+
       /**
        * STRUCT TEST
        */
@@ -1575,6 +1600,7 @@
     }
     else {
       printf ("Connect failed: %s\n", error->message);
+      g_object_unref (socket);
       g_error_free (error);
       error = NULL;
 
@@ -1596,5 +1622,9 @@
   g_object_unref (transport);
   g_free (host);
 
+  if (ssl) {
+    thrift_ssl_socket_finalize_openssl();
+  }
+
   return fail_count;
 }
diff --git a/test/known_failures_Linux.json b/test/known_failures_Linux.json
index edf0fbb..4ca2050 100644
--- a/test/known_failures_Linux.json
+++ b/test/known_failures_Linux.json
@@ -11,6 +11,7 @@
   "cpp-cpp_compact_http-ip-ssl",
   "cpp-cpp_header_buffered-ip-ssl",
   "cpp-cpp_header_framed-ip-ssl",
+  "cpp-cpp_header_http-domain",
   "cpp-cpp_header_http-ip-ssl",
   "cpp-cpp_json_buffered-ip-ssl",
   "cpp-cpp_json_framed-ip",
@@ -35,7 +36,10 @@
   "cpp-java_json_http-ip-ssl",
   "cpp-perl_binary_buffered-ip-ssl",
   "cpp-perl_binary_framed-ip-ssl",
-  "cpp-py_binary-accel_framed-ip-ssl",
+  "csharp-c_glib_binary_buffered-ip-ssl",
+  "csharp-c_glib_binary_framed-ip-ssl",
+  "csharp-c_glib_compact_buffered-ip-ssl",
+  "csharp-c_glib_compact_framed-ip-ssl",
   "csharp-cpp_binary_buffered-ip-ssl",
   "csharp-cpp_binary_framed-ip-ssl",
   "csharp-cpp_compact_buffered-ip-ssl",
@@ -101,6 +105,8 @@
   "d-cpp_json_framed-ip-ssl",
   "d-cpp_json_http-ip",
   "d-cpp_json_http-ip-ssl",
+  "d-d_binary_http-ip",
+  "d-d_compact_http-ip",
   "d-dart_binary_framed-ip",
   "d-dart_binary_http-ip",
   "d-dart_compact_framed-ip",
@@ -220,8 +226,6 @@
   "hs-dart_json_framed-ip",
   "hs-py3_json_buffered-ip",
   "hs-py3_json_framed-ip",
-  "hs-py_json_buffered-ip",
-  "hs-py_json_framed-ip",
   "java-d_compact_buffered-ip",
   "java-d_compact_buffered-ip-ssl",
   "java-d_compact_framed-ip",
diff --git a/test/tests.json b/test/tests.json
index 09d4c89..5de36f5 100644
--- a/test/tests.json
+++ b/test/tests.json
@@ -12,6 +12,9 @@
     "client": {
       "command": [
         "test_client"
+      ],
+      "sockets": [
+        "ip-ssl"
       ]
     },
     "transports": [
diff --git a/tutorial/c_glib/Makefile.am b/tutorial/c_glib/Makefile.am
index 565f635..15a9995 100755
--- a/tutorial/c_glib/Makefile.am
+++ b/tutorial/c_glib/Makefile.am
@@ -24,9 +24,9 @@
 	gen-c_glib/shared_types.h \
 	gen-c_glib/tutorial_types.h
 
-AM_CFLAGS = -g -Wall -Wextra -pedantic $(GLIB_CFLAGS) $(GOBJECT_CFLAGS) @GCOV_CFLAGS@
+AM_CFLAGS = -g -Wall -Wextra -pedantic $(GLIB_CFLAGS) $(GOBJECT_CFLAGS) $(OPENSSL_INCLUDES) @GCOV_CFLAGS@
 AM_CPPFLAGS = -I$(top_srcdir)/lib/c_glib/src -Igen-c_glib
-AM_LDFLAGS = $(GLIB_LIBS) $(GOBJECT_LIBS) @GCOV_LDFLAGS@
+AM_LDFLAGS = $(GLIB_LIBS) $(GOBJECT_LIBS) $(OPENSSL_LDFLAGS) $(OPENSSL_LIBS) @GCOV_LDFLAGS@
 
 THRIFT = $(top_builddir)/compiler/cpp/thrift
 
@@ -55,6 +55,7 @@
 
 tutorial_server_SOURCES = \
 	c_glib_server.c
+tutorial_server_LDFLAGS = $(OPENSSL_LIBS)
 
 tutorial_server_LDADD = \
 	libtutorialgencglib.la \