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

@ -71,6 +71,10 @@ if WITH_DART
SUBDIRS += dart
endif
if WITH_DOTNETCORE
SUBDIRS += netcore
endif
if WITH_GO
SUBDIRS += go
endif
@ -89,6 +93,14 @@ if WITH_LUA
SUBDIRS += lua
endif
if WITH_RS
SUBDIRS += rs
endif
if WITH_CL
SUBDIRS += cl
endif
# All of the libs that don't use Automake need to go in here
# so they will end up in our release tarballs.
EXTRA_DIST = \

View file

@ -0,0 +1,5 @@
# Maven Ant tasks Jar details
mvn.ant.task.version=2.1.3
mvn.repo=http://repo1.maven.org/maven2
mvn.ant.task.url=${mvn.repo}/org/apache/maven/maven-ant-tasks/${mvn.ant.task.version}
mvn.ant.task.jar=maven-ant-tasks-${mvn.ant.task.version}.jar

View file

@ -7,9 +7,9 @@
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
@ -19,23 +19,24 @@
-->
<project name="libthrift-as3" default="compile" basedir="."
xmlns:artifact="antlib:org.apache.maven.artifact.ant">
<property name="as3.artifactid" value="${ant.project.name}"/>
<property name="thrift.root" location="${basedir}/../../"/>
<property name="thrift.java.dir" location="${thrift.root}/lib/java"/>
<property name="build.tools.dir" location="${thrift.java.dir}/build/tools/"/>
<property name="thrift_compiler" value="${thrift.root}/compiler/cpp/thrift"/>
<property name="thrift_compiler" value="${thrift.root}/compiler/cpp/thrift"/>
<property file="${basedir}/build.properties"/>
<!-- inherit from the java build file for version and other properties -->
<property file="${thrift.java.dir}/build.properties" />
<property file="${thrift.java.dir}/gradle.properties" />
<property environment="env"/>
<condition property="version" value="${thrift.version}">
<isset property="release"/>
</condition>
<property name="version" value="${thrift.version}-snapshot"/>
<property name="version" value="${thrift.version}-SNAPSHOT"/>
<property name="as3.final.name" value="${as3.artifactid}-${version}"/>
@ -52,12 +53,13 @@
<target name="setup.init">
<tstamp/>
<mkdir dir="${build.dir}"/>
<mkdir dir="${build.tools.dir}"/>
</target>
<target name="flex.check" unless="FLEX_HOME">
<fail message='You must set the FLEX_HOME property pointing to your flex SDK, eg. ant -DFLEX_HOME="/Applications/Adobe Flex Builder 3/sdks/3.2.0"'/>
</target>
<target name="flex.init" depends="flex.check" unless="flex.finished">
<taskdef resource="flexTasks.tasks" classpath="${FLEX_HOME}/ant/lib/flexTasks.jar" />
<property name="flex.finished" value="true"/>
@ -69,10 +71,10 @@
<include name="**/*.as"/>
</fileset>
</path>
<pathconvert
property="as.src.classes"
pathsep=" "
dirsep="."
<pathconvert
property="as.src.classes"
pathsep=" "
dirsep="."
refid="as.src.files"
>
<map from="${src}/" to=""/>
@ -108,19 +110,19 @@
<artifact:remoteRepository id="apache" url="${apache.repo}"/>
<!-- Pom file information -->
<artifact:pom id="pom"
groupId="${thrift.groupid}"
<artifact:pom id="pom"
groupId="${thrift.groupid}"
artifactId="${as3.artifactid}"
version="${version}"
version="${version}"
url="http://thrift.apache.org"
name="Apache Thrift"
description="Thrift is a software framework for scalable cross-language services development."
packaging="pom"
packaging="swc"
>
<remoteRepository refid="central"/>
<remoteRepository refid="apache"/>
<license name="The Apache Software License, Version 2.0" url="${license}"/>
<scm connection="scm:git:https://git-wip-us.apache.org/repos/asf/thrift.git"
<scm connection="scm:git:https://git-wip-us.apache.org/repos/asf/thrift.git"
developerConnection="scm:git:https://git-wip-us.apache.org/repos/asf/thrift.git"
url="https://git-wip-us.apache.org/repos/asf?p=thrift.git"
/>
@ -176,5 +178,5 @@
<!-- run with: ant -Drelease=true publish -->
<signAndDeploy file="${as3.pom.xml}" packaging="pom" classifier="" pom="${as3.pom.xml}"/>
<signAndDeploy file="${as3.swc.file}" packaging="swc" classifier="" pom="${as3.pom.xml}"/>
</target>
</target>
</project>

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

40
vendor/git.apache.org/thrift.git/lib/cl/Makefile.am generated vendored Normal file
View file

@ -0,0 +1,40 @@
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
THRIFT = $(top_builddir)/compiler/cpp/thrift
all-local:
bash ensure-externals.sh
run-tests: test/make-test-binary.lisp
$(SBCL) --script test/make-test-binary.lisp
check-local: run-tests
./run-tests
clean-local:
$(RM) run-tests quicklisp.lisp backport-update.zip
$(RM) -rf lib externals quicklisp
EXTRA_DIST = \
README.md \
READMES \
load-locally.lisp \
test \
ensure-externals.sh

253
vendor/git.apache.org/thrift.git/lib/cl/README.md generated vendored Normal file
View file

