Upgrading dependency to Thrift 0.12.0

This commit is contained in:
Renan DelValle 2018-11-27 18:03:50 -08:00
parent 3e4590dcc0
commit 356978cb42
No known key found for this signature in database
GPG key ID: C240AD6D6F443EC9
1302 changed files with 101701 additions and 26784 deletions

View file

@ -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
@ -54,6 +57,17 @@ set(thrift_c_glib_SOURCES
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)

View file

@ -34,9 +34,13 @@ 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 \
src/thrift/c_glib/protocol/thrift_compact_protocol_factory.c \
@ -45,6 +49,7 @@ libthrift_c_glib_la_SOURCES = src/thrift/c_glib/thrift.c \
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 +59,8 @@ libthrift_c_glib_la_SOURCES = src/thrift/c_glib/thrift.c \
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) $(GLIB_LIBS) $(GOBJECT_LIBS) $(OPENSSL_LDFLAGS) $(OPENSSL_LIBS)
include_thriftdir = $(includedir)/thrift/c_glib
include_thrift_HEADERS = \
@ -65,11 +71,15 @@ include_thrift_HEADERS = \
include_protocoldir = $(include_thriftdir)/protocol
include_protocol_HEADERS = src/thrift/c_glib/protocol/thrift_protocol.h \
src/thrift/c_glib/protocol/thrift_protocol_decorator.h \
src/thrift/c_glib/protocol/thrift_protocol_factory.h \
src/thrift/c_glib/protocol/thrift_binary_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_compact_protocol_factory.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 \
@ -79,6 +89,8 @@ include_transport_HEADERS = src/thrift/c_glib/transport/thrift_buffered_transpor
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 \
@ -90,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 = \

View file

@ -32,3 +32,18 @@ Dependencies
GLib
http://www.gtk.org/
Breaking Changes
================
0.12.0
------
The compiler's handling of namespaces when generating the name of types,
functions and header files has been improved. This means code written to use
classes generated by previous versions of the compiler may need to be updated to
reflect the proper convention for class names, which is
- A lowercase, [snake-case](https://en.wikipedia.org/wiki/Snake_case)
representation of the class' namespace, followed by
- An underscore and
- A lowercase, snake-case representation of the class' name.

View file

@ -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);
}

View file

@ -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_ */

View file

@ -784,11 +784,18 @@ thrift_binary_protocol_read_string (ThriftProtocol *protocol,
}
xfer += ret;
if (read_len > 0)
{
/* allocate the memory for the string */
len = (guint32) read_len + 1; /* space for null terminator */
*str = g_new0 (gchar, len);
if (read_len < 0) {
g_set_error (error, THRIFT_PROTOCOL_ERROR,
THRIFT_PROTOCOL_ERROR_NEGATIVE_SIZE,
"got negative size of %d", read_len);
*str = NULL;
return -1;
}
/* allocate the memory for the string */
len = (guint32) read_len + 1; /* space for null terminator */
*str = g_new0 (gchar, len);
if (read_len > 0) {
if ((ret =
thrift_transport_read_all (protocol->transport,
*str, read_len, error)) < 0)
@ -800,7 +807,7 @@ thrift_binary_protocol_read_string (ThriftProtocol *protocol,
}
xfer += ret;
} else {
*str = NULL;
**str = 0;
}
return xfer;

View file

@ -120,7 +120,7 @@ thrift_bitwise_cast_gdouble (const guint64 v)
static guint64
i64_to_zigzag (const gint64 l)
{
return (l << 1) ^ (l >> 63);
return (((guint64)l) << 1) ^ (l >> 63);
}
/**
@ -130,7 +130,7 @@ i64_to_zigzag (const gint64 l)
static guint32
i32_to_zigzag (const gint32 n)
{
return (n << 1) ^ (n >> 31);
return (((guint32)n) << 1) ^ (n >> 31);
}
/**
@ -1388,9 +1388,17 @@ thrift_compact_protocol_read_string (ThriftProtocol *protocol,
return -1;
}
if (read_len < 0) {
g_set_error (error, THRIFT_PROTOCOL_ERROR,
THRIFT_PROTOCOL_ERROR_NEGATIVE_SIZE,
"got negative size of %d", read_len);
*str = NULL;
return -1;
}
/* allocate the memory as an array of unsigned char for binary data */
*str = g_new0 (gchar, read_len + 1);
if (read_len > 0) {
/* allocate the memory as an array of unsigned char for binary data */
*str = g_new0 (gchar, read_len + 1);
if ((ret =
thrift_transport_read_all (protocol->transport,
*str, read_len, error)) < 0) {
@ -1399,16 +1407,8 @@ thrift_compact_protocol_read_string (ThriftProtocol *protocol,
return -1;
}
xfer += ret;
} else if (read_len == 0) {
*str = NULL;
} else {
g_set_error (error, THRIFT_PROTOCOL_ERROR,
THRIFT_PROTOCOL_ERROR_NEGATIVE_SIZE,
"got negative size of %d", read_len);
*str = NULL;
return -1;
**str = 0;
}
return xfer;

View file

@ -0,0 +1,158 @@
/*
* 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_multiplexed_protocol.h>
enum
{
PROP_THRIFT_MULTIPLEXED_PROTOCOL_SERVICE_NAME = 1,
PROP_THRIFT_MULTIPLEXED_PROTOCOL_END
};
G_DEFINE_TYPE(ThriftMultiplexedProtocol, thrift_multiplexed_protocol, THRIFT_TYPE_PROTOCOL_DECORATOR)
static GParamSpec *thrift_multiplexed_protocol_obj_properties[PROP_THRIFT_MULTIPLEXED_PROTOCOL_END] = { NULL, };
gint32
thrift_multiplexed_protocol_write_message_begin (ThriftMultiplexedProtocol *protocol,
const gchar *name, const ThriftMessageType message_type,
const gint32 seqid, GError **error)
{
gint32 ret;
gchar *service_name = NULL;
g_return_val_if_fail (THRIFT_IS_MULTIPLEXED_PROTOCOL (protocol), -1);
ThriftMultiplexedProtocol *self = THRIFT_MULTIPLEXED_PROTOCOL (protocol);
ThriftMultiplexedProtocolClass *multiplexClass = THRIFT_MULTIPLEXED_PROTOCOL_GET_CLASS(self);
if( (message_type == T_CALL || message_type == T_ONEWAY) && self->service_name != NULL) {
service_name = g_strdup_printf("%s%s%s", self->service_name, THRIFT_MULTIPLEXED_PROTOCOL_DEFAULT_SEPARATOR, name);
}else{
service_name = g_strdup(name);
}
/* relay to the protocol_decorator */
ret = thrift_protocol_decorator_write_message_begin(protocol, service_name, message_type, seqid, error);
g_free(service_name);
return ret;
}
static void
thrift_multiplexed_protocol_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
ThriftMultiplexedProtocol *self = THRIFT_MULTIPLEXED_PROTOCOL (object);
switch (property_id)
{
case PROP_THRIFT_MULTIPLEXED_PROTOCOL_SERVICE_NAME:
self->service_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_protocol_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
ThriftMultiplexedProtocol *self = THRIFT_MULTIPLEXED_PROTOCOL (object);
switch (property_id)
{
case PROP_THRIFT_MULTIPLEXED_PROTOCOL_SERVICE_NAME:
g_value_set_string (value, self->service_name);
break;
default:
/* We don't have any other property... */
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
thrift_multiplexed_protocol_init (ThriftMultiplexedProtocol *protocol)
{
protocol->service_name = NULL;
}
static void
thrift_multiplexed_protocol_finalize (GObject *gobject)
{
ThriftMultiplexedProtocol *self = THRIFT_MULTIPLEXED_PROTOCOL (gobject);
if (self->service_name) {
g_free(self->service_name);
self->service_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_multiplexed_protocol_parent_class)->finalize(gobject);
}
/* initialize the class */
static void
thrift_multiplexed_protocol_class_init (ThriftMultiplexedProtocolClass *klass)
{
ThriftProtocolClass *cls = THRIFT_PROTOCOL_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
cls->write_message_begin = thrift_multiplexed_protocol_write_message_begin;
object_class->set_property = thrift_multiplexed_protocol_set_property;
object_class->get_property = thrift_multiplexed_protocol_get_property;
object_class->finalize = thrift_multiplexed_protocol_finalize;
thrift_multiplexed_protocol_obj_properties[PROP_THRIFT_MULTIPLEXED_PROTOCOL_SERVICE_NAME] =
g_param_spec_string ("service-name",
"Service name the protocol points to",
"Set the service name",
NULL,
(G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
g_object_class_install_properties (object_class,
PROP_THRIFT_MULTIPLEXED_PROTOCOL_END,
thrift_multiplexed_protocol_obj_properties);
}

View file

@ -0,0 +1,76 @@
/*
* 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_MULTIPLEXED_PROTOCOL_H
#define _THRIFT_MULTIPLEXED_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_multiplexed_protocol.h
* \brief Multiplexed protocol implementation of a Thrift protocol. Implements the
* ThriftProtocol interface.
*/
/* type macros */
#define THRIFT_TYPE_MULTIPLEXED_PROTOCOL (thrift_multiplexed_protocol_get_type ())
#define THRIFT_MULTIPLEXED_PROTOCOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THRIFT_TYPE_MULTIPLEXED_PROTOCOL, ThriftMultiplexedProtocol))
#define THRIFT_IS_MULTIPLEXED_PROTOCOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THRIFT_TYPE_MULTIPLEXED_PROTOCOL))
#define THRIFT_MULTIPLEXED_PROTOCOL_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), THRIFT_TYPE_MULTIPLEXED_PROTOCOL, ThriftMultiplexedProtocolClass))
#define THRIFT_IS_MULTIPLEXED_PROTOCOL_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), THRIFT_TYPE_MULTIPLEXED_PROTOCOL))
#define THRIFT_MULTIPLEXED_PROTOCOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THRIFT_TYPE_MULTIPLEXED_PROTOCOL, ThriftMultiplexedProtocolClass))
/* constant */
#define THRIFT_MULTIPLEXED_PROTOCOL_DEFAULT_SEPARATOR ":"
typedef struct _ThriftMultiplexedProtocol ThriftMultiplexedProtocol;
/*!
* Thrift Multiplexed Protocol instance.
*/
struct _ThriftMultiplexedProtocol
{
ThriftProtocolDecorator parent;
gchar *service_name;
};
typedef struct _ThriftMultiplexedProtocolClass ThriftMultiplexedProtocolClass;
/*!
* Thrift Multiplexed Protocol class.
*/
struct _ThriftMultiplexedProtocolClass
{
ThriftProtocolDecoratorClass parent;
};
/* used by THRIFT_TYPE_MULTIPLEXED_PROTOCOL */
GType thrift_multiplexed_protocol_get_type (void);
G_END_DECLS
#endif /* _THRIFT_MULTIPLEXED_PROTOCOL_H */

View file

@ -61,15 +61,15 @@ thrift_protocol_set_property (GObject *object, guint property_id,
switch (property_id)
{
case PROP_THRIFT_PROTOCOL_TRANSPORT:
protocol->transport = g_value_get_object (value);
protocol->transport = g_value_dup_object (value);
break;
}
}
gint32
thrift_protocol_write_message_begin (ThriftProtocol *protocol,
const gchar *name,
thrift_protocol_write_message_begin (ThriftProtocol *protocol,
const gchar *name,
const ThriftMessageType message_type,
const gint32 seqid, GError **error)
{
@ -243,7 +243,7 @@ thrift_protocol_write_binary (ThriftProtocol *protocol, const gpointer buf,
len, error);
}
gint32
gint32
thrift_protocol_read_message_begin (ThriftProtocol *protocol,
gchar **name,
ThriftMessageType *message_type,
@ -254,7 +254,7 @@ thrift_protocol_read_message_begin (ThriftProtocol *protocol,
seqid, error);
}
gint32
gint32
thrift_protocol_read_message_end (ThriftProtocol *protocol,
GError **error)
{
@ -262,7 +262,7 @@ thrift_protocol_read_message_end (ThriftProtocol *protocol,
error);
}
gint32
gint32
thrift_protocol_read_struct_begin (ThriftProtocol *protocol,
gchar **name,
GError **error)
@ -279,7 +279,7 @@ thrift_protocol_read_struct_end (ThriftProtocol *protocol, GError **error)
error);
}
gint32
gint32
thrift_protocol_read_field_begin (ThriftProtocol *protocol,
gchar **name,
ThriftType *field_type,
@ -293,7 +293,7 @@ thrift_protocol_read_field_begin (ThriftProtocol *protocol,
error);
}
gint32
gint32
thrift_protocol_read_field_end (ThriftProtocol *protocol,
GError **error)
{
@ -301,7 +301,7 @@ thrift_protocol_read_field_end (ThriftProtocol *protocol,
error);
}
gint32
gint32
thrift_protocol_read_map_begin (ThriftProtocol *protocol,
ThriftType *key_type,
ThriftType *value_type, guint32 *size,
@ -311,17 +311,17 @@ thrift_protocol_read_map_begin (ThriftProtocol *protocol,
key_type,
value_type,
size,
error);
error);
}
gint32
gint32
thrift_protocol_read_map_end (ThriftProtocol *protocol, GError **error)
{
return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_map_end (protocol,
error);
}
gint32
gint32
thrift_protocol_read_list_begin (ThriftProtocol *protocol,
ThriftType *element_type,
guint32 *size, GError **error)
@ -412,7 +412,7 @@ thrift_protocol_read_string (ThriftProtocol *protocol,
}
gint32
thrift_protocol_read_binary (ThriftProtocol *protocol, gpointer *buf,
thrift_protocol_read_binary (ThriftProtocol *protocol, gpointer *buf,
guint32 *len, GError **error)
{
return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_binary (protocol, buf,
@ -548,6 +548,20 @@ thrift_protocol_init (ThriftProtocol *protocol)
protocol->transport = NULL;
}
static void
thrift_protocol_dispose (GObject *gobject)
{
ThriftProtocol *self = THRIFT_PROTOCOL (gobject);
g_clear_object(&self->transport);
/* Always chain up to the parent class; there is no need to check if
* the parent class implements the dispose() virtual function: it is
* always guaranteed to do so
*/
G_OBJECT_CLASS (thrift_protocol_parent_class)->dispose(gobject);
}
static void
thrift_protocol_class_init (ThriftProtocolClass *cls)
{
@ -555,6 +569,7 @@ thrift_protocol_class_init (ThriftProtocolClass *cls)
gobject_class->get_property = thrift_protocol_get_property;
gobject_class->set_property = thrift_protocol_set_property;
gobject_class->dispose = thrift_protocol_dispose;
g_object_class_install_property (gobject_class,
PROP_THRIFT_PROTOCOL_TRANSPORT,

View file

@ -0,0 +1,623 @@
/*
* 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_binary_protocol.h>
#include <thrift/c_glib/protocol/thrift_protocol_decorator.h>
G_DEFINE_TYPE(ThriftProtocolDecorator, thrift_protocol_decorator, THRIFT_TYPE_PROTOCOL)
enum
{
PROP_THRIFT_TYPE_PROTOCOL_DECORATOR_CONCRETE_PROTOCOL = 1,
PROP_THRIFT_TYPE_PROTOCOL_DECORATOR_END
};
static GParamSpec *thrift_protocol_decorator_obj_properties[PROP_THRIFT_TYPE_PROTOCOL_DECORATOR_END] = { NULL, };
gint32
thrift_protocol_decorator_write_message_begin (ThriftProtocol *protocol,
const gchar *name,
const ThriftMessageType message_type,
const gint32 seqid, GError **error)
{
ThriftProtocolDecorator *self = THRIFT_PROTOCOL_DECORATOR (protocol);
ThriftProtocolClass *proto = THRIFT_PROTOCOL_GET_CLASS (self->concrete_protocol);
g_debug("Concrete protocol %p | %p", (void *)self->concrete_protocol, (void *)proto);
return proto->write_message_begin (self->concrete_protocol, name,
message_type, seqid,
error);
}
gint32
thrift_protocol_decorator_write_message_end (ThriftProtocol *protocol, GError **error)
{
ThriftProtocolDecorator *self = THRIFT_PROTOCOL_DECORATOR (protocol);
return THRIFT_PROTOCOL_GET_CLASS (self->concrete_protocol)->write_message_end (self->concrete_protocol,
error);
}
gint32
thrift_protocol_decorator_write_struct_begin (ThriftProtocol *protocol, const gchar *name,
GError **error)
{
ThriftProtocolDecorator *self = THRIFT_PROTOCOL_DECORATOR (protocol);
return THRIFT_PROTOCOL_GET_CLASS (self->concrete_protocol)->write_struct_begin (self->concrete_protocol,
name, error);
}
gint32
thrift_protocol_decorator_write_struct_end (ThriftProtocol *protocol, GError **error)
{
ThriftProtocolDecorator *self = THRIFT_PROTOCOL_DECORATOR (protocol);
return THRIFT_PROTOCOL_GET_CLASS (self->concrete_protocol)->write_struct_end (self->concrete_protocol,
error);
}
gint32
thrift_protocol_decorator_write_field_begin (ThriftProtocol *protocol,
const gchar *name,
const ThriftType field_type,
const gint16 field_id,
GError **error)
{
ThriftProtocolDecorator *self = THRIFT_PROTOCOL_DECORATOR (protocol);
return THRIFT_PROTOCOL_GET_CLASS (self->concrete_protocol)->write_field_begin (self->concrete_protocol,
name, field_type,
field_id, error);
}
gint32
thrift_protocol_decorator_write_field_end (ThriftProtocol *protocol, GError **error)
{
ThriftProtocolDecorator *self = THRIFT_PROTOCOL_DECORATOR (protocol);
return THRIFT_PROTOCOL_GET_CLASS (self->concrete_protocol)->write_field_end (self->concrete_protocol,
error);
}
gint32
thrift_protocol_decorator_write_field_stop (ThriftProtocol *protocol, GError **error)
{
ThriftProtocolDecorator *self = THRIFT_PROTOCOL_DECORATOR (protocol);
return THRIFT_PROTOCOL_GET_CLASS (self->concrete_protocol)->write_field_stop (self->concrete_protocol,
error);
}
gint32
thrift_protocol_decorator_write_map_begin (ThriftProtocol *protocol,
const ThriftType key_type,
const ThriftType value_type,
const guint32 size, GError **error)
{
ThriftProtocolDecorator *self = THRIFT_PROTOCOL_DECORATOR (protocol);
return THRIFT_PROTOCOL_GET_CLASS (self->concrete_protocol)->write_map_begin (self->concrete_protocol,
key_type, value_type,
size, error);
}
gint32
thrift_protocol_decorator_write_map_end (ThriftProtocol *protocol, GError **error)
{
ThriftProtocolDecorator *self = THRIFT_PROTOCOL_DECORATOR (protocol);
return THRIFT_PROTOCOL_GET_CLASS (self->concrete_protocol)->write_map_end (self->concrete_protocol,
error);
}
gint32
thrift_protocol_decorator_write_list_begin (ThriftProtocol *protocol,
const ThriftType element_type,
const guint32 size, GError **error)
{
ThriftProtocolDecorator *self = THRIFT_PROTOCOL_DECORATOR (protocol);
return THRIFT_PROTOCOL_GET_CLASS (self->concrete_protocol)->write_list_begin (self->concrete_protocol,
element_type, size,
error);
}
gint32
thrift_protocol_decorator_write_list_end (ThriftProtocol *protocol, GError **error)
{
ThriftProtocolDecorator *self = THRIFT_PROTOCOL_DECORATOR (protocol);
return THRIFT_PROTOCOL_GET_CLASS (self->concrete_protocol)->write_list_end (self->concrete_protocol,
error);
}
gint32
thrift_protocol_decorator_write_set_begin (ThriftProtocol *protocol,
const ThriftType element_type,
const guint32 size, GError **error)
{
ThriftProtocolDecorator *self = THRIFT_PROTOCOL_DECORATOR (protocol);
return THRIFT_PROTOCOL_GET_CLASS (self->concrete_protocol)->write_set_begin (self->concrete_protocol,
element_type, size,
error);
}
gint32
thrift_protocol_decorator_write_set_end (ThriftProtocol *protocol, GError **error)
{
ThriftProtocolDecorator *self = THRIFT_PROTOCOL_DECORATOR (protocol);
return THRIFT_PROTOCOL_GET_CLASS (self->concrete_protocol)->write_set_end (self->concrete_protocol,
error);
}
gint32
thrift_protocol_decorator_write_bool (ThriftProtocol *protocol,
const gboolean value, GError **error)
{
ThriftProtocolDecorator *self = THRIFT_PROTOCOL_DECORATOR (protocol);
return THRIFT_PROTOCOL_GET_CLASS (self->concrete_protocol)->write_bool (self->concrete_protocol, value,
error);
}
gint32
thrift_protocol_decorator_write_byte (ThriftProtocol *protocol, const gint8 value,
GError **error)
{
ThriftProtocolDecorator *self = THRIFT_PROTOCOL_DECORATOR (protocol);
return THRIFT_PROTOCOL_GET_CLASS (self->concrete_protocol)->write_byte (self->concrete_protocol, value,
error);
}
gint32
thrift_protocol_decorator_write_i16 (ThriftProtocol *protocol, const gint16 value,
GError **error)
{
ThriftProtocolDecorator *self = THRIFT_PROTOCOL_DECORATOR (protocol);
return THRIFT_PROTOCOL_GET_CLASS (self->concrete_protocol)->write_i16 (self->concrete_protocol, value,
error);
}
gint32
thrift_protocol_decorator_write_i32 (ThriftProtocol *protocol, const gint32 value,
GError **error)
{
ThriftProtocolDecorator *self = THRIFT_PROTOCOL_DECORATOR (protocol);
return THRIFT_PROTOCOL_GET_CLASS (self->concrete_protocol)->write_i32 (self->concrete_protocol, value,
error);
}
gint32
thrift_protocol_decorator_write_i64 (ThriftProtocol *protocol, const gint64 value,
GError **error)
{
ThriftProtocolDecorator *self = THRIFT_PROTOCOL_DECORATOR (protocol);
return THRIFT_PROTOCOL_GET_CLASS (self->concrete_protocol)->write_i64 (self->concrete_protocol, value,
error);
}
gint32
thrift_protocol_decorator_write_double (ThriftProtocol *protocol,
const gdouble value, GError **error)
{
ThriftProtocolDecorator *self = THRIFT_PROTOCOL_DECORATOR (protocol);
return THRIFT_PROTOCOL_GET_CLASS (self->concrete_protocol)->write_double (self->concrete_protocol,
value, error);
}
gint32
thrift_protocol_decorator_write_string (ThriftProtocol *protocol,
const gchar *str, GError **error)
{
ThriftProtocolDecorator *self = THRIFT_PROTOCOL_DECORATOR (protocol);
return THRIFT_PROTOCOL_GET_CLASS (self->concrete_protocol)->write_string (self->concrete_protocol, str,
error);
}
gint32
thrift_protocol_decorator_write_binary (ThriftProtocol *protocol, const gpointer buf,
const guint32 len, GError **error)
{
ThriftProtocolDecorator *self = THRIFT_PROTOCOL_DECORATOR (protocol);
return THRIFT_PROTOCOL_GET_CLASS (self->concrete_protocol)->write_binary (self->concrete_protocol, buf,
len, error);
}
gint32
thrift_protocol_decorator_read_message_begin (ThriftProtocol *protocol,
gchar **name,
ThriftMessageType *message_type,
gint32 *seqid, GError **error)
{
ThriftProtocolDecorator *self = THRIFT_PROTOCOL_DECORATOR (protocol);
return THRIFT_PROTOCOL_GET_CLASS (self->concrete_protocol)->read_message_begin (self->concrete_protocol,
name, message_type,
seqid, error);
}
gint32
thrift_protocol_decorator_read_message_end (ThriftProtocol *protocol,
GError **error)
{
ThriftProtocolDecorator *self = THRIFT_PROTOCOL_DECORATOR (protocol);
return THRIFT_PROTOCOL_GET_CLASS (self->concrete_protocol)->read_message_end (self->concrete_protocol,
error);
}
gint32
thrift_protocol_decorator_read_struct_begin (ThriftProtocol *protocol,
gchar **name,
GError **error)
{
ThriftProtocolDecorator *self = THRIFT_PROTOCOL_DECORATOR (protocol);
return THRIFT_PROTOCOL_GET_CLASS (self->concrete_protocol)->read_struct_begin (self->concrete_protocol,
name,
error);
}
gint32
thrift_protocol_decorator_read_struct_end (ThriftProtocol *protocol, GError **error)
{
ThriftProtocolDecorator *self = THRIFT_PROTOCOL_DECORATOR (protocol);
return THRIFT_PROTOCOL_GET_CLASS (self->concrete_protocol)->read_struct_end (self->concrete_protocol,
error);
}
gint32
thrift_protocol_decorator_read_field_begin (ThriftProtocol *protocol,
gchar **name,
ThriftType *field_type,
gint16 *field_id,
GError **error)
{
ThriftProtocolDecorator *self = THRIFT_PROTOCOL_DECORATOR (protocol);
return THRIFT_PROTOCOL_GET_CLASS (self->concrete_protocol)->read_field_begin (self->concrete_protocol,
name,
field_type,
field_id,
error);
}
gint32
thrift_protocol_decorator_read_field_end (ThriftProtocol *protocol,
GError **error)
{
ThriftProtocolDecorator *self = THRIFT_PROTOCOL_DECORATOR (protocol);
return THRIFT_PROTOCOL_GET_CLASS (self->concrete_protocol)->read_field_end (self->concrete_protocol,
error);
}
gint32
thrift_protocol_decorator_read_map_begin (ThriftProtocol *protocol,
ThriftType *key_type,
ThriftType *value_type, guint32 *size,
GError **error)
{
ThriftProtocolDecorator *self = THRIFT_PROTOCOL_DECORATOR (protocol);
return THRIFT_PROTOCOL_GET_CLASS (self->concrete_protocol)->read_map_begin (self->concrete_protocol,
key_type,
value_type,
size,
error);
}
gint32
thrift_protocol_decorator_read_map_end (ThriftProtocol *protocol, GError **error)
{
ThriftProtocolDecorator *self = THRIFT_PROTOCOL_DECORATOR (protocol);
return THRIFT_PROTOCOL_GET_CLASS (self->concrete_protocol)->read_map_end (self->concrete_protocol,
error);
}
gint32
thrift_protocol_decorator_read_list_begin (ThriftProtocol *protocol,
ThriftType *element_type,
guint32 *size, GError **error)
{
ThriftProtocolDecorator *self = THRIFT_PROTOCOL_DECORATOR (protocol);
return THRIFT_PROTOCOL_GET_CLASS (self->concrete_protocol)->read_list_begin (self->concrete_protocol,
element_type,
size, error);
}
gint32
thrift_protocol_decorator_read_list_end (ThriftProtocol *protocol, GError **error)
{
ThriftProtocolDecorator *self = THRIFT_PROTOCOL_DECORATOR (protocol);
return THRIFT_PROTOCOL_GET_CLASS (self->concrete_protocol)->read_list_end (self->concrete_protocol,
error);
}
gint32
thrift_protocol_decorator_read_set_begin (ThriftProtocol *protocol,
ThriftType *element_type,
guint32 *size, GError **error)
{
ThriftProtocolDecorator *self = THRIFT_PROTOCOL_DECORATOR (protocol);
return THRIFT_PROTOCOL_GET_CLASS (self->concrete_protocol)->read_set_begin (self->concrete_protocol,
element_type,
size, error);
}
gint32
thrift_protocol_decorator_read_set_end (ThriftProtocol *protocol, GError **error)
{
ThriftProtocolDecorator *self = THRIFT_PROTOCOL_DECORATOR (protocol);
return THRIFT_PROTOCOL_GET_CLASS (self->concrete_protocol)->read_set_end (self->concrete_protocol,
error);
}
gint32
thrift_protocol_decorator_read_bool (ThriftProtocol *protocol, gboolean *value,
GError **error)
{
ThriftProtocolDecorator *self = THRIFT_PROTOCOL_DECORATOR (protocol);
return THRIFT_PROTOCOL_GET_CLASS (self->concrete_protocol)->read_bool (self->concrete_protocol, value,
error);
}
gint32
thrift_protocol_decorator_read_byte (ThriftProtocol *protocol, gint8 *value,
GError **error)
{
ThriftProtocolDecorator *self = THRIFT_PROTOCOL_DECORATOR (protocol);
return THRIFT_PROTOCOL_GET_CLASS (self->concrete_protocol)->read_byte (self->concrete_protocol, value,
error);
}
gint32
thrift_protocol_decorator_read_i16 (ThriftProtocol *protocol, gint16 *value,
GError **error)
{
ThriftProtocolDecorator *self = THRIFT_PROTOCOL_DECORATOR (protocol);
return THRIFT_PROTOCOL_GET_CLASS (self->concrete_protocol)->read_i16 (self->concrete_protocol, value,
error);
}
gint32
thrift_protocol_decorator_read_i32 (ThriftProtocol *protocol, gint32 *value,
GError **error)
{
ThriftProtocolDecorator *self = THRIFT_PROTOCOL_DECORATOR (protocol);
return THRIFT_PROTOCOL_GET_CLASS (self->concrete_protocol)->read_i32 (self->concrete_protocol, value,
error);
}
gint32
thrift_protocol_decorator_read_i64 (ThriftProtocol *protocol, gint64 *value,
GError **error)
{
ThriftProtocolDecorator *self = THRIFT_PROTOCOL_DECORATOR (protocol);
return THRIFT_PROTOCOL_GET_CLASS (self->concrete_protocol)->read_i64 (self->concrete_protocol, value,
error);
}
gint32
thrift_protocol_decorator_read_double (ThriftProtocol *protocol,
gdouble *value, GError **error)
{
ThriftProtocolDecorator *self = THRIFT_PROTOCOL_DECORATOR (protocol);
return THRIFT_PROTOCOL_GET_CLASS (self->concrete_protocol)->read_double (self->concrete_protocol, value,
error);
}
gint32
thrift_protocol_decorator_read_string (ThriftProtocol *protocol,
gchar **str, GError **error)
{
ThriftProtocolDecorator *self = THRIFT_PROTOCOL_DECORATOR (protocol);
return THRIFT_PROTOCOL_GET_CLASS (self->concrete_protocol)->read_string (self->concrete_protocol, str,
error);
}
gint32
thrift_protocol_decorator_read_binary (ThriftProtocol *protocol, gpointer *buf,
guint32 *len, GError **error)
{
ThriftProtocolDecorator *self = THRIFT_PROTOCOL_DECORATOR (protocol);
return THRIFT_PROTOCOL_GET_CLASS (self->concrete_protocol)->read_binary (self->concrete_protocol, buf,
len, error);
}
static void
thrift_protocol_decorator_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
ThriftProtocolDecorator *self = THRIFT_PROTOCOL_DECORATOR (object);
switch (property_id)
{
case PROP_THRIFT_TYPE_PROTOCOL_DECORATOR_CONCRETE_PROTOCOL:
self->concrete_protocol = g_value_dup_object (value);
break;
default:
/* We don't have any other property... */
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
thrift_protocol_decorator_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
ThriftProtocolDecorator *self = THRIFT_PROTOCOL_DECORATOR (object);
switch (property_id)
{
case PROP_THRIFT_TYPE_PROTOCOL_DECORATOR_CONCRETE_PROTOCOL:
g_value_set_object (value, self->concrete_protocol);
break;
default:
/* We don't have any other property... */
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
ThriftProtocol *
thrift_protocol_decorator_get_concrete_protocol(ThriftProtocolDecorator *protocol)
{
ThriftProtocol *retval = NULL;
if(!THRIFT_IS_PROTOCOL_DECORATOR(protocol)){
g_warning("The type is not protocol decorator");
return NULL;
}
ThriftProtocolDecorator *self = THRIFT_PROTOCOL_DECORATOR(protocol);
g_debug("Getting concrete protocol from %p -> %p", (void *)self, (void *)self->concrete_protocol);
return retval;
}
static void
thrift_protocol_decorator_init (ThriftProtocolDecorator *protocol)
{
protocol->concrete_protocol = NULL;
}
static void
thrift_protocol_decorator_dispose (GObject *gobject)
{
ThriftProtocolDecorator *self = THRIFT_PROTOCOL_DECORATOR (gobject);
g_clear_object(&self->concrete_protocol);
/* Always chain up to the parent class; there is no need to check if
* the parent class implements the dispose() virtual function: it is
* always guaranteed to do so
*/
G_OBJECT_CLASS (thrift_protocol_decorator_parent_class)->dispose(gobject);
}
/* initialize the class */
static void
thrift_protocol_decorator_class_init (ThriftProtocolDecoratorClass *klass)
{
ThriftProtocolClass *cls = THRIFT_PROTOCOL_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->set_property = thrift_protocol_decorator_set_property;
object_class->get_property = thrift_protocol_decorator_get_property;
object_class->dispose = thrift_protocol_decorator_dispose;
thrift_protocol_decorator_obj_properties[PROP_THRIFT_TYPE_PROTOCOL_DECORATOR_CONCRETE_PROTOCOL] =
g_param_spec_object ("protocol",
"Protocol",
"Set the protocol to be implemented", THRIFT_TYPE_PROTOCOL,
(G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
g_object_class_install_properties (object_class,
PROP_THRIFT_TYPE_PROTOCOL_DECORATOR_END,
thrift_protocol_decorator_obj_properties);
g_debug("Current decorator write_message_begin addr %p, new %p", cls->write_message_begin, thrift_protocol_decorator_write_message_begin);
cls->write_message_begin = thrift_protocol_decorator_write_message_begin;
cls->write_message_end = thrift_protocol_decorator_write_message_end;
cls->write_struct_begin = thrift_protocol_decorator_write_struct_begin;
cls->write_struct_end = thrift_protocol_decorator_write_struct_end;
cls->write_field_begin = thrift_protocol_decorator_write_field_begin;
cls->write_field_end = thrift_protocol_decorator_write_field_end;
cls->write_field_stop = thrift_protocol_decorator_write_field_stop;
cls->write_map_begin = thrift_protocol_decorator_write_map_begin;
cls->write_map_end = thrift_protocol_decorator_write_map_end;
cls->write_list_begin = thrift_protocol_decorator_write_list_begin;
cls->write_list_end = thrift_protocol_decorator_write_list_end;
cls->write_set_begin = thrift_protocol_decorator_write_set_begin;
cls->write_set_end = thrift_protocol_decorator_write_set_end;
cls->write_bool = thrift_protocol_decorator_write_bool;
cls->write_byte = thrift_protocol_decorator_write_byte;
cls->write_i16 = thrift_protocol_decorator_write_i16;
cls->write_i32 = thrift_protocol_decorator_write_i32;
cls->write_i64 = thrift_protocol_decorator_write_i64;
cls->write_double = thrift_protocol_decorator_write_double;
cls->write_string = thrift_protocol_decorator_write_string;
cls->write_binary = thrift_protocol_decorator_write_binary;
cls->read_message_begin = thrift_protocol_decorator_read_message_begin;
cls->read_message_end = thrift_protocol_decorator_read_message_end;
cls->read_struct_begin = thrift_protocol_decorator_read_struct_begin;
cls->read_struct_end = thrift_protocol_decorator_read_struct_end;
cls->read_field_begin = thrift_protocol_decorator_read_field_begin;
cls->read_field_end = thrift_protocol_decorator_read_field_end;
cls->read_map_begin = thrift_protocol_decorator_read_map_begin;
cls->read_map_end = thrift_protocol_decorator_read_map_end;
cls->read_list_begin = thrift_protocol_decorator_read_list_begin;
cls->read_list_end = thrift_protocol_decorator_read_list_end;
cls->read_set_begin = thrift_protocol_decorator_read_set_begin;
cls->read_set_end = thrift_protocol_decorator_read_set_end;
cls->read_bool = thrift_protocol_decorator_read_bool;
cls->read_byte = thrift_protocol_decorator_read_byte;
cls->read_i16 = thrift_protocol_decorator_read_i16;
cls->read_i32 = thrift_protocol_decorator_read_i32;
cls->read_i64 = thrift_protocol_decorator_read_i64;
cls->read_double = thrift_protocol_decorator_read_double;
cls->read_string = thrift_protocol_decorator_read_string;
cls->read_binary = thrift_protocol_decorator_read_binary;
}

View file

@ -0,0 +1,72 @@
/*
* 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_PROTOCOL_DECORATOR_H
#define _THRIFT_PROTOCOL_DECORATOR_H
#include <glib-object.h>
#include <thrift/c_glib/protocol/thrift_protocol.h>
#include <thrift/c_glib/transport/thrift_transport.h>
G_BEGIN_DECLS
/*! \file thrift_protocol_decorator.h
* \brief Multiplexed protocol implementation of a Thrift protocol. Implements the
* ThriftProtocol interface.
*/
/* type macros */
#define THRIFT_TYPE_PROTOCOL_DECORATOR (thrift_protocol_decorator_get_type ())
#define THRIFT_PROTOCOL_DECORATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THRIFT_TYPE_PROTOCOL_DECORATOR, ThriftProtocolDecorator))
#define THRIFT_IS_PROTOCOL_DECORATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THRIFT_TYPE_PROTOCOL_DECORATOR))
#define THRIFT_PROTOCOL_DECORATOR_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), THRIFT_TYPE_PROTOCOL_DECORATOR, ThriftProtocolDecoratorClass))
#define THRIFT_IS_PROTOCOL_DECORATOR_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), THRIFT_TYPE_PROTOCOL_DECORATOR))
#define THRIFT_PROTOCOL_DECORATOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THRIFT_TYPE_PROTOCOL_DECORATOR, ThriftProtocolDecoratorClass))
typedef struct _ThriftProtocolDecorator ThriftProtocolDecorator;
/*!
* Thrift Protocol Decorator instance.
*/
struct _ThriftProtocolDecorator
{
ThriftProtocol parent;
ThriftProtocol *concrete_protocol;
};
typedef struct _ThriftProtocolDecoratorClass ThriftProtocolDecoratorClass;
/*!
* Thrift Protocol Decorator class.
*/
struct _ThriftProtocolDecoratorClass
{
ThriftProtocolClass parent;
};
/* used by THRIFT_TYPE_PROTOCOL_DECORATOR */
GType thrift_protocol_decorator_get_type (void);
G_END_DECLS
#endif /* _THRIFT_PROTOCOL_DECORATOR_H */

View file

@ -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);
}

View file

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

View file

@ -76,22 +76,22 @@ thrift_server_set_property (GObject *object, guint property_id,
switch (property_id)
{
case PROP_THRIFT_SERVER_PROCESSOR:
server->processor = g_value_get_object (value);
server->processor = g_value_dup_object (value);
break;
case PROP_THRIFT_SERVER_SERVER_TRANSPORT:
server->server_transport = g_value_get_object (value);
server->server_transport = g_value_dup_object (value);
break;
case PROP_THRIFT_SERVER_INPUT_TRANSPORT_FACTORY:
server->input_transport_factory = g_value_get_object (value);
server->input_transport_factory = g_value_dup_object (value);
break;
case PROP_THRIFT_SERVER_OUTPUT_TRANSPORT_FACTORY:
server->output_transport_factory = g_value_get_object (value);
server->output_transport_factory = g_value_dup_object (value);
break;
case PROP_THRIFT_SERVER_INPUT_PROTOCOL_FACTORY:
server->input_protocol_factory = g_value_get_object (value);
server->input_protocol_factory = g_value_dup_object (value);
break;
case PROP_THRIFT_SERVER_OUTPUT_PROTOCOL_FACTORY:
server->output_protocol_factory = g_value_get_object (value);
server->output_protocol_factory = g_value_dup_object (value);
break;
}
}
@ -120,7 +120,27 @@ thrift_server_init (ThriftServer *server)
server->output_protocol_factory = NULL;
}
/* class initializer for ThriftServer
static void
thrift_server_dispose (GObject *gobject)
{
ThriftServer *self = THRIFT_SERVER (gobject);
g_clear_object(&self->output_protocol_factory);
g_clear_object(&self->input_protocol_factory);
g_clear_object(&self->output_transport_factory);
g_clear_object(&self->input_transport_factory);
g_clear_object(&self->server_transport);
g_clear_object(&self->processor);
/* Always chain up to the parent class; there is no need to check if
* the parent class implements the dispose() virtual function: it is
* always guaranteed to do so
*/
G_OBJECT_CLASS (thrift_server_parent_class)->dispose(gobject);
}
/*
* class initializer for ThriftServer
* TODO: implement ServerEventHandler as a GClosure
*/
static void
@ -130,6 +150,7 @@ thrift_server_class_init (ThriftServerClass *cls)
gobject_class->get_property = thrift_server_get_property;
gobject_class->set_property = thrift_server_set_property;
gobject_class->dispose = thrift_server_dispose;
g_object_class_install_property (gobject_class,
PROP_THRIFT_SERVER_PROCESSOR,

View file

@ -17,7 +17,6 @@
* under the License.
*/
#include <assert.h>
#include <netdb.h>
#include <stdlib.h>
#include <stdio.h>
@ -84,7 +83,7 @@ thrift_buffered_transport_read_slow (ThriftTransport *transport, gpointer buf,
guint32 have = t->r_buf->len;
/* we shouldn't hit this unless the buffer doesn't have enough to read */
assert (t->r_buf->len < want);
g_assert (t->r_buf->len < want);
/* first copy what we have in our buffer. */
if (have > 0)

View file

@ -17,7 +17,6 @@
* under the License.
*/
#include <assert.h>
#include <netdb.h>
#include <stdlib.h>
#include <stdio.h>
@ -120,7 +119,7 @@ thrift_framed_transport_read_slow (ThriftTransport *transport, gpointer buf,
gint32 result = -1;
/* we shouldn't hit this unless the buffer doesn't have enough to read */
assert (t->r_buf->len < want);
g_assert (t->r_buf->len < want);
/* first copy what we have in our buffer, if there is anything left */
if (have > 0)

View file

@ -17,7 +17,6 @@
* under the License.
*/
#include <assert.h>
#include <netdb.h>
#include <stdlib.h>
#include <stdio.h>

View file

@ -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_ */

View file

@ -224,12 +224,12 @@ thrift_server_socket_class_init (ThriftServerSocketClass *cls)
"port (construct)",
"Set the port to listen to",
0, /* min */
65534, /* max */
65535, /* max */
9090, /* default by convention */
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_READWRITE);
g_object_class_install_property (gobject_class,
PROP_THRIFT_SERVER_SOCKET_PORT,
PROP_THRIFT_SERVER_SOCKET_PORT,
param_spec);
param_spec = g_param_spec_uint ("backlog",

View file

@ -49,7 +49,7 @@ struct _ThriftServerSocket
ThriftServerTransport parent;
/* private */
gshort port;
guint port;
gshort backlog;
int sd;
guint8 *buf;

View file

@ -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,8 +147,8 @@ 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_port = htons (tsocket->port);
pin.sin_addr.s_addr = ((struct in_addr *) (hp->h_addr_list[0]))->s_addr;
pin.sin_port = htons (tsocket->port);
/* create the socket */
if ((tsocket->sd = socket (AF_INET, SOCK_STREAM, 0)) == -1)
@ -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
@ -210,7 +213,7 @@ thrift_socket_read_end (ThriftTransport *transport, GError **error)
/* implements thrift_transport_write */
gboolean
thrift_socket_write (ThriftTransport *transport, const gpointer buf,
thrift_socket_write (ThriftTransport *transport, const gpointer buf,
const guint32 len, GError **error)
{
gint ret = 0;
@ -315,6 +318,9 @@ thrift_socket_set_property (GObject *object, guint property_id,
switch (property_id)
{
case PROP_THRIFT_SOCKET_HOSTNAME:
if (socket->hostname) {
g_free(socket->hostname);
}
socket->hostname = g_strdup (g_value_get_string (value));
break;
case PROP_THRIFT_SOCKET_PORT:
@ -347,8 +353,8 @@ thrift_socket_class_init (ThriftSocketClass *cls)
param_spec = g_param_spec_uint ("port",
"port (construct)",
"Set the port of the remote host",
0, /* min */
65534, /* max */
0u, /* min */
65535u, /* max */
9090, /* default by convention */
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_READWRITE);

View file

@ -50,11 +50,8 @@ struct _ThriftSocket
/* private */
gchar *hostname;
gshort port;
guint port;
int sd;
guint8 *buf;
guint32 buf_size;
guint32 buf_len;
};
typedef struct _ThriftSocketClass ThriftSocketClass;

View file

@ -0,0 +1,806 @@
/*
* 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 <glib-object.h>
#include <glib.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;
/* 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)
/**
* 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)
{
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) {
thrift_ssl_socket_get_ssl_error(ssl_socket, "Check socket data",
THRIFT_SSL_SOCKET_ERROR_SSL, rc, error);
}
if (rc == 0) {
ERR_clear_error();
}
retval = (rc > 0);
}
return retval;
}
/* implements thrift_transport_open */
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)) {
thrift_ssl_socket_close(transport, NULL);
return FALSE;
}
return TRUE;
}
/* implements thrift_transport_close */
gboolean
thrift_ssl_socket_close (ThriftTransport *transport, GError **error)
{
gboolean retval = FALSE;
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(ssl_socket->ssl);
ssl_socket->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;
ThriftSocket *socket = THRIFT_SOCKET (transport);
g_return_val_if_fail (socket->sd != THRIFT_INVALID_SOCKET && ssl_socket->ssl!=NULL, FALSE);
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;
}
}else{
thrift_ssl_socket_get_ssl_error(ssl_socket, "Receive error",
THRIFT_SSL_SOCKET_ERROR_SSL, bytes, error);
}
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_SOCKET (transport);
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)
{
thrift_ssl_socket_get_ssl_error(ssl_socket, "Send error",
THRIFT_SSL_SOCKET_ERROR_SSL, ret, error);
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;
ThriftSocket *socket = THRIFT_SOCKET (transport);
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) {
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) {
thrift_ssl_socket_get_ssl_error(ssl_socket, "Error while connect/bind", THRIFT_SSL_SOCKET_ERROR_CONNECT_BIND, rc, error);
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 default SSL context");
return FALSE;
}
}
return TRUE;
}
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;
}
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) {
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_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;
}
/* 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;
if(socket!=NULL){
g_debug("Instance %p destroyed", (void *)socket);
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)
{
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);
/* 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;
SSL_CTX *ssl_context = NULL;
/* Create the context */
if((ssl_context=thrift_ssl_socket_context_initialize(ssl_protocol, error))==NULL){
g_warning("We cannot initialize context for protocol %d", ssl_protocol);
return thriftSSLSocket;
}
/* FIXME if the protocol is different? */
thriftSSLSocket = g_object_new (THRIFT_TYPE_SSL_SOCKET, "ssl_context", ssl_context, NULL);
return thriftSSLSocket;
}
ThriftSSLSocket*
thrift_ssl_socket_new_with_host(ThriftSSLSocketProtocol ssl_protocol, gchar *hostname, guint port, GError **error)
{
ThriftSSLSocket *thriftSSLSocket = NULL;
SSL_CTX *ssl_context = NULL;
/* Create the context */
if((ssl_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", ssl_context, "hostname", hostname, "port", port, 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;
}
}
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("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. */
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;
}

View file

@ -0,0 +1,218 @@
/*
* 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_CONNECT_BIND,
THRIFT_SSL_SOCKET_ERROR_CIPHER_NOT_AVAILABLE,
THRIFT_SSL_SOCKET_ERROR_SSL,
THRIFT_SSL_SOCKET_ERROR_SSL_CERT_VALIDATION_FAILED
} 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 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 */
/**
* Convenience function to create a new SSL context with the protocol specified
* and assign this new context to the created ThriftSSLSocket with specified host:port.
* @param ssl_protocol
* @param hostname
* @param port
* @param error
* @return
*/
ThriftSSLSocket*
thrift_ssl_socket_new_with_host(ThriftSSLSocketProtocol ssl_protocol, gchar *hostname, guint port, GError **error);
/**
* Convenience function to create a new SSL context with the protocol specified
* and assign this new context to the created ThriftSSLSocket.
* @param ssl_protocol
* @param error
* @return
*/
ThriftSSLSocket*
thrift_ssl_socket_new(ThriftSSLSocketProtocol ssl_protocol, GError **error);
/**
* Load a certificate chain from a PEM file.
* @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);
/**
* 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[]);
/**
* Check if the ssl socket is open and ready to send and receive
* @param transport
* @return true if open
*/
gboolean
thrift_ssl_socket_is_open (ThriftTransport *transport);
/**
* Open connection if required and set the socket to be ready to send and receive
* @param transport
* @param error
* @return true if operation was correct
*/
gboolean
thrift_ssl_socket_open (ThriftTransport *transport, GError **error);
/**
* @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

View file

@ -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)

View file

@ -37,16 +37,17 @@ BUILT_SOURCES = \
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 @@ testtransportsocket_LDADD = \
$(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 \
@ -226,8 +237,6 @@ nodist_libtestgencpp_la_SOURCES = \
gen-cpp/ThriftTest_types.h
libtestgencpp_la_CPPFLAGS = -I../../cpp/src $(BOOST_CPPFLAGS) -I./gen-cpp
THRIFT = $(top_builddir)/compiler/cpp/thrift
gen-c_glib/t_test_container_test_types.c gen-c_glib/t_test_container_test_types.h gen-c_glib/t_test_container_service.c gen-c_glib/t_test_container_service.h: ContainerTest.thrift $(THRIFT)
$(THRIFT) --gen c_glib $<

View file

@ -19,7 +19,7 @@
/* Disable string-function optimizations when glibc is used, as these produce
compiler warnings about string length when a string function is used inside
a call to assert () */
a call to g_assert () */
#ifdef __GLIBC__
#include <features.h>
#define __NO_STRING_INLINES 1
@ -28,7 +28,6 @@
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <netdb.h>
#include <string.h>
#include <sys/wait.h>
@ -96,7 +95,7 @@ test_create_and_destroy(void)
/* create an object and then destroy it */
object = g_object_new (THRIFT_TYPE_BINARY_PROTOCOL, NULL);
assert (object != NULL);
g_assert (object != NULL);
g_object_unref (object);
}
@ -110,11 +109,11 @@ test_initialize(void)
/* create a ThriftTransport */
tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost",
"port", 51188, NULL);
assert (tsocket != NULL);
g_assert (tsocket != NULL);
/* create a ThriftBinaryProtocol using the Transport */
protocol = g_object_new (THRIFT_TYPE_BINARY_PROTOCOL, "transport",
tsocket, NULL);
assert (protocol != NULL);
g_assert (protocol != NULL);
/* fetch the properties */
g_object_get (G_OBJECT(protocol), "transport", &temp, NULL);
g_object_unref (temp);
@ -139,7 +138,7 @@ test_read_and_write_primitives(void)
/* fork a server from the client */
pid = fork ();
assert (pid >= 0);
g_assert (pid >= 0);
if (pid == 0)
{
@ -155,47 +154,48 @@ test_read_and_write_primitives(void)
"port", port, NULL);
transport = THRIFT_TRANSPORT (tsocket);
thrift_transport_open (transport, NULL);
assert (thrift_transport_is_open (transport));
g_assert (thrift_transport_is_open (transport));
/* create a ThriftBinaryTransport */
tb = g_object_new (THRIFT_TYPE_BINARY_PROTOCOL, "transport",
tsocket, NULL);
protocol = THRIFT_PROTOCOL (tb);
assert (protocol != NULL);
g_assert (protocol != NULL);
/* write a bunch of primitives */
assert (thrift_binary_protocol_write_bool (protocol, TEST_BOOL, NULL) > 0);
assert (thrift_binary_protocol_write_byte (protocol, TEST_BYTE, NULL) > 0);
assert (thrift_binary_protocol_write_i16 (protocol, TEST_I16, NULL) > 0);
assert (thrift_binary_protocol_write_i32 (protocol, TEST_I32, NULL) > 0);
assert (thrift_binary_protocol_write_i64 (protocol, TEST_I64, NULL) > 0);
assert (thrift_binary_protocol_write_double (protocol,
g_assert (thrift_binary_protocol_write_bool (protocol, TEST_BOOL, NULL) > 0);
g_assert (thrift_binary_protocol_write_byte (protocol, TEST_BYTE, NULL) > 0);
g_assert (thrift_binary_protocol_write_i16 (protocol, TEST_I16, NULL) > 0);
g_assert (thrift_binary_protocol_write_i32 (protocol, TEST_I32, NULL) > 0);
g_assert (thrift_binary_protocol_write_i64 (protocol, TEST_I64, NULL) > 0);
g_assert (thrift_binary_protocol_write_double (protocol,
TEST_DOUBLE, NULL) > 0);
assert (thrift_binary_protocol_write_string (protocol,
g_assert (thrift_binary_protocol_write_string (protocol,
TEST_STRING, NULL) > 0);
assert (thrift_binary_protocol_write_binary (protocol, binary,
g_assert (thrift_binary_protocol_write_string (protocol, "", NULL) > 0);
g_assert (thrift_binary_protocol_write_binary (protocol, binary,
len, NULL) > 0);
assert (thrift_binary_protocol_write_binary (protocol, NULL, 0, NULL) > 0);
assert (thrift_binary_protocol_write_binary (protocol, binary,
g_assert (thrift_binary_protocol_write_binary (protocol, NULL, 0, NULL) > 0);
g_assert (thrift_binary_protocol_write_binary (protocol, binary,
len, NULL) > 0);
/* test write errors */
transport_write_error = 1;
assert (thrift_binary_protocol_write_byte (protocol, TEST_BYTE,
g_assert (thrift_binary_protocol_write_byte (protocol, TEST_BYTE,
NULL) == -1);
assert (thrift_binary_protocol_write_i16 (protocol, TEST_I16, NULL) == -1);
assert (thrift_binary_protocol_write_i32 (protocol, TEST_I32, NULL) == -1);
assert (thrift_binary_protocol_write_i64 (protocol, TEST_I64, NULL) == -1);
assert (thrift_binary_protocol_write_double (protocol, TEST_DOUBLE,
g_assert (thrift_binary_protocol_write_i16 (protocol, TEST_I16, NULL) == -1);
g_assert (thrift_binary_protocol_write_i32 (protocol, TEST_I32, NULL) == -1);
g_assert (thrift_binary_protocol_write_i64 (protocol, TEST_I64, NULL) == -1);
g_assert (thrift_binary_protocol_write_double (protocol, TEST_DOUBLE,
NULL) == -1);
assert (thrift_binary_protocol_write_binary (protocol, binary, len,
g_assert (thrift_binary_protocol_write_binary (protocol, binary, len,
NULL) == -1);
transport_write_error = 0;
/* test binary partial failure */
transport_write_count = 0;
transport_write_error_at = 1;
assert (thrift_binary_protocol_write_binary (protocol, binary,
g_assert (thrift_binary_protocol_write_binary (protocol, binary,
len, NULL) == -1);
transport_write_error_at = -1;
@ -203,8 +203,8 @@ test_read_and_write_primitives(void)
thrift_transport_close (transport, NULL);
g_object_unref (tsocket);
g_object_unref (protocol);
assert (wait (&status) == pid);
assert (status == 0);
g_assert (wait (&status) == pid);
g_assert (status == 0);
}
}
@ -221,7 +221,7 @@ test_read_and_write_complex_types (void)
/* fork a server from the client */
pid = fork ();
assert (pid >= 0);
g_assert (pid >= 0);
if (pid == 0)
{
@ -237,33 +237,33 @@ test_read_and_write_complex_types (void)
"port", port, NULL);
transport = THRIFT_TRANSPORT (tsocket);
thrift_transport_open (transport, NULL);
assert (thrift_transport_is_open (transport));
g_assert (thrift_transport_is_open (transport));
/* create a ThriftBinaryTransport */
tb = g_object_new (THRIFT_TYPE_BINARY_PROTOCOL, "transport",
tsocket, NULL);
protocol = THRIFT_PROTOCOL (tb);
assert (protocol != NULL);
g_assert (protocol != NULL);
/* test structures */
assert (thrift_binary_protocol_write_struct_begin (protocol,
g_assert (thrift_binary_protocol_write_struct_begin (protocol,
NULL, NULL) == 0);
assert (thrift_binary_protocol_write_struct_end (protocol, NULL) == 0);
g_assert (thrift_binary_protocol_write_struct_end (protocol, NULL) == 0);
assert (thrift_binary_protocol_write_field_begin (protocol, "test", T_VOID,
g_assert (thrift_binary_protocol_write_field_begin (protocol, "test", T_VOID,
1, NULL) > 0);
assert (thrift_binary_protocol_write_field_end (protocol, NULL) == 0);
g_assert (thrift_binary_protocol_write_field_end (protocol, NULL) == 0);
/* test write error */
transport_write_error = 1;
assert (thrift_binary_protocol_write_field_begin (protocol, "test", T_VOID,
g_assert (thrift_binary_protocol_write_field_begin (protocol, "test", T_VOID,
1, NULL) == -1);
transport_write_error = 0;
/* test 2nd write error */
transport_write_count = 0;
transport_write_error_at = 1;
assert (thrift_binary_protocol_write_field_begin (protocol, "test", T_VOID,
g_assert (thrift_binary_protocol_write_field_begin (protocol, "test", T_VOID,
1, NULL) == -1);
transport_write_error_at = -1;
@ -271,12 +271,12 @@ test_read_and_write_complex_types (void)
thrift_binary_protocol_write_byte (protocol, T_VOID, NULL);
/* test write_field_stop */
assert (thrift_binary_protocol_write_field_stop (protocol, NULL) > 0);
g_assert (thrift_binary_protocol_write_field_stop (protocol, NULL) > 0);
/* write a map */
assert (thrift_binary_protocol_write_map_begin (protocol, T_VOID, T_VOID,
g_assert (thrift_binary_protocol_write_map_begin (protocol, T_VOID, T_VOID,
1, NULL) > 0);
assert (thrift_binary_protocol_write_map_end (protocol, NULL) == 0);
g_assert (thrift_binary_protocol_write_map_end (protocol, NULL) == 0);
/* test 2nd read failure on a map */
thrift_binary_protocol_write_byte (protocol, T_VOID, NULL);
@ -287,21 +287,21 @@ test_read_and_write_complex_types (void)
/* test 1st write failure on a map */
transport_write_error = 1;
assert (thrift_binary_protocol_write_map_begin (protocol, T_VOID, T_VOID,
g_assert (thrift_binary_protocol_write_map_begin (protocol, T_VOID, T_VOID,
1, NULL) == -1);
transport_write_error = 0;
/* test 2nd write failure on a map */
transport_write_count = 0;
transport_write_error_at = 1;
assert (thrift_binary_protocol_write_map_begin (protocol, T_VOID, T_VOID,
g_assert (thrift_binary_protocol_write_map_begin (protocol, T_VOID, T_VOID,
1, NULL) == -1);
transport_write_error_at = -1;
/* test 3rd write failure on a map */
transport_write_count = 0;
transport_write_error_at = 2;
assert (thrift_binary_protocol_write_map_begin (protocol, T_VOID, T_VOID,
g_assert (thrift_binary_protocol_write_map_begin (protocol, T_VOID, T_VOID,
1, NULL) == -1);
transport_write_error_at = -1;
@ -311,9 +311,9 @@ test_read_and_write_complex_types (void)
thrift_binary_protocol_write_i32 (protocol, -10, NULL);
/* test list operations */
assert (thrift_binary_protocol_write_list_begin (protocol, T_VOID,
g_assert (thrift_binary_protocol_write_list_begin (protocol, T_VOID,
1, NULL) > 0);
assert (thrift_binary_protocol_write_list_end (protocol, NULL) == 0);
g_assert (thrift_binary_protocol_write_list_end (protocol, NULL) == 0);
/* test 2nd read failure on a list */
thrift_binary_protocol_write_byte (protocol, T_VOID, NULL);
@ -324,27 +324,27 @@ test_read_and_write_complex_types (void)
/* test first write error on a list */
transport_write_error = 1;
assert (thrift_binary_protocol_write_list_begin (protocol, T_VOID,
g_assert (thrift_binary_protocol_write_list_begin (protocol, T_VOID,
1, NULL) == -1);
transport_write_error = 0;
/* test 2nd write error on a list */
transport_write_count = 0;
transport_write_error_at = 1;
assert (thrift_binary_protocol_write_list_begin (protocol, T_VOID,
g_assert (thrift_binary_protocol_write_list_begin (protocol, T_VOID,
1, NULL) == -1);
transport_write_error_at = -1;
/* test set operation s*/
assert (thrift_binary_protocol_write_set_begin (protocol, T_VOID,
g_assert (thrift_binary_protocol_write_set_begin (protocol, T_VOID,
1, NULL) > 0);
assert (thrift_binary_protocol_write_set_end (protocol, NULL) == 0);
g_assert (thrift_binary_protocol_write_set_end (protocol, NULL) == 0);
/* invalid version */
assert (thrift_binary_protocol_write_i32 (protocol, -1, NULL) > 0);
g_assert (thrift_binary_protocol_write_i32 (protocol, -1, NULL) > 0);
/* sz > 0 for a message */
assert (thrift_binary_protocol_write_i32 (protocol, 1, NULL) > 0);
g_assert (thrift_binary_protocol_write_i32 (protocol, 1, NULL) > 0);
/* send a valid message */
thrift_binary_protocol_write_i32 (protocol, 0x80010000, NULL);
@ -359,26 +359,26 @@ test_read_and_write_complex_types (void)
thrift_binary_protocol_write_string (protocol, "test", NULL);
/* send a valid message */
assert (thrift_binary_protocol_write_message_begin (protocol, "test",
g_assert (thrift_binary_protocol_write_message_begin (protocol, "test",
T_CALL, 1, NULL) > 0);
assert (thrift_binary_protocol_write_message_end (protocol, NULL) == 0);
g_assert (thrift_binary_protocol_write_message_end (protocol, NULL) == 0);
/* send broken writes */
transport_write_error = 1;
assert (thrift_binary_protocol_write_message_begin (protocol, "test",
g_assert (thrift_binary_protocol_write_message_begin (protocol, "test",
T_CALL, 1, NULL) == -1);
transport_write_error = 0;
transport_write_count = 0;
transport_write_error_at = 2;
assert (thrift_binary_protocol_write_message_begin (protocol, "test",
g_assert (thrift_binary_protocol_write_message_begin (protocol, "test",
T_CALL, 1, NULL) == -1);
transport_write_error_at = -1;
transport_write_count = 0;
transport_write_error_at = 3;
assert (thrift_binary_protocol_write_message_begin (protocol, "test",
g_assert (thrift_binary_protocol_write_message_begin (protocol, "test",
T_CALL, 1, NULL) == -1);
transport_write_error_at = -1;
@ -386,8 +386,8 @@ test_read_and_write_complex_types (void)
thrift_transport_close (transport, NULL);
g_object_unref (tsocket);
g_object_unref (protocol);
assert (wait (&status) == pid);
assert (status == 0);
g_assert (wait (&status) == pid);
g_assert (status == 0);
}
}
@ -407,7 +407,7 @@ test_read_and_write_many_frames (void)
/* fork a server from the client */
pid = fork ();
assert (pid >= 0);
g_assert (pid >= 0);
if (pid == 0)
{
@ -421,47 +421,49 @@ test_read_and_write_many_frames (void)
/* create a ThriftSocket */
tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost",
"port", port, NULL);
assert (tsocket != NULL);
g_assert (tsocket != NULL);
transport = THRIFT_TRANSPORT (tsocket);
/* wrap in a framed transport */
ft = g_object_new (THRIFT_TYPE_FRAMED_TRANSPORT, "transport", transport,
"w_buf_size", 1, NULL);
assert (ft != NULL);
g_assert (ft != NULL);
transport = THRIFT_TRANSPORT (ft);
thrift_transport_open (transport, NULL);
assert (thrift_transport_is_open (transport));
g_assert (thrift_transport_is_open (transport));
/* create a binary protocol */
tb = g_object_new (THRIFT_TYPE_BINARY_PROTOCOL, "transport",
transport, NULL);
protocol = THRIFT_PROTOCOL (tb);
assert (protocol != NULL);
g_assert (protocol != NULL);
/* write a bunch of primitives */
assert (thrift_binary_protocol_write_bool (protocol, TEST_BOOL, NULL) > 0);
g_assert (thrift_binary_protocol_write_bool (protocol, TEST_BOOL, NULL) > 0);
thrift_transport_flush (transport, NULL);
assert (thrift_binary_protocol_write_byte (protocol, TEST_BYTE, NULL) > 0);
g_assert (thrift_binary_protocol_write_byte (protocol, TEST_BYTE, NULL) > 0);
thrift_transport_flush (transport, NULL);
assert (thrift_binary_protocol_write_i16 (protocol, TEST_I16, NULL) > 0);
g_assert (thrift_binary_protocol_write_i16 (protocol, TEST_I16, NULL) > 0);
thrift_transport_flush (transport, NULL);
assert (thrift_binary_protocol_write_i32 (protocol, TEST_I32, NULL) > 0);
g_assert (thrift_binary_protocol_write_i32 (protocol, TEST_I32, NULL) > 0);
thrift_transport_flush (transport, NULL);
assert (thrift_binary_protocol_write_i64 (protocol, TEST_I64, NULL) > 0);
g_assert (thrift_binary_protocol_write_i64 (protocol, TEST_I64, NULL) > 0);
thrift_transport_flush (transport, NULL);
assert (thrift_binary_protocol_write_double (protocol,
g_assert (thrift_binary_protocol_write_double (protocol,
TEST_DOUBLE, NULL) > 0);
thrift_transport_flush (transport, NULL);
assert (thrift_binary_protocol_write_string (protocol,
g_assert (thrift_binary_protocol_write_string (protocol,
TEST_STRING, NULL) > 0);
thrift_transport_flush (transport, NULL);
assert (thrift_binary_protocol_write_binary (protocol, binary,
g_assert (thrift_binary_protocol_write_string (protocol, "", NULL) > 0);
thrift_transport_flush (transport, NULL);
g_assert (thrift_binary_protocol_write_binary (protocol, binary,
len, NULL) > 0);
thrift_transport_flush (transport, NULL);
assert (thrift_binary_protocol_write_binary (protocol, NULL, 0, NULL) > 0);
g_assert (thrift_binary_protocol_write_binary (protocol, NULL, 0, NULL) > 0);
thrift_transport_flush (transport, NULL);
assert (thrift_binary_protocol_write_binary (protocol, binary,
g_assert (thrift_binary_protocol_write_binary (protocol, binary,
len, NULL) > 0);
thrift_transport_flush (transport, NULL);
@ -471,8 +473,8 @@ test_read_and_write_many_frames (void)
g_object_unref (ft);
g_object_unref (tsocket);
g_object_unref (tb);
assert (wait (&status) == pid);
assert (status == 0);
g_assert (wait (&status) == pid);
g_assert (status == 0);
}
}
@ -491,6 +493,7 @@ thrift_server_primitives (const int port)
gint64 value_64 = 0;
gdouble value_double = 0;
gchar *string = NULL;
gchar *empty_string = NULL;
gpointer binary = NULL;
guint32 len = 0;
void *comparator = (void *) TEST_STRING;
@ -500,61 +503,68 @@ thrift_server_primitives (const int port)
transport = THRIFT_SERVER_TRANSPORT (tsocket);
thrift_server_transport_listen (transport, NULL);
client = thrift_server_transport_accept (transport, NULL);
assert (client != NULL);
g_assert (client != NULL);
tbp = g_object_new (THRIFT_TYPE_BINARY_PROTOCOL, "transport",
client, NULL);
protocol = THRIFT_PROTOCOL (tbp);
assert (thrift_binary_protocol_read_bool (protocol,
g_assert (thrift_binary_protocol_read_bool (protocol,
&value_boolean, NULL) > 0);
assert (thrift_binary_protocol_read_byte (protocol, &value_byte, NULL) > 0);
assert (thrift_binary_protocol_read_i16 (protocol, &value_16, NULL) > 0);
assert (thrift_binary_protocol_read_i32 (protocol, &value_32, NULL) > 0);
assert (thrift_binary_protocol_read_i64 (protocol, &value_64, NULL) > 0);
assert (thrift_binary_protocol_read_double (protocol,
g_assert (thrift_binary_protocol_read_byte (protocol, &value_byte, NULL) > 0);
g_assert (thrift_binary_protocol_read_i16 (protocol, &value_16, NULL) > 0);
g_assert (thrift_binary_protocol_read_i32 (protocol, &value_32, NULL) > 0);
g_assert (thrift_binary_protocol_read_i64 (protocol, &value_64, NULL) > 0);
g_assert (thrift_binary_protocol_read_double (protocol,
&value_double, NULL) > 0);
assert (thrift_binary_protocol_read_string (protocol, &string, NULL) > 0);
assert (thrift_binary_protocol_read_binary (protocol, &binary,
g_assert (thrift_binary_protocol_read_string (protocol, &string, NULL) > 0);
g_assert (thrift_binary_protocol_read_string (protocol, &empty_string,
NULL) > 0);
g_assert (thrift_binary_protocol_read_binary (protocol, &binary,
&len, NULL) > 0);
assert (value_boolean == TEST_BOOL);
assert (value_byte == TEST_BYTE);
assert (value_16 == TEST_I16);
assert (value_32 == TEST_I32);
assert (value_64 == TEST_I64);
assert (value_double == TEST_DOUBLE);
assert (strcmp (TEST_STRING, string) == 0);
assert (memcmp (comparator, binary, len) == 0);
g_assert (value_boolean == TEST_BOOL);
g_assert (value_byte == TEST_BYTE);
g_assert (value_16 == TEST_I16);
g_assert (value_32 == TEST_I32);
g_assert (value_64 == TEST_I64);
g_assert (value_double == TEST_DOUBLE);
g_assert (strcmp (TEST_STRING, string) == 0);
g_assert (strcmp ("", empty_string) == 0);
g_assert (memcmp (comparator, binary, len) == 0);
g_free (string);
g_free (empty_string);
g_free (binary);
thrift_binary_protocol_read_binary (protocol, &binary, &len, NULL);
g_assert (thrift_binary_protocol_read_binary (protocol, &binary,
&len, NULL) > 0);
g_assert (binary == NULL);
g_assert (len == 0);
g_free (binary);
transport_read_count = 0;
transport_read_error_at = 0;
assert (thrift_binary_protocol_read_binary (protocol, &binary,
g_assert (thrift_binary_protocol_read_binary (protocol, &binary,
&len, NULL) == -1);
transport_read_error_at = -1;
transport_read_count = 0;
transport_read_error_at = 1;
assert (thrift_binary_protocol_read_binary (protocol, &binary,
g_assert (thrift_binary_protocol_read_binary (protocol, &binary,
&len, NULL) == -1);
transport_read_error_at = -1;
transport_read_error = 1;
assert (thrift_binary_protocol_read_bool (protocol,
g_assert (thrift_binary_protocol_read_bool (protocol,
&value_boolean, NULL) == -1);
assert (thrift_binary_protocol_read_byte (protocol,
g_assert (thrift_binary_protocol_read_byte (protocol,
&value_byte, NULL) == -1);
assert (thrift_binary_protocol_read_i16 (protocol,
g_assert (thrift_binary_protocol_read_i16 (protocol,
&value_16, NULL) == -1);
assert (thrift_binary_protocol_read_i32 (protocol, &value_32, NULL) == -1);
assert (thrift_binary_protocol_read_i64 (protocol, &value_64, NULL) == -1);
assert (thrift_binary_protocol_read_double (protocol,
g_assert (thrift_binary_protocol_read_i32 (protocol, &value_32, NULL) == -1);
g_assert (thrift_binary_protocol_read_i64 (protocol, &value_64, NULL) == -1);
g_assert (thrift_binary_protocol_read_double (protocol,
&value_double, NULL) == -1);
transport_read_error = 0;
@ -592,7 +602,7 @@ thrift_server_complex_types (const int port)
transport = THRIFT_SERVER_TRANSPORT (tsocket);
thrift_server_transport_listen (transport, NULL);
client = thrift_server_transport_accept (transport, NULL);
assert (client != NULL);
g_assert (client != NULL);
tbp = g_object_new (THRIFT_TYPE_BINARY_PROTOCOL, "transport",
client, NULL);
@ -607,7 +617,7 @@ thrift_server_complex_types (const int port)
/* test first read error on a field */
transport_read_error = 1;
assert (thrift_binary_protocol_read_field_begin (protocol,
g_assert (thrift_binary_protocol_read_field_begin (protocol,
&field_name, &field_type,
&field_id, NULL) == -1);
transport_read_error = 0;
@ -618,7 +628,7 @@ thrift_server_complex_types (const int port)
/* test 2nd read failure on a field */
transport_read_count = 0;
transport_read_error_at = 1;
assert (thrift_binary_protocol_read_field_begin (protocol,
g_assert (thrift_binary_protocol_read_field_begin (protocol,
&field_name, &field_type,
&field_id, NULL) == -1);
transport_read_error_at = -1;
@ -634,7 +644,7 @@ thrift_server_complex_types (const int port)
/* test read failure on a map */
transport_read_count = 0;
transport_read_error_at = 0;
assert (thrift_binary_protocol_read_map_begin (protocol,
g_assert (thrift_binary_protocol_read_map_begin (protocol,
&key_type, &value_type,
&size, NULL) == -1);
transport_read_error_at = -1;
@ -642,7 +652,7 @@ thrift_server_complex_types (const int port)
/* test 2nd read failure on a map */
transport_read_count = 0;
transport_read_error_at = 1;
assert (thrift_binary_protocol_read_map_begin (protocol,
g_assert (thrift_binary_protocol_read_map_begin (protocol,
&key_type, &value_type,
&size, NULL) == -1);
transport_read_error_at = -1;
@ -650,7 +660,7 @@ thrift_server_complex_types (const int port)
/* test 3rd read failure on a map */
transport_read_count = 0;
transport_read_error_at = 2;
assert (thrift_binary_protocol_read_map_begin (protocol,
g_assert (thrift_binary_protocol_read_map_begin (protocol,
&key_type, &value_type,
&size, NULL) == -1);
transport_read_error_at = -1;
@ -663,7 +673,7 @@ thrift_server_complex_types (const int port)
thrift_binary_protocol_read_byte (protocol, &value, NULL);
/* test negative map size */
assert (thrift_binary_protocol_read_map_begin (protocol,
g_assert (thrift_binary_protocol_read_map_begin (protocol,
&key_type, &value_type,
&size, NULL) == -1);
@ -673,7 +683,7 @@ thrift_server_complex_types (const int port)
/* test read failure */
transport_read_error = 1;
assert (thrift_binary_protocol_read_list_begin (protocol, &element_type,
g_assert (thrift_binary_protocol_read_list_begin (protocol, &element_type,
&size, NULL) == -1);
transport_read_error = 0;
@ -695,23 +705,23 @@ thrift_server_complex_types (const int port)
/* broken read */
transport_read_error = 1;
assert (thrift_binary_protocol_read_message_begin (protocol, &message_name,
g_assert (thrift_binary_protocol_read_message_begin (protocol, &message_name,
&message_type, &seqid,
NULL) == -1);
transport_read_error = 0;
/* invalid protocol version */
assert (thrift_binary_protocol_read_message_begin (protocol, &message_name,
g_assert (thrift_binary_protocol_read_message_begin (protocol, &message_name,
&message_type, &seqid,
NULL) == -1);
/* sz > 0 */
assert (thrift_binary_protocol_read_message_begin (protocol, &message_name,
g_assert (thrift_binary_protocol_read_message_begin (protocol, &message_name,
&message_type, &seqid,
NULL) > 0);
/* read a valid message */
assert (thrift_binary_protocol_read_message_begin (protocol, &message_name,
g_assert (thrift_binary_protocol_read_message_begin (protocol, &message_name,
&message_type, &seqid,
NULL) > 0);
g_free (message_name);
@ -719,7 +729,7 @@ thrift_server_complex_types (const int port)
/* broken 2nd read on a message */
transport_read_count = 0;
transport_read_error_at = 1;
assert (thrift_binary_protocol_read_message_begin (protocol, &message_name,
g_assert (thrift_binary_protocol_read_message_begin (protocol, &message_name,
&message_type, &seqid,
NULL) == -1);
transport_read_error_at = -1;
@ -727,19 +737,19 @@ thrift_server_complex_types (const int port)
/* broken 3rd read on a message */
transport_read_count = 0;
transport_read_error_at = 3; /* read_string does two reads */
assert (thrift_binary_protocol_read_message_begin (protocol, &message_name,
g_assert (thrift_binary_protocol_read_message_begin (protocol, &message_name,
&message_type, &seqid,
NULL) == -1);
g_free (message_name);
transport_read_error_at = -1;
/* read a valid message */
assert (thrift_binary_protocol_read_message_begin (protocol, &message_name,
g_assert (thrift_binary_protocol_read_message_begin (protocol, &message_name,
&message_type, &seqid,
NULL) > 0);
g_free (message_name);
assert (thrift_binary_protocol_read_message_end (protocol, NULL) == 0);
g_assert (thrift_binary_protocol_read_message_end (protocol, NULL) == 0);
/* handle 2nd write failure on a message */
thrift_binary_protocol_read_i32 (protocol, &version, NULL);
@ -768,6 +778,7 @@ thrift_server_many_frames (const int port)
gint64 value_64 = 0;
gdouble value_double = 0;
gchar *string = NULL;
gchar *empty_string = NULL;
gpointer binary = NULL;
guint32 len = 0;
void *comparator = (void *) TEST_STRING;
@ -780,34 +791,44 @@ thrift_server_many_frames (const int port)
client = g_object_new (THRIFT_TYPE_FRAMED_TRANSPORT, "transport",
thrift_server_transport_accept (transport, NULL),
"r_buf_size", 1, NULL);
assert (client != NULL);
g_assert (client != NULL);
tbp = g_object_new (THRIFT_TYPE_BINARY_PROTOCOL, "transport",
client, NULL);
protocol = THRIFT_PROTOCOL (tbp);
assert (thrift_binary_protocol_read_bool (protocol,
g_assert (thrift_binary_protocol_read_bool (protocol,
&value_boolean, NULL) > 0);
assert (thrift_binary_protocol_read_byte (protocol, &value_byte, NULL) > 0);
assert (thrift_binary_protocol_read_i16 (protocol, &value_16, NULL) > 0);
assert (thrift_binary_protocol_read_i32 (protocol, &value_32, NULL) > 0);
assert (thrift_binary_protocol_read_i64 (protocol, &value_64, NULL) > 0);
assert (thrift_binary_protocol_read_double (protocol,
g_assert (thrift_binary_protocol_read_byte (protocol, &value_byte, NULL) > 0);
g_assert (thrift_binary_protocol_read_i16 (protocol, &value_16, NULL) > 0);
g_assert (thrift_binary_protocol_read_i32 (protocol, &value_32, NULL) > 0);
g_assert (thrift_binary_protocol_read_i64 (protocol, &value_64, NULL) > 0);
g_assert (thrift_binary_protocol_read_double (protocol,
&value_double, NULL) > 0);
assert (thrift_binary_protocol_read_string (protocol, &string, NULL) > 0);
assert (thrift_binary_protocol_read_binary (protocol, &binary,
g_assert (thrift_binary_protocol_read_string (protocol, &string, NULL) > 0);
g_assert (thrift_binary_protocol_read_string (protocol, &empty_string,
NULL) > 0);
g_assert (thrift_binary_protocol_read_binary (protocol, &binary,
&len, NULL) > 0);
assert (value_boolean == TEST_BOOL);
assert (value_byte == TEST_BYTE);
assert (value_16 == TEST_I16);
assert (value_32 == TEST_I32);
assert (value_64 == TEST_I64);
assert (value_double == TEST_DOUBLE);
assert (strcmp (TEST_STRING, string) == 0);
assert (memcmp (comparator, binary, len) == 0);
g_assert (value_boolean == TEST_BOOL);
g_assert (value_byte == TEST_BYTE);
g_assert (value_16 == TEST_I16);
g_assert (value_32 == TEST_I32);
g_assert (value_64 == TEST_I64);
g_assert (value_double == TEST_DOUBLE);
g_assert (strcmp (TEST_STRING, string) == 0);
g_assert (strcmp ("", empty_string) == 0);
g_assert (memcmp (comparator, binary, len) == 0);
g_free (string);
g_free (empty_string);
g_free (binary);
g_assert (thrift_binary_protocol_read_binary (protocol, &binary,
&len, NULL) > 0);
g_assert (binary == NULL);
g_assert (len == 0);
g_free (binary);
thrift_transport_read_end (client, NULL);

View file

@ -17,7 +17,6 @@
* under the License.
*/
#include <assert.h>
#include <netdb.h>
#include <signal.h>
#include <sys/wait.h>
@ -32,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
@ -43,10 +43,10 @@ test_create_and_destroy(void)
GObject *object = NULL;
object = g_object_new (THRIFT_TYPE_BUFFERED_TRANSPORT, NULL);
assert (object != 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);
}
@ -56,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);
pid = fork ();
g_assert ( pid >= 0 );
/* create a BufferedTransport wrapper of the Socket */
transport = g_object_new (THRIFT_TYPE_BUFFERED_TRANSPORT,
"transport", THRIFT_TRANSPORT (tsocket), 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);
/* this shouldn't work */
assert (thrift_buffered_transport_open (transport, NULL) == FALSE);
assert (thrift_buffered_transport_is_open (transport) == TRUE);
assert (thrift_buffered_transport_close (transport, NULL) == TRUE);
g_object_unref (transport);
g_object_unref (tsocket);
/* create a BufferedTransport wrapper of the Socket */
transport = g_object_new (THRIFT_TYPE_BUFFERED_TRANSPORT,
"transport", THRIFT_TRANSPORT (tsocket), NULL);
/* try and underlying socket failure */
tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost.broken",
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);
/* create a BufferedTransport wrapper of the Socket */
transport = g_object_new (THRIFT_TYPE_BUFFERED_TRANSPORT,
"transport", THRIFT_TRANSPORT (tsocket), NULL);
/* try and underlying socket failure */
tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost.broken",
NULL);
assert (thrift_buffered_transport_open (transport, &err) == FALSE);
g_object_unref (transport);
g_object_unref (tsocket);
g_error_free (err);
err = 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
@ -98,60 +115,84 @@ test_read_and_write(void)
guchar buf[10] = TEST_DATA; /* a buffer */
pid = fork ();
assert ( pid >= 0 );
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);
{
/* 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);
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);
assert (thrift_buffered_transport_open (transport, NULL) == TRUE);
assert (thrift_buffered_transport_is_open (transport));
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 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);
/* 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);
/* 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 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 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);
/* 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);
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_object_unref (transport);
g_object_unref (tsocket);
assert ( wait (&status) == pid );
assert ( status == 0 );
g_assert ( wait (&status) == pid );
g_assert ( status == 0 );
}
}
static void
thrift_socket_server_open (const int port, int times)
{
int bytes = 0;
ThriftServerTransport *transport = NULL;
ThriftTransport *client = NULL;
guchar buf[10]; /* a buffer */
guchar match[10] = TEST_DATA;
int i;
ThriftServerSocket *tsocket = g_object_new (THRIFT_TYPE_SERVER_SOCKET,
"port", port, NULL);
transport = THRIFT_SERVER_TRANSPORT (tsocket);
thrift_server_transport_listen (transport, NULL);
for(i=0;i<times;i++){
client = thrift_server_transport_accept (transport, NULL);
g_assert (client != NULL);
thrift_socket_close (client, NULL);
g_object_unref (client);
}
g_object_unref (tsocket);
}
static void
@ -164,21 +205,21 @@ 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);
assert (client != NULL);
thrift_server_transport_accept (transport, NULL),
"r_buf_size", 5, NULL);
g_assert (client != NULL);
/* read 10 bytes */
bytes = thrift_buffered_transport_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 */
g_assert (bytes == 10); /* make sure we've read 10 bytes */
g_assert ( memcmp (buf, match, 10) == 0 ); /* make sure what we got matches */
/* read 1 byte */
bytes = thrift_buffered_transport_read (client, buf, 1, NULL);
@ -207,65 +248,65 @@ test_write_fail(void)
signal(SIGPIPE, SIG_IGN);
pid = fork ();
assert ( pid >= 0 );
g_assert ( pid >= 0 );
if ( pid == 0 )
{
/* child listens */
ThriftServerTransport *transport = NULL;
ThriftTransport *client = NULL;
{
/* child listens */
ThriftServerTransport *transport = NULL;
ThriftTransport *client = NULL;
ThriftServerSocket *tsocket = g_object_new (THRIFT_TYPE_SERVER_SOCKET,
"port", port, NULL);
ThriftServerSocket *tsocket = g_object_new (THRIFT_TYPE_SERVER_SOCKET,
"port", port, NULL);
transport = THRIFT_SERVER_TRANSPORT (tsocket);
thrift_server_transport_listen (transport, 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);
assert (client != 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);
/* 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);
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);
assert (thrift_buffered_transport_open (transport, NULL) == TRUE);
assert (thrift_buffered_transport_is_open (transport));
g_assert (thrift_buffered_transport_open (transport, NULL) == TRUE);
g_assert (thrift_buffered_transport_is_open (transport));
/* recognize disconnection */
sleep(1);
assert (thrift_buffered_transport_write (transport, buf, 10, NULL) == TRUE);
assert (thrift_buffered_transport_write (transport, buf, 10, NULL) == FALSE);
/* 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 */
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 */
assert (thrift_buffered_transport_write (transport, buf, 1, NULL) == TRUE);
assert (thrift_buffered_transport_flush (transport, 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);
thrift_buffered_transport_close (transport, NULL);
g_object_unref (transport);
g_object_unref (tsocket);
g_object_unref (transport);
g_object_unref (tsocket);
assert ( wait (&status) == pid );
assert ( status == 0 );
}
g_assert ( wait (&status) == pid );
g_assert ( status == 0 );
}
}
int

File diff suppressed because it is too large Load diff

View file

@ -512,13 +512,12 @@ main(int argc, char *argv[])
THRIFT_SERVER_SOCKET_ERROR_ACCEPT));
/* Free our resources */
g_object_unref (server);
g_object_unref (transport_factory);
g_object_unref (protocol_factory);
g_object_unref (server_transport);
g_object_unref (processor);
g_object_unref (handler);
g_clear_object (&server);
g_clear_object (&protocol_factory);
g_clear_object (&transport_factory);
g_clear_object (&server_transport);
g_clear_object (&processor);
g_clear_object (&handler);
/* Wait for the child process to complete and return its exit status */
g_assert (wait (&status) == pid);
@ -527,4 +526,4 @@ main(int argc, char *argv[])
return exit_status;
}
}
}

View file

@ -17,7 +17,6 @@
* under the License.
*/
#include <assert.h>
#include <math.h>
#include <string.h>
#include <glib-object.h>
@ -838,11 +837,11 @@ test_services_inherited (void)
NULL);
/* TTestInheritedClient inherits from TTestSrvClient */
assert (g_type_is_a (T_TEST_TYPE_INHERITED_CLIENT,
g_assert (g_type_is_a (T_TEST_TYPE_INHERITED_CLIENT,
T_TEST_TYPE_SRV_CLIENT));
/* TTestInheritedClient implements TTestSrvClient's interface */
assert (g_type_is_a (T_TEST_TYPE_INHERITED_CLIENT,
g_assert (g_type_is_a (T_TEST_TYPE_INHERITED_CLIENT,
T_TEST_TYPE_SRV_IF));
/* TTestInheritedClient's inherited properties can be set and retrieved */
@ -856,8 +855,8 @@ test_services_inherited (void)
"output_protocol", &output_protocol,
NULL);
assert (input_protocol == G_OBJECT(protocol));
assert (output_protocol == G_OBJECT(protocol));
g_assert (input_protocol == G_OBJECT(protocol));
g_assert (output_protocol == G_OBJECT(protocol));
g_object_unref (output_protocol);
g_object_unref (input_protocol);

View file

@ -17,7 +17,6 @@
* under the License.
*/
#include <assert.h>
#include <string.h>
#include <fcntl.h>
@ -37,7 +36,7 @@ test_create_and_destroy (void)
{
GObject *object;
object = g_object_new (THRIFT_TYPE_FD_TRANSPORT, "fd", -1, NULL);
assert (object != NULL);
g_assert (object != NULL);
g_object_unref (object);
}
@ -54,7 +53,7 @@ test_open_and_close (void)
filename = NULL;
fd = g_file_open_tmp (NULL, &filename, &error);
assert (fd >= 0);
g_assert (fd >= 0);
transport = THRIFT_TRANSPORT (g_object_new (THRIFT_TYPE_FD_TRANSPORT,
"fd", fd,
@ -62,20 +61,20 @@ test_open_and_close (void)
klass = THRIFT_TRANSPORT_GET_CLASS (transport);
/* open is no-op */
assert (klass->is_open (transport));
assert (klass->peek (transport, &error));
assert (klass->open (transport, &error));
assert (klass->is_open (transport));
assert (klass->peek (transport, &error));
g_assert (klass->is_open (transport));
g_assert (klass->peek (transport, &error));
g_assert (klass->open (transport, &error));
g_assert (klass->is_open (transport));
g_assert (klass->peek (transport, &error));
assert (klass->close (transport, &error));
assert (! klass->open (transport, &error));
assert (! klass->is_open (transport));
assert (! klass->peek (transport, &error));
g_assert (klass->close (transport, &error));
g_assert (! klass->open (transport, &error));
g_assert (! klass->is_open (transport));
g_assert (! klass->peek (transport, &error));
/* already closed */
assert (close (fd) != 0);
assert (errno == EBADF);
g_assert (close (fd) != 0);
g_assert (errno == EBADF);
g_object_unref (transport);
@ -88,13 +87,13 @@ test_open_and_close (void)
NULL));
klass = THRIFT_TRANSPORT_GET_CLASS (transport);
assert (! klass->is_open (transport));
g_assert (! klass->is_open (transport));
error = NULL;
assert (! klass->peek (transport, &error));
g_assert (! klass->peek (transport, &error));
error = NULL;
assert (! klass->open (transport, &error));
g_assert (! klass->open (transport, &error));
error = NULL;
assert (! klass->close (transport, &error));
g_assert (! klass->close (transport, &error));
g_object_unref (transport);
}
@ -115,22 +114,22 @@ test_read_and_write (void)
filename = NULL;
fd = g_file_open_tmp (NULL, &filename, &error);
assert (fd >= 0);
g_assert (fd >= 0);
/* write */
transport = THRIFT_TRANSPORT (g_object_new (THRIFT_TYPE_FD_TRANSPORT,
"fd", fd,
NULL));
klass = THRIFT_TRANSPORT_GET_CLASS (transport);
assert (klass->is_open (transport));
assert (klass->write (transport, (gpointer) TEST_DATA, 11, &error));
assert (klass->flush (transport, &error));
assert (klass->close (transport, &error));
g_assert (klass->is_open (transport));
g_assert (klass->write (transport, (gpointer) TEST_DATA, 11, &error));
g_assert (klass->flush (transport, &error));
g_assert (klass->close (transport, &error));
g_object_unref (transport);
/* read */
fd = open(filename, O_RDONLY, S_IRUSR | S_IWUSR);
assert (fd >= 0);
g_assert (fd >= 0);
transport = THRIFT_TRANSPORT (g_object_new (THRIFT_TYPE_FD_TRANSPORT,
"fd", fd,
@ -142,24 +141,24 @@ test_read_and_write (void)
want = 7;
while (want > 0) {
got = klass->read (transport, (gpointer) b, want, &error);
assert (got > 0 && got <= want);
g_assert (got > 0 && got <= want);
b += got;
want -= got;
}
assert (memcmp (out_buf, TEST_DATA, 7) == 0);
g_assert (memcmp (out_buf, TEST_DATA, 7) == 0);
memset(out_buf, 0, 8);
b = out_buf;
want = 4;
while (want > 0) {
got = klass->read (transport, (gpointer) b, want, &error);
assert (got > 0 && got <= want);
g_assert (got > 0 && got <= want);
b += got;
want -= got;
}
assert (memcmp (out_buf, TEST_DATA + 7, 4) == 0);
g_assert (memcmp (out_buf, TEST_DATA + 7, 4) == 0);
assert (klass->close (transport, &error));
g_assert (klass->close (transport, &error));
g_object_unref (transport);
/* clean up */

View file

@ -17,7 +17,6 @@
* under the License.
*/
#include <assert.h>
#include <netdb.h>
#include <sys/wait.h>
@ -31,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
@ -42,10 +42,10 @@ test_create_and_destroy(void)
GObject *object = NULL;
object = g_object_new (THRIFT_TYPE_FRAMED_TRANSPORT, NULL);
assert (object != 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 +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);
pid = fork ();
g_assert ( pid >= 0 );
/* create a BufferedTransport wrapper of the Socket */
transport = g_object_new (THRIFT_TYPE_FRAMED_TRANSPORT,
"transport", THRIFT_TRANSPORT (tsocket), 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);
/* this shouldn't work */
assert (thrift_framed_transport_open (transport, NULL) == FALSE);
assert (thrift_framed_transport_is_open (transport) == TRUE);
assert (thrift_framed_transport_close (transport, NULL) == TRUE);
g_object_unref (transport);
g_object_unref (tsocket);
/* create a BufferedTransport wrapper of the Socket */
transport = g_object_new (THRIFT_TYPE_FRAMED_TRANSPORT,
"transport", THRIFT_TRANSPORT (tsocket), NULL);
/* try and underlying socket failure */
tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost.broken",
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);
/* create a BufferedTransport wrapper of the Socket */
transport = g_object_new (THRIFT_TYPE_FRAMED_TRANSPORT,
"transport", THRIFT_TRANSPORT (tsocket), NULL);
/* try and underlying socket failure */
tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost.broken",
NULL);
assert (thrift_framed_transport_open (transport, &err) == FALSE);
g_object_unref (transport);
g_object_unref (tsocket);
g_error_free (err);
err = 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
@ -97,49 +115,49 @@ test_read_and_write(void)
guchar buf[10] = TEST_DATA; /* a buffer */
pid = fork ();
assert ( pid >= 0 );
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);
{
/* 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);
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);
assert (thrift_framed_transport_open (transport, NULL) == TRUE);
assert (thrift_framed_transport_is_open (transport));
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);
/* 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, 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 (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);
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_object_unref (transport);
g_object_unref (tsocket);
assert ( wait (&status) == pid );
assert ( status == 0 );
}
g_assert ( wait (&status) == pid );
g_assert ( status == 0 );
}
}
/* test reading from the transport after the peer has unexpectedly
@ -156,76 +174,100 @@ test_read_after_peer_close(void)
g_assert (pid >= 0);
if (pid == 0)
{
ThriftServerTransport *server_transport = NULL;
ThriftTransport *client_transport = NULL;
{
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);
/* 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);
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);
/* 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);
/* close the connection immediately after the client connects */
thrift_transport_close (client_transport, NULL);
g_object_unref (client_transport);
g_object_unref (server_transport);
g_object_unref (client_transport);
g_object_unref (server_transport);
exit (0);
} else {
ThriftSocket *tsocket = NULL;
ThriftTransport *transport = NULL;
guchar buf[10]; /* a buffer */
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);
/* 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);
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));
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
/* 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_object_unref (transport);
g_object_unref (tsocket);
g_assert (wait (&status) == pid);
g_assert (status == 0);
g_assert (wait (&status) == pid);
g_assert (status == 0);
}
}
static void
thrift_socket_server_open (const int port, int times)
{
int bytes = 0;
ThriftServerTransport *transport = NULL;
ThriftTransport *client = NULL;
guchar buf[10]; /* a buffer */
guchar match[10] = TEST_DATA;
int i;
ThriftServerSocket *tsocket = g_object_new (THRIFT_TYPE_SERVER_SOCKET,
"port", port, NULL);
transport = THRIFT_SERVER_TRANSPORT (tsocket);
thrift_server_transport_listen (transport, NULL);
for(i=0;i<times;i++){
client = thrift_server_transport_accept (transport, NULL);
g_assert (client != NULL);
thrift_socket_close (client, NULL);
g_object_unref (client);
}
g_object_unref (tsocket);
}
static void
@ -238,21 +280,21 @@ 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);
assert (client != NULL);
thrift_server_transport_accept (transport, NULL),
"r_buf_size", 5, NULL);
g_assert (client != NULL);
/* read 10 bytes */
bytes = thrift_framed_transport_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 */
g_assert (bytes == 10); /* make sure we've read 10 bytes */
g_assert ( memcmp (buf, match, 10) == 0 ); /* make sure what we got matches */
bytes = thrift_framed_transport_read (client, buf, 6, NULL);
bytes = thrift_framed_transport_read (client, buf, 5, NULL);

View file

@ -17,7 +17,6 @@
* under the License.
*/
#include <assert.h>
#include <netdb.h>
#include <thrift/c_glib/transport/thrift_transport.h>
@ -37,7 +36,7 @@ test_create_and_destroy (void)
object = g_object_new (THRIFT_TYPE_MEMORY_BUFFER,
"buf_size", 10,
NULL);
assert (object != NULL);
g_assert (object != NULL);
g_object_unref (object);
}
@ -48,7 +47,7 @@ test_create_and_destroy_large (void)
object = g_object_new (THRIFT_TYPE_MEMORY_BUFFER,
"buf_size", 10 * 1024 * 1024,
NULL);
assert (object != NULL);
g_assert (object != NULL);
g_object_unref (object);
}
@ -57,7 +56,7 @@ test_create_and_destroy_default (void)
{
GObject *object = NULL;
object = g_object_new (THRIFT_TYPE_MEMORY_BUFFER, NULL);
assert (object != NULL);
g_assert (object != NULL);
g_object_unref (object);
}
@ -66,11 +65,11 @@ test_create_and_destroy_external (void)
{
GObject *object = NULL;
GByteArray *buf = g_byte_array_new ();
assert (buf != NULL);
g_assert (buf != NULL);
object = g_object_new (THRIFT_TYPE_MEMORY_BUFFER,
"buf", buf,
NULL);
assert (object != NULL);
g_assert (object != NULL);
g_object_unref (object);
}
@ -84,12 +83,12 @@ test_create_and_destroy_unowned (void)
object = g_object_new (THRIFT_TYPE_MEMORY_BUFFER,
"owner", FALSE,
NULL);
assert (object != NULL);
g_assert (object != NULL);
g_value_init (&val, G_TYPE_POINTER);
g_object_get_property (object, "buf", &val);
buf = (GByteArray*) g_value_get_pointer (&val);
assert (buf != NULL);
g_assert (buf != NULL);
g_byte_array_unref (buf);
g_value_unset (&val);
@ -105,9 +104,9 @@ test_open_and_close (void)
tbuffer = g_object_new (THRIFT_TYPE_MEMORY_BUFFER, NULL);
/* no-ops */
assert (thrift_memory_buffer_open (THRIFT_TRANSPORT (tbuffer), NULL) == TRUE);
assert (thrift_memory_buffer_is_open (THRIFT_TRANSPORT (tbuffer)) == TRUE);
assert (thrift_memory_buffer_close (THRIFT_TRANSPORT (tbuffer), NULL) == TRUE);
g_assert (thrift_memory_buffer_open (THRIFT_TRANSPORT (tbuffer), NULL) == TRUE);
g_assert (thrift_memory_buffer_is_open (THRIFT_TRANSPORT (tbuffer)) == TRUE);
g_assert (thrift_memory_buffer_close (THRIFT_TRANSPORT (tbuffer), NULL) == TRUE);
g_object_unref (tbuffer);
}
@ -122,18 +121,18 @@ test_read_and_write (void)
GError *error = NULL;
tbuffer = g_object_new (THRIFT_TYPE_MEMORY_BUFFER, "buf_size", 5, NULL);
assert (thrift_memory_buffer_write (THRIFT_TRANSPORT (tbuffer),
g_assert (thrift_memory_buffer_write (THRIFT_TRANSPORT (tbuffer),
(gpointer) TEST_DATA,
10, &error) == FALSE);
assert (error != NULL);
g_assert (error != NULL);
g_error_free (error);
error = NULL;
g_object_unref (tbuffer);
tbuffer = g_object_new (THRIFT_TYPE_MEMORY_BUFFER, "buf_size", 15, NULL);
assert (thrift_memory_buffer_write (THRIFT_TRANSPORT (tbuffer),
g_assert (thrift_memory_buffer_write (THRIFT_TRANSPORT (tbuffer),
(gpointer) TEST_DATA, 10, &error) == TRUE);
assert (error == NULL);
g_assert (error == NULL);
memset(read, 0, 10);
b = read;
@ -141,12 +140,12 @@ test_read_and_write (void)
while (want > 0) {
got = thrift_memory_buffer_read (THRIFT_TRANSPORT (tbuffer),
(gpointer) b, want, &error);
assert (got > 0 && got <= want);
assert (error == NULL);
g_assert (got > 0 && got <= want);
g_assert (error == NULL);
b += got;
want -= got;
}
assert (memcmp (read, TEST_DATA, 10) == 0);
g_assert (memcmp (read, TEST_DATA, 10) == 0);
g_object_unref (tbuffer);
}
@ -161,9 +160,9 @@ test_read_and_write_default (void)
tbuffer = g_object_new (THRIFT_TYPE_MEMORY_BUFFER, NULL);
for (i = 0; i < 100; ++i) {
assert (thrift_memory_buffer_write (THRIFT_TRANSPORT (tbuffer),
g_assert (thrift_memory_buffer_write (THRIFT_TRANSPORT (tbuffer),
(gpointer) TEST_DATA, 10, &error) == TRUE);
assert (error == NULL);
g_assert (error == NULL);
}
for (i = 0; i < 100; ++i) {
@ -173,12 +172,12 @@ test_read_and_write_default (void)
while (want > 0) {
got = thrift_memory_buffer_read (THRIFT_TRANSPORT (tbuffer),
(gpointer) b, want, &error);
assert (got > 0 && got <= want);
assert (error == NULL);
g_assert (got > 0 && got <= want);
g_assert (error == NULL);
b += got;
want -= got;
}
assert (memcmp (read, TEST_DATA, 10) == 0);
g_assert (memcmp (read, TEST_DATA, 10) == 0);
}
g_object_unref (tbuffer);
}
@ -190,14 +189,14 @@ test_read_and_write_external (void)
gchar *b;
GError *error = NULL;
GByteArray *buf = g_byte_array_new ();
assert (buf != NULL);
g_assert (buf != NULL);
tbuffer = g_object_new (THRIFT_TYPE_MEMORY_BUFFER, "buf", buf, NULL);
assert (thrift_memory_buffer_write (THRIFT_TRANSPORT (tbuffer),
g_assert (thrift_memory_buffer_write (THRIFT_TRANSPORT (tbuffer),
(gpointer) TEST_DATA, 10, &error) == TRUE);
assert (error == NULL);
g_assert (error == NULL);
assert (memcmp (buf->data, TEST_DATA, 10) == 0);
g_assert (memcmp (buf->data, TEST_DATA, 10) == 0);
g_object_unref (tbuffer);
}

View file

@ -17,7 +17,6 @@
* under the License.
*/
#include <assert.h>
#include <glib.h>
#include <thrift/c_glib/thrift_struct.h>
@ -76,18 +75,18 @@ test_simple (void)
/* write-to-read with optional fields */
s1->im_optional = 10;
assert (s1->__isset_im_default == FALSE);
assert (s1->__isset_im_optional == FALSE);
g_assert (s1->__isset_im_default == FALSE);
g_assert (s1->__isset_im_optional == FALSE);
write_to_read (THRIFT_STRUCT (s1), THRIFT_STRUCT (s2), NULL, NULL);
assert (s2->__isset_im_default == TRUE);
assert (s2->__isset_im_optional == FALSE);
assert (s2->im_optional == 0);
g_assert (s2->__isset_im_default == TRUE);
g_assert (s2->__isset_im_optional == FALSE);
g_assert (s2->im_optional == 0);
s1->__isset_im_optional = TRUE;
write_to_read (THRIFT_STRUCT (s1), THRIFT_STRUCT (s3), NULL, NULL);
assert (s3->__isset_im_default == TRUE);
assert (s3->__isset_im_optional == TRUE);
assert (s3->im_optional == 10);
g_assert (s3->__isset_im_default == TRUE);
g_assert (s3->__isset_im_optional == TRUE);
g_assert (s3->im_optional == 10);
g_object_unref (s1);
g_object_unref (s2);
@ -109,10 +108,10 @@ test_tricky1 (void)
write_to_read (THRIFT_STRUCT (t2), THRIFT_STRUCT (t1), NULL, NULL);
write_to_read (THRIFT_STRUCT (t1), THRIFT_STRUCT (t2), NULL, NULL);
assert (t1->__isset_im_default == FALSE);
assert (t2->__isset_im_optional == TRUE);
assert (t1->im_default == t2->im_optional);
assert (t1->im_default == 0);
g_assert (t1->__isset_im_default == FALSE);
g_assert (t2->__isset_im_optional == TRUE);
g_assert (t1->im_default == t2->im_optional);
g_assert (t1->im_default == 0);
g_object_unref (t1);
g_object_unref (t2);
@ -133,7 +132,7 @@ test_tricky2 (void)
write_to_read (THRIFT_STRUCT (t1), THRIFT_STRUCT (t3), NULL, NULL);
write_to_read (THRIFT_STRUCT (t3), THRIFT_STRUCT (t1), NULL, NULL);
assert (t1->__isset_im_default == TRUE);
g_assert (t1->__isset_im_default == TRUE);
g_object_unref (t1);
g_object_unref (t3);
@ -176,12 +175,12 @@ test_tricky4 (void)
/* throws protocol exception */
write_to_read (THRIFT_STRUCT (t2), THRIFT_STRUCT (t3), NULL, &read_error);
assert (read_error != NULL);
g_assert (read_error != NULL);
g_error_free (read_error);
write_to_read (THRIFT_STRUCT (t3), THRIFT_STRUCT (t2), NULL, NULL);
assert (t2->__isset_im_optional);
g_assert (t2->__isset_im_optional);
g_object_unref (t2);
g_object_unref (t3);

View file

@ -17,7 +17,6 @@
* under the License.
*/
#include <assert.h>
#include <glib.h>
#include <stdlib.h>
#include <unistd.h>
@ -89,7 +88,7 @@ test_server (void)
/* run the server in a child process */
pid = fork ();
assert (pid >= 0);
g_assert (pid >= 0);
if (pid == 0)
{
@ -103,8 +102,8 @@ test_server (void)
g_object_unref (ss);
g_object_unref (tss);
g_object_unref (p);
assert (wait (&status) == pid);
assert (status == SIGINT);
g_assert (wait (&status) == pid);
g_assert (status == SIGINT);
}
}

View file

@ -17,7 +17,6 @@
* under the License.
*/
#include <assert.h>
#include <glib-object.h>
#include "../src/thrift/c_glib/thrift_struct.c"
@ -89,7 +88,7 @@ test_initialize_object (void)
ThriftTestStruct *t = NULL;
t = g_object_new (THRIFT_TYPE_TEST_STRUCT, NULL);
assert ( THRIFT_IS_STRUCT (t));
g_assert ( THRIFT_IS_STRUCT (t));
thrift_struct_read (THRIFT_STRUCT (t), NULL, NULL);
thrift_struct_write (THRIFT_STRUCT (t), NULL, NULL);
thrift_test_struct_read (THRIFT_STRUCT (t), NULL, NULL);

View file

@ -1,4 +1,3 @@
#include <assert.h>
#include <netdb.h>
#include <thrift/c_glib/thrift.h>
@ -87,14 +86,14 @@ test_thrift_handler (void)
g_object_weak_ref (G_OBJECT (argument), set_indicator, (gpointer) &indicator);
assert (thrift_test_handler_test_insanity (NULL, &_return, argument, &error));
assert (! indicator);
g_assert (thrift_test_handler_test_insanity (NULL, &_return, argument, &error));
g_assert (! indicator);
g_hash_table_unref (_return);
assert (! indicator);
g_assert (! indicator);
g_object_unref (argument);
assert (indicator);
g_assert (indicator);
}
int

View file

@ -17,7 +17,7 @@
* under the License.
*/
/* test a C client with a C++ server */
/* test a C client with a C++ server (that makes sense...) */
#include <signal.h>
#include <sys/types.h>
@ -25,23 +25,34 @@
#include <thrift/protocol/TBinaryProtocol.h>
#include <thrift/protocol/TDebugProtocol.h>
#include <thrift/server/TSimpleServer.h>
#include <thrift/stdcxx.h>
#include <thrift/transport/TServerSocket.h>
#include "ThriftTest.h"
#include "ThriftTest_types.h"
#include <iostream>
using namespace std;
using namespace boost;
#include <map>
#include <set>
#include <string>
#include <vector>
using namespace apache::thrift;
using namespace apache::thrift::concurrency;
using namespace apache::thrift::protocol;
using namespace apache::thrift::transport;
using namespace apache::thrift::server;
using namespace apache::thrift::transport;
using namespace thrift::test;
using std::cout;
using std::endl;
using std::fixed;
using std::make_pair;
using std::map;
using std::set;
using std::string;
using std::vector;
#define TEST_PORT 9980
// Extra functions required for ThriftTest_types to work
@ -347,7 +358,7 @@ test_thrift_client (void)
gchar *string = NULL;
gint8 byte = 0;
gint16 i16 = 0;
gint32 i32 = 0, another_i32 = 56789;
gint32 i32 = 0, another_i32 = 56789;
gint64 i64 = 0;
double dbl = 0.0;
TTestXtruct *xtruct_in, *xtruct_out;
@ -356,7 +367,7 @@ test_thrift_client (void)
GHashTable *set_in = NULL, *set_out = NULL;
GArray *list_in = NULL, *list_out = NULL;
TTestNumberz enum_in, enum_out;
TTestUserId user_id_in, user_id_out;
TTestUserId user_id_in, user_id_out;
GHashTable *insanity_in = NULL;
TTestXtruct *xtruct1, *xtruct2;
TTestInsanity *insanity_out = NULL;
@ -371,7 +382,7 @@ test_thrift_client (void)
#endif
// create a C client
tsocket = (ThriftSocket *) g_object_new (THRIFT_TYPE_SOCKET,
tsocket = (ThriftSocket *) g_object_new (THRIFT_TYPE_SOCKET,
"hostname", "localhost",
"port", TEST_PORT, NULL);
protocol = (ThriftBinaryProtocol *) g_object_new (THRIFT_TYPE_BINARY_PROTOCOL,
@ -607,11 +618,11 @@ main (void)
if (pid == 0) /* child */
{
boost::shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());
boost::shared_ptr<TestHandler> testHandler(new TestHandler());
boost::shared_ptr<ThriftTestProcessor> testProcessor(new ThriftTestProcessor(testHandler));
boost::shared_ptr<TServerSocket> serverSocket(new TServerSocket(TEST_PORT));
boost::shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());
stdcxx::shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());
stdcxx::shared_ptr<TestHandler> testHandler(new TestHandler());
stdcxx::shared_ptr<ThriftTestProcessor> testProcessor(new ThriftTestProcessor(testHandler));
stdcxx::shared_ptr<TServerSocket> serverSocket(new TServerSocket(TEST_PORT));
stdcxx::shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());
TSimpleServer simpleServer(testProcessor, serverSocket, transportFactory, protocolFactory);
signal (SIGALRM, bailout);
alarm (60);

View file

@ -17,7 +17,6 @@
* under the License.
*/
#include <assert.h>
#include <netdb.h>
#include <sys/wait.h>
@ -34,9 +33,9 @@ int
my_socket(int domain, int type, int protocol)
{
if (socket_error == 0)
{
return socket (domain, type, protocol);
}
{
return socket (domain, type, protocol);
}
return -1;
}
@ -45,9 +44,9 @@ ssize_t
my_recv(int socket, void *buffer, size_t length, int flags)
{
if (recv_error == 0)
{
return recv (socket, buffer, length, flags);
}
{
return recv (socket, buffer, length, flags);
}
return -1;
}
@ -56,9 +55,9 @@ ssize_t
my_send(int socket, const void *buffer, size_t length, int flags)
{
if (send_error == 0)
{
return send (socket, buffer, length, flags);
}
{
return send (socket, buffer, length, flags);
}
return -1;
}
@ -71,7 +70,7 @@ my_send(int socket, const void *buffer, size_t length, int flags)
#undef send
static void thrift_socket_server (const int port);
static void thrift_socket_server_open (const int port, int times);
/* test object creation and destruction */
static void
test_create_and_destroy(void)
@ -81,7 +80,7 @@ test_create_and_destroy(void)
GObject *object = NULL;
object = g_object_new (THRIFT_TYPE_SOCKET, NULL);
assert (object != NULL);
g_assert (object != NULL);
g_object_get (G_OBJECT(object), "hostname", &hostname, "port", &port, NULL);
g_free (hostname);
@ -94,82 +93,100 @@ test_open_and_close(void)
ThriftSocket *tsocket = NULL;
ThriftTransport *transport = NULL;
GError *err = NULL;
int port = 51199;
pid_t pid;
int status;
/* open a connection and close it */
tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost",
"port", 51188, NULL);
transport = THRIFT_TRANSPORT (tsocket);
thrift_socket_open (transport, NULL);
assert (thrift_socket_is_open (transport) == TRUE);
thrift_socket_close (transport, NULL);
assert (thrift_socket_is_open (transport) == FALSE);
pid = fork ();
g_assert ( pid >= 0 );
/* test close failure */
tsocket->sd = -1;
thrift_socket_close (transport, NULL);
g_object_unref (tsocket);
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);
/* try a hostname lookup failure */
tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost.broken",
NULL);
transport = THRIFT_TRANSPORT (tsocket);
assert (thrift_socket_open (transport, &err) == FALSE);
g_object_unref (tsocket);
g_error_free (err);
err = NULL;
/* open a connection and close it */
tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost",
"port", port, NULL);
transport = THRIFT_TRANSPORT (tsocket);
thrift_socket_open (transport, NULL);
g_assert (thrift_socket_is_open (transport) == TRUE);
thrift_socket_close (transport, NULL);
g_assert (thrift_socket_is_open (transport) == FALSE);
/* try an error call to socket() */
tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost", NULL);
transport = THRIFT_TRANSPORT (tsocket);
socket_error = 1;
assert (thrift_socket_open (transport, &err) == FALSE);
socket_error = 0;
g_object_unref (tsocket);
g_error_free (err);
/* test close failure */
tsocket->sd = -1;
thrift_socket_close (transport, NULL);
g_object_unref (tsocket);
/* try a hostname lookup failure */
tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost.broken",
NULL);
transport = THRIFT_TRANSPORT (tsocket);
g_assert (thrift_socket_open (transport, &err) == FALSE);
g_object_unref (tsocket);
g_error_free (err);
err = NULL;
/* try an error call to socket() */
tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost", NULL);
transport = THRIFT_TRANSPORT (tsocket);
socket_error = 1;
g_assert (thrift_socket_open (transport, &err) == FALSE);
socket_error = 0;
g_object_unref (tsocket);
g_error_free (err);
g_assert ( wait (&status) == pid );
g_assert ( status == 0 );
}
}
static void
test_read_and_write(void)
{
int status;
pid_t pid;
ThriftSocket *tsocket = NULL;
ThriftTransport *transport = NULL;
pid_t pid;
int port = 51199;
int status;
guchar buf[10] = TEST_DATA; /* a buffer */
pid = fork ();
assert ( pid >= 0 );
g_assert ( pid >= 0 );
if ( pid == 0 )
{
/* child listens */
thrift_socket_server (port);
exit (0);
} else {
/* parent connects, wait a bit for the socket to be created */
sleep (1);
{
/* child listens */
thrift_socket_server (port);
exit (0);
} else {
/* parent connects, wait a bit for the socket to be created */
sleep (1);
tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost",
"port", port, NULL);
transport = THRIFT_TRANSPORT (tsocket);
assert (thrift_socket_open (transport, NULL) == TRUE);
assert (thrift_socket_is_open (transport));
thrift_socket_write (transport, buf, 10, NULL);
tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost",
"port", port, NULL);
transport = THRIFT_TRANSPORT (tsocket);
g_assert (thrift_socket_open (transport, NULL) == TRUE);
g_assert (thrift_socket_is_open (transport));
thrift_socket_write (transport, buf, 10, NULL);
/* write fail */
send_error = 1;
thrift_socket_write (transport, buf, 1, NULL);
send_error = 0;
/* write fail */
send_error = 1;
thrift_socket_write (transport, buf, 1, NULL);
send_error = 0;
thrift_socket_write_end (transport, NULL);
thrift_socket_flush (transport, NULL);
thrift_socket_close (transport, NULL);
g_object_unref (tsocket);
thrift_socket_write_end (transport, NULL);
thrift_socket_flush (transport, NULL);
thrift_socket_close (transport, NULL);
g_object_unref (tsocket);
assert ( wait (&status) == pid );
assert ( status == 0 );
}
g_assert ( wait (&status) == pid );
g_assert ( status == 0 );
}
}
/* test ThriftSocket's peek() implementation */
@ -184,9 +201,9 @@ test_peek(void)
GError *error = NULL;
client_transport = g_object_new (THRIFT_TYPE_SOCKET,
"hostname", "localhost",
"port", port,
NULL);
"hostname", "localhost",
"port", port,
NULL);
/* thrift_transport_peek returns FALSE when the socket is closed */
g_assert (thrift_transport_is_open (client_transport) == FALSE);
@ -197,80 +214,104 @@ test_peek(void)
g_assert (pid >= 0);
if (pid == 0)
{
ThriftServerTransport *server_transport = NULL;
{
ThriftServerTransport *server_transport = NULL;
g_object_unref (client_transport);
g_object_unref (client_transport);
/* child listens */
server_transport = g_object_new (THRIFT_TYPE_SERVER_SOCKET,
"port", port,
NULL);
g_assert (server_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, &error);
g_assert (error == 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);
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);
/* 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);
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);
g_object_unref (client_transport);
g_object_unref (server_transport);
exit (0);
}
exit (0);
}
else {
/* parent connects, wait a bit for the socket to be created */
sleep (1);
/* parent connects, wait a bit for the socket to be created */
sleep (1);
/* connect to the child */
thrift_transport_open (client_transport, &error);
g_assert (error == NULL);
g_assert (thrift_transport_is_open (client_transport) == TRUE);
/* connect to the child */
thrift_transport_open (client_transport, &error);
g_assert (error == NULL);
g_assert (thrift_transport_is_open (client_transport) == TRUE);
/* thrift_transport_peek returns TRUE when the socket is open and there is
/* thrift_transport_peek returns TRUE when the socket is open and there is
data available to be read */
g_assert (thrift_transport_peek (client_transport, &error) == TRUE);
g_assert (error == NULL);
g_assert (thrift_transport_peek (client_transport, &error) == TRUE);
g_assert (error == NULL);
/* read exactly one character from the server */
g_assert_cmpint (thrift_transport_read (client_transport,
&data,
sizeof data,
&error), ==, sizeof data);
/* read exactly one character from the server */
g_assert_cmpint (thrift_transport_read (client_transport,
&data,
sizeof data,
&error), ==, sizeof data);
/* thrift_transport_peek returns FALSE when the socket is open but there is
/* thrift_transport_peek returns FALSE when the socket is open but there is
no (more) data available to be read */
g_assert (thrift_transport_is_open (client_transport) == TRUE);
g_assert (thrift_transport_peek (client_transport, &error) == FALSE);
g_assert (error == NULL);
g_assert (thrift_transport_is_open (client_transport) == TRUE);
g_assert (thrift_transport_peek (client_transport, &error) == FALSE);
g_assert (error == NULL);
thrift_transport_read_end (client_transport, &error);
thrift_transport_close (client_transport, &error);
thrift_transport_read_end (client_transport, &error);
thrift_transport_close (client_transport, &error);
g_object_unref (client_transport);
g_object_unref (client_transport);
g_assert (wait (&status) == pid);
g_assert (status == 0);
g_assert (wait (&status) == pid);
g_assert (status == 0);
}
}
static void
thrift_socket_server_open (const int port, int times)
{
int bytes = 0;
ThriftServerTransport *transport = NULL;
ThriftTransport *client = NULL;
guchar buf[10]; /* a buffer */
guchar match[10] = TEST_DATA;
int i;
ThriftServerSocket *tsocket = g_object_new (THRIFT_TYPE_SERVER_SOCKET,
"port", port, NULL);
transport = THRIFT_SERVER_TRANSPORT (tsocket);
thrift_server_transport_listen (transport, NULL);
for(i=0;i<times;i++){
client = thrift_server_transport_accept (transport, NULL);
g_assert (client != NULL);
thrift_socket_close (client, NULL);
g_object_unref (client);
}
g_object_unref (tsocket);
}
static void
thrift_socket_server (const int port)
{
@ -281,17 +322,17 @@ thrift_socket_server (const int port)
guchar match[10] = TEST_DATA;
ThriftServerSocket *tsocket = g_object_new (THRIFT_TYPE_SERVER_SOCKET,
"port", port, NULL);
"port", port, NULL);
transport = THRIFT_SERVER_TRANSPORT (tsocket);
thrift_server_transport_listen (transport, NULL);
client = thrift_server_transport_accept (transport, NULL);
assert (client != NULL);
g_assert (client != NULL);
/* read 10 bytes */
bytes = thrift_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 */
g_assert (bytes == 10); /* make sure we've read 10 bytes */
g_assert ( memcmp(buf, match, 10) == 0 ); /* make sure what we got matches */
/* failed read */
recv_error = 1;

View file

@ -0,0 +1,542 @@
/*
* 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.
*/
#define _POSIX_C_SOURCE 200112L /* https://stackoverflow.com/questions/37541985/storage-size-of-addrinfo-isnt-known */
#include <sys/wait.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.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_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);
g_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);
g_assert (ssl_ctx!=NULL);
g_free (hostname);
g_object_unref (object);
}
static void
test_ssl_open_and_close_non_ssl_server(void)
{
ThriftSSLSocket *tSSLSocket = NULL;
ThriftTransport *transport = NULL;
GError *error=NULL;
pid_t pid;
int non_ssl_port = 51198;
char errormsg[255];
pid = fork ();
g_assert ( pid >= 0 );
if ( pid == 0 )
{
/* child listens */
/* This is a non SSL server */
thrift_socket_server (non_ssl_port);
exit (0);
} else {
/* parent connects, wait a bit for the socket to be created */
sleep (1);
/* open a connection and close it */
tSSLSocket = thrift_ssl_socket_new_with_host(SSLTLS, "localhost", non_ssl_port, &error);
transport = THRIFT_TRANSPORT (tSSLSocket);
g_assert (thrift_ssl_socket_open (transport, &error) == FALSE);
g_assert_cmpstr(error->message, == ,"Error while connect/bind: 68 -> Connection reset by peer");
g_clear_error (&error);
g_assert (thrift_ssl_socket_is_open (transport) == FALSE);
thrift_ssl_socket_close (transport, NULL);
g_assert (thrift_ssl_socket_is_open (transport) == FALSE);
/* test close failure */
THRIFT_SOCKET(tSSLSocket)->sd = -1;
thrift_ssl_socket_close (transport, NULL);
g_object_unref (tSSLSocket);
/* try a hostname lookup failure */
tSSLSocket = thrift_ssl_socket_new_with_host(SSLTLS, "localhost.broken", non_ssl_port, &error);
transport = THRIFT_TRANSPORT (tSSLSocket);
g_assert (thrift_ssl_socket_open (transport, &error) == FALSE);
snprintf(errormsg, 255, "host lookup failed for localhost.broken:%d - Unknown host", non_ssl_port);
g_assert_cmpstr(error->message, ==, errormsg);
g_clear_error (&error);
g_object_unref (tSSLSocket);
error = NULL;
/* try an error call to socket() */
/*
tSSLSocket = thrift_ssl_socket_new_with_host(SSLTLS, "localhost", port, &error);
transport = THRIFT_TRANSPORT (tSSLSocket);
socket_error = 1;
assert (thrift_ssl_socket_open (transport, &error) == FALSE);
socket_error = 0;
g_object_unref (tSSLSocket);
g_error_free (error);
*/
}
}
static void
test_ssl_write_invalid_socket(void)
{
ThriftSSLSocket *tSSLSocket = NULL;
ThriftTransport *transport = NULL;
GError *error=NULL;
char buffer[] = "this must not break";
/* open a connection and close it */
tSSLSocket = thrift_ssl_socket_new_with_host(SSLTLS, "localhost", 51188+1, &error);
transport = THRIFT_TRANSPORT (tSSLSocket);
g_assert (thrift_ssl_socket_open (transport, NULL) == FALSE);
g_assert (thrift_ssl_socket_is_open (transport) == FALSE);
/* FIXME This must be tested but since the assertion inside thrift_ssl_socket_write breaks the test unit
it's disabled. They idea is to disable trap/coredump during this test
g_assert (thrift_ssl_socket_write(transport, buffer, sizeof(buffer), &error) == FALSE);
g_message ("write_failed_with_error: %s",
error != NULL ? error->message : "No");
g_clear_error (&error);
*/
thrift_ssl_socket_close (transport, NULL);
g_assert (thrift_ssl_socket_is_open (transport) == FALSE);
/* test close failure */
THRIFT_SOCKET(tSSLSocket)->sd = -1;
thrift_ssl_socket_close (transport, NULL);
g_object_unref (tSSLSocket);
}
/**
* 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 (struct addrinfo));
hints.ai_family = AF_UNSPEC; /* use AF_INET6 to force IPv6 */
hints.ai_socktype = SOCK_STREAM;
if ( (res = getaddrinfo(hostname, NULL, &hints, &addr_info) ) != 0)
{
/* get the host info */
g_error("Cannot get the host address");
return retval;
}
/* loop through all the results and connect to the first we can */
char dnshost[INET6_ADDRSTRLEN]; /* bigger addr supported IPV6 */
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 ();
g_assert ( pid >= 0 );
if ( pid == 0 )
{
thrift_ssl_socket_server (port);
exit (0);
} else {
*/
/* parent connects, wait a bit for the socket to be created */
sleep (1);
/* Test against level2 owncloud certificate */
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);
g_assert (thrift_ssl_socket_open (transport, NULL) == TRUE);
g_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);
/* g_assert ( wait (&status) == pid ); */
g_assert ( status == 0 );
/* } */
}
#endif
static void
thrift_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);
g_assert (client != NULL);
/* read 10 bytes */
bytes = thrift_ssl_socket_read (client, buf, 10, NULL);
g_assert (bytes == 10); /* make sure we've read 10 bytes */
g_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/OpenAndCloseNonSSLServer", test_ssl_open_and_close_non_ssl_server);
g_test_add_func ("/testtransportsslsocket/OpenAndWriteInvalidSocket", test_ssl_write_invalid_socket);
retval = g_test_run ();
thrift_ssl_socket_finalize_openssl();
return retval;
}