@ -0,0 +1,253 @@
Thrift Common Lisp Library
License
=======
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
Using Thrift with Common Lisp
============================
Thrift is a protocol and library for language-independent communication between cooperating
processes. The communication takes the form of request and response messages, of which the forms
are specified in advance throufh a shared interface definition. A Thrift definition file is translated
into Lisp source files, which comprise several definitions:
* Three packages, one for the namespace of the implementation operators, and one each for request and
response operators.
* Various type definitions as implementations for Thrift typedef and enum definitions.
* DEF-STRUCT and DEF-EXCEPTION forms for Thrift struct and exception definitions.
* DEF-SERVICE forms for thrift service definitions.
Each service definition expands in a collection of generic function definitions. For each `op`
in the service definition, two functions are defined
* `op`-request is defined for use by a client. It accepts an additional initial `protocol` argument,
to act as the client proxy for the operation and mediate the interaction with a remote process
through a Thrift-encoded transport stream.
* `op`-response is defined for use by a server. It accepts a single `protocol` argument. A server
uses it to decode the request message, invoke the base `op` function with the message arguments,
encode and send the the result as a response, and handles exceptions.
The client interface is one operator
* `with-client (variable location) . body` : creates a connection in a dynamic context and closes it
upon exit. The variable is bound to a client proxy stream/protocol instance, which wraps the
base i/o stream - socket, file, etc, with an operators which implement the Thrift protocol
and transport mechanisms.
The server interface combines server and service objects
* `serve (location service)` : accepts connections on the designated port and responds to
requests of the service's operations.
Building
--------
The Thrift Common Lisp library is packaged as the ASDF[[1]] system `thrift`.
It depends on the systems
* puri[[2]] : for the thrift uri class
* closer-mop[[3]] : for class metadata
* trivial-utf-8[[4]] : for string codecs
* usocket[[5]] : for the socket transport
* ieee-floats[[6]] : for conversion between ints and floats
* trivial-gray-streams[[7]] : an abstraction layer for gray streams
* alexandria[[8]] : handy utilities
The dependencies are bundled for local builds of tests and tutorial binaries -
it is possible to use those bundles to load the library, too.
In order to build it, register those systems with ASDF and evaluate:
(asdf:load-system :thrift)
This will compile and load the Lisp compiler for Thrift definition files, the
transport and protocol implementations, and the client and server interface
functions. In order to use Thrift in an application, one must also author and/or
load the interface definitions for the remote service.[[9]] If one is implementing a service,
one must also define the actual functions to which Thrift is to act as the proxy
interface. The remainder of this document follows the Thrift tutorial to illustrate how
to perform the steps
* implement the service
* translate the Thrift IDL
* load the Lisp service interfaces
* run a server for the service
* use a client to access the service remotely
Note that, if one is to implement a new service, one will also need to author the
IDL files, as there is no facility to generate them from a service implementation.
Implement the Service
---------------------
The tutorial comprises serveral functions: `add`, `ping`, `zip`, and `calculate`.
Each translated IDL file generates three packages for every service. In the case of
the tutorial file, the relevant packages are:
* tutorial.calculator
* tutorial.calculator-implementation
* tutorial.calculator-response
This is to separate the request (generated), response (generated) and implementation
(meant to be implemented by the programmer) functions for defined Thrift methods.
It is suggested to work in the `tutorial-implementation` package while implementing
the services - it imports the `common-lisp` package, while the service-specific ones
don't (to avoid conflicts between Thrift method names and function names in `common-lisp`).
;; define the base operations
(in-package :tutorial-implementation)
(defun tutorial.calculator-implementation:add (num1 num2)
(format t "~&Asked to add ~A and ~A." num1 num2)
(+ num1 num2))
(defun tutorial.calculator-implementation:ping ()
(print :ping))
(defun tutorial.calculator-implementation:zip ()
(print :zip))
(defun tutorial.calculator-implementation:calculate (logid task)
(calculate-op (work-op task) (work-num1 task) (work-num2 task)))
(defgeneric calculate-op (op arg1 arg2)
(:method :around (op arg1 arg2)
(let ((result (call-next-method)))
(format t "~&Asked to calculate: ~d on ~A and ~A = ~d." op arg1 arg2 result)
result))
(:method ((op (eql operation.add)) arg1 arg2)
(+ arg1 arg2))
(:method ((op (eql operation.subtract)) arg1 arg2)
(- arg1 arg2))
(:method ((op (eql operation.multiply)) arg1 arg2)
(* arg1 arg2))
(:method ((op (eql operation.divide)) arg1 arg2)
(/ arg1 arg2)))
(defun zip () (print 'zip))
Translate the Thrift IDL
------------------------
IDL files employ the file extension `thrift`. In this case, there are two files to translate
* `tutorial.thrift`
* `shared.thrift`
As the former includes the latter, one uses it to generate the interfaces:
$THRIFT/bin/thrift -r --gen cl $THRIFT/tutorial/tutorial.thrift
`-r` stands for recursion, while `--gen` lets one choose the language to translate to.
Load the Lisp translated service interfaces
-------------------------------------------
The translator generates three files for each IDL file. For example `tutorial-types.lisp`,
`tutorial-vars.lisp` and an `.asd` file that can be used to load them both and pull in
other includes (like `shared` within the tutorial) as dependencies.
Run a Server for the Service
----------------------------
The actual service name, as specified in the `def-service` form in `tutorial.lisp`, is `calculator`.
Each service definition defines a global variable with the service name and binds it to a
service instance whch describes the operations.
In order to start a service, specify a location and the service instance.
(in-package :tutorial)
(serve #u"thrift://127.0.0.1:9091" calculator)
Use a Client to Access the Service Remotely
-------------------------------------------
[in some other process] run the client
(in-package :cl-user)
(macrolet ((show (form)
`(format *trace-output* "~%~s =>~{ ~s~}"
',form
(multiple-value-list (ignore-errors ,form)))))
(with-client (protocol #u"thrift://127.0.0.1:9091")
(show (tutorial.calculator:ping protocol))
(show (tutorial.calculator:add protocol 1 2))
(show (tutorial.calculator:add protocol 1 4))
(let ((task (make-instance 'tutorial:work
:op operation.subtract :num1 15 :num2 10)))
(show (tutorial.calculator:calculate protocol 1 task))
(setf (tutorial:work-op task) operation.divide
(tutorial:work-num1 task) 1
(tutorial:work-num2 task) 0)
(show (tutorial.calculator:calculate protocol 1 task)))
(show (shared.shared-service:get-struct protocol 1))
(show (zip protocol))))
Issues
------
### optional fields
Where the IDL declares a field options, the def-struct form includes no
initform for the slot and the encoding operator skips an unbound slot. This leave some ambiguity
with bool fields.
### instantiation protocol :
struct classes are standard classes and exception classes are
whatever the implementation prescribes. decoders apply make-struct to an initargs list.
particularly at the service end, there are advantages to resourcing structs and decoding
with direct side-effects on slot-values
### maps:
Maps are now represented as hash tables. As data through the call/reply interface is all statically
typed, it is not necessary for the objects to themselves indicate the coding form. Association lists
would be sufficient. As the key type is arbitrary, property lists offer no additional convenience:
as `getf` operates with `eq` a new access interface would be necessary and they would not be
available for function application.
[1]: www.common-lisp.net/asdf
[2]: http://github.com/lisp/com.b9.puri.ppcre
[3]: www.common-lisp.net/closer-mop
[4]: trivial-utf-8
[5]: https://github.com/usocket/usocket
[6]: https://github.com/marijnh/ieee-floats
[7]: https://github.com/trivial-gray-streams/trivial-gray-streams
[8]: https://gitlab.common-lisp.net/alexandria/alexandria
[9]: http://wiki.apache.org/thrift/ThriftGeneration
* usocket[[5]] : for the socket transport
* ieee-floats[[6]] : for conversion between ints and floats
* trivial-gray-streams[[7]] : an abstraction layer for gray streams
* alexandria[[8]] : handy utilities

View file

@ -0,0 +1,64 @@
(in-package :cl-user)
#+(or ccl sbcl) /development/source/library/
(load "build-init.lisp")
;;; ! first, select the api version in the cassandra system definition
;;; as only one should be loaded at a time.
(asdf:load-system :de.setf.cassandra)
(in-package :de.setf.cassandra)
(defparameter *c-location*
;; remote
;; #u"thrift://ec2-174-129-66-148.compute-1.amazonaws.com:9160"
;; local
#u"thrift://127.0.0.1:9160"
"A cassandra service location - either the local one or a remote service
- always a 'thrift' uri.")
(defparameter *c* (thrift:client *c-location*))
(cassandra:describe-keyspaces *c*)
;; => ("Keyspace1" "system")
(cassandra:describe-cluster-name *c*)
;; =>"Test Cluster"
(cassandra:describe-version *c*)
;; => "2.1.0"
(loop for space in (cassandra:describe-keyspaces *c*)
collect (loop for key being each hash-key of (cassandra:describe-keyspace *c* space)
using (hash-value value)
collect (cons key
(loop for key being each hash-key of value
using (hash-value value)
collect (cons key value)))))
(close *c*)
(defun describe-cassandra (location &optional (stream *standard-output*))
"Print the first-order store metadata for a cassandra LOCATION."
(thrift:with-client (cassandra location)
(let* ((keyspace-names (cassandra:describe-keyspaces cassandra))
(cluster (cassandra:describe-cluster-name cassandra))
(version (cassandra:describe-version cassandra))
(keyspace-descriptions (loop for space in keyspace-names
collect (cons space
(loop for key being each hash-key
of (cassandra:describe-keyspace cassandra space)
using (hash-value value)
collect (cons key
(loop for key being each hash-key of value
using (hash-value value)
collect (cons key value))))))))
(format stream "~&connection to : ~a" cassandra)
(format stream "~&version : ~a" version)
(format stream "~&cluster : ~a" cluster)
(format stream "~&keyspaces~{~{~%~%space: ~a~@{~% ~{~a :~@{~20t~:w~^~%~}~}~}~}~}" keyspace-descriptions))))
;;; (describe-cassandra *c-location*)

16
vendor/git.apache.org/thrift.git/lib/cl/ensure-externals.sh generated vendored Executable file
View file

@ -0,0 +1,16 @@
#!/bin/bash
set -e
if [[ ! -e quicklisp.lisp ]]; then curl -O https://beta.quicklisp.org/quicklisp.lisp; fi
sbcl --load quicklisp.lisp \
--eval "(ignore-errors (quicklisp-quickstart:install :path \"quicklisp/\"))" \
--eval "(load \"quicklisp/setup.lisp\")" \
--eval "(quicklisp:bundle-systems '(#:puri #:usocket #:closer-mop #:trivial-utf-8 #:ieee-floats #:trivial-gray-streams #:alexandria #:bordeaux-threads #:cl-ppcre #:fiasco #:net.didierverna.clon) :to \"externals/\")" \
--eval "(quit)" \
--no-userinit
if [[ ! -e backport-update.zip ]]; then
curl -O -L https://github.com/TurtleWarePL/de.setf.thrift/archive/backport-update.zip;
fi
mkdir -p lib
unzip -u backport-update.zip -d lib

View file

@ -0,0 +1,23 @@
(in-package #:cl-user)
;;;; Licensed 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.
;;;; Just a script for loading the library itself, using bundled dependencies.
;;;; This is here for when we want to build the self-test and cross-test
;;;; binaries.
(require "asdf")
(load (merge-pathnames "externals/bundle.lisp" *load-truename*))
(asdf:load-asd (merge-pathnames "lib/de.setf.thrift-backport-update/thrift.asd" *load-truename*))
(asdf:load-system :thrift)

View file

@ -0,0 +1,31 @@
;;;; Licensed 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.
;;;; This file is used to build the binary that runs all self-tests. The
;;;; binary is then meant to be hooked up to Thrift's `make check` facility,
;;;; but can easily be run on its own as well.
(in-package #:cl-user)
(require "asdf")
(load (merge-pathnames "../load-locally.lisp" *load-truename*))
(asdf:load-asd (merge-pathnames "../lib/de.setf.thrift-backport-update/test/thrift-test.asd" *load-truename*))
(asdf:load-system :thrift-test)
(asdf:load-system :net.didierverna.clon)
(net.didierverna.clon:nickname-package)
(defun main ()
(let ((result (if (fiasco:run-tests 'thrift-test) 0 -1)))
(clon:exit result)))
(clon:dump "run-tests" main)

View file

@ -17,4 +17,4 @@
* under the License.
*/
#define ThriftVersion @"0.10.0"
#define ThriftVersion @"1.0.0-dev"

View file

@ -26,14 +26,14 @@
/**
* De-serialize object from the given input protocol
*
* @param input protocol used for reading
* @param inProtocol protocol used for reading
*/
-(BOOL) read:(id <TProtocol>)inProtocol error:(NSError **)error;
/**
* Serialize object to the given protocol
*
* @param buf output protocol used for writing
* @param outProtocol output protocol used for writing
*/
-(BOOL) write:(id <TProtocol>)outProtocol error:(NSError **)error;

View file

@ -41,6 +41,10 @@ extern NSString *const TSockerServerTransportKey;
protocolFactory:(id <TProtocolFactory>)protocolFactory
processorFactory:(id <TProcessorFactory>)processorFactory;
- (instancetype) initWithPath: (NSString *) path
protocolFactory: (id <TProtocolFactory>) protocolFactory
processorFactory: (id <TProcessorFactory>) processorFactory;
@end

View file

@ -25,7 +25,7 @@
#import <sys/socket.h>
#include <netinet/in.h>
#include <sys/un.h>
NSString *const TSocketServerClientConnectionFinished = @"TSocketServerClientConnectionFinished";
@ -40,13 +40,14 @@ NSString *const TSockerServerTransportKey = @"TSockerServerTransport";
@property(strong, nonatomic) id<TProcessorFactory> processorFactory;
@property(strong, nonatomic) NSFileHandle *socketFileHandle;
@property(strong, nonatomic) dispatch_queue_t processingQueue;
@property(strong, nonatomic) NSString *domainSocketPath;
@end
@implementation TSocketServer
-(instancetype) initWithPort:(int)port
-(instancetype) initWithSocket:(CFSocketRef)socket
protocolFactory:(id <TProtocolFactory>)protocolFactory
processorFactory:(id <TProcessorFactory>)processorFactory;
{
@ -62,32 +63,7 @@ NSString *const TSockerServerTransportKey = @"TSockerServerTransport";
_processingQueue = dispatch_queue_create("TSocketServer.processing", processingQueueAttr);
// create a socket.
int fd = -1;
CFSocketRef socket = CFSocketCreate(kCFAllocatorDefault, PF_INET, SOCK_STREAM, IPPROTO_TCP, 0, NULL, NULL);
if (socket) {
CFSocketSetSocketFlags(socket, CFSocketGetSocketFlags(socket) & ~kCFSocketCloseOnInvalidate);
fd = CFSocketGetNative(socket);
int yes = 1;
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&yes, sizeof(yes));
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_len = sizeof(addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
NSData *address = [NSData dataWithBytes:&addr length:sizeof(addr)];
if (CFSocketSetAddress(socket, (__bridge CFDataRef)address) != kCFSocketSuccess) {
CFSocketInvalidate(socket);
CFRelease(socket);
NSLog(@"TSocketServer: Could not bind to address");
return nil;
}
}
else {
NSLog(@"TSocketServer: No server socket");
return nil;
}
int fd = CFSocketGetNative(socket);
// wrap it in a file handle so we can get messages from it
_socketFileHandle = [[NSFileHandle alloc] initWithFileDescriptor:fd
@ -106,15 +82,114 @@ NSString *const TSockerServerTransportKey = @"TSockerServerTransport";
// tell socket to listen
[_socketFileHandle acceptConnectionInBackgroundAndNotify];
NSLog(@"TSocketServer: Listening on TCP port %d", port);
return self;
}
- (id) initWithPort: (int) port
protocolFactory: (id <TProtocolFactory>) protocolFactory
processorFactory: (id <TProcessorFactory>) processorFactory
{
CFSocketRef socket = [[self class] createSocketWithPort:port];
if (socket == NULL) {
return nil;
}
if (self = [self initWithSocket:socket protocolFactory:protocolFactory processorFactory:processorFactory]) {
NSLog(@"TSocketServer: Listening on TCP port %d", port);
}
return self;
}
+(CFSocketRef) createSocketWithPort:(int)port
{
CFSocketRef socket = CFSocketCreate(kCFAllocatorDefault, PF_INET, SOCK_STREAM, IPPROTO_TCP, 0, NULL, NULL);
if (socket) {
CFSocketSetSocketFlags(socket, CFSocketGetSocketFlags(socket) & ~kCFSocketCloseOnInvalidate);
int fd = CFSocketGetNative(socket);
int yes = 1;
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&yes, sizeof(yes));
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_len = sizeof(addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
NSData *address = [NSData dataWithBytes:&addr length:sizeof(addr)];
if (CFSocketSetAddress(socket, (__bridge CFDataRef)address) != kCFSocketSuccess) {
CFSocketInvalidate(socket);
CFRelease(socket);
NSLog(@"TSocketServer: Could not bind to address");
return NULL;
}
return socket;
}
else {
NSLog(@"TSocketServer: No server socket");
return NULL;
}
}
- (id) initWithPath: (NSString *) path
protocolFactory: (id <TProtocolFactory>) protocolFactory
processorFactory: (id <TProcessorFactory>) processorFactory
{
_domainSocketPath = path;
CFSocketRef socket = [[self class] createSocketWithPath:path];
if (socket == NULL) {
return nil;
}
if (self = [self initWithSocket:socket protocolFactory:protocolFactory processorFactory:processorFactory]) {
NSLog(@"TSocketServer: Listening on path %@", path);
}
return self;
}
+ (CFSocketRef) createSocketWithPath: (NSString *) path
{
CFSocketRef socket = CFSocketCreate(kCFAllocatorDefault, PF_LOCAL, SOCK_STREAM, IPPROTO_IP, 0, NULL, NULL);
if (socket) {
CFSocketSetSocketFlags(socket, CFSocketGetSocketFlags(socket) & ~kCFSocketCloseOnInvalidate);
int fd = CFSocketGetNative(socket);
int yes = 1;
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&yes, sizeof(yes));
size_t nullTerminatedPathLength = path.length + 1;
struct sockaddr_un addr;
if (nullTerminatedPathLength> sizeof(addr.sun_path)) {
NSLog(@"TSocketServer: Unable to create socket at path %@. Path is too long.", path);
return NULL;
}
addr.sun_family = AF_LOCAL;
memcpy(addr.sun_path, path.UTF8String, nullTerminatedPathLength);
addr.sun_len = SUN_LEN(&addr);
NSData *address = [NSData dataWithBytes:&addr length:sizeof(addr)];
if (CFSocketSetAddress(socket, (__bridge CFDataRef)address) != kCFSocketSuccess) {
CFSocketInvalidate(socket);
CFRelease(socket);
NSLog(@"TSocketServer: Could not bind to address");
return NULL;
}
return socket;
} else {
NSLog(@"TSocketServer: No server socket");
return NULL;
}
}
-(void) dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
if (_domainSocketPath != nil) {
unlink(_domainSocketPath.UTF8String);
}
}

View file

@ -94,7 +94,7 @@
-(BOOL) write:(const UInt8 *)data offset:(UInt32)offset length:(UInt32)length error:(NSError *__autoreleasing *)error
{
int got = 0;
UInt32 got = 0;
NSInteger total = 0;
while (got < length) {

View file

@ -28,6 +28,8 @@ NS_ASSUME_NONNULL_BEGIN
-(id) initWithHostname:(NSString *)hostname
port:(int)port;
-(id) initWithPath:(NSString *)path;
@end

View file

@ -24,21 +24,21 @@
#import <CFNetwork/CFNetwork.h>
#endif
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/un.h>
@interface TSocketTransport () <NSStreamDelegate>
@end
@implementation TSocketTransport
-(id) initWithHostname:(NSString *)hostname
port:(int)port
- (id) initWithReadStream: (CFReadStreamRef) readStream writeStream: (CFWriteStreamRef) writeStream
{
NSInputStream *inputStream = nil;
NSOutputStream *outputStream = nil;
CFReadStreamRef readStream = NULL;
CFWriteStreamRef writeStream = NULL;
CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, (__bridge CFStringRef)hostname, port, &readStream, &writeStream);
if (readStream && writeStream) {
CFReadStreamSetProperty(readStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);
@ -70,4 +70,62 @@
return [super initWithInputStream:inputStream outputStream:outputStream];
}
- (id) initWithHostname: (NSString *) hostname
port: (int) port
{
CFReadStreamRef readStream = NULL;
CFWriteStreamRef writeStream = NULL;
CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, (__bridge CFStringRef)hostname, port, &readStream, &writeStream);
return [self initWithReadStream:readStream writeStream:writeStream];
}
- (id) initWithPath: (NSString *) path
{
CFSocketNativeHandle sockfd = socket(AF_LOCAL, SOCK_STREAM, IPPROTO_IP);
int yes = 1;
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0)
{
NSLog(@"TSocketTransport: Unable to set REUSEADDR property of socket.");
return nil;
}
NSData *serverAddress = [[self class] createAddressWithPath:path];
CFReadStreamRef readStream = NULL;
CFWriteStreamRef writeStream = NULL;
CFStreamCreatePairWithSocket(kCFAllocatorDefault, sockfd, &readStream, &writeStream);
if (!readStream || !writeStream)
{
NSLog(@"TSocketTransport: Unable to create read/write stream pair for socket.");
return nil;
}
if (connect(sockfd, (struct sockaddr *)serverAddress.bytes, (socklen_t) serverAddress.length) < 0)
{
NSLog(@"TSocketTransport: Connect error: %s\n", strerror(errno));
return nil;
}
return [self initWithReadStream:readStream writeStream:writeStream];
}
+ (NSData *) createAddressWithPath: (NSString *)path
{
struct sockaddr_un servaddr;
size_t nullTerminatedPathLength = path.length + 1;
if (nullTerminatedPathLength> sizeof(servaddr.sun_path)) {
NSLog(@"TSocketTransport: Unable to create socket at path %@. Path is too long.", path);
return nil;
}
bzero(&servaddr,sizeof(servaddr));
servaddr.sun_family = AF_LOCAL;
memcpy(servaddr.sun_path, path.UTF8String, nullTerminatedPathLength);
servaddr.sun_len = SUN_LEN(&servaddr);
return [NSData dataWithBytes:&servaddr length:sizeof(servaddr)];
}
@end

View file

@ -28,6 +28,7 @@ set( thriftcpp_SOURCES
src/thrift/TApplicationException.cpp
src/thrift/TOutput.cpp
src/thrift/async/TAsyncChannel.cpp
src/thrift/async/TAsyncProtocolProcessor.cpp
src/thrift/async/TConcurrentClientSyncInfo.h
src/thrift/async/TConcurrentClientSyncInfo.cpp
src/thrift/concurrency/ThreadManager.cpp
@ -57,7 +58,7 @@ set( thriftcpp_SOURCES
src/thrift/server/TThreadedServer.cpp
)
# This files don't work on Windows CE as there is no pipe support
# These files don't work on Windows CE as there is no pipe support
# TODO: These files won't work with UNICODE support on windows. If fixed this can be re-added.
if (NOT WINCE)
list(APPEND thriftcpp_SOURCES
@ -138,7 +139,8 @@ endif()
# Thrift non blocking server
set( thriftcppnb_SOURCES
src/thrift/server/TNonblockingServer.cpp
src/thrift/async/TAsyncProtocolProcessor.cpp
src/thrift/transport/TNonblockingServerSocket.cpp
src/thrift/transport/TNonblockingSSLServerSocket.cpp
src/thrift/async/TEvhttpServer.cpp
src/thrift/async/TEvhttpClientChannel.cpp
)

View file

@ -62,7 +62,7 @@ pkgconfig_DATA += thrift-qt5.pc
endif
AM_CXXFLAGS = -Wall -Wextra -pedantic
AM_CPPFLAGS = $(BOOST_CPPFLAGS) $(OPENSSL_INCLUDES) -I$(srcdir)/src -D__STDC_LIMIT_MACROS
AM_CPPFLAGS = $(BOOST_CPPFLAGS) $(OPENSSL_INCLUDES) -I$(srcdir)/src -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS
# Define the source files for the module
@ -70,6 +70,7 @@ libthrift_la_SOURCES = src/thrift/TApplicationException.cpp \
src/thrift/TOutput.cpp \
src/thrift/VirtualProfiling.cpp \
src/thrift/async/TAsyncChannel.cpp \
src/thrift/async/TAsyncProtocolProcessor.cpp \
src/thrift/async/TConcurrentClientSyncInfo.cpp \
src/thrift/concurrency/ThreadManager.cpp \
src/thrift/concurrency/TimerManager.cpp \
@ -94,6 +95,8 @@ libthrift_la_SOURCES = src/thrift/TApplicationException.cpp \
src/thrift/transport/TSocketPool.cpp \
src/thrift/transport/TServerSocket.cpp \
src/thrift/transport/TSSLServerSocket.cpp \
src/thrift/transport/TNonblockingServerSocket.cpp \
src/thrift/transport/TNonblockingSSLServerSocket.cpp \
src/thrift/transport/TTransportUtils.cpp \
src/thrift/transport/TBufferTransports.cpp \
src/thrift/server/TConnectedClient.cpp \
@ -114,13 +117,12 @@ libthrift_la_SOURCES += src/thrift/concurrency/Mutex.cpp \
endif
libthriftnb_la_SOURCES = src/thrift/server/TNonblockingServer.cpp \
src/thrift/async/TAsyncProtocolProcessor.cpp \
src/thrift/async/TEvhttpServer.cpp \
src/thrift/async/TEvhttpClientChannel.cpp
libthriftz_la_SOURCES = src/thrift/transport/TZlibTransport.cpp \
src/thrift/transport/THeaderTransport.cpp \
src/thrift/protocol/THeaderProtocol.cpp
src/thrift/protocol/THeaderProtocol.cpp
libthriftqt_la_MOC = src/thrift/qt/moc_TQTcpServer.cpp
@ -148,7 +150,7 @@ libthriftz_la_CXXFLAGS = $(AM_CXXFLAGS)
libthriftqt_la_CXXFLAGS = $(AM_CXXFLAGS)
libthriftqt5_la_CXXFLAGS = $(AM_CXXFLAGS)
libthriftnb_la_LDFLAGS = -release $(VERSION) $(BOOST_LDFLAGS)
libthriftz_la_LDFLAGS = -release $(VERSION) $(BOOST_LDFLAGS)
libthriftz_la_LDFLAGS = -release $(VERSION) $(BOOST_LDFLAGS) $(ZLIB_LIBS)
libthriftqt_la_LDFLAGS = -release $(VERSION) $(BOOST_LDFLAGS) $(QT_LIBS)
libthriftqt5_la_LDFLAGS = -release $(VERSION) $(BOOST_LDFLAGS) $(QT5_LIBS)
@ -162,8 +164,8 @@ include_thrift_HEADERS = \
src/thrift/TProcessor.h \
src/thrift/TApplicationException.h \
src/thrift/TLogging.h \
src/thrift/cxxfunctional.h \
src/thrift/TToString.h \
src/thrift/stdcxx.h \
src/thrift/TBase.h
include_concurrencydir = $(include_thriftdir)/concurrency
@ -212,6 +214,9 @@ include_transport_HEADERS = \
src/thrift/transport/TServerSocket.h \
src/thrift/transport/TSSLServerSocket.h \
src/thrift/transport/TServerTransport.h \
src/thrift/transport/TNonblockingServerTransport.h \
src/thrift/transport/TNonblockingServerSocket.h \
src/thrift/transport/TNonblockingSSLServerSocket.h \
src/thrift/transport/THttpTransport.h \
src/thrift/transport/THttpClient.h \
src/thrift/transport/THttpServer.h \
@ -260,8 +265,6 @@ include_qt_HEADERS = \
src/thrift/qt/TQIODeviceTransport.h \
src/thrift/qt/TQTcpServer.h
THRIFT = $(top_builddir)/compiler/cpp/thrift
WINDOWS_DIST = \
src/thrift/windows \
thrift.sln \

View file

@ -19,7 +19,6 @@ KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
# Using Thrift with C++
The Thrift C++ libraries are built using the GNU tools. Follow the instructions
@ -55,15 +54,22 @@ you are using libthriftnb you will also need libevent.
## Dependencies
boost shared pointers
http://www.boost.org/libs/smart_ptr/smart_ptr.htm
If your C++ environment implements C++11 or later, thrift will automatically use
std::shared_ptr. Otherwise you will need the boost library to provide a shared_ptr
implementation for C++ environments pre-C++11. If you are linking against code
that expects to be using boost::shared_ptr, you can define the preprocessor
variable FORCE_BOOST_SMART_PTR for your build of thrift to make it use boost instead
of std for a number of memory related classes. See thrift/stdcxx.h for more.
libevent (for libthriftnb only)
http://monkey.org/~provos/libevent/
# Using Thrift with C++ on Windows
You need to define an environment variables for 3rd party components separately:
Both the autoconf and cmake build systems are able to automatically detect many
system configurations without the need to specify library locations, however if
you run into problems or want to redirect thrift to build and link against your
own provided third party libraries:
BOOST_ROOT : For boost, e.g. D:\boost_1_55_0
OPENSSL_ROOT_DIR : For OpenSSL, e.g. D:\OpenSSL-Win32
@ -74,13 +80,7 @@ LIBEVENT_ROOT_DIR : For Libevent e.g. D:\libevent-2.0.21-stable
See /3rdparty.user for more details.
Thrift is divided into two libraries.
* libthrift - The core Thrift library contains all the core Thrift code. It requires
boost shared pointers, pthreads, and librt.
* libthriftnb - This library contains the Thrift nonblocking server, which uses libevent.
To link this library you will also need to link libevent.
The same linking guidelines described above for libthriftnb apply to windows as well.
## Linking Against Thrift
@ -93,8 +93,7 @@ the config header: "windows/confg.h"
## Dependencies
boost shared pointers
http://www.boost.org/libs/smart_ptr/smart_ptr.htm
The same dependencies for shared_ptr as described above apply to windows as well.
boost thread
http://www.boost.org/doc/libs/release/doc/html/thread.html
@ -272,3 +271,26 @@ OpenSSL's RAND_poll() when OpenSSL library is first initialized.
The PRNG seed is key to the application security. This method should be
overridden if it's not strong enough for you.
# Breaking Changes
## 0.11.0
Older versions of thrift depended on the <boost/smart_ptr.hpp> classes which
were used in thrift headers to define interfaces. Thrift now detects C++11
at build time and will prefer to use <memory> classes from C++11 instead.
You can force the library to build with boost memory classes by defining the
preprocessor macro `FORCE_BOOST_SMART_PTR`. (THRIFT-2221)
In the pthread mutex implementation, the contention profiling code was enabled
by default in all builds. This changed to be disabled by default. (THRIFT-4151)
In older releases, if a TSSLSocketFactory's lifetime was not at least as long
as the TSSLSockets it created, we silently reverted openssl to unsafe multithread behavior
and so the results were undefined. Changes were made in 0.11.0 that cause either an
assertion or a core instead of undefined behavior. The lifetime of a TSSLSocketFactory
*must* be longer than any TSSLSocket that it creates, otherwise openssl will be cleaned
up too early. If the static boolean is set to disable openssl initialization and
cleanup and leave it up to the consuming application, this requirement is not needed.
(THRIFT-4164)

View file

@ -53,6 +53,12 @@
<ClCompile Include="src\thrift\server\TSimpleServer.cpp"/>
<ClCompile Include="src\thrift\server\TThreadPoolServer.cpp"/>
<ClCompile Include="src\thrift\server\TThreadedServer.cpp"/>
<ClCompile Include="src\thrift\server\TConnectedClient.cpp"/>
<ClCompile Include="src\thrift\server\TNonblockingServer.cpp"/>
<ClCompile Include="src\thrift\server\TServerFramework.cpp"/>
<ClCompile Include="src\thrift\server\TSimpleServer.cpp"/>
<ClCompile Include="src\thrift\server\TThreadedServer.cpp"/>
<ClCompile Include="src\thrift\server\TThreadPoolServer.cpp"/>
<ClCompile Include="src\thrift\TApplicationException.cpp"/>
<ClCompile Include="src\thrift\TOutput.cpp"/>
<ClCompile Include="src\thrift\transport\TBufferTransports.cpp"/>

View file

@ -35,16 +35,21 @@
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\thrift\async\TAsyncProtocolProcessor.cpp"/>
<ClCompile Include="src\thrift\async\TEvhttpClientChannel.cpp"/>
<ClCompile Include="src\thrift\async\TEvhttpServer.cpp"/>
<ClCompile Include="src\thrift\server\TNonblockingServer.cpp"/>
<ClCompile Include="src\thrift\async\TAsyncProtocolProcessor.cpp" />
<ClCompile Include="src\thrift\async\TEvhttpClientChannel.cpp" />
<ClCompile Include="src\thrift\async\TEvhttpServer.cpp" />
<ClCompile Include="src\thrift\server\TNonblockingServer.cpp" />
<ClCompile Include="src\thrift\transport\TNonblockingServerSocket.cpp" />
<ClCompile Include="src\thrift\transport\TNonblockingSSLServerSocket.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\thrift\async\TAsyncProtocolProcessor.h" />
<ClInclude Include="src\thrift\async\TEvhttpClientChannel.h" />
<ClInclude Include="src\thrift\async\TEvhttpServer.h" />
<ClInclude Include="src\thrift\server\TNonblockingServer.h" />
<ClInclude Include="src\thrift\transport\TNonblockingServerSocket.h" />
<ClInclude Include="src\thrift\transport\TNonblockingServerTransport.h" />
<ClInclude Include="src\thrift\transport\TNonblockingSSLServerSocket.h" />
<ClInclude Include="src\thrift\windows\config.h" />
<ClInclude Include="src\thrift\windows\force_inc.h" />
<ClInclude Include="src\thrift\windows\TargetVersion.h" />
@ -290,4 +295,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>

View file

@ -10,6 +10,9 @@
<Filter Include="windows">
<UniqueIdentifier>{60fc9e5e-0866-4aba-8662-439bb4a461d3}</UniqueIdentifier>
</Filter>
<Filter Include="transport">
<UniqueIdentifier>{23fe2fde-a7c9-43ec-a409-7f53df5eee64}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\thrift\server\TNonblockingServer.cpp">
@ -27,6 +30,12 @@
<ClCompile Include="src\thrift\windows\StdAfx.cpp">
<Filter>windows</Filter>
</ClCompile>
<ClCompile Include="src\thrift\transport\TNonblockingServerSocket.cpp">
<Filter>transport</Filter>
</ClCompile>
<ClCompile Include="src\thrift\transport\TNonblockingSSLServerSocket.cpp">
<Filter>transport</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\thrift\server\TNonblockingServer.h">
@ -53,5 +62,14 @@
<ClInclude Include="src\thrift\windows\force_inc.h">
<Filter>windows</Filter>
</ClInclude>
<ClInclude Include="src\thrift\transport\TNonblockingServerSocket.h">
<Filter>transport</Filter>
</ClInclude>
<ClInclude Include="src\thrift\transport\TNonblockingServerTransport.h">
<Filter>transport</Filter>
</ClInclude>
<ClInclude Include="src\thrift\transport\TNonblockingSSLServerSocket.h">
<Filter>transport</Filter>
</ClInclude>
</ItemGroup>
</Project>
</Project>

View file

@ -33,8 +33,8 @@ namespace thrift {
template <class Protocol_>
class TDispatchProcessorT : public TProcessor {
public:
virtual bool process(boost::shared_ptr<protocol::TProtocol> in,
boost::shared_ptr<protocol::TProtocol> out,
virtual bool process(stdcxx::shared_ptr<protocol::TProtocol> in,
stdcxx::shared_ptr<protocol::TProtocol> out,
void* connectionContext) {
protocol::TProtocol* inRaw = in.get();
protocol::TProtocol* outRaw = out.get();
@ -105,8 +105,8 @@ protected:
*/
class TDispatchProcessor : public TProcessor {
public:
virtual bool process(boost::shared_ptr<protocol::TProtocol> in,
boost::shared_ptr<protocol::TProtocol> out,
virtual bool process(stdcxx::shared_ptr<protocol::TProtocol> in,
stdcxx::shared_ptr<protocol::TProtocol> out,
void* connectionContext) {
std::string fname;
protocol::TMessageType mtype;

View file

@ -18,9 +18,9 @@
*/
#include <thrift/Thrift.h>
#include <thrift/TToString.h>
#include <cstring>
#include <cstdlib>
#include <boost/lexical_cast.hpp>
#include <stdarg.h>
#include <stdio.h>
@ -94,13 +94,13 @@ void TOutput::errorTimeWrapper(const char* msg) {
}
void TOutput::perror(const char* message, int errno_copy) {
std::string out = message + strerror_s(errno_copy);
std::string out = message + std::string(": ") + strerror_s(errno_copy);
f_(out.c_str());
}
std::string TOutput::strerror_s(int errno_copy) {
#ifndef HAVE_STRERROR_R
return "errno = " + boost::lexical_cast<std::string>(errno_copy);
return "errno = " + to_string(errno_copy);
#else // HAVE_STRERROR_R
char b_errbuf[1024] = {'\0'};
@ -112,7 +112,7 @@ std::string TOutput::strerror_s(int errno_copy) {
if (rv == -1) {
// strerror_r failed. omgwtfbbq.
return "XSI-compliant strerror_r() failed with errno = "
+ boost::lexical_cast<std::string>(errno_copy);
+ to_string(errno_copy);
}
#endif
// Can anyone prove that explicit cast is probably not necessary

View file

@ -22,7 +22,7 @@
#include <string>
#include <thrift/protocol/TProtocol.h>
#include <boost/shared_ptr.hpp>
#include <thrift/stdcxx.h>
namespace apache {
namespace thrift {
@ -142,28 +142,28 @@ class TProcessor {
public:
virtual ~TProcessor() {}
virtual bool process(boost::shared_ptr<protocol::TProtocol> in,
boost::shared_ptr<protocol::TProtocol> out,
virtual bool process(stdcxx::shared_ptr<protocol::TProtocol> in,
stdcxx::shared_ptr<protocol::TProtocol> out,
void* connectionContext) = 0;
bool process(boost::shared_ptr<apache::thrift::protocol::TProtocol> io, void* connectionContext) {
bool process(stdcxx::shared_ptr<apache::thrift::protocol::TProtocol> io, void* connectionContext) {
return process(io, io, connectionContext);
}
boost::shared_ptr<TProcessorEventHandler> getEventHandler() const { return eventHandler_; }
stdcxx::shared_ptr<TProcessorEventHandler> getEventHandler() const { return eventHandler_; }
void setEventHandler(boost::shared_ptr<TProcessorEventHandler> eventHandler) {
void setEventHandler(stdcxx::shared_ptr<TProcessorEventHandler> eventHandler) {
eventHandler_ = eventHandler;
}
protected:
TProcessor() {}
boost::shared_ptr<TProcessorEventHandler> eventHandler_;
stdcxx::shared_ptr<TProcessorEventHandler> eventHandler_;
};
/**
* This is a helper class to allow boost::shared_ptr to be used with handler
* This is a helper class to allow stdcxx::shared_ptr to be used with handler
* pointers returned by the generated handler factories.
*
* The handler factory classes generated by the thrift compiler return raw
@ -177,7 +177,7 @@ protected:
template <typename HandlerFactory_>
class ReleaseHandler {
public:
ReleaseHandler(const boost::shared_ptr<HandlerFactory_>& handlerFactory)
ReleaseHandler(const stdcxx::shared_ptr<HandlerFactory_>& handlerFactory)
: handlerFactory_(handlerFactory) {}
void operator()(typename HandlerFactory_::Handler* handler) {
@ -187,18 +187,18 @@ public:
}
private:
boost::shared_ptr<HandlerFactory_> handlerFactory_;
stdcxx::shared_ptr<HandlerFactory_> handlerFactory_;
};
struct TConnectionInfo {
// The input and output protocols
boost::shared_ptr<protocol::TProtocol> input;
boost::shared_ptr<protocol::TProtocol> output;
stdcxx::shared_ptr<protocol::TProtocol> input;
stdcxx::shared_ptr<protocol::TProtocol> output;
// The underlying transport used for the connection
// This is the transport that was returned by TServerTransport::accept(),
// and it may be different than the transport pointed to by the input and
// output protocols.
boost::shared_ptr<transport::TTransport> transport;
stdcxx::shared_ptr<transport::TTransport> transport;
};
class TProcessorFactory {
@ -212,17 +212,17 @@ public:
* accepted on. This generally means that this call does not need to be
* thread safe, as it will always be invoked from a single thread.
*/
virtual boost::shared_ptr<TProcessor> getProcessor(const TConnectionInfo& connInfo) = 0;
virtual stdcxx::shared_ptr<TProcessor> getProcessor(const TConnectionInfo& connInfo) = 0;
};
class TSingletonProcessorFactory : public TProcessorFactory {
public:
TSingletonProcessorFactory(boost::shared_ptr<TProcessor> processor) : processor_(processor) {}
TSingletonProcessorFactory(stdcxx::shared_ptr<TProcessor> processor) : processor_(processor) {}
boost::shared_ptr<TProcessor> getProcessor(const TConnectionInfo&) { return processor_; }
stdcxx::shared_ptr<TProcessor> getProcessor(const TConnectionInfo&) { return processor_; }
private:
boost::shared_ptr<TProcessor> processor_;
stdcxx::shared_ptr<TProcessor> processor_;
};
}
} // apache::thrift

View file

@ -20,20 +20,45 @@
#ifndef _THRIFT_TOSTRING_H_
#define _THRIFT_TOSTRING_H_ 1
#include <boost/lexical_cast.hpp>
#include <vector>
#include <cmath>
#include <limits>
#include <map>
#include <set>
#include <string>
#include <sstream>
#include <string>
#include <vector>
namespace apache {
namespace thrift {
template <typename T>
std::string to_string(const T& t) {
return boost::lexical_cast<std::string>(t);
std::ostringstream o;
o << t;
return o.str();
}
// TODO: replace the computations below with std::numeric_limits::max_digits10 once C++11
// is enabled.
inline std::string to_string(const float& t) {
std::ostringstream o;
o.precision(static_cast<std::streamsize>(std::ceil(static_cast<double>(std::numeric_limits<float>::digits * std::log10(2.0f) + 1))));
o << t;
return o.str();
}
inline std::string to_string(const double& t) {
std::ostringstream o;
o.precision(static_cast<std::streamsize>(std::ceil(static_cast<double>(std::numeric_limits<double>::digits * std::log10(2.0f) + 1))));
o << t;
return o.str();
}
inline std::string to_string(const long double& t) {
std::ostringstream o;
o.precision(static_cast<std::streamsize>(std::ceil(static_cast<double>(std::numeric_limits<long double>::digits * std::log10(2.0f) + 1))));
o << t;
return o.str();
}
template <typename K, typename V>

View file

@ -20,9 +20,7 @@
#ifndef _THRIFT_TASYNC_BUFFER_PROCESSOR_H_
#define _THRIFT_TASYNC_BUFFER_PROCESSOR_H_ 1
#include <thrift/cxxfunctional.h>
#include <boost/shared_ptr.hpp>
#include <thrift/stdcxx.h>
#include <thrift/transport/TBufferTransports.h>
namespace apache {
@ -36,9 +34,9 @@ public:
// forcefully close the connection (if applicable).
// "in" and "out" should be TMemoryBuffer or similar,
// not a wrapper around a socket.
virtual void process(apache::thrift::stdcxx::function<void(bool healthy)> _return,
boost::shared_ptr<apache::thrift::transport::TBufferBase> ibuf,
boost::shared_ptr<apache::thrift::transport::TBufferBase> obuf) = 0;
virtual void process(stdcxx::function<void(bool healthy)> _return,
stdcxx::shared_ptr<transport::TBufferBase> ibuf,
stdcxx::shared_ptr<transport::TBufferBase> obuf) = 0;
virtual ~TAsyncBufferProcessor() {}
};
}

View file

@ -18,7 +18,7 @@
*/
#include <thrift/async/TAsyncChannel.h>
#include <thrift/cxxfunctional.h>
#include <thrift/stdcxx.h>
namespace apache {
namespace thrift {

View file

@ -20,7 +20,7 @@
#ifndef _THRIFT_ASYNC_TASYNCCHANNEL_H_
#define _THRIFT_ASYNC_TASYNCCHANNEL_H_ 1
#include <thrift/cxxfunctional.h>
#include <thrift/stdcxx.h>
#include <thrift/Thrift.h>
namespace apache {

View file

@ -35,8 +35,8 @@ template <class Protocol_>
class TAsyncDispatchProcessorT : public TAsyncProcessor {
public:
virtual void process(apache::thrift::stdcxx::function<void(bool success)> _return,
boost::shared_ptr<protocol::TProtocol> in,
boost::shared_ptr<protocol::TProtocol> out) {
stdcxx::shared_ptr<protocol::TProtocol> in,
stdcxx::shared_ptr<protocol::TProtocol> out) {
protocol::TProtocol* inRaw = in.get();
protocol::TProtocol* outRaw = out.get();
@ -107,8 +107,8 @@ public:
class TAsyncDispatchProcessor : public TAsyncProcessor {
public:
virtual void process(apache::thrift::stdcxx::function<void(bool success)> _return,
boost::shared_ptr<protocol::TProtocol> in,
boost::shared_ptr<protocol::TProtocol> out) {
stdcxx::shared_ptr<protocol::TProtocol> in,
stdcxx::shared_ptr<protocol::TProtocol> out) {
protocol::TProtocol* inRaw = in.get();
protocol::TProtocol* outRaw = out.get();

View file

@ -20,9 +20,8 @@
#ifndef _THRIFT_TASYNCPROCESSOR_H_
#define _THRIFT_TASYNCPROCESSOR_H_ 1
#include <thrift/cxxfunctional.h>
#include <boost/shared_ptr.hpp>
#include <thrift/protocol/TProtocol.h>
#include <thrift/stdcxx.h>
#include <thrift/TProcessor.h>
namespace apache {
@ -38,25 +37,25 @@ class TAsyncProcessor {
public:
virtual ~TAsyncProcessor() {}
virtual void process(apache::thrift::stdcxx::function<void(bool success)> _return,
boost::shared_ptr<protocol::TProtocol> in,
boost::shared_ptr<protocol::TProtocol> out) = 0;
virtual void process(stdcxx::function<void(bool success)> _return,
stdcxx::shared_ptr<protocol::TProtocol> in,
stdcxx::shared_ptr<protocol::TProtocol> out) = 0;
void process(apache::thrift::stdcxx::function<void(bool success)> _return,
boost::shared_ptr<apache::thrift::protocol::TProtocol> io) {
void process(stdcxx::function<void(bool success)> _return,
stdcxx::shared_ptr<protocol::TProtocol> io) {
return process(_return, io, io);
}
boost::shared_ptr<TProcessorEventHandler> getEventHandler() const { return eventHandler_; }
stdcxx::shared_ptr<TProcessorEventHandler> getEventHandler() const { return eventHandler_; }
void setEventHandler(boost::shared_ptr<TProcessorEventHandler> eventHandler) {
void setEventHandler(stdcxx::shared_ptr<TProcessorEventHandler> eventHandler) {
eventHandler_ = eventHandler;
}
protected:
TAsyncProcessor() {}
boost::shared_ptr<TProcessorEventHandler> eventHandler_;
stdcxx::shared_ptr<TProcessorEventHandler> eventHandler_;
};
class TAsyncProcessorFactory {
@ -70,16 +69,15 @@ public:
* accepted on. This generally means that this call does not need to be
* thread safe, as it will always be invoked from a single thread.
*/
virtual boost::shared_ptr<TAsyncProcessor> getProcessor(const TConnectionInfo& connInfo) = 0;
virtual stdcxx::shared_ptr<TAsyncProcessor> getProcessor(const TConnectionInfo& connInfo) = 0;
};
}
}
} // apache::thrift::async
// XXX I'm lazy for now
namespace apache {
namespace thrift {
using apache::thrift::async::TAsyncProcessor;
using apache::thrift::async::TAsyncProcessor;
}
}

View file

@ -27,10 +27,10 @@ namespace thrift {
namespace async {
void TAsyncProtocolProcessor::process(apache::thrift::stdcxx::function<void(bool healthy)> _return,
boost::shared_ptr<TBufferBase> ibuf,
boost::shared_ptr<TBufferBase> obuf) {
boost::shared_ptr<TProtocol> iprot(pfact_->getProtocol(ibuf));
boost::shared_ptr<TProtocol> oprot(pfact_->getProtocol(obuf));
stdcxx::shared_ptr<TBufferBase> ibuf,
stdcxx::shared_ptr<TBufferBase> obuf) {
stdcxx::shared_ptr<TProtocol> iprot(pfact_->getProtocol(ibuf));
stdcxx::shared_ptr<TProtocol> oprot(pfact_->getProtocol(obuf));
return underlying_
->process(apache::thrift::stdcxx::bind(&TAsyncProtocolProcessor::finish,
_return,
@ -42,7 +42,7 @@ void TAsyncProtocolProcessor::process(apache::thrift::stdcxx::function<void(bool
/* static */ void TAsyncProtocolProcessor::finish(
apache::thrift::stdcxx::function<void(bool healthy)> _return,
boost::shared_ptr<TProtocol> oprot,
stdcxx::shared_ptr<TProtocol> oprot,
bool healthy) {
(void)oprot;
// This is a stub function to hold a reference to oprot.

View file

@ -30,23 +30,23 @@ namespace async {
class TAsyncProtocolProcessor : public TAsyncBufferProcessor {
public:
TAsyncProtocolProcessor(boost::shared_ptr<TAsyncProcessor> underlying,
boost::shared_ptr<apache::thrift::protocol::TProtocolFactory> pfact)
TAsyncProtocolProcessor(stdcxx::shared_ptr<TAsyncProcessor> underlying,
stdcxx::shared_ptr<apache::thrift::protocol::TProtocolFactory> pfact)
: underlying_(underlying), pfact_(pfact) {}
virtual void process(apache::thrift::stdcxx::function<void(bool healthy)> _return,
boost::shared_ptr<apache::thrift::transport::TBufferBase> ibuf,
boost::shared_ptr<apache::thrift::transport::TBufferBase> obuf);
stdcxx::shared_ptr<apache::thrift::transport::TBufferBase> ibuf,
stdcxx::shared_ptr<apache::thrift::transport::TBufferBase> obuf);
virtual ~TAsyncProtocolProcessor() {}
private:
static void finish(apache::thrift::stdcxx::function<void(bool healthy)> _return,
boost::shared_ptr<apache::thrift::protocol::TProtocol> oprot,
stdcxx::shared_ptr<apache::thrift::protocol::TProtocol> oprot,
bool healthy);
boost::shared_ptr<TAsyncProcessor> underlying_;
boost::shared_ptr<apache::thrift::protocol::TProtocolFactory> pfact_;
stdcxx::shared_ptr<TAsyncProcessor> underlying_;
stdcxx::shared_ptr<apache::thrift::protocol::TProtocolFactory> pfact_;
};
}
}

View file

@ -22,7 +22,7 @@
#include <thrift/protocol/TProtocol.h>
#include <thrift/concurrency/Mutex.h>
#include <thrift/concurrency/Monitor.h>
#include <boost/shared_ptr.hpp>
#include <thrift/stdcxx.h>
#include <vector>
#include <string>
#include <map>
@ -60,7 +60,7 @@ private:
class TConcurrentClientSyncInfo {
private: // typedefs
typedef boost::shared_ptr< ::apache::thrift::concurrency::Monitor> MonitorPtr;
typedef stdcxx::shared_ptr< ::apache::thrift::concurrency::Monitor> MonitorPtr;
typedef std::map<int32_t, MonitorPtr> MonitorMap;
public:

View file

@ -38,13 +38,14 @@ TEvhttpClientChannel::TEvhttpClientChannel(const std::string& host,
const std::string& path,
const char* address,
int port,
struct event_base* eb)
struct event_base* eb,
struct evdns_base* dnsbase)
: host_(host), path_(path), conn_(NULL) {
conn_ = evhttp_connection_new(address, port);
conn_ = evhttp_connection_base_new(eb, dnsbase, address, port);
if (conn_ == NULL) {
throw TException("evhttp_connection_new failed");
}
evhttp_connection_set_base(conn_, eb);
}
TEvhttpClientChannel::~TEvhttpClientChannel() {

View file

@ -23,10 +23,11 @@
#include <queue>
#include <string>
#include <utility>
#include <boost/shared_ptr.hpp>
#include <thrift/stdcxx.h>
#include <thrift/async/TAsyncChannel.h>
struct event_base;
struct evdns_base;
struct evhttp_connection;
struct evhttp_request;
@ -50,7 +51,8 @@ public:
const std::string& path,
const char* address,
int port,
struct event_base* eb);
struct event_base* eb,
struct evdns_base *dnsbase = 0);
~TEvhttpClientChannel();
virtual void sendAndRecvMessage(const VoidCallback& cob,

View file

@ -20,10 +20,10 @@
#include <thrift/async/TEvhttpServer.h>
#include <thrift/async/TAsyncBufferProcessor.h>
#include <thrift/transport/TBufferTransports.h>
#include <thrift/stdcxx.h>
#include <evhttp.h>
#include <event2/buffer.h>
#include <event2/buffer_compat.h>
#include <iostream>
#ifndef HTTP_INTERNAL // libevent < 2
@ -31,6 +31,8 @@
#endif
using apache::thrift::transport::TMemoryBuffer;
using apache::thrift::stdcxx::scoped_ptr;
using apache::thrift::stdcxx::shared_ptr;
namespace apache {
namespace thrift {
@ -38,17 +40,17 @@ namespace async {
struct TEvhttpServer::RequestContext {
struct evhttp_request* req;
boost::shared_ptr<apache::thrift::transport::TMemoryBuffer> ibuf;
boost::shared_ptr<apache::thrift::transport::TMemoryBuffer> obuf;
stdcxx::shared_ptr<apache::thrift::transport::TMemoryBuffer> ibuf;
stdcxx::shared_ptr<apache::thrift::transport::TMemoryBuffer> obuf;
RequestContext(struct evhttp_request* req);
};
TEvhttpServer::TEvhttpServer(boost::shared_ptr<TAsyncBufferProcessor> processor)
TEvhttpServer::TEvhttpServer(stdcxx::shared_ptr<TAsyncBufferProcessor> processor)
: processor_(processor), eb_(NULL), eh_(NULL) {
}
TEvhttpServer::TEvhttpServer(boost::shared_ptr<TAsyncBufferProcessor> processor, int port)
TEvhttpServer::TEvhttpServer(stdcxx::shared_ptr<TAsyncBufferProcessor> processor, int port)
: processor_(processor), eb_(NULL), eh_(NULL) {
// Create event_base and evhttp.
eb_ = event_base_new();
@ -118,7 +120,7 @@ void TEvhttpServer::process(struct evhttp_request* req) {
void TEvhttpServer::complete(RequestContext* ctx, bool success) {
(void)success;
std::auto_ptr<RequestContext> ptr(ctx);
scoped_ptr<RequestContext> ptr(ctx);
int code = success ? 200 : 400;
const char* reason = success ? "OK" : "Bad Request";

View file

@ -20,7 +20,7 @@
#ifndef _THRIFT_TEVHTTP_SERVER_H_
#define _THRIFT_TEVHTTP_SERVER_H_ 1
#include <boost/shared_ptr.hpp>
#include <thrift/stdcxx.h>
struct event_base;
struct evhttp;
@ -41,14 +41,14 @@ public:
* address of the server as the extra arg.
* Do not call "serve" on this server.
*/
TEvhttpServer(boost::shared_ptr<TAsyncBufferProcessor> processor);
TEvhttpServer(stdcxx::shared_ptr<TAsyncBufferProcessor> processor);
/**
* Create a TEvhttpServer with an embedded event_base and evhttp,
* listening on port and responding on the endpoint "/".
* Call "serve" on this server to serve forever.
*/
TEvhttpServer(boost::shared_ptr<TAsyncBufferProcessor> processor, int port);
TEvhttpServer(stdcxx::shared_ptr<TAsyncBufferProcessor> processor, int port);
~TEvhttpServer();
@ -63,7 +63,7 @@ private:
void process(struct evhttp_request* req);
void complete(RequestContext* ctx, bool success);
boost::shared_ptr<TAsyncBufferProcessor> processor_;
stdcxx::shared_ptr<TAsyncBufferProcessor> processor_;
struct event_base* eb_;
struct evhttp* eh_;
};

View file

@ -23,9 +23,9 @@
#include <thrift/concurrency/Exception.h>
#include <thrift/concurrency/Util.h>
#include <thrift/transport/PlatformSocket.h>
#include <assert.h>
#include <thrift/stdcxx.h>
#include <boost/scoped_ptr.hpp>
#include <assert.h>
#include <boost/thread.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
@ -155,7 +155,7 @@ public:
private:
void init(Mutex* mutex) { mutex_ = mutex; }
boost::scoped_ptr<Mutex> ownedMutex_;
stdcxx::scoped_ptr<Mutex> ownedMutex_;
Mutex* mutex_;
};

View file

@ -33,7 +33,9 @@ namespace thrift {
namespace concurrency {
/**
* Implementation of Mutex class using boost interprocess mutex
* Implementation of Mutex class using boost::timed_mutex
*
* Methods throw boost::lock_error on error.
*
* @version $Id:$
*/

View file

@ -23,18 +23,20 @@
#include <thrift/concurrency/BoostThreadFactory.h>
#include <thrift/concurrency/Exception.h>
#include <thrift/stdcxx.h>
#include <cassert>
#include <boost/weak_ptr.hpp>
#include <boost/thread.hpp>
namespace apache {
namespace thrift {
namespace concurrency {
using boost::shared_ptr;
using boost::weak_ptr;
using stdcxx::bind;
using stdcxx::scoped_ptr;
using stdcxx::shared_ptr;
using stdcxx::weak_ptr;
namespace concurrency {
/**
* The boost thread class.
@ -48,7 +50,8 @@ public:
static void* threadMain(void* arg);
private:
std::auto_ptr<boost::thread> thread_;
scoped_ptr<boost::thread> thread_;
Monitor monitor_;
STATE state_;
weak_ptr<BoostThread> self_;
bool detached_;
@ -60,7 +63,7 @@ public:
}
~BoostThread() {
if (!detached_) {
if (!detached_ && thread_->joinable()) {
try {
join();
} catch (...) {
@ -69,26 +72,46 @@ public:
}
}
void start() {
if (state_ != uninitialized) {
return;
}
STATE getState() const
{
Synchronized sync(monitor_);
return state_;
}
void setState(STATE newState)
{
Synchronized sync(monitor_);
state_ = newState;
// unblock start() with the knowledge that the thread has actually
// started running, which avoids a race in detached threads.
if (newState == started) {
monitor_.notify();
}
}
void start() {
// Create reference
shared_ptr<BoostThread>* selfRef = new shared_ptr<BoostThread>();
*selfRef = self_.lock();
state_ = starting;
setState(starting);
thread_
= std::auto_ptr<boost::thread>(new boost::thread(boost::bind(threadMain, (void*)selfRef)));
Synchronized sync(monitor_);
thread_.reset(new boost::thread(bind(threadMain, (void*)selfRef)));
if (detached_)
thread_->detach();
// Wait for the thread to start and get far enough to grab everything
// that it needs from the calling context, thus absolving the caller
// from being required to hold on to runnable indefinitely.
monitor_.wait();
}
void join() {
if (!detached_ && state_ != uninitialized) {
if (!detached_ && getState() != uninitialized) {
thread_->join();
}
}
@ -109,19 +132,11 @@ void* BoostThread::threadMain(void* arg) {
shared_ptr<BoostThread> thread = *(shared_ptr<BoostThread>*)arg;
delete reinterpret_cast<shared_ptr<BoostThread>*>(arg);
if (!thread) {
return (void*)0;
}
if (thread->state_ != starting) {
return (void*)0;
}
thread->state_ = started;
thread->setState(started);
thread->runnable()->run();
if (thread->state_ != stopping && thread->state_ != stopped) {
thread->state_ = stopping;
if (thread->getState() != stopping && thread->getState() != stopped) {
thread->setState(stopping);
}
return (void*)0;
}

View file

@ -20,9 +20,9 @@
#ifndef _THRIFT_CONCURRENCY_BOOSTTHREADFACTORY_H_
#define _THRIFT_CONCURRENCY_BOOSTTHREADFACTORY_H_ 1
#include <thrift/concurrency/Monitor.h>
#include <thrift/concurrency/Thread.h>
#include <boost/shared_ptr.hpp>
#include <thrift/stdcxx.h>
namespace apache {
namespace thrift {
@ -38,9 +38,8 @@ class BoostThreadFactory : public ThreadFactory {
public:
/**
* Boost thread factory. All threads created by a factory are reference-counted
* via boost::shared_ptr and boost::weak_ptr. The factory guarantees that threads and
* the Runnable tasks they host will be properly cleaned up once the last strong reference
* to both is given up.
* via stdcxx::shared_ptr. The factory guarantees that threads and the Runnable tasks they
* host will be properly cleaned up once the last strong reference to both is given up.
*
* Threads are created with the specified boost policy, priority, stack-size. A detachable thread
* is not joinable.
@ -51,7 +50,7 @@ public:
BoostThreadFactory(bool detached = true);
// From ThreadFactory;
boost::shared_ptr<Thread> newThread(boost::shared_ptr<Runnable> runnable) const;
stdcxx::shared_ptr<Thread> newThread(stdcxx::shared_ptr<Runnable> runnable) const;
// From ThreadFactory;
Thread::id_t getCurrentThreadId() const;

View file

@ -20,8 +20,8 @@
#ifndef _THRIFT_CONCURRENCY_FUNCTION_RUNNER_H
#define _THRIFT_CONCURRENCY_FUNCTION_RUNNER_H 1
#include <thrift/cxxfunctional.h>
#include <thrift/concurrency/Thread.h>
#include <thrift/stdcxx.h>
namespace apache {
namespace thrift {
@ -53,20 +53,20 @@ public:
// This is the type of callback 'pthread_create()' expects.
typedef void* (*PthreadFuncPtr)(void* arg);
// This a fully-generic void(void) callback for custom bindings.
typedef apache::thrift::stdcxx::function<void()> VoidFunc;
typedef stdcxx::function<void()> VoidFunc;
typedef apache::thrift::stdcxx::function<bool()> BoolFunc;
typedef stdcxx::function<bool()> BoolFunc;
/**
* Syntactic sugar to make it easier to create new FunctionRunner
* objects wrapped in shared_ptr.
*/
static boost::shared_ptr<FunctionRunner> create(const VoidFunc& cob) {
return boost::shared_ptr<FunctionRunner>(new FunctionRunner(cob));
static stdcxx::shared_ptr<FunctionRunner> create(const VoidFunc& cob) {
return stdcxx::shared_ptr<FunctionRunner>(new FunctionRunner(cob));
}
static boost::shared_ptr<FunctionRunner> create(PthreadFuncPtr func, void* arg) {
return boost::shared_ptr<FunctionRunner>(new FunctionRunner(func, arg));
static stdcxx::shared_ptr<FunctionRunner> create(PthreadFuncPtr func, void* arg) {
return stdcxx::shared_ptr<FunctionRunner>(new FunctionRunner(func, arg));
}
private:
@ -81,7 +81,7 @@ public:
* execute the given callback. Note that the 'void*' return value is ignored.
*/
FunctionRunner(PthreadFuncPtr func, void* arg)
: func_(apache::thrift::stdcxx::bind(pthread_func_wrapper, func, arg)), intervalMs_(-1) {}
: func_(stdcxx::bind(pthread_func_wrapper, func, arg)), intervalMs_(-1) {}
/**
* Given a generic callback, this FunctionRunner will execute it.

View file

@ -23,8 +23,7 @@
#include <thrift/concurrency/Exception.h>
#include <thrift/concurrency/Util.h>
#include <thrift/transport/PlatformSocket.h>
#include <boost/scoped_ptr.hpp>
#include <thrift/stdcxx.h>
#include <assert.h>
@ -34,9 +33,11 @@
namespace apache {
namespace thrift {
namespace concurrency {
using boost::scoped_ptr;
using stdcxx::scoped_ptr;
using stdcxx::shared_ptr;
namespace concurrency {
/**
* Monitor implementation using the POSIX pthread library

View file

@ -17,25 +17,32 @@
* under the License.
*/
// needed to test for pthread implementation capabilities:
#define __USE_GNU
#include <thrift/thrift-config.h>
#include <thrift/Thrift.h>
#include <thrift/concurrency/Exception.h>
#include <thrift/concurrency/Mutex.h>
#include <thrift/concurrency/Util.h>
#include <assert.h>
#ifdef HAVE_PTHREAD_H
#include <stdlib.h>
#include <pthread.h>
#endif
#include <signal.h>
#include <string.h>
using boost::shared_ptr;
#include <boost/format.hpp>
namespace apache {
namespace thrift {
namespace concurrency {
#ifndef THRIFT_NO_CONTENTION_PROFILING
// Enable this to turn on mutex contention profiling support
// #define THRIFT_PTHREAD_MUTEX_CONTENTION_PROFILING
#ifdef THRIFT_PTHREAD_MUTEX_CONTENTION_PROFILING
static int32_t mutexProfilingCounter = 0;
static int32_t mutexProfilingSampleRate = 0;
@ -105,17 +112,25 @@ static inline int64_t maybeGetProfilingStartTime() {
#define PROFILE_MUTEX_LOCKED()
#define PROFILE_MUTEX_START_UNLOCK()
#define PROFILE_MUTEX_UNLOCKED()
#endif // THRIFT_NO_CONTENTION_PROFILING
#endif // THRIFT_PTHREAD_MUTEX_CONTENTION_PROFILING
#define EINTR_LOOP(_CALL) int ret; do { ret = _CALL; } while (ret == EINTR)
#define ABORT_ONFAIL(_CALL) { EINTR_LOOP(_CALL); if (ret) { abort(); } }
#define THROW_SRE(_CALLSTR, RET) { throw SystemResourceException(boost::str(boost::format("%1% returned %2% (%3%)") % _CALLSTR % RET % ::strerror(RET))); }
#define THROW_SRE_ONFAIL(_CALL) { EINTR_LOOP(_CALL); if (ret) { THROW_SRE(#_CALL, ret); } }
#define THROW_SRE_TRYFAIL(_CALL) { EINTR_LOOP(_CALL); if (ret == 0) { return true; } else if (ret == EBUSY) { return false; } THROW_SRE(#_CALL, ret); }
/**
* Implementation of Mutex class using POSIX mutex
*
* Throws apache::thrift::concurrency::SystemResourceException on error.
*
* @version $Id:$
*/
class Mutex::impl {
public:
impl(Initializer init) : initialized_(false) {
#ifndef THRIFT_NO_CONTENTION_PROFILING
#ifdef THRIFT_PTHREAD_MUTEX_CONTENTION_PROFILING
profileTime_ = 0;
#endif
init(&pthread_mutex_);
@ -125,19 +140,19 @@ public:
~impl() {
if (initialized_) {
initialized_ = false;
int ret = pthread_mutex_destroy(&pthread_mutex_);
THRIFT_UNUSED_VARIABLE(ret);
assert(ret == 0);
ABORT_ONFAIL(pthread_mutex_destroy(&pthread_mutex_));
}
}
void lock() const {
PROFILE_MUTEX_START_LOCK();
pthread_mutex_lock(&pthread_mutex_);
THROW_SRE_ONFAIL(pthread_mutex_lock(&pthread_mutex_));
PROFILE_MUTEX_LOCKED();
}
bool trylock() const { return (0 == pthread_mutex_trylock(&pthread_mutex_)); }
bool trylock() const {
THROW_SRE_TRYFAIL(pthread_mutex_trylock(&pthread_mutex_));
}
bool timedlock(int64_t milliseconds) const {
#if defined(_POSIX_TIMEOUTS) && _POSIX_TIMEOUTS >= 200112L
@ -145,14 +160,16 @@ public:
struct THRIFT_TIMESPEC ts;
Util::toTimespec(ts, milliseconds + Util::currentTime());
int ret = pthread_mutex_timedlock(&pthread_mutex_, &ts);
EINTR_LOOP(pthread_mutex_timedlock(&pthread_mutex_, &ts));
if (ret == 0) {
PROFILE_MUTEX_LOCKED();
return true;
} else if (ret == ETIMEDOUT) {
PROFILE_MUTEX_NOT_LOCKED();
return false;
}
PROFILE_MUTEX_NOT_LOCKED();
return false;
THROW_SRE("pthread_mutex_timedlock(&pthread_mutex_, &ts)", ret);
#else
/* Otherwise follow solution used by Mono for Android */
struct THRIFT_TIMESPEC sleepytime, now, to;
@ -177,7 +194,7 @@ public:
void unlock() const {
PROFILE_MUTEX_START_UNLOCK();
pthread_mutex_unlock(&pthread_mutex_);
THROW_SRE_ONFAIL(pthread_mutex_unlock(&pthread_mutex_));
PROFILE_MUTEX_UNLOCKED();
}
@ -186,7 +203,7 @@ public:
private:
mutable pthread_mutex_t pthread_mutex_;
mutable bool initialized_;
#ifndef THRIFT_NO_CONTENTION_PROFILING
#ifdef THRIFT_PTHREAD_MUTEX_CONTENTION_PROFILING
mutable int64_t profileTime_;
#endif
};
@ -216,28 +233,16 @@ void Mutex::unlock() const {
void Mutex::DEFAULT_INITIALIZER(void* arg) {
pthread_mutex_t* pthread_mutex = (pthread_mutex_t*)arg;
int ret = pthread_mutex_init(pthread_mutex, NULL);
THRIFT_UNUSED_VARIABLE(ret);
assert(ret == 0);
THROW_SRE_ONFAIL(pthread_mutex_init(pthread_mutex, NULL));
}
#if defined(PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP) \
|| defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP)
#if defined(PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP) || defined(PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP) || defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP)
static void init_with_kind(pthread_mutex_t* mutex, int kind) {
pthread_mutexattr_t mutexattr;
int ret = pthread_mutexattr_init(&mutexattr);
assert(ret == 0);
// Apparently, this can fail. Should we really be aborting?
ret = pthread_mutexattr_settype(&mutexattr, kind);
assert(ret == 0);
ret = pthread_mutex_init(mutex, &mutexattr);
assert(ret == 0);
ret = pthread_mutexattr_destroy(&mutexattr);
assert(ret == 0);
THRIFT_UNUSED_VARIABLE(ret);
THROW_SRE_ONFAIL(pthread_mutexattr_init(&mutexattr));
THROW_SRE_ONFAIL(pthread_mutexattr_settype(&mutexattr, kind));
THROW_SRE_ONFAIL(pthread_mutex_init(mutex, &mutexattr));
THROW_SRE_ONFAIL(pthread_mutexattr_destroy(&mutexattr));
}
#endif
@ -255,6 +260,12 @@ void Mutex::ADAPTIVE_INITIALIZER(void* arg) {
}
#endif
#ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
void Mutex::ERRORCHECK_INITIALIZER(void* arg) {
init_with_kind((pthread_mutex_t*)arg, PTHREAD_MUTEX_ERRORCHECK);
}
#endif
#ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
void Mutex::RECURSIVE_INITIALIZER(void* arg) {
init_with_kind((pthread_mutex_t*)arg, PTHREAD_MUTEX_RECURSIVE_NP);
@ -269,50 +280,46 @@ void Mutex::RECURSIVE_INITIALIZER(void* arg) {
class ReadWriteMutex::impl {
public:
impl() : initialized_(false) {
#ifndef THRIFT_NO_CONTENTION_PROFILING
#ifdef THRIFT_PTHREAD_MUTEX_CONTENTION_PROFILING
profileTime_ = 0;
#endif
int ret = pthread_rwlock_init(&rw_lock_, NULL);
THRIFT_UNUSED_VARIABLE(ret);
assert(ret == 0);
THROW_SRE_ONFAIL(pthread_rwlock_init(&rw_lock_, NULL));
initialized_ = true;
}
~impl() {
if (initialized_) {
initialized_ = false;
int ret = pthread_rwlock_destroy(&rw_lock_);
THRIFT_UNUSED_VARIABLE(ret);
assert(ret == 0);
ABORT_ONFAIL(pthread_rwlock_destroy(&rw_lock_));
}
}
void acquireRead() const {
PROFILE_MUTEX_START_LOCK();
pthread_rwlock_rdlock(&rw_lock_);
THROW_SRE_ONFAIL(pthread_rwlock_rdlock(&rw_lock_));
PROFILE_MUTEX_NOT_LOCKED(); // not exclusive, so use not-locked path
}
void acquireWrite() const {
PROFILE_MUTEX_START_LOCK();
pthread_rwlock_wrlock(&rw_lock_);
THROW_SRE_ONFAIL(pthread_rwlock_wrlock(&rw_lock_));
PROFILE_MUTEX_LOCKED();
}
bool attemptRead() const { return !pthread_rwlock_tryrdlock(&rw_lock_); }
bool attemptRead() const { THROW_SRE_TRYFAIL(pthread_rwlock_tryrdlock(&rw_lock_)); }
bool attemptWrite() const { return !pthread_rwlock_trywrlock(&rw_lock_); }
bool attemptWrite() const { THROW_SRE_TRYFAIL(pthread_rwlock_trywrlock(&rw_lock_)); }
void release() const {
PROFILE_MUTEX_START_UNLOCK();
pthread_rwlock_unlock(&rw_lock_);
THROW_SRE_ONFAIL(pthread_rwlock_unlock(&rw_lock_));
PROFILE_MUTEX_UNLOCKED();
}
private:
mutable pthread_rwlock_t rw_lock_;
mutable bool initialized_;
#ifndef THRIFT_NO_CONTENTION_PROFILING
#ifdef THRIFT_PTHREAD_MUTEX_CONTENTION_PROFILING
mutable int64_t profileTime_;
#endif
};

View file

@ -20,7 +20,7 @@
#ifndef _THRIFT_CONCURRENCY_MUTEX_H_
#define _THRIFT_CONCURRENCY_MUTEX_H_ 1
#include <boost/shared_ptr.hpp>
#include <thrift/stdcxx.h>
#include <boost/noncopyable.hpp>
#include <stdint.h>
@ -53,6 +53,11 @@ void enableMutexProfiling(int32_t profilingSampleRate, MutexWaitCallback callbac
#endif
/**
* NOTE: All mutex implementations throw an exception on failure. See each
* specific implementation to understand the exception type(s) used.
*/
/**
* A simple mutex class
*
@ -64,6 +69,7 @@ public:
Mutex(Initializer init = DEFAULT_INITIALIZER);
virtual ~Mutex() {}
virtual void lock() const;
virtual bool trylock() const;
virtual bool timedlock(int64_t milliseconds) const;
@ -71,13 +77,16 @@ public:
void* getUnderlyingImpl() const;
static void DEFAULT_INITIALIZER(void*);
// If you attempt to use one of these and it fails to link, it means
// your version of pthreads does not support it - try another one.
static void ADAPTIVE_INITIALIZER(void*);
static void DEFAULT_INITIALIZER(void*);
static void ERRORCHECK_INITIALIZER(void*);
static void RECURSIVE_INITIALIZER(void*);
private:
class impl;
boost::shared_ptr<impl> impl_;
stdcxx::shared_ptr<impl> impl_;
};
class ReadWriteMutex {
@ -98,7 +107,7 @@ public:
private:
class impl;
boost::shared_ptr<impl> impl_;
stdcxx::shared_ptr<impl> impl_;
};
/**

View file

@ -19,8 +19,9 @@
#include <thrift/thrift-config.h>
#include <thrift/concurrency/PosixThreadFactory.h>
#include <thrift/concurrency/Exception.h>
#include <thrift/concurrency/Monitor.h>
#include <thrift/concurrency/PosixThreadFactory.h>
#if GOOGLE_PERFTOOLS_REGISTER_THREAD
#include <google/profiler.h>
@ -31,15 +32,12 @@
#include <iostream>
#include <boost/weak_ptr.hpp>
#include <thrift/stdcxx.h>
namespace apache {
namespace thrift {
namespace concurrency {
using boost::shared_ptr;
using boost::weak_ptr;
/**
* The POSIX thread class.
*
@ -55,11 +53,12 @@ public:
private:
pthread_t pthread_;
STATE state_;
Monitor monitor_; // guard to protect state_ and also notification
STATE state_; // to protect proper thread start behavior
int policy_;
int priority_;
int stackSize_;
weak_ptr<PthreadThread> self_;
stdcxx::weak_ptr<PthreadThread> self_;
bool detached_;
public:
@ -67,13 +66,12 @@ public:
int priority,
int stackSize,
bool detached,
shared_ptr<Runnable> runnable)
stdcxx::shared_ptr<Runnable> runnable)
:
#ifndef _WIN32
pthread_(0),
#endif // _WIN32
state_(uninitialized),
policy_(policy),
priority_(priority),
@ -96,8 +94,26 @@ public:
}
}
STATE getState() const
{
Synchronized sync(monitor_);
return state_;
}
void setState(STATE newState)
{
Synchronized sync(monitor_);
state_ = newState;
// unblock start() with the knowledge that the thread has actually
// started running, which avoids a race in detached threads.
if (newState == started) {
monitor_.notify();
}
}
void start() {
if (state_ != uninitialized) {
if (getState() != uninitialized) {
return;
}
@ -139,18 +155,27 @@ public:
}
// Create reference
shared_ptr<PthreadThread>* selfRef = new shared_ptr<PthreadThread>();
stdcxx::shared_ptr<PthreadThread>* selfRef = new stdcxx::shared_ptr<PthreadThread>();
*selfRef = self_.lock();
state_ = starting;
setState(starting);
Synchronized sync(monitor_);
if (pthread_create(&pthread_, &thread_attr, threadMain, (void*)selfRef) != 0) {
throw SystemResourceException("pthread_create failed");
}
// The caller may not choose to guarantee the scope of the Runnable
// being used in the thread, so we must actually wait until the thread
// starts before we return. If we do not wait, it would be possible
// for the caller to start destructing the Runnable and the Thread,
// and we would end up in a race. This was identified with valgrind.
monitor_.wait();
}
void join() {
if (!detached_ && state_ != uninitialized) {
if (!detached_ && getState() != uninitialized) {
void* ignore;
/* XXX
If join fails it is most likely due to the fact
@ -164,8 +189,6 @@ public:
if (res != 0) {
GlobalOutput.printf("PthreadThread::join(): fail with code %d", res);
}
} else {
GlobalOutput.printf("PthreadThread::join(): detached thread");
}
}
@ -178,36 +201,31 @@ public:
#endif // _WIN32
}
shared_ptr<Runnable> runnable() const { return Thread::runnable(); }
stdcxx::shared_ptr<Runnable> runnable() const { return Thread::runnable(); }
void runnable(shared_ptr<Runnable> value) { Thread::runnable(value); }
void runnable(stdcxx::shared_ptr<Runnable> value) { Thread::runnable(value); }
void weakRef(shared_ptr<PthreadThread> self) {
void weakRef(stdcxx::shared_ptr<PthreadThread> self) {
assert(self.get() == this);
self_ = weak_ptr<PthreadThread>(self);
self_ = stdcxx::weak_ptr<PthreadThread>(self);
}
};
void* PthreadThread::threadMain(void* arg) {
shared_ptr<PthreadThread> thread = *(shared_ptr<PthreadThread>*)arg;
delete reinterpret_cast<shared_ptr<PthreadThread>*>(arg);
if (thread == NULL) {
return (void*)0;
}
if (thread->state_ != starting) {
return (void*)0;
}
stdcxx::shared_ptr<PthreadThread> thread = *(stdcxx::shared_ptr<PthreadThread>*)arg;
delete reinterpret_cast<stdcxx::shared_ptr<PthreadThread>*>(arg);
#if GOOGLE_PERFTOOLS_REGISTER_THREAD
ProfilerRegisterThread();
#endif
thread->state_ = started;
thread->setState(started);
thread->runnable()->run();
if (thread->state_ != stopping && thread->state_ != stopped) {
thread->state_ = stopping;
STATE _s = thread->getState();
if (_s != stopping && _s != stopped) {
thread->setState(stopping);
}
return (void*)0;
@ -276,9 +294,9 @@ PosixThreadFactory::PosixThreadFactory(bool detached)
stackSize_(1) {
}
shared_ptr<Thread> PosixThreadFactory::newThread(shared_ptr<Runnable> runnable) const {
shared_ptr<PthreadThread> result
= shared_ptr<PthreadThread>(new PthreadThread(toPthreadPolicy(policy_),
stdcxx::shared_ptr<Thread> PosixThreadFactory::newThread(stdcxx::shared_ptr<Runnable> runnable) const {
stdcxx::shared_ptr<PthreadThread> result
= stdcxx::shared_ptr<PthreadThread>(new PthreadThread(toPthreadPolicy(policy_),
toPthreadPriority(policy_, priority_),
stackSize_,
isDetached(),

View file

@ -22,7 +22,7 @@
#include <thrift/concurrency/Thread.h>
#include <boost/shared_ptr.hpp>
#include <thrift/stdcxx.h>
namespace apache {
namespace thrift {
@ -63,9 +63,9 @@ public:
/**
* Posix thread (pthread) factory. All threads created by a factory are reference-counted
* via boost::shared_ptr and boost::weak_ptr. The factory guarantees that threads and
* the Runnable tasks they host will be properly cleaned up once the last strong reference
* to both is given up.
* via stdcxx::shared_ptr. The factory guarantees that threads and the Runnable tasks
* they host will be properly cleaned up once the last strong reference to both is
* given up.
*
* Threads are created with the specified policy, priority, stack-size and detachable-mode
* detached means the thread is free-running and will release all system resources the
@ -88,7 +88,7 @@ public:
PosixThreadFactory(bool detached);
// From ThreadFactory;
boost::shared_ptr<Thread> newThread(boost::shared_ptr<Runnable> runnable) const;
stdcxx::shared_ptr<Thread> newThread(stdcxx::shared_ptr<Runnable> runnable) const;
// From ThreadFactory;
Thread::id_t getCurrentThreadId() const;

View file

@ -33,11 +33,14 @@ namespace concurrency {
/**
* Implementation of Mutex class using C++11 std::timed_mutex
*
* Methods throw std::system_error on error.
*
* @version $Id:$
*/
class Mutex::impl : public std::timed_mutex {};
Mutex::Mutex(Initializer init) : impl_(new Mutex::impl()) {
((void)init);
}
void* Mutex::getUnderlyingImpl() const {
@ -61,6 +64,7 @@ void Mutex::unlock() const {
}
void Mutex::DEFAULT_INITIALIZER(void* arg) {
((void)arg);
}
}
}

View file

@ -21,13 +21,12 @@
#if USE_STD_THREAD
#include <thrift/concurrency/StdThreadFactory.h>
#include <thrift/concurrency/Exception.h>
#include <thrift/concurrency/Monitor.h>
#include <thrift/concurrency/StdThreadFactory.h>
#include <thrift/stdcxx.h>
#include <cassert>
#include <boost/enable_shared_from_this.hpp>
#include <boost/weak_ptr.hpp>
#include <thread>
namespace apache {
@ -43,25 +42,26 @@ namespace concurrency {
*
* @version $Id:$
*/
class StdThread : public Thread, public boost::enable_shared_from_this<StdThread> {
class StdThread : public Thread, public stdcxx::enable_shared_from_this<StdThread> {
public:
enum STATE { uninitialized, starting, started, stopping, stopped };
static void threadMain(boost::shared_ptr<StdThread> thread);
static void threadMain(stdcxx::shared_ptr<StdThread> thread);
private:
std::unique_ptr<std::thread> thread_;
Monitor monitor_;
STATE state_;
bool detached_;
public:
StdThread(bool detached, boost::shared_ptr<Runnable> runnable)
StdThread(bool detached, stdcxx::shared_ptr<Runnable> runnable)
: state_(uninitialized), detached_(detached) {
this->Thread::runnable(runnable);
}
~StdThread() {
if (!detached_) {
if (!detached_ && thread_->joinable()) {
try {
join();
} catch (...) {
@ -70,18 +70,42 @@ public:
}
}
STATE getState() const
{
Synchronized sync(monitor_);
return state_;
}
void setState(STATE newState)
{
Synchronized sync(monitor_);
state_ = newState;
// unblock start() with the knowledge that the thread has actually
// started running, which avoids a race in detached threads.
if (newState == started) {
monitor_.notify();
}
}
void start() {
if (state_ != uninitialized) {
if (getState() != uninitialized) {
return;
}
boost::shared_ptr<StdThread> selfRef = shared_from_this();
state_ = starting;
stdcxx::shared_ptr<StdThread> selfRef = shared_from_this();
setState(starting);
Synchronized sync(monitor_);
thread_ = std::unique_ptr<std::thread>(new std::thread(threadMain, selfRef));
if (detached_)
thread_->detach();
// Wait for the thread to start and get far enough to grab everything
// that it needs from the calling context, thus absolving the caller
// from being required to hold on to runnable indefinitely.
monitor_.wait();
}
void join() {
@ -92,35 +116,29 @@ public:
Thread::id_t getId() { return thread_.get() ? thread_->get_id() : std::thread::id(); }
boost::shared_ptr<Runnable> runnable() const { return Thread::runnable(); }
stdcxx::shared_ptr<Runnable> runnable() const { return Thread::runnable(); }
void runnable(boost::shared_ptr<Runnable> value) { Thread::runnable(value); }
void runnable(stdcxx::shared_ptr<Runnable> value) { Thread::runnable(value); }
};
void StdThread::threadMain(boost::shared_ptr<StdThread> thread) {
if (thread == NULL) {
return;
}
void StdThread::threadMain(stdcxx::shared_ptr<StdThread> thread) {
#if GOOGLE_PERFTOOLS_REGISTER_THREAD
ProfilerRegisterThread();
#endif
if (thread->state_ != starting) {
return;
}
thread->state_ = started;
thread->setState(started);
thread->runnable()->run();
if (thread->state_ != stopping && thread->state_ != stopped) {
thread->state_ = stopping;
if (thread->getState() != stopping && thread->getState() != stopped) {
thread->setState(stopping);
}
return;
}
StdThreadFactory::StdThreadFactory(bool detached) : ThreadFactory(detached) {
}
boost::shared_ptr<Thread> StdThreadFactory::newThread(boost::shared_ptr<Runnable> runnable) const {
boost::shared_ptr<StdThread> result = boost::shared_ptr<StdThread>(new StdThread(isDetached(), runnable));
stdcxx::shared_ptr<Thread> StdThreadFactory::newThread(stdcxx::shared_ptr<Runnable> runnable) const {
stdcxx::shared_ptr<StdThread> result = stdcxx::shared_ptr<StdThread>(new StdThread(isDetached(), runnable));
runnable->thread(result);
return result;
}

View file

@ -22,7 +22,7 @@
#include <thrift/concurrency/Thread.h>
#include <boost/shared_ptr.hpp>
#include <thrift/stdcxx.h>
namespace apache {
namespace thrift {
@ -38,8 +38,8 @@ class StdThreadFactory : public ThreadFactory {
public:
/**
* Std thread factory. All threads created by a factory are reference-counted
* via boost::shared_ptr and boost::weak_ptr. The factory guarantees that threads and
* the Runnable tasks they host will be properly cleaned up once the last strong reference
* via stdcxx::shared_ptr. The factory guarantees that threads and the Runnable tasks
* they host will be properly cleaned up once the last strong reference
* to both is given up.
*
* By default threads are not joinable.
@ -48,7 +48,7 @@ public:
StdThreadFactory(bool detached = true);
// From ThreadFactory;
boost::shared_ptr<Thread> newThread(boost::shared_ptr<Runnable> runnable) const;
stdcxx::shared_ptr<Thread> newThread(stdcxx::shared_ptr<Runnable> runnable) const;
// From ThreadFactory;
Thread::id_t getCurrentThreadId() const;

View file

@ -21,8 +21,7 @@
#define _THRIFT_CONCURRENCY_THREAD_H_ 1
#include <stdint.h>
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
#include <thrift/stdcxx.h>
#include <thrift/thrift-config.h>
@ -57,16 +56,16 @@ public:
* Gets the thread object that is hosting this runnable object - can return
* an empty boost::shared pointer if no references remain on that thread object
*/
virtual boost::shared_ptr<Thread> thread() { return thread_.lock(); }
virtual stdcxx::shared_ptr<Thread> thread() { return thread_.lock(); }
/**
* Sets the thread that is executing this object. This is only meant for
* use by concrete implementations of Thread.
*/
virtual void thread(boost::shared_ptr<Thread> value) { thread_ = value; }
virtual void thread(stdcxx::shared_ptr<Thread> value) { thread_ = value; }
private:
boost::weak_ptr<Thread> thread_;
stdcxx::weak_ptr<Thread> thread_;
};
/**
@ -122,13 +121,13 @@ public:
/**
* Gets the runnable object this thread is hosting
*/
virtual boost::shared_ptr<Runnable> runnable() const { return _runnable; }
virtual stdcxx::shared_ptr<Runnable> runnable() const { return _runnable; }
protected:
virtual void runnable(boost::shared_ptr<Runnable> value) { _runnable = value; }
virtual void runnable(stdcxx::shared_ptr<Runnable> value) { _runnable = value; }
private:
boost::shared_ptr<Runnable> _runnable;
stdcxx::shared_ptr<Runnable> _runnable;
};
/**
@ -155,7 +154,7 @@ public:
/**
* Create a new thread.
*/
virtual boost::shared_ptr<Thread> newThread(boost::shared_ptr<Runnable> runnable) const = 0;
virtual stdcxx::shared_ptr<Thread> newThread(stdcxx::shared_ptr<Runnable> runnable) const = 0;
/**
* Gets the current thread id or unknown_thread_id if the current thread is not a thrift thread

View file

@ -24,22 +24,18 @@
#include <thrift/concurrency/Monitor.h>
#include <thrift/concurrency/Util.h>
#include <boost/shared_ptr.hpp>
#include <thrift/stdcxx.h>
#include <stdexcept>
#include <deque>
#include <set>
#if defined(DEBUG)
#include <iostream>
#endif // defined(DEBUG)
namespace apache {
namespace thrift {
namespace concurrency {
using boost::shared_ptr;
using boost::dynamic_pointer_cast;
using stdcxx::shared_ptr;
using stdcxx::dynamic_pointer_cast;
/**
* ThreadManager class
@ -508,7 +504,7 @@ void ThreadManager::Impl::remove(shared_ptr<Runnable> task) {
}
}
boost::shared_ptr<Runnable> ThreadManager::Impl::removeNextPending() {
stdcxx::shared_ptr<Runnable> ThreadManager::Impl::removeNextPending() {
Guard g(mutex_);
if (state_ != ThreadManager::STARTED) {
throw IllegalStateException(
@ -517,7 +513,7 @@ boost::shared_ptr<Runnable> ThreadManager::Impl::removeNextPending() {
}
if (tasks_.empty()) {
return boost::shared_ptr<Runnable>();
return stdcxx::shared_ptr<Runnable>();
}
shared_ptr<ThreadManager::Task> task = tasks_.front();

View file

@ -20,10 +20,9 @@
#ifndef _THRIFT_CONCURRENCY_THREADMANAGER_H_
#define _THRIFT_CONCURRENCY_THREADMANAGER_H_ 1
#include <boost/shared_ptr.hpp>
#include <thrift/cxxfunctional.h>
#include <sys/types.h>
#include <thrift/concurrency/Thread.h>
#include <thrift/stdcxx.h>
namespace apache {
namespace thrift {
@ -59,7 +58,7 @@ protected:
ThreadManager() {}
public:
typedef apache::thrift::stdcxx::function<void(boost::shared_ptr<Runnable>)> ExpireCallback;
typedef apache::thrift::stdcxx::function<void(stdcxx::shared_ptr<Runnable>)> ExpireCallback;
virtual ~ThreadManager() {}
@ -88,14 +87,14 @@ public:
/**
* \returns the current thread factory
*/
virtual boost::shared_ptr<ThreadFactory> threadFactory() const = 0;
virtual stdcxx::shared_ptr<ThreadFactory> threadFactory() const = 0;
/**
* Set the thread factory.
* \throws InvalidArgumentException if the new thread factory has a different
* detached disposition than the one replacing it
*/
virtual void threadFactory(boost::shared_ptr<ThreadFactory> value) = 0;
virtual void threadFactory(stdcxx::shared_ptr<ThreadFactory> value) = 0;
/**
* Adds worker thread(s).
@ -162,21 +161,21 @@ public:
*
* @throws TooManyPendingTasksException Pending task count exceeds max pending task count
*/
virtual void add(boost::shared_ptr<Runnable> task,
virtual void add(stdcxx::shared_ptr<Runnable> task,
int64_t timeout = 0LL,
int64_t expiration = 0LL) = 0;
/**
* Removes a pending task
*/
virtual void remove(boost::shared_ptr<Runnable> task) = 0;
virtual void remove(stdcxx::shared_ptr<Runnable> task) = 0;
/**
* Remove the next pending task which would be run.
*
* @return the task removed.
*/
virtual boost::shared_ptr<Runnable> removeNextPending() = 0;
virtual stdcxx::shared_ptr<Runnable> removeNextPending() = 0;
/**
* Remove tasks from front of task queue that have expired.
@ -191,14 +190,14 @@ public:
*/
virtual void setExpireCallback(ExpireCallback expireCallback) = 0;
static boost::shared_ptr<ThreadManager> newThreadManager();
static stdcxx::shared_ptr<ThreadManager> newThreadManager();
/**
* Creates a simple thread manager the uses count number of worker threads and has
* a pendingTaskCountMax maximum pending tasks. The default, 0, specified no limit
* on pending tasks
*/
static boost::shared_ptr<ThreadManager> newSimpleThreadManager(size_t count = 4,
static stdcxx::shared_ptr<ThreadManager> newSimpleThreadManager(size_t count = 4,
size_t pendingTaskCountMax = 0);
class Task;

View file

@ -29,7 +29,8 @@ namespace apache {
namespace thrift {
namespace concurrency {
using boost::shared_ptr;
using stdcxx::shared_ptr;
using stdcxx::weak_ptr;
/**
* TimerManager class
@ -52,6 +53,10 @@ public:
}
}
bool operator==(const shared_ptr<Runnable> & runnable) const { return runnable_ == runnable; }
task_iterator it_;
private:
shared_ptr<Runnable> runnable_;
friend class TimerManager::Dispatcher;
@ -106,6 +111,7 @@ public:
for (task_iterator ix = manager_->taskMap_.begin(); ix != expiredTaskEnd; ix++) {
shared_ptr<TimerManager::Task> task = ix->second;
expiredTasks.insert(task);
task->it_ = manager_->taskMap_.end();
if (task->state_ == TimerManager::Task::WAITING) {
task->state_ = TimerManager::Task::EXECUTING;
}
@ -233,7 +239,7 @@ size_t TimerManager::taskCount() const {
return taskCount_;
}
void TimerManager::add(shared_ptr<Runnable> task, int64_t timeout) {
TimerManager::Timer TimerManager::add(shared_ptr<Runnable> task, int64_t timeout) {
int64_t now = Util::currentTime();
timeout += now;
@ -248,9 +254,9 @@ void TimerManager::add(shared_ptr<Runnable> task, int64_t timeout) {
// because the new task might insert at the front.
bool notifyRequired = (taskCount_ == 0) ? true : timeout < taskMap_.begin()->first;
shared_ptr<Task> timer(new Task(task));
taskCount_++;
taskMap_.insert(
std::pair<int64_t, shared_ptr<Task> >(timeout, shared_ptr<Task>(new Task(task))));
timer->it_ = taskMap_.insert(std::pair<int64_t, shared_ptr<Task> >(timeout, timer));
// If the task map was empty, or if we have an expiration that is earlier
// than any previously seen, kick the dispatcher so it can update its
@ -258,10 +264,13 @@ void TimerManager::add(shared_ptr<Runnable> task, int64_t timeout) {
if (notifyRequired) {
monitor_.notify();
}
return timer;
}
}
void TimerManager::add(shared_ptr<Runnable> task, const struct THRIFT_TIMESPEC& value) {
TimerManager::Timer TimerManager::add(shared_ptr<Runnable> task,
const struct THRIFT_TIMESPEC& value) {
int64_t expiration;
Util::toMilliseconds(expiration, value);
@ -272,10 +281,11 @@ void TimerManager::add(shared_ptr<Runnable> task, const struct THRIFT_TIMESPEC&
throw InvalidArgumentException();
}
add(task, expiration - now);
return add(task, expiration - now);
}
void TimerManager::add(shared_ptr<Runnable> task, const struct timeval& value) {
TimerManager::Timer TimerManager::add(shared_ptr<Runnable> task,
const struct timeval& value) {
int64_t expiration;
Util::toMilliseconds(expiration, value);
@ -286,15 +296,47 @@ void TimerManager::add(shared_ptr<Runnable> task, const struct timeval& value) {
throw InvalidArgumentException();
}
add(task, expiration - now);
return add(task, expiration - now);
}
void TimerManager::remove(shared_ptr<Runnable> task) {
(void)task;
Synchronized s(monitor_);
if (state_ != TimerManager::STARTED) {
throw IllegalStateException();
}
bool found = false;
for (task_iterator ix = taskMap_.begin(); ix != taskMap_.end();) {
if (*ix->second == task) {
found = true;
taskCount_--;
taskMap_.erase(ix++);
} else {
++ix;
}
}
if (!found) {
throw NoSuchTaskException();
}
}
void TimerManager::remove(Timer handle) {
Synchronized s(monitor_);
if (state_ != TimerManager::STARTED) {
throw IllegalStateException();
}
shared_ptr<Task> task = handle.lock();
if (!task) {
throw NoSuchTaskException();
}
if (task->it_ == taskMap_.end()) {
// Task is being executed
throw UncancellableTaskException();
}
taskMap_.erase(task->it_);
taskCount_--;
}
TimerManager::STATE TimerManager::state() const {

View file

@ -24,7 +24,7 @@
#include <thrift/concurrency/Monitor.h>
#include <thrift/concurrency/Thread.h>
#include <boost/shared_ptr.hpp>
#include <thrift/stdcxx.h>
#include <map>
#include <time.h>
@ -42,13 +42,16 @@ namespace concurrency {
class TimerManager {
public:
class Task;
typedef stdcxx::weak_ptr<Task> Timer;
TimerManager();
virtual ~TimerManager();
virtual boost::shared_ptr<const ThreadFactory> threadFactory() const;
virtual stdcxx::shared_ptr<const ThreadFactory> threadFactory() const;
virtual void threadFactory(boost::shared_ptr<const ThreadFactory> value);
virtual void threadFactory(stdcxx::shared_ptr<const ThreadFactory> value);
/**
* Starts the timer manager service
@ -69,28 +72,33 @@ public:
*
* @param task The task to execute
* @param timeout Time in milliseconds to delay before executing task
* @return Handle of the timer, which can be used to remove the timer.
*/
virtual void add(boost::shared_ptr<Runnable> task, int64_t timeout);
virtual Timer add(stdcxx::shared_ptr<Runnable> task, int64_t timeout);
/**
* Adds a task to be executed at some time in the future by a worker thread.
*
* @param task The task to execute
* @param timeout Absolute time in the future to execute task.
* @return Handle of the timer, which can be used to remove the timer.
*/
virtual void add(boost::shared_ptr<Runnable> task, const struct THRIFT_TIMESPEC& timeout);
virtual Timer add(stdcxx::shared_ptr<Runnable> task, const struct THRIFT_TIMESPEC& timeout);
/**
* Adds a task to be executed at some time in the future by a worker thread.
*
* @param task The task to execute
* @param timeout Absolute time in the future to execute task.
* @return Handle of the timer, which can be used to remove the timer.
*/
virtual void add(boost::shared_ptr<Runnable> task, const struct timeval& timeout);
virtual Timer add(stdcxx::shared_ptr<Runnable> task, const struct timeval& timeout);
/**
* Removes a pending task
*
* @param task The task to remove. All timers which execute this task will
* be removed.
* @throws NoSuchTaskException Specified task doesn't exist. It was either
* processed already or this call was made for a
* task that was never added to this timer
@ -98,25 +106,38 @@ public:
* @throws UncancellableTaskException Specified task is already being
* executed or has completed execution.
*/
virtual void remove(boost::shared_ptr<Runnable> task);
virtual void remove(stdcxx::shared_ptr<Runnable> task);
/**
* Removes a single pending task
*
* @param timer The timer to remove. The timer is returned when calling the
* add() method.
* @throws NoSuchTaskException Specified task doesn't exist. It was either
* processed already or this call was made for a
* task that was never added to this timer
*
* @throws UncancellableTaskException Specified task is already being
* executed or has completed execution.
*/
virtual void remove(Timer timer);
enum STATE { UNINITIALIZED, STARTING, STARTED, STOPPING, STOPPED };
virtual STATE state() const;
private:
boost::shared_ptr<const ThreadFactory> threadFactory_;
class Task;
stdcxx::shared_ptr<const ThreadFactory> threadFactory_;
friend class Task;
std::multimap<int64_t, boost::shared_ptr<Task> > taskMap_;
std::multimap<int64_t, stdcxx::shared_ptr<Task> > taskMap_;
size_t taskCount_;
Monitor monitor_;
STATE state_;
class Dispatcher;
friend class Dispatcher;
boost::shared_ptr<Dispatcher> dispatcher_;
boost::shared_ptr<Thread> dispatcherThread_;
typedef std::multimap<int64_t, boost::shared_ptr<TimerManager::Task> >::iterator task_iterator;
stdcxx::shared_ptr<Dispatcher> dispatcher_;
stdcxx::shared_ptr<Thread> dispatcherThread_;
typedef std::multimap<int64_t, stdcxx::shared_ptr<TimerManager::Task> >::iterator task_iterator;
typedef std::pair<task_iterator, task_iterator> task_range;
};
}

View file

@ -1,132 +0,0 @@
/*
* 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_CXXFUNCTIONAL_H_
#define _THRIFT_CXXFUNCTIONAL_H_ 1
// clang-format off
/**
* Loads <functional> from the 'right' location, depending
* on compiler and whether or not it's using C++03 with TR1
* or C++11.
*/
/*
* MSVC 10 and 11 have the <functional> stuff at <functional>.
* In MSVC 10 all of the implementations live in std::tr1.
* In MSVC 11 all of the implementations live in std, with aliases
* in std::tr1 to point to the ones in std.
*/
#if defined(_WIN32) && !defined(__MINGW32__)
#define _THRIFT_USING_MICROSOFT_STDLIB 1
#endif
#ifdef __clang__
/* Clang has two options, depending on standard library:
* - no -stdlib or -stdlib=libstdc++ set; uses GNU libstdc++.
* <tr1/functional>
* - -stdlib=libc++; uses LLVM libc++.
* <functional>, no 'std::tr1'.
*
* The compiler itself doesn't define anything differently
* depending on the value of -stdlib, but the library headers
* will set different preprocessor options. In order to check,
* though, we have to pull in some library header.
*/
#include <utility>
/* With LLVM libc++, utility pulls in __config, which sets
_LIBCPP_VERSION. */
#if defined(_LIBCPP_VERSION)
#define _THRIFT_USING_CLANG_LIBCXX 1
/* With GNU libstdc++, utility pulls in bits/c++config.h,
which sets __GLIBCXX__. */
#elif defined(__GLIBCXX__)
#define _THRIFT_USING_GNU_LIBSTDCXX 1
/* No idea. */
#else
#error Unable to detect which C++ standard library is in use.
#endif
#elif __GNUC__
#define _THRIFT_USING_GNU_LIBSTDCXX 1
#endif
#if _THRIFT_USING_MICROSOFT_STDLIB
#include <functional>
namespace apache { namespace thrift { namespace stdcxx {
using ::std::tr1::function;
using ::std::tr1::bind;
namespace placeholders {
using ::std::tr1::placeholders::_1;
using ::std::tr1::placeholders::_2;
using ::std::tr1::placeholders::_3;
using ::std::tr1::placeholders::_4;
using ::std::tr1::placeholders::_5;
using ::std::tr1::placeholders::_6;
} // apache::thrift::stdcxx::placeholders
}}} // apache::thrift::stdcxx
#elif _THRIFT_USING_CLANG_LIBCXX
#include <functional>
namespace apache { namespace thrift { namespace stdcxx {
using ::std::function;
using ::std::bind;
namespace placeholders {
using ::std::placeholders::_1;
using ::std::placeholders::_2;
using ::std::placeholders::_3;
using ::std::placeholders::_4;
using ::std::placeholders::_5;
using ::std::placeholders::_6;
} // apache::thrift::stdcxx::placeholders
}}} // apache::thrift::stdcxx
#elif _THRIFT_USING_GNU_LIBSTDCXX
#ifdef USE_BOOST_THREAD
#include <boost/tr1/functional.hpp>
#else
#include <tr1/functional>
#endif
namespace apache { namespace thrift { namespace stdcxx {
using ::std::tr1::function;
using ::std::tr1::bind;
namespace placeholders {
using ::std::tr1::placeholders::_1;
using ::std::tr1::placeholders::_2;
using ::std::tr1::placeholders::_3;
using ::std::tr1::placeholders::_4;
using ::std::tr1::placeholders::_5;
using ::std::tr1::placeholders::_6;
} // apache::thrift::stdcxx::placeholders
}}} // apache::thrift::stdcxx
#endif
// Alias for thrift c++ compatibility namespace
namespace tcxx = apache::thrift::stdcxx;
#endif // #ifndef _THRIFT_CXXFUNCTIONAL_H_

View file

@ -34,26 +34,26 @@ PeekProcessor::PeekProcessor() {
PeekProcessor::~PeekProcessor() {
}
void PeekProcessor::initialize(boost::shared_ptr<TProcessor> actualProcessor,
boost::shared_ptr<TProtocolFactory> protocolFactory,
boost::shared_ptr<TPipedTransportFactory> transportFactory) {
void PeekProcessor::initialize(stdcxx::shared_ptr<TProcessor> actualProcessor,
stdcxx::shared_ptr<TProtocolFactory> protocolFactory,
stdcxx::shared_ptr<TPipedTransportFactory> transportFactory) {
actualProcessor_ = actualProcessor;
pipedProtocol_ = protocolFactory->getProtocol(targetTransport_);
transportFactory_ = transportFactory;
transportFactory_->initializeTargetTransport(targetTransport_);
}
boost::shared_ptr<TTransport> PeekProcessor::getPipedTransport(boost::shared_ptr<TTransport> in) {
stdcxx::shared_ptr<TTransport> PeekProcessor::getPipedTransport(stdcxx::shared_ptr<TTransport> in) {
return transportFactory_->getTransport(in);
}
void PeekProcessor::setTargetTransport(boost::shared_ptr<TTransport> targetTransport) {
void PeekProcessor::setTargetTransport(stdcxx::shared_ptr<TTransport> targetTransport) {
targetTransport_ = targetTransport;
if (boost::dynamic_pointer_cast<TMemoryBuffer>(targetTransport_)) {
memoryBuffer_ = boost::dynamic_pointer_cast<TMemoryBuffer>(targetTransport);
} else if (boost::dynamic_pointer_cast<TPipedTransport>(targetTransport_)) {
memoryBuffer_ = boost::dynamic_pointer_cast<TMemoryBuffer>(
boost::dynamic_pointer_cast<TPipedTransport>(targetTransport_)->getTargetTransport());
if (stdcxx::dynamic_pointer_cast<TMemoryBuffer>(targetTransport_)) {
memoryBuffer_ = stdcxx::dynamic_pointer_cast<TMemoryBuffer>(targetTransport);
} else if (stdcxx::dynamic_pointer_cast<TPipedTransport>(targetTransport_)) {
memoryBuffer_ = stdcxx::dynamic_pointer_cast<TMemoryBuffer>(
stdcxx::dynamic_pointer_cast<TPipedTransport>(targetTransport_)->getTargetTransport());
}
if (!memoryBuffer_) {
@ -62,8 +62,8 @@ void PeekProcessor::setTargetTransport(boost::shared_ptr<TTransport> targetTrans
}
}
bool PeekProcessor::process(boost::shared_ptr<TProtocol> in,
boost::shared_ptr<TProtocol> out,
bool PeekProcessor::process(stdcxx::shared_ptr<TProtocol> in,
stdcxx::shared_ptr<TProtocol> out,
void* connectionContext) {
std::string fname;
@ -120,7 +120,7 @@ void PeekProcessor::peekBuffer(uint8_t* buffer, uint32_t size) {
(void)size;
}
void PeekProcessor::peek(boost::shared_ptr<TProtocol> in, TType ftype, int16_t fid) {
void PeekProcessor::peek(stdcxx::shared_ptr<TProtocol> in, TType ftype, int16_t fid) {
(void)fid;
in->skip(ftype);
}

Some files were not shown because too many files have changed in this diff Show more