diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:45:59 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:45:59 +0000 |
commit | 19fcec84d8d7d21e796c7624e521b60d28ee21ed (patch) | |
tree | 42d26aa27d1e3f7c0b8bd3fd14e7d7082f5008dc /src/jaegertracing/thrift/lib/c_glib | |
parent | Initial commit. (diff) | |
download | ceph-upstream.tar.xz ceph-upstream.zip |
Adding upstream version 16.2.11+ds.upstream/16.2.11+dsupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
85 files changed, 19794 insertions, 0 deletions
diff --git a/src/jaegertracing/thrift/lib/c_glib/CMakeLists.txt b/src/jaegertracing/thrift/lib/c_glib/CMakeLists.txt new file mode 100644 index 000000000..3e4a154b8 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/CMakeLists.txt @@ -0,0 +1,87 @@ +# +# 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. +# + +# Find required packages +find_package(GLIB REQUIRED COMPONENTS gobject) +include_directories(${GLIB_INCLUDE_DIRS}) + +include_directories(src) + +# SYSLIBS contains libraries that need to be linked to all lib targets +set(SYSLIBS ${GLIB_LIBRARIES} ${GLIB_GOBJECT_LIBRARIES}) + +# Create the thrift C glib library +set(thrift_c_glib_SOURCES + src/thrift/c_glib/thrift.c + src/thrift/c_glib/thrift_struct.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_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_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 + src/thrift/c_glib/transport/thrift_transport.c + src/thrift/c_glib/transport/thrift_transport_factory.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_server_transport.c + src/thrift/c_glib/transport/thrift_server_socket.c + src/thrift/c_glib/transport/thrift_buffered_transport.c + src/thrift/c_glib/transport/thrift_fd_transport.c + src/thrift/c_glib/transport/thrift_framed_transport.c + src/thrift/c_glib/transport/thrift_memory_buffer.c + src/thrift/c_glib/server/thrift_server.c + 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 thrift_c_glib_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) + +ADD_LIBRARY_THRIFT(thrift_c_glib ${thrift_c_glib_SOURCES}) +TARGET_LINK_LIBRARIES_THRIFT(thrift_c_glib ${SYSLIBS}) + +# Install the headers +install(DIRECTORY "src/thrift" DESTINATION "${INCLUDE_INSTALL_DIR}" + FILES_MATCHING PATTERN "*.h") +# Copy config.h file +install(DIRECTORY "${CMAKE_BINARY_DIR}/thrift" DESTINATION "${INCLUDE_INSTALL_DIR}" + FILES_MATCHING PATTERN "*.h") + +if(BUILD_TESTING) + add_subdirectory(test) +endif() diff --git a/src/jaegertracing/thrift/lib/c_glib/Makefile.am b/src/jaegertracing/thrift/lib/c_glib/Makefile.am new file mode 100755 index 000000000..fd7f93d76 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/Makefile.am @@ -0,0 +1,118 @@ +# +# 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. +# +AUTOMAKE_OPTIONS = serial-tests nostdinc +SUBDIRS = . test + +pkgconfigdir = $(libdir)/pkgconfig + +lib_LTLIBRARIES = libthrift_c_glib.la +pkgconfig_DATA = thrift_c_glib.pc + +AM_CPPFLAGS = -Isrc -I src/thrift/c_glib +AM_CFLAGS = -Wall -Wextra -pedantic + +# Define the source files for the module + +libthrift_c_glib_la_SOURCES = src/thrift/c_glib/thrift.c \ + src/thrift/c_glib/thrift_struct.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 \ + src/thrift/c_glib/transport/thrift_transport.c \ + src/thrift/c_glib/transport/thrift_transport_factory.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 \ + src/thrift/c_glib/transport/thrift_fd_transport.c \ + src/thrift/c_glib/transport/thrift_framed_transport.c \ + src/thrift/c_glib/transport/thrift_memory_buffer.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) $(GOBJECT_CFLAGS) $(OPENSSL_INCLUDES) -I$(top_builddir)/lib/c_glib/src/thrift +libthrift_c_glib_la_LDFLAGS = $(AM_LDFLAGS) $(GLIB_LIBS) $(GOBJECT_LIBS) $(OPENSSL_LDFLAGS) $(OPENSSL_LIBS) + +include_thriftdir = $(includedir)/thrift/c_glib +include_thrift_HEADERS = \ + $(top_builddir)/config.h \ + src/thrift/c_glib/thrift.h \ + src/thrift/c_glib/thrift_application_exception.h \ + src/thrift/c_glib/thrift_struct.h + +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_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 \ + src/thrift/c_glib/transport/thrift_fd_transport.h \ + src/thrift/c_glib/transport/thrift_framed_transport.h \ + src/thrift/c_glib/transport/thrift_memory_buffer.h \ + 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 \ + src/thrift/c_glib/transport/thrift_framed_transport_factory.h + +include_serverdir = $(include_thriftdir)/server +include_server_HEADERS = src/thrift/c_glib/server/thrift_server.h \ + src/thrift/c_glib/server/thrift_simple_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_multiplexed_processor.h + + +EXTRA_DIST = \ + CMakeLists.txt \ + coding_standards.md \ + README.md \ + test/glib.suppress \ + thrift_c_glib.pc.in + +CLEANFILES = \ + *.gcno \ + *.gcda diff --git a/src/jaegertracing/thrift/lib/c_glib/README.md b/src/jaegertracing/thrift/lib/c_glib/README.md new file mode 100644 index 000000000..dd84f3d35 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/README.md @@ -0,0 +1,49 @@ +Thrift C Software 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 C +=================== + +The Thrift C libraries are built using the GNU tools. Follow the instructions +in the top-level README in order to generate the Makefiles. + +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. diff --git a/src/jaegertracing/thrift/lib/c_glib/coding_standards.md b/src/jaegertracing/thrift/lib/c_glib/coding_standards.md new file mode 100644 index 000000000..24b3a0056 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/coding_standards.md @@ -0,0 +1,5 @@ +## C Glib Coding Standards + +Please follow: + * [Thrift General Coding Standards](/doc/coding_standards.md) + * [GNOME C Coding Style](https://help.gnome.org/users/programming-guidelines/stable/c-coding-style.html.en) diff --git a/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/processor/thrift_dispatch_processor.c b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/processor/thrift_dispatch_processor.c new file mode 100644 index 000000000..57d621751 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/processor/thrift_dispatch_processor.c @@ -0,0 +1,143 @@ +/* + * 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 <thrift/c_glib/thrift.h> +#include <thrift/c_glib/thrift_application_exception.h> +#include <thrift/c_glib/processor/thrift_dispatch_processor.h> + +G_DEFINE_ABSTRACT_TYPE (ThriftDispatchProcessor, + thrift_dispatch_processor, + THRIFT_TYPE_PROCESSOR) + +gboolean +thrift_dispatch_processor_process (ThriftProcessor *processor, + ThriftProtocol *in, + ThriftProtocol *out, + GError **error) +{ + gchar *fname; + ThriftMessageType mtype; + gint32 seqid; + ThriftDispatchProcessor *dispatch_processor = + THRIFT_DISPATCH_PROCESSOR (processor); + + /* Read the start of the message, which we expect to be a method call */ + if (thrift_protocol_read_message_begin (in, + &fname, + &mtype, + &seqid, + error) < 0) { + g_warning ("error reading start of message: %s", + (error != NULL) ? (*error)->message : "(null)"); + return FALSE; + } + else if (mtype != T_CALL && mtype != T_ONEWAY) { + g_warning ("received invalid message type %d from client", mtype); + return FALSE; + } + + /* Dispatch the method call */ + return THRIFT_DISPATCH_PROCESSOR_GET_CLASS (dispatch_processor) + ->dispatch_call (dispatch_processor, + in, + out, + fname, + seqid, + error); +} + +static gboolean +thrift_dispatch_processor_real_dispatch_call (ThriftDispatchProcessor *self, + ThriftProtocol *in, + ThriftProtocol *out, + gchar *fname, + gint32 seqid, + GError **error) +{ + ThriftTransport *transport; + ThriftApplicationException *xception; + gchar *message; + gint32 result; + gboolean dispatch_result = FALSE; + + THRIFT_UNUSED_VAR (self); + + /* By default, return an application exception to the client indicating the + method name is not recognized. */ + + if ((thrift_protocol_skip (in, T_STRUCT, error) < 0) || + (thrift_protocol_read_message_end (in, error) < 0)) + return FALSE; + + g_object_get (in, "transport", &transport, NULL); + result = thrift_transport_read_end (transport, error); + g_object_unref (transport); + if (result < 0) + return FALSE; + + if (thrift_protocol_write_message_begin (out, + fname, + T_EXCEPTION, + seqid, + error) < 0) + return FALSE; + message = g_strconcat ("Invalid method name: '", fname, "'", NULL); + g_free (fname); + xception = + g_object_new (THRIFT_TYPE_APPLICATION_EXCEPTION, + "type", THRIFT_APPLICATION_EXCEPTION_ERROR_UNKNOWN_METHOD, + "message", message, + NULL); + g_free (message); + 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 FALSE; + + g_object_get (out, "transport", &transport, NULL); + dispatch_result = + ((thrift_transport_write_end (transport, error) >= 0) && + (thrift_transport_flush (transport, error) >= 0)); + g_object_unref (transport); + + return dispatch_result; +} + +static void +thrift_dispatch_processor_init (ThriftDispatchProcessor *self) +{ + THRIFT_UNUSED_VAR (self); +} + +static void +thrift_dispatch_processor_class_init (ThriftDispatchProcessorClass *klass) +{ + ThriftProcessorClass *processor_class = + THRIFT_PROCESSOR_CLASS (klass); + + /* Implement ThriftProcessor's process method */ + processor_class->process = thrift_dispatch_processor_process; + + /* Provide a default implement for dispatch_call, which returns an exception + to the client indicating the method name was not recognized */ + klass->dispatch_call = thrift_dispatch_processor_real_dispatch_call; +} diff --git a/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/processor/thrift_dispatch_processor.h b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/processor/thrift_dispatch_processor.h new file mode 100644 index 000000000..5afb85ec8 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/processor/thrift_dispatch_processor.h @@ -0,0 +1,95 @@ +/* + * 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_DISPATCH_PROCESSOR_H +#define _THRIFT_DISPATCH_PROCESSOR_H + +#include <glib-object.h> + +#include <thrift/c_glib/processor/thrift_processor.h> + +G_BEGIN_DECLS + +/*! \file thrift_dispatch_processor.h + * \brief Parses a method-call message header and invokes a function + * to dispatch the call by function name. + * + * ThriftDispatchProcessor is an abstract helper class that parses the + * header of a method-call message and invokes a member function, + * dispatch_call, with the method's name. + * + * Subclasses must implement dispatch_call to dispatch the method call + * to the implementing function. + */ + +/* Type macros */ +#define THRIFT_TYPE_DISPATCH_PROCESSOR (thrift_dispatch_processor_get_type ()) +#define THRIFT_DISPATCH_PROCESSOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THRIFT_TYPE_DISPATCH_PROCESSOR, ThriftDispatchProcessor)) +#define THRIFT_IS_DISPATCH_PROCESSOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THRIFT_TYPE_DISPATCH_PROCESSOR)) +#define THRIFT_DISPATCH_PROCESSOR_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), THRIFT_TYPE_DISPATCH_PROCESSOR, ThriftDispatchProcessorClass)) +#define THRIFT_IS_DISPATCH_PROCESSOR_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), THRIFT_TYPE_DISPATCH_PROCESSOR)) +#define THRIFT_DISPATCH_PROCESSOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THRIFT_TYPE_DISPATCH_PROCESSOR, ThriftDispatchProcessorClass)) + +/*! + * Thrift Dispatch Processor object + */ +struct _ThriftDispatchProcessor +{ + ThriftProcessor parent; +}; +typedef struct _ThriftDispatchProcessor ThriftDispatchProcessor; + +/*! + * Thrift Dispatch Processor class + */ +struct _ThriftDispatchProcessorClass +{ + ThriftProcessorClass parent; + + /* public */ + gboolean (*process) (ThriftProcessor *processor, + ThriftProtocol *in, + ThriftProtocol *out, + GError **error); + + /* protected */ + gboolean (*dispatch_call) (ThriftDispatchProcessor *self, + ThriftProtocol *in, + ThriftProtocol *out, + gchar *fname, + gint32 seqid, + GError **error); +}; +typedef struct _ThriftDispatchProcessorClass ThriftDispatchProcessorClass; + +/* Used by THRIFT_TYPE_DISPATCH_PROCESSOR */ +GType thrift_dispatch_processor_get_type (void); + +/*! + * Processes a request. + * \public \memberof ThriftDispatchProcessorClass + */ +gboolean thrift_dispatch_processor_process (ThriftProcessor *processor, + ThriftProtocol *in, + ThriftProtocol *out, + GError **error); + +G_END_DECLS + +#endif /* _THRIFT_DISPATCH_PROCESSOR_H */ diff --git a/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/processor/thrift_multiplexed_processor.c b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/processor/thrift_multiplexed_processor.c new file mode 100644 index 000000000..68a0f4d46 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/processor/thrift_multiplexed_processor.c @@ -0,0 +1,346 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#include <string.h> +#include <stdio.h> + +#include <thrift/c_glib/thrift.h> +#include <thrift/c_glib/processor/thrift_processor.h> +#include <thrift/c_glib/processor/thrift_multiplexed_processor.h> +#include <thrift/c_glib/protocol/thrift_multiplexed_protocol.h> +#include <thrift/c_glib/protocol/thrift_stored_message_protocol.h> +#include <thrift/c_glib/thrift_application_exception.h> + +G_DEFINE_TYPE(ThriftMultiplexedProcessor, thrift_multiplexed_processor, THRIFT_TYPE_PROCESSOR) + + +enum +{ + PROP_THRIFT_MULTIPLEXED_PROCESSOR_DEFAULT_SERVICE_NAME = 1, + PROP_THRIFT_MULTIPLEXED_PROCESSOR_END +}; + +static GParamSpec *thrift_multiplexed_processor_obj_properties[PROP_THRIFT_MULTIPLEXED_PROCESSOR_END] = { NULL, }; + + +static gboolean +thrift_multiplexed_processor_register_processor_impl(ThriftProcessor *processor, const gchar * multiplexed_processor_name, ThriftProcessor * multiplexed_processor , GError **error) +{ + ThriftMultiplexedProcessor *self = THRIFT_MULTIPLEXED_PROCESSOR(processor); + g_hash_table_replace(self->multiplexed_services, + g_strdup(multiplexed_processor_name), + g_object_ref (multiplexed_processor)); + + /* Make first registered become default */ + if(!self->default_processor_name){ + self->default_processor_name = g_strdup(multiplexed_processor_name); + } + return TRUE; +} + + +static gboolean +thrift_multiplexed_processor_process_impl (ThriftProcessor *processor, ThriftProtocol *in, + ThriftProtocol *out, GError **error) +{ + gboolean retval = FALSE; + gboolean token_error = FALSE; + ThriftApplicationException *xception; + ThriftStoredMessageProtocol *stored_message_protocol = NULL; + ThriftMessageType message_type; + ThriftMultiplexedProcessor *self = THRIFT_MULTIPLEXED_PROCESSOR(processor); + ThriftProcessor *multiplexed_processor = NULL; + ThriftTransport *transport; + char *token=NULL; + int token_index=0; + char *state=NULL; + gchar *fname=NULL; + gint32 seqid, result; + + /* FIXME It seems that previous processor is not managing error correctly */ + if(*error!=NULL) { + g_debug ("thrift_multiplexed_processor: last error not removed: %s", + *error != NULL ? (*error)->message : "(null)"); + g_clear_error (error); + } + + + THRIFT_PROTOCOL_GET_CLASS(in)->read_message_begin(in, &fname, &message_type, &seqid, error); + + if(!(message_type == T_CALL || message_type == T_ONEWAY)) { + g_set_error (error, + THRIFT_MULTIPLEXED_PROCESSOR_ERROR, + THRIFT_MULTIPLEXED_PROCESSOR_ERROR_MESSAGE_TYPE, + "message type invalid for this processor"); + }else{ + /* Split by the token */ + for (token = strtok_r(fname, THRIFT_MULTIPLEXED_PROTOCOL_DEFAULT_SEPARATOR, &state), + token_index=0; + token != NULL && !token_error; + token = strtok_r(NULL, THRIFT_MULTIPLEXED_PROTOCOL_DEFAULT_SEPARATOR, &state), + token_index++) + { + switch(token_index){ + case 0: + /* It should be the service name */ + multiplexed_processor = g_hash_table_lookup(self->multiplexed_services, token); + if(multiplexed_processor==NULL){ + token_error=TRUE; + } + break; + case 1: + /* It should be the function name */ + stored_message_protocol = g_object_new (THRIFT_TYPE_STORED_MESSAGE_PROTOCOL, + "protocol", in, + "name", token, + "type", message_type, + "seqid", seqid, + NULL); + break; + default: + g_set_error (error, + THRIFT_MULTIPLEXED_PROCESSOR_ERROR, + THRIFT_MULTIPLEXED_PROCESSOR_ERROR_MESSAGE_WRONGLY_MULTIPLEXED, + "the message has more tokens than expected!"); + token_error=TRUE; + break; + } + } + /* Set default */ + if(!stored_message_protocol && + !multiplexed_processor && + token_index==1 && self->default_processor_name){ + /* It should be the service name */ + multiplexed_processor = g_hash_table_lookup(self->multiplexed_services, self->default_processor_name); + if(multiplexed_processor==NULL){ + g_set_error (error, + THRIFT_MULTIPLEXED_PROCESSOR_ERROR, + THRIFT_MULTIPLEXED_PROCESSOR_ERROR_SERVICE_UNAVAILABLE, + "service %s not available on this processor", + self->default_processor_name); + }else{ + /* Set the message name to the original name */ + stored_message_protocol = g_object_new (THRIFT_TYPE_STORED_MESSAGE_PROTOCOL, + "protocol", in, + "name", fname, + "type", message_type, + "seqid", seqid, + NULL); + } + + } + + if(stored_message_protocol!=NULL && multiplexed_processor!=NULL){ + retval = THRIFT_PROCESSOR_GET_CLASS (multiplexed_processor)->process (multiplexed_processor, (ThriftProtocol *) stored_message_protocol, out, error) ; + }else{ + if(!error) + g_set_error (error, + THRIFT_MULTIPLEXED_PROCESSOR_ERROR, + THRIFT_MULTIPLEXED_PROCESSOR_ERROR_SERVICE_UNAVAILABLE, + "service %s is not multiplexed in this processor", + fname); + } + + + } + + if(!retval){ + /* By default, return an application exception to the client indicating the + method name is not recognized. */ + /* Copied from dispach processor */ + + if ((thrift_protocol_skip (in, T_STRUCT, error) < 0) || + (thrift_protocol_read_message_end (in, error) < 0)) + return retval; + + g_object_get (in, "transport", &transport, NULL); + result = thrift_transport_read_end (transport, error); + g_object_unref (transport); + if (result < 0) { + /* We must free fname */ + g_free(fname); + return retval; + } + + if (thrift_protocol_write_message_begin (out, + fname, + T_EXCEPTION, + seqid, + error) < 0){ + /* We must free fname */ + g_free(fname); + + return retval; + } + + + xception = + g_object_new (THRIFT_TYPE_APPLICATION_EXCEPTION, + "type", THRIFT_APPLICATION_EXCEPTION_ERROR_UNKNOWN_METHOD, + "message", (*error)->message, + NULL); + result = thrift_struct_write (THRIFT_STRUCT (xception), + out, + error); + g_object_unref (xception); + if ((result < 0) || + (thrift_protocol_write_message_end (out, error) < 0)) + return retval; + + g_object_get (out, "transport", &transport, NULL); + retval = + ((thrift_transport_write_end (transport, error) >= 0) && + (thrift_transport_flush (transport, error) >= 0)); + g_object_unref (transport); + }else{ + /* The protocol now has a copy we can free it */ + g_free(fname); + + } + + /* + FIXME This makes everything fail, I don't know why. + if(stored_message_protocol!=NULL){ + // After its use we must free it + g_object_unref(stored_message_protocol); + } + */ + return retval; +} + +/* define the GError domain for Thrift transports */ +GQuark +thrift_multiplexed_processor_error_quark (void) +{ + return g_quark_from_static_string (THRIFT_MULTIPLEXED_PROCESSOR_ERROR_DOMAIN); +} + + +static void +thrift_multiplexed_processor_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + ThriftMultiplexedProcessor *self = THRIFT_MULTIPLEXED_PROCESSOR (object); + + switch (property_id) + { + case PROP_THRIFT_MULTIPLEXED_PROCESSOR_DEFAULT_SERVICE_NAME: + self->default_processor_name = g_value_dup_string (value); + break; + + default: + /* We don't have any other property... */ + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +thrift_multiplexed_processor_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + ThriftMultiplexedProcessor *self = THRIFT_MULTIPLEXED_PROCESSOR (object); + + switch (property_id) + { + case PROP_THRIFT_MULTIPLEXED_PROCESSOR_DEFAULT_SERVICE_NAME: + g_value_set_string (value, self->default_processor_name); + break; + + default: + /* We don't have any other property... */ + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +/* destructor */ +static void +thrift_multiplexed_processor_finalize (GObject *object) +{ + ThriftMultiplexedProcessor *self = THRIFT_MULTIPLEXED_PROCESSOR(object); + + /* Free our multiplexed hash table */ + g_hash_table_unref (self->multiplexed_services); + self->multiplexed_services = NULL; + + if(self->default_processor_name){ + g_free(self->default_processor_name); + self->default_processor_name=NULL; + } + + /* Chain up to parent */ + if (G_OBJECT_CLASS (thrift_multiplexed_processor_parent_class)->finalize) + (*G_OBJECT_CLASS (thrift_multiplexed_processor_parent_class)->finalize) (object); +} + +/* class initializer for ThriftMultiplexedProcessor */ +static void +thrift_multiplexed_processor_class_init (ThriftMultiplexedProcessorClass *cls) +{ + /* Override */ + THRIFT_PROCESSOR_CLASS(cls)->process = thrift_multiplexed_processor_process_impl; + GObjectClass *gobject_class = G_OBJECT_CLASS (cls); + + /* Object methods */ + gobject_class->set_property = thrift_multiplexed_processor_set_property; + gobject_class->get_property = thrift_multiplexed_processor_get_property; + gobject_class->finalize = thrift_multiplexed_processor_finalize; + + /* Class methods */ + cls->register_processor = thrift_multiplexed_processor_register_processor_impl; + + + thrift_multiplexed_processor_obj_properties[PROP_THRIFT_MULTIPLEXED_PROCESSOR_DEFAULT_SERVICE_NAME] = + g_param_spec_string ("default", + "Default service name the protocol points to where no multiplexed client used", + "Set the default service name", + NULL, + (G_PARAM_READWRITE)); + + g_object_class_install_properties (gobject_class, + PROP_THRIFT_MULTIPLEXED_PROCESSOR_END, + thrift_multiplexed_processor_obj_properties); + +} + +static void +thrift_multiplexed_processor_init (ThriftMultiplexedProcessor *self) +{ + + /* Create our multiplexed services hash table */ + self->multiplexed_services = g_hash_table_new_full ( + g_str_hash, + g_str_equal, + g_free, + g_object_unref); + self->default_processor_name = NULL; +} + + +gboolean +thrift_multiplexed_processor_register_processor(ThriftProcessor *processor, const gchar * multiplexed_processor_name, ThriftProcessor * multiplexed_processor , GError **error) +{ + return THRIFT_MULTIPLEXED_PROCESSOR_GET_CLASS(processor)->register_processor(processor, multiplexed_processor_name, multiplexed_processor, error); +} + + diff --git a/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/processor/thrift_multiplexed_processor.h b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/processor/thrift_multiplexed_processor.h new file mode 100644 index 000000000..6406616c2 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/processor/thrift_multiplexed_processor.h @@ -0,0 +1,114 @@ +/* + * thrift_multiplexed_processor.h + * + * Created on: 14 sept. 2017 + * Author: gaguilar + */ + +#ifndef _THRIFT_MULTIPLEXED_MULTIPLEXED_PROCESSOR_H_ +#define _THRIFT_MULTIPLEXED_MULTIPLEXED_PROCESSOR_H_ + + +#include <glib-object.h> + +#include <thrift/c_glib/processor/thrift_processor.h> + + +G_BEGIN_DECLS + +/*! \file thrift_multiplexed_processor.h + * \brief The multiplexed processor for c_glib. + */ + +/* type macros */ +#define THRIFT_TYPE_MULTIPLEXED_PROCESSOR (thrift_multiplexed_processor_get_type ()) +#define THRIFT_MULTIPLEXED_PROCESSOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THRIFT_TYPE_MULTIPLEXED_PROCESSOR, ThriftMultiplexedProcessor)) +#define THRIFT_IS_MULTIPLEXED_PROCESSOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THRIFT_TYPE_MULTIPLEXED_PROCESSOR)) +#define THRIFT_MULTIPLEXED_PROCESSOR_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), THRIFT_TYPE_MULTIPLEXED_PROCESSOR, ThriftMultiplexedProcessorClass)) +#define THRIFT_IS_MULTIPLEXED_PROCESSOR_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), THRIFT_TYPE_MULTIPLEXED_PROCESSOR)) +#define THRIFT_MULTIPLEXED_PROCESSOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THRIFT_TYPE_MULTIPLEXED_PROCESSOR, ThriftMultiplexedProcessorClass)) + +/* define the GError domain string */ +#define THRIFT_MULTIPLEXED_PROCESSOR_ERROR_DOMAIN "thrift-multiplexed-processor-error-quark" + + +/*! + * Thrift MultiplexedProcessor object + */ +struct _ThriftMultiplexedProcessor +{ + ThriftProcessor parent; + + /* private */ + gchar * default_processor_name; + GHashTable *multiplexed_services; +}; +typedef struct _ThriftMultiplexedProcessor ThriftMultiplexedProcessor; + +/*! + * Thrift MultiplexedProcessor class + */ +struct _ThriftMultiplexedProcessorClass +{ + ThriftProcessorClass parent; + + gboolean (* register_processor) (ThriftProcessor *self, const gchar * multiplexed_processor_name, ThriftProcessor * multiplexed_processor , GError **error); + +}; +typedef struct _ThriftMultiplexedProcessorClass ThriftMultiplexedProcessorClass; + +/* used by THRIFT_TYPE_MULTIPLEXED_PROCESSOR */ +GType thrift_multiplexed_processor_get_type (void); + +/*! + * Processes the request. + * \public \memberof ThriftMultiplexedProcessorClass + */ +gboolean thrift_multiplexed_processor_process (ThriftMultiplexedProcessor *processor, + ThriftProtocol *in, ThriftProtocol *out, + GError **error); + + +/* Public API */ + +/** + * @brief Registers a processor in the multiplexed processor under its name. It + * will take a reference to the processor so refcount will be incremented. + * It will also be decremented on object destruction. + * + * The first registered processor becomes default. But you can override it with + * "default" property. + * + * It returns a compliant error if it cannot be registered. + * + * @param processor Pointer to the multiplexed processor. + * @param multiplexed_processor_name Name of the processor you want to register + * @param multiplexed_processor Pointer to implemented processor you want multiplex. + * @param error Error object where we should store errors. + * + * @see https://developer.gnome.org/glib/stable/glib-Error-Reporting.html#g-set-error + */ +gboolean thrift_multiplexed_processor_register_processor(ThriftProcessor *processor, const gchar * multiplexed_processor_name, ThriftProcessor * multiplexed_processor , GError **error); + + +/* define error/exception types */ +typedef enum +{ + THRIFT_MULTIPLEXED_PROCESSOR_ERROR_UNKNOWN, + THRIFT_MULTIPLEXED_PROCESSOR_ERROR_SERVICE_UNAVAILABLE, + THRIFT_MULTIPLEXED_PROCESSOR_ERROR_MESSAGE_TYPE, + THRIFT_MULTIPLEXED_PROCESSOR_ERROR_MESSAGE_WRONGLY_MULTIPLEXED, + THRIFT_MULTIPLEXED_PROCESSOR_ERROR_SEND, + THRIFT_MULTIPLEXED_PROCESSOR_ERROR_RECEIVE, + THRIFT_MULTIPLEXED_PROCESSOR_ERROR_CLOSE +} ThriftMultiplexedProcessorError; + + +GQuark thrift_multiplexed_processor_error_quark (void); +#define THRIFT_MULTIPLEXED_PROCESSOR_ERROR (thrift_multiplexed_processor_error_quark ()) + + +G_END_DECLS + + +#endif /* _THRIFT_MULTIPLEXED_MULTIPLEXED_PROCESSOR_H_ */ diff --git a/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/processor/thrift_processor.c b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/processor/thrift_processor.c new file mode 100644 index 000000000..c242c2503 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/processor/thrift_processor.c @@ -0,0 +1,45 @@ +/* + * 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 <thrift/c_glib/thrift.h> +#include <thrift/c_glib/processor/thrift_processor.h> + +G_DEFINE_ABSTRACT_TYPE(ThriftProcessor, thrift_processor, G_TYPE_OBJECT) + +gboolean +thrift_processor_process (ThriftProcessor *processor, ThriftProtocol *in, + ThriftProtocol *out, GError **error) +{ + return + THRIFT_PROCESSOR_GET_CLASS (processor)->process (processor, in, out, error); +} + +/* class initializer for ThriftProcessor */ +static void +thrift_processor_class_init (ThriftProcessorClass *cls) +{ + /* set these as virtual methods to be implemented by a subclass */ + cls->process = thrift_processor_process; +} + +static void +thrift_processor_init (ThriftProcessor *processor) +{ + THRIFT_UNUSED_VAR (processor); +} diff --git a/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/processor/thrift_processor.h b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/processor/thrift_processor.h new file mode 100644 index 000000000..ff2d2dae4 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/processor/thrift_processor.h @@ -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_PROCESSOR_H +#define _THRIFT_PROCESSOR_H + +#include <glib-object.h> + +#include <thrift/c_glib/protocol/thrift_protocol.h> + +G_BEGIN_DECLS + +/*! \file thrift_processor.h + * \brief Abstract class for Thrift processors. + */ + +/* type macros */ +#define THRIFT_TYPE_PROCESSOR (thrift_processor_get_type ()) +#define THRIFT_PROCESSOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THRIFT_TYPE_PROCESSOR, ThriftProcessor)) +#define THRIFT_IS_PROCESSOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THRIFT_TYPE_PROCESSOR)) +#define THRIFT_PROCESSOR_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), THRIFT_TYPE_PROCESSOR, ThriftProcessorClass)) +#define THRIFT_IS_PROCESSOR_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), THRIFT_TYPE_PROCESSOR)) +#define THRIFT_PROCESSOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THRIFT_TYPE_PROCESSOR, ThriftProcessorClass)) + +/*! + * Thrift Processorobject + */ +struct _ThriftProcessor +{ + GObject parent; +}; +typedef struct _ThriftProcessor ThriftProcessor; + +/*! + * Thrift Processor class + */ +struct _ThriftProcessorClass +{ + GObjectClass parent; + + /* vtable */ + gboolean (*process) (ThriftProcessor *processor, ThriftProtocol *in, + ThriftProtocol *out, GError **error); +}; +typedef struct _ThriftProcessorClass ThriftProcessorClass; + +/* used by THRIFT_TYPE_PROCESSOR */ +GType thrift_processor_get_type (void); + +/*! + * Processes the request. + * \public \memberof ThriftProcessorClass + */ +gboolean thrift_processor_process (ThriftProcessor *processor, + ThriftProtocol *in, ThriftProtocol *out, + GError **error); + +G_END_DECLS + +#endif /* _THRIFT_PROCESSOR_H */ diff --git a/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_binary_protocol.c b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_binary_protocol.c new file mode 100644 index 000000000..7c2d017e1 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_binary_protocol.c @@ -0,0 +1,911 @@ +/* + * 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/protocol/thrift_protocol.h> +#include <thrift/c_glib/protocol/thrift_binary_protocol.h> + +G_DEFINE_TYPE(ThriftBinaryProtocol, thrift_binary_protocol, THRIFT_TYPE_PROTOCOL) + +static guint64 +thrift_bitwise_cast_guint64 (gdouble v) +{ + union { + gdouble from; + guint64 to; + } u; + u.from = v; + return u.to; +} + +static gdouble +thrift_bitwise_cast_gdouble (guint64 v) +{ + union { + guint64 from; + gdouble to; + } u; + u.from = v; + return u.to; +} + +gint32 +thrift_binary_protocol_write_message_begin (ThriftProtocol *protocol, + const gchar *name, const ThriftMessageType message_type, + const gint32 seqid, GError **error) +{ + gint32 version = (THRIFT_BINARY_PROTOCOL_VERSION_1) + | ((gint32) message_type); + gint32 ret; + gint32 xfer = 0; + + g_return_val_if_fail (THRIFT_IS_BINARY_PROTOCOL (protocol), -1); + + if ((ret = thrift_protocol_write_i32 (protocol, version, error)) < 0) + { + return -1; + } + xfer += ret; + if ((ret = thrift_protocol_write_string (protocol, name, error)) < 0) + { + return -1; + } + xfer += ret; + if ((ret = thrift_protocol_write_i32 (protocol, seqid, error)) < 0) + { + return -1; + } + xfer += ret; + return xfer; +} + +gint32 +thrift_binary_protocol_write_message_end (ThriftProtocol *protocol, + GError **error) +{ + /* satisfy -Wall */ + THRIFT_UNUSED_VAR (protocol); + THRIFT_UNUSED_VAR (error); + return 0; +} + +gint32 +thrift_binary_protocol_write_struct_begin (ThriftProtocol *protocol, + const gchar *name, + GError **error) +{ + /* satisfy -Wall */ + THRIFT_UNUSED_VAR (protocol); + THRIFT_UNUSED_VAR (name); + THRIFT_UNUSED_VAR (error); + return 0; +} + +gint32 +thrift_binary_protocol_write_struct_end (ThriftProtocol *protocol, + GError **error) +{ + /* satisfy -Wall */ + THRIFT_UNUSED_VAR (protocol); + THRIFT_UNUSED_VAR (error); + return 0; +} + +gint32 +thrift_binary_protocol_write_field_begin (ThriftProtocol *protocol, + const gchar *name, + const ThriftType field_type, + const gint16 field_id, + GError **error) +{ + gint32 ret; + gint32 xfer = 0; + + g_return_val_if_fail (THRIFT_IS_BINARY_PROTOCOL (protocol), -1); + + THRIFT_UNUSED_VAR (name); + + if ((ret = thrift_protocol_write_byte (protocol, (gint8) field_type, + error)) < 0) + { + return -1; + } + xfer += ret; + if ((ret = thrift_protocol_write_i16 (protocol, field_id, error)) < 0) + { + return -1; + } + xfer += ret; + return xfer; +} + +gint32 +thrift_binary_protocol_write_field_end (ThriftProtocol *protocol, + GError **error) +{ + /* satisfy -Wall */ + THRIFT_UNUSED_VAR (protocol); + THRIFT_UNUSED_VAR (error); + return 0; +} + +gint32 +thrift_binary_protocol_write_field_stop (ThriftProtocol *protocol, + GError **error) +{ + g_return_val_if_fail (THRIFT_IS_BINARY_PROTOCOL (protocol), -1); + return thrift_protocol_write_byte (protocol, (gint8) T_STOP, error); +} + +gint32 +thrift_binary_protocol_write_map_begin (ThriftProtocol *protocol, + const ThriftType key_type, + const ThriftType value_type, + const guint32 size, + GError **error) +{ + gint32 ret; + gint32 xfer = 0; + + g_return_val_if_fail (THRIFT_IS_BINARY_PROTOCOL (protocol), -1); + + if ((ret = thrift_protocol_write_byte (protocol, (gint8) key_type, + error)) < 0) + { + return -1; + } + xfer += ret; + if ((ret = thrift_protocol_write_byte (protocol, (gint8) value_type, + error)) < 0) + { + return -1; + } + xfer += ret; + if ((ret = thrift_protocol_write_i32 (protocol, (gint32) size, error)) < 0) + { + return -1; + } + xfer += ret; + return xfer; +} + +gint32 +thrift_binary_protocol_write_map_end (ThriftProtocol *protocol, + GError **error) +{ + THRIFT_UNUSED_VAR (protocol); + THRIFT_UNUSED_VAR (error); + return 0; +} + +gint32 +thrift_binary_protocol_write_list_begin (ThriftProtocol *protocol, + const ThriftType element_type, + const guint32 size, + GError **error) +{ + gint32 ret; + gint32 xfer = 0; + + g_return_val_if_fail (THRIFT_IS_BINARY_PROTOCOL (protocol), -1); + + if ((ret = thrift_protocol_write_byte (protocol, (gint8) element_type, + error)) < 0) + { + return -1; + } + xfer += ret; + + if ((ret = thrift_protocol_write_i32 (protocol, (gint32) size, error)) < 0) + { + return -1; + } + xfer += ret; + + return xfer; +} + +gint32 +thrift_binary_protocol_write_list_end (ThriftProtocol *protocol, + GError **error) +{ + THRIFT_UNUSED_VAR (protocol); + THRIFT_UNUSED_VAR (error); + return 0; +} + +gint32 +thrift_binary_protocol_write_set_begin (ThriftProtocol *protocol, + const ThriftType element_type, + const guint32 size, + GError **error) +{ + g_return_val_if_fail (THRIFT_IS_BINARY_PROTOCOL (protocol), -1); + + return thrift_protocol_write_list_begin (protocol, element_type, + size, error); +} + +gint32 +thrift_binary_protocol_write_set_end (ThriftProtocol *protocol, GError **error) +{ + THRIFT_UNUSED_VAR (protocol); + THRIFT_UNUSED_VAR (error); + return 0; +} + +gint32 +thrift_binary_protocol_write_bool (ThriftProtocol *protocol, + const gboolean value, GError **error) +{ + guint8 tmp; + + g_return_val_if_fail (THRIFT_IS_BINARY_PROTOCOL (protocol), -1); + + tmp = value ? 1 : 0; + return thrift_protocol_write_byte (protocol, tmp, error); +} + +gint32 +thrift_binary_protocol_write_byte (ThriftProtocol *protocol, const gint8 value, + GError **error) +{ + g_return_val_if_fail (THRIFT_IS_BINARY_PROTOCOL (protocol), -1); + + if (thrift_transport_write (protocol->transport, + (const gpointer) &value, 1, error)) + { + return 1; + } else { + return -1; + } +} + +gint32 +thrift_binary_protocol_write_i16 (ThriftProtocol *protocol, const gint16 value, + GError **error) +{ + gint16 net; + + g_return_val_if_fail (THRIFT_IS_BINARY_PROTOCOL (protocol), -1); + + net = g_htons (value); + if (thrift_transport_write (protocol->transport, + (const gpointer) &net, 2, error)) + { + return 2; + } else { + return -1; + } +} + +gint32 +thrift_binary_protocol_write_i32 (ThriftProtocol *protocol, const gint32 value, + GError **error) +{ + gint32 net; + + g_return_val_if_fail (THRIFT_IS_BINARY_PROTOCOL (protocol), -1); + + net = g_htonl (value); + if (thrift_transport_write (protocol->transport, + (const gpointer) &net, 4, error)) + { + return 4; + } else { + return -1; + } +} + +gint32 +thrift_binary_protocol_write_i64 (ThriftProtocol *protocol, const gint64 value, + GError **error) +{ + gint64 net; + + g_return_val_if_fail (THRIFT_IS_BINARY_PROTOCOL (protocol), -1); + + net = GUINT64_TO_BE (value); + if (thrift_transport_write (protocol->transport, + (const gpointer) &net, 8, error)) + { + return 8; + } else { + return -1; + } +} + +gint32 +thrift_binary_protocol_write_double (ThriftProtocol *protocol, + const gdouble value, GError **error) +{ + guint64 bits; + + g_return_val_if_fail (THRIFT_IS_BINARY_PROTOCOL (protocol), -1); + + bits = GUINT64_FROM_BE (thrift_bitwise_cast_guint64 (value)); + if (thrift_transport_write (protocol->transport, + (const gpointer) &bits, 8, error)) + { + return 8; + } else { + return -1; + } +} + +gint32 +thrift_binary_protocol_write_string (ThriftProtocol *protocol, + const gchar *str, GError **error) +{ + guint32 len; + + g_return_val_if_fail (THRIFT_IS_BINARY_PROTOCOL (protocol), -1); + + len = str != NULL ? strlen (str) : 0; + /* write the string length + 1 which includes the null terminator */ + return thrift_protocol_write_binary (protocol, (const gpointer) str, + len, error); +} + +gint32 +thrift_binary_protocol_write_binary (ThriftProtocol *protocol, + const gpointer buf, + const guint32 len, GError **error) +{ + gint32 ret; + gint32 xfer = 0; + + g_return_val_if_fail (THRIFT_IS_BINARY_PROTOCOL (protocol), -1); + + if ((ret = thrift_protocol_write_i32 (protocol, len, error)) < 0) + { + return -1; + } + xfer += ret; + + if (len > 0) + { + if (thrift_transport_write (protocol->transport, + (const gpointer) buf, len, error) == FALSE) + { + return -1; + } + xfer += len; + } + + return xfer; +} + +gint32 +thrift_binary_protocol_read_message_begin (ThriftProtocol *protocol, + gchar **name, + ThriftMessageType *message_type, + gint32 *seqid, GError **error) +{ + gint32 ret; + gint32 xfer = 0; + gint32 sz; + + g_return_val_if_fail (THRIFT_IS_BINARY_PROTOCOL (protocol), -1); + + if ((ret = thrift_protocol_read_i32 (protocol, &sz, error)) < 0) + { + return -1; + } + xfer += ret; + + if (sz < 0) + { + /* check for version */ + guint32 version = sz & THRIFT_BINARY_PROTOCOL_VERSION_MASK; + if (version != THRIFT_BINARY_PROTOCOL_VERSION_1) + { + g_set_error (error, THRIFT_PROTOCOL_ERROR, + THRIFT_PROTOCOL_ERROR_BAD_VERSION, + "expected version %d, got %d", + THRIFT_BINARY_PROTOCOL_VERSION_1, version); + return -1; + } + + *message_type = (ThriftMessageType) (sz & 0x000000ff); + + if ((ret = thrift_protocol_read_string (protocol, name, error)) < 0) + { + return -1; + } + xfer += ret; + + if ((ret = thrift_protocol_read_i32 (protocol, seqid, error)) < 0) + { + return -1; + } + xfer += ret; + } + return xfer; +} + +gint32 +thrift_binary_protocol_read_message_end (ThriftProtocol *protocol, + GError **error) +{ + THRIFT_UNUSED_VAR (protocol); + THRIFT_UNUSED_VAR (error); + return 0; +} + +gint32 +thrift_binary_protocol_read_struct_begin (ThriftProtocol *protocol, + gchar **name, + GError **error) +{ + THRIFT_UNUSED_VAR (protocol); + THRIFT_UNUSED_VAR (error); + *name = NULL; + return 0; +} + +gint32 +thrift_binary_protocol_read_struct_end (ThriftProtocol *protocol, + GError **error) +{ + THRIFT_UNUSED_VAR (protocol); + THRIFT_UNUSED_VAR (error); + return 0; +} + +gint32 +thrift_binary_protocol_read_field_begin (ThriftProtocol *protocol, + gchar **name, + ThriftType *field_type, + gint16 *field_id, + GError **error) +{ + gint32 ret; + gint32 xfer = 0; + gint8 type; + + g_return_val_if_fail (THRIFT_IS_BINARY_PROTOCOL (protocol), -1); + + THRIFT_UNUSED_VAR (name); + + if ((ret = thrift_protocol_read_byte (protocol, &type, error)) < 0) + { + return -1; + } + xfer += ret; + *field_type = (ThriftType) type; + if (*field_type == T_STOP) + { + *field_id = 0; + return xfer; + } + if ((ret = thrift_protocol_read_i16 (protocol, field_id, error)) < 0) + { + return -1; + } + xfer += ret; + return xfer; +} + +gint32 +thrift_binary_protocol_read_field_end (ThriftProtocol *protocol, + GError **error) +{ + THRIFT_UNUSED_VAR (protocol); + THRIFT_UNUSED_VAR (error); + return 0; +} + +gint32 +thrift_binary_protocol_read_map_begin (ThriftProtocol *protocol, + ThriftType *key_type, + ThriftType *value_type, + guint32 *size, + GError **error) +{ + gint32 ret; + gint32 xfer = 0; + gint8 k, v; + gint32 sizei; + + g_return_val_if_fail (THRIFT_IS_BINARY_PROTOCOL (protocol), -1); + + if ((ret = thrift_protocol_read_byte (protocol, &k, error)) < 0) + { + return -1; + } + xfer += ret; + *key_type = (ThriftType) k; + + if ((ret = thrift_protocol_read_byte (protocol, &v, error)) < 0) + { + return -1; + } + xfer += ret; + *value_type = (ThriftType) v; + + if ((ret = thrift_protocol_read_i32 (protocol, &sizei, error)) <0) + { + return -1; + } + xfer += ret; + + if (sizei < 0) + { + g_set_error (error, THRIFT_PROTOCOL_ERROR, + THRIFT_PROTOCOL_ERROR_NEGATIVE_SIZE, + "got negative size of %d", sizei); + return -1; + } + + *size = (guint32) sizei; + return xfer; +} + +gint32 +thrift_binary_protocol_read_map_end (ThriftProtocol *protocol, + GError **error) +{ + THRIFT_UNUSED_VAR (protocol); + THRIFT_UNUSED_VAR (error); + return 0; +} + +gint32 +thrift_binary_protocol_read_list_begin (ThriftProtocol *protocol, + ThriftType *element_type, + guint32 *size, GError **error) +{ + gint32 ret; + gint32 xfer = 0; + gint8 e; + gint32 sizei; + + g_return_val_if_fail (THRIFT_IS_BINARY_PROTOCOL (protocol), -1); + + if ((ret = thrift_protocol_read_byte (protocol, &e, error)) < 0) + { + return -1; + } + xfer += ret; + *element_type = (ThriftType) e; + + if ((ret = thrift_protocol_read_i32 (protocol, &sizei, error)) < 0) + { + return -1; + } + xfer += ret; + + if (sizei < 0) + { + g_set_error (error, THRIFT_PROTOCOL_ERROR, + THRIFT_PROTOCOL_ERROR_NEGATIVE_SIZE, + "got negative size of %d", sizei); + return -1; + } + + *size = (guint32) sizei; + return xfer; +} + +gint32 +thrift_binary_protocol_read_list_end (ThriftProtocol *protocol, + GError **error) +{ + THRIFT_UNUSED_VAR (protocol); + THRIFT_UNUSED_VAR (error); + return 0; +} + +gint32 +thrift_binary_protocol_read_set_begin (ThriftProtocol *protocol, + ThriftType *element_type, + guint32 *size, GError **error) +{ + g_return_val_if_fail (THRIFT_IS_BINARY_PROTOCOL (protocol), -1); + + return thrift_protocol_read_list_begin (protocol, element_type, size, error); +} + +gint32 +thrift_binary_protocol_read_set_end (ThriftProtocol *protocol, + GError **error) +{ + THRIFT_UNUSED_VAR (protocol); + THRIFT_UNUSED_VAR (error); + return 0; +} + +gint32 +thrift_binary_protocol_read_bool (ThriftProtocol *protocol, gboolean *value, + GError **error) +{ + gint32 ret; + gpointer b[1]; + + g_return_val_if_fail (THRIFT_IS_BINARY_PROTOCOL (protocol), -1); + + if ((ret = + thrift_transport_read_all (protocol->transport, + b, 1, error)) < 0) + { + return -1; + } + *value = *(gint8 *) b != 0; + return ret; +} + +gint32 +thrift_binary_protocol_read_byte (ThriftProtocol *protocol, gint8 *value, + GError **error) +{ + gint32 ret; + gpointer b[1]; + + g_return_val_if_fail (THRIFT_IS_BINARY_PROTOCOL (protocol), -1); + + if ((ret = + thrift_transport_read_all (protocol->transport, + b, 1, error)) < 0) + { + return -1; + } + *value = *(gint8 *) b; + return ret; +} + +gint32 +thrift_binary_protocol_read_i16 (ThriftProtocol *protocol, gint16 *value, + GError **error) +{ + gint32 ret; + union + { + gint8 byte_array[2]; + gint16 int16; + } b; + + g_return_val_if_fail (THRIFT_IS_BINARY_PROTOCOL (protocol), -1); + + if ((ret = + thrift_transport_read_all (protocol->transport, + b.byte_array, 2, error)) < 0) + { + return -1; + } + *value = g_ntohs (b.int16); + return ret; +} + +gint32 +thrift_binary_protocol_read_i32 (ThriftProtocol *protocol, gint32 *value, + GError **error) +{ + gint32 ret; + union + { + gint8 byte_array[4]; + gint32 int32; + } b; + + g_return_val_if_fail (THRIFT_IS_BINARY_PROTOCOL (protocol), -1); + + if ((ret = + thrift_transport_read_all (protocol->transport, + b.byte_array, 4, error)) < 0) + { + return -1; + } + *value = g_ntohl (b.int32); + return ret; +} + +gint32 +thrift_binary_protocol_read_i64 (ThriftProtocol *protocol, gint64 *value, + GError **error) +{ + gint32 ret; + union + { + gint8 byte_array[8]; + gint64 int64; + } b; + + g_return_val_if_fail (THRIFT_IS_BINARY_PROTOCOL (protocol), -1); + + if ((ret = + thrift_transport_read_all (protocol->transport, + b.byte_array, 8, error)) < 0) + { + return -1; + } + *value = GUINT64_FROM_BE (b.int64); + return ret; +} + +gint32 +thrift_binary_protocol_read_double (ThriftProtocol *protocol, + gdouble *value, GError **error) +{ + gint32 ret; + union + { + gint8 byte_array[8]; + guint64 uint64; + } b; + + g_return_val_if_fail (THRIFT_IS_BINARY_PROTOCOL (protocol), -1); + + if ((ret = + thrift_transport_read_all (protocol->transport, + b.byte_array, 8, error)) < 0) + { + return -1; + } + *value = thrift_bitwise_cast_gdouble (GUINT64_FROM_BE (b.uint64)); + return ret; +} + +gint32 +thrift_binary_protocol_read_string (ThriftProtocol *protocol, + gchar **str, GError **error) +{ + guint32 len; + gint32 ret; + gint32 xfer = 0; + gint32 read_len = 0; + + g_return_val_if_fail (THRIFT_IS_BINARY_PROTOCOL (protocol), -1); + + /* read the length into read_len */ + if ((ret = + thrift_protocol_read_i32 (protocol, &read_len, error)) < 0) + { + return -1; + } + xfer += ret; + + 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) + { + g_free (*str); + *str = NULL; + len = 0; + return -1; + } + xfer += ret; + } else { + **str = 0; + } + + return xfer; +} + +gint32 +thrift_binary_protocol_read_binary (ThriftProtocol *protocol, + gpointer *buf, guint32 *len, + GError **error) +{ + gint32 ret; + gint32 xfer = 0; + gint32 read_len = 0; + + g_return_val_if_fail (THRIFT_IS_BINARY_PROTOCOL (protocol), -1); + + /* read the length into read_len */ + if ((ret = + thrift_protocol_read_i32 (protocol, &read_len, error)) < 0) + { + return -1; + } + xfer += ret; + + if (read_len > 0) + { + /* allocate the memory as an array of unsigned char for binary data */ + *len = (guint32) read_len; + *buf = g_new (guchar, *len); + if ((ret = + thrift_transport_read_all (protocol->transport, + *buf, *len, error)) < 0) + { + g_free (*buf); + *buf = NULL; + *len = 0; + return -1; + } + xfer += ret; + } else { + *len = (guint32) read_len; + *buf = NULL; + } + + return xfer; +} + +static void +thrift_binary_protocol_init (ThriftBinaryProtocol *protocol) +{ + THRIFT_UNUSED_VAR (protocol); +} + +/* initialize the class */ +static void +thrift_binary_protocol_class_init (ThriftBinaryProtocolClass *klass) +{ + ThriftProtocolClass *cls = THRIFT_PROTOCOL_CLASS (klass); + + cls->write_message_begin = thrift_binary_protocol_write_message_begin; + cls->write_message_end = thrift_binary_protocol_write_message_end; + cls->write_struct_begin = thrift_binary_protocol_write_struct_begin; + cls->write_struct_end = thrift_binary_protocol_write_struct_end; + cls->write_field_begin = thrift_binary_protocol_write_field_begin; + cls->write_field_end = thrift_binary_protocol_write_field_end; + cls->write_field_stop = thrift_binary_protocol_write_field_stop; + cls->write_map_begin = thrift_binary_protocol_write_map_begin; + cls->write_map_end = thrift_binary_protocol_write_map_end; + cls->write_list_begin = thrift_binary_protocol_write_list_begin; + cls->write_list_end = thrift_binary_protocol_write_list_end; + cls->write_set_begin = thrift_binary_protocol_write_set_begin; + cls->write_set_end = thrift_binary_protocol_write_set_end; + cls->write_bool = thrift_binary_protocol_write_bool; + cls->write_byte = thrift_binary_protocol_write_byte; + cls->write_i16 = thrift_binary_protocol_write_i16; + cls->write_i32 = thrift_binary_protocol_write_i32; + cls->write_i64 = thrift_binary_protocol_write_i64; + cls->write_double = thrift_binary_protocol_write_double; + cls->write_string = thrift_binary_protocol_write_string; + cls->write_binary = thrift_binary_protocol_write_binary; + cls->read_message_begin = thrift_binary_protocol_read_message_begin; + cls->read_message_end = thrift_binary_protocol_read_message_end; + cls->read_struct_begin = thrift_binary_protocol_read_struct_begin; + cls->read_struct_end = thrift_binary_protocol_read_struct_end; + cls->read_field_begin = thrift_binary_protocol_read_field_begin; + cls->read_field_end = thrift_binary_protocol_read_field_end; + cls->read_map_begin = thrift_binary_protocol_read_map_begin; + cls->read_map_end = thrift_binary_protocol_read_map_end; + cls->read_list_begin = thrift_binary_protocol_read_list_begin; + cls->read_list_end = thrift_binary_protocol_read_list_end; + cls->read_set_begin = thrift_binary_protocol_read_set_begin; + cls->read_set_end = thrift_binary_protocol_read_set_end; + cls->read_bool = thrift_binary_protocol_read_bool; + cls->read_byte = thrift_binary_protocol_read_byte; + cls->read_i16 = thrift_binary_protocol_read_i16; + cls->read_i32 = thrift_binary_protocol_read_i32; + cls->read_i64 = thrift_binary_protocol_read_i64; + cls->read_double = thrift_binary_protocol_read_double; + cls->read_string = thrift_binary_protocol_read_string; + cls->read_binary = thrift_binary_protocol_read_binary; +} diff --git a/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_binary_protocol.h b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_binary_protocol.h new file mode 100644 index 000000000..5230bcced --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_binary_protocol.h @@ -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_BINARY_PROTOCOL_H +#define _THRIFT_BINARY_PROTOCOL_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_binary_protocol.h + * \brief Binary protocol implementation of a Thrift protocol. Implements the + * ThriftProtocol interface. + */ + +/* type macros */ +#define THRIFT_TYPE_BINARY_PROTOCOL (thrift_binary_protocol_get_type ()) +#define THRIFT_BINARY_PROTOCOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THRIFT_TYPE_BINARY_PROTOCOL, ThriftBinaryProtocol)) +#define THRIFT_IS_BINARY_PROTOCOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THRIFT_TYPE_BINARY_PROTOCOL)) +#define THRIFT_BINARY_PROTOCOL_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), THRIFT_TYPE_BINARY_PROTOCOL, ThriftBinaryProtocolClass)) +#define THRIFT_IS_BINARY_PROTOCOL_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), THRIFT_TYPE_BINARY_PROTOCOL)) +#define THRIFT_BINARY_PROTOCOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THRIFT_TYPE_BINARY_PROTOCOL, ThriftBinaryProtocolClass)) + +/* version numbers */ +#define THRIFT_BINARY_PROTOCOL_VERSION_1 0x80010000 +#define THRIFT_BINARY_PROTOCOL_VERSION_MASK 0xffff0000 + +typedef struct _ThriftBinaryProtocol ThriftBinaryProtocol; + +/*! + * Thrift Binary Protocol instance. + */ +struct _ThriftBinaryProtocol +{ + ThriftProtocol parent; +}; + +typedef struct _ThriftBinaryProtocolClass ThriftBinaryProtocolClass; + +/*! + * Thrift Binary Protocol class. + */ +struct _ThriftBinaryProtocolClass +{ + ThriftProtocolClass parent; +}; + +/* used by THRIFT_TYPE_BINARY_PROTOCOL */ +GType thrift_binary_protocol_get_type (void); + +G_END_DECLS + +#endif /* _THRIFT_BINARY_PROTOCOL_H */ diff --git a/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_binary_protocol_factory.c b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_binary_protocol_factory.c new file mode 100644 index 000000000..774e9ad4a --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_binary_protocol_factory.c @@ -0,0 +1,50 @@ +/* + * 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 <thrift/c_glib/thrift.h> +#include <thrift/c_glib/protocol/thrift_binary_protocol.h> +#include <thrift/c_glib/protocol/thrift_binary_protocol_factory.h> + +G_DEFINE_TYPE(ThriftBinaryProtocolFactory, thrift_binary_protocol_factory, THRIFT_TYPE_PROTOCOL_FACTORY) + +ThriftProtocol * +thrift_binary_protocol_factory_get_protocol (ThriftProtocolFactory *factory, + ThriftTransport *transport) +{ + ThriftBinaryProtocol *tb = g_object_new (THRIFT_TYPE_BINARY_PROTOCOL, + "transport", transport, NULL); + + THRIFT_UNUSED_VAR (factory); + + return THRIFT_PROTOCOL (tb); +} + +static void +thrift_binary_protocol_factory_class_init (ThriftBinaryProtocolFactoryClass *cls) +{ + ThriftProtocolFactoryClass *protocol_factory_class = THRIFT_PROTOCOL_FACTORY_CLASS (cls); + + protocol_factory_class->get_protocol = thrift_binary_protocol_factory_get_protocol; +} + +static void +thrift_binary_protocol_factory_init (ThriftBinaryProtocolFactory *factory) +{ + THRIFT_UNUSED_VAR (factory); +} diff --git a/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_binary_protocol_factory.h b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_binary_protocol_factory.h new file mode 100644 index 000000000..eddc07390 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_binary_protocol_factory.h @@ -0,0 +1,56 @@ +/* + * 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_BINARY_PROTOCOL_FACTORY_H +#define _THRIFT_BINARY_PROTOCOL_FACTORY_H + +#include <glib-object.h> + +#include <thrift/c_glib/protocol/thrift_protocol_factory.h> + +G_BEGIN_DECLS + +/* type macros */ +#define THRIFT_TYPE_BINARY_PROTOCOL_FACTORY (thrift_binary_protocol_factory_get_type ()) +#define THRIFT_BINARY_PROTOCOL_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THRIFT_TYPE_BINARY_PROTOCOL_FACTORY, ThriftBinaryProtocolFactory)) +#define THRIFT_IS_BINARY_PROTOCOL_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THRIFT_TYPE_BINARY_PROTOCOL_FACTORY)) +#define THRIFT_BINARY_PROTOCOL_FACTORY_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), THRIFT_TYPE_BINARY_PROTOCOL_FACTORY, ThriftBinaryProtocolFactoryClass)) +#define THRIFT_IS_BINARY_PROTOCOL_FACTORY_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), THRIFT_TYPE_BINARY_PROTOCOL_FACTORY)) +#define THRIFT_BINARY_PROTOCOL_FACTORY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THRIFT_TYPE_BINARY_PROTOCOL_FACTORY, ThriftBinaryProtocolFactoryClass)) + +typedef struct _ThriftBinaryProtocolFactory ThriftBinaryProtocolFactory; + +struct _ThriftBinaryProtocolFactory +{ + ThriftProtocolFactory parent; +}; + +typedef struct _ThriftBinaryProtocolFactoryClass ThriftBinaryProtocolFactoryClass; + +struct _ThriftBinaryProtocolFactoryClass +{ + ThriftProtocolFactoryClass parent; +}; + +/* used by THRIFT_TYPE_BINARY_PROTOCOL_FACTORY */ +GType thrift_binary_protocol_factory_get_type (void); + +G_END_DECLS + +#endif /* _THRIFT_BINARY_PROTOCOL_FACTORY_H */ diff --git a/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_compact_protocol.c b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_compact_protocol.c new file mode 100644 index 000000000..cae4749f0 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_compact_protocol.c @@ -0,0 +1,1609 @@ +/* + * 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/protocol/thrift_protocol.h> +#include <thrift/c_glib/protocol/thrift_compact_protocol.h> + +#include <thrift/config.h> + +/* + * *_to_zigzag depend on the fact that the right shift + * operator on a signed integer is an arithmetic (sign-extending) shift. + * If this is not the case, the current implementation will not work. + */ +#if !defined(SIGNED_RIGHT_SHIFT_IS) || !defined(ARITHMETIC_RIGHT_SHIFT) +# error "Unable to determine the behavior of a signed right shift" +#endif +#if SIGNED_RIGHT_SHIFT_IS != ARITHMETIC_RIGHT_SHIFT +# error "thrift_compact_protocol only works if signed right shift is arithmetic" +#endif + +/* object properties */ +enum _ThriftCompactProtocolProperties +{ + PROP_0, + PROP_THRIFT_COMPACT_PROTOCOL_STRING_LIMIT, + PROP_THRIFT_COMPACT_PROTOCOL_CONTAINER_LIMIT +}; + +G_DEFINE_TYPE (ThriftCompactProtocol, thrift_compact_protocol, + THRIFT_TYPE_PROTOCOL) + +static const gint8 PROTOCOL_ID = (gint8)0x82u; +static const gint8 VERSION_N = 1; +static const gint8 VERSION_MASK = 0x1f; /* 0001 1111 */ +static const gint8 TYPE_MASK = (gint8)0xe0u; /* 1110 0000 */ +static const gint8 TYPE_BITS = 0x07; /* 0000 0111 */ +static const gint32 TYPE_SHIFT_AMOUNT = 5; + +enum Types { + CT_STOP = 0x00, + CT_BOOLEAN_TRUE = 0x01, + CT_BOOLEAN_FALSE = 0x02, + CT_BYTE = 0x03, + CT_I16 = 0x04, + CT_I32 = 0x05, + CT_I64 = 0x06, + CT_DOUBLE = 0x07, + CT_BINARY = 0x08, + CT_LIST = 0x09, + CT_SET = 0x0A, + CT_MAP = 0x0B, + CT_STRUCT = 0x0C +}; + +static const gint8 TTypeToCType[16] = { + CT_STOP, /* T_STOP */ + 0, /* unused */ + CT_BOOLEAN_TRUE, /* T_BOOL */ + CT_BYTE, /* T_BYTE */ + CT_DOUBLE, /* T_DOUBLE */ + 0, /* unused */ + CT_I16, /* T_I16 */ + 0, /* unused */ + CT_I32, /* T_I32 */ + 0, /* unused */ + CT_I64, /* T_I64 */ + CT_BINARY, /* T_STRING */ + CT_STRUCT, /* T_STRUCT */ + CT_MAP, /* T_MAP */ + CT_SET, /* T_SET */ + CT_LIST, /* T_LIST */ +}; + +static guint64 +thrift_bitwise_cast_guint64 (const gdouble v) +{ + union { + gdouble from; + guint64 to; + } u; + u.from = v; + return u.to; +} + +static gdouble +thrift_bitwise_cast_gdouble (const guint64 v) +{ + union { + guint64 from; + gdouble to; + } u; + u.from = v; + return u.to; +} + +/** + * Convert l into a zigzag long. This allows negative numbers to be + * represented compactly as a varint. + */ +static guint64 +i64_to_zigzag (const gint64 l) +{ + return (((guint64)l) << 1) ^ (l >> 63); +} + +/** + * Convert n into a zigzag int. This allows negative numbers to be + * represented compactly as a varint. + */ +static guint32 +i32_to_zigzag (const gint32 n) +{ + return (((guint32)n) << 1) ^ (n >> 31); +} + +/** + * Convert from zigzag int to int. + */ +static gint32 +zigzag_to_i32 (guint32 n) +{ + return (n >> 1) ^ (guint32) (-(gint32) (n & 1)); +} + +/** + * Convert from zigzag long to long. + */ +static gint64 +zigzag_to_i64 (guint64 n) +{ + return (n >> 1) ^ (guint64) (-(gint64) (n & 1)); +} + +ThriftType thrift_compact_protocol_get_ttype (ThriftCompactProtocol *protocol, + const gint8 type, GError **error) +{ + THRIFT_UNUSED_VAR (protocol); + + switch (type) { + case T_STOP: + return T_STOP; + case CT_BOOLEAN_FALSE: + case CT_BOOLEAN_TRUE: + return T_BOOL; + case CT_BYTE: + return T_BYTE; + case CT_I16: + return T_I16; + case CT_I32: + return T_I32; + case CT_I64: + return T_I64; + case CT_DOUBLE: + return T_DOUBLE; + case CT_BINARY: + return T_STRING; + case CT_LIST: + return T_LIST; + case CT_SET: + return T_SET; + case CT_MAP: + return T_MAP; + case CT_STRUCT: + return T_STRUCT; + default: + g_set_error (error, THRIFT_PROTOCOL_ERROR, + THRIFT_PROTOCOL_ERROR_INVALID_DATA, + "unrecognized type"); + return -1; + } +} + +/** + * Write an i32 as a varint. Results in 1-5 bytes on the wire. + */ +gint32 +thrift_compact_protocol_write_varint32 (ThriftCompactProtocol *protocol, + const guint32 n, + GError **error) +{ + guint8 buf[5]; + gint32 xfer; + guint32 m; + + THRIFT_UNUSED_VAR (error); + + xfer = 0; + m = n; + + while (TRUE) { + if ((m & ~0x7F) == 0) { + buf[xfer++] = (gint8)m; + break; + } else { + buf[xfer++] = (gint8)((m & 0x7F) | 0x80); + m >>= 7; + } + } + + if (thrift_transport_write (THRIFT_PROTOCOL (protocol)->transport, + (const gpointer) buf, xfer, error)) { + return xfer; + } else { + return -1; + } +} + +/** + * Write an i64 as a varint. Results in 1-10 bytes on the wire. + */ +gint32 +thrift_compact_protocol_write_varint64 (ThriftCompactProtocol *protocol, + const guint64 n, + GError **error) +{ + guint8 buf[10]; + gint32 xfer; + guint64 m; + + THRIFT_UNUSED_VAR (error); + + xfer = 0; + m = n; + + while (TRUE) { + if ((m & ~0x7FL) == 0) { + buf[xfer++] = (gint8)m; + break; + } else { + buf[xfer++] = (gint8)((m & 0x7F) | 0x80); + m >>= 7; + } + } + + if (thrift_transport_write (THRIFT_PROTOCOL (protocol)->transport, + (const gpointer) buf, xfer, error)) { + return xfer; + } else { + return -1; + } +} + +/** + * Read an i64 from the wire as a proper varint. The MSB of each byte is set + * if there is another byte to follow. This can read up to 10 bytes. + */ +gint32 +thrift_compact_protocol_read_varint64 (ThriftCompactProtocol *protocol, + gint64 *i64, + GError **error) +{ + ThriftProtocol *tp; + gint32 ret; + gint32 xfer; + guint64 val; + gint shift; + guint8 byte; + + tp = THRIFT_PROTOCOL (protocol); + xfer = 0; + val = 0; + shift = 0; + byte = 0; + + while (TRUE) { + if ((ret = thrift_transport_read_all (tp->transport, + (gpointer) &byte, 1, error)) < 0) { + return -1; + } + ++xfer; + val |= (guint64)(byte & 0x7f) << shift; + shift += 7; + if (!(byte & 0x80)) { + *i64 = (gint64) val; + return xfer; + } + if (G_UNLIKELY (xfer == 10)) { /* 7 * 9 < 64 < 7 * 10 */ + g_set_error (error, THRIFT_PROTOCOL_ERROR, + THRIFT_PROTOCOL_ERROR_INVALID_DATA, + "variable-length int over 10 bytes"); + return -1; + } + } +} + +/** + * Read an i32 from the wire as a varint. The MSB of each byte is set + * if there is another byte to follow. This can read up to 5 bytes. + */ +gint32 +thrift_compact_protocol_read_varint32 (ThriftCompactProtocol *protocol, + gint32 *i32, + GError **error) +{ + gint64 val; + gint32 ret; + gint32 xfer; + + xfer = 0; + + if ((ret = thrift_compact_protocol_read_varint64 (protocol, &val, + error)) < 0) { + return -1; + } + xfer += ret; + + *i32 = (gint32)val; + + return xfer; +} + +gint32 +thrift_compact_protocol_write_field_begin_internal (ThriftCompactProtocol + *protocol, + const gchar *name, + const ThriftType field_type, + const gint16 field_id, + const gint8 type_override, + GError **error) +{ + gint32 ret; + gint32 xfer; + gint8 type_to_write; + + THRIFT_UNUSED_VAR (name); + + xfer = 0; + + /* if there's a type override, use that. */ + type_to_write + = (type_override == -1 ? TTypeToCType[field_type] : type_override); + + /* check if we can use delta encoding for the field id */ + if (field_id > protocol->_last_field_id + && field_id - protocol->_last_field_id <= 15) { + /* write them together */ + if ((ret = thrift_protocol_write_byte (THRIFT_PROTOCOL (protocol), + (gint8) ((field_id + - protocol->_last_field_id) + << 4 | type_to_write), + error)) < 0) { + return -1; + } + xfer += ret; + } else { + /* write them separate */ + if ((ret = thrift_protocol_write_byte (THRIFT_PROTOCOL (protocol), + type_to_write, error)) < 0) { + return -1; + } + xfer += ret; + + if ((ret = thrift_protocol_write_i16 (THRIFT_PROTOCOL (protocol), field_id, + error)) < 0) { + return -1; + } + xfer += ret; + } + + protocol->_last_field_id = field_id; + return xfer; +} + +/** + * Method for writing the start of lists and sets. List and sets on + * the wire differ only by the type indicator. + */ +gint32 +thrift_compact_protocol_write_collection_begin (ThriftCompactProtocol *protocol, + const ThriftType elem_type, + guint32 size, GError **error) +{ + gint32 ret; + gint32 xfer; + + xfer = 0; + + if (size <= 14) { + if ((ret = thrift_protocol_write_byte (THRIFT_PROTOCOL (protocol), + (gint8) (size << 4 + | TTypeToCType[elem_type]), + error)) < 0) { + return -1; + } + xfer += ret; + } else { + if ((ret = thrift_protocol_write_byte (THRIFT_PROTOCOL (protocol), + (gint8) (0xf0 + | TTypeToCType[elem_type]), + error)) < 0) { + return -1; + } + xfer += ret; + + if ((ret = thrift_compact_protocol_write_varint32 (protocol, + (guint32) size, + error)) < 0) { + return -1; + } + xfer += ret; + } + + return xfer; +} + +/* + * public methods + */ + +gint32 +thrift_compact_protocol_write_message_begin (ThriftProtocol *protocol, + const gchar *name, + const ThriftMessageType + message_type, + const gint32 seqid, GError **error) +{ + gint8 version; + gint32 ret; + gint32 xfer; + + ThriftCompactProtocol *cp; + + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + + cp = THRIFT_COMPACT_PROTOCOL (protocol); + + version = (VERSION_N & VERSION_MASK) + | (((gint32) message_type << TYPE_SHIFT_AMOUNT) & TYPE_MASK); + xfer = 0; + + if ((ret = thrift_protocol_write_byte (protocol, PROTOCOL_ID, error)) < 0) { + return -1; + } + xfer += ret; + + if ((ret = thrift_protocol_write_byte (protocol, version, error)) < 0) { + return -1; + } + xfer += ret; + + if ((ret = thrift_compact_protocol_write_varint32 (cp, + (guint32) seqid, + error)) < 0) { + return -1; + } + xfer += ret; + + if ((ret = thrift_protocol_write_string (protocol, name, error)) < 0) { + return -1; + } + xfer += ret; + + return xfer; +} + +gint32 +thrift_compact_protocol_write_message_end (ThriftProtocol *protocol, + GError **error) +{ + /* satisfy -Wall */ + THRIFT_UNUSED_VAR (protocol); + THRIFT_UNUSED_VAR (error); + return 0; +} + +gint32 +thrift_compact_protocol_write_struct_begin (ThriftProtocol *protocol, + const gchar *name, + GError **error) +{ + ThriftCompactProtocol *cp; + GQueue *q; + + /* satisfy -Wall */ + THRIFT_UNUSED_VAR (name); + THRIFT_UNUSED_VAR (error); + + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + + cp = THRIFT_COMPACT_PROTOCOL (protocol); + q = &(cp->_last_field); + + g_queue_push_tail (q, GINT_TO_POINTER ((gint) cp->_last_field_id)); + cp->_last_field_id = 0; + return 0; +} + +gint32 +thrift_compact_protocol_write_struct_end (ThriftProtocol *protocol, + GError **error) +{ + ThriftCompactProtocol *cp; + GQueue *q; + + /* satisfy -Wall */ + THRIFT_UNUSED_VAR (error); + + cp = THRIFT_COMPACT_PROTOCOL (protocol); + q = &(cp->_last_field); + + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + + cp->_last_field_id = (gint16) GPOINTER_TO_INT (g_queue_pop_tail (q)); + return 0; +} + +gint32 +thrift_compact_protocol_write_field_begin (ThriftProtocol *protocol, + const gchar *name, + const ThriftType field_type, + const gint16 field_id, + GError **error) +{ + ThriftCompactProtocol *cp; + + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + + cp = THRIFT_COMPACT_PROTOCOL (protocol); + + if (field_type == T_BOOL) { + cp->_bool_field_name = name; + cp->_bool_field_type = field_type; + cp->_bool_field_id = field_id; + return 0; + } else { + return thrift_compact_protocol_write_field_begin_internal (cp, name, + field_type, + field_id, -1, + error); + } +} + +gint32 +thrift_compact_protocol_write_field_end (ThriftProtocol *protocol, + GError **error) +{ + /* satisfy -Wall */ + THRIFT_UNUSED_VAR (protocol); + THRIFT_UNUSED_VAR (error); + return 0; +} + +gint32 +thrift_compact_protocol_write_field_stop (ThriftProtocol *protocol, + GError **error) +{ + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + return thrift_protocol_write_byte (protocol, (gint8) T_STOP, error); +} + +gint32 +thrift_compact_protocol_write_map_begin (ThriftProtocol *protocol, + const ThriftType key_type, + const ThriftType value_type, + const guint32 size, + GError **error) +{ + gint32 ret; + gint32 xfer; + + ThriftCompactProtocol *cp; + + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + + cp = THRIFT_COMPACT_PROTOCOL (protocol); + + xfer = 0; + + if ((ret = thrift_compact_protocol_write_varint32 (cp, (guint32) size, + error)) < 0) { + return -1; + } + xfer += ret; + + if (size > 0) { + if ((ret = thrift_protocol_write_byte (protocol, + (gint8) (TTypeToCType[key_type] << 4 + | TTypeToCType[value_type]), + error)) < 0) { + return -1; + } + xfer += ret; + } + + return xfer; +} + +gint32 +thrift_compact_protocol_write_map_end (ThriftProtocol *protocol, + GError **error) +{ + THRIFT_UNUSED_VAR (protocol); + THRIFT_UNUSED_VAR (error); + return 0; +} + +gint32 +thrift_compact_protocol_write_list_begin (ThriftProtocol *protocol, + const ThriftType element_type, + const guint32 size, + GError **error) +{ + ThriftCompactProtocol *cp; + + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + + cp = THRIFT_COMPACT_PROTOCOL (protocol); + + return thrift_compact_protocol_write_collection_begin (cp, element_type, + size, error); +} + +gint32 +thrift_compact_protocol_write_list_end (ThriftProtocol *protocol, + GError **error) +{ + THRIFT_UNUSED_VAR (protocol); + THRIFT_UNUSED_VAR (error); + return 0; +} + +gint32 +thrift_compact_protocol_write_set_begin (ThriftProtocol *protocol, + const ThriftType element_type, + const guint32 size, + GError **error) +{ + ThriftCompactProtocol *cp; + + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + + cp = THRIFT_COMPACT_PROTOCOL (protocol); + + return thrift_compact_protocol_write_collection_begin (cp, element_type, + size, error); +} + +gint32 +thrift_compact_protocol_write_set_end (ThriftProtocol *protocol, GError **error) +{ + THRIFT_UNUSED_VAR (protocol); + THRIFT_UNUSED_VAR (error); + return 0; +} + +gint32 +thrift_compact_protocol_write_bool (ThriftProtocol *protocol, + const gboolean value, GError **error) +{ + ThriftCompactProtocol *cp; + + gint32 ret; + gint32 xfer; + + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + + cp = THRIFT_COMPACT_PROTOCOL (protocol); + + xfer = 0; + + if (cp->_bool_field_name != NULL) { + /* we haven't written the field header yet */ + if ((ret = thrift_compact_protocol_write_field_begin_internal (cp, + cp->_bool_field_name, + cp->_bool_field_type, + cp->_bool_field_id, + (gint8) (value + ? CT_BOOLEAN_TRUE : CT_BOOLEAN_FALSE), + error)) < 0) { + return -1; + } + xfer += ret; + + cp->_bool_field_name = NULL; + } else { + /* we're not part of a field, so just write the value */ + if ((ret = thrift_protocol_write_byte (protocol, + (gint8) (value ? CT_BOOLEAN_TRUE + : CT_BOOLEAN_FALSE), + error)) < 0) { + return -1; + } + xfer += ret; + } + return xfer; +} + +gint32 +thrift_compact_protocol_write_byte (ThriftProtocol *protocol, const gint8 value, + GError **error) +{ + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + + if (thrift_transport_write (protocol->transport, + (const gpointer) &value, 1, error)) { + return 1; + } else { + return -1; + } +} + +gint32 +thrift_compact_protocol_write_i16 (ThriftProtocol *protocol, const gint16 value, + GError **error) +{ + ThriftCompactProtocol *cp; + + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + + cp = THRIFT_COMPACT_PROTOCOL (protocol); + + return thrift_compact_protocol_write_varint32 (cp, + i32_to_zigzag ((gint32) value), + error); +} + +gint32 +thrift_compact_protocol_write_i32 (ThriftProtocol *protocol, const gint32 value, + GError **error) +{ + ThriftCompactProtocol *cp; + + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + + cp = THRIFT_COMPACT_PROTOCOL (protocol); + + return thrift_compact_protocol_write_varint32 (cp, + i32_to_zigzag (value), + error); +} + +gint32 +thrift_compact_protocol_write_i64 (ThriftProtocol *protocol, const gint64 value, + GError **error) +{ + ThriftCompactProtocol *cp; + + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + + cp = THRIFT_COMPACT_PROTOCOL (protocol); + + return thrift_compact_protocol_write_varint64 (cp, + i64_to_zigzag (value), + error); +} + +gint32 +thrift_compact_protocol_write_double (ThriftProtocol *protocol, + const gdouble value, GError **error) +{ + guint64 bits; + + g_assert (sizeof (gdouble) == sizeof (guint64)); + + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + + bits = GUINT64_TO_LE (thrift_bitwise_cast_guint64 (value)); + if (thrift_transport_write (protocol->transport, + (const gpointer) &bits, 8, error)) { + return 8; + } else { + return -1; + } +} + +gint32 +thrift_compact_protocol_write_string (ThriftProtocol *protocol, + const gchar *str, GError **error) +{ + size_t len; + + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + + len = str != NULL ? strlen (str) : 0; + if (len > G_MAXINT32) { + g_set_error (error, THRIFT_PROTOCOL_ERROR, + THRIFT_PROTOCOL_ERROR_SIZE_LIMIT, + "string size (guess: %lu) is too large", (unsigned long) len); + return -1; + } + + /* write the string length + 1 which includes the null terminator */ + return thrift_protocol_write_binary (protocol, (const gpointer) str, + (const guint32) len, error); +} + +gint32 +thrift_compact_protocol_write_binary (ThriftProtocol *protocol, + const gpointer buf, + const guint32 len, GError **error) +{ + ThriftCompactProtocol *cp; + + gint32 ret; + gint32 xfer; + + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + + cp = THRIFT_COMPACT_PROTOCOL (protocol); + + xfer = 0; + + if ((ret = thrift_compact_protocol_write_varint32 (cp, len, error)) < 0) { + return -1; + } + xfer += ret; + + if (len > 0) { + /* checking len + xfer > uint_max, but we don't want to overflow while + * checking for overflows. transforming to len > uint_max - xfer. + */ + if (len > (guint32) (G_MAXINT32 - xfer)) { + g_set_error (error, THRIFT_PROTOCOL_ERROR, + THRIFT_PROTOCOL_ERROR_SIZE_LIMIT, + "size %d + %d is too large", len, xfer); + return -1; + } + + if (thrift_transport_write (protocol->transport, + (const gpointer) buf, len, error) == FALSE) { + return -1; + } + xfer += len; + } + + return xfer; +} + +gint32 +thrift_compact_protocol_read_message_begin (ThriftProtocol *protocol, + gchar **name, + ThriftMessageType *message_type, + gint32 *seqid, GError **error) +{ + ThriftCompactProtocol *cp; + + gint32 ret; + gint32 xfer; + + gint8 protocol_id, version_and_type, version; + + xfer = 0; + + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + + cp = THRIFT_COMPACT_PROTOCOL (protocol); + + if ((ret = thrift_protocol_read_byte (protocol, &protocol_id, error)) < 0) { + return -1; + } + xfer += ret; + + if (protocol_id != PROTOCOL_ID) { + g_set_error (error, THRIFT_PROTOCOL_ERROR, + THRIFT_PROTOCOL_ERROR_BAD_VERSION, + "bad protocol id"); + return -1; + } + + if ((ret = thrift_protocol_read_byte (protocol, &version_and_type, + error)) < 0) { + return -1; + } + xfer += ret; + + version = (gint8)(version_and_type & VERSION_MASK); + if (version != VERSION_N) { + g_set_error (error, THRIFT_PROTOCOL_ERROR, + THRIFT_PROTOCOL_ERROR_BAD_VERSION, + "bad version and/or type"); + return -1; + } + + *message_type + = (ThriftMessageType)((version_and_type >> TYPE_SHIFT_AMOUNT) & TYPE_BITS); + + if ((ret = thrift_compact_protocol_read_varint32 (cp, seqid, error)) < 0) { + return -1; + } + xfer += ret; + + if ((ret = thrift_protocol_read_string (protocol, name, error)) < 0) { + return -1; + } + xfer += ret; + + return xfer; +} + +gint32 +thrift_compact_protocol_read_message_end (ThriftProtocol *protocol, + GError **error) +{ + THRIFT_UNUSED_VAR (protocol); + THRIFT_UNUSED_VAR (error); + return 0; +} + +gint32 +thrift_compact_protocol_read_struct_begin (ThriftProtocol *protocol, + gchar **name, + GError **error) +{ + ThriftCompactProtocol *cp; + GQueue *q; + + THRIFT_UNUSED_VAR (error); + + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + + cp = THRIFT_COMPACT_PROTOCOL (protocol); + q = &(cp->_last_field); + + *name = NULL; + + g_queue_push_tail (q, GINT_TO_POINTER ((gint) cp->_last_field_id)); + cp->_last_field_id = 0; + + return 0; +} + +gint32 +thrift_compact_protocol_read_struct_end (ThriftProtocol *protocol, + GError **error) +{ + ThriftCompactProtocol *cp; + GQueue *q; + + THRIFT_UNUSED_VAR (error); + + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + + cp = THRIFT_COMPACT_PROTOCOL (protocol); + q = &(cp->_last_field); + + cp->_last_field_id = (gint16) GPOINTER_TO_INT (g_queue_pop_tail (q)); + + return 0; +} + +gint32 +thrift_compact_protocol_read_field_begin (ThriftProtocol *protocol, + gchar **name, + ThriftType *field_type, + gint16 *field_id, + GError **error) +{ + ThriftCompactProtocol *cp; + + gint32 ret; + gint32 xfer; + + gint16 modifier; + gint8 byte; + gint8 type; + + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + + cp = THRIFT_COMPACT_PROTOCOL (protocol); + + THRIFT_UNUSED_VAR (name); + + xfer = 0; + + if ((ret = thrift_protocol_read_byte (protocol, &byte, error)) < 0) { + return -1; + } + xfer += ret; + + type = (byte & 0x0f); + + /* if it's a stop, then we can return immediately, as the struct is over. */ + if (type == T_STOP) { + *field_type = T_STOP; + *field_id = 0; + return xfer; + } + + /* mask off the 4 MSB of the type header. + * it could contain a field id delta. + */ + modifier = (gint16)(((guint8)byte & 0xf0) >> 4); + if (modifier == 0) { + /* not a delta, look ahead for the zigzag varint field id. */ + if ((ret = thrift_protocol_read_i16 (protocol, field_id, error)) < 0) { + return -1; + } + xfer += ret; + } else { + *field_id = (gint16)(cp->_last_field_id + modifier); + } + if ((ret = thrift_compact_protocol_get_ttype (cp, type, error)) < 0) { + return -1; + } + *field_type = ret; + + /* if this happens to be a boolean field, the value is encoded in the type */ + if (type == CT_BOOLEAN_TRUE || type == CT_BOOLEAN_FALSE) { + /* save the boolean value in a special instance variable. */ + cp->_has_bool_value = TRUE; + cp->_bool_value = + (type == CT_BOOLEAN_TRUE ? TRUE : FALSE); + } + + /* push the new field onto the field stack so we can keep the deltas going. */ + cp->_last_field_id = *field_id; + + return xfer; +} + +gint32 +thrift_compact_protocol_read_field_end (ThriftProtocol *protocol, + GError **error) +{ + THRIFT_UNUSED_VAR (protocol); + THRIFT_UNUSED_VAR (error); + return 0; +} + +gint32 +thrift_compact_protocol_read_map_begin (ThriftProtocol *protocol, + ThriftType *key_type, + ThriftType *value_type, + guint32 *size, + GError **error) +{ + gint32 ret; + gint32 xfer; + + gint8 kv_type; + gint32 msize; + + ThriftCompactProtocol *cp; + + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + + kv_type = 0; + msize = 0; + + cp = THRIFT_COMPACT_PROTOCOL (protocol); + + xfer = 0; + + if ((ret = thrift_compact_protocol_read_varint32 (cp, &msize, error)) <0) { + return -1; + } + xfer += ret; + + /* still read the kv byte if negative size */ + if (msize != 0) { + if ((ret = thrift_protocol_read_byte (protocol, &kv_type, error)) < 0) { + return -1; + } + xfer += ret; + } + + if (cp->container_limit > 0 && msize > cp->container_limit) { + g_set_error (error, THRIFT_PROTOCOL_ERROR, + THRIFT_PROTOCOL_ERROR_SIZE_LIMIT, + "got size over limit (%d > %d)", msize, cp->container_limit); + return -1; + } else if (msize > 0) { + if ((ret = thrift_compact_protocol_get_ttype (cp, + (gint8)((guint8)kv_type + >> 4), + error)) < 0) { + return -1; + } + *key_type = ret; + if ((ret = thrift_compact_protocol_get_ttype (cp, + (gint8)((guint8)kv_type + & 0xf), + error)) < 0) { + return -1; + } + *value_type = ret; + *size = (guint32) msize; + } else if (msize == 0) { + *key_type = 0; + *value_type = 0; + *size = 0; + } else { + g_set_error (error, THRIFT_PROTOCOL_ERROR, + THRIFT_PROTOCOL_ERROR_NEGATIVE_SIZE, + "got negative size of %d", msize); + return -1; + } + + return xfer; +} + +gint32 +thrift_compact_protocol_read_map_end (ThriftProtocol *protocol, + GError **error) +{ + THRIFT_UNUSED_VAR (protocol); + THRIFT_UNUSED_VAR (error); + return 0; +} + +gint32 +thrift_compact_protocol_read_list_begin (ThriftProtocol *protocol, + ThriftType *element_type, + guint32 *size, GError **error) +{ + ThriftCompactProtocol *cp; + + gint32 ret; + gint32 xfer; + + gint8 size_and_type; + gint32 lsize; + + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + + cp = THRIFT_COMPACT_PROTOCOL (protocol); + + size_and_type = 0; + + xfer = 0; + + if ((ret = thrift_protocol_read_byte (protocol, &size_and_type, error)) < 0) { + return -1; + } + xfer += ret; + + lsize = ((guint8)size_and_type >> 4) & 0x0f; + if (lsize == 15) { + if ((ret = thrift_compact_protocol_read_varint32 (cp, &lsize, error)) < 0) { + return -1; + } + xfer += ret; + } + + if (lsize < 0) { + g_set_error (error, THRIFT_PROTOCOL_ERROR, + THRIFT_PROTOCOL_ERROR_NEGATIVE_SIZE, + "got negative size of %d", lsize); + return -1; + } else if (cp->container_limit > 0 && lsize > cp->container_limit) { + g_set_error (error, THRIFT_PROTOCOL_ERROR, + THRIFT_PROTOCOL_ERROR_SIZE_LIMIT, + "got size over limit (%d > %d)", lsize, cp->container_limit); + return -1; + } + + if ((ret = thrift_compact_protocol_get_ttype (cp, + (gint8)(size_and_type & 0x0f), + error)) < 0) { + return -1; + } + *element_type = ret; + *size = (guint32) lsize; + + return xfer; +} + +gint32 +thrift_compact_protocol_read_list_end (ThriftProtocol *protocol, + GError **error) +{ + THRIFT_UNUSED_VAR (protocol); + THRIFT_UNUSED_VAR (error); + return 0; +} + +gint32 +thrift_compact_protocol_read_set_begin (ThriftProtocol *protocol, + ThriftType *element_type, + guint32 *size, GError **error) +{ + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + + return thrift_protocol_read_list_begin (protocol, element_type, size, error); +} + +gint32 +thrift_compact_protocol_read_set_end (ThriftProtocol *protocol, + GError **error) +{ + THRIFT_UNUSED_VAR (protocol); + THRIFT_UNUSED_VAR (error); + return 0; +} + +gint32 +thrift_compact_protocol_read_bool (ThriftProtocol *protocol, gboolean *value, + GError **error) +{ + ThriftCompactProtocol *cp; + + gint32 ret; + gint32 xfer; + + gint8 val; + + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + + cp = THRIFT_COMPACT_PROTOCOL (protocol); + + xfer = 0; + + if (cp->_has_bool_value == TRUE) { + *value = cp->_bool_value; + cp->_has_bool_value = FALSE; + return 0; + } else { + if ((ret = thrift_protocol_read_byte (protocol, &val, error)) < 0) { + return -1; + } + xfer += ret; + + *value = (val == CT_BOOLEAN_TRUE); + return xfer; + } +} + +gint32 +thrift_compact_protocol_read_byte (ThriftProtocol *protocol, gint8 *value, + GError **error) +{ + gint32 ret; + gpointer b[1]; + + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + + if ((ret = + thrift_transport_read_all (protocol->transport, + b, 1, error)) < 0) { + return -1; + } + *value = *(gint8 *) b; + return ret; +} + +gint32 +thrift_compact_protocol_read_i16 (ThriftProtocol *protocol, gint16 *value, + GError **error) +{ + ThriftCompactProtocol *cp; + + gint32 ret; + gint32 val; + gint32 xfer; + + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + + cp = THRIFT_COMPACT_PROTOCOL (protocol); + + xfer = 0; + + if ((ret = thrift_compact_protocol_read_varint32 (cp, &val, error)) < 0) { + return -1; + } + xfer += ret; + + *value = (gint16) zigzag_to_i32 ((guint32) val); + + return xfer; +} + +gint32 +thrift_compact_protocol_read_i32 (ThriftProtocol *protocol, gint32 *value, + GError **error) +{ + ThriftCompactProtocol *cp; + + gint32 ret; + gint32 val; + gint32 xfer; + + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + + cp = THRIFT_COMPACT_PROTOCOL (protocol); + + xfer = 0; + + if ((ret = thrift_compact_protocol_read_varint32 (cp, &val, error)) < 0) { + return -1; + } + xfer += ret; + + *value = zigzag_to_i32 ((guint32) val); + + return xfer; +} + +gint32 +thrift_compact_protocol_read_i64 (ThriftProtocol *protocol, gint64 *value, + GError **error) +{ + ThriftCompactProtocol *cp; + + gint32 ret; + gint64 val; + gint32 xfer; + + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + + cp = THRIFT_COMPACT_PROTOCOL (protocol); + + xfer = 0; + + if ((ret = thrift_compact_protocol_read_varint64 (cp, &val, error)) < 0) { + return -1; + } + xfer += ret; + + *value = zigzag_to_i64 ((guint64) val); + + return xfer; +} + +gint32 +thrift_compact_protocol_read_double (ThriftProtocol *protocol, + gdouble *value, GError **error) +{ + gint32 ret; + union { + guint64 bits; + guint8 b[8]; + } u; + + g_assert (sizeof (gdouble) == sizeof (guint64)); + + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + + if ((ret = + thrift_transport_read_all (protocol->transport, + u.b, 8, error)) < 0) { + return -1; + } + u.bits = GUINT64_FROM_LE (u.bits); + *value = thrift_bitwise_cast_gdouble (u.bits); + return ret; +} + +gint32 +thrift_compact_protocol_read_string (ThriftProtocol *protocol, + gchar **str, GError **error) +{ + ThriftCompactProtocol *cp; + + gint32 ret; + gint32 xfer; + + gint32 read_len; + + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + + cp = THRIFT_COMPACT_PROTOCOL (protocol); + + xfer = 0; + read_len = 0; + + /* read the length into read_len */ + if ((ret = + thrift_compact_protocol_read_varint32 (cp, &read_len, error)) < 0) { + return -1; + } + xfer += ret; + + if (cp->string_limit > 0 && read_len > cp->string_limit) { + g_set_error (error, THRIFT_PROTOCOL_ERROR, + THRIFT_PROTOCOL_ERROR_SIZE_LIMIT, + "got size over limit (%d > %d)", read_len, cp->string_limit); + *str = NULL; + 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) { + if ((ret = + thrift_transport_read_all (protocol->transport, + *str, read_len, error)) < 0) { + g_free (*str); + *str = NULL; + return -1; + } + xfer += ret; + } else { + **str = 0; + } + + return xfer; +} + +gint32 +thrift_compact_protocol_read_binary (ThriftProtocol *protocol, + gpointer *buf, guint32 *len, + GError **error) +{ + ThriftCompactProtocol *cp; + + gint32 ret; + gint32 xfer; + + gint32 read_len; + + g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); + + cp = THRIFT_COMPACT_PROTOCOL (protocol); + + xfer = 0; + read_len = 0; + + /* read the length into read_len */ + if ((ret = + thrift_compact_protocol_read_varint32 (cp, &read_len, error)) < 0) { + return -1; + } + xfer += ret; + + if (cp->string_limit > 0 && read_len > cp->string_limit) { + g_set_error (error, THRIFT_PROTOCOL_ERROR, + THRIFT_PROTOCOL_ERROR_SIZE_LIMIT, + "got size over limit (%d > %d)", read_len, cp->string_limit); + *buf = NULL; + *len = 0; + return -1; + } + + if (read_len > 0) { + /* allocate the memory as an array of unsigned char for binary data */ + *len = (guint32) read_len; + *buf = g_new (guchar, *len); + if ((ret = + thrift_transport_read_all (protocol->transport, + *buf, *len, error)) < 0) { + g_free (*buf); + *buf = NULL; + *len = 0; + return -1; + } + xfer += ret; + + } else if (read_len == 0) { + *len = (guint32) read_len; + *buf = NULL; + + } else { + g_set_error (error, THRIFT_PROTOCOL_ERROR, + THRIFT_PROTOCOL_ERROR_NEGATIVE_SIZE, + "got negative size of %d", read_len); + *buf = NULL; + *len = 0; + return -1; + } + + return xfer; +} + +/* property accessor */ +void +thrift_compact_protocol_get_property (GObject *object, guint property_id, + GValue *value, GParamSpec *pspec) +{ + ThriftCompactProtocol *tc; + + THRIFT_UNUSED_VAR (pspec); + + tc = THRIFT_COMPACT_PROTOCOL (object); + + switch (property_id) { + case PROP_THRIFT_COMPACT_PROTOCOL_STRING_LIMIT: + g_value_set_int (value, tc->string_limit); + break; + case PROP_THRIFT_COMPACT_PROTOCOL_CONTAINER_LIMIT: + g_value_set_int (value, tc->container_limit); + break; + } +} + +/* property mutator */ +void +thrift_compact_protocol_set_property (GObject *object, guint property_id, + const GValue *value, GParamSpec *pspec) +{ + ThriftCompactProtocol *tc; + + THRIFT_UNUSED_VAR (pspec); + + tc = THRIFT_COMPACT_PROTOCOL (object); + + switch (property_id) { + case PROP_THRIFT_COMPACT_PROTOCOL_STRING_LIMIT: + tc->string_limit = g_value_get_int (value); + break; + case PROP_THRIFT_COMPACT_PROTOCOL_CONTAINER_LIMIT: + tc->container_limit = g_value_get_int (value); + break; + } +} + +/* initialize the class */ +static void +thrift_compact_protocol_class_init (ThriftCompactProtocolClass *klass) +{ + ThriftProtocolClass *cls; + GObjectClass *gobject_class; + GParamSpec *param_spec; + + cls = THRIFT_PROTOCOL_CLASS (klass); + gobject_class = G_OBJECT_CLASS (klass); + param_spec = NULL; + + /* setup accessors and mutators */ + gobject_class->get_property = thrift_compact_protocol_get_property; + gobject_class->set_property = thrift_compact_protocol_set_property; + + param_spec = g_param_spec_int ("string_limit", + "Max allowed string size", + "Set the max string limit", + 0, /* min */ + G_MAXINT32, /* max */ + 0, /* default value */ + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE); + g_object_class_install_property (gobject_class, + PROP_THRIFT_COMPACT_PROTOCOL_STRING_LIMIT, + param_spec); + + param_spec = g_param_spec_int ("container_limit", + "Max allowed container size", + "Set the max container limit", + 0, /* min */ + G_MAXINT32, /* max */ + 0, /* default value */ + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE); + g_object_class_install_property (gobject_class, + PROP_THRIFT_COMPACT_PROTOCOL_CONTAINER_LIMIT, + param_spec); + + cls->write_message_begin = thrift_compact_protocol_write_message_begin; + cls->write_message_end = thrift_compact_protocol_write_message_end; + cls->write_struct_begin = thrift_compact_protocol_write_struct_begin; + cls->write_struct_end = thrift_compact_protocol_write_struct_end; + cls->write_field_begin = thrift_compact_protocol_write_field_begin; + cls->write_field_end = thrift_compact_protocol_write_field_end; + cls->write_field_stop = thrift_compact_protocol_write_field_stop; + cls->write_map_begin = thrift_compact_protocol_write_map_begin; + cls->write_map_end = thrift_compact_protocol_write_map_end; + cls->write_list_begin = thrift_compact_protocol_write_list_begin; + cls->write_list_end = thrift_compact_protocol_write_list_end; + cls->write_set_begin = thrift_compact_protocol_write_set_begin; + cls->write_set_end = thrift_compact_protocol_write_set_end; + cls->write_bool = thrift_compact_protocol_write_bool; + cls->write_byte = thrift_compact_protocol_write_byte; + cls->write_i16 = thrift_compact_protocol_write_i16; + cls->write_i32 = thrift_compact_protocol_write_i32; + cls->write_i64 = thrift_compact_protocol_write_i64; + cls->write_double = thrift_compact_protocol_write_double; + cls->write_string = thrift_compact_protocol_write_string; + cls->write_binary = thrift_compact_protocol_write_binary; + cls->read_message_begin = thrift_compact_protocol_read_message_begin; + cls->read_message_end = thrift_compact_protocol_read_message_end; + cls->read_struct_begin = thrift_compact_protocol_read_struct_begin; + cls->read_struct_end = thrift_compact_protocol_read_struct_end; + cls->read_field_begin = thrift_compact_protocol_read_field_begin; + cls->read_field_end = thrift_compact_protocol_read_field_end; + cls->read_map_begin = thrift_compact_protocol_read_map_begin; + cls->read_map_end = thrift_compact_protocol_read_map_end; + cls->read_list_begin = thrift_compact_protocol_read_list_begin; + cls->read_list_end = thrift_compact_protocol_read_list_end; + cls->read_set_begin = thrift_compact_protocol_read_set_begin; + cls->read_set_end = thrift_compact_protocol_read_set_end; + cls->read_bool = thrift_compact_protocol_read_bool; + cls->read_byte = thrift_compact_protocol_read_byte; + cls->read_i16 = thrift_compact_protocol_read_i16; + cls->read_i32 = thrift_compact_protocol_read_i32; + cls->read_i64 = thrift_compact_protocol_read_i64; + cls->read_double = thrift_compact_protocol_read_double; + cls->read_string = thrift_compact_protocol_read_string; + cls->read_binary = thrift_compact_protocol_read_binary; +} + +static void +thrift_compact_protocol_init (ThriftCompactProtocol *self) +{ + g_queue_init (&(self->_last_field)); +} diff --git a/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_compact_protocol.h b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_compact_protocol.h new file mode 100644 index 000000000..effcaadf0 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_compact_protocol.h @@ -0,0 +1,107 @@ +/* + * 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_COMPACT_PROTOCOL_H +#define _THRIFT_COMPACT_PROTOCOL_H + +#include <glib.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_compact_protocol.h + * \brief Compact protocol implementation of a Thrift protocol. Implements the + * ThriftProtocol interface. + */ + +/* type macros */ +#define THRIFT_TYPE_COMPACT_PROTOCOL (thrift_compact_protocol_get_type ()) +#define THRIFT_COMPACT_PROTOCOL(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), THRIFT_TYPE_COMPACT_PROTOCOL, \ + ThriftCompactProtocol)) +#define THRIFT_IS_COMPACT_PROTOCOL(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THRIFT_TYPE_COMPACT_PROTOCOL)) +#define THRIFT_COMPACT_PROTOCOL_CLASS(c) \ + (G_TYPE_CHECK_CLASS_CAST ((c), THRIFT_TYPE_COMPACT_PROTOCOL, \ + ThriftCompactProtocolClass)) +#define THRIFT_IS_COMPACT_PROTOCOL_CLASS(c) \ + (G_TYPE_CHECK_CLASS_TYPE ((c), THRIFT_TYPE_COMPACT_PROTOCOL)) +#define THRIFT_COMPACT_PROTOCOL_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), THRIFT_TYPE_COMPACT_PROTOCOL, \ + ThriftCompactProtocolClass)) + + +typedef struct _ThriftCompactProtocol ThriftCompactProtocol; + +/*! + * Thrift Compact Protocol instance. + */ +struct _ThriftCompactProtocol +{ + ThriftProtocol parent; + + /* protected */ + gint32 string_limit; + gint32 container_limit; + + /* private */ + + /** + * (Writing) If we encounter a boolean field begin, save the TField here + * so it can have the value incorporated. + */ + const gchar* _bool_field_name; + ThriftType _bool_field_type; + gint16 _bool_field_id; + + /** + * (Reading) If we read a field header, and it's a boolean field, save + * the boolean value here so that read_bool can use it. + */ + gboolean _has_bool_value; + gboolean _bool_value; + + /** + * Used to keep track of the last field for the current and previous structs, + * so we can do the delta stuff. + */ + + GQueue _last_field; + gint16 _last_field_id; +}; + +typedef struct _ThriftCompactProtocolClass ThriftCompactProtocolClass; + +/*! + * Thrift Compact Protocol class. + */ +struct _ThriftCompactProtocolClass +{ + ThriftProtocolClass parent; +}; + +/* used by THRIFT_TYPE_COMPACT_PROTOCOL */ +GType thrift_compact_protocol_get_type (void); + +G_END_DECLS + +#endif /* _THRIFT_COMPACT_PROTOCOL_H */ diff --git a/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_compact_protocol_factory.c b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_compact_protocol_factory.c new file mode 100644 index 000000000..e725e1fd0 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_compact_protocol_factory.c @@ -0,0 +1,140 @@ +/* + * 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 <thrift/c_glib/thrift.h> +#include <thrift/c_glib/protocol/thrift_compact_protocol.h> +#include <thrift/c_glib/protocol/thrift_compact_protocol_factory.h> + +/* object properties */ +enum _ThriftCompactProtocolFactoryProperties +{ + PROP_0, + PROP_THRIFT_COMPACT_PROTOCOL_FACTORY_STRING_LIMIT, + PROP_THRIFT_COMPACT_PROTOCOL_FACTORY_CONTAINER_LIMIT +}; + +G_DEFINE_TYPE (ThriftCompactProtocolFactory, thrift_compact_protocol_factory, + THRIFT_TYPE_PROTOCOL_FACTORY) + +ThriftProtocol * +thrift_compact_protocol_factory_get_protocol (ThriftProtocolFactory *factory, + ThriftTransport *transport) +{ + ThriftCompactProtocolFactory *tcf; + ThriftCompactProtocol *tc; + + tcf = THRIFT_COMPACT_PROTOCOL_FACTORY (factory); + + tc = g_object_new (THRIFT_TYPE_COMPACT_PROTOCOL, + "transport", transport, + "string_limit", tcf->string_limit, + "container_limit", tcf->container_limit, + NULL); + + return THRIFT_PROTOCOL (tc); +} + +/* property accessor */ +void +thrift_compact_protocol_factory_get_property (GObject *object, guint property_id, + GValue *value, GParamSpec *pspec) +{ + ThriftCompactProtocolFactory *tcf; + + THRIFT_UNUSED_VAR (pspec); + + tcf = THRIFT_COMPACT_PROTOCOL_FACTORY (object); + + switch (property_id) { + case PROP_THRIFT_COMPACT_PROTOCOL_FACTORY_STRING_LIMIT: + g_value_set_int (value, tcf->string_limit); + break; + case PROP_THRIFT_COMPACT_PROTOCOL_FACTORY_CONTAINER_LIMIT: + g_value_set_int (value, tcf->container_limit); + break; + } +} + +/* property mutator */ +void +thrift_compact_protocol_factory_set_property (GObject *object, guint property_id, + const GValue *value, GParamSpec + *pspec) +{ + ThriftCompactProtocolFactory *tcf; + + THRIFT_UNUSED_VAR (pspec); + + tcf = THRIFT_COMPACT_PROTOCOL_FACTORY (object); + + switch (property_id) { + case PROP_THRIFT_COMPACT_PROTOCOL_FACTORY_STRING_LIMIT: + tcf->string_limit = g_value_get_int (value); + break; + case PROP_THRIFT_COMPACT_PROTOCOL_FACTORY_CONTAINER_LIMIT: + tcf->container_limit = g_value_get_int (value); + break; + } +} + +static void +thrift_compact_protocol_factory_class_init (ThriftCompactProtocolFactoryClass + *klass) +{ + ThriftProtocolFactoryClass *cls; + GObjectClass *gobject_class; + GParamSpec *param_spec; + + cls = THRIFT_PROTOCOL_FACTORY_CLASS (klass); + gobject_class = G_OBJECT_CLASS (klass); + param_spec = NULL; + + /* setup accessors and mutators */ + gobject_class->get_property = thrift_compact_protocol_factory_get_property; + gobject_class->set_property = thrift_compact_protocol_factory_set_property; + + param_spec = g_param_spec_int ("string_limit", + "Max allowed string size", + "Set the max string limit", + 0, /* min */ + G_MAXINT32, /* max */ + 0, /* default value */ + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE); + g_object_class_install_property (gobject_class, + PROP_THRIFT_COMPACT_PROTOCOL_FACTORY_STRING_LIMIT, + param_spec); + + param_spec = g_param_spec_int ("container_limit", + "Max allowed container size", + "Set the max container limit", + 0, /* min */ + G_MAXINT32, /* max */ + 0, /* default value */ + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE); + g_object_class_install_property (gobject_class, + PROP_THRIFT_COMPACT_PROTOCOL_FACTORY_CONTAINER_LIMIT, param_spec); + + cls->get_protocol = thrift_compact_protocol_factory_get_protocol; +} + +static void +thrift_compact_protocol_factory_init (ThriftCompactProtocolFactory *factory) +{ + THRIFT_UNUSED_VAR (factory); +} diff --git a/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_compact_protocol_factory.h b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_compact_protocol_factory.h new file mode 100644 index 000000000..3bf953b4c --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_compact_protocol_factory.h @@ -0,0 +1,70 @@ +/* + * 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_COMPACT_PROTOCOL_FACTORY_H +#define _THRIFT_COMPACT_PROTOCOL_FACTORY_H + +#include <glib-object.h> + +#include <thrift/c_glib/protocol/thrift_protocol_factory.h> + +G_BEGIN_DECLS + +/* type macros */ +#define THRIFT_TYPE_COMPACT_PROTOCOL_FACTORY \ + (thrift_compact_protocol_factory_get_type ()) +#define THRIFT_COMPACT_PROTOCOL_FACTORY(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), THRIFT_TYPE_COMPACT_PROTOCOL_FACTORY, \ + ThriftCompactProtocolFactory)) +#define THRIFT_IS_COMPACT_PROTOCOL_FACTORY(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THRIFT_TYPE_COMPACT_PROTOCOL_FACTORY)) +#define THRIFT_COMPACT_PROTOCOL_FACTORY_CLASS(c) \ + (G_TYPE_CHECK_CLASS_CAST ((c), THRIFT_TYPE_COMPACT_PROTOCOL_FACTORY, \ + ThriftCompactProtocolFactoryClass)) +#define THRIFT_IS_COMPACT_PROTOCOL_FACTORY_CLASS(c) \ + (G_TYPE_CHECK_CLASS_TYPE ((c), THRIFT_TYPE_COMPACT_PROTOCOL_FACTORY)) +#define THRIFT_COMPACT_PROTOCOL_FACTORY_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), THRIFT_TYPE_COMPACT_PROTOCOL_FACTORY, \ + ThriftCompactProtocolFactoryClass)) + +typedef struct _ThriftCompactProtocolFactory ThriftCompactProtocolFactory; + +struct _ThriftCompactProtocolFactory +{ + ThriftProtocolFactory parent; + + /* protected */ + gint32 string_limit; + gint32 container_limit; +}; + +typedef struct _ThriftCompactProtocolFactoryClass + ThriftCompactProtocolFactoryClass; + +struct _ThriftCompactProtocolFactoryClass +{ + ThriftProtocolFactoryClass parent; +}; + +/* used by THRIFT_TYPE_COMPACT_PROTOCOL_FACTORY */ +GType thrift_compact_protocol_factory_get_type (void); + +G_END_DECLS + +#endif /* _THRIFT_COMPACT_PROTOCOL_FACTORY_H */ diff --git a/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_multiplexed_protocol.c b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_multiplexed_protocol.c new file mode 100644 index 000000000..5084ead47 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_multiplexed_protocol.c @@ -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); + + 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: + g_free(self->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); +} diff --git a/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_multiplexed_protocol.h b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_multiplexed_protocol.h new file mode 100644 index 000000000..c6e08fb19 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_multiplexed_protocol.h @@ -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 */ diff --git a/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_protocol.c b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_protocol.c new file mode 100644 index 000000000..6e6ae4d9a --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_protocol.c @@ -0,0 +1,646 @@ +/* + * 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 <thrift/c_glib/thrift.h> +#include <thrift/c_glib/protocol/thrift_protocol.h> +#include <thrift/c_glib/transport/thrift_transport.h> + +/* define the GError domain string */ +#define THRIFT_PROTOCOL_ERROR_DOMAIN "thrift-protocol-error-quark" + +/* object properties */ +enum _ThriftProtocolProperties +{ + PROP_0, + PROP_THRIFT_PROTOCOL_TRANSPORT +}; + +G_DEFINE_ABSTRACT_TYPE(ThriftProtocol, thrift_protocol, G_TYPE_OBJECT) + +void +thrift_protocol_get_property (GObject *object, guint property_id, + GValue *value, GParamSpec *pspec) +{ + ThriftProtocol *protocol = THRIFT_PROTOCOL (object); + + THRIFT_UNUSED_VAR (pspec); + + switch (property_id) + { + case PROP_THRIFT_PROTOCOL_TRANSPORT: + g_value_set_object (value, protocol->transport); + break; + } +} + +void +thrift_protocol_set_property (GObject *object, guint property_id, + const GValue *value, GParamSpec *pspec) +{ + + ThriftProtocol *protocol = THRIFT_PROTOCOL (object); + + THRIFT_UNUSED_VAR (pspec); + + switch (property_id) + { + case PROP_THRIFT_PROTOCOL_TRANSPORT: + protocol->transport = g_value_dup_object (value); + break; + } +} + + +gint32 +thrift_protocol_write_message_begin (ThriftProtocol *protocol, + const gchar *name, + const ThriftMessageType message_type, + const gint32 seqid, GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_message_begin + (protocol, name, + message_type, seqid, + error); +} + +gint32 +thrift_protocol_write_message_end (ThriftProtocol *protocol, GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_message_end (protocol, + error); +} + +gint32 +thrift_protocol_write_struct_begin (ThriftProtocol *protocol, const gchar *name, + GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_struct_begin (protocol, + name, error); +} + +gint32 +thrift_protocol_write_struct_end (ThriftProtocol *protocol, GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_struct_end (protocol, + error); +} + +gint32 +thrift_protocol_write_field_begin (ThriftProtocol *protocol, + const gchar *name, + const ThriftType field_type, + const gint16 field_id, + GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_field_begin (protocol, + name, field_type, + field_id, error); +} + +gint32 +thrift_protocol_write_field_end (ThriftProtocol *protocol, GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_field_end (protocol, + error); +} + +gint32 +thrift_protocol_write_field_stop (ThriftProtocol *protocol, GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_field_stop (protocol, + error); +} + +gint32 +thrift_protocol_write_map_begin (ThriftProtocol *protocol, + const ThriftType key_type, + const ThriftType value_type, + const guint32 size, GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_map_begin (protocol, + key_type, value_type, + size, error); +} + +gint32 +thrift_protocol_write_map_end (ThriftProtocol *protocol, GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_map_end (protocol, + error); +} + +gint32 +thrift_protocol_write_list_begin (ThriftProtocol *protocol, + const ThriftType element_type, + const guint32 size, GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_list_begin (protocol, + element_type, size, + error); +} + +gint32 +thrift_protocol_write_list_end (ThriftProtocol *protocol, GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_list_end (protocol, + error); +} + +gint32 +thrift_protocol_write_set_begin (ThriftProtocol *protocol, + const ThriftType element_type, + const guint32 size, GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_set_begin (protocol, + element_type, size, + error); +} + +gint32 +thrift_protocol_write_set_end (ThriftProtocol *protocol, GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_set_end (protocol, + error); +} + +gint32 +thrift_protocol_write_bool (ThriftProtocol *protocol, + const gboolean value, GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_bool (protocol, value, + error); +} + +gint32 +thrift_protocol_write_byte (ThriftProtocol *protocol, const gint8 value, + GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_byte (protocol, value, + error); +} + +gint32 +thrift_protocol_write_i16 (ThriftProtocol *protocol, const gint16 value, + GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_i16 (protocol, value, + error); +} + +gint32 +thrift_protocol_write_i32 (ThriftProtocol *protocol, const gint32 value, + GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_i32 (protocol, value, + error); +} + +gint32 +thrift_protocol_write_i64 (ThriftProtocol *protocol, const gint64 value, + GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_i64 (protocol, value, + error); +} + +gint32 +thrift_protocol_write_double (ThriftProtocol *protocol, + const gdouble value, GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_double (protocol, + value, error); +} + +gint32 +thrift_protocol_write_string (ThriftProtocol *protocol, + const gchar *str, GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_string (protocol, str, + error); +} + +gint32 +thrift_protocol_write_binary (ThriftProtocol *protocol, const gpointer buf, + const guint32 len, GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->write_binary (protocol, buf, + len, error); +} + +gint32 +thrift_protocol_read_message_begin (ThriftProtocol *protocol, + gchar **name, + ThriftMessageType *message_type, + gint32 *seqid, GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_message_begin (protocol, + name, message_type, + seqid, error); +} + +gint32 +thrift_protocol_read_message_end (ThriftProtocol *protocol, + GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_message_end (protocol, + error); +} + +gint32 +thrift_protocol_read_struct_begin (ThriftProtocol *protocol, + gchar **name, + GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_struct_begin (protocol, + name, + error); +} + +gint32 +thrift_protocol_read_struct_end (ThriftProtocol *protocol, GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_struct_end (protocol, + error); +} + +gint32 +thrift_protocol_read_field_begin (ThriftProtocol *protocol, + gchar **name, + ThriftType *field_type, + gint16 *field_id, + GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_field_begin (protocol, + name, + field_type, + field_id, + error); +} + +gint32 +thrift_protocol_read_field_end (ThriftProtocol *protocol, + GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_field_end (protocol, + error); +} + +gint32 +thrift_protocol_read_map_begin (ThriftProtocol *protocol, + ThriftType *key_type, + ThriftType *value_type, guint32 *size, + GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_map_begin (protocol, + key_type, + value_type, + size, + error); +} + +gint32 +thrift_protocol_read_map_end (ThriftProtocol *protocol, GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_map_end (protocol, + error); +} + +gint32 +thrift_protocol_read_list_begin (ThriftProtocol *protocol, + ThriftType *element_type, + guint32 *size, GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_list_begin (protocol, + element_type, + size, error); +} + +gint32 +thrift_protocol_read_list_end (ThriftProtocol *protocol, GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_list_end (protocol, + error); +} + +gint32 +thrift_protocol_read_set_begin (ThriftProtocol *protocol, + ThriftType *element_type, + guint32 *size, GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_set_begin (protocol, + element_type, + size, error); +} + +gint32 +thrift_protocol_read_set_end (ThriftProtocol *protocol, GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_set_end (protocol, + error); +} + +gint32 +thrift_protocol_read_bool (ThriftProtocol *protocol, gboolean *value, + GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_bool (protocol, value, + error); +} + +gint32 +thrift_protocol_read_byte (ThriftProtocol *protocol, gint8 *value, + GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_byte (protocol, value, + error); +} + +gint32 +thrift_protocol_read_i16 (ThriftProtocol *protocol, gint16 *value, + GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_i16 (protocol, value, + error); +} + +gint32 +thrift_protocol_read_i32 (ThriftProtocol *protocol, gint32 *value, + GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_i32 (protocol, value, + error); +} + +gint32 +thrift_protocol_read_i64 (ThriftProtocol *protocol, gint64 *value, + GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_i64 (protocol, value, + error); +} + +gint32 +thrift_protocol_read_double (ThriftProtocol *protocol, + gdouble *value, GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_double (protocol, value, + error); +} + +gint32 +thrift_protocol_read_string (ThriftProtocol *protocol, + gchar **str, GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_string (protocol, str, + error); +} + +gint32 +thrift_protocol_read_binary (ThriftProtocol *protocol, gpointer *buf, + guint32 *len, GError **error) +{ + return THRIFT_PROTOCOL_GET_CLASS (protocol)->read_binary (protocol, buf, + len, error); +} + +#define THRIFT_SKIP_RESULT_OR_RETURN(_RES, _CALL) \ + { \ + gint32 _x = (_CALL); \ + if (_x < 0) { return _x; } \ + (_RES) += _x; \ + } + +gint32 +thrift_protocol_skip (ThriftProtocol *protocol, ThriftType type, GError **error) +{ + switch (type) + { + case T_BOOL: + { + gboolean boolv; + return thrift_protocol_read_bool (protocol, &boolv, error); + } + case T_BYTE: + { + gint8 bytev; + return thrift_protocol_read_byte (protocol, &bytev, error); + } + + case T_I16: + { + gint16 i16; + return thrift_protocol_read_i16 (protocol, &i16, error); + } + case T_I32: + { + gint32 i32; + return thrift_protocol_read_i32 (protocol, &i32, error); + } + case T_I64: + { + gint64 i64; + return thrift_protocol_read_i64 (protocol, &i64, error); + } + case T_DOUBLE: + { + gdouble dub; + return thrift_protocol_read_double (protocol, &dub, error); + } + case T_STRING: + { + gpointer data; + guint32 len; + gint32 ret = thrift_protocol_read_binary (protocol, &data, &len, error); + g_free (data); + return ret; + } + case T_STRUCT: + { + gint32 result = 0; + gchar *name; + gint16 fid; + ThriftType ftype; + THRIFT_SKIP_RESULT_OR_RETURN(result, + thrift_protocol_read_struct_begin (protocol, &name, error)) + while (1) + { + THRIFT_SKIP_RESULT_OR_RETURN(result, + thrift_protocol_read_field_begin (protocol, &name, &ftype, + &fid, error)) + if (ftype == T_STOP) + { + break; + } + THRIFT_SKIP_RESULT_OR_RETURN(result, + thrift_protocol_skip (protocol, ftype, error)) + THRIFT_SKIP_RESULT_OR_RETURN(result, + thrift_protocol_read_field_end (protocol, error)) + } + THRIFT_SKIP_RESULT_OR_RETURN(result, + thrift_protocol_read_struct_end (protocol, error)) + return result; + } + case T_SET: + { + gint32 result = 0; + ThriftType elem_type; + guint32 i, size; + THRIFT_SKIP_RESULT_OR_RETURN(result, + thrift_protocol_read_set_begin (protocol, &elem_type, &size, + error)) + for (i = 0; i < size; i++) + { + THRIFT_SKIP_RESULT_OR_RETURN(result, + thrift_protocol_skip (protocol, elem_type, error)) + } + THRIFT_SKIP_RESULT_OR_RETURN(result, + thrift_protocol_read_set_end (protocol, error)) + return result; + } + case T_MAP: + { + gint32 result = 0; + ThriftType elem_type; + ThriftType key_type; + guint32 i, size; + THRIFT_SKIP_RESULT_OR_RETURN(result, + thrift_protocol_read_map_begin (protocol, &key_type, &elem_type, &size, + error)) + for (i = 0; i < size; i++) + { + THRIFT_SKIP_RESULT_OR_RETURN(result, + thrift_protocol_skip (protocol, key_type, error)) + THRIFT_SKIP_RESULT_OR_RETURN(result, + thrift_protocol_skip (protocol, elem_type, error)) + } + THRIFT_SKIP_RESULT_OR_RETURN(result, + thrift_protocol_read_map_end (protocol, error)) + return result; + } + case T_LIST: + { + gint32 result = 0; + ThriftType elem_type; + guint32 i, size; + THRIFT_SKIP_RESULT_OR_RETURN(result, + thrift_protocol_read_list_begin (protocol, &elem_type, &size, + error)) + for (i = 0; i < size; i++) + { + THRIFT_SKIP_RESULT_OR_RETURN(result, + thrift_protocol_skip (protocol, elem_type, error)) + } + THRIFT_SKIP_RESULT_OR_RETURN(result, + thrift_protocol_read_list_end (protocol, error)) + return result; + } + default: + break; + } + + g_set_error (error, THRIFT_PROTOCOL_ERROR, + THRIFT_PROTOCOL_ERROR_INVALID_DATA, + "unrecognized type"); + return -1; +} + +/* define the GError domain for Thrift protocols */ +GQuark +thrift_protocol_error_quark (void) +{ + return g_quark_from_static_string (THRIFT_PROTOCOL_ERROR_DOMAIN); +} + + +static void +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) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (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, + g_param_spec_object ("transport", "Transport", "Thrift Transport", + THRIFT_TYPE_TRANSPORT, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + cls->write_message_begin = thrift_protocol_write_message_begin; + cls->write_message_end = thrift_protocol_write_message_end; + cls->write_struct_begin = thrift_protocol_write_struct_begin; + cls->write_struct_end = thrift_protocol_write_struct_end; + cls->write_field_begin = thrift_protocol_write_field_begin; + cls->write_field_end = thrift_protocol_write_field_end; + cls->write_field_stop = thrift_protocol_write_field_stop; + cls->write_map_begin = thrift_protocol_write_map_begin; + cls->write_map_end = thrift_protocol_write_map_end; + cls->write_list_begin = thrift_protocol_write_list_begin; + cls->write_list_end = thrift_protocol_write_list_end; + cls->write_set_begin = thrift_protocol_write_set_begin; + cls->write_set_end = thrift_protocol_write_set_end; + cls->write_bool = thrift_protocol_write_bool; + cls->write_byte = thrift_protocol_write_byte; + cls->write_i16 = thrift_protocol_write_i16; + cls->write_i32 = thrift_protocol_write_i32; + cls->write_i64 = thrift_protocol_write_i64; + cls->write_double = thrift_protocol_write_double; + cls->write_string = thrift_protocol_write_string; + cls->write_binary = thrift_protocol_write_binary; + cls->read_message_begin = thrift_protocol_read_message_begin; + cls->read_message_end = thrift_protocol_read_message_end; + cls->read_struct_begin = thrift_protocol_read_struct_begin; + cls->read_struct_end = thrift_protocol_read_struct_end; + cls->read_field_begin = thrift_protocol_read_field_begin; + cls->read_field_end = thrift_protocol_read_field_end; + cls->read_map_begin = thrift_protocol_read_map_begin; + cls->read_map_end = thrift_protocol_read_map_end; + cls->read_list_begin = thrift_protocol_read_list_begin; + cls->read_set_begin = thrift_protocol_read_set_begin; + cls->read_set_end = thrift_protocol_read_set_end; + cls->read_bool = thrift_protocol_read_bool; + cls->read_byte = thrift_protocol_read_byte; + cls->read_i16 = thrift_protocol_read_i16; + cls->read_i32 = thrift_protocol_read_i32; + cls->read_i64 = thrift_protocol_read_i64; + cls->read_double = thrift_protocol_read_double; + cls->read_string = thrift_protocol_read_string; + cls->read_binary = thrift_protocol_read_binary; +} diff --git a/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_protocol.h b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_protocol.h new file mode 100644 index 000000000..58fe5e0af --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_protocol.h @@ -0,0 +1,341 @@ +/* + * 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_H +#define _THRIFT_PROTOCOL_H + +#include <glib-object.h> + +#include <thrift/c_glib/transport/thrift_transport.h> + +G_BEGIN_DECLS + +/*! \file thrift_protocol.h + * \brief Abstract class for Thrift protocol implementations. + */ + +/** + * Enumerated definition of the types that the Thrift protocol supports. + * Take special note of the T_END type which is used specifically to mark + * the end of a sequence of fields. + */ +typedef enum { + T_STOP = 0, + T_VOID = 1, + T_BOOL = 2, + T_BYTE = 3, + T_I08 = 3, + T_I16 = 6, + T_I32 = 8, + T_U64 = 9, + T_I64 = 10, + T_DOUBLE = 4, + T_STRING = 11, + T_UTF7 = 11, + T_STRUCT = 12, + T_MAP = 13, + T_SET = 14, + T_LIST = 15, + T_UTF8 = 16, + T_UTF16 = 17 +} ThriftType; + +/** + * Enumerated definition of the message types that the Thrift protocol + * supports. + */ +typedef enum { + T_CALL = 1, + T_REPLY = 2, + T_EXCEPTION = 3, + T_ONEWAY = 4 +} ThriftMessageType; + +/* type macros */ +#define THRIFT_TYPE_PROTOCOL (thrift_protocol_get_type ()) +#define THRIFT_PROTOCOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THRIFT_TYPE_PROTOCOL, ThriftProtocol)) +#define THRIFT_IS_PROTOCOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THRIFT_TYPE_PROTOCOL)) +#define THRIFT_PROTOCOL_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), THRIFT_TYPE_PROTOCOL, ThriftProtocolClass)) +#define THRIFT_IS_PROTOCOL_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), THRIFT_TYPE_PROTOCOL)) +#define THRIFT_PROTOCOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THRIFT_TYPE_PROTOCOL, ThriftProtocolClass)) + +typedef struct _ThriftProtocol ThriftProtocol; + +/*! + * Thrift Protocol object + */ +struct _ThriftProtocol +{ + GObject parent; + + /* protected */ + ThriftTransport *transport; +}; + +typedef struct _ThriftProtocolClass ThriftProtocolClass; + +/*! + * Thrift Protocol class + */ +struct _ThriftProtocolClass +{ + GObjectClass parent; + + gint32 (*write_message_begin) (ThriftProtocol *protocol, const gchar *name, + const ThriftMessageType message_type, + const gint32 seqid, GError **error); + gint32 (*write_message_end) (ThriftProtocol *protocol, GError **error); + gint32 (*write_struct_begin) (ThriftProtocol *protocol, const gchar *name, + GError **error); + gint32 (*write_struct_end) (ThriftProtocol *protocol, GError **error); + gint32 (*write_field_begin) (ThriftProtocol *protocol, const gchar *name, + const ThriftType field_type, + const gint16 field_id, GError **error); + gint32 (*write_field_end) (ThriftProtocol *protocol, GError **error); + gint32 (*write_field_stop) (ThriftProtocol *protocol, GError **error); + gint32 (*write_map_begin) (ThriftProtocol *protocol, + const ThriftType key_type, + const ThriftType value_type, + const guint32 size, GError **error); + gint32 (*write_map_end) (ThriftProtocol *protocol, GError **error); + gint32 (*write_list_begin) (ThriftProtocol *protocol, + const ThriftType element_type, + const guint32 size, GError **error); + gint32 (*write_list_end) (ThriftProtocol *protocol, GError **error); + gint32 (*write_set_begin) (ThriftProtocol *protocol, + const ThriftType element_type, + const guint32 size, GError **error); + gint32 (*write_set_end) (ThriftProtocol *protocol, GError **error); + gint32 (*write_bool) (ThriftProtocol *protocol, const gboolean value, + GError **error); + gint32 (*write_byte) (ThriftProtocol *protocol, const gint8 value, + GError **error); + gint32 (*write_i16) (ThriftProtocol *protocol, const gint16 value, + GError **error); + gint32 (*write_i32) (ThriftProtocol *protocol, const gint32 value, + GError **error); + gint32 (*write_i64) (ThriftProtocol *protocol, const gint64 value, + GError **error); + gint32 (*write_double) (ThriftProtocol *protocol, const gdouble value, + GError **error); + gint32 (*write_string) (ThriftProtocol *protocol, const gchar *str, + GError **error); + gint32 (*write_binary) (ThriftProtocol *protocol, const gpointer buf, + const guint32 len, GError **error); + + gint32 (*read_message_begin) (ThriftProtocol *thrift_protocol, gchar **name, + ThriftMessageType *message_type, + gint32 *seqid, GError **error); + gint32 (*read_message_end) (ThriftProtocol *protocol, GError **error); + gint32 (*read_struct_begin) (ThriftProtocol *protocol, gchar **name, + GError **error); + gint32 (*read_struct_end) (ThriftProtocol *protocol, GError **error); + gint32 (*read_field_begin) (ThriftProtocol *protocol, gchar **name, + ThriftType *field_type, gint16 *field_id, + GError **error); + gint32 (*read_field_end) (ThriftProtocol *protocol, GError **error); + gint32 (*read_map_begin) (ThriftProtocol *protocol, ThriftType *key_type, + ThriftType *value_type, guint32 *size, + GError **error); + gint32 (*read_map_end) (ThriftProtocol *protocol, GError **error); + gint32 (*read_list_begin) (ThriftProtocol *protocol, ThriftType *element_type, + guint32 *size, GError **error); + gint32 (*read_list_end) (ThriftProtocol *protocol, GError **error); + gint32 (*read_set_begin) (ThriftProtocol *protocol, ThriftType *element_type, + guint32 *size, GError **error); + gint32 (*read_set_end) (ThriftProtocol *protocol, GError **error); + gint32 (*read_bool) (ThriftProtocol *protocol, gboolean *value, + GError **error); + gint32 (*read_byte) (ThriftProtocol *protocol, gint8 *value, GError **error); + gint32 (*read_i16) (ThriftProtocol *protocol, gint16 *value, GError **error); + gint32 (*read_i32) (ThriftProtocol *protocol, gint32 *value, GError **error); + gint32 (*read_i64) (ThriftProtocol *protocol, gint64 *value, GError **error); + gint32 (*read_double) (ThriftProtocol *protocol, gdouble *value, + GError **error); + gint32 (*read_string) (ThriftProtocol *protocol, gchar **str, GError **error); + gint32 (*read_binary) (ThriftProtocol *protocol, gpointer *buf, + guint32 *len, GError **error); +}; + +/* used by THRIFT_TYPE_PROTOCOL */ +GType thrift_protocol_get_type (void); + +/* virtual public methods */ +gint32 thrift_protocol_write_message_begin (ThriftProtocol *protocol, + const gchar *name, const ThriftMessageType message_type, + const gint32 seqid, GError **error); + +gint32 thrift_protocol_write_message_end (ThriftProtocol *protocol, + GError **error); + +gint32 thrift_protocol_write_struct_begin (ThriftProtocol *protocol, + const gchar *name, + GError **error); + +gint32 thrift_protocol_write_struct_end (ThriftProtocol *protocol, + GError **error); + +gint32 thrift_protocol_write_field_begin (ThriftProtocol *protocol, + const gchar *name, + const ThriftType field_type, + const gint16 field_id, + GError **error); + +gint32 thrift_protocol_write_field_end (ThriftProtocol *protocol, + GError **error); + +gint32 thrift_protocol_write_field_stop (ThriftProtocol *protocol, + GError **error); + +gint32 thrift_protocol_write_map_begin (ThriftProtocol *protocol, + const ThriftType key_type, + const ThriftType value_type, + const guint32 size, GError **error); + +gint32 thrift_protocol_write_map_end (ThriftProtocol *protocol, GError **error); + +gint32 thrift_protocol_write_list_begin (ThriftProtocol *protocol, + const ThriftType element_type, + const guint32 size, GError **error); + +gint32 thrift_protocol_write_list_end (ThriftProtocol *protocol, + GError **error); + +gint32 thrift_protocol_write_set_begin (ThriftProtocol *protocol, + const ThriftType element_type, + const guint32 size, GError **error); + +gint32 thrift_protocol_write_set_end (ThriftProtocol *protocol, + GError **error); + +gint32 thrift_protocol_write_bool (ThriftProtocol *protocol, + const gboolean value, GError **error); + +gint32 thrift_protocol_write_byte (ThriftProtocol *protocol, const gint8 value, + GError **error); + +gint32 thrift_protocol_write_i16 (ThriftProtocol *protocol, const gint16 value, + GError **error); + +gint32 thrift_protocol_write_i32 (ThriftProtocol *protocol, const gint32 value, + GError **error); + +gint32 thrift_protocol_write_i64 (ThriftProtocol *protocol, const gint64 value, + GError **error); + +gint32 thrift_protocol_write_double (ThriftProtocol *protocol, + const gdouble value, GError **error); + +gint32 thrift_protocol_write_string (ThriftProtocol *protocol, + const gchar *str, GError **error); + +gint32 thrift_protocol_write_binary (ThriftProtocol *protocol, + const gpointer buf, + const guint32 len, GError **error); + +gint32 thrift_protocol_read_message_begin (ThriftProtocol *thrift_protocol, + gchar **name, + ThriftMessageType *message_type, + gint32 *seqid, GError **error); + +gint32 thrift_protocol_read_message_end (ThriftProtocol *protocol, + GError **error); + +gint32 thrift_protocol_read_struct_begin (ThriftProtocol *protocol, + gchar **name, + GError **error); + +gint32 thrift_protocol_read_struct_end (ThriftProtocol *protocol, + GError **error); + +gint32 thrift_protocol_read_field_begin (ThriftProtocol *protocol, + gchar **name, + ThriftType *field_type, + gint16 *field_id, + GError **error); + +gint32 thrift_protocol_read_field_end (ThriftProtocol *protocol, + GError **error); + +gint32 thrift_protocol_read_map_begin (ThriftProtocol *protocol, + ThriftType *key_type, + ThriftType *value_type, guint32 *size, + GError **error); + +gint32 thrift_protocol_read_map_end (ThriftProtocol *protocol, GError **error); + +gint32 thrift_protocol_read_list_begin (ThriftProtocol *protocol, + ThriftType *element_type, + guint32 *size, GError **error); + +gint32 thrift_protocol_read_list_end (ThriftProtocol *protocol, GError **error); + +gint32 thrift_protocol_read_set_begin (ThriftProtocol *protocol, + ThriftType *element_type, + guint32 *size, GError **error); + +gint32 thrift_protocol_read_set_end (ThriftProtocol *protocol, GError **error); + +gint32 thrift_protocol_read_bool (ThriftProtocol *protocol, gboolean *value, + GError **error); + +gint32 thrift_protocol_read_byte (ThriftProtocol *protocol, gint8 *value, + GError **error); + +gint32 thrift_protocol_read_i16 (ThriftProtocol *protocol, gint16 *value, + GError **error); + +gint32 thrift_protocol_read_i32 (ThriftProtocol *protocol, gint32 *value, + GError **error); + +gint32 thrift_protocol_read_i64 (ThriftProtocol *protocol, gint64 *value, + GError **error); + +gint32 thrift_protocol_read_double (ThriftProtocol *protocol, + gdouble *value, GError **error); + +gint32 thrift_protocol_read_string (ThriftProtocol *protocol, + gchar **str, GError **error); + +gint32 thrift_protocol_read_binary (ThriftProtocol *protocol, + gpointer *buf, guint32 *len, + GError **error); + +gint32 thrift_protocol_skip (ThriftProtocol *protocol, ThriftType type, + GError **error); + +/* define error types */ +typedef enum +{ + THRIFT_PROTOCOL_ERROR_UNKNOWN, + THRIFT_PROTOCOL_ERROR_INVALID_DATA, + THRIFT_PROTOCOL_ERROR_NEGATIVE_SIZE, + THRIFT_PROTOCOL_ERROR_SIZE_LIMIT, + THRIFT_PROTOCOL_ERROR_BAD_VERSION, + THRIFT_PROTOCOL_ERROR_NOT_IMPLEMENTED, + THRIFT_PROTOCOL_ERROR_DEPTH_LIMIT +} ThriftProtocolError; + +/* define an error domain for GError to use */ +GQuark thrift_protocol_error_quark (void); +#define THRIFT_PROTOCOL_ERROR (thrift_protocol_error_quark ()) + +G_END_DECLS + +#endif /* _THRIFT_PROTOCOL_H */ diff --git a/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_protocol_decorator.c b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_protocol_decorator.c new file mode 100644 index 000000000..03f9420f7 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_protocol_decorator.c @@ -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; +} diff --git a/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_protocol_decorator.h b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_protocol_decorator.h new file mode 100644 index 000000000..13b6af238 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_protocol_decorator.h @@ -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 */ diff --git a/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_protocol_factory.c b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_protocol_factory.c new file mode 100644 index 000000000..bef40876f --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_protocol_factory.c @@ -0,0 +1,43 @@ +/* + * 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 <thrift/c_glib/thrift.h> +#include <thrift/c_glib/protocol/thrift_protocol_factory.h> + +G_DEFINE_ABSTRACT_TYPE(ThriftProtocolFactory, thrift_protocol_factory, G_TYPE_OBJECT) + +ThriftProtocol * +thrift_protocol_factory_get_protocol(ThriftProtocolFactory *factory, + ThriftTransport *transport) +{ + return THRIFT_PROTOCOL_FACTORY_GET_CLASS (factory)->get_protocol (factory, + transport); +} + +static void +thrift_protocol_factory_init (ThriftProtocolFactory *factory) +{ + THRIFT_UNUSED_VAR (factory); +} + +static void +thrift_protocol_factory_class_init (ThriftProtocolFactoryClass *cls) +{ + cls->get_protocol = thrift_protocol_factory_get_protocol; +} diff --git a/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_protocol_factory.h b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_protocol_factory.h new file mode 100644 index 000000000..5f146dde3 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_protocol_factory.h @@ -0,0 +1,73 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_PROTOCOL_FACTORY_H +#define _THRIFT_PROTOCOL_FACTORY_H + +#include <glib-object.h> + +#include <thrift/c_glib/transport/thrift_transport.h> +#include <thrift/c_glib/protocol/thrift_protocol.h> + +G_BEGIN_DECLS + +/*! \file thrift_protocol_factory.h + * \brief Abstract class for Thrift protocol factory implementations. + */ + +/* type macros */ +#define THRIFT_TYPE_PROTOCOL_FACTORY (thrift_protocol_factory_get_type ()) +#define THRIFT_PROTOCOL_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THRIFT_TYPE_PROTOCOL_FACTORY, ThriftProtocolFactory)) +#define THRIFT_IS_PROTOCOL_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THRIFT_TYPE_PROTOCOL_FACTORY)) +#define THRIFT_PROTOCOL_FACTORY_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), THRIFT_TYPE_PROTOCOL_FACTORY, ThriftProtocolFactoryClass)) +#define THRIFT_IS_PROTOCOL_FACTORY_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), THRIFT_TYPE_PROTOCOL_FACTORY)) +#define THRIFT_PROTOCOL_FACTORY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THRIFT_TYPE_PROTOCOL_FACTORY, ThriftProtocolFactoryClass)) + +typedef struct _ThriftProtocolFactory ThriftProtocolFactory; + +/*! + * Thrift Protocol Factory object + */ +struct _ThriftProtocolFactory +{ + GObject parent; +}; + +typedef struct _ThriftProtocolFactoryClass ThriftProtocolFactoryClass; + +/*! + * Thrift Protocol Factory class + */ +struct _ThriftProtocolFactoryClass +{ + GObjectClass parent; + + ThriftProtocol *(*get_protocol) (ThriftProtocolFactory *factory, + ThriftTransport *transport); +}; + +/* used by THRIFT_TYPE_PROTOCOL_FACTORY */ +GType thrift_protocol_factory_get_type (void); + +/* virtual public methods */ +ThriftProtocol *thrift_protocol_factory_get_protocol(ThriftProtocolFactory *factory, ThriftTransport *transport); + +G_END_DECLS + +#endif /* _THRIFT_PROTOCOL_FACTORY_H */ diff --git a/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_stored_message_protocol.c b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_stored_message_protocol.c new file mode 100644 index 000000000..22aca8a29 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_stored_message_protocol.c @@ -0,0 +1,192 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include <string.h> +#include <stdio.h> +#include <glib.h> +#include <glib-object.h> + +#include <thrift/c_glib/thrift.h> +#include <thrift/c_glib/protocol/thrift_protocol.h> +#include <thrift/c_glib/protocol/thrift_protocol_decorator.h> +#include <thrift/c_glib/protocol/thrift_stored_message_protocol.h> + + +enum +{ + PROP_THRIFT_STORED_MESSAGE_PROTOCOL_MESSAGE_NAME = 1, + PROP_THRIFT_STORED_MESSAGE_PROTOCOL_MESSAGE_TYPE, + PROP_THRIFT_STORED_MESSAGE_PROTOCOL_SEQUENCE_ID, + PROP_THRIFT_STORED_MESSAGE_PROTOCOL_TRANSPORT, /* TODO ugly hack */ + PROP_THRIFT_STORED_MESSAGE_PROTOCOL_END +}; + +G_DEFINE_TYPE(ThriftStoredMessageProtocol, thrift_stored_message_protocol, THRIFT_TYPE_PROTOCOL_DECORATOR) + + +static GParamSpec *thrift_stored_message_protocol_obj_properties[PROP_THRIFT_STORED_MESSAGE_PROTOCOL_END] = { NULL, }; + +gint32 +thrift_stored_message_protocol_read_message_begin (ThriftProtocol *protocol, + gchar **name, + ThriftMessageType *message_type, + gint32 *seqid, GError **error) +{ + gint32 ret = 0; + g_return_val_if_fail (THRIFT_IS_STORED_MESSAGE_PROTOCOL (protocol), -1); + THRIFT_UNUSED_VAR (error); + + ThriftStoredMessageProtocol *self = THRIFT_STORED_MESSAGE_PROTOCOL (protocol); + + /* We return the stored values on construction */ + *name = self->name; + *message_type = self->mtype; + *seqid = self->seqid; + + return ret; +} + + +static void +thrift_stored_message_protocol_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + ThriftStoredMessageProtocol *self = THRIFT_STORED_MESSAGE_PROTOCOL (object); + + switch (property_id) + { + case PROP_THRIFT_STORED_MESSAGE_PROTOCOL_MESSAGE_NAME: + self->name = g_value_dup_string (value); + break; + case PROP_THRIFT_STORED_MESSAGE_PROTOCOL_MESSAGE_TYPE: + self->mtype = g_value_get_int (value); + break; + case PROP_THRIFT_STORED_MESSAGE_PROTOCOL_SEQUENCE_ID: + self->seqid = g_value_get_int (value); + break; + + default: + /* We don't have any other property... */ + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +thrift_stored_message_protocol_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + ThriftStoredMessageProtocol *self = THRIFT_STORED_MESSAGE_PROTOCOL (object); + ThriftProtocolDecorator *decorator = THRIFT_PROTOCOL_DECORATOR (object); + ThriftTransport *transport=NULL; + switch (property_id) + { + case PROP_THRIFT_STORED_MESSAGE_PROTOCOL_MESSAGE_NAME: + g_value_set_string (value, self->name); + break; + case PROP_THRIFT_STORED_MESSAGE_PROTOCOL_TRANSPORT: + /* FIXME Since we don't override properties in the decorator as it should + we just override the properties that we know are used */ + g_object_get(decorator->concrete_protocol,pspec->name, &transport, NULL); + g_value_set_pointer (value, transport); + break; + + default: + /* We don't have any other property... */ + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + + +static void +thrift_stored_message_protocol_init (ThriftStoredMessageProtocol *protocol) +{ + protocol->name = NULL; +} + +static void +thrift_stored_message_protocol_finalize (GObject *gobject) +{ + ThriftStoredMessageProtocol *self = THRIFT_STORED_MESSAGE_PROTOCOL (gobject); + + if (self->name) { + g_free(self->name); + self->name = NULL; + } + + /* Always chain up to the parent class; as with dispose(), finalize() + * is guaranteed to exist on the parent's class virtual function table + */ + G_OBJECT_CLASS (thrift_stored_message_protocol_parent_class)->finalize(gobject); +} + + +/* initialize the class */ +static void +thrift_stored_message_protocol_class_init (ThriftStoredMessageProtocolClass *klass) +{ + ThriftProtocolClass *cls = THRIFT_PROTOCOL_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + cls->read_message_begin = thrift_stored_message_protocol_read_message_begin; + + object_class->set_property = thrift_stored_message_protocol_set_property; + object_class->get_property = thrift_stored_message_protocol_get_property; + object_class->finalize = thrift_stored_message_protocol_finalize; + + thrift_stored_message_protocol_obj_properties[PROP_THRIFT_STORED_MESSAGE_PROTOCOL_MESSAGE_NAME] = + g_param_spec_string ("name", + "Service name the protocol points to", + "Set the service name", + NULL, + (G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE)); + thrift_stored_message_protocol_obj_properties[PROP_THRIFT_STORED_MESSAGE_PROTOCOL_MESSAGE_TYPE] = + g_param_spec_int ("type", + "Message type in the wire", + "Set the message type in the wire", + T_CALL, T_ONEWAY, + T_CALL, + (G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE)); + thrift_stored_message_protocol_obj_properties[PROP_THRIFT_STORED_MESSAGE_PROTOCOL_SEQUENCE_ID] = + g_param_spec_int ("seqid", + "Sequence id type in the wire", + "Set the Sequence id in the wire", + G_MININT, 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); +} diff --git a/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_stored_message_protocol.h b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_stored_message_protocol.h new file mode 100644 index 000000000..88782ac36 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/protocol/thrift_stored_message_protocol.h @@ -0,0 +1,78 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_STORED_MESSAGE_PROTOCOL_H +#define _THRIFT_STORED_MESSAGE_PROTOCOL_H + +#include <glib-object.h> + +#include <thrift/c_glib/protocol/thrift_protocol.h> +#include <thrift/c_glib/protocol/thrift_protocol_decorator.h> +#include <thrift/c_glib/transport/thrift_transport.h> + +G_BEGIN_DECLS + +/*! \file thrift_stored_message_protocol.h + * \brief StoredMessage protocol implementation of a pre-stored message header + * on Thrift protocol. Implements the ThriftProtocol interface. + */ + +/* type macros */ +#define THRIFT_TYPE_STORED_MESSAGE_PROTOCOL (thrift_stored_message_protocol_get_type ()) +#define THRIFT_STORED_MESSAGE_PROTOCOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THRIFT_TYPE_STORED_MESSAGE_PROTOCOL, ThriftStoredMessageProtocol)) +#define THRIFT_IS_STORED_MESSAGE_PROTOCOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THRIFT_TYPE_STORED_MESSAGE_PROTOCOL)) +#define THRIFT_STORED_MESSAGE_PROTOCOL_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), THRIFT_TYPE_STORED_MESSAGE_PROTOCOL, ThriftStoredMessageProtocolClass)) +#define THRIFT_IS_STORED_MESSAGE_PROTOCOL_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), THRIFT_TYPE_STORED_MESSAGE_PROTOCOL)) +#define THRIFT_STORED_MESSAGE_PROTOCOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THRIFT_TYPE_STORED_MESSAGE_PROTOCOL, ThriftStoredMessageProtocolClass)) + +/* constant */ +#define THRIFT_STORED_MESSAGE_PROTOCOL_DEFAULT_SEPARATOR ":" + +typedef struct _ThriftStoredMessageProtocol ThriftStoredMessageProtocol; + + + +/*! + * Thrift StoredMessage Protocol instance. + */ +struct _ThriftStoredMessageProtocol +{ + ThriftProtocolDecorator parent; + + gchar *name; + ThriftMessageType mtype; + gint32 seqid; +}; + +typedef struct _ThriftStoredMessageProtocolClass ThriftStoredMessageProtocolClass; + +/*! + * Thrift StoredMessage Protocol class. + */ +struct _ThriftStoredMessageProtocolClass +{ + ThriftProtocolDecoratorClass parent; +}; + +/* used by THRIFT_TYPE_STORED_MESSAGE_PROTOCOL */ +GType thrift_stored_message_protocol_get_type (void); + +G_END_DECLS + +#endif /* _THRIFT_STORED_MESSAGE_PROTOCOL_H */ diff --git a/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/server/thrift_server.c b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/server/thrift_server.c new file mode 100644 index 000000000..ccf9153db --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/server/thrift_server.c @@ -0,0 +1,195 @@ +/* + * 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 <thrift/c_glib/thrift.h> +#include "thrift_server.h" + +/* object properties */ +enum _ThriftServerProperties +{ + PROP_0, + PROP_THRIFT_SERVER_PROCESSOR, + PROP_THRIFT_SERVER_SERVER_TRANSPORT, + PROP_THRIFT_SERVER_INPUT_TRANSPORT_FACTORY, + PROP_THRIFT_SERVER_OUTPUT_TRANSPORT_FACTORY, + PROP_THRIFT_SERVER_INPUT_PROTOCOL_FACTORY, + PROP_THRIFT_SERVER_OUTPUT_PROTOCOL_FACTORY +}; + +G_DEFINE_ABSTRACT_TYPE(ThriftServer, thrift_server, G_TYPE_OBJECT) + +void +thrift_server_get_property (GObject *object, guint property_id, + GValue *value, GParamSpec *pspec) +{ + ThriftServer *server = THRIFT_SERVER (object); + + THRIFT_UNUSED_VAR (pspec); + + switch (property_id) + { + case PROP_THRIFT_SERVER_PROCESSOR: + g_value_set_object (value, server->processor); + break; + case PROP_THRIFT_SERVER_SERVER_TRANSPORT: + g_value_set_object (value, server->server_transport); + break; + case PROP_THRIFT_SERVER_INPUT_TRANSPORT_FACTORY: + g_value_set_object (value, server->input_transport_factory); + break; + case PROP_THRIFT_SERVER_OUTPUT_TRANSPORT_FACTORY: + g_value_set_object (value, server->output_transport_factory); + break; + case PROP_THRIFT_SERVER_INPUT_PROTOCOL_FACTORY: + g_value_set_object (value, server->input_protocol_factory); + break; + case PROP_THRIFT_SERVER_OUTPUT_PROTOCOL_FACTORY: + g_value_set_object (value, server->output_protocol_factory); + break; + } +} + +void +thrift_server_set_property (GObject *object, guint property_id, + const GValue *value, GParamSpec *pspec) +{ + ThriftServer *server = THRIFT_SERVER (object); + + THRIFT_UNUSED_VAR (pspec); + + switch (property_id) + { + case PROP_THRIFT_SERVER_PROCESSOR: + server->processor = g_value_dup_object (value); + break; + case PROP_THRIFT_SERVER_SERVER_TRANSPORT: + server->server_transport = g_value_dup_object (value); + break; + case PROP_THRIFT_SERVER_INPUT_TRANSPORT_FACTORY: + server->input_transport_factory = g_value_dup_object (value); + break; + case PROP_THRIFT_SERVER_OUTPUT_TRANSPORT_FACTORY: + server->output_transport_factory = g_value_dup_object (value); + break; + case PROP_THRIFT_SERVER_INPUT_PROTOCOL_FACTORY: + server->input_protocol_factory = g_value_dup_object (value); + break; + case PROP_THRIFT_SERVER_OUTPUT_PROTOCOL_FACTORY: + server->output_protocol_factory = g_value_dup_object (value); + break; + } +} + +gboolean +thrift_server_serve (ThriftServer *server, GError **error) +{ + return THRIFT_SERVER_GET_CLASS (server)->serve (server, error); +} + +void +thrift_server_stop (ThriftServer *server) +{ + THRIFT_SERVER_GET_CLASS (server)->stop (server); +} + +/* instance initializer for Thrift Server */ +static void +thrift_server_init (ThriftServer *server) +{ + server->processor = NULL; + server->server_transport = NULL; + server->input_transport_factory = NULL; + server->output_transport_factory = NULL; + server->input_protocol_factory = NULL; + server->output_protocol_factory = NULL; +} + +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 +thrift_server_class_init (ThriftServerClass *cls) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (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, + g_param_spec_object ("processor", "Processor", "Thrift Processor", + THRIFT_TYPE_PROCESSOR, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + g_object_class_install_property (gobject_class, + PROP_THRIFT_SERVER_SERVER_TRANSPORT, + g_param_spec_object ("server_transport", "Server Transport", + "Thrift Server Transport", + THRIFT_TYPE_SERVER_TRANSPORT, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + g_object_class_install_property (gobject_class, + PROP_THRIFT_SERVER_INPUT_TRANSPORT_FACTORY, + g_param_spec_object ("input_transport_factory", "Input Transport Factory", + "Thrift Server Input Transport Factory", + THRIFT_TYPE_TRANSPORT_FACTORY, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + g_object_class_install_property (gobject_class, + PROP_THRIFT_SERVER_OUTPUT_TRANSPORT_FACTORY, + g_param_spec_object ("output_transport_factory", + "Output Transport Factory", + "Thrift Server Output Transport Factory", + THRIFT_TYPE_TRANSPORT_FACTORY, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + g_object_class_install_property (gobject_class, + PROP_THRIFT_SERVER_INPUT_PROTOCOL_FACTORY, + g_param_spec_object ("input_protocol_factory", "Input Protocol Factory", + "Thrift Server Input Protocol Factory", + THRIFT_TYPE_PROTOCOL_FACTORY, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + g_object_class_install_property (gobject_class, + PROP_THRIFT_SERVER_OUTPUT_PROTOCOL_FACTORY, + g_param_spec_object ("output_protocol_factory", "Output Protocol Factory", + "Thrift Server Output Protocol Factory", + THRIFT_TYPE_PROTOCOL_FACTORY, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + /* set these as virtual methods to be implemented by a subclass */ + cls->serve = thrift_server_serve; + cls->stop = thrift_server_stop; +} diff --git a/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/server/thrift_server.h b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/server/thrift_server.h new file mode 100644 index 000000000..49beddcbe --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/server/thrift_server.h @@ -0,0 +1,93 @@ +/* + * 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_SERVER_H +#define _THRIFT_SERVER_H + +#include <glib-object.h> + +#include <thrift/c_glib/processor/thrift_processor.h> +#include <thrift/c_glib/transport/thrift_server_transport.h> +#include <thrift/c_glib/transport/thrift_transport_factory.h> +#include <thrift/c_glib/protocol/thrift_protocol_factory.h> + +G_BEGIN_DECLS + +/*! \file thrift_server.h + * \brief Abstract class for Thrift servers. + */ + +/* type macros */ +#define THRIFT_TYPE_SERVER (thrift_server_get_type ()) +#define THRIFT_SERVER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THRIFT_TYPE_SERVER, ThriftServer)) +#define THRIFT_IS_SERVER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THRIFT_TYPE_SERVER)) +#define THRIFT_SERVER_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), THRIFT_TYPE_SERVER, ThriftServerClass)) +#define THRIFT_IS_SERVER_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), THRIFT_TYPE_SERVER)) +#define THRIFT_SERVER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THRIFT_TYPE_SERVER, ThriftServerClass)) + +typedef struct _ThriftServer ThriftServer; + +/*! + * Thrift Server object + */ +struct _ThriftServer +{ + GObject parent; + + /* protected */ + ThriftProcessor *processor; + ThriftServerTransport *server_transport; + ThriftTransportFactory *input_transport_factory; + ThriftTransportFactory *output_transport_factory; + ThriftProtocolFactory *input_protocol_factory; + ThriftProtocolFactory *output_protocol_factory; +}; + +typedef struct _ThriftServerClass ThriftServerClass; + +/*! + * Thrift Server class + */ +struct _ThriftServerClass +{ + GObjectClass parent; + + /* vtable */ + gboolean (*serve) (ThriftServer *server, GError **error); + void (*stop) (ThriftServer *server); +}; + +/* used by THRIFT_TYPE_SERVER */ +GType thrift_server_get_type (void); + +/*! + * Processes the request. + * \public \memberof ThriftServerClass + */ +gboolean thrift_server_serve (ThriftServer *server, GError **error); + +/*! + * Stop handling requests. + */ +void thrift_server_stop (ThriftServer *server); + +G_END_DECLS + +#endif /* _THRIFT_SERVER_H */ + diff --git a/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/server/thrift_simple_server.c b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/server/thrift_simple_server.c new file mode 100644 index 000000000..22a96c7a4 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/server/thrift_simple_server.c @@ -0,0 +1,138 @@ +/* + * 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 <thrift/c_glib/server/thrift_simple_server.h> +#include <thrift/c_glib/transport/thrift_transport_factory.h> +#include <thrift/c_glib/protocol/thrift_protocol_factory.h> +#include <thrift/c_glib/protocol/thrift_binary_protocol_factory.h> + +G_DEFINE_TYPE(ThriftSimpleServer, thrift_simple_server, THRIFT_TYPE_SERVER) + +gboolean +thrift_simple_server_serve (ThriftServer *server, GError **error) +{ + ThriftTransport *t = NULL; + ThriftTransport *input_transport = NULL, *output_transport = NULL; + ThriftProtocol *input_protocol = NULL, *output_protocol = NULL; + ThriftSimpleServer *tss = THRIFT_SIMPLE_SERVER(server); + GError *process_error = NULL; + + g_return_val_if_fail (THRIFT_IS_SIMPLE_SERVER (server), FALSE); + + if (thrift_server_transport_listen (server->server_transport, error)) { + tss->running = TRUE; + while (tss->running == TRUE) + { + t = thrift_server_transport_accept (server->server_transport, + error); + if (t != NULL && tss->running) { + input_transport = + THRIFT_TRANSPORT_FACTORY_GET_CLASS (server->input_transport_factory) + ->get_transport (server->input_transport_factory, t); + output_transport = + THRIFT_TRANSPORT_FACTORY_GET_CLASS (server->output_transport_factory) + ->get_transport (server->output_transport_factory, t); + input_protocol = + THRIFT_PROTOCOL_FACTORY_GET_CLASS (server->input_protocol_factory) + ->get_protocol (server->input_protocol_factory, input_transport); + output_protocol = + THRIFT_PROTOCOL_FACTORY_GET_CLASS (server->output_protocol_factory) + ->get_protocol (server->output_protocol_factory, output_transport); + + while (THRIFT_PROCESSOR_GET_CLASS (server->processor) + ->process (server->processor, + input_protocol, + output_protocol, + &process_error) && + thrift_transport_peek (input_transport, &process_error)) + { + } + + if (process_error != NULL) + { + g_message ("thrift_simple_server_serve: %s", process_error->message); + g_clear_error (&process_error); + + /* Note we do not propagate processing errors to the caller as they + * normally are transient and not fatal to the server */ + } + + /* TODO: handle exceptions */ + THRIFT_TRANSPORT_GET_CLASS (input_transport)->close (input_transport, + NULL); + THRIFT_TRANSPORT_GET_CLASS (output_transport)->close (output_transport, + NULL); + } + } + + /* attempt to shutdown */ + THRIFT_SERVER_TRANSPORT_GET_CLASS (server->server_transport) + ->close (server->server_transport, NULL); + } + + /* Since this method is designed to run forever, it can only ever return on + * error */ + return FALSE; +} + +void +thrift_simple_server_stop (ThriftServer *server) +{ + g_return_if_fail (THRIFT_IS_SIMPLE_SERVER (server)); + (THRIFT_SIMPLE_SERVER (server))->running = FALSE; +} + +static void +thrift_simple_server_init (ThriftSimpleServer *tss) +{ + ThriftServer *server = THRIFT_SERVER(tss); + + tss->running = FALSE; + + if (server->input_transport_factory == NULL) + { + server->input_transport_factory = + g_object_new (THRIFT_TYPE_TRANSPORT_FACTORY, NULL); + } + if (server->output_transport_factory == NULL) + { + server->output_transport_factory = + g_object_new (THRIFT_TYPE_TRANSPORT_FACTORY, NULL); + } + if (server->input_protocol_factory == NULL) + { + server->input_protocol_factory = + g_object_new (THRIFT_TYPE_BINARY_PROTOCOL_FACTORY, NULL); + } + if (server->output_protocol_factory == NULL) + { + server->output_protocol_factory = + g_object_new (THRIFT_TYPE_BINARY_PROTOCOL_FACTORY, NULL); + } +} + +/* initialize the class */ +static void +thrift_simple_server_class_init (ThriftSimpleServerClass *class) +{ + ThriftServerClass *cls = THRIFT_SERVER_CLASS(class); + + cls->serve = thrift_simple_server_serve; + cls->stop = thrift_simple_server_stop; +} diff --git a/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/server/thrift_simple_server.h b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/server/thrift_simple_server.h new file mode 100644 index 000000000..86b538b48 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/server/thrift_simple_server.h @@ -0,0 +1,70 @@ +/* + * 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_SIMPLE_SERVER_H +#define _THRIFT_SIMPLE_SERVER_H + +#include <glib-object.h> + +#include <thrift/c_glib/server/thrift_server.h> + +G_BEGIN_DECLS + +/*! \file thrift_simple_server.h + * \brief A simple Thrift server, single-threaded. + */ + +/* type macros */ +#define THRIFT_TYPE_SIMPLE_SERVER (thrift_simple_server_get_type ()) +#define THRIFT_SIMPLE_SERVER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THRIFT_TYPE_SIMPLE_SERVER, ThriftSimpleServer)) +#define THRIFT_IS_SIMPLE_SERVER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THRIFT_TYPE_SIMPLE_SERVER)) +#define THRIFT_SIMPLE_SERVER_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c) THRIFT_TYPE_SIMPLE_SERVER, ThriftSimpleServerClass)) +#define THRIFT_IS_SIMPLE_SERVER_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), THRIFT_TYPE_SIMPLE_SERVER)) +#define THRIFT_SIMPLE_SERVER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THRIFT_TYPE_SIMPLE_SERVER, ThriftSimpleServerClass)) + +typedef struct _ThriftSimpleServer ThriftSimpleServer; + +/** + * Thrift Simple Server instance. + */ +struct _ThriftSimpleServer +{ + ThriftServer parent; + + /* private */ + volatile gboolean running; +}; + +typedef struct _ThriftSimpleServerClass ThriftSimpleServerClass; + +/** + * Thrift Simple Server class. + */ +struct _ThriftSimpleServerClass +{ + ThriftServerClass parent; +}; + +/* used by THRIFT_TYPE_SIMPLE_SERVER */ +GType thrift_simple_server_get_type (void); + +G_END_DECLS + +#endif /* _THRIFT_SIMPLE_SERVER_H */ + diff --git a/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/thrift.c b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/thrift.c new file mode 100644 index 000000000..8de869f79 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/thrift.c @@ -0,0 +1,101 @@ +/* + * 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 <thrift/c_glib/thrift.h> + +/** + * GHashTable callback to add keys to a GList. + */ +void +thrift_hash_table_get_keys (gpointer key, gpointer value, gpointer user_data) +{ + GList **list = (GList **) user_data; + + THRIFT_UNUSED_VAR (value); + + *list = g_list_append (*list, key); +} +void thrift_safe_hash_table_destroy(GHashTable* hash_table) +{ + if (hash_table) + { + g_hash_table_destroy(hash_table); + } +} + +guint thrift_boolean_hash(gconstpointer v) +{ + const gboolean* p = v; + return p && *p ? 1 : 0; +} +gboolean thrift_boolean_equal(gconstpointer a, gconstpointer b) +{ + if (a == b) { + return TRUE; + } + if (!a || !b) { + return FALSE; + } + const gboolean* pa = a; + const gboolean* pb = b; + return *pa == *pb; +} + +guint thrift_int8_hash(gconstpointer v) +{ + const gint8* p = v; + return p ? *p : 0; +} +gboolean thrift_int8_equal(gconstpointer a, gconstpointer b) +{ + if (a == b) { + return TRUE; + } + if (!a || !b) { + return FALSE; + } + const gint8* pa = a; + const gint8* pb = b; + return *pa == *pb; +} + +guint thrift_int16_hash(gconstpointer v) +{ + const gint16* p = v; + return p ? *p : 0; +} +gboolean thrift_int16_equal(gconstpointer a, gconstpointer b) +{ + if (a == b) { + return TRUE; + } + if (!a || !b) { + return FALSE; + } + const gint16* pa = a; + const gint16* pb = b; + return *pa == *pb; +} + +void +thrift_string_free (gpointer str) +{ + GByteArray* ptr = str; + g_byte_array_unref(ptr); +} diff --git a/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/thrift.h b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/thrift.h new file mode 100644 index 000000000..94a647831 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/thrift.h @@ -0,0 +1,49 @@ +/* + * 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_H +#define _THRIFT_H + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <glib.h> + +/* this macro is called to satisfy -Wall hardcore compilation */ +#ifndef THRIFT_UNUSED_VAR +# define THRIFT_UNUSED_VAR(x) ((void) x) +#endif + +void thrift_hash_table_get_keys (gpointer key, gpointer value, + gpointer user_data); +void thrift_safe_hash_table_destroy(GHashTable* hash_table); + +guint thrift_boolean_hash(gconstpointer v); +gboolean thrift_boolean_equal(gconstpointer a, gconstpointer b); + +guint thrift_int8_hash(gconstpointer v); +gboolean thrift_int8_equal(gconstpointer a, gconstpointer b); + +guint thrift_int16_hash(gconstpointer v); +gboolean thrift_int16_equal(gconstpointer a, gconstpointer b); + +void thrift_string_free (gpointer str); + +#endif /* #ifndef _THRIFT_THRIFT_H */ diff --git a/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/thrift_application_exception.c b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/thrift_application_exception.c new file mode 100644 index 000000000..1234caef9 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/thrift_application_exception.c @@ -0,0 +1,277 @@ +/* + * 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 "thrift_application_exception.h" +#include <thrift/c_glib/protocol/thrift_protocol.h> + +/* object properties */ +enum _ThriftApplicationExceptionProperties +{ + PROP_0, + PROP_THRIFT_APPLICATION_EXCEPTION_TYPE, + PROP_THRIFT_APPLICATION_EXCEPTION_MESSAGE +}; + +G_DEFINE_TYPE(ThriftApplicationException, thrift_application_exception, THRIFT_TYPE_STRUCT) + +gint32 +thrift_application_exception_read (ThriftStruct *object, + ThriftProtocol *protocol, GError **error) +{ + gint32 ret; + gint32 xfer = 0; + gchar *name; + ThriftType ftype; + gint16 fid; + ThriftApplicationException *this = THRIFT_APPLICATION_EXCEPTION (object); + + /* read the struct begin marker */ + if ((ret = thrift_protocol_read_struct_begin (protocol, &name, error)) < 0) + { + if (name) g_free (name); + return -1; + } + xfer += ret; + if (name) g_free (name); + + while (1) + { + if ((ret = thrift_protocol_read_field_begin (protocol, &name, &ftype, + &fid, error)) < 0) + { + if (name) g_free (name); + return -1; + } + xfer += ret; + if (name) g_free (name); + + /* break if we get a STOP field */ + if (ftype == T_STOP) + { + break; + } + + switch (fid) + { + case 1: + if (ftype == T_STRING) + { + if ((ret = thrift_protocol_read_string (protocol, &this->message, + error)) < 0) + return -1; + xfer += ret; + this->__isset_message = TRUE; + } else { + if ((ret = thrift_protocol_skip (protocol, ftype, error)) < 0) + return -1; + xfer += ret; + } + break; + case 2: + if (ftype == T_I32) + { + if ((ret = thrift_protocol_read_i32 (protocol, &this->type, + error)) < 0) + return -1; + xfer += ret; + this->__isset_type = TRUE; + } else { + if ((ret = thrift_protocol_skip (protocol, ftype, error)) < 0) + return -1; + xfer += ret; + } + break; + default: + if ((ret = thrift_protocol_skip (protocol, ftype, error)) < 0) + return -1; + xfer += ret; + break; + } + if ((ret = thrift_protocol_read_field_end (protocol, error)) < 0) + return -1; + xfer += ret; + } + + if ((ret = thrift_protocol_read_struct_end (protocol, error)) < 0) + return -1; + xfer += ret; + + return xfer; +} + +gint32 +thrift_application_exception_write (ThriftStruct *object, + ThriftProtocol *protocol, GError **error) +{ + gint32 ret; + gint32 xfer = 0; + + ThriftApplicationException *this = THRIFT_APPLICATION_EXCEPTION (object); + + if ((ret = thrift_protocol_write_struct_begin (protocol, + "TApplicationException", + error)) < 0) + return -1; + xfer += ret; + if ((ret = thrift_protocol_write_field_begin (protocol, "message", + T_STRING, 1, error)) < 0) + return -1; + xfer += ret; + if ((ret = thrift_protocol_write_string (protocol, this->message, error)) < 0) + return -1; + xfer += ret; + if ((ret = thrift_protocol_write_field_end (protocol, error)) < 0) + return -1; + xfer += ret; + if ((ret = thrift_protocol_write_field_begin (protocol, "type", + T_I32, 2, error)) < 0) + return -1; + xfer += ret; + if ((ret = thrift_protocol_write_i32 (protocol, this->type, error)) < 0) + return -1; + xfer += ret; + if ((ret = thrift_protocol_write_field_end (protocol, error)) < 0) + return -1; + xfer += ret; + if ((ret = thrift_protocol_write_field_stop (protocol, error)) < 0) + return -1; + xfer += ret; + if ((ret = thrift_protocol_write_struct_end (protocol, error)) < 0) + return -1; + xfer += ret; + + return xfer; +} + + +/* GError domain */ +#define THRIFT_APPLICATION_EXCEPTION_ERROR_DOMAIN "thrift-application-exception-error-quark" + +GQuark +thrift_application_exception_error_quark (void) +{ + return g_quark_from_static_string (THRIFT_APPLICATION_EXCEPTION_ERROR_DOMAIN); +} + +static void +thrift_application_exception_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + ThriftApplicationException *tae = THRIFT_APPLICATION_EXCEPTION (object); + + switch (property_id) + { + case PROP_THRIFT_APPLICATION_EXCEPTION_TYPE: + g_value_set_int (value, tae->type); + break; + case PROP_THRIFT_APPLICATION_EXCEPTION_MESSAGE: + g_value_set_string (value, tae->message); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +thrift_application_exception_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + ThriftApplicationException *tae = THRIFT_APPLICATION_EXCEPTION (object); + + switch (property_id) + { + case PROP_THRIFT_APPLICATION_EXCEPTION_TYPE: + tae->type = g_value_get_int (value); + tae->__isset_type = TRUE; + break; + case PROP_THRIFT_APPLICATION_EXCEPTION_MESSAGE: + if (tae->message != NULL) + g_free (tae->message); + + tae->message = g_value_dup_string (value); + tae->__isset_message = TRUE; + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +void +thrift_application_exception_init (ThriftApplicationException *object) +{ + object->type = 0; + object->__isset_type = FALSE; + object->message = NULL; + object->__isset_message = FALSE; +} + +void +thrift_application_exception_finalize (GObject *object) +{ + ThriftApplicationException *tae = THRIFT_APPLICATION_EXCEPTION (object); + + if (tae->__isset_message) { + g_free(tae->message); + } +} + +void +thrift_application_exception_class_init (ThriftApplicationExceptionClass *class) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(class); + ThriftStructClass *cls = THRIFT_STRUCT_CLASS(class); + GParamSpec *param_spec; + + cls->read = thrift_application_exception_read; + cls->write = thrift_application_exception_write; + + gobject_class->finalize = thrift_application_exception_finalize; + gobject_class->get_property = thrift_application_exception_get_property; + gobject_class->set_property = thrift_application_exception_set_property; + + param_spec = g_param_spec_int ("type", + "Exception type", + "The type of the exception, one of the " + "values defined by the " + "ThriftApplicationExceptionError " + "enumeration.", + 0, + THRIFT_APPLICATION_EXCEPTION_ERROR_N - 1, + 0, + G_PARAM_READWRITE); + g_object_class_install_property (gobject_class, + PROP_THRIFT_APPLICATION_EXCEPTION_TYPE, + param_spec); + + param_spec = g_param_spec_string ("message", + "Exception message", + "A string describing the exception that " + "occurred.", + NULL, + G_PARAM_READWRITE); + g_object_class_install_property (gobject_class, + PROP_THRIFT_APPLICATION_EXCEPTION_MESSAGE, + param_spec); +} diff --git a/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/thrift_application_exception.h b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/thrift_application_exception.h new file mode 100644 index 000000000..733f793cb --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/thrift_application_exception.h @@ -0,0 +1,86 @@ +/* + * 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_APPLICATION_EXCEPTION_H +#define _THRIFT_APPLICATION_EXCEPTION_H + +#include <glib-object.h> +#include "thrift_struct.h" + +G_BEGIN_DECLS + +/*! \file thrift_application_exception.h + * \brief C Implementation of a TApplicationException. + */ + +/* type macros */ +#define THRIFT_TYPE_APPLICATION_EXCEPTION (thrift_application_exception_get_type ()) +#define THRIFT_APPLICATION_EXCEPTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THRIFT_TYPE_APPLICATION_EXCEPTION, ThriftApplicationException)) +#define THRIFT_IS_APPLICATION_EXCEPTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THRIFT_TYPE_APPLICATION_EXCEPTION)) +#define THRIFT_APPLICATION_EXCEPTION_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), THRIFT_TYPE_APPLICATION_EXCEPTION, ThriftApplicationExceptionClass)) +#define THRIFT_IS_APPLICATION_EXCEPTION_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), THRIFT_TYPE_APPLICATION_EXCEPTION)) +#define THRIFT_APPLICATION_EXCEPTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THRIFT_TYPE_APPLICATION_EXCEPTION, ThriftApplicationExceptionClass)) + +typedef struct _ThriftApplicationException ThriftApplicationException; + +struct _ThriftApplicationException +{ + ThriftStruct parent; + + /* private */ + gint32 type; + gboolean __isset_type; + gchar *message; + gboolean __isset_message; +}; + +typedef struct _ThriftApplicationExceptionClass ThriftApplicationExceptionClass; + +struct _ThriftApplicationExceptionClass +{ + ThriftStructClass parent; +}; + +GType thrift_application_exception_get_type (void); + +/* gerror codes */ +typedef enum +{ + THRIFT_APPLICATION_EXCEPTION_ERROR_UNKNOWN, + THRIFT_APPLICATION_EXCEPTION_ERROR_UNKNOWN_METHOD, + THRIFT_APPLICATION_EXCEPTION_ERROR_INVALID_MESSAGE_TYPE, + THRIFT_APPLICATION_EXCEPTION_ERROR_WRONG_METHOD_NAME, + THRIFT_APPLICATION_EXCEPTION_ERROR_BAD_SEQUENCE_ID, + THRIFT_APPLICATION_EXCEPTION_ERROR_MISSING_RESULT, + THRIFT_APPLICATION_EXCEPTION_ERROR_INTERNAL_ERROR, + THRIFT_APPLICATION_EXCEPTION_ERROR_PROTOCOL_ERROR, + THRIFT_APPLICATION_EXCEPTION_ERROR_INVALID_TRANSFORM, + THRIFT_APPLICATION_EXCEPTION_ERROR_INVALID_PROTOCOL, + THRIFT_APPLICATION_EXCEPTION_ERROR_UNSUPPORTED_CLIENT_TYPE, + + THRIFT_APPLICATION_EXCEPTION_ERROR_N +} ThriftApplicationExceptionError; + +/* define error domain for GError */ +GQuark thrift_application_exception_error_quark (void); +#define THRIFT_APPLICATION_EXCEPTION_ERROR (thrift_application_exception_error_quark ()) + +G_END_DECLS + +#endif /* _THRIFT_APPLICATION_EXCEPTION_H */ diff --git a/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/thrift_struct.c b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/thrift_struct.c new file mode 100644 index 000000000..f24f2a1c8 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/thrift_struct.c @@ -0,0 +1,52 @@ +/* + * 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 <thrift/c_glib/thrift.h> +#include "thrift_struct.h" + +G_DEFINE_ABSTRACT_TYPE(ThriftStruct, thrift_struct, G_TYPE_OBJECT) + +gint32 +thrift_struct_read (ThriftStruct *object, ThriftProtocol *protocol, + GError **error) +{ + g_return_val_if_fail (THRIFT_IS_STRUCT (object), -1); + return THRIFT_STRUCT_GET_CLASS (object)->read (object, protocol, error); +} + +gint32 +thrift_struct_write (ThriftStruct *object, ThriftProtocol *protocol, + GError **error) +{ + g_return_val_if_fail (THRIFT_IS_STRUCT (object), -1); + return THRIFT_STRUCT_GET_CLASS (object)->write (object, protocol, error); +} + +static void +thrift_struct_class_init (ThriftStructClass *cls) +{ + cls->read = thrift_struct_read; + cls->write = thrift_struct_write; +} + +static void +thrift_struct_init (ThriftStruct *structure) +{ + THRIFT_UNUSED_VAR (structure); +} diff --git a/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/thrift_struct.h b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/thrift_struct.h new file mode 100644 index 000000000..f4cfcb2c4 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/thrift_struct.h @@ -0,0 +1,68 @@ +/* + * 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_STRUCT_H +#define THRIFT_STRUCT_H + +#include <glib-object.h> + +#include <thrift/c_glib/protocol/thrift_protocol.h> + +G_BEGIN_DECLS + +#define THRIFT_TYPE_STRUCT (thrift_struct_get_type ()) +#define THRIFT_STRUCT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THRIFT_TYPE_STRUCT, ThriftStruct)) +#define THRIFT_STRUCT_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), THRIFT_TYPE_STRUCT, ThriftStructClass)) +#define THRIFT_IS_STRUCT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THRIFT_TYPE_STRUCT)) +#define THRIFT_IS_STRUCT_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), THRIFT_TYPE_STRUCT)) +#define THRIFT_STRUCT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THRIFT_TYPE_STRUCT, ThriftStructClass)) + +typedef struct _ThriftStruct ThriftStruct; + +/* struct */ +struct _ThriftStruct +{ + GObject parent; + + /* private */ +}; + +typedef struct _ThriftStructClass ThriftStructClass; + +struct _ThriftStructClass +{ + GObjectClass parent; + + /* public */ + gint32 (*read) (ThriftStruct *object, ThriftProtocol *protocol, + GError **error); + gint32 (*write) (ThriftStruct *object, ThriftProtocol *protocol, + GError **error); +}; + +GType thrift_struct_get_type (void); + +gint32 thrift_struct_read (ThriftStruct *object, ThriftProtocol *protocol, + GError **error); + +gint32 thrift_struct_write (ThriftStruct *object, ThriftProtocol *protocol, + GError **error); +G_END_DECLS + +#endif diff --git a/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_buffered_transport.c b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_buffered_transport.c new file mode 100644 index 000000000..0ab3e9329 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_buffered_transport.c @@ -0,0 +1,390 @@ +/* + * 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 <netdb.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> + +#include <thrift/c_glib/thrift.h> +#include <thrift/c_glib/transport/thrift_transport.h> +#include <thrift/c_glib/transport/thrift_buffered_transport.h> + +/* object properties */ +enum _ThriftBufferedTransportProperties +{ + PROP_0, + PROP_THRIFT_BUFFERED_TRANSPORT_TRANSPORT, + PROP_THRIFT_BUFFERED_TRANSPORT_READ_BUFFER_SIZE, + PROP_THRIFT_BUFFERED_TRANSPORT_WRITE_BUFFER_SIZE +}; + +G_DEFINE_TYPE(ThriftBufferedTransport, thrift_buffered_transport, THRIFT_TYPE_TRANSPORT) + +/* implements thrift_transport_is_open */ +gboolean +thrift_buffered_transport_is_open (ThriftTransport *transport) +{ + ThriftBufferedTransport *t = THRIFT_BUFFERED_TRANSPORT (transport); + return THRIFT_TRANSPORT_GET_CLASS (t->transport)->is_open (t->transport); +} + +/* overrides thrift_transport_peek */ +gboolean +thrift_buffered_transport_peek (ThriftTransport *transport, GError **error) +{ + ThriftBufferedTransport *t = THRIFT_BUFFERED_TRANSPORT (transport); + return (t->r_buf->len > 0) || thrift_transport_peek (t->transport, error); +} + +/* implements thrift_transport_open */ +gboolean +thrift_buffered_transport_open (ThriftTransport *transport, GError **error) +{ + ThriftBufferedTransport *t = THRIFT_BUFFERED_TRANSPORT (transport); + return THRIFT_TRANSPORT_GET_CLASS (t->transport)->open (t->transport, error); +} + +/* implements thrift_transport_close */ +gboolean +thrift_buffered_transport_close (ThriftTransport *transport, GError **error) +{ + ThriftBufferedTransport *t = THRIFT_BUFFERED_TRANSPORT (transport); + return THRIFT_TRANSPORT_GET_CLASS (t->transport)->close (t->transport, error); +} + +/* the actual read is "slow" because it calls the underlying transport */ +gint32 +thrift_buffered_transport_read_slow (ThriftTransport *transport, gpointer buf, + guint32 len, GError **error) +{ + ThriftBufferedTransport *t = THRIFT_BUFFERED_TRANSPORT (transport); + gint ret = 0; + guint32 want = len; + guint32 got = 0; + guchar *tmpdata = g_alloca (len); + guint32 have = t->r_buf->len; + + /* we shouldn't hit this unless the buffer doesn't have enough to read */ + g_assert (t->r_buf->len < want); + + /* first copy what we have in our buffer. */ + if (have > 0) + { + memcpy (buf, t->r_buf, t->r_buf->len); + want -= t->r_buf->len; + t->r_buf = g_byte_array_remove_range (t->r_buf, 0, t->r_buf->len); + } + + /* if the buffer is still smaller than what we want to read, then just + * read it directly. otherwise, fill the buffer and then give out + * enough to satisfy the read. */ + if (t->r_buf_size < want) + { + if ((ret = THRIFT_TRANSPORT_GET_CLASS (t->transport)->read (t->transport, + tmpdata, + want, + error)) < 0) { + return ret; + } + got += ret; + + /* copy the data starting from where we left off */ + memcpy ((guint8 *)buf + have, tmpdata, got); + return got + have; + } else { + guint32 give; + + if ((ret = THRIFT_TRANSPORT_GET_CLASS (t->transport)->read (t->transport, + tmpdata, + want, + error)) < 0) { + return ret; + } + got += ret; + t->r_buf = g_byte_array_append (t->r_buf, tmpdata, got); + + /* hand over what we have up to what the caller wants */ + give = want < t->r_buf->len ? want : t->r_buf->len; + + + memcpy ((guint8 *)buf + len - want, t->r_buf->data, give); + t->r_buf = g_byte_array_remove_range (t->r_buf, 0, give); + want -= give; + + return (len - want); + } +} + +/* implements thrift_transport_read */ +gint32 +thrift_buffered_transport_read (ThriftTransport *transport, gpointer buf, + guint32 len, GError **error) +{ + ThriftBufferedTransport *t = THRIFT_BUFFERED_TRANSPORT (transport); + + /* if we have enough buffer data to fulfill the read, just use + * a memcpy */ + if (len <= t->r_buf->len) + { + memcpy (buf, t->r_buf->data, len); + g_byte_array_remove_range (t->r_buf, 0, len); + return len; + } + + return thrift_buffered_transport_read_slow (transport, buf, len, error); +} + +/* implements thrift_transport_read_end + * called when write is complete. nothing to do on our end. */ +gboolean +thrift_buffered_transport_read_end (ThriftTransport *transport, GError **error) +{ + /* satisfy -Wall */ + THRIFT_UNUSED_VAR (transport); + THRIFT_UNUSED_VAR (error); + return TRUE; +} + +gboolean +thrift_buffered_transport_write_slow (ThriftTransport *transport, gpointer buf, + guint32 len, GError **error) +{ + ThriftBufferedTransport *t = THRIFT_BUFFERED_TRANSPORT (transport); + guint32 have_bytes = t->w_buf->len; + guint32 space = t->w_buf_size - t->w_buf->len; + + /* we need two syscalls because the buffered data plus the buffer itself + * is too big. */ + if ((have_bytes + len >= 2*t->w_buf_size) || (have_bytes == 0)) + { + if (have_bytes > 0) + { + if (!THRIFT_TRANSPORT_GET_CLASS (t->transport)->write (t->transport, + t->w_buf->data, + have_bytes, + error)) { + return FALSE; + } + t->w_buf = g_byte_array_remove_range (t->w_buf, 0, have_bytes); + } + if (!THRIFT_TRANSPORT_GET_CLASS (t->transport)->write (t->transport, + buf, len, error)) { + return FALSE; + } + return TRUE; + } + + t->w_buf = g_byte_array_append (t->w_buf, buf, space); + if (!THRIFT_TRANSPORT_GET_CLASS (t->transport)->write (t->transport, + t->w_buf->data, + t->w_buf->len, + error)) { + return FALSE; + } + + t->w_buf = g_byte_array_remove_range (t->w_buf, 0, t->w_buf->len); + t->w_buf = g_byte_array_append (t->w_buf, (guint8 *)buf + space, len-space); + + return TRUE; +} + +/* implements thrift_transport_write */ +gboolean +thrift_buffered_transport_write (ThriftTransport *transport, + const gpointer buf, + const guint32 len, GError **error) +{ + ThriftBufferedTransport *t = THRIFT_BUFFERED_TRANSPORT (transport); + + /* the length of the current buffer plus the length of the data being read */ + if (t->w_buf->len + len <= t->w_buf_size) + { + t->w_buf = g_byte_array_append (t->w_buf, buf, len); + return len; + } + + return thrift_buffered_transport_write_slow (transport, buf, len, error); +} + +/* implements thrift_transport_write_end + * called when write is complete. nothing to do on our end. */ +gboolean +thrift_buffered_transport_write_end (ThriftTransport *transport, GError **error) +{ + /* satisfy -Wall */ + THRIFT_UNUSED_VAR (transport); + THRIFT_UNUSED_VAR (error); + return TRUE; +} + +/* implements thrift_transport_flush */ +gboolean +thrift_buffered_transport_flush (ThriftTransport *transport, GError **error) +{ + ThriftBufferedTransport *t = THRIFT_BUFFERED_TRANSPORT (transport); + + if (t->w_buf != NULL && t->w_buf->len > 0) + { + /* write the buffer and then empty it */ + if (!THRIFT_TRANSPORT_GET_CLASS (t->transport)->write (t->transport, + t->w_buf->data, + t->w_buf->len, + error)) { + return FALSE; + } + t->w_buf = g_byte_array_remove_range (t->w_buf, 0, t->w_buf->len); + } + THRIFT_TRANSPORT_GET_CLASS (t->transport)->flush (t->transport, + error); + + return TRUE; +} + +/* initializes the instance */ +static void +thrift_buffered_transport_init (ThriftBufferedTransport *transport) +{ + transport->transport = NULL; + transport->r_buf = g_byte_array_new (); + transport->w_buf = g_byte_array_new (); +} + +/* destructor */ +static void +thrift_buffered_transport_finalize (GObject *object) +{ + ThriftBufferedTransport *transport = THRIFT_BUFFERED_TRANSPORT (object); + + if (transport->r_buf != NULL) + { + g_byte_array_free (transport->r_buf, TRUE); + } + transport->r_buf = NULL; + + if (transport->w_buf != NULL) + { + g_byte_array_free (transport->w_buf, TRUE); + } + transport->w_buf = NULL; +} + +/* property accessor */ +void +thrift_buffered_transport_get_property (GObject *object, guint property_id, + GValue *value, GParamSpec *pspec) +{ + ThriftBufferedTransport *transport = THRIFT_BUFFERED_TRANSPORT (object); + + THRIFT_UNUSED_VAR (pspec); + + switch (property_id) + { + case PROP_THRIFT_BUFFERED_TRANSPORT_TRANSPORT: + g_value_set_object (value, transport->transport); + break; + case PROP_THRIFT_BUFFERED_TRANSPORT_READ_BUFFER_SIZE: + g_value_set_uint (value, transport->r_buf_size); + break; + case PROP_THRIFT_BUFFERED_TRANSPORT_WRITE_BUFFER_SIZE: + g_value_set_uint (value, transport->w_buf_size); + break; + } +} + +/* property mutator */ +void +thrift_buffered_transport_set_property (GObject *object, guint property_id, + const GValue *value, GParamSpec *pspec) +{ + ThriftBufferedTransport *transport = THRIFT_BUFFERED_TRANSPORT (object); + + THRIFT_UNUSED_VAR (pspec); + + switch (property_id) + { + case PROP_THRIFT_BUFFERED_TRANSPORT_TRANSPORT: + transport->transport = g_value_get_object (value); + break; + case PROP_THRIFT_BUFFERED_TRANSPORT_READ_BUFFER_SIZE: + transport->r_buf_size = g_value_get_uint (value); + break; + case PROP_THRIFT_BUFFERED_TRANSPORT_WRITE_BUFFER_SIZE: + transport->w_buf_size = g_value_get_uint (value); + break; + } +} + +/* initializes the class */ +static void +thrift_buffered_transport_class_init (ThriftBufferedTransportClass *cls) +{ + ThriftTransportClass *ttc = THRIFT_TRANSPORT_CLASS (cls); + GObjectClass *gobject_class = G_OBJECT_CLASS (cls); + GParamSpec *param_spec = NULL; + + /* setup accessors and mutators */ + gobject_class->get_property = thrift_buffered_transport_get_property; + gobject_class->set_property = thrift_buffered_transport_set_property; + + param_spec = g_param_spec_object ("transport", "transport (construct)", + "Thrift transport", + THRIFT_TYPE_TRANSPORT, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + g_object_class_install_property (gobject_class, + PROP_THRIFT_BUFFERED_TRANSPORT_TRANSPORT, + param_spec); + + param_spec = g_param_spec_uint ("r_buf_size", + "read buffer size (construct)", + "Set the read buffer size", + 0, /* min */ + 1048576, /* max, 1024*1024 */ + 512, /* default value */ + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE); + g_object_class_install_property (gobject_class, + PROP_THRIFT_BUFFERED_TRANSPORT_READ_BUFFER_SIZE, + param_spec); + + param_spec = g_param_spec_uint ("w_buf_size", + "write buffer size (construct)", + "Set the write buffer size", + 0, /* min */ + 1048576, /* max, 1024*1024 */ + 512, /* default value */ + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE); + g_object_class_install_property (gobject_class, + PROP_THRIFT_BUFFERED_TRANSPORT_WRITE_BUFFER_SIZE, + param_spec); + + + gobject_class->finalize = thrift_buffered_transport_finalize; + ttc->is_open = thrift_buffered_transport_is_open; + ttc->peek = thrift_buffered_transport_peek; + ttc->open = thrift_buffered_transport_open; + ttc->close = thrift_buffered_transport_close; + ttc->read = thrift_buffered_transport_read; + ttc->read_end = thrift_buffered_transport_read_end; + ttc->write = thrift_buffered_transport_write; + ttc->write_end = thrift_buffered_transport_write_end; + ttc->flush = thrift_buffered_transport_flush; +} diff --git a/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_buffered_transport.h b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_buffered_transport.h new file mode 100644 index 000000000..837f46770 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_buffered_transport.h @@ -0,0 +1,77 @@ +/* + * 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_BUFFERED_TRANSPORT_H +#define _THRIFT_BUFFERED_TRANSPORT_H + +#include <glib.h> +#include <glib-object.h> + +#include <thrift/c_glib/transport/thrift_transport.h> + +G_BEGIN_DECLS + +/*! \file thrift_buffered_transport.h + * \brief Implementation of a Thrift buffered transport. Subclasses + * the ThriftTransport class. + */ + +/* type macros */ +#define THRIFT_TYPE_BUFFERED_TRANSPORT (thrift_buffered_transport_get_type ()) +#define THRIFT_BUFFERED_TRANSPORT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THRIFT_TYPE_BUFFERED_TRANSPORT, ThriftBufferedTransport)) +#define THRIFT_IS_BUFFERED_TRANSPORT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THRIFT_TYPE_BUFFERED_TRANSPORT)) +#define THRIFT_BUFFERED_TRANSPORT_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), THRIFT_TYPE_BUFFERED_TRANSPORT, ThriftBufferedTransportClass)) +#define THRIFT_IS_BUFFERED_TRANSPORT_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), THRIFT_TYPE_BUFFERED_TRANSPORT) +#define THRIFT_BUFFERED_TRANSPORT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THRIFT_TYPE_BUFFERED_TRANSPORT, ThriftBufferedTransportClass)) + +typedef struct _ThriftBufferedTransport ThriftBufferedTransport; + +/*! + * ThriftBufferedTransport instance. + */ +struct _ThriftBufferedTransport +{ + ThriftTransport parent; + + /* protected */ + ThriftTransport *transport; + + /* private */ + GByteArray *r_buf; + GByteArray *w_buf; + guint32 r_buf_size; + guint32 w_buf_size; +}; + +typedef struct _ThriftBufferedTransportClass ThriftBufferedTransportClass; + +/*! + * ThriftBufferedTransport class. + */ +struct _ThriftBufferedTransportClass +{ + ThriftTransportClass parent; +}; + +/* used by THRIFT_TYPE_BUFFERED_TRANSPORT */ +GType thrift_buffered_transport_get_type (void); + +G_END_DECLS + +#endif diff --git a/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_buffered_transport_factory.c b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_buffered_transport_factory.c new file mode 100644 index 000000000..86050b691 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_buffered_transport_factory.c @@ -0,0 +1,55 @@ +/* + * 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 <thrift/c_glib/thrift.h> +#include <thrift/c_glib/transport/thrift_buffered_transport.h> +#include <thrift/c_glib/transport/thrift_buffered_transport_factory.h> + +G_DEFINE_TYPE (ThriftBufferedTransportFactory, + thrift_buffered_transport_factory, + THRIFT_TYPE_TRANSPORT_FACTORY) + +/* Wraps a transport with a ThriftBufferedTransport. */ +ThriftTransport * +thrift_buffered_transport_factory_get_transport (ThriftTransportFactory *factory, + ThriftTransport *transport) +{ + THRIFT_UNUSED_VAR (factory); + + return THRIFT_TRANSPORT (g_object_new (THRIFT_TYPE_BUFFERED_TRANSPORT, + "transport", transport, + NULL)); +} + +static void +thrift_buffered_transport_factory_init (ThriftBufferedTransportFactory *self) +{ + THRIFT_UNUSED_VAR (self); +} + +static void +thrift_buffered_transport_factory_class_init (ThriftBufferedTransportFactoryClass *klass) +{ + ThriftTransportFactoryClass *base_class = + THRIFT_TRANSPORT_FACTORY_CLASS (klass); + + base_class->get_transport = + klass->get_transport = + thrift_buffered_transport_factory_get_transport; +} diff --git a/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_buffered_transport_factory.h b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_buffered_transport_factory.h new file mode 100644 index 000000000..d43f4e4ad --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_buffered_transport_factory.h @@ -0,0 +1,86 @@ +/* + * 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_BUFFERED_TRANSPORT_FACTORY_H +#define _THRIFT_BUFFERED_TRANSPORT_FACTORY_H + +#include <glib-object.h> + +#include <thrift/c_glib/transport/thrift_transport.h> +#include <thrift/c_glib/transport/thrift_transport_factory.h> + +G_BEGIN_DECLS + +/*! \file thrift_buffered_transport_factory.h + * \brief Wraps a transport with a ThriftBufferedTransport. + */ + +/* type macros */ +#define THRIFT_TYPE_BUFFERED_TRANSPORT_FACTORY \ + (thrift_buffered_transport_factory_get_type ()) +#define THRIFT_BUFFERED_TRANSPORT_FACTORY(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + THRIFT_TYPE_BUFFERED_TRANSPORT_FACTORY, \ + ThriftBufferedTransportFactory)) +#define THRIFT_IS_BUFFERED_TRANSPORT_FACTORY(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ + THRIFT_TYPE_BUFFERED_TRANSPORT_FACTORY)) +#define THRIFT_BUFFERED_TRANSPORT_FACTORY_CLASS(c) \ + (G_TYPE_CHECK_CLASS_CAST ((c), \ + THRIFT_TYPE_BUFFERED_TRANSPORT_FACTORY, \ + ThriftBufferedTransportFactoryClass)) +#define THRIFT_IS_BUFFERED_TRANSPORT_FACTORY_CLASS(c) \ + (G_TYPE_CHECK_CLASS_TYPE ((c), \ + THRIFT_TYPE_BUFFERED_TRANSPORT_FACTORY)) +#define THRIFT_BUFFERED_TRANSPORT_FACTORY_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + THRIFT_TYPE_BUFFERED_TRANSPORT_FACTORY, \ + ThriftBufferedTransportFactoryClass)) + +typedef struct _ThriftBufferedTransportFactory ThriftBufferedTransportFactory; + +/* Thrift Buffered-Transport Factory instance */ +struct _ThriftBufferedTransportFactory +{ + ThriftTransportFactory parent; +}; + +typedef struct _ThriftBufferedTransportFactoryClass ThriftBufferedTransportFactoryClass; + +/* Thrift Buffered-Transport Factory class */ +struct _ThriftBufferedTransportFactoryClass +{ + ThriftTransportFactoryClass parent; + + /* vtable */ + ThriftTransport *(*get_transport) (ThriftTransportFactory *factory, + ThriftTransport *transport); +}; + +/* used by THRIFT_TYPE_BUFFERED_TRANSPORT_FACTORY */ +GType thrift_buffered_transport_factory_get_type (void); + +/* virtual public methods */ +ThriftTransport * +thrift_buffered_transport_factory_get_transport (ThriftTransportFactory *factory, + ThriftTransport *transport); + +G_END_DECLS + +#endif /* _THRIFT_BUFFERED_TRANSPORT_FACTORY_H */ diff --git a/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_fd_transport.c b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_fd_transport.c new file mode 100644 index 000000000..14abff7a4 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_fd_transport.c @@ -0,0 +1,265 @@ +/* + * 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 <unistd.h> +#include <fcntl.h> +#include <string.h> + +#include <glib.h> +#include <glib/gstdio.h> + +#include <thrift/c_glib/thrift.h> +#include <thrift/c_glib/transport/thrift_transport.h> +#include <thrift/c_glib/transport/thrift_fd_transport.h> + +/* object properties */ +enum _ThriftFDTransportProperties +{ + PROP_0, + PROP_THRIFT_FD_TRANSPORT_FD +}; + +G_DEFINE_TYPE (ThriftFDTransport, thrift_fd_transport, THRIFT_TYPE_TRANSPORT) + +/* implements thrift_transport_is_open */ +gboolean +thrift_fd_transport_is_open (ThriftTransport *transport) +{ + ThriftFDTransport *t; + t = THRIFT_FD_TRANSPORT (transport); + return t->fd >= 0 && ! (fcntl (t->fd, F_GETFL) == -1 && errno == EBADF); +} + +/* implements thrift_transport_open */ +gboolean +thrift_fd_transport_open (ThriftTransport *transport, GError **error) +{ + THRIFT_UNUSED_VAR (error); + return thrift_fd_transport_is_open (transport); +} + +/* implements thrift_transport_close */ +gboolean +thrift_fd_transport_close (ThriftTransport *transport, GError **error) +{ + ThriftFDTransport *t; + t = THRIFT_FD_TRANSPORT (transport); + +#if GLIB_CHECK_VERSION (2, 36, 0) + return g_close (t->fd, error); +#else + if (close (t->fd) == 0) { + g_clear_error (error); + return TRUE; + } else { + g_set_error (error, + THRIFT_TRANSPORT_ERROR, + THRIFT_TRANSPORT_ERROR_CLOSE, + strerror (errno)); + return FALSE; + } +#endif +} + +/* implements thrift_transport_read */ +gint32 +thrift_fd_transport_read (ThriftTransport *transport, gpointer buf, + guint32 len, GError **error) +{ + ThriftFDTransport *t; + ssize_t n; + + t = THRIFT_FD_TRANSPORT (transport); + n = read (t->fd, (guint8 *) buf, len); + if (n == -1) { + g_set_error (error, + THRIFT_TRANSPORT_ERROR, + THRIFT_TRANSPORT_ERROR_RECEIVE, + "Failed to read from fd: %s", + strerror (errno)); + return -1; + } + return n; +} + +/* implements thrift_transport_read_end + * called when write is complete. nothing to do on our end. */ +gboolean +thrift_fd_transport_read_end (ThriftTransport *transport, GError **error) +{ + /* satisfy -Wall */ + THRIFT_UNUSED_VAR (transport); + THRIFT_UNUSED_VAR (error); + return TRUE; +} + +/* implements thrift_transport_write */ +gboolean +thrift_fd_transport_write (ThriftTransport *transport, + const gpointer buf, + const guint32 len, GError **error) +{ + ThriftFDTransport *t; + guint8 *_buf; + guint32 _len; + ssize_t n; + + t = THRIFT_FD_TRANSPORT (transport); + _buf = (guint8 *) buf; + _len = len; + while (_len > 0) { + n = write (t->fd, _buf, _len); + if (n == -1) { + g_set_error (error, + THRIFT_TRANSPORT_ERROR, + THRIFT_TRANSPORT_ERROR_SEND, + "Failed to write from fd: %s", + strerror (errno)); + return FALSE; + } else { + _buf += n; + _len -= n; + } + } + return TRUE; +} + +/* implements thrift_transport_write_end + * called when write is complete. nothing to do on our end. */ +gboolean +thrift_fd_transport_write_end (ThriftTransport *transport, GError **error) +{ + THRIFT_UNUSED_VAR (transport); + THRIFT_UNUSED_VAR (error); + return TRUE; +} + +/* implements thrift_transport_flush */ +gboolean +thrift_fd_transport_flush (ThriftTransport *transport, GError **error) +{ + ThriftFDTransport *t; + t = THRIFT_FD_TRANSPORT (transport); + if (fsync (t->fd) == -1) { + g_set_error (error, + THRIFT_TRANSPORT_ERROR, + THRIFT_TRANSPORT_ERROR_UNKNOWN, + "Failed to flush fd: %s", + strerror (errno)); + return FALSE; + } else { + return TRUE; + } +} + +/* initializes the instance */ +static void +thrift_fd_transport_init (ThriftFDTransport *transport) +{ + transport->fd = -1; +} + +/* destructor */ +static void +thrift_fd_transport_finalize (GObject *object) +{ + THRIFT_UNUSED_VAR (object); +} + +/* property accessor */ +void +thrift_fd_transport_get_property (GObject *object, guint property_id, + GValue *value, GParamSpec *pspec) +{ + ThriftFDTransport *t; + + THRIFT_UNUSED_VAR (pspec); + + t = THRIFT_FD_TRANSPORT (object); + + switch (property_id) { + case PROP_THRIFT_FD_TRANSPORT_FD: + g_value_set_int (value, t->fd); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +/* property mutator */ +void +thrift_fd_transport_set_property (GObject *object, guint property_id, + const GValue *value, GParamSpec *pspec) +{ + ThriftFDTransport *t; + + THRIFT_UNUSED_VAR (pspec); + + t = THRIFT_FD_TRANSPORT (object); + + switch (property_id) { + case PROP_THRIFT_FD_TRANSPORT_FD: + t->fd = g_value_get_int (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +/* initializes the class */ +static void +thrift_fd_transport_class_init (ThriftFDTransportClass *cls) +{ + ThriftTransportClass *ttc; + GObjectClass *gobject_class; + GParamSpec *param_spec; + + ttc = THRIFT_TRANSPORT_CLASS (cls); + gobject_class = G_OBJECT_CLASS (cls); + param_spec = NULL; + + /* setup accessors and mutators */ + gobject_class->get_property = thrift_fd_transport_get_property; + gobject_class->set_property = thrift_fd_transport_set_property; + + param_spec = g_param_spec_int ("fd", + "file descriptor (construct)", + "Set the file descriptor", + INT_MIN, /* min */ + INT_MAX, /* max, 1024*1024 */ + -1, /* default value */ + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE); + g_object_class_install_property (gobject_class, + PROP_THRIFT_FD_TRANSPORT_FD, + param_spec); + + gobject_class->finalize = thrift_fd_transport_finalize; + ttc->is_open = thrift_fd_transport_is_open; + ttc->open = thrift_fd_transport_open; + ttc->close = thrift_fd_transport_close; + ttc->read = thrift_fd_transport_read; + ttc->read_end = thrift_fd_transport_read_end; + ttc->write = thrift_fd_transport_write; + ttc->write_end = thrift_fd_transport_write_end; + ttc->flush = thrift_fd_transport_flush; +} diff --git a/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_fd_transport.h b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_fd_transport.h new file mode 100644 index 000000000..0e6d5c4b3 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_fd_transport.h @@ -0,0 +1,74 @@ +/* + * 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_FD_TRANSPORT_H +#define _THRIFT_FD_TRANSPORT_H + +#include <glib-object.h> + +#include "thrift_transport.h" + +G_BEGIN_DECLS + +/*! \file thrift_fd_transport.h + * \brief Class for Thrift file descriptor transports. + */ + +/* type macros */ +#define THRIFT_TYPE_FD_TRANSPORT (thrift_fd_transport_get_type ()) +#define THRIFT_FD_TRANSPORT(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), THRIFT_TYPE_FD_TRANSPORT, \ + ThriftFDTransport)) +#define THRIFT_IS_FD_TRANSPORT(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THRIFT_TYPE_FD_TRANSPORT)) +#define THRIFT_FD_TRANSPORT_CLASS(c) \ + (G_TYPE_CHECK_CLASS_CAST ((c), THRIFT_TYPE_FD_TRANSPORT, \ + ThriftFDTransportClass)) +#define THRIFT_IS_FD_TRANSPORT_CLASS(c) \ + (G_TYPE_CHECK_CLASS_TYPE ((c), THRIFT_TYPE_FD_TRANSPORT)) +#define THRIFT_FD_TRANSPORT_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), THRIFT_TYPE_FD_TRANSPORT, \ + ThriftFDTransportClass)) + +typedef struct _ThriftFDTransport ThriftFDTransport; + +struct _ThriftFDTransport +{ + ThriftTransport parent; + + /* protected */ + gint fd; +}; + +typedef struct _ThriftFDTransportClass ThriftFDTransportClass; + +/*! + * Thrift Transport class + */ +struct _ThriftFDTransportClass +{ + ThriftTransportClass parent; +}; + +/* used by THRIFT_TYPE_FD_TRANSPORT */ +GType thrift_fd_transport_get_type (void); + +G_END_DECLS + +#endif /* _THRIFT_FD_TRANSPORT_H */ diff --git a/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_framed_transport.c b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_framed_transport.c new file mode 100644 index 000000000..c54824635 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_framed_transport.c @@ -0,0 +1,383 @@ +/* + * 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 <netdb.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <sys/socket.h> +#include <netinet/in.h> + +#include <thrift/c_glib/thrift.h> +#include <thrift/c_glib/transport/thrift_transport.h> +#include <thrift/c_glib/transport/thrift_framed_transport.h> + +/* object properties */ +enum _ThriftFramedTransportProperties +{ + PROP_0, + PROP_THRIFT_FRAMED_TRANSPORT_TRANSPORT, + PROP_THRIFT_FRAMED_TRANSPORT_READ_BUFFER_SIZE, + PROP_THRIFT_FRAMED_TRANSPORT_WRITE_BUFFER_SIZE +}; + +G_DEFINE_TYPE(ThriftFramedTransport, thrift_framed_transport, THRIFT_TYPE_TRANSPORT) + +/* implements thrift_transport_is_open */ +gboolean +thrift_framed_transport_is_open (ThriftTransport *transport) +{ + ThriftFramedTransport *t = THRIFT_FRAMED_TRANSPORT (transport); + return THRIFT_TRANSPORT_GET_CLASS (t->transport)->is_open (t->transport); +} + +/* overrides thrift_transport_peek */ +gboolean +thrift_framed_transport_peek (ThriftTransport *transport, GError **error) +{ + ThriftFramedTransport *t = THRIFT_FRAMED_TRANSPORT (transport); + return (t->r_buf->len > 0) || thrift_transport_peek (t->transport, error); +} + +/* implements thrift_transport_open */ +gboolean +thrift_framed_transport_open (ThriftTransport *transport, GError **error) +{ + ThriftFramedTransport *t = THRIFT_FRAMED_TRANSPORT (transport); + return THRIFT_TRANSPORT_GET_CLASS (t->transport)->open (t->transport, error); +} + +/* implements thrift_transport_close */ +gboolean +thrift_framed_transport_close (ThriftTransport *transport, GError **error) +{ + ThriftFramedTransport *t = THRIFT_FRAMED_TRANSPORT (transport); + return THRIFT_TRANSPORT_GET_CLASS (t->transport)->close (t->transport, error); +} + +/* reads a frame and puts it into the buffer */ +gboolean +thrift_framed_transport_read_frame (ThriftTransport *transport, + GError **error) +{ + ThriftFramedTransport *t = THRIFT_FRAMED_TRANSPORT (transport); + guint32 sz; + gint32 bytes; + gboolean result = FALSE; + + /* read the size */ + if (thrift_transport_read (t->transport, + &sz, + sizeof (sz), + error) == sizeof (sz)) + { + guchar *tmpdata; + + sz = ntohl (sz); + + /* create a buffer to hold the data and read that much data */ + tmpdata = g_alloca (sz); + bytes = thrift_transport_read (t->transport, tmpdata, sz, error); + + if (bytes > 0 && (error == NULL || *error == NULL)) + { + /* add the data to the buffer */ + g_byte_array_append (t->r_buf, tmpdata, bytes); + + result = TRUE; + } + } + + return result; +} + +/* the actual read is "slow" because it calls the underlying transport */ +gint32 +thrift_framed_transport_read_slow (ThriftTransport *transport, gpointer buf, + guint32 len, GError **error) +{ + ThriftFramedTransport *t = THRIFT_FRAMED_TRANSPORT (transport); + guint32 want = len; + guint32 have = t->r_buf->len; + gint32 result = -1; + + /* we shouldn't hit this unless the buffer doesn't have enough to read */ + g_assert (t->r_buf->len < want); + + /* first copy what we have in our buffer, if there is anything left */ + if (have > 0) + { + memcpy (buf, t->r_buf, t->r_buf->len); + want -= t->r_buf->len; + t->r_buf = g_byte_array_remove_range (t->r_buf, 0, t->r_buf->len); + } + + /* read a frame of input and buffer it */ + if (thrift_framed_transport_read_frame (transport, error) == TRUE) + { + /* hand over what we have up to what the caller wants */ + guint32 give = want < t->r_buf->len ? want : t->r_buf->len; + + /* copy the data into the buffer */ + memcpy ((guint8 *)buf + len - want, t->r_buf->data, give); + t->r_buf = g_byte_array_remove_range (t->r_buf, 0, give); + want -= give; + + result = len - want; + } + + return result; +} + +/* implements thrift_transport_read */ +gint32 +thrift_framed_transport_read (ThriftTransport *transport, gpointer buf, + guint32 len, GError **error) +{ + ThriftFramedTransport *t = THRIFT_FRAMED_TRANSPORT (transport); + + /* if we have enough buffer data to fulfill the read, just use + * a memcpy from the buffer */ + if (len <= t->r_buf->len) + { + memcpy (buf, t->r_buf->data, len); + g_byte_array_remove_range (t->r_buf, 0, len); + return len; + } + + return thrift_framed_transport_read_slow (transport, buf, len, error); +} + +/* implements thrift_transport_read_end + * called when read is complete. nothing to do on our end. */ +gboolean +thrift_framed_transport_read_end (ThriftTransport *transport, GError **error) +{ + /* satisfy -Wall */ + THRIFT_UNUSED_VAR (transport); + THRIFT_UNUSED_VAR (error); + return TRUE; +} + +gboolean +thrift_framed_transport_write_slow (ThriftTransport *transport, gpointer buf, + guint32 len, GError **error) +{ + ThriftFramedTransport *t = THRIFT_FRAMED_TRANSPORT (transport); + + THRIFT_UNUSED_VAR (error); + + /* append the data to the buffer and we're done */ + g_byte_array_append (t->w_buf, buf, len); + + return TRUE; +} + +/* implements thrift_transport_write */ +gboolean +thrift_framed_transport_write (ThriftTransport *transport, + const gpointer buf, + const guint32 len, GError **error) +{ + ThriftFramedTransport *t = THRIFT_FRAMED_TRANSPORT (transport); + + /* the length of the current buffer plus the length of the data being read */ + if (t->w_buf->len + len <= t->w_buf_size) + { + t->w_buf = g_byte_array_append (t->w_buf, buf, len); + return TRUE; + } + + return thrift_framed_transport_write_slow (transport, buf, len, error); +} + +/* implements thrift_transport_write_end + * called when write is complete. nothing to do on our end. */ +gboolean +thrift_framed_transport_write_end (ThriftTransport *transport, GError **error) +{ + /* satisfy -Wall */ + THRIFT_UNUSED_VAR (transport); + THRIFT_UNUSED_VAR (error); + return TRUE; +} + +/* implements thrift_transport_flush */ +gboolean +thrift_framed_transport_flush (ThriftTransport *transport, GError **error) +{ + ThriftFramedTransport *t = THRIFT_FRAMED_TRANSPORT (transport); + gint32 sz_hbo, sz_nbo; + guchar *tmpdata; + + /* get the size of the frame in host and network byte order */ + sz_hbo = t->w_buf->len + sizeof(sz_nbo); + sz_nbo = (gint32) htonl ((guint32) t->w_buf->len); + + /* copy the size of the frame and then the frame itself */ + tmpdata = g_alloca (sz_hbo); + memcpy (tmpdata, (guint8 *) &sz_nbo, sizeof (sz_nbo)); + + if (t->w_buf->len > 0) + { + memcpy (tmpdata + sizeof (sz_nbo), t->w_buf->data, t->w_buf->len); + t->w_buf = g_byte_array_remove_range (t->w_buf, 0, t->w_buf->len); + } + + /* write the buffer and then empty it */ + THRIFT_TRANSPORT_GET_CLASS (t->transport)->write (t->transport, + tmpdata, sz_hbo, + error); + + THRIFT_TRANSPORT_GET_CLASS (t->transport)->flush (t->transport, + error); + + return TRUE; +} + +/* initializes the instance */ +static void +thrift_framed_transport_init (ThriftFramedTransport *transport) +{ + transport->transport = NULL; + transport->r_buf = g_byte_array_new (); + transport->w_buf = g_byte_array_new (); +} + +/* destructor */ +static void +thrift_framed_transport_finalize (GObject *object) +{ + ThriftFramedTransport *transport = THRIFT_FRAMED_TRANSPORT (object); + + if (transport->r_buf != NULL) + { + g_byte_array_free (transport->r_buf, TRUE); + } + transport->r_buf = NULL; + + if (transport->w_buf != NULL) + { + g_byte_array_free (transport->w_buf, TRUE); + } + transport->w_buf = NULL; +} + +/* property accessor */ +void +thrift_framed_transport_get_property (GObject *object, guint property_id, + GValue *value, GParamSpec *pspec) +{ + ThriftFramedTransport *transport = THRIFT_FRAMED_TRANSPORT (object); + + THRIFT_UNUSED_VAR (pspec); + + switch (property_id) + { + case PROP_THRIFT_FRAMED_TRANSPORT_TRANSPORT: + g_value_set_object (value, transport->transport); + break; + case PROP_THRIFT_FRAMED_TRANSPORT_READ_BUFFER_SIZE: + g_value_set_uint (value, transport->r_buf_size); + break; + case PROP_THRIFT_FRAMED_TRANSPORT_WRITE_BUFFER_SIZE: + g_value_set_uint (value, transport->w_buf_size); + break; + } +} + +/* property mutator */ +void +thrift_framed_transport_set_property (GObject *object, guint property_id, + const GValue *value, GParamSpec *pspec) +{ + ThriftFramedTransport *transport = THRIFT_FRAMED_TRANSPORT (object); + + THRIFT_UNUSED_VAR (pspec); + + switch (property_id) + { + case PROP_THRIFT_FRAMED_TRANSPORT_TRANSPORT: + transport->transport = g_value_get_object (value); + break; + case PROP_THRIFT_FRAMED_TRANSPORT_READ_BUFFER_SIZE: + transport->r_buf_size = g_value_get_uint (value); + break; + case PROP_THRIFT_FRAMED_TRANSPORT_WRITE_BUFFER_SIZE: + transport->w_buf_size = g_value_get_uint (value); + break; + } +} + +/* initializes the class */ +static void +thrift_framed_transport_class_init (ThriftFramedTransportClass *cls) +{ + ThriftTransportClass *ttc = THRIFT_TRANSPORT_CLASS (cls); + GObjectClass *gobject_class = G_OBJECT_CLASS (cls); + GParamSpec *param_spec = NULL; + + /* setup accessors and mutators */ + gobject_class->get_property = thrift_framed_transport_get_property; + gobject_class->set_property = thrift_framed_transport_set_property; + + param_spec = g_param_spec_object ("transport", "transport (construct)", + "Thrift transport", + THRIFT_TYPE_TRANSPORT, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + g_object_class_install_property (gobject_class, + PROP_THRIFT_FRAMED_TRANSPORT_TRANSPORT, + param_spec); + + param_spec = g_param_spec_uint ("r_buf_size", + "read buffer size (construct)", + "Set the read buffer size", + 0, /* min */ + 1048576, /* max, 1024*1024 */ + 512, /* default value */ + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE); + g_object_class_install_property (gobject_class, + PROP_THRIFT_FRAMED_TRANSPORT_READ_BUFFER_SIZE, + param_spec); + + param_spec = g_param_spec_uint ("w_buf_size", + "write buffer size (construct)", + "Set the write buffer size", + 0, /* min */ + 1048576, /* max, 1024*1024 */ + 512, /* default value */ + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE); + g_object_class_install_property (gobject_class, + PROP_THRIFT_FRAMED_TRANSPORT_WRITE_BUFFER_SIZE, + param_spec); + + gobject_class->finalize = thrift_framed_transport_finalize; + ttc->is_open = thrift_framed_transport_is_open; + ttc->peek = thrift_framed_transport_peek; + ttc->open = thrift_framed_transport_open; + ttc->close = thrift_framed_transport_close; + ttc->read = thrift_framed_transport_read; + ttc->read_end = thrift_framed_transport_read_end; + ttc->write = thrift_framed_transport_write; + ttc->write_end = thrift_framed_transport_write_end; + ttc->flush = thrift_framed_transport_flush; +} diff --git a/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_framed_transport.h b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_framed_transport.h new file mode 100644 index 000000000..95c012393 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_framed_transport.h @@ -0,0 +1,77 @@ +/* + * 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_FRAMED_TRANSPORT_H +#define _THRIFT_FRAMED_TRANSPORT_H + +#include <glib.h> +#include <glib-object.h> + +#include <thrift/c_glib/transport/thrift_transport.h> + +G_BEGIN_DECLS + +/*! \file thrift_framed_transport.h + * \brief Implementation of a Thrift framed transport. Subclasses + * the ThriftTransport class. + */ + +/* type macros */ +#define THRIFT_TYPE_FRAMED_TRANSPORT (thrift_framed_transport_get_type ()) +#define THRIFT_FRAMED_TRANSPORT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THRIFT_TYPE_FRAMED_TRANSPORT, ThriftFramedTransport)) +#define THRIFT_IS_FRAMED_TRANSPORT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THRIFT_TYPE_FRAMED_TRANSPORT)) +#define THRIFT_FRAMED_TRANSPORT_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), THRIFT_TYPE_FRAMED_TRANSPORT, ThriftFramedTransportClass)) +#define THRIFT_IS_FRAMED_TRANSPORT_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), THRIFT_TYPE_FRAMED_TRANSPORT) +#define THRIFT_FRAMED_TRANSPORT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THRIFT_TYPE_FRAMED_TRANSPORT, ThriftFramedTransportClass)) + +typedef struct _ThriftFramedTransport ThriftFramedTransport; + +/*! + * ThriftFramedTransport instance. + */ +struct _ThriftFramedTransport +{ + ThriftTransport parent; + + /* protected */ + ThriftTransport *transport; + + /* private */ + GByteArray *r_buf; + GByteArray *w_buf; + guint32 r_buf_size; + guint32 w_buf_size; +}; + +typedef struct _ThriftFramedTransportClass ThriftFramedTransportClass; + +/*! + * ThriftFramedTransport class. + */ +struct _ThriftFramedTransportClass +{ + ThriftTransportClass parent; +}; + +/* used by THRIFT_TYPE_FRAMED_TRANSPORT */ +GType thrift_framed_transport_get_type (void); + +G_END_DECLS + +#endif diff --git a/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_framed_transport_factory.c b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_framed_transport_factory.c new file mode 100644 index 000000000..e68fe0a24 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_framed_transport_factory.c @@ -0,0 +1,55 @@ +/* + * 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 <thrift/c_glib/thrift.h> +#include <thrift/c_glib/transport/thrift_framed_transport.h> +#include <thrift/c_glib/transport/thrift_framed_transport_factory.h> + +G_DEFINE_TYPE (ThriftFramedTransportFactory, + thrift_framed_transport_factory, + THRIFT_TYPE_TRANSPORT_FACTORY) + +/* Wraps a transport with a ThriftFramedTransport. */ +ThriftTransport * +thrift_framed_transport_factory_get_transport (ThriftTransportFactory *factory, + ThriftTransport *transport) +{ + THRIFT_UNUSED_VAR (factory); + + return THRIFT_TRANSPORT (g_object_new (THRIFT_TYPE_FRAMED_TRANSPORT, + "transport", transport, + NULL)); +} + +static void +thrift_framed_transport_factory_init (ThriftFramedTransportFactory *self) +{ + THRIFT_UNUSED_VAR (self); +} + +static void +thrift_framed_transport_factory_class_init (ThriftFramedTransportFactoryClass *klass) +{ + ThriftTransportFactoryClass *base_class = + THRIFT_TRANSPORT_FACTORY_CLASS (klass); + + base_class->get_transport = + klass->get_transport = + thrift_framed_transport_factory_get_transport; +} diff --git a/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_framed_transport_factory.h b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_framed_transport_factory.h new file mode 100644 index 000000000..c3e94962f --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_framed_transport_factory.h @@ -0,0 +1,86 @@ +/* + * 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_FRAMED_TRANSPORT_FACTORY_H +#define _THRIFT_FRAMED_TRANSPORT_FACTORY_H + +#include <glib-object.h> + +#include <thrift/c_glib/transport/thrift_transport.h> +#include <thrift/c_glib/transport/thrift_transport_factory.h> + +G_BEGIN_DECLS + +/*! \file thrift_framed_transport_factory.h + * \brief Wraps a transport with a ThriftFramedTransport. + */ + +/* type macros */ +#define THRIFT_TYPE_FRAMED_TRANSPORT_FACTORY \ + (thrift_framed_transport_factory_get_type ()) +#define THRIFT_FRAMED_TRANSPORT_FACTORY(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + THRIFT_TYPE_FRAMED_TRANSPORT_FACTORY, \ + ThriftFramedTransportFactory)) +#define THRIFT_IS_FRAMED_TRANSPORT_FACTORY(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ + THRIFT_TYPE_FRAMED_TRANSPORT_FACTORY)) +#define THRIFT_FRAMED_TRANSPORT_FACTORY_CLASS(c) \ + (G_TYPE_CHECK_CLASS_CAST ((c), \ + THRIFT_TYPE_FRAMED_TRANSPORT_FACTORY, \ + ThriftFramedTransportFactoryClass)) +#define THRIFT_IS_FRAMED_TRANSPORT_FACTORY_CLASS(c) \ + (G_TYPE_CHECK_CLASS_TYPE ((c), \ + THRIFT_TYPE_FRAMED_TRANSPORT_FACTORY)) +#define THRIFT_FRAMED_TRANSPORT_FACTORY_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + THRIFT_TYPE_FRAMED_TRANSPORT_FACTORY, \ + ThriftFramedTransportFactoryClass)) + +typedef struct _ThriftFramedTransportFactory ThriftFramedTransportFactory; + +/* Thrift Framed-Transport Factory instance */ +struct _ThriftFramedTransportFactory +{ + ThriftTransportFactory parent; +}; + +typedef struct _ThriftFramedTransportFactoryClass ThriftFramedTransportFactoryClass; + +/* Thrift Framed-Transport Factory class */ +struct _ThriftFramedTransportFactoryClass +{ + ThriftTransportFactoryClass parent; + + /* vtable */ + ThriftTransport *(*get_transport) (ThriftTransportFactory *factory, + ThriftTransport *transport); +}; + +/* used by THRIFT_TYPE_FRAMED_TRANSPORT_FACTORY */ +GType thrift_framed_transport_factory_get_type (void); + +/* virtual public methods */ +ThriftTransport * +thrift_framed_transport_factory_get_transport (ThriftTransportFactory *factory, + ThriftTransport *transport); + +G_END_DECLS + +#endif /* _THRIFT_FRAMED_TRANSPORT_FACTORY_H */ diff --git a/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_memory_buffer.c b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_memory_buffer.c new file mode 100644 index 000000000..91818e91a --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_memory_buffer.c @@ -0,0 +1,285 @@ +/* + * 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 <netdb.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> + +#include <thrift/c_glib/thrift.h> +#include <thrift/c_glib/transport/thrift_transport.h> +#include <thrift/c_glib/transport/thrift_memory_buffer.h> + +/* object properties */ +enum _ThriftMemoryBufferProperties +{ + PROP_0, + PROP_THRIFT_MEMORY_BUFFER_BUFFER_SIZE, + PROP_THRIFT_MEMORY_BUFFER_BUFFER, + PROP_THRIFT_MEMORY_BUFFER_OWNER +}; + +G_DEFINE_TYPE(ThriftMemoryBuffer, thrift_memory_buffer, THRIFT_TYPE_TRANSPORT) + +/* implements thrift_transport_is_open */ +gboolean +thrift_memory_buffer_is_open (ThriftTransport *transport) +{ + THRIFT_UNUSED_VAR (transport); + return TRUE; +} + +/* implements thrift_transport_open */ +gboolean +thrift_memory_buffer_open (ThriftTransport *transport, GError **error) +{ + THRIFT_UNUSED_VAR (transport); + THRIFT_UNUSED_VAR (error); + return TRUE; +} + +/* implements thrift_transport_close */ +gboolean +thrift_memory_buffer_close (ThriftTransport *transport, GError **error) +{ + THRIFT_UNUSED_VAR (transport); + THRIFT_UNUSED_VAR (error); + return TRUE; +} + +/* implements thrift_transport_read */ +gint32 +thrift_memory_buffer_read (ThriftTransport *transport, gpointer buf, + guint32 len, GError **error) +{ + ThriftMemoryBuffer *t = THRIFT_MEMORY_BUFFER (transport); + guint32 give = len; + + THRIFT_UNUSED_VAR (error); + + /* if the requested bytes are more than what we have available, + * just give all that we have the buffer */ + if (t->buf->len < len) + { + give = t->buf->len; + } + + memcpy (buf, t->buf->data, give); + g_byte_array_remove_range (t->buf, 0, give); + + return give; +} + +/* implements thrift_transport_read_end + * called when read is complete. nothing to do on our end. */ +gboolean +thrift_memory_buffer_read_end (ThriftTransport *transport, GError **error) +{ + /* satisfy -Wall */ + THRIFT_UNUSED_VAR (transport); + THRIFT_UNUSED_VAR (error); + return TRUE; +} + +/* implements thrift_transport_write */ +gboolean +thrift_memory_buffer_write (ThriftTransport *transport, + const gpointer buf, + const guint32 len, GError **error) +{ + ThriftMemoryBuffer *t = THRIFT_MEMORY_BUFFER (transport); + + THRIFT_UNUSED_VAR (error); + + /* return an exception if the buffer doesn't have enough space. */ + if (len > t->buf_size - t->buf->len) + { + g_set_error (error, THRIFT_TRANSPORT_ERROR, THRIFT_TRANSPORT_ERROR_SEND, + "unable to write %d bytes to buffer of length %d", + len, t->buf_size); + return FALSE; + } else { + t->buf = g_byte_array_append (t->buf, buf, len); + return TRUE; + } +} + +/* implements thrift_transport_write_end + * called when write is complete. nothing to do on our end. */ +gboolean +thrift_memory_buffer_write_end (ThriftTransport *transport, GError **error) +{ + /* satisfy -Wall */ + THRIFT_UNUSED_VAR (transport); + THRIFT_UNUSED_VAR (error); + return TRUE; +} + +/* implements thrift_transport_flush */ +gboolean +thrift_memory_buffer_flush (ThriftTransport *transport, GError **error) +{ + THRIFT_UNUSED_VAR (transport); + THRIFT_UNUSED_VAR (error); + + return TRUE; +} + +/* initializes class before constructor properties are set */ +static void +thrift_memory_buffer_init (ThriftMemoryBuffer *t) +{ + THRIFT_UNUSED_VAR (t); +} + +/* destructor */ +static void +thrift_memory_buffer_finalize (GObject *object) +{ + ThriftMemoryBuffer *t = THRIFT_MEMORY_BUFFER (object); + + if (t->owner && t->buf != NULL) + { + g_byte_array_unref (t->buf); + } + t->buf = NULL; +} + +/* property accessor */ +void +thrift_memory_buffer_get_property (GObject *object, guint property_id, + GValue *value, GParamSpec *pspec) +{ + ThriftMemoryBuffer *t = THRIFT_MEMORY_BUFFER (object); + + THRIFT_UNUSED_VAR (pspec); + + switch (property_id) + { + case PROP_THRIFT_MEMORY_BUFFER_BUFFER_SIZE: + g_value_set_uint (value, t->buf_size); + break; + case PROP_THRIFT_MEMORY_BUFFER_BUFFER: + g_value_set_pointer (value, (gpointer) (t->buf)); + break; + case PROP_THRIFT_MEMORY_BUFFER_OWNER: + g_value_set_boolean (value, t->owner); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +/* property mutator */ +void +thrift_memory_buffer_set_property (GObject *object, guint property_id, + const GValue *value, GParamSpec *pspec) +{ + ThriftMemoryBuffer *t = THRIFT_MEMORY_BUFFER (object); + + THRIFT_UNUSED_VAR (pspec); + + switch (property_id) + { + case PROP_THRIFT_MEMORY_BUFFER_BUFFER_SIZE: + t->buf_size = g_value_get_uint (value); + break; + case PROP_THRIFT_MEMORY_BUFFER_BUFFER: + t->buf = (GByteArray*) g_value_get_pointer (value); + break; + case PROP_THRIFT_MEMORY_BUFFER_OWNER: + t->owner = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +/* initializes class after constructor properties are set */ +static void +thrift_memory_buffer_constructed (GObject *object) +{ + ThriftMemoryBuffer *t = THRIFT_MEMORY_BUFFER (object); + + if (t->buf == NULL) { + t->buf = g_byte_array_new (); + } + + G_OBJECT_CLASS (thrift_memory_buffer_parent_class)->constructed (object); +} + +/* initializes the class */ +static void +thrift_memory_buffer_class_init (ThriftMemoryBufferClass *cls) +{ + ThriftTransportClass *ttc = THRIFT_TRANSPORT_CLASS (cls); + GObjectClass *gobject_class = G_OBJECT_CLASS (cls); + GParamSpec *param_spec = NULL; + + /* setup accessors and mutators */ + gobject_class->get_property = thrift_memory_buffer_get_property; + gobject_class->set_property = thrift_memory_buffer_set_property; + + param_spec = g_param_spec_uint ("buf_size", + "buffer size (construct)", + "Set the read/write buffer size limit", + 0, /* min */ + G_MAXUINT32, /* max */ + G_MAXUINT32, /* default */ + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE); + g_object_class_install_property (gobject_class, + PROP_THRIFT_MEMORY_BUFFER_BUFFER_SIZE, + param_spec); + + param_spec = g_param_spec_pointer ("buf", + "internal buffer (GByteArray)", + "Set the internal buffer (GByteArray)", + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE); + g_object_class_install_property (gobject_class, + PROP_THRIFT_MEMORY_BUFFER_BUFFER, + param_spec); + + param_spec = g_param_spec_boolean ("owner", + "internal buffer memory management policy", + "Set whether internal buffer should be" + " unreferenced when thrift_memory_buffer" + " is finalized", + TRUE, + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE); + g_object_class_install_property (gobject_class, + PROP_THRIFT_MEMORY_BUFFER_OWNER, + param_spec); + + gobject_class->constructed = thrift_memory_buffer_constructed; + gobject_class->finalize = thrift_memory_buffer_finalize; + ttc->is_open = thrift_memory_buffer_is_open; + ttc->open = thrift_memory_buffer_open; + ttc->close = thrift_memory_buffer_close; + ttc->read = thrift_memory_buffer_read; + ttc->read_end = thrift_memory_buffer_read_end; + ttc->write = thrift_memory_buffer_write; + ttc->write_end = thrift_memory_buffer_write_end; + ttc->flush = thrift_memory_buffer_flush; +} diff --git a/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_memory_buffer.h b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_memory_buffer.h new file mode 100644 index 000000000..d5d47b390 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_memory_buffer.h @@ -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_MEMORY_BUFFER_H +#define _THRIFT_MEMORY_BUFFER_H + +#include <glib.h> +#include <glib-object.h> + +#include <thrift/c_glib/transport/thrift_transport.h> + +G_BEGIN_DECLS + +/*! \file thrift_memory_buffer.h + * \brief Implementation of a Thrift memory buffer transport. + */ + +/* type macros */ +#define THRIFT_TYPE_MEMORY_BUFFER (thrift_memory_buffer_get_type ()) +#define THRIFT_MEMORY_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THRIFT_TYPE_MEMORY_BUFFER, ThriftMemoryBuffer)) +#define THRIFT_IS_MEMORY_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THRIFT_TYPE_MEMORY_BUFFER)) +#define THRIFT_MEMORY_BUFFER_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), THRIFT_TYPE_MEMORY_BUFFER, ThriftMemoryBufferClass)) +#define THRIFT_IS_MEMORY_BUFFER_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), THRIFT_TYPE_MEMORY_BUFFER) +#define THRIFT_MEMORY_BUFFER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THRIFT_TYPE_MEMORY_BUFFER, ThriftMemoryBufferClass)) + +typedef struct _ThriftMemoryBuffer ThriftMemoryBuffer; + +/*! + * ThriftMemoryBuffer instance. + */ +struct _ThriftMemoryBuffer +{ + ThriftTransport parent; + + /* private */ + GByteArray *buf; + guint32 buf_size; + gboolean owner; +}; + +typedef struct _ThriftMemoryBufferClass ThriftMemoryBufferClass; + +/*! + * ThriftMemoryBuffer class. + */ +struct _ThriftMemoryBufferClass +{ + ThriftTransportClass parent; +}; + +/* used by THRIFT_TYPE_MEMORY_BUFFER */ +GType thrift_memory_buffer_get_type (void); + +G_END_DECLS + +#endif diff --git a/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_platform_socket.h b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_platform_socket.h new file mode 100644 index 000000000..ede60f172 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_platform_socket.h @@ -0,0 +1,120 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/* clang-format off */ + +#ifndef _THRIFT_TRANSPORT_PLATFORM_SOCKET_H_ +# define _THRIFT_TRANSPORT_PLATFORM_SOCKET_H_ + +#ifdef _WIN32 +# define THRIFT_GET_SOCKET_ERROR ::WSAGetLastError() +# define THRIFT_ERRNO (*_errno()) +# define THRIFT_EINPROGRESS WSAEINPROGRESS +# define THRIFT_EAGAIN WSAEWOULDBLOCK +# define THRIFT_EINTR WSAEINTR +# define THRIFT_ECONNRESET WSAECONNRESET +# define THRIFT_ENOTCONN WSAENOTCONN +# define THRIFT_ETIMEDOUT WSAETIMEDOUT +# define THRIFT_EWOULDBLOCK WSAEWOULDBLOCK +# define THRIFT_EPIPE WSAECONNRESET +# define THRIFT_NO_SOCKET_CACHING SO_EXCLUSIVEADDRUSE +# define THRIFT_INVALID_SOCKET INVALID_SOCKET +# define THRIFT_SOCKETPAIR thrift_socketpair +# define THRIFT_FCNTL thrift_fcntl +# define THRIFT_O_NONBLOCK 1 +# define THRIFT_F_GETFL 0 +# define THRIFT_F_SETFL 1 +# define THRIFT_GETTIMEOFDAY thrift_gettimeofday +# define THRIFT_CLOSESOCKET closesocket +# define THRIFT_CLOSE _close +# define THRIFT_OPEN _open +# define THRIFT_FTRUNCATE _chsize_s +# define THRIFT_FSYNC _commit +# define THRIFT_LSEEK _lseek +# define THRIFT_WRITE _write +# define THRIFT_READ _read +# define THRIFT_FSTAT _fstat +# define THRIFT_STAT _stat +# ifdef _WIN32_WCE +# define THRIFT_GAI_STRERROR(...) thrift_wstr2str(gai_strerrorW(__VA_ARGS__)) +# else +# define THRIFT_GAI_STRERROR gai_strerrorA +# endif +# define THRIFT_SSIZET ptrdiff_t +# define THRIFT_SNPRINTF _snprintf +# define THRIFT_SLEEP_SEC thrift_sleep +# define THRIFT_SLEEP_USEC thrift_usleep +# define THRIFT_TIMESPEC thrift_timespec +# define THRIFT_CTIME_R thrift_ctime_r +# define THRIFT_POLL thrift_poll +# if WINVER <= 0x0502 /* XP, Server2003 */ +# define THRIFT_POLLFD thrift_pollfd +# define THRIFT_POLLIN 0x0300 +# define THRIFT_POLLOUT 0x0010 +# else /* Vista, Win7... */ +# define THRIFT_POLLFD pollfd +# define THRIFT_POLLIN POLLIN +# define THRIFT_POLLOUT POLLOUT +# endif /* WINVER */ +# define THRIFT_SHUT_RDWR SD_BOTH +#else /* not _WIN32 */ +# include <errno.h> +# define THRIFT_GET_SOCKET_ERROR errno +# define THRIFT_ERRNO errno +# define THRIFT_EINTR EINTR +# define THRIFT_EINPROGRESS EINPROGRESS +# define THRIFT_ECONNRESET ECONNRESET +# define THRIFT_ENOTCONN ENOTCONN +# define THRIFT_ETIMEDOUT ETIMEDOUT +# define THRIFT_EWOULDBLOCK EWOULDBLOCK +# define THRIFT_EAGAIN EAGAIN +# define THRIFT_EPIPE EPIPE +# define THRIFT_NO_SOCKET_CACHING SO_REUSEADDR +# define THRIFT_INVALID_SOCKET (-1) +# define THRIFT_SOCKETPAIR socketpair +# define THRIFT_FCNTL fcntl +# define THRIFT_O_NONBLOCK O_NONBLOCK +# define THRIFT_F_GETFL F_GETFL +# define THRIFT_F_SETFL F_SETFL +# define THRIFT_GETTIMEOFDAY gettimeofday +# define THRIFT_CLOSESOCKET close +# define THRIFT_CLOSE close +# define THRIFT_OPEN open +# define THRIFT_FTRUNCATE ftruncate +# define THRIFT_FSYNC fsync +# define THRIFT_LSEEK lseek +# define THRIFT_WRITE write +# define THRIFT_READ read +# define THRIFT_STAT stat +# define THRIFT_FSTAT fstat +# define THRIFT_GAI_STRERROR gai_strerror +# define THRIFT_SSIZET ssize_t +# define THRIFT_SNPRINTF snprintf +# define THRIFT_SLEEP_SEC sleep +# define THRIFT_SLEEP_USEC usleep +# define THRIFT_TIMESPEC timespec +# define THRIFT_CTIME_R ctime_r +# define THRIFT_POLL poll +# define THRIFT_POLLFD pollfd +# define THRIFT_POLLIN POLLIN +# define THRIFT_POLLOUT POLLOUT +# define THRIFT_SHUT_RDWR SHUT_RDWR +#endif + +#endif /* _THRIFT_TRANSPORT_PLATFORM_SOCKET_H_ */ diff --git a/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_server_socket.c b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_server_socket.c new file mode 100644 index 000000000..21ce1eee0 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_server_socket.c @@ -0,0 +1,307 @@ +/* + * 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 <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <netinet/in.h> + +#include <thrift/c_glib/thrift.h> +#include <thrift/c_glib/transport/thrift_socket.h> +#include <thrift/c_glib/transport/thrift_transport.h> +#include <thrift/c_glib/transport/thrift_server_transport.h> +#include <thrift/c_glib/transport/thrift_server_socket.h> + +/* object properties */ +enum _ThriftServerSocketProperties +{ + PROP_0, + PROP_THRIFT_SERVER_SOCKET_PORT, + PROP_THRIFT_SERVER_SOCKET_PATH, + PROP_THRIFT_SERVER_SOCKET_BACKLOG +}; + +/* define the GError domain string */ +#define THRIFT_SERVER_SOCKET_ERROR_DOMAIN "thrift-server-socket-error-quark" + +G_DEFINE_TYPE(ThriftServerSocket, thrift_server_socket, THRIFT_TYPE_SERVER_TRANSPORT) + +gboolean +thrift_server_socket_listen (ThriftServerTransport *transport, GError **error) +{ + int enabled = 1; /* for setsockopt() */ + ThriftServerSocket *tsocket = THRIFT_SERVER_SOCKET (transport); + + const int socket_domain = tsocket->path ? PF_UNIX : AF_INET; + + /* create a socket */ + if ((tsocket->sd = socket (socket_domain, SOCK_STREAM, 0)) == -1) + { + g_set_error (error, THRIFT_SERVER_SOCKET_ERROR, + THRIFT_SERVER_SOCKET_ERROR_SOCKET, + "failed to create socket - %s", strerror (errno)); + return FALSE; + } + + if (setsockopt(tsocket->sd, SOL_SOCKET, SO_REUSEADDR, &enabled, + sizeof(enabled)) == -1) + { + g_set_error (error, THRIFT_SERVER_SOCKET_ERROR, + THRIFT_SERVER_SOCKET_ERROR_SETSOCKOPT, + "unable to set SO_REUSEADDR - %s", strerror(errno)); + return FALSE; + } + + /* bind to the socket */ + if (tsocket->path) + { + /* create a socket structure */ + struct sockaddr_un pin; + memset (&pin, 0, sizeof(pin)); + pin.sun_family = AF_UNIX; + memcpy(pin.sun_path, tsocket->path, strlen(tsocket->path) + 1); + + if (bind(tsocket->sd, (struct sockaddr *) &pin, sizeof(pin)) == -1) + { + g_set_error (error, THRIFT_SERVER_SOCKET_ERROR, + THRIFT_SERVER_SOCKET_ERROR_BIND, + "failed to bind to path %s: - %s", + tsocket->path, strerror(errno)); + return FALSE; + } + } + else + { + /* create a address structure */ + struct sockaddr_in pin; + memset (&pin, 0, sizeof(pin)); + pin.sin_family = AF_INET; + pin.sin_addr.s_addr = INADDR_ANY; + pin.sin_port = htons(tsocket->port); + + if (bind(tsocket->sd, (struct sockaddr *) &pin, sizeof(pin)) == -1) + { + g_set_error (error, THRIFT_SERVER_SOCKET_ERROR, + THRIFT_SERVER_SOCKET_ERROR_BIND, + "failed to bind to port %d - %s", + tsocket->port, strerror(errno)); + return FALSE; + } + } + + if (listen(tsocket->sd, tsocket->backlog) == -1) + { + if (tsocket->path) + { + g_set_error (error, THRIFT_SERVER_SOCKET_ERROR, + THRIFT_SERVER_SOCKET_ERROR_BIND, + "failed to bind to path %s: - %s", + tsocket->path, strerror(errno)); + return FALSE; + } + else + { + g_set_error (error, THRIFT_SERVER_SOCKET_ERROR, + THRIFT_SERVER_SOCKET_ERROR_LISTEN, + "failed to listen to port %d - %s", + tsocket->port, strerror(errno)); + return FALSE; + } + } + + return TRUE; +} + +ThriftTransport * +thrift_server_socket_accept (ThriftServerTransport *transport, GError **error) +{ + int sd = THRIFT_INVALID_SOCKET; + guint addrlen = 0; + struct sockaddr_in address; + ThriftSocket *socket = NULL; + + ThriftServerSocket *tsocket = THRIFT_SERVER_SOCKET (transport); + + if ((sd = accept(tsocket->sd, (struct sockaddr *) &address, &addrlen)) == -1) + { + g_set_error (error, THRIFT_SERVER_SOCKET_ERROR, + THRIFT_SERVER_SOCKET_ERROR_ACCEPT, + "failed to accept connection - %s", + strerror(errno)); + return FALSE; + } + + socket = g_object_new (THRIFT_TYPE_SOCKET, NULL); + socket->sd = sd; + + return THRIFT_TRANSPORT(socket); +} + +gboolean +thrift_server_socket_close (ThriftServerTransport *transport, GError **error) +{ + ThriftServerSocket *tsocket = THRIFT_SERVER_SOCKET (transport); + + if (close (tsocket->sd) == -1) + { + g_set_error (error, THRIFT_SERVER_SOCKET_ERROR, + THRIFT_SERVER_SOCKET_ERROR_CLOSE, + "unable to close socket - %s", strerror(errno)); + return FALSE; + } + tsocket->sd = THRIFT_INVALID_SOCKET; + + return TRUE; +} + +/* define the GError domain for this implementation */ +GQuark +thrift_server_socket_error_quark (void) +{ + return g_quark_from_static_string(THRIFT_SERVER_SOCKET_ERROR_DOMAIN); +} + +/* initializes the instance */ +static void +thrift_server_socket_init (ThriftServerSocket *socket) +{ + socket->sd = THRIFT_INVALID_SOCKET; +} + +/* destructor */ +static void +thrift_server_socket_finalize (GObject *object) +{ + ThriftServerSocket *socket = THRIFT_SERVER_SOCKET (object); + + if (socket->sd != THRIFT_INVALID_SOCKET) + { + close (socket->sd); + } + socket->sd = THRIFT_INVALID_SOCKET; +} + +/* property accessor */ +void +thrift_server_socket_get_property (GObject *object, guint property_id, + GValue *value, GParamSpec *pspec) +{ + ThriftServerSocket *socket = THRIFT_SERVER_SOCKET (object); + + switch (property_id) + { + case PROP_THRIFT_SERVER_SOCKET_PORT: + g_value_set_uint (value, socket->port); + break; + case PROP_THRIFT_SERVER_SOCKET_PATH: + g_value_set_string (value, socket->path); + break; + case PROP_THRIFT_SERVER_SOCKET_BACKLOG: + g_value_set_uint (value, socket->backlog); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +/* property mutator */ +void +thrift_server_socket_set_property (GObject *object, guint property_id, + const GValue *value, GParamSpec *pspec) +{ + ThriftServerSocket *socket = THRIFT_SERVER_SOCKET (object); + + switch (property_id) + { + case PROP_THRIFT_SERVER_SOCKET_PORT: + socket->port = g_value_get_uint (value); + break; + case PROP_THRIFT_SERVER_SOCKET_PATH: + if (socket->path) { + g_free(socket->path); + } + socket->path = g_strdup (g_value_get_string (value)); + break; + case PROP_THRIFT_SERVER_SOCKET_BACKLOG: + socket->backlog = g_value_get_uint (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +/* initializes the class */ +static void +thrift_server_socket_class_init (ThriftServerSocketClass *cls) +{ + ThriftServerTransportClass *tstc = THRIFT_SERVER_TRANSPORT_CLASS (cls); + GObjectClass *gobject_class = G_OBJECT_CLASS (cls); + GParamSpec *param_spec = NULL; + + /* setup accessors and mutators */ + gobject_class->get_property = thrift_server_socket_get_property; + gobject_class->set_property = thrift_server_socket_set_property; + + param_spec = g_param_spec_uint ("port", + "port (construct)", + "Set the port to listen to", + 0, /* min */ + 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, + param_spec); + + param_spec = g_param_spec_string ("path", + "path (construct)", + "Set the path to listen to", + NULL, /* default value */ + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE); + g_object_class_install_property (gobject_class, + PROP_THRIFT_SERVER_SOCKET_PATH, + param_spec); + + param_spec = g_param_spec_uint ("backlog", + "backlog (construct)", + "Set the accept backlog", + 0, /* max */ + 65534, /* max */ + 1024, /* default */ + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE); + g_object_class_install_property (gobject_class, + PROP_THRIFT_SERVER_SOCKET_BACKLOG, + param_spec); + + gobject_class->finalize = thrift_server_socket_finalize; + + tstc->listen = thrift_server_socket_listen; + tstc->accept = thrift_server_socket_accept; + tstc->close = thrift_server_socket_close; +} + diff --git a/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_server_socket.h b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_server_socket.h new file mode 100644 index 000000000..7710d5161 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_server_socket.h @@ -0,0 +1,91 @@ +/* + * 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_SERVER_SOCKET_H +#define _THRIFT_SERVER_SOCKET_H + +#include <glib-object.h> + +#include "thrift_server_transport.h" + +G_BEGIN_DECLS + +/*! \file thrift_server_socket.h + * \brief Socket implementation of a Thrift server transport. Implements the + * ThriftServerTransport class. + */ + +/* type macros */ +#define THRIFT_TYPE_SERVER_SOCKET (thrift_server_socket_get_type ()) +#define THRIFT_SERVER_SOCKET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THRIFT_TYPE_SERVER_SOCKET, ThriftServerSocket)) +#define THRIFT_IS_SERVER_SOCKET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THRIFT_TYPE_SERVER_SOCKET)) +#define THRIFT_SERVER_SOCKET_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), THRIFT_TYPE_SERVER_SOCKET, ThriftServerSocketClass)) +#define THRIFT_IS_SERVER_SOCKET_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), THRIFT_TYPE_SERVER_SOCKET)) +#define THRIFT_SERVER_SOCKET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THRIFT_TYPE_SERVER_SOCKET, ThriftServerSocketClass)) + +typedef struct _ThriftServerSocket ThriftServerSocket; + +/*! + * Thrift ServerSocket instance. + */ +struct _ThriftServerSocket +{ + ThriftServerTransport parent; + + /* private */ + guint port; + gchar *path; + gshort backlog; + int sd; + guint8 *buf; + guint32 buf_size; + guint32 buf_len; +}; + +typedef struct _ThriftServerSocketClass ThriftServerSocketClass; + +/*! + * Thrift ServerSocket class. + */ +struct _ThriftServerSocketClass +{ + ThriftServerTransportClass parent; +}; + +/* used by THRIFT_TYPE_SERVER_SOCKET */ +GType thrift_server_socket_get_type (void); + +/* define error/exception types */ +typedef enum +{ + THRIFT_SERVER_SOCKET_ERROR_SOCKET, + THRIFT_SERVER_SOCKET_ERROR_SETSOCKOPT, + THRIFT_SERVER_SOCKET_ERROR_BIND, + THRIFT_SERVER_SOCKET_ERROR_LISTEN, + THRIFT_SERVER_SOCKET_ERROR_ACCEPT, + THRIFT_SERVER_SOCKET_ERROR_CLOSE +} ThriftServerSocketError; + +/* define a error domain for GError to use */ +GQuark thrift_server_socket_error_quark (void); +#define THRIFT_SERVER_SOCKET_ERROR (thrift_server_socket_error_quark ()) + +G_END_DECLS + +#endif diff --git a/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_server_transport.c b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_server_transport.c new file mode 100644 index 000000000..c25d1384f --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_server_transport.c @@ -0,0 +1,62 @@ +/* + * 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 <thrift/c_glib/thrift.h> +#include <thrift/c_glib/transport/thrift_transport.h> +#include <thrift/c_glib/transport/thrift_server_transport.h> + +G_DEFINE_ABSTRACT_TYPE(ThriftServerTransport, thrift_server_transport, G_TYPE_OBJECT) + +/* base initializer for the server transport interface */ +static void +thrift_server_transport_class_init (ThriftServerTransportClass *c) +{ + c->listen = thrift_server_transport_listen; + c->accept = thrift_server_transport_accept; + c->close = thrift_server_transport_close; +} + +static void +thrift_server_transport_init (ThriftServerTransport *transport) +{ + THRIFT_UNUSED_VAR (transport); +} + +gboolean +thrift_server_transport_listen (ThriftServerTransport *transport, + GError **error) +{ + return THRIFT_SERVER_TRANSPORT_GET_CLASS (transport)->listen (transport, + error); +} + +ThriftTransport * +thrift_server_transport_accept (ThriftServerTransport *transport, + GError **error) +{ + return THRIFT_SERVER_TRANSPORT_GET_CLASS (transport)->accept (transport, + error); +} + +gboolean +thrift_server_transport_close (ThriftServerTransport *transport, GError **error) +{ + return THRIFT_SERVER_TRANSPORT_GET_CLASS (transport)->close (transport, + error); +} diff --git a/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_server_transport.h b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_server_transport.h new file mode 100644 index 000000000..98a9191bd --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_server_transport.h @@ -0,0 +1,89 @@ +/* + * 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_SERVER_TRANSPORT_H +#define _THRIFT_SERVER_TRANSPORT_H + +#include <glib-object.h> + +#include "thrift_transport.h" + +G_BEGIN_DECLS + +/*! \file thrift_server_transport.h + * \brief Abstract class for Thrift server transports. + */ + +/* type macros */ +#define THRIFT_TYPE_SERVER_TRANSPORT (thrift_server_transport_get_type ()) +#define THRIFT_SERVER_TRANSPORT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THRIFT_TYPE_SERVER_TRANSPORT, ThriftServerTransport)) +#define THRIFT_IS_SERVER_TRANSPORT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THRIFT_TYPE_SERVER_TRANSPORT)) +#define THRIFT_SERVER_TRANSPORT_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), THRIFT_TYPE_SERVER_TRANSPORT, ThriftServerTransportClass)) +#define THRIFT_IS_SERVER_TRANSPORT_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), THRIFT_TYPE_SERVER_TRANSPORT)) +#define THRIFT_SERVER_TRANSPORT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THRIFT_TYPE_SERVER_TRANSPORT, ThriftServerTransportClass)) + +typedef struct _ThriftServerTransport ThriftServerTransport; + +struct _ThriftServerTransport +{ + GObject parent; +}; + +typedef struct _ThriftServerTransportClass ThriftServerTransportClass; + +/*! + * Thrift Transport class + */ +struct _ThriftServerTransportClass +{ + GObjectClass parent; + + /* vtable */ + gboolean (*listen) (ThriftServerTransport *transport, GError **error); + ThriftTransport *(*accept) (ThriftServerTransport *transport, GError **error); + gboolean (*close) (ThriftServerTransport *transport, GError **error); +}; + +/* used by THRIFT_TYPE_SERVER_TRANSPORT */ +GType thrift_server_transport_get_type (void); + +/*! + * Listen for new connections. + * \public \memberof ThriftServerTransportClass + */ +gboolean thrift_server_transport_listen (ThriftServerTransport *transport, + GError **error); + +/*! + * Accept a connection. + * \public \memberof ThriftServerTransportClass + */ +ThriftTransport *thrift_server_transport_accept + (ThriftServerTransport *transport, GError **error); + +/*! + * Close the transport. + * \public \memberof ThriftServerTransportClass + */ +gboolean thrift_server_transport_close (ThriftServerTransport *transport, + GError **error); + +G_END_DECLS + +#endif /* _THRIFT_SERVER_TRANSPORT_H */ diff --git a/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_socket.c b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_socket.c new file mode 100644 index 000000000..b7b413910 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_socket.c @@ -0,0 +1,427 @@ +/* + * 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 <sys/un.h> +#include <netinet/in.h> + +#include <thrift/c_glib/thrift.h> +#include <thrift/c_glib/transport/thrift_transport.h> +#include <thrift/c_glib/transport/thrift_socket.h> + +/* object properties */ +enum _ThriftSocketProperties +{ + PROP_0, + PROP_THRIFT_SOCKET_HOSTNAME, + PROP_THRIFT_SOCKET_PORT, + PROP_THRIFT_SOCKET_PATH +}; + +G_DEFINE_TYPE(ThriftSocket, thrift_socket, THRIFT_TYPE_TRANSPORT) + +/* implements thrift_transport_is_open */ +gboolean +thrift_socket_is_open (ThriftTransport *transport) +{ + ThriftSocket *socket = THRIFT_SOCKET (transport); + return socket->sd != THRIFT_INVALID_SOCKET; +} + +/* overrides thrift_transport_peek */ +gboolean +thrift_socket_peek (ThriftTransport *transport, GError **error) +{ + gboolean result = FALSE; + guint8 buf; + int r; + int errno_copy; + + ThriftSocket *socket = THRIFT_SOCKET (transport); + + if (thrift_socket_is_open (transport)) + { + r = recv (socket->sd, &buf, 1, MSG_PEEK); + if (r == -1) + { + errno_copy = errno; + + #if defined __FreeBSD__ || defined __MACH__ + /* FreeBSD returns -1 and ECONNRESET if the socket was closed by the other + side */ + if (errno_copy == ECONNRESET) + { + thrift_socket_close (transport, error); + } + else + { + #endif + + g_set_error (error, + THRIFT_TRANSPORT_ERROR, + THRIFT_TRANSPORT_ERROR_SOCKET, + "failed to peek at socket - %s", + strerror (errno_copy)); + + #if defined __FreeBSD__ || defined __MACH__ + } + #endif + } + else if (r > 0) + { + result = TRUE; + } + } + + 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) +{ + struct hostent *hp = NULL; + struct sockaddr_in pin; + int err; +#if defined(HAVE_GETHOSTBYNAME_R) + struct hostent he; + char buf[1024]; +#endif + + ThriftSocket *tsocket = THRIFT_SOCKET (transport); + g_return_val_if_fail (tsocket->sd == THRIFT_INVALID_SOCKET, FALSE); + + if (tsocket->path) { + /* create a socket structure */ + struct sockaddr_un pin; + memset (&pin, 0, sizeof(pin)); + pin.sun_family = AF_UNIX; + memcpy(pin.sun_path, tsocket->path, strlen(tsocket->path) + 1); + + /* create the socket */ + if ((tsocket->sd = socket (PF_UNIX, SOCK_STREAM, 0)) == -1) + { + g_set_error (error, THRIFT_TRANSPORT_ERROR, THRIFT_TRANSPORT_ERROR_SOCKET, + "failed to create socket for path %s: - %s", + tsocket->path, + strerror(errno)); + return FALSE; + } + + /* open a connection */ + if (connect (tsocket->sd, (struct sockaddr *) &pin, sizeof(pin)) == -1) + { + thrift_socket_close(tsocket, NULL); + g_set_error (error, THRIFT_TRANSPORT_ERROR, THRIFT_TRANSPORT_ERROR_CONNECT, + "failed to connect to path %s: - %s", + tsocket->path, strerror(errno)); + return FALSE; + } + return TRUE; + } + + /* lookup the destination host */ +#if defined(HAVE_GETHOSTBYNAME_R) + if (gethostbyname_r (tsocket->hostname, &he, buf, 1024, &hp, &err) != 0 || hp == NULL) +#else + if ((hp = gethostbyname (tsocket->hostname)) == NULL && (err = h_errno)) +#endif + { + /* host lookup failed, bail out with an error */ + g_set_error (error, THRIFT_TRANSPORT_ERROR, THRIFT_TRANSPORT_ERROR_HOST, + "host lookup failed for %s:%d - %s", + tsocket->hostname, tsocket->port, + hstrerror (err)); + return FALSE; + } + + /* 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_list[0]))->s_addr; + pin.sin_port = htons (tsocket->port); + + /* create the socket */ + if ((tsocket->sd = socket (AF_INET, SOCK_STREAM, 0)) == -1) + { + g_set_error (error, THRIFT_TRANSPORT_ERROR, THRIFT_TRANSPORT_ERROR_SOCKET, + "failed to create socket for host %s:%d - %s", + tsocket->hostname, tsocket->port, + strerror(errno)); + return FALSE; + } + + /* open a connection */ + if (connect (tsocket->sd, (struct sockaddr *) &pin, sizeof(pin)) == -1) + { + thrift_socket_close(transport, 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; + } + + return TRUE; +} + + +/* implements thrift_transport_read */ +gint32 +thrift_socket_read (ThriftTransport *transport, gpointer buf, + guint32 len, GError **error) +{ + gint ret = 0; + guint got = 0; + + ThriftSocket *socket = THRIFT_SOCKET (transport); + + while (got < len) + { + ret = recv (socket->sd, (guint8 *)buf + got, len-got, 0); + if (ret <= 0) + { + g_set_error (error, THRIFT_TRANSPORT_ERROR, + THRIFT_TRANSPORT_ERROR_RECEIVE, + "failed to read %d bytes - %s", len, strerror(errno)); + return -1; + } + got += ret; + } + + return got; +} + +/* implements thrift_transport_read_end + * called when write is complete. nothing to do on our end. */ +gboolean +thrift_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_socket_write (ThriftTransport *transport, const gpointer buf, + const guint32 len, GError **error) +{ + gint ret = 0; + guint sent = 0; + + ThriftSocket *socket = THRIFT_SOCKET (transport); + g_return_val_if_fail (socket->sd != THRIFT_INVALID_SOCKET, FALSE); + + while (sent < len) + { + ret = send (socket->sd, (guint8 *)buf + sent, len - sent, 0); + if (ret < 0) + { + g_set_error (error, THRIFT_TRANSPORT_ERROR, + THRIFT_TRANSPORT_ERROR_SEND, + "failed to send %d bytes - %s", len, strerror(errno)); + return FALSE; + } + sent += ret; + } + + return TRUE; +} + +/* implements thrift_transport_write_end + * called when write is complete. nothing to do on our end. */ +gboolean +thrift_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_socket_flush (ThriftTransport *transport, GError **error) +{ + /* satisfy -Wall */ + THRIFT_UNUSED_VAR (transport); + THRIFT_UNUSED_VAR (error); + return TRUE; +} + +/* initializes the instance */ +static void +thrift_socket_init (ThriftSocket *socket) +{ + socket->sd = THRIFT_INVALID_SOCKET; +} + +/* destructor */ +static void +thrift_socket_finalize (GObject *object) +{ + ThriftSocket *socket = THRIFT_SOCKET (object); + + if (socket->hostname != NULL) + { + g_free (socket->hostname); + } + socket->hostname = NULL; + if (socket->path != NULL) + { + g_free (socket->path); + } + + if (socket->sd != THRIFT_INVALID_SOCKET) + { + close (socket->sd); + } + socket->sd = THRIFT_INVALID_SOCKET; +} + +/* property accessor */ +void +thrift_socket_get_property (GObject *object, guint property_id, + GValue *value, GParamSpec *pspec) +{ + ThriftSocket *socket = THRIFT_SOCKET (object); + + THRIFT_UNUSED_VAR (pspec); + + switch (property_id) + { + case PROP_THRIFT_SOCKET_HOSTNAME: + g_value_set_string (value, socket->hostname); + break; + case PROP_THRIFT_SOCKET_PORT: + g_value_set_uint (value, socket->port); + break; + case PROP_THRIFT_SOCKET_PATH: + g_value_set_string (value, socket->path); + break; + } +} + +/* property mutator */ +void +thrift_socket_set_property (GObject *object, guint property_id, + const GValue *value, GParamSpec *pspec) +{ + ThriftSocket *socket = THRIFT_SOCKET (object); + + THRIFT_UNUSED_VAR (pspec); + + 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: + socket->port = g_value_get_uint (value); + break; + case PROP_THRIFT_SOCKET_PATH: + if (socket->path) { + g_free(socket->path); + } + socket->path = g_strdup (g_value_get_string (value)); + break; + } +} + +/* initializes the class */ +static void +thrift_socket_class_init (ThriftSocketClass *cls) +{ + ThriftTransportClass *ttc = THRIFT_TRANSPORT_CLASS (cls); + GObjectClass *gobject_class = G_OBJECT_CLASS (cls); + GParamSpec *param_spec = NULL; + + /* setup accessors and mutators */ + gobject_class->get_property = thrift_socket_get_property; + gobject_class->set_property = thrift_socket_set_property; + + param_spec = g_param_spec_string ("hostname", + "hostname (construct)", + "Set the hostname of the remote host", + "localhost", /* default value */ + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE); + g_object_class_install_property (gobject_class, PROP_THRIFT_SOCKET_HOSTNAME, + param_spec); + + param_spec = g_param_spec_uint ("port", + "port (construct)", + "Set the port of the remote host", + 0u, /* min */ + 65535u, /* max */ + 9090, /* default by convention */ + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE); + g_object_class_install_property (gobject_class, PROP_THRIFT_SOCKET_PORT, + param_spec); + + param_spec = g_param_spec_string ("path", + "path (construct)", + "Set the path of the remote host", + NULL, /* default value */ + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE); + g_object_class_install_property (gobject_class, PROP_THRIFT_SOCKET_PATH, + param_spec); + + gobject_class->finalize = thrift_socket_finalize; + ttc->is_open = thrift_socket_is_open; + ttc->peek = thrift_socket_peek; + ttc->open = thrift_socket_open; + ttc->close = thrift_socket_close; + ttc->read = thrift_socket_read; + ttc->read_end = thrift_socket_read_end; + ttc->write = thrift_socket_write; + ttc->write_end = thrift_socket_write_end; + ttc->flush = thrift_socket_flush; +} diff --git a/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_socket.h b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_socket.h new file mode 100644 index 000000000..c91f52f18 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_socket.h @@ -0,0 +1,73 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_SOCKET_H +#define _THRIFT_SOCKET_H + +#include <glib-object.h> + +#include <thrift/c_glib/transport/thrift_transport.h> + +G_BEGIN_DECLS + +/*! \file thrift_socket.h + * \brief Socket implementation of a Thrift transport. Subclasses the + * ThriftTransport class. + */ + +/* type macros */ +#define THRIFT_TYPE_SOCKET (thrift_socket_get_type ()) +#define THRIFT_SOCKET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THRIFT_TYPE_SOCKET, ThriftSocket)) +#define THRIFT_IS_SOCKET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THRIFT_TYPE_SOCKET)) +#define THRIFT_SOCKET_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), THRIFT_TYPE_SOCKET, ThriftSocketClass)) +#define THRIFT_IS_SOCKET_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), THRIFT_TYPE_SOCKET)) +#define THRIFT_SOCKET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THRIFT_TYPE_SOCKET, ThriftSocketClass)) + +typedef struct _ThriftSocket ThriftSocket; + +/*! + * Thrift Socket instance. + */ +struct _ThriftSocket +{ + ThriftTransport parent; + + /* private */ + gchar *hostname; + guint port; + gchar *path; + int sd; +}; + +typedef struct _ThriftSocketClass ThriftSocketClass; + +/*! + * Thrift Socket class. + */ +struct _ThriftSocketClass +{ + ThriftTransportClass parent; +}; + +/* used by THRIFT_TYPE_SOCKET */ +GType thrift_socket_get_type (void); + +G_END_DECLS + +#endif diff --git a/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_ssl_socket.c b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_ssl_socket.c new file mode 100644 index 000000000..df17fa6ee --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_ssl_socket.c @@ -0,0 +1,804 @@ +/* + * 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); + + 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; +} + diff --git a/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_ssl_socket.h b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_ssl_socket.h new file mode 100644 index 000000000..0ca465a0f --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_ssl_socket.h @@ -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 diff --git a/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_transport.c b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_transport.c new file mode 100644 index 000000000..9dd267143 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_transport.c @@ -0,0 +1,162 @@ +/* + * 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 <thrift/c_glib/thrift.h> +#include <thrift/c_glib/transport/thrift_transport.h> + +/* define the GError domain string */ +#define THRIFT_TRANSPORT_ERROR_DOMAIN "thrift-transport-error-quark" + +G_DEFINE_ABSTRACT_TYPE(ThriftTransport, thrift_transport, G_TYPE_OBJECT) + +gboolean +thrift_transport_is_open (ThriftTransport *transport) +{ + return THRIFT_TRANSPORT_GET_CLASS (transport)->is_open (transport); +} + +gboolean +thrift_transport_peek (ThriftTransport *transport, GError **error) +{ + return THRIFT_TRANSPORT_GET_CLASS (transport)->peek (transport, error); +} + +gboolean +thrift_transport_open (ThriftTransport *transport, GError **error) +{ + return THRIFT_TRANSPORT_GET_CLASS (transport)->open (transport, error); +} + +gboolean +thrift_transport_close (ThriftTransport *transport, GError **error) +{ + return THRIFT_TRANSPORT_GET_CLASS (transport)->close (transport, error); +} + +gint32 +thrift_transport_read (ThriftTransport *transport, gpointer buf, + guint32 len, GError **error) +{ + return THRIFT_TRANSPORT_GET_CLASS (transport)->read (transport, buf, + len, error); +} + +gboolean +thrift_transport_read_end (ThriftTransport *transport, GError **error) +{ + return THRIFT_TRANSPORT_GET_CLASS (transport)->read_end (transport, + error); +} + +gboolean +thrift_transport_write (ThriftTransport *transport, const gpointer buf, + const guint32 len, GError **error) +{ + return THRIFT_TRANSPORT_GET_CLASS (transport)->write (transport, buf, + len, error); +} + +gboolean +thrift_transport_write_end (ThriftTransport *transport, GError **error) +{ + return THRIFT_TRANSPORT_GET_CLASS (transport)->write_end (transport, + error); +} + +gboolean +thrift_transport_flush (ThriftTransport *transport, GError **error) +{ + return THRIFT_TRANSPORT_GET_CLASS (transport)->flush (transport, error); +} + +gint32 +thrift_transport_read_all (ThriftTransport *transport, gpointer buf, + guint32 len, GError **error) +{ + return THRIFT_TRANSPORT_GET_CLASS (transport)->read_all (transport, buf, + len, error); +} + +/* by default, peek returns true if and only if the transport is open */ +static gboolean +thrift_transport_real_peek (ThriftTransport *transport, GError **error) +{ + THRIFT_UNUSED_VAR (error); + + return THRIFT_TRANSPORT_GET_CLASS (transport)->is_open (transport); +} + +static gint32 +thrift_transport_real_read_all (ThriftTransport *transport, gpointer buf, + guint32 len, GError **error) +{ + ThriftTransportClass *ttc; + guint32 have; + gint32 ret; + gint8 *bytes; + + THRIFT_UNUSED_VAR (error); + + ttc = THRIFT_TRANSPORT_GET_CLASS (transport); + have = 0; + ret = 0; + bytes = (gint8*) buf; + + while (have < len) { + if ((ret = ttc->read (transport, (gpointer) (bytes + have), len - have, + error)) < 0) { + return ret; + } + have += ret; + } + + return have; +} + +/* define the GError domain for Thrift transports */ +GQuark +thrift_transport_error_quark (void) +{ + return g_quark_from_static_string (THRIFT_TRANSPORT_ERROR_DOMAIN); +} + +/* class initializer for ThriftTransport */ +static void +thrift_transport_class_init (ThriftTransportClass *cls) +{ + /* set these as virtual methods to be implemented by a subclass */ + cls->is_open = thrift_transport_is_open; + cls->open = thrift_transport_open; + cls->close = thrift_transport_close; + cls->read = thrift_transport_read; + cls->read_end = thrift_transport_read_end; + cls->write = thrift_transport_write; + cls->write_end = thrift_transport_write_end; + cls->flush = thrift_transport_flush; + + /* provide a default implementation for the peek and read_all methods */ + cls->peek = thrift_transport_real_peek; + cls->read_all = thrift_transport_real_read_all; +} + +static void +thrift_transport_init (ThriftTransport *transport) +{ + THRIFT_UNUSED_VAR (transport); +} diff --git a/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_transport.h b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_transport.h new file mode 100644 index 000000000..94bb6f507 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_transport.h @@ -0,0 +1,176 @@ +/* + * 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_TRANSPORT_H +#define _THRIFT_TRANSPORT_H + +#include <glib-object.h> + +G_BEGIN_DECLS + +/*! \file thrift_transport.h + * \brief Abstract class for Thrift transports. + * + * An abstract class is used instead of an interface because: + * - interfaces can't seem to be used as properties. ThriftProtocol has + * a ThriftTransport as an object property. + * - if a method needs to be added that all subclasses can use, a class + * is necessary. + */ + +/* type macros */ +#define THRIFT_TYPE_TRANSPORT (thrift_transport_get_type ()) +#define THRIFT_TRANSPORT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THRIFT_TYPE_TRANSPORT, ThriftTransport)) +#define THRIFT_IS_TRANSPORT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THRIFT_TYPE_TRANSPORT)) +#define THRIFT_TRANSPORT_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), THRIFT_TYPE_TRANSPORT, ThriftTransportClass)) +#define THRIFT_IS_TRANSPORT_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), THRIFT_TYPE_TRANSPORT)) +#define THRIFT_TRANSPORT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THRIFT_TYPE_TRANSPORT, ThriftTransportClass)) + +typedef struct _ThriftTransport ThriftTransport; + +/*! + * Thrift Protocol object + */ +struct _ThriftTransport +{ + GObject parent; +}; + +typedef struct _ThriftTransportClass ThriftTransportClass; + +/*! + * Thrift Transport class + */ +struct _ThriftTransportClass +{ + GObjectClass parent; + + /* vtable */ + gboolean (*is_open) (ThriftTransport *transport); + gboolean (*peek) (ThriftTransport *transport, GError **error); + gboolean (*open) (ThriftTransport *transport, GError **error); + gboolean (*close) (ThriftTransport *transport, GError **error); + gint32 (*read) (ThriftTransport *transport, gpointer buf, + guint32 len, GError **error); + gboolean (*read_end) (ThriftTransport *transport, GError **error); + gboolean (*write) (ThriftTransport *transport, const gpointer buf, + const guint32 len, GError **error); + gboolean (*write_end) (ThriftTransport *transport, GError **error); + gboolean (*flush) (ThriftTransport *transport, GError **error); + gint32 (*read_all) (ThriftTransport *transport, gpointer buf, + guint32 len, GError **error); +}; + +/* used by THRIFT_TYPE_TRANSPORT */ +GType thrift_transport_get_type (void); + +/* virtual public methods */ + +/*! + * Checks if this transport is opened. + * \public \memberof ThriftTransportInterface + */ +gboolean thrift_transport_is_open (ThriftTransport *transport); + +/*! + * Open the transport for reading and writing. + * \public \memberof ThriftTransportInterface + */ +gboolean thrift_transport_open (ThriftTransport *transport, GError **error); + +/*! + * Tests whether there is more data to read or if the remote side is still + * open. By default this is true whenever the transport is open, but + * implementations should add logic to test for this condition where possible + * (i.e. on a socket). + * + * This is used by a server to check if it should listen for another request. + * \public \memberof ThriftTransportInterface + */ +gboolean thrift_transport_peek (ThriftTransport *transport, GError **error); + +/*! + * Close the transport. + * \public \memberof ThriftTransportInterface + */ +gboolean thrift_transport_close (ThriftTransport *transport, GError **error); + +/*! + * Read some data into the buffer buf. + * \public \memberof ThriftTransportInterface + */ +gint32 thrift_transport_read (ThriftTransport *transport, gpointer buf, + guint32 len, GError **error); + +/*! + * Called when read is completed. + * \public \memberof ThriftTransportInterface + */ +gboolean thrift_transport_read_end (ThriftTransport *transport, GError **error); + +/*! + * Writes data from a buffer to the transport. + * \public \memberof ThriftTransportInterface + */ +gboolean thrift_transport_write (ThriftTransport *transport, const gpointer buf, + const guint32 len, GError **error); + +/*! + * Called when write is completed. + * \public \memberof ThriftTransportInterface + */ +gboolean thrift_transport_write_end (ThriftTransport *transport, + GError **error); + +/*! + * Flushes any pending data to be written. Typically used with buffered + * transport mechanisms. + * \public \memberof ThriftTransportInterface + */ +gboolean thrift_transport_flush (ThriftTransport *transport, GError **error); + +/*! + * Read len bytes of data into the buffer buf. + * \public \memberof ThriftTransportInterface + */ +gint32 thrift_transport_read_all (ThriftTransport *transport, gpointer buf, + guint32 len, GError **error); + +/* define error/exception types */ +typedef enum +{ + THRIFT_TRANSPORT_ERROR_UNKNOWN, + THRIFT_TRANSPORT_ERROR_HOST, + THRIFT_TRANSPORT_ERROR_SOCKET, + THRIFT_TRANSPORT_ERROR_CONNECT, + THRIFT_TRANSPORT_ERROR_SEND, + THRIFT_TRANSPORT_ERROR_RECEIVE, + THRIFT_TRANSPORT_ERROR_CLOSE +} ThriftTransportError; + +/* define an error domain for GError to use */ +GQuark thrift_transport_error_quark (void); +#define THRIFT_TRANSPORT_ERROR (thrift_transport_error_quark ()) + +/* define macro for invalid socket */ +#define THRIFT_INVALID_SOCKET (-1) + +G_END_DECLS + +#endif /* _THRIFT_TRANSPORT_H */ diff --git a/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_transport_factory.c b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_transport_factory.c new file mode 100644 index 000000000..a2025cf4b --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_transport_factory.c @@ -0,0 +1,44 @@ +/* + * 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 <thrift/c_glib/thrift.h> +#include <thrift/c_glib/transport/thrift_transport_factory.h> + +G_DEFINE_TYPE(ThriftTransportFactory, thrift_transport_factory, G_TYPE_OBJECT) + +/* builds a transport from the base transport. */ +ThriftTransport * +thrift_transport_factory_get_transport (ThriftTransportFactory *factory, + ThriftTransport *transport) +{ + THRIFT_UNUSED_VAR (factory); + return transport; +} + +static void +thrift_transport_factory_class_init (ThriftTransportFactoryClass *cls) +{ + cls->get_transport = thrift_transport_factory_get_transport; +} + +static void +thrift_transport_factory_init (ThriftTransportFactory *factory) +{ + THRIFT_UNUSED_VAR (factory); +} diff --git a/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_transport_factory.h b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_transport_factory.h new file mode 100644 index 000000000..0e3da302e --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/src/thrift/c_glib/transport/thrift_transport_factory.h @@ -0,0 +1,71 @@ +/* + * 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_TRANSPORT_FACTORY_H +#define _THRIFT_TRANSPORT_FACTORY_H + +#include <glib-object.h> + +#include "thrift_transport.h" + +G_BEGIN_DECLS + +/*! \file thrift_transport_factory.h + * \brief Base class for Thrift Transport Factories. Used by Thrift Servers + * to obtain a client transport from an existing transport. The default + * implementation simply clones the provided transport. + */ + +/* type macros */ +#define THRIFT_TYPE_TRANSPORT_FACTORY (thrift_transport_factory_get_type ()) +#define THRIFT_TRANSPORT_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THRIFT_TYPE_TRANSPORT_FACTORY, ThriftTransportFactory)) +#define THRIFT_IS_TRANSPORT_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THRIFT_TYPE_TRANSPORT_FACTORY)) +#define THRIFT_TRANSPORT_FACTORY_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), THRIFT_TYPE_TRANSPORT_FACTORY, ThriftTransportFactoryClass)) +#define THRIFT_IS_TRANSPORT_FACTORY_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), THRIFT_TYPE_TRANSPORT_FACTORY)) +#define THRIFT_TRANSPORT_FACTORY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THRIFT_TYPE_TRANSPORT_FACTORY, ThriftTransportFactoryClass)) + +typedef struct _ThriftTransportFactory ThriftTransportFactory; + +/* Thrift Transport Factory instance */ +struct _ThriftTransportFactory +{ + GObject parent; +}; + +typedef struct _ThriftTransportFactoryClass ThriftTransportFactoryClass; + +/* Thrift Transport Factory class */ +struct _ThriftTransportFactoryClass +{ + GObjectClass parent; + + /* vtable */ + ThriftTransport *(*get_transport) (ThriftTransportFactory *factory, + ThriftTransport *transport); +}; + +/* used by THRIFT_TYPE_TRANSPORT_FACTORY */ +GType thrift_transport_factory_get_type (void); + +/* virtual public methods */ +ThriftTransport *thrift_transport_factory_get_transport (ThriftTransportFactory *factory, ThriftTransport *transport); + +G_END_DECLS + +#endif /* _THRIFT_TRANSPORT_FACTORY_H */ diff --git a/src/jaegertracing/thrift/lib/c_glib/test/CMakeLists.txt b/src/jaegertracing/thrift/lib/c_glib/test/CMakeLists.txt new file mode 100644 index 000000000..318b57629 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/test/CMakeLists.txt @@ -0,0 +1,202 @@ +# +# 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. +# + + +set(TEST_PREFIX "c_glib") + +# include_directories(SYSTEM ${Boost_INCLUDE_DIRS}) + +#Make sure gen-cpp and gen-c_glib files can be included +include_directories("${CMAKE_CURRENT_BINARY_DIR}") + +# Create the thrift C test library +set(testgenc_SOURCES + gen-c_glib/t_test_debug_proto_test_types.c + gen-c_glib/t_test_enum_test_types.c + gen-c_glib/t_test_enum_test_service.c + gen-c_glib/t_test_empty_service.c + gen-c_glib/t_test_inherited.c + gen-c_glib/t_test_optional_required_test_types.c + gen-c_glib/t_test_reverse_order_service.c + gen-c_glib/t_test_second_service.c + gen-c_glib/t_test_service_for_exception_with_a_map.c + gen-c_glib/t_test_srv.c + gen-c_glib/t_test_thrift_test.c + gen-c_glib/t_test_thrift_test_types.c + gen-c_glib/t_test_debug_proto_test_types.h + gen-c_glib/t_test_enum_test_types.h + gen-c_glib/t_test_enum_test_service.h + gen-c_glib/t_test_empty_service.h + gen-c_glib/t_test_inherited.h + gen-c_glib/t_test_optional_required_test_types.h + gen-c_glib/t_test_reverse_order_service.h + gen-c_glib/t_test_second_service.h + gen-c_glib/t_test_service_for_exception_with_a_map.h + gen-c_glib/t_test_srv.h + gen-c_glib/t_test_thrift_test.h + gen-c_glib/t_test_thrift_test_types.h +) + +add_library(testgenc STATIC ${testgenc_SOURCES}) +LINK_AGAINST_THRIFT_LIBRARY(testgenc thrift_c_glib) + + +add_executable(testserialization testserialization.c) +target_link_libraries(testserialization testgenc) +LINK_AGAINST_THRIFT_LIBRARY(testserialization thrift_c_glib) +add_test(NAME testserialization COMMAND testserialization) + +add_executable(testapplicationexception testapplicationexception.c) +LINK_AGAINST_THRIFT_LIBRARY(testapplicationexception thrift_c_glib) +add_test(NAME testapplicationexception COMMAND testapplicationexception) + +add_executable(testtransportsocket testtransportsocket.c) +LINK_AGAINST_THRIFT_LIBRARY(testtransportsocket thrift_c_glib) +add_test(NAME testtransportsocket COMMAND testtransportsocket) + +add_executable(testbinaryprotocol testbinaryprotocol.c) +LINK_AGAINST_THRIFT_LIBRARY(testbinaryprotocol thrift_c_glib) +add_test(NAME testbinaryprotocol COMMAND testbinaryprotocol) + +add_executable(testcompactprotocol testcompactprotocol.c) +LINK_AGAINST_THRIFT_LIBRARY(testcompactprotocol thrift_c_glib) +add_test(NAME testcompactprotocol COMMAND testcompactprotocol) + +add_executable(testbufferedtransport testbufferedtransport.c) +LINK_AGAINST_THRIFT_LIBRARY(testbufferedtransport thrift_c_glib) +add_test(NAME testbufferedtransport COMMAND testbufferedtransport) + +add_executable(testframedtransport testframedtransport.c) +LINK_AGAINST_THRIFT_LIBRARY(testframedtransport thrift_c_glib) +add_test(NAME testframedtransport COMMAND testframedtransport) + +add_executable(testfdtransport testfdtransport.c) +LINK_AGAINST_THRIFT_LIBRARY(testfdtransport thrift_c_glib) +add_test(NAME testfdtransport COMMAND testfdtransport) + +add_executable(testmemorybuffer testmemorybuffer.c) +LINK_AGAINST_THRIFT_LIBRARY(testmemorybuffer thrift_c_glib) +add_test(NAME testmemorybuffer COMMAND testmemorybuffer) + +add_executable(testsimpleserver testsimpleserver.c) +LINK_AGAINST_THRIFT_LIBRARY(testsimpleserver thrift_c_glib) +add_test(NAME testsimpleserver COMMAND testsimpleserver) + +add_executable(testdebugproto testdebugproto.c) +target_link_libraries(testdebugproto testgenc) +add_test(NAME testdebugproto COMMAND testdebugproto) + +add_executable(testoptionalrequired testoptionalrequired.c) +target_link_libraries(testoptionalrequired testgenc) +add_test(NAME testoptionalrequired COMMAND testoptionalrequired) + +include_directories("${PROJECT_SOURCE_DIR}/test/c_glib/src" "${CMAKE_CURRENT_BINARY_DIR}/gen-c_glib") + +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) + + +if(BUILD_CPP) + + include_directories("${PROJECT_SOURCE_DIR}/lib/cpp/src") + + # Create the thrift C++ test library + set(testgenc_cpp_SOURCES + gen-cpp/ThriftTest.cpp + gen-cpp/ThriftTest_constants.cpp + gen-cpp/ThriftTest_types.cpp + gen-cpp/ThriftTest.h + gen-cpp/ThriftTest_constants.h + gen-cpp/ThriftTest_types.h + ) + + add_library(testgenc_cpp STATIC ${testgenc_cpp_SOURCES}) + LINK_AGAINST_THRIFT_LIBRARY(testgenc_cpp thrift) + + #HACK: testthrifttestclient.cpp includes ThriftTest.h without gen-*/ prefixes + # so we include it here + include_directories("${CMAKE_CURRENT_BINARY_DIR}/gen-cpp" "${CMAKE_CURRENT_BINARY_DIR}/gen-c_glib") + + add_executable(testthrifttestclient testthrifttestclient.cpp) + target_link_libraries(testthrifttestclient testgenc testgenc_cpp ${ZLIB_LIBRARIES}) + add_test(NAME testthrifttestclient COMMAND testthrifttestclient) + +endif(BUILD_CPP) + +# +# Common thrift code generation rules +# + +add_custom_command(OUTPUT + gen-c_glib/t_test_debug_proto_test_types.c + gen-c_glib/t_test_debug_proto_test_types.h + gen-c_glib/t_test_empty_service.c + gen-c_glib/t_test_empty_service.h + gen-c_glib/t_test_inherited.c + gen-c_glib/t_test_inherited.h + gen-c_glib/t_test_reverse_order_service.c + gen-c_glib/t_test_reverse_order_service.h + gen-c_glib/t_test_service_for_exception_with_a_map.c + gen-c_glib/t_test_service_for_exception_with_a_map.h + gen-c_glib/t_test_srv.c + gen-c_glib/t_test_srv.h + COMMAND ${THRIFT_COMPILER} --gen c_glib ${PROJECT_SOURCE_DIR}/test/DebugProtoTest.thrift +) + +add_custom_command(OUTPUT + gen-c_glib/t_test_enum_test_types.c + gen-c_glib/t_test_enum_test_types.h + gen-c_glib/t_test_enum_test_service.c + gen-c_glib/t_test_enum_test_service.h + COMMAND ${THRIFT_COMPILER} --gen c_glib ${PROJECT_SOURCE_DIR}/test/EnumTest.thrift +) + +add_custom_command(OUTPUT + gen-c_glib/t_test_optional_required_test_types.c + gen-c_glib/t_test_optional_required_test_types.h + COMMAND ${THRIFT_COMPILER} --gen c_glib ${PROJECT_SOURCE_DIR}/test/OptionalRequiredTest.thrift +) + +add_custom_command(OUTPUT + gen-c_glib/t_test_second_service.c + gen-c_glib/t_test_thrift_test.c + gen-c_glib/t_test_thrift_test_types.c + gen-c_glib/t_test_second_service.h + gen-c_glib/t_test_thrift_test.h + gen-c_glib/t_test_thrift_test_types.h + COMMAND ${THRIFT_COMPILER} --gen c_glib ${PROJECT_SOURCE_DIR}/test/ThriftTest.thrift +) + +add_custom_command(OUTPUT + gen-cpp/ThriftTest.cpp + gen-cpp/ThriftTest_constants.cpp + gen-cpp/ThriftTest_types.cpp + gen-cpp/ThriftTest.h + gen-cpp/ThriftTest_constants.h + gen-cpp/ThriftTest_types.h + COMMAND ${THRIFT_COMPILER} --gen cpp ${PROJECT_SOURCE_DIR}/test/ThriftTest.thrift +) + +# TODO: Add memory checks using ctest_memcheck or similar diff --git a/src/jaegertracing/thrift/lib/c_glib/test/ContainerTest.thrift b/src/jaegertracing/thrift/lib/c_glib/test/ContainerTest.thrift new file mode 100644 index 000000000..a92a9a51c --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/test/ContainerTest.thrift @@ -0,0 +1,35 @@ +/* + * 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. + */ + +namespace c_glib TTest + +typedef list<string> StringList +typedef list<StringList> ListStringList + +struct ContainersWithDefaultValues { + 1: list<string> StringList = [ "Apache", "Thrift" ]; +} + +service ContainerService { + void receiveStringList(1: list<string> stringList); + list<string> returnStringList(); + + list<list<string>> returnListStringList(); + ListStringList returnTypedefdListStringList(); +} diff --git a/src/jaegertracing/thrift/lib/c_glib/test/Makefile.am b/src/jaegertracing/thrift/lib/c_glib/test/Makefile.am new file mode 100755 index 000000000..c99e0da83 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/test/Makefile.am @@ -0,0 +1,324 @@ +# +# 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. +# +AUTOMAKE_OPTIONS = subdir-objects serial-tests nostdinc + +SUBDIRS = + +BUILT_SOURCES = \ + gen-c_glib/t_test_container_test_types.c \ + gen-c_glib/t_test_container_test_types.h \ + gen-c_glib/t_test_debug_proto_test_types.h \ + gen-c_glib/t_test_empty_service.h \ + gen-c_glib/t_test_inherited.h \ + gen-c_glib/t_test_optional_required_test_types.h \ + gen-c_glib/t_test_reverse_order_service.h \ + gen-c_glib/t_test_second_service.h \ + gen-c_glib/t_test_service_for_exception_with_a_map.h \ + gen-c_glib/t_test_container_service.c \ + gen-c_glib/t_test_container_service.h \ + gen-c_glib/t_test_srv.h \ + gen-c_glib/t_test_thrift_test.h \ + gen-c_glib/t_test_thrift_test_types.h + +AM_CPPFLAGS = -I../src -I./gen-c_glib -I$(top_builddir)/lib/c_glib/src/thrift +AM_CFLAGS = -g -Wall -Wextra -pedantic $(GLIB_CFLAGS) $(GOBJECT_CFLAGS) $(OPENSSL_INCLUDES) \ + @GCOV_CFLAGS@ +AM_CXXFLAGS = $(AM_CFLAGS) +AM_LDFLAGS = $(GLIB_LIBS) $(GOBJECT_LIBS) $(OPENSSL_LIBS) @GCOV_LDFLAGS@ + +check_PROGRAMS = \ + testserialization \ + testapplicationexception \ + testcontainertest \ + testtransportsocket \ + testtransportsslsocket \ + testbinaryprotocol \ + testcompactprotocol \ + testbufferedtransport \ + testframedtransport \ + testfdtransport \ + testmemorybuffer \ + teststruct \ + testsimpleserver \ + testdebugproto \ + testoptionalrequired \ + testthrifttest + +if WITH_CPP + BUILT_SOURCES += gen-cpp/ThriftTest_types.cpp + check_PROGRAMS += testthrifttestclient +endif + +testserialization_SOURCES = testserialization.c +testserialization_LDADD = \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/protocol/libthrift_c_glib_la-thrift_protocol.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_transport.o \ + libtestgenc.la + +testapplicationexception_SOURCES = testapplicationexception.c +testapplicationexception_LDADD = \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/libthrift_c_glib_la-thrift_application_exception.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/protocol/libthrift_c_glib_la-thrift_protocol.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/libthrift_c_glib_la-thrift_struct.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_transport.o + +testcontainertest_SOURCES = testcontainertest.c +testcontainertest_LDADD = \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/libthrift_c_glib_la-thrift_struct.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/protocol/libthrift_c_glib_la-thrift_protocol.o \ + $(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_transport_factory.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/processor/libthrift_c_glib_la-thrift_processor.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/protocol/libthrift_c_glib_la-thrift_protocol_factory.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/protocol/libthrift_c_glib_la-thrift_binary_protocol.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/protocol/libthrift_c_glib_la-thrift_binary_protocol_factory.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_server_transport.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_server_socket.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/server/libthrift_c_glib_la-thrift_server.o \ + libtestgenc.la + +testtransportsocket_SOURCES = testtransportsocket.c +testtransportsocket_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_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 + + +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 \ + $(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_framed_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_server_transport.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_server_socket.o + +testcompactprotocol_SOURCES = testcompactprotocol.c +testcompactprotocol_LDADD = \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/protocol/libthrift_c_glib_la-thrift_protocol.o \ + $(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_framed_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_server_transport.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_server_socket.o + +testbufferedtransport_SOURCES = testbufferedtransport.c +testbufferedtransport_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_server_transport.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_server_socket.o + +testframedtransport_SOURCES = testframedtransport.c +testframedtransport_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_server_transport.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_server_socket.o + +testfdtransport_SOURCES = testfdtransport.c +testfdtransport_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_fd_transport.o + +testmemorybuffer_SOURCES = testmemorybuffer.c +testmemorybuffer_LDADD = \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_transport.o + +teststruct_SOURCES = teststruct.c +teststruct_LDADD = \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/protocol/libthrift_c_glib_la-thrift_protocol.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_transport.o + +testsimpleserver_SOURCES = testsimpleserver.c +testsimpleserver_LDADD = \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/protocol/libthrift_c_glib_la-thrift_protocol.o \ + $(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_transport_factory.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/processor/libthrift_c_glib_la-thrift_processor.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/protocol/libthrift_c_glib_la-thrift_protocol_factory.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/protocol/libthrift_c_glib_la-thrift_binary_protocol.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/protocol/libthrift_c_glib_la-thrift_binary_protocol_factory.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_server_transport.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_server_socket.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/server/libthrift_c_glib_la-thrift_server.o + +testdebugproto_SOURCES = testdebugproto.c +testdebugproto_LDADD = libtestgenc.la + +testoptionalrequired_SOURCES = testoptionalrequired.c +testoptionalrequired_LDADD = \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/protocol/libthrift_c_glib_la-thrift_protocol.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_transport.o \ + libtestgenc.la + +testthrifttest_SOURCES = testthrifttest.c +testthrifttest_LDADD = libtestgenc.la \ + $(top_builddir)/test/c_glib/src/thrift_test_handler.o +testthrifttest_CFLAGS = -I$(top_srcdir)/test/c_glib/src -I./gen-c_glib $(GLIB_CFLAGS) + +testthrifttestclient_SOURCES = testthrifttestclient.cpp +testthrifttestclient_CPPFLAGS = -I../../cpp/src $(BOOST_CPPFLAGS) -I./gen-cpp -I../src -I./gen-c_glib $(GLIB_CFLAGS) +testthrifttestclient_LDADD = ../../cpp/.libs/libthrift.la ../libthrift_c_glib.la libtestgenc.la libtestgencpp.la +testthrifttestclient_LDFLAGS = -L../.libs -L../../cpp/.libs $(GLIB_LIBS) $(GOBJECT_LIBS) + +check_LTLIBRARIES = libtestgenc.la + +if WITH_CPP + check_LTLIBRARIES += libtestgencpp.la +endif + +nodist_libtestgenc_la_SOURCES = \ + gen-c_glib/t_test_container_test_types.c \ + gen-c_glib/t_test_debug_proto_test_types.c \ + gen-c_glib/t_test_enum_test_types.c \ + gen-c_glib/t_test_enum_test_service.c \ + gen-c_glib/t_test_empty_service.c \ + gen-c_glib/t_test_inherited.c \ + gen-c_glib/t_test_optional_required_test_types.c \ + gen-c_glib/t_test_reverse_order_service.c \ + gen-c_glib/t_test_second_service.c \ + gen-c_glib/t_test_service_for_exception_with_a_map.c \ + gen-c_glib/t_test_srv.c \ + gen-c_glib/t_test_container_service.c \ + gen-c_glib/t_test_thrift_test.c \ + gen-c_glib/t_test_thrift_test_types.c \ + gen-c_glib/t_test_container_test_types.h \ + gen-c_glib/t_test_debug_proto_test_types.h \ + gen-c_glib/t_test_enum_test_types.h \ + gen-c_glib/t_test_enum_test_service.h \ + gen-c_glib/t_test_empty_service.h \ + gen-c_glib/t_test_inherited.h \ + gen-c_glib/t_test_optional_required_test_types.h \ + gen-c_glib/t_test_reverse_order_service.h \ + gen-c_glib/t_test_second_service.h \ + gen-c_glib/t_test_service_for_exception_with_a_map.h \ + gen-c_glib/t_test_srv.h \ + gen-c_glib/t_test_container_service.h \ + gen-c_glib/t_test_thrift_test.h \ + gen-c_glib/t_test_thrift_test_types.h +libtestgenc_la_LIBADD = $(top_builddir)/lib/c_glib/libthrift_c_glib.la +libtestgenc_la_CPPFLAGS = $(AM_CPPFLAGS) -Wno-unused-function + +nodist_libtestgencpp_la_SOURCES = \ + gen-cpp/ThriftTest.cpp \ + gen-cpp/ThriftTest_constants.cpp \ + gen-cpp/ThriftTest_types.cpp \ + gen-cpp/ThriftTest.h \ + gen-cpp/ThriftTest_constants.h \ + gen-cpp/ThriftTest_types.h +libtestgencpp_la_CPPFLAGS = -I../../cpp/src $(BOOST_CPPFLAGS) -I./gen-cpp + +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 $< + +gen-c_glib/t_test_debug_proto_test_types.c gen-c_glib/t_test_debug_proto_test_types.h gen-c_glib/t_test_empty_service.c gen-c_glib/t_test_empty_service.h gen-c_glib/t_test_inherited.c gen-c_glib/t_test_inherited.h gen-c_glib/t_test_reverse_order_service.c gen-c_glib/t_test_reverse_order_service.h gen-c_glib/t_test_service_for_exception_with_a_map.c gen-c_glib/t_test_service_for_exception_with_a_map.h gen-c_glib/t_test_srv.c gen-c_glib/t_test_srv.h: ../../../test/DebugProtoTest.thrift $(THRIFT) + $(THRIFT) --gen c_glib $< + +gen-c_glib/t_test_enum_test_types.c gen-c_glib/t_test_enum_test_types.h gen-c_glib/t_test_enum_test_service.c gen-c_glib/t_test_enum_test_service.h : ../../../test/EnumTest.thrift $(THRIFT) + $(THRIFT) --gen c_glib $< + +gen-c_glib/t_test_optional_required_test_types.c gen-c_glib/t_test_optional_required_test_types.h: ../../../test/OptionalRequiredTest.thrift $(THRIFT) + $(THRIFT) --gen c_glib $< + +gen-c_glib/t_test_second_service.c gen-c_glib/t_test_thrift_test.c gen-c_glib/t_test_thrift_test_types.c gen-c_glib/t_test_second_service.h gen-c_glib/t_test_thrift_test.h gen-c_glib/t_test_thrift_test_types.h: ../../../test/ThriftTest.thrift $(THRIFT) + $(THRIFT) --gen c_glib $< + +gen-cpp/ThriftTest.cpp gen-cpp/ThriftTest_constants.cpp gen-cpp/ThriftTest_types.cpp: ../../../test/ThriftTest.thrift $(THRIFT) + $(THRIFT) --gen cpp $< + +TESTS = \ + $(check_PROGRAMS) \ + $(check_SCRIPTS) + +# globally added to all instances of valgrind calls +# VALGRIND_OPTS = --suppressions=glib.suppress +VALGRIND_OPTS = + +# globally added to all memcheck calls +VALGRIND_MEM_OPTS = --tool=memcheck \ + --num-callers=10 \ + ${myextravalgrindmemopts} + +# globally added to all leakcheck calls +VALGRIND_LEAK_OPTS = --tool=memcheck \ + --num-callers=10 \ + --leak-check=full \ + --leak-resolution=high \ + ${myextravalgrindleakopts} + +memcheck: $(check_PROGRAMS) + @for x in $(check_PROGRAMS); \ + do \ + $(MAKE) memcheck-$$x; \ + done + +leakcheck: $(check_PROGRAMS) + @for x in $(check_PROGRAMS); \ + do \ + $(MAKE) leakcheck-$$x; \ + done + +memcheck-%: % + @echo "*****************************************"; \ + echo "MEMCHECK: $<"; \ + echo "ARGS: ${VALGRIND_OPTS} ${VALGRIND_MEM_OPTS} ${$<_VALGRIND_MEM_OPTS}"; \ + $(LIBTOOL) --mode=execute \ + valgrind \ + ${VALGRIND_OPTS} \ + ${VALGRIND_MEM_OPTS} \ + ${$<_VALGRIND_MEM_OPTS} ./$< + +leakcheck-%: % + @echo "*****************************************"; \ + echo "LEAKCHECK: $<"; \ + echo "ARGS: ${VALGRIND_OPTS} ${VALGRIND_LEAK_OPTS} ${$<_VALGRIND_LEAK_OPTS}"; \ + G_SLICE=always-malloc $(LIBTOOL) --mode=execute \ + valgrind \ + ${VALGRIND_OPTS} \ + ${VALGRIND_LEAK_OPTS} \ + ${$<_VALGRIND_LEAK_OPTS} ./$< + +clean-local: + $(RM) gen-c_glib/* gen-cpp/* + +CLEANFILES = \ + *.bb \ + *.bbg \ + *.da \ + *.gcno \ + *.gcda \ + *.gcov + +EXTRA_DIST = \ + CMakeLists.txt \ + ContainerTest.thrift + diff --git a/src/jaegertracing/thrift/lib/c_glib/test/glib.suppress b/src/jaegertracing/thrift/lib/c_glib/test/glib.suppress new file mode 100644 index 000000000..0e0e9fe27 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/test/glib.suppress @@ -0,0 +1,64 @@ +{ + g_type_init_1 + Memcheck:Leak + fun:malloc + ... + fun:g_type_init_with_debug_flags +} + +{ + g_type_init_2 + Memcheck:Leak + fun:calloc + ... + fun:g_type_init_with_debug_flags +} + +{ + g_type_init_3 + Memcheck:Leak + fun:realloc + ... + fun:g_type_init_with_debug_flags +} + +{ + g_type_register_static_1 + Memcheck:Leak + fun:realloc + ... + fun:g_type_register_static +} + +{ + g_type_register_statuc_2 + Memcheck:Leak + fun:malloc + fun:realloc + fun:g_realloc + ... + fun:g_type_register_static +} + +{ + type_class_init_Wm1 + Memcheck:Leak + fun:calloc + fun:g_malloc0 + fun:type_class_init_Wm + fun:g_type_class_ref + ... + fun:g_object_newv +} + +{ + type_class_init_Wm2 + Memcheck:Leak + fun:calloc + fun:g_malloc0 + fun:type_class_init_Wm + fun:g_type_class_ref + ... + fun:type_class_init_Wm +} + diff --git a/src/jaegertracing/thrift/lib/c_glib/test/testapplicationexception.c b/src/jaegertracing/thrift/lib/c_glib/test/testapplicationexception.c new file mode 100644 index 000000000..89e39e262 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/test/testapplicationexception.c @@ -0,0 +1,180 @@ +/* + * 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 <glib.h> +#include <string.h> + +#include <thrift/c_glib/thrift_application_exception.h> + +static void +test_create_and_destroy (void) +{ + GObject *object = NULL; + + /* A ThriftApplicationException can be created... */ + object = g_object_new (THRIFT_TYPE_APPLICATION_EXCEPTION, NULL); + + g_assert (object != NULL); + g_assert (THRIFT_IS_APPLICATION_EXCEPTION (object)); + + /* ...and destroyed */ + g_object_unref (object); +} + +static void +test_initialize (void) +{ + ThriftApplicationException *xception = NULL; + gint32 type = THRIFT_APPLICATION_EXCEPTION_ERROR_INTERNAL_ERROR; + gchar *message = "Exception message"; + gint32 retrieved_type = 0; + gchar *retrieved_message = NULL; + + /* A ThriftApplicationException has "type" and "message" properties that can + be initialized at object creation */ + xception = + g_object_new (THRIFT_TYPE_APPLICATION_EXCEPTION, + "type", type, + "message", message, + NULL); + + g_assert (xception != NULL); + + /* A ThriftApplicationException's properties can be retrieved */ + g_object_get (xception, + "type", &retrieved_type, + "message", &retrieved_message, + NULL); + + g_assert (retrieved_type == type); + g_assert (retrieved_message != NULL); + g_assert_cmpstr (retrieved_message, ==, message); + + g_free (retrieved_message); + g_object_unref (xception); +} + +static void +test_properties_test (void) +{ + ThriftApplicationException *xception = NULL; + gint32 retrieved_type; + + xception = g_object_new (THRIFT_TYPE_APPLICATION_EXCEPTION, NULL); + +#define TEST_TYPE_VALUE(_type) \ + retrieved_type = -1; \ + g_object_set (xception, "type", _type, NULL); \ + g_object_get (xception, "type", &retrieved_type, NULL); \ + g_assert_cmpint (retrieved_type, ==, _type); + + /* The "type" property can be set to any valid Thrift exception type */ + TEST_TYPE_VALUE (THRIFT_APPLICATION_EXCEPTION_ERROR_UNKNOWN); + TEST_TYPE_VALUE (THRIFT_APPLICATION_EXCEPTION_ERROR_UNKNOWN_METHOD); + TEST_TYPE_VALUE (THRIFT_APPLICATION_EXCEPTION_ERROR_INVALID_MESSAGE_TYPE); + TEST_TYPE_VALUE (THRIFT_APPLICATION_EXCEPTION_ERROR_WRONG_METHOD_NAME); + TEST_TYPE_VALUE (THRIFT_APPLICATION_EXCEPTION_ERROR_BAD_SEQUENCE_ID); + TEST_TYPE_VALUE (THRIFT_APPLICATION_EXCEPTION_ERROR_MISSING_RESULT); + TEST_TYPE_VALUE (THRIFT_APPLICATION_EXCEPTION_ERROR_INTERNAL_ERROR); + TEST_TYPE_VALUE (THRIFT_APPLICATION_EXCEPTION_ERROR_PROTOCOL_ERROR); + TEST_TYPE_VALUE (THRIFT_APPLICATION_EXCEPTION_ERROR_INVALID_TRANSFORM); + TEST_TYPE_VALUE (THRIFT_APPLICATION_EXCEPTION_ERROR_INVALID_PROTOCOL); + TEST_TYPE_VALUE (THRIFT_APPLICATION_EXCEPTION_ERROR_UNSUPPORTED_CLIENT_TYPE); + +/* "g_test_expect_message" is required for the property range tests below but is + not present in GLib before version 2.34 */ +#if (GLIB_CHECK_VERSION (2, 34, 0)) + g_object_set (xception, + "type", THRIFT_APPLICATION_EXCEPTION_ERROR_UNKNOWN, + NULL); + + /* The "type" property cannot be set to a value too low (less than zero) */ + g_test_expect_message ("GLib-GObject", + G_LOG_LEVEL_WARNING, + "value*out of range*type*"); + g_object_set (xception, "type", -1, NULL); + g_test_assert_expected_messages (); + + g_object_get (xception, "type", &retrieved_type, NULL); + g_assert_cmpint (retrieved_type, !=, -1); + g_assert_cmpint (retrieved_type, + ==, + THRIFT_APPLICATION_EXCEPTION_ERROR_UNKNOWN); + + /* The "type" property cannot be set to a value too high (greater than the + highest defined exception-type value) */ + g_test_expect_message ("GLib-GObject", + G_LOG_LEVEL_WARNING, + "value*out of range*type*"); + g_object_set (xception, "type", THRIFT_APPLICATION_EXCEPTION_ERROR_N, NULL); + g_test_assert_expected_messages (); + + g_object_get (xception, "type", &retrieved_type, NULL); + g_assert_cmpint (retrieved_type, !=, THRIFT_APPLICATION_EXCEPTION_ERROR_N); + g_assert_cmpint (retrieved_type, + ==, + THRIFT_APPLICATION_EXCEPTION_ERROR_UNKNOWN); +#endif + + g_object_unref (xception); +} + +static void +test_properties_message (void) +{ + ThriftApplicationException *xception = NULL; + gchar *message = "Exception message"; + gchar *retrieved_message; + + xception = g_object_new (THRIFT_TYPE_APPLICATION_EXCEPTION, NULL); + + /* The "message" property can be set to NULL */ + g_object_set (xception, "message", NULL, NULL); + g_object_get (xception, "message", &retrieved_message, NULL); + g_assert (retrieved_message == NULL); + + /* The "message" property can be set to a valid string */ + g_object_set (xception, "message", message, NULL); + g_object_get (xception, "message", &retrieved_message, NULL); + g_assert_cmpint (strcmp (retrieved_message, message), ==, 0); + + g_free (retrieved_message); + g_object_unref (xception); +} + +int +main (int argc, char **argv) +{ +#if (!GLIB_CHECK_VERSION (2, 36, 0)) + g_type_init (); +#endif + + g_test_init (&argc, &argv, NULL); + + g_test_add_func ("/testapplicationexception/CreateAndDestroy", + test_create_and_destroy); + g_test_add_func ("/testapplicationexception/Initialize", + test_initialize); + g_test_add_func ("/testapplicationexception/Properties/test", + test_properties_test); + g_test_add_func ("/testapplicationexception/Properties/message", + test_properties_message); + + return g_test_run (); +} diff --git a/src/jaegertracing/thrift/lib/c_glib/test/testbinaryprotocol.c b/src/jaegertracing/thrift/lib/c_glib/test/testbinaryprotocol.c new file mode 100755 index 000000000..14f4fb063 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/test/testbinaryprotocol.c @@ -0,0 +1,859 @@ +/* + * 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. + */ + +/* 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 g_assert () */ +#ifdef __GLIBC__ +#include <features.h> +#define __NO_STRING_INLINES 1 +#endif + +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <netdb.h> +#include <string.h> +#include <sys/wait.h> + +#include <thrift/c_glib/protocol/thrift_protocol.h> +#include <thrift/c_glib/transport/thrift_socket.h> +#include <thrift/c_glib/transport/thrift_server_socket.h> +#include <thrift/c_glib/transport/thrift_framed_transport.h> + +#define TEST_BOOL TRUE +#define TEST_BYTE 123 +#define TEST_I16 12345 +#define TEST_I32 1234567890 +#define TEST_I64 G_GINT64_CONSTANT (123456789012345) +#define TEST_DOUBLE 1234567890.123 +#define TEST_STRING "this is a test string 1234567890!@#$%^&*()" +#define TEST_PORT 51199 + +static int transport_read_count = 0; +static int transport_read_error = 0; +static int transport_read_error_at = -1; +gint32 +my_thrift_transport_read_all (ThriftTransport *transport, gpointer buf, + guint32 len, GError **error) +{ + if (transport_read_count != transport_read_error_at + && transport_read_error == 0) + { + transport_read_count++; + return thrift_transport_read_all (transport, buf, len, error); + } + return -1; +} + +static int transport_write_count = 0; +static int transport_write_error = 0; +static int transport_write_error_at = -1; +gboolean +my_thrift_transport_write (ThriftTransport *transport, const gpointer buf, + const guint32 len, GError **error) +{ + if (transport_write_count != transport_write_error_at + && transport_write_error == 0) + { + transport_write_count++; + return thrift_transport_write (transport, buf, len, error); + } + return FALSE; +} + +#define thrift_transport_read_all my_thrift_transport_read_all +#define thrift_transport_write my_thrift_transport_write +#include "../src/thrift/c_glib/protocol/thrift_binary_protocol.c" +#undef thrift_transport_read_all +#undef thrift_transport_write + +static void thrift_server_primitives (const int port); +static void thrift_server_complex_types (const int port); +static void thrift_server_many_frames (const int port); + +static void +test_create_and_destroy(void) +{ + GObject *object = NULL; + + /* create an object and then destroy it */ + object = g_object_new (THRIFT_TYPE_BINARY_PROTOCOL, NULL); + g_assert (object != NULL); + g_object_unref (object); +} + +static void +test_initialize(void) +{ + ThriftSocket *tsocket = NULL; + ThriftBinaryProtocol *protocol = NULL; + ThriftSocket *temp = NULL; + + /* create a ThriftTransport */ + tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost", + "port", 51188, NULL); + g_assert (tsocket != NULL); + /* create a ThriftBinaryProtocol using the Transport */ + protocol = g_object_new (THRIFT_TYPE_BINARY_PROTOCOL, "transport", + tsocket, NULL); + g_assert (protocol != NULL); + /* fetch the properties */ + g_object_get (G_OBJECT(protocol), "transport", &temp, NULL); + g_object_unref (temp); + + /* clean up memory */ + g_object_unref (protocol); + g_object_unref (tsocket); +} + +static void +test_read_and_write_primitives(void) +{ + int status; + pid_t pid; + ThriftSocket *tsocket = NULL; + ThriftTransport *transport = NULL; + ThriftBinaryProtocol *tb = NULL; + ThriftProtocol *protocol = NULL; + gpointer binary = (gpointer *) TEST_STRING; + guint32 len = strlen (TEST_STRING); + int port = TEST_PORT; + + /* fork a server from the client */ + pid = fork (); + g_assert (pid >= 0); + + if (pid == 0) + { + /* child listens */ + thrift_server_primitives (port); + exit (0); + } else { + /* parent. 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); + transport = THRIFT_TRANSPORT (tsocket); + thrift_transport_open (transport, NULL); + 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); + g_assert (protocol != NULL); + + /* write a bunch of primitives */ + 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); + g_assert (thrift_binary_protocol_write_string (protocol, + TEST_STRING, NULL) > 0); + g_assert (thrift_binary_protocol_write_string (protocol, "", NULL) > 0); + g_assert (thrift_binary_protocol_write_binary (protocol, binary, + len, NULL) > 0); + 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; + g_assert (thrift_binary_protocol_write_byte (protocol, TEST_BYTE, + NULL) == -1); + 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); + 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; + g_assert (thrift_binary_protocol_write_binary (protocol, binary, + len, NULL) == -1); + transport_write_error_at = -1; + + /* clean up */ + thrift_transport_close (transport, NULL); + g_object_unref (tsocket); + g_object_unref (protocol); + g_assert (wait (&status) == pid); + g_assert (status == 0); + } +} + +static void +test_read_and_write_complex_types (void) +{ + int status; + pid_t pid; + ThriftSocket *tsocket = NULL; + ThriftTransport *transport = NULL; + ThriftBinaryProtocol *tb = NULL; + ThriftProtocol *protocol = NULL; + int port = TEST_PORT; + + /* fork a server from the client */ + pid = fork (); + g_assert (pid >= 0); + + if (pid == 0) + { + /* child listens */ + thrift_server_complex_types (port); + exit (0); + } else { + /* parent. 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); + transport = THRIFT_TRANSPORT (tsocket); + thrift_transport_open (transport, NULL); + 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); + g_assert (protocol != NULL); + + /* test structures */ + g_assert (thrift_binary_protocol_write_struct_begin (protocol, + NULL, NULL) == 0); + g_assert (thrift_binary_protocol_write_struct_end (protocol, NULL) == 0); + + g_assert (thrift_binary_protocol_write_field_begin (protocol, "test", T_VOID, + 1, NULL) > 0); + g_assert (thrift_binary_protocol_write_field_end (protocol, NULL) == 0); + + /* test write error */ + transport_write_error = 1; + 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; + g_assert (thrift_binary_protocol_write_field_begin (protocol, "test", T_VOID, + 1, NULL) == -1); + transport_write_error_at = -1; + + /* test 2nd read failure on a field */ + thrift_binary_protocol_write_byte (protocol, T_VOID, NULL); + + /* test write_field_stop */ + g_assert (thrift_binary_protocol_write_field_stop (protocol, NULL) > 0); + + /* write a map */ + g_assert (thrift_binary_protocol_write_map_begin (protocol, T_VOID, T_VOID, + 1, 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); + + /* test 3rd read failure on a map */ + thrift_binary_protocol_write_byte (protocol, T_VOID, NULL); + thrift_binary_protocol_write_byte (protocol, T_VOID, NULL); + + /* test 1st write failure on a map */ + transport_write_error = 1; + 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; + 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; + g_assert (thrift_binary_protocol_write_map_begin (protocol, T_VOID, T_VOID, + 1, NULL) == -1); + transport_write_error_at = -1; + + /* test negative map size */ + thrift_binary_protocol_write_byte (protocol, T_VOID, NULL); + thrift_binary_protocol_write_byte (protocol, T_VOID, NULL); + thrift_binary_protocol_write_i32 (protocol, -10, NULL); + + /* test list operations */ + g_assert (thrift_binary_protocol_write_list_begin (protocol, T_VOID, + 1, 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); + + /* test negative list size */ + thrift_binary_protocol_write_byte (protocol, T_VOID, NULL); + thrift_binary_protocol_write_i32 (protocol, -10, NULL); + + /* test first write error on a list */ + transport_write_error = 1; + 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; + g_assert (thrift_binary_protocol_write_list_begin (protocol, T_VOID, + 1, NULL) == -1); + transport_write_error_at = -1; + + /* test set operation s*/ + g_assert (thrift_binary_protocol_write_set_begin (protocol, T_VOID, + 1, NULL) > 0); + g_assert (thrift_binary_protocol_write_set_end (protocol, NULL) == 0); + + /* invalid version */ + g_assert (thrift_binary_protocol_write_i32 (protocol, -1, NULL) > 0); + + /* sz > 0 for a message */ + g_assert (thrift_binary_protocol_write_i32 (protocol, 1, NULL) > 0); + + /* send a valid message */ + thrift_binary_protocol_write_i32 (protocol, 0x80010000, NULL); + thrift_binary_protocol_write_string (protocol, "test", NULL); + thrift_binary_protocol_write_i32 (protocol, 1, NULL); + + /* broken 2nd read */ + thrift_binary_protocol_write_i32 (protocol, 0x80010000, NULL); + + /* send a broken 3rd read */ + thrift_binary_protocol_write_i32 (protocol, 0x80010000, NULL); + thrift_binary_protocol_write_string (protocol, "test", NULL); + + /* send a valid message */ + g_assert (thrift_binary_protocol_write_message_begin (protocol, "test", + T_CALL, 1, NULL) > 0); + + g_assert (thrift_binary_protocol_write_message_end (protocol, NULL) == 0); + + /* send broken writes */ + transport_write_error = 1; + 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; + 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; + g_assert (thrift_binary_protocol_write_message_begin (protocol, "test", + T_CALL, 1, NULL) == -1); + transport_write_error_at = -1; + + /* clean up */ + thrift_transport_close (transport, NULL); + g_object_unref (tsocket); + g_object_unref (protocol); + g_assert (wait (&status) == pid); + g_assert (status == 0); + } +} + +static void +test_read_and_write_many_frames (void) +{ + int status; + pid_t pid; + ThriftSocket *tsocket = NULL; + ThriftTransport *transport = NULL; + ThriftFramedTransport *ft = NULL; + ThriftBinaryProtocol *tb = NULL; + ThriftProtocol *protocol = NULL; + gpointer binary = (gpointer *) TEST_STRING; + const guint32 len = strlen (TEST_STRING); + int port = TEST_PORT; + + /* fork a server from the client */ + pid = fork (); + g_assert (pid >= 0); + + if (pid == 0) + { + /* child listens */ + thrift_server_many_frames (port); + exit (0); + } else { + /* parent. 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); + 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); + g_assert (ft != NULL); + transport = THRIFT_TRANSPORT (ft); + + thrift_transport_open (transport, NULL); + 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); + g_assert (protocol != NULL); + + /* write a bunch of primitives */ + g_assert (thrift_binary_protocol_write_bool (protocol, TEST_BOOL, NULL) > 0); + thrift_transport_flush (transport, NULL); + g_assert (thrift_binary_protocol_write_byte (protocol, TEST_BYTE, NULL) > 0); + thrift_transport_flush (transport, NULL); + g_assert (thrift_binary_protocol_write_i16 (protocol, TEST_I16, NULL) > 0); + thrift_transport_flush (transport, NULL); + g_assert (thrift_binary_protocol_write_i32 (protocol, TEST_I32, NULL) > 0); + thrift_transport_flush (transport, NULL); + g_assert (thrift_binary_protocol_write_i64 (protocol, TEST_I64, NULL) > 0); + thrift_transport_flush (transport, NULL); + g_assert (thrift_binary_protocol_write_double (protocol, + TEST_DOUBLE, NULL) > 0); + thrift_transport_flush (transport, NULL); + g_assert (thrift_binary_protocol_write_string (protocol, + TEST_STRING, NULL) > 0); + thrift_transport_flush (transport, NULL); + 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); + g_assert (thrift_binary_protocol_write_binary (protocol, NULL, 0, NULL) > 0); + thrift_transport_flush (transport, NULL); + g_assert (thrift_binary_protocol_write_binary (protocol, binary, + len, NULL) > 0); + thrift_transport_flush (transport, NULL); + + /* clean up */ + thrift_transport_write_end (transport, NULL); + thrift_transport_close (transport, NULL); + g_object_unref (ft); + g_object_unref (tsocket); + g_object_unref (tb); + g_assert (wait (&status) == pid); + g_assert (status == 0); + } +} + + +static void +thrift_server_primitives (const int port) +{ + ThriftServerTransport *transport = NULL; + ThriftTransport *client = NULL; + ThriftBinaryProtocol *tbp = NULL; + ThriftProtocol *protocol = NULL; + gboolean value_boolean = FALSE; + gint8 value_byte = 0; + gint16 value_16 = 0; + gint32 value_32 = 0; + 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; + + 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); + + tbp = g_object_new (THRIFT_TYPE_BINARY_PROTOCOL, "transport", + client, NULL); + protocol = THRIFT_PROTOCOL (tbp); + + g_assert (thrift_binary_protocol_read_bool (protocol, + &value_boolean, NULL) > 0); + 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); + 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); + + 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); + + transport_read_count = 0; + transport_read_error_at = 0; + 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; + g_assert (thrift_binary_protocol_read_binary (protocol, &binary, + &len, NULL) == -1); + transport_read_error_at = -1; + + transport_read_error = 1; + g_assert (thrift_binary_protocol_read_bool (protocol, + &value_boolean, NULL) == -1); + g_assert (thrift_binary_protocol_read_byte (protocol, + &value_byte, NULL) == -1); + g_assert (thrift_binary_protocol_read_i16 (protocol, + &value_16, NULL) == -1); + 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; + + /* test partial write failure */ + thrift_protocol_read_i32 (protocol, &value_32, NULL); + + thrift_transport_read_end (client, NULL); + thrift_transport_close (client, NULL); + + g_object_unref (tbp); + g_object_unref (client); + g_object_unref (tsocket); +} + +static void +thrift_server_complex_types (const int port) +{ + ThriftServerTransport *transport = NULL; + ThriftTransport *client = NULL; + ThriftBinaryProtocol *tbp = NULL; + ThriftProtocol *protocol = NULL; + gchar *struct_name = NULL; + gchar *field_name = NULL; + gchar *message_name = NULL; + ThriftType element_type, key_type, value_type, field_type; + ThriftMessageType message_type; + gint8 value = 0; + gint16 field_id = 0; + guint32 size = 0; + gint32 seqid = 0; + gint32 version = 0; + + 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); + + tbp = g_object_new (THRIFT_TYPE_BINARY_PROTOCOL, "transport", + client, NULL); + protocol = THRIFT_PROTOCOL (tbp); + + thrift_binary_protocol_read_struct_begin (protocol, &struct_name, NULL); + thrift_binary_protocol_read_struct_end (protocol, NULL); + + thrift_binary_protocol_read_field_begin (protocol, &field_name, &field_type, + &field_id, NULL); + thrift_binary_protocol_read_field_end (protocol, NULL); + + /* test first read error on a field */ + transport_read_error = 1; + g_assert (thrift_binary_protocol_read_field_begin (protocol, + &field_name, &field_type, + &field_id, NULL) == -1); + transport_read_error = 0; + + /* test 2nd write failure */ + thrift_binary_protocol_read_byte (protocol, &value, NULL); + + /* test 2nd read failure on a field */ + transport_read_count = 0; + transport_read_error_at = 1; + g_assert (thrift_binary_protocol_read_field_begin (protocol, + &field_name, &field_type, + &field_id, NULL) == -1); + transport_read_error_at = -1; + + /* test field stop */ + thrift_binary_protocol_read_field_begin (protocol, &field_name, &field_type, + &field_id, NULL); + + thrift_binary_protocol_read_map_begin (protocol, &key_type, &value_type, + &size, NULL); + thrift_binary_protocol_read_map_end (protocol, NULL); + + /* test read failure on a map */ + transport_read_count = 0; + transport_read_error_at = 0; + g_assert (thrift_binary_protocol_read_map_begin (protocol, + &key_type, &value_type, + &size, NULL) == -1); + transport_read_error_at = -1; + + /* test 2nd read failure on a map */ + transport_read_count = 0; + transport_read_error_at = 1; + g_assert (thrift_binary_protocol_read_map_begin (protocol, + &key_type, &value_type, + &size, NULL) == -1); + transport_read_error_at = -1; + + /* test 3rd read failure on a map */ + transport_read_count = 0; + transport_read_error_at = 2; + g_assert (thrift_binary_protocol_read_map_begin (protocol, + &key_type, &value_type, + &size, NULL) == -1); + transport_read_error_at = -1; + + /* test 2nd write failure */ + thrift_binary_protocol_read_byte (protocol, &value, NULL); + + /* test 3rd write failure */ + thrift_binary_protocol_read_byte (protocol, &value, NULL); + thrift_binary_protocol_read_byte (protocol, &value, NULL); + + /* test negative map size */ + g_assert (thrift_binary_protocol_read_map_begin (protocol, + &key_type, &value_type, + &size, NULL) == -1); + + /* test list operations */ + thrift_binary_protocol_read_list_begin (protocol, &element_type, &size, NULL); + thrift_binary_protocol_read_list_end (protocol, NULL); + + /* test read failure */ + transport_read_error = 1; + g_assert (thrift_binary_protocol_read_list_begin (protocol, &element_type, + &size, NULL) == -1); + transport_read_error = 0; + + /* test 2nd read failure */ + transport_read_count = 0; + transport_read_error_at = 1; + thrift_binary_protocol_read_list_begin (protocol, &element_type, &size, NULL); + transport_read_error_at = -1; + + /* test negative list size failure */ + thrift_binary_protocol_read_list_begin (protocol, &element_type, &size, NULL); + + /* test 2nd write failure */ + thrift_binary_protocol_read_byte (protocol, &value, NULL); + + /* test set operations */ + thrift_binary_protocol_read_set_begin (protocol, &element_type, &size, NULL); + thrift_binary_protocol_read_set_end (protocol, NULL); + + /* broken read */ + transport_read_error = 1; + g_assert (thrift_binary_protocol_read_message_begin (protocol, &message_name, + &message_type, &seqid, + NULL) == -1); + transport_read_error = 0; + + /* invalid protocol version */ + g_assert (thrift_binary_protocol_read_message_begin (protocol, &message_name, + &message_type, &seqid, + NULL) == -1); + + /* sz > 0 */ + g_assert (thrift_binary_protocol_read_message_begin (protocol, &message_name, + &message_type, &seqid, + NULL) > 0); + + /* read a valid message */ + g_assert (thrift_binary_protocol_read_message_begin (protocol, &message_name, + &message_type, &seqid, + NULL) > 0); + g_free (message_name); + + /* broken 2nd read on a message */ + transport_read_count = 0; + transport_read_error_at = 1; + g_assert (thrift_binary_protocol_read_message_begin (protocol, &message_name, + &message_type, &seqid, + NULL) == -1); + transport_read_error_at = -1; + + /* broken 3rd read on a message */ + transport_read_count = 0; + transport_read_error_at = 3; /* read_string does two reads */ + 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 */ + g_assert (thrift_binary_protocol_read_message_begin (protocol, &message_name, + &message_type, &seqid, + NULL) > 0); + g_free (message_name); + + 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); + + /* handle 2nd write failure on a message */ + thrift_binary_protocol_read_i32 (protocol, &version, NULL); + thrift_binary_protocol_read_string (protocol, &message_name, NULL); + + g_object_unref (client); + /* TODO: investigate g_object_unref (tbp); */ + g_object_unref (tsocket); +} + +static void +thrift_server_many_frames (const int port) +{ + ThriftServerTransport *transport = NULL; + ThriftTransport *client = NULL; + ThriftBinaryProtocol *tbp = NULL; + ThriftProtocol *protocol = NULL; + ThriftServerSocket *tsocket = NULL; + gboolean value_boolean = FALSE; + gint8 value_byte = 0; + gint16 value_16 = 0; + gint32 value_32 = 0; + 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; + + tsocket = g_object_new (THRIFT_TYPE_SERVER_SOCKET, "port", port, NULL); + transport = THRIFT_SERVER_TRANSPORT (tsocket); + thrift_server_transport_listen (transport, NULL); + + /* wrap the client in a framed transport */ + client = g_object_new (THRIFT_TYPE_FRAMED_TRANSPORT, "transport", + thrift_server_transport_accept (transport, NULL), + "r_buf_size", 1, NULL); + g_assert (client != NULL); + + tbp = g_object_new (THRIFT_TYPE_BINARY_PROTOCOL, "transport", + client, NULL); + protocol = THRIFT_PROTOCOL (tbp); + + g_assert (thrift_binary_protocol_read_bool (protocol, + &value_boolean, NULL) > 0); + 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); + 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); + + 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); + thrift_transport_close (client, NULL); + + g_object_unref (tbp); + g_object_unref (client); + g_object_unref (tsocket); +} + +int +main(int argc, char *argv[]) +{ +#if (!GLIB_CHECK_VERSION (2, 36, 0)) + g_type_init(); +#endif + + g_test_init (&argc, &argv, NULL); + + g_test_add_func ("/testbinaryprotocol/CreateAndDestroy", test_create_and_destroy); + g_test_add_func ("/testbinaryprotocol/Initialize", test_initialize); + g_test_add_func ("/testbinaryprotocol/ReadAndWritePrimitives", test_read_and_write_primitives); + g_test_add_func ("/testbinaryprotocol/ReadAndWriteComplexTypes", test_read_and_write_complex_types); + g_test_add_func ("/testbinaryprotocol/ReadAndWriteManyFrames", + test_read_and_write_many_frames); + + return g_test_run (); +} diff --git a/src/jaegertracing/thrift/lib/c_glib/test/testbufferedtransport.c b/src/jaegertracing/thrift/lib/c_glib/test/testbufferedtransport.c new file mode 100755 index 000000000..d01806d61 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/test/testbufferedtransport.c @@ -0,0 +1,325 @@ +/* + * 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 <netdb.h> +#include <signal.h> +#include <sys/wait.h> + +#include <thrift/c_glib/transport/thrift_transport.h> +#include <thrift/c_glib/transport/thrift_socket.h> +#include <thrift/c_glib/transport/thrift_server_transport.h> +#include <thrift/c_glib/transport/thrift_server_socket.h> + +#define TEST_DATA { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j' } + +#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 +test_create_and_destroy(void) +{ + ThriftTransport *transport = NULL; + guint r_buf_size = 0; + guint w_buf_size = 0; + + GObject *object = NULL; + object = g_object_new (THRIFT_TYPE_BUFFERED_TRANSPORT, NULL); + g_assert (object != NULL); + g_object_get (G_OBJECT (object), "transport", &transport, + "r_buf_size", &r_buf_size, + "w_buf_size", &w_buf_size, NULL); + g_object_unref (object); +} + +static void +test_open_and_close(void) +{ + ThriftSocket *tsocket = NULL; + ThriftTransport *transport = NULL; + GError *err = NULL; + pid_t pid; + int port = 51199; + int status; + + pid = fork (); + g_assert ( pid >= 0 ); + + if ( pid == 0 ) + { + /* child listens */ + thrift_socket_server_open (port,1); + exit (0); + } else { + /* parent connects, wait a bit for the socket to be created */ + sleep (1); + /* create a ThriftSocket */ + tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost", + "port", port, NULL); + + /* create a BufferedTransport wrapper of the Socket */ + transport = g_object_new (THRIFT_TYPE_BUFFERED_TRANSPORT, + "transport", THRIFT_TRANSPORT (tsocket), NULL); + + /* this shouldn't work */ + g_assert (thrift_buffered_transport_open (transport, NULL) == TRUE); + g_assert (thrift_buffered_transport_is_open (transport) == TRUE); + g_assert (thrift_buffered_transport_close (transport, NULL) == TRUE); + g_object_unref (transport); + g_object_unref (tsocket); + + /* try and underlying socket failure */ + tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost.broken", + NULL); + + /* create a BufferedTransport wrapper of the Socket */ + transport = g_object_new (THRIFT_TYPE_BUFFERED_TRANSPORT, + "transport", THRIFT_TRANSPORT (tsocket), NULL); + + g_assert (thrift_buffered_transport_open (transport, &err) == FALSE); + g_object_unref (transport); + g_object_unref (tsocket); + g_error_free (err); + err = NULL; + g_assert ( wait (&status) == pid ); + g_assert ( status == 0 ); + } +} + +static void +test_read_and_write(void) +{ + int status; + pid_t pid; + ThriftSocket *tsocket = NULL; + ThriftTransport *transport = NULL; + int port = 51199; + guchar buf[10] = TEST_DATA; /* a buffer */ + + pid = fork (); + g_assert ( pid >= 0 ); + + if ( pid == 0 ) + { + /* child listens */ + thrift_server (port); + exit (0); + } else { + /* parent connects, wait a bit for the socket to be created */ + sleep (1); + + tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost", + "port", port, NULL); + transport = g_object_new (THRIFT_TYPE_BUFFERED_TRANSPORT, + "transport", THRIFT_TRANSPORT (tsocket), + "w_buf_size", 4, NULL); + + g_assert (thrift_buffered_transport_open (transport, NULL) == TRUE); + g_assert (thrift_buffered_transport_is_open (transport)); + + /* write 10 bytes */ + thrift_buffered_transport_write (transport, buf, 10, NULL); + + /* write 1 byte at a time */ + thrift_buffered_transport_write (transport, buf, 1, NULL); + thrift_buffered_transport_write (transport, buf, 1, NULL); + thrift_buffered_transport_write (transport, buf, 1, NULL); + + /* overflow the buffer */ + thrift_buffered_transport_write (transport, buf, 2, NULL); + thrift_buffered_transport_write (transport, buf, 1, NULL); + thrift_buffered_transport_flush (transport, NULL); + + /* write 1 byte and flush */ + thrift_buffered_transport_write (transport, buf, 1, NULL); + thrift_buffered_transport_flush (transport, NULL); + + /* write and overflow buffer with 2 system calls */ + thrift_buffered_transport_write (transport, buf, 1, NULL); + thrift_buffered_transport_write (transport, buf, 3, NULL); + + /* write 10 bytes */ + thrift_buffered_transport_write (transport, buf, 10, NULL); + + thrift_buffered_transport_write_end (transport, NULL); + thrift_buffered_transport_flush (transport, NULL); + thrift_buffered_transport_close (transport, NULL); + + g_object_unref (transport); + g_object_unref (tsocket); + + g_assert ( wait (&status) == pid ); + g_assert ( status == 0 ); + } +} + + +static void +thrift_socket_server_open (const int port, int times) +{ + ThriftServerTransport *transport = NULL; + ThriftTransport *client = NULL; + 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_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); + + /* 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); + + /* read 10 bytes */ + bytes = thrift_buffered_transport_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 */ + + /* read 1 byte */ + bytes = thrift_buffered_transport_read (client, buf, 1, NULL); + + bytes = thrift_buffered_transport_read (client, buf, 6, NULL); + bytes = thrift_buffered_transport_read (client, buf, 2, NULL); + bytes = thrift_buffered_transport_read (client, buf, 1, NULL); + + thrift_buffered_transport_read_end (client, NULL); + thrift_buffered_transport_close (client, NULL); + g_object_unref (client); + g_object_unref (tsocket); +} + +static void +test_write_fail(void) +{ + int status; + pid_t pid; + ThriftSocket *tsocket = NULL; + ThriftTransport *transport = NULL; + int port = 51198; + guchar buf[10] = TEST_DATA; /* a buffer */ + + /* SIGPIPE when send to disconnected socket */ + signal(SIGPIPE, SIG_IGN); + + pid = fork (); + g_assert ( pid >= 0 ); + + if ( pid == 0 ) + { + /* child listens */ + ThriftServerTransport *transport = NULL; + ThriftTransport *client = NULL; + + ThriftServerSocket *tsocket = g_object_new (THRIFT_TYPE_SERVER_SOCKET, + "port", port, NULL); + + transport = THRIFT_SERVER_TRANSPORT (tsocket); + thrift_server_transport_listen (transport, NULL); + + /* wrap the client in a BufferedTransport */ + client = g_object_new (THRIFT_TYPE_BUFFERED_TRANSPORT, "transport", + thrift_server_transport_accept (transport, NULL), + "r_buf_size", 5, NULL); + g_assert (client != NULL); + + /* just close socket */ + thrift_buffered_transport_close (client, NULL); + g_object_unref (client); + g_object_unref (tsocket); + exit (0); + } else { + /* parent connects, wait a bit for the socket to be created */ + sleep (1); + + tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost", + "port", port, NULL); + transport = g_object_new (THRIFT_TYPE_BUFFERED_TRANSPORT, + "transport", THRIFT_TRANSPORT (tsocket), + "w_buf_size", 4, NULL); + + + g_assert (thrift_buffered_transport_open (transport, NULL) == TRUE); + g_assert (thrift_buffered_transport_is_open (transport)); + + /* recognize disconnection */ + sleep(1); + g_assert (thrift_buffered_transport_write (transport, buf, 10, NULL) == TRUE); + g_assert (thrift_buffered_transport_write (transport, buf, 10, NULL) == FALSE); + + /* write and overflow buffer */ + g_assert (thrift_buffered_transport_write (transport, buf, 10, NULL) == FALSE); + + /* write 1 and flush */ + g_assert (thrift_buffered_transport_write (transport, buf, 1, NULL) == TRUE); + g_assert (thrift_buffered_transport_flush (transport, NULL) == FALSE); + + thrift_buffered_transport_close (transport, NULL); + + g_object_unref (transport); + g_object_unref (tsocket); + + g_assert ( wait (&status) == pid ); + g_assert ( status == 0 ); + } +} + +int +main(int argc, char *argv[]) +{ +#if (!GLIB_CHECK_VERSION (2, 36, 0)) + g_type_init(); +#endif + + g_test_init (&argc, &argv, NULL); + + g_test_add_func ("/testbufferedtransport/CreateAndDestroy", test_create_and_destroy); + g_test_add_func ("/testbufferedtransport/OpenAndClose", test_open_and_close); + g_test_add_func ("/testbufferedtransport/ReadAndWrite", test_read_and_write); + g_test_add_func ("/testbufferedtransport/WriteFail", test_write_fail); + + return g_test_run (); +} + diff --git a/src/jaegertracing/thrift/lib/c_glib/test/testcompactprotocol.c b/src/jaegertracing/thrift/lib/c_glib/test/testcompactprotocol.c new file mode 100755 index 000000000..e5ad49120 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/test/testcompactprotocol.c @@ -0,0 +1,1293 @@ +/* + * 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. + */ + +/* 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 g_assert () */ +#if !defined(__APPLE__) && !defined(__FreeBSD__) && \ + !defined(__OpenBSD__) && !defined(__NetBSD__) +#include <features.h> +#endif + +#ifdef __GLIBC__ +#define __NO_STRING_INLINES 1 +#endif + +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <netdb.h> +#include <string.h> +#include <sys/wait.h> + +#include <thrift/c_glib/protocol/thrift_protocol.h> +#include <thrift/c_glib/transport/thrift_socket.h> +#include <thrift/c_glib/transport/thrift_server_socket.h> +#include <thrift/c_glib/transport/thrift_framed_transport.h> + +#define TEST_BOOL TRUE +#define TEST_BYTE 123 +#define TEST_I16 12345 +#define TEST_I32 1234567890 +#define TEST_I64 123456789012345 +#define TEST_NI16 (-12345) +#define TEST_NI32 (-1234567890) +#define TEST_NI64 (-123456789012345) +#define TEST_DOUBLE 1234567890.123 +#define TEST_STRING "this is a test string 1234567890!@#$%^&*()" +#define TEST_PORT 51199 + +static int transport_read_count = 0; +static int transport_read_error = 0; +static int transport_read_error_at = -1; +gint32 +my_thrift_transport_read_all (ThriftTransport *transport, gpointer buf, + guint32 len, GError **error) +{ + if (transport_read_count != transport_read_error_at + && transport_read_error == 0) + { + transport_read_count++; + return thrift_transport_read_all (transport, buf, len, error); + } + return -1; +} + +static int transport_write_count = 0; +static int transport_write_error = 0; +static int transport_write_error_at = -1; +gboolean +my_thrift_transport_write (ThriftTransport *transport, const gpointer buf, + const guint32 len, GError **error) +{ + if (transport_write_count != transport_write_error_at + && transport_write_error == 0) + { + transport_write_count++; + return thrift_transport_write (transport, buf, len, error); + } + return FALSE; +} + +#define thrift_transport_read_all my_thrift_transport_read_all +#define thrift_transport_write my_thrift_transport_write +#include "../src/thrift/c_glib/protocol/thrift_compact_protocol.c" +#undef thrift_transport_read_all +#undef thrift_transport_write + +static void thrift_server_primitives (const int port); +static void thrift_server_complex_types (const int port); +static void thrift_server_many_frames (const int port); + +static void +test_create_and_destroy (void) +{ + GObject *object = NULL; + + /* create an object and then destroy it */ + object = g_object_new (THRIFT_TYPE_COMPACT_PROTOCOL, NULL); + g_assert (object != NULL); + g_object_unref (object); +} + +static void +test_initialize (void) +{ + ThriftSocket *tsocket = NULL; + ThriftCompactProtocol *protocol = NULL; + ThriftSocket *temp = NULL; + + /* create a ThriftTransport */ + tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost", + "port", 51188, NULL); + g_assert (tsocket != NULL); + /* create a ThriftCompactProtocol using the Transport */ + protocol = g_object_new (THRIFT_TYPE_COMPACT_PROTOCOL, "transport", + tsocket, NULL); + g_assert (protocol != NULL); + /* fetch the properties */ + g_object_get (G_OBJECT (protocol), "transport", &temp, NULL); + g_object_unref (temp); + + /* clean up memory */ + g_object_unref (protocol); + g_object_unref (tsocket); +} + +static void +test_read_and_write_primitives (void) +{ + int status; + pid_t pid; + ThriftSocket *tsocket = NULL; + ThriftTransport *transport = NULL; + ThriftCompactProtocol *tc = NULL; + ThriftProtocol *protocol = NULL; + gpointer binary = (gpointer *) TEST_STRING; + guint32 len = strlen (TEST_STRING); + int port = TEST_PORT; + + /* fork a server from the client */ + pid = fork (); + g_assert (pid >= 0); + + if (pid == 0) + { + /* child listens */ + thrift_server_primitives (port); + exit (0); + } else { + /* parent. 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); + transport = THRIFT_TRANSPORT (tsocket); + thrift_transport_open (transport, NULL); + g_assert (thrift_transport_is_open (transport)); + + /* create a ThriftCompactTransport */ + tc = g_object_new (THRIFT_TYPE_COMPACT_PROTOCOL, "transport", + tsocket, NULL); + protocol = THRIFT_PROTOCOL (tc); + g_assert (protocol != NULL); + + /* write a bunch of primitives */ + g_assert (thrift_compact_protocol_write_bool (protocol, TEST_BOOL, NULL) > 0); + g_assert (thrift_compact_protocol_write_byte (protocol, TEST_BYTE, NULL) > 0); + g_assert (thrift_compact_protocol_write_i16 (protocol, TEST_I16, NULL) > 0); + g_assert (thrift_compact_protocol_write_i32 (protocol, TEST_I32, NULL) > 0); + g_assert (thrift_compact_protocol_write_i64 (protocol, TEST_I64, NULL) > 0); + g_assert (thrift_compact_protocol_write_i16 (protocol, TEST_NI16, NULL) > 0); + g_assert (thrift_compact_protocol_write_i32 (protocol, TEST_NI32, NULL) > 0); + g_assert (thrift_compact_protocol_write_i64 (protocol, TEST_NI64, NULL) > 0); + g_assert (thrift_compact_protocol_write_i16 (protocol, 2, NULL) > 0); + g_assert (thrift_compact_protocol_write_i32 (protocol, 2, NULL) > 0); + g_assert (thrift_compact_protocol_write_i64 (protocol, 2, NULL) > 0); + g_assert (thrift_compact_protocol_write_i16 (protocol, -2, NULL) > 0); + g_assert (thrift_compact_protocol_write_i32 (protocol, -2, NULL) > 0); + g_assert (thrift_compact_protocol_write_i64 (protocol, -2, NULL) > 0); + g_assert (thrift_compact_protocol_write_double (protocol, + TEST_DOUBLE, NULL) > 0); + g_assert (thrift_compact_protocol_write_string (protocol, + TEST_STRING, NULL) > 0); + g_assert (thrift_compact_protocol_write_string (protocol, "", NULL) > 0); + g_assert (thrift_compact_protocol_write_binary (protocol, binary, + len, NULL) > 0); + g_assert (thrift_compact_protocol_write_binary (protocol, NULL, 0, NULL) > 0); + g_assert (thrift_compact_protocol_write_binary (protocol, binary, + len, NULL) > 0); + + /* test write errors */ + transport_write_error = 1; + g_assert (thrift_compact_protocol_write_byte (protocol, TEST_BYTE, + NULL) == -1); + g_assert (thrift_compact_protocol_write_i16 (protocol, TEST_I16, NULL) == -1); + g_assert (thrift_compact_protocol_write_i32 (protocol, TEST_I32, NULL) == -1); + g_assert (thrift_compact_protocol_write_i64 (protocol, TEST_I64, NULL) == -1); + g_assert (thrift_compact_protocol_write_i16 (protocol, TEST_NI16, + NULL) == -1); + g_assert (thrift_compact_protocol_write_i32 (protocol, TEST_NI32, + NULL) == -1); + g_assert (thrift_compact_protocol_write_i64 (protocol, TEST_NI64, + NULL) == -1); + g_assert (thrift_compact_protocol_write_double (protocol, TEST_DOUBLE, + NULL) == -1); + g_assert (thrift_compact_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; + g_assert (thrift_compact_protocol_write_binary (protocol, binary, + len, NULL) == -1); + transport_write_error_at = -1; + + /* clean up */ + thrift_transport_close (transport, NULL); + g_object_unref (tsocket); + g_object_unref (protocol); + g_assert (wait (&status) == pid); + g_assert (status == 0); + } +} + +static void +test_read_and_write_complex_types (void) +{ + int status; + pid_t pid; + ThriftSocket *tsocket = NULL; + ThriftTransport *transport = NULL; + ThriftCompactProtocol *tc = NULL; + ThriftProtocol *protocol = NULL; + int port = TEST_PORT; + + /* fork a server from the client */ + pid = fork (); + g_assert (pid >= 0); + + if (pid == 0) + { + /* child listens */ + thrift_server_complex_types (port); + exit (0); + } else { + /* parent. 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); + transport = THRIFT_TRANSPORT (tsocket); + thrift_transport_open (transport, NULL); + g_assert (thrift_transport_is_open (transport)); + + /* create a ThriftCompactTransport */ + tc = g_object_new (THRIFT_TYPE_COMPACT_PROTOCOL, "transport", + tsocket, NULL); + protocol = THRIFT_PROTOCOL (tc); + g_assert (protocol != NULL); + + /* test structures */ + g_assert (thrift_compact_protocol_write_struct_begin (protocol, + NULL, NULL) == 0); + g_assert (thrift_compact_protocol_write_struct_end (protocol, NULL) == 0); + + /* test field state w.r.t. deltas */ + + g_assert (thrift_compact_protocol_write_field_begin (protocol, "test", + T_DOUBLE, 1, NULL) == 1); + g_assert (thrift_compact_protocol_write_field_begin (protocol, "test", + T_DOUBLE, + 16, NULL) == 1); + g_assert (thrift_compact_protocol_write_field_begin (protocol, "test", + T_DOUBLE, + 17, NULL) == 1); + g_assert (thrift_compact_protocol_write_field_begin (protocol, "test", + T_DOUBLE, + 15, NULL) > 1); + g_assert (thrift_compact_protocol_write_field_begin (protocol, "test", + T_DOUBLE, + 30, NULL) == 1); + g_assert (thrift_compact_protocol_write_field_begin (protocol, "test", + T_DOUBLE, + 46, NULL) > 1); + g_assert (thrift_compact_protocol_write_field_begin (protocol, "test", + T_DOUBLE, + 47, NULL) == 1); + + /* test fields */ + g_assert (thrift_compact_protocol_write_field_begin (protocol, "test", + T_DOUBLE, + 1, NULL) > 1); + g_assert (thrift_compact_protocol_write_field_end (protocol, NULL) == 0); + + /* test field state w.r.t. structs */ + + g_assert (thrift_compact_protocol_write_field_begin (protocol, "test", + T_DOUBLE, + 1, NULL) > 1); + g_assert (thrift_compact_protocol_write_field_end (protocol, NULL) == 0); + g_assert (thrift_compact_protocol_write_field_begin (protocol, "test", + T_DOUBLE, + 16, NULL) == 1); + g_assert (thrift_compact_protocol_write_field_end (protocol, NULL) == 0); + + g_assert (thrift_compact_protocol_write_struct_begin (protocol, + NULL, NULL) == 0); + g_assert (thrift_compact_protocol_write_field_begin (protocol, "test", + T_DOUBLE, + 17, NULL) > 1); + g_assert (thrift_compact_protocol_write_field_end (protocol, NULL) == 0); + + g_assert (thrift_compact_protocol_write_struct_begin (protocol, + NULL, NULL) == 0); + g_assert (thrift_compact_protocol_write_field_begin (protocol, "test", + T_DOUBLE, + 18, NULL) > 1); + g_assert (thrift_compact_protocol_write_field_end (protocol, NULL) == 0); + g_assert (thrift_compact_protocol_write_field_begin (protocol, "test", + T_DOUBLE, + 19, NULL) == 1); + g_assert (thrift_compact_protocol_write_field_end (protocol, NULL) == 0); + g_assert (thrift_compact_protocol_write_struct_end (protocol, NULL) == 0); + + g_assert (thrift_compact_protocol_write_field_begin (protocol, "test", + T_DOUBLE, + 18, NULL) == 1); + g_assert (thrift_compact_protocol_write_field_end (protocol, NULL) == 0); + g_assert (thrift_compact_protocol_write_field_begin (protocol, "test", + T_DOUBLE, + 25, NULL) == 1); + g_assert (thrift_compact_protocol_write_field_end (protocol, NULL) == 0); + g_assert (thrift_compact_protocol_write_struct_end (protocol, NULL) == 0); + + g_assert (thrift_compact_protocol_write_field_begin (protocol, "test", + T_DOUBLE, + 17, NULL) == 1); + g_assert (thrift_compact_protocol_write_field_end (protocol, NULL) == 0); + + /* test field state w.r.t. bools */ + + /* deltas */ + /* non-bool field -> bool field -> non-bool field */ + g_assert (thrift_compact_protocol_write_field_begin (protocol, "test", + T_DOUBLE, + 18, NULL) == 1); + g_assert (thrift_compact_protocol_write_field_end (protocol, NULL) == 0); + g_assert (thrift_compact_protocol_write_field_begin (protocol, "test", T_BOOL, + 19, NULL) == 0); + g_assert (thrift_compact_protocol_write_bool (protocol, TEST_BOOL, + NULL) == 1); + g_assert (thrift_compact_protocol_write_field_end (protocol, NULL) == 0); + g_assert (thrift_compact_protocol_write_field_begin (protocol, "test", + T_DOUBLE, + 20, NULL) == 1); + g_assert (thrift_compact_protocol_write_field_end (protocol, NULL) == 0); + /* bool -> bool field -> bool */ + g_assert (thrift_compact_protocol_write_bool (protocol, TEST_BOOL, NULL) > 0); + g_assert (thrift_compact_protocol_write_field_begin (protocol, "test", T_BOOL, + 21, NULL) == 0); + g_assert (thrift_compact_protocol_write_bool (protocol, TEST_BOOL, + NULL) == 1); + g_assert (thrift_compact_protocol_write_field_end (protocol, NULL) == 0); + g_assert (thrift_compact_protocol_write_bool (protocol, TEST_BOOL, NULL) > 0); + + /* no deltas */ + /* non-bool field -> bool field -> non-bool field */ + g_assert (thrift_compact_protocol_write_field_begin (protocol, "test", + T_DOUBLE, + 1, NULL) > 1); + g_assert (thrift_compact_protocol_write_field_end (protocol, NULL) == 0); + g_assert (thrift_compact_protocol_write_field_begin (protocol, "test", T_BOOL, + 1, NULL) == 0); + g_assert (thrift_compact_protocol_write_bool (protocol, TEST_BOOL, NULL) > 1); + g_assert (thrift_compact_protocol_write_field_end (protocol, NULL) == 0); + g_assert (thrift_compact_protocol_write_field_begin (protocol, "test", + T_DOUBLE, + 1, NULL) > 1); + g_assert (thrift_compact_protocol_write_field_end (protocol, NULL) == 0); + /* bool -> bool field -> bool */ + g_assert (thrift_compact_protocol_write_bool (protocol, TEST_BOOL, NULL) > 0); + g_assert (thrift_compact_protocol_write_field_begin (protocol, "test", T_BOOL, + 1, NULL) == 0); + g_assert (thrift_compact_protocol_write_bool (protocol, TEST_BOOL, NULL) > 1); + g_assert (thrift_compact_protocol_write_field_end (protocol, NULL) == 0); + g_assert (thrift_compact_protocol_write_bool (protocol, TEST_BOOL, NULL) > 0); + + /* test write error */ + transport_write_error = 1; + g_assert (thrift_compact_protocol_write_field_begin (protocol, "test", + T_DOUBLE, + 1, NULL) == -1); + transport_write_error = 0; + + /* test 2nd write error */ + transport_write_count = 0; + transport_write_error_at = 1; + g_assert (thrift_compact_protocol_write_field_begin (protocol, "test", + T_DOUBLE, + 1, NULL) == -1); + transport_write_error_at = -1; + + /* test 2nd read failure on a field */ + thrift_compact_protocol_write_byte (protocol, T_DOUBLE, NULL); + + /* test write_field_stop */ + g_assert (thrift_compact_protocol_write_field_stop (protocol, NULL) > 0); + + /* write a map */ + g_assert (thrift_compact_protocol_write_map_begin (protocol, T_DOUBLE, + T_DOUBLE, + 1, NULL) > 0); + g_assert (thrift_compact_protocol_write_map_end (protocol, NULL) == 0); + + /* test 1st read failure on map---nothing to do on our side */ + + /* test 2nd read failure on a map */ + thrift_compact_protocol_write_byte (protocol, T_DOUBLE, NULL); + + /* test 1st write failure on a map */ + transport_write_error = 1; + g_assert (thrift_compact_protocol_write_map_begin (protocol, T_DOUBLE, + T_DOUBLE, + 1, NULL) == -1); + transport_write_error = 0; + + /* test 2nd write failure on a map */ + transport_write_count = 0; + transport_write_error_at = 1; + g_assert (thrift_compact_protocol_write_map_begin (protocol, T_DOUBLE, + T_DOUBLE, + 1, NULL) == -1); + transport_write_error_at = -1; + + /* test negative map size */ + thrift_compact_protocol_write_varint32 (tc, -10, NULL); + thrift_compact_protocol_write_byte (protocol, T_DOUBLE, NULL); + + /* test list operations */ + g_assert (thrift_compact_protocol_write_list_begin (protocol, T_DOUBLE, + 15, NULL) > 0); + g_assert (thrift_compact_protocol_write_list_end (protocol, NULL) == 0); + + /* test 1st read failure on a small list---nothing to do on our end */ + + /* test 1st read failure on a big list---nothing to do on our end */ + + /* test 2nd read failure on a big list */ + thrift_compact_protocol_write_byte (protocol, (gint8) 0xf0, NULL); + + /* test negative list size */ + thrift_compact_protocol_write_byte (protocol, (gint8) 0xf0, NULL); + thrift_compact_protocol_write_varint32 (tc, -10, NULL); + + /* test first write error on a small list */ + transport_write_error = 1; + g_assert (thrift_compact_protocol_write_list_begin (protocol, T_DOUBLE, + 14, NULL) == -1); + transport_write_error = 0; + + /* test first write error on a big list */ + transport_write_error = 1; + g_assert (thrift_compact_protocol_write_list_begin (protocol, T_DOUBLE, + 15, NULL) == -1); + transport_write_error = 0; + + /* test 2nd write error on a big list */ + transport_write_count = 0; + transport_write_error_at = 1; + g_assert (thrift_compact_protocol_write_list_begin (protocol, T_DOUBLE, + 15, NULL) == -1); + transport_write_error_at = -1; + + /* test set operation s*/ + g_assert (thrift_compact_protocol_write_set_begin (protocol, T_DOUBLE, + 1, NULL) > 0); + g_assert (thrift_compact_protocol_write_set_end (protocol, NULL) == 0); + + /* invalid protocol */ + g_assert (thrift_compact_protocol_write_byte (protocol, 0, NULL) > 0); + + /* invalid version */ + g_assert (thrift_compact_protocol_write_byte (protocol, (gint8) 0x82u, + NULL) > 0); + g_assert (thrift_compact_protocol_write_byte (protocol, 0, NULL) > 0); + + /* send a valid message */ + g_assert (thrift_compact_protocol_write_byte (protocol, (gint8) 0x82u, + NULL) > 0); + g_assert (thrift_compact_protocol_write_byte (protocol, 0x01u, NULL) > 0); + thrift_compact_protocol_write_varint32 (tc, 1, NULL); + thrift_compact_protocol_write_string (protocol, "test", NULL); + + /* broken 2nd read */ + thrift_compact_protocol_write_byte (protocol, (gint8) 0x82u, NULL); + + /* send a broken 3rd read */ + thrift_compact_protocol_write_byte (protocol, (gint8) 0x82u, NULL); + thrift_compact_protocol_write_byte (protocol, 0x01u, NULL); + + /* send a broken 4th read */ + thrift_compact_protocol_write_byte (protocol, (gint8) 0x82u, NULL); + thrift_compact_protocol_write_byte (protocol, 0x01u, NULL); + thrift_compact_protocol_write_varint32 (tc, 1, NULL); + + /* send a valid message */ + g_assert (thrift_compact_protocol_write_message_begin (protocol, "test", + T_CALL, 1, NULL) > 0); + + g_assert (thrift_compact_protocol_write_message_end (protocol, NULL) == 0); + + /* send broken writes */ + transport_write_error = 1; + g_assert (thrift_compact_protocol_write_message_begin (protocol, "test", + T_CALL, 1, NULL) == -1); + transport_write_error = 0; + + transport_write_count = 0; + transport_write_error_at = 1; + g_assert (thrift_compact_protocol_write_message_begin (protocol, "test", + T_CALL, 1, NULL) == -1); + transport_write_error_at = -1; + + transport_write_count = 0; + transport_write_error_at = 2; + g_assert (thrift_compact_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; + g_assert (thrift_compact_protocol_write_message_begin (protocol, "test", + T_CALL, 1, NULL) == -1); + transport_write_error_at = -1; + + /* clean up */ + thrift_transport_close (transport, NULL); + g_object_unref (tsocket); + g_object_unref (protocol); + g_assert (wait (&status) == pid); + g_assert (status == 0); + } +} + +static void +test_read_and_write_many_frames (void) +{ + int status; + pid_t pid; + ThriftSocket *tsocket = NULL; + ThriftTransport *transport = NULL; + ThriftFramedTransport *ft = NULL; + ThriftCompactProtocol *tc = NULL; + ThriftProtocol *protocol = NULL; + gpointer binary = (gpointer *) TEST_STRING; + const guint32 len = strlen (TEST_STRING); + int port = TEST_PORT; + + /* fork a server from the client */ + pid = fork (); + g_assert (pid >= 0); + + if (pid == 0) + { + /* child listens */ + thrift_server_many_frames (port); + exit (0); + } else { + /* parent. 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); + 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); + g_assert (ft != NULL); + transport = THRIFT_TRANSPORT (ft); + + thrift_transport_open (transport, NULL); + g_assert (thrift_transport_is_open (transport)); + + /* create a compact protocol */ + tc = g_object_new (THRIFT_TYPE_COMPACT_PROTOCOL, "transport", + transport, NULL); + protocol = THRIFT_PROTOCOL (tc); + g_assert (protocol != NULL); + + /* write a bunch of primitives */ + g_assert (thrift_compact_protocol_write_bool (protocol, TEST_BOOL, + NULL) > 0); + thrift_transport_flush (transport, NULL); + g_assert (thrift_compact_protocol_write_byte (protocol, TEST_BYTE, + NULL) > 0); + thrift_transport_flush (transport, NULL); + g_assert (thrift_compact_protocol_write_i16 (protocol, TEST_I16, NULL) > 0); + thrift_transport_flush (transport, NULL); + g_assert (thrift_compact_protocol_write_i32 (protocol, TEST_I32, NULL) > 0); + thrift_transport_flush (transport, NULL); + g_assert (thrift_compact_protocol_write_i64 (protocol, TEST_I64, NULL) > 0); + thrift_transport_flush (transport, NULL); + g_assert (thrift_compact_protocol_write_i16 (protocol, TEST_NI16, NULL) > 0); + thrift_transport_flush (transport, NULL); + g_assert (thrift_compact_protocol_write_i32 (protocol, TEST_NI32, NULL) > 0); + thrift_transport_flush (transport, NULL); + g_assert (thrift_compact_protocol_write_i64 (protocol, TEST_NI64, NULL) > 0); + thrift_transport_flush (transport, NULL); + g_assert (thrift_compact_protocol_write_i16 (protocol, 2, NULL) > 0); + thrift_transport_flush (transport, NULL); + g_assert (thrift_compact_protocol_write_i32 (protocol, 2, NULL) > 0); + thrift_transport_flush (transport, NULL); + g_assert (thrift_compact_protocol_write_i64 (protocol, 2, NULL) > 0); + thrift_transport_flush (transport, NULL); + g_assert (thrift_compact_protocol_write_i16 (protocol, -2, NULL) > 0); + thrift_transport_flush (transport, NULL); + g_assert (thrift_compact_protocol_write_i32 (protocol, -2, NULL) > 0); + thrift_transport_flush (transport, NULL); + g_assert (thrift_compact_protocol_write_i64 (protocol, -2, NULL) > 0); + thrift_transport_flush (transport, NULL); + g_assert (thrift_compact_protocol_write_double (protocol, + TEST_DOUBLE, NULL) > 0); + thrift_transport_flush (transport, NULL); + g_assert (thrift_compact_protocol_write_string (protocol, + TEST_STRING, NULL) > 0); + thrift_transport_flush (transport, NULL); + g_assert (thrift_compact_protocol_write_string (protocol, "", NULL) > 0); + thrift_transport_flush (transport, NULL); + g_assert (thrift_compact_protocol_write_binary (protocol, binary, + len, NULL) > 0); + thrift_transport_flush (transport, NULL); + g_assert (thrift_compact_protocol_write_binary (protocol, NULL, + 0, NULL) > 0); + thrift_transport_flush (transport, NULL); + g_assert (thrift_compact_protocol_write_binary (protocol, binary, + len, NULL) > 0); + thrift_transport_flush (transport, NULL); + + /* clean up */ + thrift_transport_write_end (transport, NULL); + thrift_transport_close (transport, NULL); + g_object_unref (ft); + g_object_unref (tsocket); + g_object_unref (tc); + g_assert (wait (&status) == pid); + g_assert (status == 0); + } +} + + +static void +thrift_server_primitives (const int port) +{ + ThriftServerTransport *transport = NULL; + ThriftTransport *client = NULL; + ThriftCompactProtocol *tc = NULL; + ThriftProtocol *protocol = NULL; + gboolean value_boolean = FALSE; + gint8 value_byte = 0, + zigzag_p16 = 0, zigzag_p32 = 0, zigzag_p64 = 0, + zigzag_n16 = 0, zigzag_n32 = 0, zigzag_n64 = 0; + gint16 value_16 = 0; + gint32 value_32 = 0; + gint64 value_64 = 0; + gint16 value_n16 = 0; + gint32 value_n32 = 0; + gint64 value_n64 = 0; + gdouble value_double = 0; + gchar *string = NULL; + gchar *empty_string = NULL; + gpointer binary = NULL; + guint32 len = 0; + void *comparator = (void *) TEST_STRING; + + 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); + + tc = g_object_new (THRIFT_TYPE_COMPACT_PROTOCOL, "transport", + client, NULL); + protocol = THRIFT_PROTOCOL (tc); + + g_assert (thrift_compact_protocol_read_bool (protocol, + &value_boolean, NULL) > 0); + g_assert (thrift_compact_protocol_read_byte (protocol, &value_byte, NULL) > 0); + g_assert (thrift_compact_protocol_read_i16 (protocol, &value_16, NULL) > 0); + g_assert (thrift_compact_protocol_read_i32 (protocol, &value_32, NULL) > 0); + g_assert (thrift_compact_protocol_read_i64 (protocol, &value_64, NULL) > 0); + g_assert (thrift_compact_protocol_read_i16 (protocol, &value_n16, NULL) > 0); + g_assert (thrift_compact_protocol_read_i32 (protocol, &value_n32, NULL) > 0); + g_assert (thrift_compact_protocol_read_i64 (protocol, &value_n64, NULL) > 0); + g_assert (thrift_compact_protocol_read_byte (protocol, &zigzag_p16, NULL) > 0); + g_assert (thrift_compact_protocol_read_byte (protocol, &zigzag_p32, NULL) > 0); + g_assert (thrift_compact_protocol_read_byte (protocol, &zigzag_p64, NULL) > 0); + g_assert (thrift_compact_protocol_read_byte (protocol, &zigzag_n16, NULL) > 0); + g_assert (thrift_compact_protocol_read_byte (protocol, &zigzag_n32, NULL) > 0); + g_assert (thrift_compact_protocol_read_byte (protocol, &zigzag_n64, NULL) > 0); + g_assert (thrift_compact_protocol_read_double (protocol, + &value_double, NULL) > 0); + g_assert (thrift_compact_protocol_read_string (protocol, &string, NULL) > 0); + g_assert (thrift_compact_protocol_read_string (protocol, &empty_string, + NULL) > 0); + g_assert (thrift_compact_protocol_read_binary (protocol, &binary, + &len, NULL) > 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_n16 == TEST_NI16); + g_assert (value_n32 == TEST_NI32); + g_assert (value_n64 == TEST_NI64); + g_assert (zigzag_p16 == 4); + g_assert (zigzag_p32 == 4); + g_assert (zigzag_p64 == 4); + g_assert (zigzag_n16 == 3); + g_assert (zigzag_n32 == 3); + g_assert (zigzag_n64 == 3); + 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_compact_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; + g_assert (thrift_compact_protocol_read_binary (protocol, &binary, + &len, NULL) == -1); + transport_read_error_at = -1; + + transport_read_count = 0; + transport_read_error_at = 1; + g_assert (thrift_compact_protocol_read_binary (protocol, &binary, + &len, NULL) == -1); + transport_read_error_at = -1; + + transport_read_error = 1; + g_assert (thrift_compact_protocol_read_bool (protocol, + &value_boolean, NULL) == -1); + g_assert (thrift_compact_protocol_read_byte (protocol, + &value_byte, NULL) == -1); + g_assert (thrift_compact_protocol_read_i16 (protocol, + &value_16, NULL) == -1); + g_assert (thrift_compact_protocol_read_i32 (protocol, &value_32, NULL) == -1); + g_assert (thrift_compact_protocol_read_i64 (protocol, &value_64, NULL) == -1); + g_assert (thrift_compact_protocol_read_i16 (protocol, + &value_n16, NULL) == -1); + g_assert (thrift_compact_protocol_read_i32 (protocol, &value_n32, NULL) == -1); + g_assert (thrift_compact_protocol_read_i64 (protocol, &value_n64, NULL) == -1); + g_assert (thrift_compact_protocol_read_double (protocol, + &value_double, NULL) == -1); + transport_read_error = 0; + + /* test partial write failure */ + thrift_protocol_read_i32 (protocol, &value_32, NULL); + + thrift_transport_read_end (client, NULL); + thrift_transport_close (client, NULL); + + g_object_unref (tc); + g_object_unref (client); + g_object_unref (tsocket); +} + +static void +thrift_server_complex_types (const int port) +{ + ThriftServerTransport *transport = NULL; + ThriftTransport *client = NULL; + ThriftCompactProtocol *tc = NULL; + ThriftProtocol *protocol = NULL; + gchar *struct_name = NULL; + gchar *field_name = NULL; + gchar *message_name = NULL; + ThriftType element_type, key_type, value_type, field_type; + ThriftMessageType message_type; + gboolean value_boolean = ! TEST_BOOL; + gint8 value = 0; + gint16 field_id = 0; + guint32 size = 0; + gint32 seqid = 0; + gint8 version_and_type = 0; + gint8 protocol_id = 0; + + 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); + + tc = g_object_new (THRIFT_TYPE_COMPACT_PROTOCOL, "transport", + client, NULL); + protocol = THRIFT_PROTOCOL (tc); + + /* test struct operations */ + + thrift_compact_protocol_read_struct_begin (protocol, &struct_name, NULL); + thrift_compact_protocol_read_struct_end (protocol, NULL); + + /* test field state w.r.t. deltas */ + + field_id = 0; + g_assert (thrift_compact_protocol_read_field_begin (protocol, &field_name, + &field_type, + &field_id, NULL) == 1); + g_assert (field_id == 1); + field_id = 0; + g_assert (thrift_compact_protocol_read_field_begin (protocol, &field_name, + &field_type, + &field_id, NULL) == 1); + g_assert (field_id == 16); + field_id = 0; + g_assert (thrift_compact_protocol_read_field_begin (protocol, &field_name, + &field_type, + &field_id, NULL) == 1); + g_assert (field_id == 17); + field_id = 0; + g_assert (thrift_compact_protocol_read_field_begin (protocol, &field_name, + &field_type, + &field_id, NULL) > 1); + g_assert (field_id == 15); + field_id = 0; + g_assert (thrift_compact_protocol_read_field_begin (protocol, &field_name, + &field_type, + &field_id, NULL) == 1); + g_assert (field_id == 30); + field_id = 0; + g_assert (thrift_compact_protocol_read_field_begin (protocol, &field_name, + &field_type, + &field_id, NULL) > 1); + g_assert (field_id == 46); + field_id = 0; + g_assert (thrift_compact_protocol_read_field_begin (protocol, &field_name, + &field_type, + &field_id, NULL) == 1); + g_assert (field_id == 47); + field_id = 0; + + /* test field operations */ + + thrift_compact_protocol_read_field_begin (protocol, &field_name, &field_type, + &field_id, NULL); + thrift_compact_protocol_read_field_end (protocol, NULL); + + /* test field state w.r.t. structs */ + + g_assert (thrift_compact_protocol_read_field_begin (protocol, &field_name, + &field_type, + &field_id, NULL) > 1); + g_assert (field_id == 1); + field_id = 0; + thrift_compact_protocol_read_field_end (protocol, NULL); + g_assert (thrift_compact_protocol_read_field_begin (protocol, &field_name, + &field_type, + &field_id, NULL) == 1); + g_assert (field_id == 16); + field_id = 0; + thrift_compact_protocol_read_field_end (protocol, NULL); + + g_assert (thrift_compact_protocol_read_struct_begin (protocol, + &struct_name, NULL) == 0); + g_assert (thrift_compact_protocol_read_field_begin (protocol, &field_name, + &field_type, + &field_id, NULL) > 1); + g_assert (field_id == 17); + field_id = 0; + thrift_compact_protocol_read_field_end (protocol, NULL); + + g_assert (thrift_compact_protocol_read_struct_begin (protocol, + &struct_name, NULL) == 0); + g_assert (thrift_compact_protocol_read_field_begin (protocol, &field_name, + &field_type, + &field_id, NULL) > 1); + g_assert (field_id == 18); + field_id = 0; + thrift_compact_protocol_read_field_end (protocol, NULL); + g_assert (thrift_compact_protocol_read_field_begin (protocol, &field_name, + &field_type, + &field_id, NULL) == 1); + g_assert (field_id == 19); + field_id = 0; + thrift_compact_protocol_read_field_end (protocol, NULL); + g_assert (thrift_compact_protocol_read_struct_end (protocol, NULL) == 0); + + g_assert (thrift_compact_protocol_read_field_begin (protocol, &field_name, + &field_type, + &field_id, NULL) == 1); + g_assert (field_id == 18); + field_id = 0; + thrift_compact_protocol_read_field_end (protocol, NULL); + g_assert (thrift_compact_protocol_read_field_begin (protocol, &field_name, + &field_type, + &field_id, NULL) == 1); + g_assert (field_id == 25); + field_id = 0; + thrift_compact_protocol_read_field_end (protocol, NULL); + g_assert (thrift_compact_protocol_read_struct_end (protocol, NULL) == 0); + + g_assert (thrift_compact_protocol_read_field_begin (protocol, &field_name, + &field_type, + &field_id, NULL) == 1); + g_assert (field_id == 17); + field_id = 0; + thrift_compact_protocol_read_field_end (protocol, NULL); + + /* test field state w.r.t. bools */ + + /* deltas */ + /* non-bool field -> bool field -> non-bool field */ + g_assert (thrift_compact_protocol_read_field_begin (protocol, &field_name, + &field_type, + &field_id, NULL) == 1); + thrift_compact_protocol_read_field_end (protocol, NULL); + g_assert (thrift_compact_protocol_read_field_begin (protocol, &field_name, + &field_type, + &field_id, NULL) == 1); + g_assert (field_type == T_BOOL); + g_assert (thrift_compact_protocol_read_bool (protocol, + &value_boolean, NULL) == 0); + g_assert (value_boolean == TEST_BOOL); + value_boolean = ! TEST_BOOL; + thrift_compact_protocol_read_field_end (protocol, NULL); + g_assert (thrift_compact_protocol_read_field_begin (protocol, &field_name, + &field_type, + &field_id, NULL) == 1); + thrift_compact_protocol_read_field_end (protocol, NULL); + /* bool -> bool field -> bool */ + g_assert (thrift_compact_protocol_read_bool (protocol, + &value_boolean, NULL) > 0); + g_assert (value_boolean == TEST_BOOL); + value_boolean = ! TEST_BOOL; + g_assert (thrift_compact_protocol_read_field_begin (protocol, &field_name, + &field_type, + &field_id, NULL) == 1); + g_assert (field_type == T_BOOL); + g_assert (thrift_compact_protocol_read_bool (protocol, + &value_boolean, NULL) == 0); + g_assert (value_boolean == TEST_BOOL); + value_boolean = ! TEST_BOOL; + thrift_compact_protocol_read_field_end (protocol, NULL); + g_assert (thrift_compact_protocol_read_bool (protocol, + &value_boolean, NULL) > 0); + g_assert (value_boolean == TEST_BOOL); + value_boolean = ! TEST_BOOL; + + /* no deltas */ + /* non-bool field -> bool field -> non-bool field */ + g_assert (thrift_compact_protocol_read_field_begin (protocol, &field_name, + &field_type, + &field_id, NULL) > 1); + thrift_compact_protocol_read_field_end (protocol, NULL); + g_assert (thrift_compact_protocol_read_field_begin (protocol, &field_name, + &field_type, + &field_id, NULL) > 1); + g_assert (field_type == T_BOOL); + g_assert (thrift_compact_protocol_read_bool (protocol, + &value_boolean, NULL) == 0); + g_assert (value_boolean == TEST_BOOL); + value_boolean = ! TEST_BOOL; + thrift_compact_protocol_read_field_end (protocol, NULL); + g_assert (thrift_compact_protocol_read_field_begin (protocol, &field_name, + &field_type, + &field_id, NULL) > 1); + thrift_compact_protocol_read_field_end (protocol, NULL); + /* bool -> bool field -> bool */ + g_assert (thrift_compact_protocol_read_bool (protocol, + &value_boolean, NULL) > 0); + g_assert (value_boolean == TEST_BOOL); + value_boolean = ! TEST_BOOL; + g_assert (thrift_compact_protocol_read_field_begin (protocol, &field_name, + &field_type, + &field_id, NULL) > 1); + g_assert (field_type == T_BOOL); + g_assert (thrift_compact_protocol_read_bool (protocol, + &value_boolean, NULL) == 0); + g_assert (value_boolean == TEST_BOOL); + value_boolean = ! TEST_BOOL; + thrift_compact_protocol_read_field_end (protocol, NULL); + g_assert (thrift_compact_protocol_read_bool (protocol, + &value_boolean, NULL) > 0); + g_assert (value_boolean == TEST_BOOL); + value_boolean = ! TEST_BOOL; + + /* test first read error on a field */ + transport_read_error = 1; + g_assert (thrift_compact_protocol_read_field_begin (protocol, + &field_name, &field_type, + &field_id, NULL) == -1); + transport_read_error = 0; + + /* test 2nd write failure */ + thrift_compact_protocol_read_byte (protocol, &value, NULL); + + /* test 2nd read failure on a field */ + transport_read_count = 0; + transport_read_error_at = 1; + g_assert (thrift_compact_protocol_read_field_begin (protocol, + &field_name, &field_type, + &field_id, NULL) == -1); + transport_read_error_at = -1; + + /* test field stop */ + thrift_compact_protocol_read_field_begin (protocol, &field_name, &field_type, + &field_id, NULL); + + /* test map operations */ + + thrift_compact_protocol_read_map_begin (protocol, &key_type, &value_type, + &size, NULL); + thrift_compact_protocol_read_map_end (protocol, NULL); + + /* test 1st read failure on a map */ + transport_read_count = 0; + transport_read_error_at = 0; + g_assert (thrift_compact_protocol_read_map_begin (protocol, + &key_type, &value_type, + &size, NULL) == -1); + transport_read_error_at = -1; + + /* test 2nd read failure on a map */ + transport_read_count = 0; + transport_read_error_at = 1; + g_assert (thrift_compact_protocol_read_map_begin (protocol, + &key_type, &value_type, + &size, NULL) == -1); + transport_read_error_at = -1; + + /* test 1st write failure on map---nothing to do on our side */ + + /* test 2nd write failure */ + thrift_compact_protocol_read_byte (protocol, &value, NULL); + + /* test negative map size */ + g_assert (thrift_compact_protocol_read_map_begin (protocol, + &key_type, &value_type, + &size, NULL) == -1); + + /* test list operations */ + thrift_compact_protocol_read_list_begin (protocol, &element_type, &size, + NULL); + thrift_compact_protocol_read_list_end (protocol, NULL); + + /* test small list 1st read failure */ + transport_read_error = 1; + g_assert (thrift_compact_protocol_read_list_begin (protocol, &element_type, + &size, NULL) == -1); + transport_read_error = 0; + + /* test big list 1st read failure */ + transport_read_error = 1; + g_assert (thrift_compact_protocol_read_list_begin (protocol, &element_type, + &size, NULL) == -1); + transport_read_error = 0; + + /* test big list 2nd read failure */ + transport_read_count = 0; + transport_read_error_at = 1; + thrift_compact_protocol_read_list_begin (protocol, &element_type, &size, + NULL); + transport_read_error_at = -1; + + /* test negative list size failure */ + thrift_compact_protocol_read_list_begin (protocol, &element_type, &size, + NULL); + + /* test small list 1st write failure---nothing to do on our end */ + + /* test big list 1st write failure---nothing to do on our end */ + + /* test big list 2nd write failure */ + thrift_compact_protocol_read_byte (protocol, &value, NULL); + + /* test set operations */ + thrift_compact_protocol_read_set_begin (protocol, &element_type, &size, NULL); + thrift_compact_protocol_read_set_end (protocol, NULL); + + /* broken read */ + transport_read_error = 1; + g_assert (thrift_compact_protocol_read_message_begin (protocol, &message_name, + &message_type, &seqid, + NULL) == -1); + transport_read_error = 0; + + /* invalid protocol */ + g_assert (thrift_compact_protocol_read_message_begin (protocol, &message_name, + &message_type, &seqid, + NULL) == -1); + + /* invalid version */ + g_assert (thrift_compact_protocol_read_message_begin (protocol, &message_name, + &message_type, &seqid, + NULL) == -1); + + /* read a valid message */ + g_assert (thrift_compact_protocol_read_message_begin (protocol, &message_name, + &message_type, &seqid, + NULL) > 0); + g_free (message_name); + + /* broken 2nd read on a message */ + transport_read_count = 0; + transport_read_error_at = 1; + g_assert (thrift_compact_protocol_read_message_begin (protocol, &message_name, + &message_type, &seqid, + NULL) == -1); + transport_read_error_at = -1; + + /* broken 3rd read on a message */ + transport_read_count = 0; + transport_read_error_at = 2; + g_assert (thrift_compact_protocol_read_message_begin (protocol, &message_name, + &message_type, &seqid, + NULL) == -1); + transport_read_error_at = -1; + + /* broken 4th read on a message */ + transport_read_count = 0; + transport_read_error_at = 3; + g_assert (thrift_compact_protocol_read_message_begin (protocol, &message_name, + &message_type, &seqid, + NULL) == -1); + transport_read_error_at = -1; + + /* read a valid message */ + g_assert (thrift_compact_protocol_read_message_begin (protocol, &message_name, + &message_type, &seqid, + NULL) > 0); + g_free (message_name); + + g_assert (thrift_compact_protocol_read_message_end (protocol, NULL) == 0); + + /* handle 2nd write failure on a message */ + thrift_compact_protocol_read_byte (protocol, &protocol_id, NULL); + + /* handle 3rd write failure on a message */ + thrift_compact_protocol_read_byte (protocol, &protocol_id, NULL); + thrift_compact_protocol_read_byte (protocol, &version_and_type, NULL); + + /* handle 4th write failure on a message */ + thrift_compact_protocol_read_byte (protocol, &protocol_id, NULL); + thrift_compact_protocol_read_byte (protocol, &version_and_type, NULL); + thrift_compact_protocol_read_varint32 (tc, &seqid, NULL); + + g_object_unref (client); + g_object_unref (tsocket); +} + +static void +thrift_server_many_frames (const int port) +{ + ThriftServerTransport *transport = NULL; + ThriftTransport *client = NULL; + ThriftCompactProtocol *tcp = NULL; + ThriftProtocol *protocol = NULL; + ThriftServerSocket *tsocket = NULL; + gboolean value_boolean = FALSE; + gint8 value_byte = 0, + zigzag_p16 = 0, zigzag_p32 = 0, zigzag_p64 = 0, + zigzag_n16 = 0, zigzag_n32 = 0, zigzag_n64 = 0; + gint16 value_16 = 0; + gint32 value_32 = 0; + gint64 value_64 = 0; + gint16 value_n16 = 0; + gint32 value_n32 = 0; + gint64 value_n64 = 0; + gdouble value_double = 0; + gchar *string = NULL; + gchar *empty_string = NULL; + gpointer binary = NULL; + guint32 len = 0; + void *comparator = (void *) TEST_STRING; + + tsocket = g_object_new (THRIFT_TYPE_SERVER_SOCKET, "port", port, NULL); + transport = THRIFT_SERVER_TRANSPORT (tsocket); + thrift_server_transport_listen (transport, NULL); + + /* wrap the client in a framed transport */ + client = g_object_new (THRIFT_TYPE_FRAMED_TRANSPORT, "transport", + thrift_server_transport_accept (transport, NULL), + "r_buf_size", 1, NULL); + g_assert (client != NULL); + + tcp = g_object_new (THRIFT_TYPE_COMPACT_PROTOCOL, "transport", + client, NULL); + protocol = THRIFT_PROTOCOL (tcp); + + g_assert (thrift_compact_protocol_read_bool (protocol, + &value_boolean, NULL) > 0); + g_assert (thrift_compact_protocol_read_byte (protocol, &value_byte, NULL) > 0); + g_assert (thrift_compact_protocol_read_i16 (protocol, &value_16, NULL) > 0); + g_assert (thrift_compact_protocol_read_i32 (protocol, &value_32, NULL) > 0); + g_assert (thrift_compact_protocol_read_i64 (protocol, &value_64, NULL) > 0); + g_assert (thrift_compact_protocol_read_i16 (protocol, &value_n16, NULL) > 0); + g_assert (thrift_compact_protocol_read_i32 (protocol, &value_n32, NULL) > 0); + g_assert (thrift_compact_protocol_read_i64 (protocol, &value_n64, NULL) > 0); + g_assert (thrift_compact_protocol_read_byte (protocol, &zigzag_p16, NULL) > 0); + g_assert (thrift_compact_protocol_read_byte (protocol, &zigzag_p32, NULL) > 0); + g_assert (thrift_compact_protocol_read_byte (protocol, &zigzag_p64, NULL) > 0); + g_assert (thrift_compact_protocol_read_byte (protocol, &zigzag_n16, NULL) > 0); + g_assert (thrift_compact_protocol_read_byte (protocol, &zigzag_n32, NULL) > 0); + g_assert (thrift_compact_protocol_read_byte (protocol, &zigzag_n64, NULL) > 0); + g_assert (thrift_compact_protocol_read_double (protocol, + &value_double, NULL) > 0); + g_assert (thrift_compact_protocol_read_string (protocol, &string, NULL) > 0); + g_assert (thrift_compact_protocol_read_string (protocol, &empty_string, + NULL) > 0); + g_assert (thrift_compact_protocol_read_binary (protocol, &binary, + &len, NULL) > 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_n16 == TEST_NI16); + g_assert (value_n32 == TEST_NI32); + g_assert (value_n64 == TEST_NI64); + g_assert (zigzag_p16 == 4); + g_assert (zigzag_p32 == 4); + g_assert (zigzag_p64 == 4); + g_assert (zigzag_n16 == 3); + g_assert (zigzag_n32 == 3); + g_assert (zigzag_n64 == 3); + 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_compact_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); + thrift_transport_close (client, NULL); + + g_object_unref (tcp); + g_object_unref (client); + g_object_unref (tsocket); +} + +int +main (int argc, char *argv[]) +{ +#if (!GLIB_CHECK_VERSION (2, 36, 0)) + g_type_init (); +#endif + + g_test_init (&argc, &argv, NULL); + + g_test_add_func ("/testcompactprotocol/CreateAndDestroy", + test_create_and_destroy); + g_test_add_func ("/testcompactprotocol/Initialize", test_initialize); + g_test_add_func ("/testcompactprotocol/ReadAndWritePrimitives", + test_read_and_write_primitives); + g_test_add_func ("/testcompactprotocol/ReadAndWriteComplexTypes", + test_read_and_write_complex_types); + g_test_add_func ("/testcompactprotocol/ReadAndWriteManyFrames", + test_read_and_write_many_frames); + + return g_test_run (); +} diff --git a/src/jaegertracing/thrift/lib/c_glib/test/testcontainertest.c b/src/jaegertracing/thrift/lib/c_glib/test/testcontainertest.c new file mode 100644 index 000000000..5fc51d516 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/test/testcontainertest.c @@ -0,0 +1,529 @@ +/* + * 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 "gen-c_glib/t_test_container_test_types.h" +#include "gen-c_glib/t_test_container_service.h" + +#include <thrift/c_glib/thrift.h> +#include <thrift/c_glib/protocol/thrift_binary_protocol_factory.h> +#include <thrift/c_glib/protocol/thrift_binary_protocol.h> +#include <thrift/c_glib/protocol/thrift_protocol_factory.h> +#include <thrift/c_glib/server/thrift_server.h> +#include <thrift/c_glib/server/thrift_simple_server.h> +#include <thrift/c_glib/transport/thrift_buffered_transport_factory.h> +#include <thrift/c_glib/transport/thrift_buffered_transport.h> +#include <thrift/c_glib/transport/thrift_server_socket.h> +#include <thrift/c_glib/transport/thrift_server_transport.h> +#include <thrift/c_glib/transport/thrift_socket.h> + +#include <glib-object.h> +#include <glib.h> + +#include <unistd.h> +#include <signal.h> +#include <string.h> +#include <sys/wait.h> +#include <sys/types.h> + +#define TEST_SERVER_HOSTNAME "localhost" +#define TEST_SERVER_PORT 9090 + +/* -------------------------------------------------------------------------- + The ContainerService handler we'll use for testing */ + +G_BEGIN_DECLS + +GType test_container_service_handler_get_type (void); + +#define TYPE_TEST_CONTAINER_SERVICE_HANDLER \ + (test_container_service_handler_get_type ()) + +#define TEST_CONTAINER_SERVICE_HANDLER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + TYPE_TEST_CONTAINER_SERVICE_HANDLER, \ + TestContainerServiceHandler)) +#define TEST_CONTAINER_SERVICE_HANDLER_CLASS(c) \ + (G_TYPE_CHECK_CLASS_CAST ((c), \ + TYPE_TEST_CONTAINER_SERVICE_HANDLER, \ + TestContainerServiceHandlerClass)) +#define IS_TEST_CONTAINER_SERVICE_HANDLER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ + TYPE_TEST_CONTAINER_SERVICE_HANDLER)) +#define IS_TEST_CONTAINER_SERVICE_HANDLER_CLASS(c) \ + (G_TYPE_CHECK_CLASS_TYPE ((c), \ + TYPE_TEST_CONTAINER_SERVICE_HANDLER)) +#define TEST_CONTAINER_SERVICE_HANDLER_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + TYPE_TEST_CONTAINER_SERVICE_HANDLER, \ + TestContainerServiceHandlerClass)) + +struct _TestContainerServiceHandler { + TTestContainerServiceHandler parent_instance; + + /* private */ + GPtrArray *string_list; +}; +typedef struct _TestContainerServiceHandler TestContainerServiceHandler; + +struct _TestContainerServiceHandlerClass { + TTestContainerServiceHandlerClass parent_class; +}; +typedef struct _TestContainerServiceHandlerClass + TestContainerServiceHandlerClass; + +G_END_DECLS + +/* -------------------------------------------------------------------------- */ + +G_DEFINE_TYPE (TestContainerServiceHandler, + test_container_service_handler, + T_TEST_TYPE_CONTAINER_SERVICE_HANDLER) + +/* A helper function used to append copies of strings to a string list */ +static void append_string_to_ptr_array (gpointer element, gpointer ptr_array) +{ + g_ptr_array_add ((GPtrArray *)ptr_array, g_strdup ((gchar *)element)); +} + +/* Accept a string list from the client and append its contents to our internal + list */ +static gboolean +test_container_service_handler_receive_string_list (TTestContainerServiceIf *iface, + const GPtrArray *stringList, + GError **error) +{ + TestContainerServiceHandler *self = TEST_CONTAINER_SERVICE_HANDLER (iface); + + /* Append the client's strings to our own internal string list */ + g_ptr_array_foreach ((GPtrArray *)stringList, + append_string_to_ptr_array, + self->string_list); + + g_clear_error (error); + return TRUE; +} + +/* Return the contents of our internal string list to the client */ +static gboolean +test_container_service_handler_return_string_list (TTestContainerServiceIf *iface, + GPtrArray **_return, + GError **error) +{ + TestContainerServiceHandler *self = TEST_CONTAINER_SERVICE_HANDLER (iface); + + /* Return (copies of) the strings contained in our list */ + g_ptr_array_foreach (self->string_list, + append_string_to_ptr_array, + *_return); + + g_clear_error (error); + return TRUE; +} + +static gboolean +test_container_service_handler_return_list_string_list (TTestContainerServiceIf *iface, + GPtrArray **_return, + GError **error) +{ + TestContainerServiceHandler *self = TEST_CONTAINER_SERVICE_HANDLER (iface); + GPtrArray *nested_list; + + /* Return a list containing our list of strings */ + nested_list + = g_ptr_array_new_with_free_func ((GDestroyNotify)g_ptr_array_unref); + g_ptr_array_add (nested_list, self->string_list); + g_ptr_array_ref (self->string_list); + + g_ptr_array_add (*_return, nested_list); + + g_clear_error (error); + return TRUE; +} + +static gboolean +test_container_service_handler_return_typedefd_list_string_list (TTestContainerServiceIf *iface, + TTestListStringList **_return, + GError **error) +{ + TestContainerServiceHandler *self = TEST_CONTAINER_SERVICE_HANDLER (iface); + TTestStringList *nested_list; + + /* Return a list containing our list of strings */ + nested_list + = g_ptr_array_new_with_free_func ((GDestroyNotify)g_ptr_array_unref); + g_ptr_array_add (nested_list, self->string_list); + g_ptr_array_ref (self->string_list); + + g_ptr_array_add (*_return, nested_list); + + g_clear_error (error); + return TRUE; +} + +static void +test_container_service_handler_finalize (GObject *object) { + TestContainerServiceHandler *self = TEST_CONTAINER_SERVICE_HANDLER (object); + + /* Destroy our internal containers */ + g_ptr_array_unref (self->string_list); + self->string_list = NULL; + + G_OBJECT_CLASS (test_container_service_handler_parent_class)-> + finalize (object); +} + +static void +test_container_service_handler_init (TestContainerServiceHandler *self) +{ + /* Create our internal containers */ + self->string_list = g_ptr_array_new_with_free_func (g_free); +} + +static void +test_container_service_handler_class_init (TestContainerServiceHandlerClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + TTestContainerServiceHandlerClass *parent_class = + T_TEST_CONTAINER_SERVICE_HANDLER_CLASS (klass); + + gobject_class->finalize = test_container_service_handler_finalize; + + parent_class->receive_string_list = + test_container_service_handler_receive_string_list; + parent_class->return_string_list = + test_container_service_handler_return_string_list; + parent_class->return_list_string_list = + test_container_service_handler_return_list_string_list; + parent_class->return_typedefd_list_string_list = + test_container_service_handler_return_typedefd_list_string_list; +} + +/* -------------------------------------------------------------------------- */ + +/* Our test server, declared globally so we can access it within a signal + handler */ +ThriftServer *server = NULL; + +/* A signal handler used to detect when the child process (the test suite) has + exited so we know to shut down the server and terminate ourselves */ +static void +sigchld_handler (int signal_number) +{ + THRIFT_UNUSED_VAR (signal_number); + + /* The child process (the tests) has exited or been terminated; shut down the + server gracefully */ + if (server != NULL) + thrift_server_stop (server); +} + +/* A helper function that executes a test case against a newly constructed + service client */ +static void +execute_with_service_client (void (*test_case)(TTestContainerServiceIf *, + GError **)) +{ + ThriftSocket *socket; + ThriftTransport *transport; + ThriftProtocol *protocol; + + TTestContainerServiceIf *client; + + GError *error = NULL; + + /* Create a client with which to access the server */ + socket = g_object_new (THRIFT_TYPE_SOCKET, + "hostname", TEST_SERVER_HOSTNAME, + "port", TEST_SERVER_PORT, + NULL); + transport = g_object_new (THRIFT_TYPE_BUFFERED_TRANSPORT, + "transport", socket, + NULL); + protocol = g_object_new (THRIFT_TYPE_BINARY_PROTOCOL, + "transport", transport, + NULL); + + thrift_transport_open (transport, &error); + g_assert_no_error (error); + + client = g_object_new (T_TEST_TYPE_CONTAINER_SERVICE_CLIENT, + "input_protocol", protocol, + "output_protocol", protocol, + NULL); + + /* Execute the test against this client */ + (*test_case)(client, &error); + g_assert_no_error (error); + + /* Clean up and exit */ + thrift_transport_close (transport, NULL); + + g_object_unref (client); + g_object_unref (protocol); + g_object_unref (transport); + g_object_unref (socket); +} + +static void +test_containers_with_default_values (void) +{ + TTestContainersWithDefaultValues *default_values; + GPtrArray *string_list; + + /* Fetch a new ContainersWithDefaultValues struct and its StringList member */ + default_values = g_object_new (T_TEST_TYPE_CONTAINERS_WITH_DEFAULT_VALUES, + NULL); + g_object_get (default_values, + "StringList", &string_list, + NULL); + + /* Make sure the list has been populated with its default values */ + g_assert_cmpint (string_list->len, ==, 2); + g_assert_cmpstr (((gchar **)string_list->pdata)[0], ==, "Apache"); + g_assert_cmpstr (((gchar **)string_list->pdata)[1], ==, "Thrift"); + + g_ptr_array_unref (string_list); + g_object_unref (default_values); +} + +static void +test_container_service_string_list_inner (TTestContainerServiceIf *client, + GError **error) +{ + gchar *test_data[] = { "one", "two", "three" }; + + GPtrArray *outgoing_string_list; + GPtrArray *incoming_string_list; + guint index; + + g_clear_error (error); + + /* Prepare our test data (our string list to send) */ + outgoing_string_list = g_ptr_array_new (); + for (index = 0; index < 3; index += 1) + g_ptr_array_add (outgoing_string_list, &test_data[index]); + + /* Send our data to the server and make sure we get the same data back on + retrieve */ + g_assert + (t_test_container_service_client_receive_string_list (client, + outgoing_string_list, + error) && + *error == NULL); + + incoming_string_list = g_ptr_array_new (); + g_assert + (t_test_container_service_client_return_string_list (client, + &incoming_string_list, + error) && + *error == NULL); + + /* Make sure the two lists are equivalent */ + g_assert_cmpint (incoming_string_list->len, ==, outgoing_string_list->len); + for (index = 0; index < incoming_string_list->len; index += 1) + g_assert_cmpstr (((gchar **)incoming_string_list->pdata)[index], + ==, + ((gchar **)outgoing_string_list->pdata)[index]); + + /* Clean up and exit */ + g_ptr_array_unref (incoming_string_list); + g_ptr_array_unref (outgoing_string_list); +} + +static void +test_container_service_string_list (void) +{ + execute_with_service_client (test_container_service_string_list_inner); +} + +static void +test_container_service_list_string_list_inner (TTestContainerServiceIf *client, + GError **error) +{ + GPtrArray *incoming_list; + GPtrArray *nested_list; + + g_clear_error (error); + + /* Receive a list of string lists from the server */ + incoming_list = + g_ptr_array_new_with_free_func ((GDestroyNotify)g_ptr_array_unref); + g_assert + (t_test_container_service_client_return_list_string_list (client, + &incoming_list, + error) && + *error == NULL); + + /* Make sure the list and its contents are valid */ + g_assert_cmpint (incoming_list->len, >, 0); + + nested_list = (GPtrArray *)g_ptr_array_index (incoming_list, 0); + g_assert (nested_list != NULL); + g_assert_cmpint (nested_list->len, >=, 0); + + /* Clean up and exit */ + g_ptr_array_unref (incoming_list); +} + +static void +test_container_service_list_string_list (void) +{ + execute_with_service_client (test_container_service_list_string_list_inner); +} + +static void +test_container_service_typedefd_list_string_list_inner (TTestContainerServiceIf *client, + GError **error) +{ + TTestListStringList *incoming_list; + TTestStringList *nested_list; + + g_clear_error (error); + + /* Receive a list of string lists from the server */ + incoming_list = + g_ptr_array_new_with_free_func ((GDestroyNotify)g_ptr_array_unref); + g_assert + (t_test_container_service_client_return_list_string_list (client, + &incoming_list, + error) && + *error == NULL); + + /* Make sure the list and its contents are valid */ + g_assert_cmpint (incoming_list->len, >, 0); + + nested_list = (TTestStringList *)g_ptr_array_index (incoming_list, 0); + g_assert (nested_list != NULL); + g_assert_cmpint (nested_list->len, >=, 0); + + /* Clean up and exit */ + g_ptr_array_unref (incoming_list); +} + +static void +test_container_service_typedefd_list_string_list (void) +{ + execute_with_service_client + (test_container_service_typedefd_list_string_list_inner); +} + +int +main(int argc, char *argv[]) +{ + pid_t pid; + int status; + +#if (!GLIB_CHECK_VERSION (2, 36, 0)) + g_type_init (); +#endif + + /* Fork to run our test suite in a child process */ + pid = fork (); + g_assert_cmpint (pid, >=, 0); + + if (pid == 0) { /* The child process */ + /* Wait a moment for the server to finish starting */ + sleep (1); + + g_test_init (&argc, &argv, NULL); + + g_test_add_func + ("/testcontainertest/ContainerTest/Structs/ContainersWithDefaultValues", + test_containers_with_default_values); + g_test_add_func + ("/testcontainertest/ContainerTest/Services/ContainerService/StringList", + test_container_service_string_list); + g_test_add_func + ("/testcontainertest/ContainerTest/Services/ContainerService/ListStringList", + test_container_service_list_string_list); + g_test_add_func + ("/testcontainertest/ContainerTest/Services/ContainerService/TypedefdListStringList", + test_container_service_typedefd_list_string_list); + + /* Run the tests and make the result available to our parent process */ + _exit (g_test_run ()); + } + else { + TTestContainerServiceHandler *handler; + TTestContainerServiceProcessor *processor; + + ThriftServerTransport *server_transport; + ThriftTransportFactory *transport_factory; + ThriftProtocolFactory *protocol_factory; + + struct sigaction sigchld_action; + + GError *error = NULL; + int exit_status = 1; + + /* Trap the event of the child process terminating so we know to stop the + server and exit */ + memset (&sigchld_action, 0, sizeof (sigchld_action)); + sigchld_action.sa_handler = sigchld_handler; + sigchld_action.sa_flags = SA_RESETHAND; + sigaction (SIGCHLD, &sigchld_action, NULL); + + /* Create our test server */ + handler = g_object_new (TYPE_TEST_CONTAINER_SERVICE_HANDLER, + NULL); + processor = g_object_new (T_TEST_TYPE_CONTAINER_SERVICE_PROCESSOR, + "handler", handler, + NULL); + server_transport = g_object_new (THRIFT_TYPE_SERVER_SOCKET, + "port", TEST_SERVER_PORT, + NULL); + transport_factory = g_object_new (THRIFT_TYPE_BUFFERED_TRANSPORT_FACTORY, + NULL); + protocol_factory = g_object_new (THRIFT_TYPE_BINARY_PROTOCOL_FACTORY, + NULL); + + server = g_object_new (THRIFT_TYPE_SIMPLE_SERVER, + "processor", processor, + "server_transport", server_transport, + "input_transport_factory", transport_factory, + "output_transport_factory", transport_factory, + "input_protocol_factory", protocol_factory, + "output_protocol_factory", protocol_factory, + NULL); + + /* Start the server */ + thrift_server_serve (server, &error); + + /* Make sure the server stopped only because it was interrupted (by the + child process terminating) */ + g_assert(!error || g_error_matches(error, + THRIFT_SERVER_SOCKET_ERROR, + THRIFT_SERVER_SOCKET_ERROR_ACCEPT)); + + /* Free our resources */ + 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); + if (WIFEXITED (status)) + exit_status = WEXITSTATUS (status); + + return exit_status; + } +} diff --git a/src/jaegertracing/thrift/lib/c_glib/test/testdebugproto.c b/src/jaegertracing/thrift/lib/c_glib/test/testdebugproto.c new file mode 100644 index 000000000..109a48b50 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/test/testdebugproto.c @@ -0,0 +1,941 @@ +/* + * 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 <math.h> +#include <string.h> +#include <glib-object.h> + +#ifndef M_PI +#define M_PI 3.1415926535897932385 +#endif + +#include <thrift/c_glib/protocol/thrift_protocol.h> +#include <thrift/c_glib/protocol/thrift_binary_protocol.h> + +#include "gen-c_glib/t_test_debug_proto_test_types.h" +#include "gen-c_glib/t_test_srv.h" +#include "gen-c_glib/t_test_inherited.h" + +static void +test_structs_doubles_create_and_destroy (void) +{ + GObject *object = NULL; + + /* A Doubles structure can be created... */ + object = g_object_new (T_TEST_TYPE_DOUBLES, NULL); + + g_assert (object != NULL); + g_assert (T_TEST_IS_DOUBLES (object)); + + /* ...and destroyed */ + g_object_unref (object); +} + +static void +test_structs_doubles_initialize (void) +{ + TTestDoubles *doubles = NULL; + gdouble nan; + gdouble inf; + gdouble neginf; + gdouble repeating; + gdouble big; + gdouble tiny; + gdouble zero; + gdouble negzero; + + /* Note there seems to be no way to get not-a-number ("NAN") values past + GObject's range-checking, so that portion of the test has been commented + out below. */ + + /* A Doubles structure's members are available as GObject properties + that can be initialized at construction... */ + doubles = g_object_new (T_TEST_TYPE_DOUBLES, + /* "nan", 0 * INFINITY, */ + "inf", INFINITY, + "neginf", -INFINITY, + "repeating", 1.0 / 3, + "big", G_MAXDOUBLE, + "tiny", 10E-101, + "zero", 1.0 * 0, + "negzero", -1.0 * 0, + NULL); + + g_assert (doubles != NULL); + + /* ...and later retrieved */ + g_object_get (doubles, + "nan", &nan, + "inf", &inf, + "neginf", &neginf, + "repeating", &repeating, + "big", &big, + "tiny", &tiny, + "zero", &zero, + "negzero", &negzero, + NULL); + + /* g_assert_cmpint (isnan (nan), !=, 0); */ + g_assert_cmpint (isinf (inf), ==, 1); + g_assert_cmpint (isinf (neginf), ==, -1); + + g_assert_cmpfloat (repeating, ==, 1.0 / 3); + g_assert_cmpfloat (big, ==, G_MAXDOUBLE); + g_assert_cmpfloat (tiny, ==, 10E-101); + g_assert_cmpfloat (zero, ==, 1.0 * 0); + g_assert_cmpfloat (negzero, ==, -1.0 * 0); + + g_object_unref (doubles); +} + +static void +test_structs_one_of_each_create_and_destroy (void) +{ + GObject *object = NULL; + + /* A OneOfEach structure can be created... */ + object = g_object_new (T_TEST_TYPE_ONE_OF_EACH, NULL); + + g_assert (object != NULL); + g_assert (T_TEST_IS_ONE_OF_EACH (object)); + + /* ...and destroyed */ + g_object_unref (object); +} + +static void +test_structs_one_of_each_initialize_default_values (void) +{ + TTestOneOfEach *one_of_each = NULL; + gint a_bite; + gint integer16; + gint64 integer64; + GArray *byte_list; + GArray *i16_list; + GArray *i64_list; + + /* A OneOfEach structure created with no explicit property values + will hold the default values specified in the .thrift file */ + one_of_each = g_object_new (T_TEST_TYPE_ONE_OF_EACH, NULL); + + g_object_get (one_of_each, + "a_bite", &a_bite, + "integer16", &integer16, + "integer64", &integer64, + "byte_list", &byte_list, + "i16_list", &i16_list, + "i64_list", &i64_list, + NULL); + + g_assert_cmpint (a_bite, ==, 0x7f); + g_assert_cmpint (integer16, ==, 0x7fff); + g_assert_cmpint (integer64, ==, G_GINT64_CONSTANT (10000000000)); + + g_assert (byte_list != NULL); + g_assert_cmpint (byte_list->len, ==, 3); + g_assert_cmpint (g_array_index (byte_list, gint8, 0), ==, 1); + g_assert_cmpint (g_array_index (byte_list, gint8, 1), ==, 2); + g_assert_cmpint (g_array_index (byte_list, gint8, 2), ==, 3); + + g_assert (i16_list != NULL); + g_assert_cmpint (i16_list->len, ==, 3); + g_assert_cmpint (g_array_index (i16_list, gint16, 0), ==, 1); + g_assert_cmpint (g_array_index (i16_list, gint16, 1), ==, 2); + g_assert_cmpint (g_array_index (i16_list, gint16, 2), ==, 3); + + g_assert (i64_list != NULL); + g_assert_cmpint (i64_list->len, ==, 3); + g_assert_cmpint (g_array_index (i64_list, gint64, 0), ==, 1); + g_assert_cmpint (g_array_index (i64_list, gint64, 1), ==, 2); + g_assert_cmpint (g_array_index (i64_list, gint64, 2), ==, 3); + + g_array_unref (i64_list); + g_array_unref (i16_list); + g_array_unref (byte_list); + g_object_unref (one_of_each); +} + +static void +test_structs_one_of_each_initialize_specified_values (void) +{ + static const gint8 initial_byte_list[5] = { 13, 21, 34, 55, 89 }; + static const gint16 initial_i16_list[5] = { 4181, 6765, 10946, 17711, 28657 }; + static const gint64 initial_i64_list[5] = + { + G_GINT64_CONSTANT (1100087778366101931), + G_GINT64_CONSTANT (1779979416004714189), + G_GINT64_CONSTANT (2880067194370816120), + G_GINT64_CONSTANT (4660046610375530309), + G_GINT64_CONSTANT (7540113804746346429) + }; + static const guint8 initial_base64[8] = + { + 0x56, 0x47, 0x68, 0x79, 0x61, 0x57, 0x5a, 0x30 + }; + + TTestOneOfEach *one_of_each; + gboolean im_true; + gboolean im_false; + gint a_bite; + gint integer16; + gint integer32; + gint64 integer64; + double double_precision; + gchar *some_characters; + gchar *zomg_unicode; + gboolean what_who; + GByteArray *base64; + GArray *byte_list; + GArray *i16_list; + GArray *i64_list; + + base64 = g_byte_array_new (); + g_byte_array_append (base64, initial_base64, 8); + + byte_list = g_array_new (FALSE, FALSE, sizeof (gint8)); + g_array_append_vals (byte_list, initial_byte_list, 5); + + i16_list = g_array_new (FALSE, FALSE, sizeof (gint16)); + g_array_append_vals (i16_list, initial_i16_list, 5); + + i64_list = g_array_new (FALSE, FALSE, sizeof (gint64)); + g_array_append_vals (i64_list, initial_i64_list, 5); + + /* All of OneOfEach's properties can be set at construction... */ + one_of_each = + g_object_new (T_TEST_TYPE_ONE_OF_EACH, + "im_true", TRUE, + "im_false", FALSE, + "a_bite", 0x50, + "integer16", 0x7e57, + "integer32", 0xdeadbeef, + "integer64", G_GINT64_CONSTANT (0xfa15efacade15bad), + "double_precision", M_PI, + "some_characters", "Debug THIS!", + "zomg_unicode", "\xd7\n\a\t", + "what_who", TRUE, + "base64", base64, + "byte_list", byte_list, + "i16_list", i16_list, + "i64_list", i64_list, + NULL); + g_assert (one_of_each != NULL); + + g_array_unref (i64_list); + i64_list = NULL; + g_array_unref (i16_list); + i16_list = NULL; + g_array_unref (byte_list); + byte_list = NULL; + g_byte_array_unref (base64); + base64 = NULL; + + /* ...and later retrieved */ + g_object_get (one_of_each, + "im_true", &im_true, + "im_false", &im_false, + "a_bite", &a_bite, + "integer16", &integer16, + "integer32", &integer32, + "integer64", &integer64, + "double_precision", &double_precision, + "some_characters", &some_characters, + "zomg_unicode", &zomg_unicode, + "what_who", &what_who, + "base64", &base64, + "byte_list", &byte_list, + "i16_list", &i16_list, + "i64_list", &i64_list, + NULL); + + g_assert (im_true == TRUE); + g_assert (im_false == FALSE); + + g_assert_cmphex (a_bite, ==, 0x50); + g_assert_cmphex (integer16, ==, 0x7e57); + g_assert_cmphex (integer32, ==, (gint32)0xdeadbeef); + g_assert_cmphex (integer64, ==, G_GINT64_CONSTANT (0xfa15efacade15bad)); + + g_assert_cmpfloat (double_precision, ==, M_PI); + + g_assert_cmpstr (some_characters, ==, "Debug THIS!"); + g_assert_cmpstr (zomg_unicode, ==, "\xd7\n\a\t"); + + g_assert (what_who == TRUE); + + g_assert_cmpint (base64->len, ==, 8); + g_assert_cmpint (memcmp (base64->data, + initial_base64, + 8 * sizeof (guint8)), ==, 0); + + g_assert_cmpint (byte_list->len, ==, 5); + g_assert_cmpint (memcmp (byte_list->data, + initial_byte_list, + 5 * sizeof (gint8)), ==, 0); + + g_assert_cmpint (i16_list->len, ==, 5); + g_assert_cmpint (memcmp (i16_list->data, + initial_i16_list, + 5 * sizeof (gint16)), ==, 0); + + g_assert_cmpint (i64_list->len, ==, 5); + g_assert_cmpint (memcmp (i64_list->data, + initial_i64_list, + 5 * sizeof (gint64)), ==, 0); + + g_array_unref (i64_list); + g_array_unref (i16_list); + g_array_unref (byte_list); + g_byte_array_unref (base64); + + g_object_unref (one_of_each); +} + +static void +test_structs_one_of_each_properties_byte_list (void) +{ + TTestOneOfEach *one_of_each; + GArray *byte_list = NULL; + + one_of_each = g_object_new (T_TEST_TYPE_ONE_OF_EACH, NULL); + + /* OneOfEach's "byte_list" member is a list that holds eight-bit-wide integer + values */ + g_object_get (one_of_each, "byte_list", &byte_list, NULL); + + g_assert (byte_list != NULL); + g_assert_cmpint (g_array_get_element_size (byte_list), ==, sizeof (gint8)); + + g_array_unref (byte_list); + g_object_unref (one_of_each); +} + +static void +test_structs_one_of_each_properties_i16_list (void) +{ + TTestOneOfEach *one_of_each; + GArray *i16_list = NULL; + + one_of_each = g_object_new (T_TEST_TYPE_ONE_OF_EACH, NULL); + + /* OneOfEach's "i16_list" member is a list that holds sixteen-bit-wide integer + values */ + g_object_get (one_of_each, "i16_list", &i16_list, NULL); + + g_assert (i16_list != NULL); + g_assert_cmpint (g_array_get_element_size (i16_list), ==, sizeof (gint16)); + + g_array_unref (i16_list); + g_object_unref (one_of_each); +} + +static void +test_structs_one_of_each_properties_i64_list (void) +{ + TTestOneOfEach *one_of_each; + GArray *i64_list = NULL; + + one_of_each = g_object_new (T_TEST_TYPE_ONE_OF_EACH, NULL); + + /* OneOfEach's "i64_list" member is a list that holds sixty-four-bit-wide + integer values */ + g_object_get (one_of_each, "i64_list", &i64_list, NULL); + + g_assert (i64_list != NULL); + g_assert_cmpint (g_array_get_element_size (i64_list), ==, sizeof (gint64)); + + g_array_unref (i64_list); + g_object_unref (one_of_each); +} + +static void +test_structs_nesting_create_and_destroy (void) +{ + GObject *object = NULL; + + /* A Nesting structure can be created... */ + object = g_object_new (T_TEST_TYPE_NESTING, NULL); + + g_assert (object != NULL); + g_assert (T_TEST_IS_NESTING (object)); + + /* ...and destroyed */ + g_object_unref (object); +} + +static void +test_structs_nesting_properties_my_bonk (void) +{ + TTestNesting *nesting; + TTestBonk *bonk = NULL; + gint type; + gchar *message; + + nesting = g_object_new (T_TEST_TYPE_NESTING, NULL); + + /* Nesting's "my_bonk" member is initialized with a new, default Bonk object + during construction */ + g_object_get (nesting, "my_bonk", &bonk, NULL); + + g_assert (bonk != NULL); + g_assert (T_TEST_IS_BONK (bonk)); + + g_object_get (bonk, + "type", &type, + "message", &message, + NULL); + + g_assert_cmpint (type, ==, 0); + g_assert (message == NULL); + + g_object_unref (bonk); + bonk = NULL; + + /* It can be replaced... */ + bonk = g_object_new (T_TEST_TYPE_BONK, + "type", 100, + "message", "Replacement Bonk", + NULL); + g_object_set (nesting, "my_bonk", bonk, NULL); + g_object_unref (bonk); + bonk = NULL; + + g_object_get (nesting, "my_bonk", &bonk, NULL); + + g_assert (bonk != NULL); + g_assert (T_TEST_IS_BONK (bonk)); + + g_object_get (bonk, + "type", &type, + "message", &message, + NULL); + + g_assert_cmpint (type, ==, 100); + g_assert_cmpstr (message, ==, "Replacement Bonk"); + + g_free (message); + g_object_unref (bonk); + bonk = NULL; + + /* ...or set to null */ + g_object_set (nesting, "my_bonk", NULL, NULL); + g_object_get (nesting, "my_bonk", &bonk, NULL); + + g_assert (bonk == NULL); + + g_object_unref (nesting); +} + +static void +test_structs_nesting_properties_my_ooe (void) +{ + TTestNesting *nesting; + TTestOneOfEach *one_of_each = NULL; + gint a_bite; + gint integer16; + + nesting = g_object_new (T_TEST_TYPE_NESTING, NULL); + + /* Nesting's "my_ooe" member is initialized with a new, default OneOfEach + object during construction */ + g_object_get (nesting, "my_ooe", &one_of_each, NULL); + + g_assert (one_of_each != NULL); + g_assert (T_TEST_IS_ONE_OF_EACH (one_of_each)); + + g_object_get (one_of_each, + "a_bite", &a_bite, + "integer16", &integer16, + NULL); + + g_assert_cmphex (a_bite, ==, 0x7f); + g_assert_cmphex (integer16, ==, 0x7fff); + + g_object_unref (one_of_each); + one_of_each = NULL; + + /* It can be replaced... */ + one_of_each = g_object_new (T_TEST_TYPE_ONE_OF_EACH, + "a_bite", 0x50, + "integer16", 0x5050, + NULL); + g_object_set (nesting, "my_ooe", one_of_each, NULL); + g_object_unref (one_of_each); + one_of_each = NULL; + + g_object_get (nesting, "my_ooe", &one_of_each, NULL); + + g_assert (one_of_each != NULL); + g_assert (T_TEST_IS_ONE_OF_EACH (one_of_each)); + + g_object_get (one_of_each, + "a_bite", &a_bite, + "integer16", &integer16, + NULL); + + g_assert_cmphex (a_bite, ==, 0x50); + g_assert_cmphex (integer16, ==, 0x5050); + + g_object_unref (one_of_each); + one_of_each = NULL; + + /* ...or set to null */ + g_object_set (nesting, "my_ooe", NULL, NULL); + g_object_get (nesting, "my_ooe", &one_of_each, NULL); + + g_assert (one_of_each == NULL); + + g_object_unref (nesting); +} + +static void +test_structs_holy_moley_create_and_destroy (void) +{ + GObject *object = NULL; + + /* A HolyMoley structure can be created... */ + object = g_object_new (T_TEST_TYPE_HOLY_MOLEY, NULL); + + g_assert (object != NULL); + g_assert (T_TEST_IS_HOLY_MOLEY (object)); + + /* ...and destroyed */ + g_object_unref (object); +} + +static void +test_structs_holy_moley_properties_big (void) +{ + TTestHolyMoley *holy_moley; + GPtrArray *big = NULL; + gint a_bite = 0; + gint integer16 = 0; + + holy_moley = g_object_new (T_TEST_TYPE_HOLY_MOLEY, NULL); + + /* A HolyMoley's "big" member is is initialized on construction */ + g_object_get (holy_moley, "big", &big, NULL); + + g_assert (big != NULL); + g_assert_cmpint (big->len, ==, 0); + + /* It can be modified... */ + g_ptr_array_add (big, + g_object_new (T_TEST_TYPE_ONE_OF_EACH, + "a_bite", 0x50, + "integer16", 0x5050, + NULL)); + + g_ptr_array_unref (big); + big = NULL; + + g_object_get (holy_moley, "big", &big, NULL); + + g_assert_cmpint (big->len, ==, 1); + g_object_get (g_ptr_array_index (big, 0), + "a_bite", &a_bite, + "integer16", &integer16, + NULL); + + g_assert_cmphex (a_bite, ==, 0x50); + g_assert_cmphex (integer16, ==, 0x5050); + + g_ptr_array_unref (big); + big = NULL; + + /* ...replaced... */ + big = g_ptr_array_new_with_free_func (g_object_unref); + g_ptr_array_add (big, + g_object_new (T_TEST_TYPE_ONE_OF_EACH, + "a_bite", 0x64, + "integer16", 0x1541, + NULL)); + + g_object_set (holy_moley, "big", big, NULL); + + g_ptr_array_unref (big); + big = NULL; + + g_object_get (holy_moley, "big", &big, NULL); + + g_assert_cmpint (big->len, ==, 1); + g_object_get (g_ptr_array_index (big, 0), + "a_bite", &a_bite, + "integer16", &integer16, + NULL); + + g_assert_cmphex (a_bite, ==, 0x64); + g_assert_cmphex (integer16, ==, 0x1541); + + g_ptr_array_unref (big); + big = NULL; + + /* ...or set to NULL */ + g_object_set (holy_moley, "big", NULL, NULL); + g_object_get (holy_moley, "big", &big, NULL); + + g_assert (big == NULL); + + g_object_unref (holy_moley); +} + +static void +test_structs_holy_moley_properties_contain (void) +{ + static gchar *strings[2] = { "Apache", "Thrift" }; + + TTestHolyMoley *holy_moley; + GHashTable *contain = NULL; + GPtrArray *string_list; + GList *key_list; + + holy_moley = g_object_new (T_TEST_TYPE_HOLY_MOLEY, NULL); + + /* A HolyMoley's "contain" member is initialized on construction */ + g_object_get (holy_moley, "contain", &contain, NULL); + + g_assert (contain != NULL); + g_assert_cmpint (g_hash_table_size (contain), ==, 0); + + /* It can be modified... */ + string_list = g_ptr_array_new (); + g_ptr_array_add (string_list, strings[0]); + g_ptr_array_add (string_list, strings[1]); + + g_hash_table_insert (contain, string_list, NULL); + string_list = NULL; + + g_hash_table_unref (contain); + contain = NULL; + + g_object_get (holy_moley, "contain", &contain, NULL); + + g_assert_cmpint (g_hash_table_size (contain), ==, 1); + + key_list = g_hash_table_get_keys (contain); + string_list = g_list_nth_data (key_list, 0); + + g_assert_cmpint (string_list->len, ==, 2); + g_assert_cmpstr (g_ptr_array_index (string_list, 0), ==, "Apache"); + g_assert_cmpstr (g_ptr_array_index (string_list, 1), ==, "Thrift"); + + g_list_free (key_list); + g_hash_table_unref (contain); + contain = NULL; + + /* ...replaced... */ + contain = g_hash_table_new_full (g_direct_hash, + g_direct_equal, + (GDestroyNotify) g_ptr_array_unref, + NULL); + g_object_set (holy_moley, "contain", contain, NULL); + g_hash_table_unref (contain); + contain = NULL; + + g_object_get (holy_moley, "contain", &contain, NULL); + + g_assert_cmpint (g_hash_table_size (contain), ==, 0); + + g_hash_table_unref (contain); + contain = NULL; + + /* ...or set to NULL */ + g_object_set (holy_moley, "contain", NULL, NULL); + g_object_get (holy_moley, "contain", &contain, NULL); + + g_assert (contain == NULL); + + g_object_unref (holy_moley); +} + +static void +test_structs_holy_moley_properties_bonks (void) +{ + TTestHolyMoley *holy_moley; + GHashTable *bonks = NULL; + GPtrArray *bonk_list = NULL; + TTestBonk *bonk = NULL; + gint type; + gchar *message; + GList *key_list; + + holy_moley = g_object_new (T_TEST_TYPE_HOLY_MOLEY, NULL); + + /* A HolyMoley's "bonks" member is initialized on construction */ + g_object_get (holy_moley, "bonks", &bonks, NULL); + + g_assert (bonks != NULL); + g_assert_cmpint (g_hash_table_size (bonks), ==, 0); + + /* It can be modified... */ + bonk = g_object_new (T_TEST_TYPE_BONK, + "type", 100, + "message", "Sample Bonk", + NULL); + bonk_list = g_ptr_array_new_with_free_func (g_object_unref); + g_ptr_array_add (bonk_list, bonk); + bonk = NULL; + + g_hash_table_insert (bonks, g_strdup ("Sample Bonks"), bonk_list); + bonk_list = NULL; + + g_hash_table_unref (bonks); + bonks = NULL; + + g_object_get (holy_moley, "bonks", &bonks, NULL); + + g_assert_cmpint (g_hash_table_size (bonks), ==, 1); + + key_list = g_hash_table_get_keys (bonks); + bonk_list = g_hash_table_lookup (bonks, g_list_nth_data (key_list, 0)); + + g_assert_cmpint (bonk_list->len, ==, 1); + + bonk = (g_ptr_array_index (bonk_list, 0)); + g_object_get (bonk, + "type", &type, + "message", &message, + NULL); + + g_assert_cmpint (type, ==, 100); + g_assert_cmpstr (message, ==, "Sample Bonk"); + + bonk = NULL; + g_free (message); + g_list_free (key_list); + g_hash_table_unref (bonks); + bonks = NULL; + + /* ...replaced... */ + bonks = g_hash_table_new_full (g_str_hash, + g_str_equal, + g_free, + (GDestroyNotify) g_ptr_array_unref); + g_object_set (holy_moley, "bonks", bonks, NULL); + g_hash_table_unref (bonks); + bonks = NULL; + + g_object_get (holy_moley, "bonks", &bonks, NULL); + + g_assert_cmpint (g_hash_table_size (bonks), ==, 0); + + g_hash_table_unref (bonks); + bonks = NULL; + + /* ...or set to NULL */ + g_object_set (holy_moley, "bonks", NULL, NULL); + g_object_get (holy_moley, "bonks", &bonks, NULL); + + g_assert (bonks == NULL); + + g_object_unref (holy_moley); +} + +static void +test_structs_empty (void) +{ + GObject *object = NULL; + GParamSpec **properties; + guint property_count; + + /* An Empty structure can be created */ + object = g_object_new (T_TEST_TYPE_EMPTY, NULL); + + g_assert (object != NULL); + g_assert (T_TEST_IS_EMPTY (object)); + + /* An Empty structure has no members and thus no properties */ + properties = g_object_class_list_properties (G_OBJECT_GET_CLASS (object), + &property_count); + g_assert_cmpint (property_count, ==, 0); + g_free (properties); + + /* An Empty structure can be destroyed */ + g_object_unref (object); +} + +static void +test_structs_wrapper_create_and_destroy (void) +{ + GObject *object = NULL; + + /* A Wrapper structure can be created... */ + object = g_object_new (T_TEST_TYPE_EMPTY, NULL); + + g_assert (object != NULL); + g_assert (T_TEST_IS_EMPTY (object)); + + /* ...and destroyed */ + g_object_unref (object); +} + +static void +test_structs_wrapper_properties_foo (void) { + TTestWrapper *wrapper; + TTestEmpty *foo; + + wrapper = g_object_new (T_TEST_TYPE_WRAPPER, NULL); + + /* A Wrapper structure has one member, "foo", which is an Empty + structure initialized during construction */ + g_object_get (wrapper, "foo", &foo, NULL); + + g_assert (foo != NULL); + g_assert (T_TEST_IS_EMPTY (foo)); + + g_object_unref (foo); + foo = NULL; + + /* A Wrapper's foo property can be replaced... */ + foo = g_object_new (T_TEST_TYPE_EMPTY, NULL); + g_object_set (wrapper, "foo", foo, NULL); + + g_object_unref (foo); + foo = NULL; + + g_object_get (wrapper, "foo", &foo, NULL); + g_assert (foo != NULL); + g_assert (T_TEST_IS_EMPTY (foo)); + + g_object_unref (foo); + foo = NULL; + + /* ...or set to NULL */ + g_object_set (wrapper, "foo", NULL, NULL); + g_object_get (wrapper, "foo", &foo, NULL); + + g_assert (foo == NULL); + + g_object_unref (wrapper); +} + +static void +test_services_inherited (void) +{ + ThriftProtocol *protocol; + TTestInheritedClient *inherited_client; + GObject *input_protocol, *output_protocol; + + protocol = g_object_new (THRIFT_TYPE_BINARY_PROTOCOL, NULL); + inherited_client = g_object_new (T_TEST_TYPE_INHERITED_CLIENT, + NULL); + + /* TTestInheritedClient inherits from TTestSrvClient */ + g_assert (g_type_is_a (T_TEST_TYPE_INHERITED_CLIENT, + T_TEST_TYPE_SRV_CLIENT)); + + /* TTestInheritedClient implements TTestSrvClient's interface */ + 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 */ + g_object_set (inherited_client, + "input_protocol", protocol, + "output_protocol", protocol, + NULL); + + g_object_get (inherited_client, + "input_protocol", &input_protocol, + "output_protocol", &output_protocol, + NULL); + + g_assert (input_protocol == G_OBJECT(protocol)); + g_assert (output_protocol == G_OBJECT(protocol)); + + g_object_unref (output_protocol); + g_object_unref (input_protocol); + g_object_unref (inherited_client); + g_object_unref (protocol); +} + +int +main(int argc, char *argv[]) +{ +#if (!GLIB_CHECK_VERSION (2, 36, 0)) + g_type_init (); +#endif + + g_test_init (&argc, &argv, NULL); + + g_test_add_func + ("/testdebugproto/DebugProto/Structs/Doubles/CreateAndDestroy", + test_structs_doubles_create_and_destroy); + g_test_add_func + ("/testdebugproto/DebugProto/Structs/Doubles/Initialize", + test_structs_doubles_initialize); + + g_test_add_func + ("/testdebugproto/DebugProto/Structs/OneOfEach/CreateAndDestroy", + test_structs_one_of_each_create_and_destroy); + g_test_add_func + ("/testdebugproto/DebugProto/Structs/OneOfEach/Initialize/DefaultValues", + test_structs_one_of_each_initialize_default_values); + g_test_add_func + ("/testdebugproto/DebugProto/Structs/OneOfEach/Initialize/SpecifiedValues", + test_structs_one_of_each_initialize_specified_values); + g_test_add_func + ("/testdebugproto/DebugProto/Structs/OneOfEach/Properties/byte_list", + test_structs_one_of_each_properties_byte_list); + g_test_add_func + ("/testdebugproto/DebugProto/Structs/OneOfEach/Properties/i16_list", + test_structs_one_of_each_properties_i16_list); + g_test_add_func + ("/testdebugproto/DebugProto/Structs/OneOfEach/Properties/i64_list", + test_structs_one_of_each_properties_i64_list); + + g_test_add_func + ("/testdebugproto/DebugProto/Structs/Nesting/CreateAndDestroy", + test_structs_nesting_create_and_destroy); + g_test_add_func + ("/testdebugproto/DebugProto/Structs/Nesting/Properties/my_bonk", + test_structs_nesting_properties_my_bonk); + g_test_add_func + ("/testdebugproto/DebugProto/Structs/Nesting/Properties/my_ooe", + test_structs_nesting_properties_my_ooe); + + g_test_add_func + ("/testdebugproto/DebugProto/Structs/HolyMoley/CreateAndDestroy", + test_structs_holy_moley_create_and_destroy); + g_test_add_func + ("/testdebugproto/DebugProto/Structs/HolyMoley/Properties/big", + test_structs_holy_moley_properties_big); + g_test_add_func + ("/testdebugproto/DebugProto/Structs/HolyMoley/Properties/contain", + test_structs_holy_moley_properties_contain); + g_test_add_func + ("/testdebugproto/DebugProto/Structs/HolyMoley/Properties/bonks", + test_structs_holy_moley_properties_bonks); + + g_test_add_func + ("/testdebugproto/DebugProto/Structs/Empty", + test_structs_empty); + + g_test_add_func + ("/testdebugproto/DebugProto/Structs/Wrapper/CreateAndDestroy", + test_structs_wrapper_create_and_destroy); + g_test_add_func + ("/testdebugproto/DebugProto/Structs/Wrapper/Properties/foo", + test_structs_wrapper_properties_foo); + + g_test_add_func + ("/testdebugproto/DebugProto/Services/Inherited", + test_services_inherited); + + return g_test_run (); +} diff --git a/src/jaegertracing/thrift/lib/c_glib/test/testfdtransport.c b/src/jaegertracing/thrift/lib/c_glib/test/testfdtransport.c new file mode 100755 index 000000000..1ea89be78 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/test/testfdtransport.c @@ -0,0 +1,184 @@ +/* + * 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 <fcntl.h> +#include <errno.h> +#include <unistd.h> + +#include <glib.h> +#include <glib/gstdio.h> + +#include <thrift/c_glib/transport/thrift_transport.h> +#include <thrift/c_glib/transport/thrift_fd_transport.h> + +static const gchar TEST_DATA[12] = "abcde01234!"; + +static void +test_create_and_destroy (void) +{ + GObject *object; + object = g_object_new (THRIFT_TYPE_FD_TRANSPORT, "fd", -1, NULL); + g_assert (object != NULL); + g_object_unref (object); +} + +static void +test_open_and_close (void) +{ + ThriftTransport *transport; + ThriftTransportClass *klass; + GError *error; + gint fd; + gchar *filename; + + error = NULL; + filename = NULL; + + fd = g_file_open_tmp (NULL, &filename, &error); + g_assert (fd >= 0); + + transport = THRIFT_TRANSPORT (g_object_new (THRIFT_TYPE_FD_TRANSPORT, + "fd", fd, + NULL)); + klass = THRIFT_TRANSPORT_GET_CLASS (transport); + + /* open is no-op */ + 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)); + + 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 */ + g_assert (close (fd) != 0); + g_assert (errno == EBADF); + + g_object_unref (transport); + + g_remove (filename); + g_free (filename); + + /* test bad fd */ + transport = THRIFT_TRANSPORT (g_object_new (THRIFT_TYPE_FD_TRANSPORT, + "fd", -1, + NULL)); + klass = THRIFT_TRANSPORT_GET_CLASS (transport); + + g_assert (! klass->is_open (transport)); + error = NULL; + g_assert (! klass->peek (transport, &error)); + error = NULL; + g_assert (! klass->open (transport, &error)); + error = NULL; + g_assert (! klass->close (transport, &error)); + + g_object_unref (transport); +} + +static void +test_read_and_write (void) +{ + gchar out_buf[8]; + gchar *b; + gint want, got; + ThriftTransport *transport; + ThriftTransportClass *klass; + GError *error; + gint fd; + gchar *filename; + + error = NULL; + filename = NULL; + + fd = g_file_open_tmp (NULL, &filename, &error); + g_assert (fd >= 0); + + /* write */ + transport = THRIFT_TRANSPORT (g_object_new (THRIFT_TYPE_FD_TRANSPORT, + "fd", fd, + NULL)); + klass = THRIFT_TRANSPORT_GET_CLASS (transport); + 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); + g_assert (fd >= 0); + + transport = THRIFT_TRANSPORT (g_object_new (THRIFT_TYPE_FD_TRANSPORT, + "fd", fd, + NULL)); + klass = THRIFT_TRANSPORT_GET_CLASS (transport); + + memset(out_buf, 0, 8); + b = out_buf; + want = 7; + while (want > 0) { + got = klass->read (transport, (gpointer) b, want, &error); + g_assert (got > 0 && got <= want); + b += got; + want -= got; + } + 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); + g_assert (got > 0 && got <= want); + b += got; + want -= got; + } + g_assert (memcmp (out_buf, TEST_DATA + 7, 4) == 0); + + g_assert (klass->close (transport, &error)); + g_object_unref (transport); + + /* clean up */ + + g_remove (filename); + g_free (filename); +} + +int +main (int argc, char *argv[]) +{ +#if (!GLIB_CHECK_VERSION (2, 36, 0)) + g_type_init (); +#endif + + g_test_init (&argc, &argv, NULL); + + g_test_add_func ("/testfdtransport/CreateAndDestroy", test_create_and_destroy); + g_test_add_func ("/testfdtransport/OpenAndClose", test_open_and_close); + g_test_add_func ("/testfdtransport/ReadAndWrite", test_read_and_write); + + return g_test_run (); +} diff --git a/src/jaegertracing/thrift/lib/c_glib/test/testframedtransport.c b/src/jaegertracing/thrift/lib/c_glib/test/testframedtransport.c new file mode 100755 index 000000000..008e61e40 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/test/testframedtransport.c @@ -0,0 +1,323 @@ +/* + * 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 <netdb.h> +#include <sys/wait.h> + +#include <thrift/c_glib/transport/thrift_transport.h> +#include <thrift/c_glib/transport/thrift_socket.h> +#include <thrift/c_glib/transport/thrift_server_transport.h> +#include <thrift/c_glib/transport/thrift_server_socket.h> + +#define TEST_DATA { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j' } + +#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 +test_create_and_destroy(void) +{ + ThriftTransport *transport = NULL; + guint r_buf_size = 0; + guint w_buf_size = 0; + + GObject *object = NULL; + object = g_object_new (THRIFT_TYPE_FRAMED_TRANSPORT, NULL); + g_assert (object != NULL); + g_object_get (G_OBJECT (object), "transport", &transport, + "r_buf_size", &r_buf_size, + "w_buf_size", &w_buf_size, NULL); + g_object_unref (object); +} + +static void +test_open_and_close(void) +{ + ThriftSocket *tsocket = NULL; + ThriftTransport *transport = NULL; + GError *err = NULL; + pid_t pid; + int port = 51199; + int status; + + pid = fork (); + g_assert ( pid >= 0 ); + + if ( pid == 0 ) + { + /* child listens */ + thrift_socket_server_open (port,1); + exit (0); + } else { + /* parent connects, wait a bit for the socket to be created */ + sleep (1); + /* create a ThriftSocket */ + tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost", + "port", port, NULL); + + /* create a BufferedTransport wrapper of the Socket */ + transport = g_object_new (THRIFT_TYPE_FRAMED_TRANSPORT, + "transport", THRIFT_TRANSPORT (tsocket), NULL); + + /* this shouldn't work */ + g_assert (thrift_framed_transport_open (transport, NULL) == TRUE); + g_assert (thrift_framed_transport_is_open (transport) == TRUE); + g_assert (thrift_framed_transport_close (transport, NULL) == TRUE); + g_object_unref (transport); + g_object_unref (tsocket); + + /* try and underlying socket failure */ + tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost.broken", + NULL); + + /* create a BufferedTransport wrapper of the Socket */ + transport = g_object_new (THRIFT_TYPE_FRAMED_TRANSPORT, + "transport", THRIFT_TRANSPORT (tsocket), NULL); + + g_assert (thrift_framed_transport_open (transport, &err) == FALSE); + g_object_unref (transport); + g_object_unref (tsocket); + g_error_free (err); + err = NULL; + + g_assert ( wait (&status) == pid ); + g_assert ( status == 0 ); + } +} + +static void +test_read_and_write(void) +{ + int status; + pid_t pid; + ThriftSocket *tsocket = NULL; + ThriftTransport *transport = NULL; + int port = 51199; + guchar buf[10] = TEST_DATA; /* a buffer */ + + pid = fork (); + g_assert ( pid >= 0 ); + + if ( pid == 0 ) + { + /* child listens */ + thrift_server (port); + exit (0); + } else { + /* parent connects, wait a bit for the socket to be created */ + sleep (1); + + tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost", + "port", port, NULL); + transport = g_object_new (THRIFT_TYPE_FRAMED_TRANSPORT, + "transport", THRIFT_TRANSPORT (tsocket), + "w_buf_size", 4, NULL); + + g_assert (thrift_framed_transport_open (transport, NULL) == TRUE); + g_assert (thrift_framed_transport_is_open (transport)); + + /* write 10 bytes */ + thrift_framed_transport_write (transport, buf, 10, NULL); + thrift_framed_transport_flush (transport, NULL); + + thrift_framed_transport_write (transport, buf, 1, NULL); + thrift_framed_transport_flush (transport, NULL); + + thrift_framed_transport_write (transport, buf, 10, NULL); + thrift_framed_transport_flush (transport, NULL); + + thrift_framed_transport_write (transport, buf, 10, NULL); + thrift_framed_transport_flush (transport, NULL); + + thrift_framed_transport_write_end (transport, NULL); + thrift_framed_transport_flush (transport, NULL); + thrift_framed_transport_close (transport, NULL); + + g_object_unref (transport); + g_object_unref (tsocket); + + g_assert ( wait (&status) == pid ); + g_assert ( status == 0 ); + } +} + +/* test reading from the transport after the peer has unexpectedly + closed the connection */ +static void +test_read_after_peer_close(void) +{ + int status; + pid_t pid; + int port = 51199; + GError *err = NULL; + + pid = fork (); + g_assert (pid >= 0); + + if (pid == 0) + { + ThriftServerTransport *server_transport = NULL; + ThriftTransport *client_transport = NULL; + + /* child listens */ + server_transport = g_object_new (THRIFT_TYPE_SERVER_SOCKET, + "port", port, + NULL); + g_assert (server_transport != NULL); + + thrift_server_transport_listen (server_transport, &err); + g_assert (err == NULL); + + /* wrap the client transport in a ThriftFramedTransport */ + client_transport = g_object_new + (THRIFT_TYPE_FRAMED_TRANSPORT, + "transport", thrift_server_transport_accept (server_transport, &err), + "r_buf_size", 0, + NULL); + g_assert (err == NULL); + g_assert (client_transport != NULL); + + /* close the connection immediately after the client connects */ + thrift_transport_close (client_transport, NULL); + + g_object_unref (client_transport); + g_object_unref (server_transport); + + exit (0); + } else { + ThriftSocket *tsocket = NULL; + ThriftTransport *transport = NULL; + guchar buf[10]; /* a buffer */ + + /* parent connects, wait a bit for the socket to be created */ + sleep (1); + + tsocket = g_object_new (THRIFT_TYPE_SOCKET, + "hostname", "localhost", + "port", port, + NULL); + transport = g_object_new (THRIFT_TYPE_FRAMED_TRANSPORT, + "transport", THRIFT_TRANSPORT (tsocket), + "w_buf_size", 0, + NULL); + + g_assert (thrift_transport_open (transport, NULL) == TRUE); + g_assert (thrift_transport_is_open (transport)); + + /* attempting to read from the transport after the peer has closed + the connection fails gracefully without generating a critical + warning or segmentation fault */ + thrift_transport_read (transport, buf, 10, &err); + g_assert (err != NULL); + + g_error_free (err); + err = NULL; + + thrift_transport_read_end (transport, &err); + g_assert (err == NULL); + + thrift_transport_close (transport, &err); + g_assert (err == NULL); + + g_object_unref (transport); + g_object_unref (tsocket); + + g_assert (wait (&status) == pid); + g_assert (status == 0); + } +} + +static void +thrift_socket_server_open (const int port, int times) +{ + ThriftServerTransport *transport = NULL; + ThriftTransport *client = NULL; + 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_server (const int port) +{ + int bytes = 0; + ThriftServerTransport *transport = NULL; + ThriftTransport *client = NULL; + guchar buf[12]; /* 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); + + /* 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); + g_assert (client != NULL); + + /* read 10 bytes */ + bytes = thrift_framed_transport_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 */ + + bytes = thrift_framed_transport_read (client, buf, 6, NULL); + bytes = thrift_framed_transport_read (client, buf, 5, NULL); + bytes = thrift_framed_transport_read (client, buf, 1, NULL); + + bytes = thrift_framed_transport_read (client, buf, 12, NULL); + + thrift_framed_transport_read_end (client, NULL); + thrift_framed_transport_close (client, NULL); + g_object_unref (client); + g_object_unref (tsocket); +} + +int +main(int argc, char *argv[]) +{ +#if (!GLIB_CHECK_VERSION (2, 36, 0)) + g_type_init(); +#endif + + g_test_init (&argc, &argv, NULL); + + g_test_add_func ("/testframedtransport/CreateAndDestroy", test_create_and_destroy); + g_test_add_func ("/testframedtransport/OpenAndClose", test_open_and_close); + g_test_add_func ("/testframedtransport/ReadAndWrite", test_read_and_write); + g_test_add_func ("/testframedtransport/ReadAfterPeerClose", test_read_after_peer_close); + + return g_test_run (); +} diff --git a/src/jaegertracing/thrift/lib/c_glib/test/testmemorybuffer.c b/src/jaegertracing/thrift/lib/c_glib/test/testmemorybuffer.c new file mode 100755 index 000000000..9fb68b93d --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/test/testmemorybuffer.c @@ -0,0 +1,223 @@ +/* + * 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 <netdb.h> + +#include <thrift/c_glib/transport/thrift_transport.h> +#include <thrift/c_glib/transport/thrift_socket.h> +#include <thrift/c_glib/transport/thrift_server_transport.h> +#include <thrift/c_glib/transport/thrift_server_socket.h> + +static const gchar TEST_DATA[11] = "abcdefghij"; + +#include "../src/thrift/c_glib/transport/thrift_memory_buffer.c" + +/* test object creation and destruction */ +static void +test_create_and_destroy (void) +{ + GObject *object = NULL; + object = g_object_new (THRIFT_TYPE_MEMORY_BUFFER, + "buf_size", 10, + NULL); + g_assert (object != NULL); + g_object_unref (object); +} + +static void +test_create_and_destroy_large (void) +{ + GObject *object = NULL; + object = g_object_new (THRIFT_TYPE_MEMORY_BUFFER, + "buf_size", 10 * 1024 * 1024, + NULL); + g_assert (object != NULL); + g_object_unref (object); +} + +static void +test_create_and_destroy_default (void) +{ + GObject *object = NULL; + object = g_object_new (THRIFT_TYPE_MEMORY_BUFFER, NULL); + g_assert (object != NULL); + g_object_unref (object); +} + +static void +test_create_and_destroy_external (void) +{ + GObject *object = NULL; + GByteArray *buf = g_byte_array_new (); + g_assert (buf != NULL); + object = g_object_new (THRIFT_TYPE_MEMORY_BUFFER, + "buf", buf, + NULL); + g_assert (object != NULL); + g_object_unref (object); +} + +static void +test_create_and_destroy_unowned (void) +{ + GObject *object = NULL; + GValue val = G_VALUE_INIT; + GByteArray *buf; + + object = g_object_new (THRIFT_TYPE_MEMORY_BUFFER, + "owner", FALSE, + 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); + g_assert (buf != NULL); + + g_byte_array_unref (buf); + g_value_unset (&val); + g_object_unref (object); +} + +static void +test_open_and_close (void) +{ + ThriftMemoryBuffer *tbuffer = NULL; + + /* create a ThriftMemoryBuffer */ + tbuffer = g_object_new (THRIFT_TYPE_MEMORY_BUFFER, NULL); + + /* no-ops */ + 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); +} + +static void +test_read_and_write (void) +{ + ThriftMemoryBuffer *tbuffer = NULL; + gint got, want; + gchar read[10]; + gchar *b; + GError *error = NULL; + + tbuffer = g_object_new (THRIFT_TYPE_MEMORY_BUFFER, "buf_size", 5, NULL); + g_assert (thrift_memory_buffer_write (THRIFT_TRANSPORT (tbuffer), + (gpointer) TEST_DATA, + 10, &error) == FALSE); + 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); + g_assert (thrift_memory_buffer_write (THRIFT_TRANSPORT (tbuffer), + (gpointer) TEST_DATA, 10, &error) == TRUE); + g_assert (error == NULL); + + memset(read, 0, 10); + b = read; + want = 10; + while (want > 0) { + got = thrift_memory_buffer_read (THRIFT_TRANSPORT (tbuffer), + (gpointer) b, want, &error); + g_assert (got > 0 && got <= want); + g_assert (error == NULL); + b += got; + want -= got; + } + g_assert (memcmp (read, TEST_DATA, 10) == 0); + g_object_unref (tbuffer); +} + +static void +test_read_and_write_default (void) +{ + ThriftMemoryBuffer *tbuffer = NULL; + gint got, want, i; + gchar read[10]; + gchar *b; + GError *error = NULL; + + tbuffer = g_object_new (THRIFT_TYPE_MEMORY_BUFFER, NULL); + for (i = 0; i < 100; ++i) { + g_assert (thrift_memory_buffer_write (THRIFT_TRANSPORT (tbuffer), + (gpointer) TEST_DATA, 10, &error) == TRUE); + g_assert (error == NULL); + } + + for (i = 0; i < 100; ++i) { + memset(read, 0, 10); + b = read; + want = 10; + while (want > 0) { + got = thrift_memory_buffer_read (THRIFT_TRANSPORT (tbuffer), + (gpointer) b, want, &error); + g_assert (got > 0 && got <= want); + g_assert (error == NULL); + b += got; + want -= got; + } + g_assert (memcmp (read, TEST_DATA, 10) == 0); + } + g_object_unref (tbuffer); +} + +static void +test_read_and_write_external (void) +{ + ThriftMemoryBuffer *tbuffer = NULL; + gchar *b; + GError *error = NULL; + GByteArray *buf = g_byte_array_new (); + g_assert (buf != NULL); + + tbuffer = g_object_new (THRIFT_TYPE_MEMORY_BUFFER, "buf", buf, NULL); + g_assert (thrift_memory_buffer_write (THRIFT_TRANSPORT (tbuffer), + (gpointer) TEST_DATA, 10, &error) == TRUE); + g_assert (error == NULL); + + g_assert (memcmp (buf->data, TEST_DATA, 10) == 0); + g_object_unref (tbuffer); +} + +int +main(int argc, char *argv[]) +{ +#if (!GLIB_CHECK_VERSION (2, 36, 0)) + g_type_init (); +#endif + + g_test_init (&argc, &argv, NULL); + + g_test_add_func ("/testmemorybuffer/CreateAndDestroy", test_create_and_destroy); + g_test_add_func ("/testmemorybuffer/CreateAndDestroyLarge", test_create_and_destroy_large); + g_test_add_func ("/testmemorybuffer/CreateAndDestroyUnlimited", test_create_and_destroy_default); + g_test_add_func ("/testmemorybuffer/CreateAndDestroyExternal", test_create_and_destroy_external); + g_test_add_func ("/testmemorybuffer/CreateAndDestroyUnowned", test_create_and_destroy_unowned); + g_test_add_func ("/testmemorybuffer/OpenAndClose", test_open_and_close); + g_test_add_func ("/testmemorybuffer/ReadAndWrite", test_read_and_write); + g_test_add_func ("/testmemorybuffer/ReadAndWriteUnlimited", test_read_and_write_default); + g_test_add_func ("/testmemorybuffer/ReadAndWriteExternal", test_read_and_write_external); + + return g_test_run (); +} diff --git a/src/jaegertracing/thrift/lib/c_glib/test/testoptionalrequired.c b/src/jaegertracing/thrift/lib/c_glib/test/testoptionalrequired.c new file mode 100755 index 000000000..636c36d69 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/test/testoptionalrequired.c @@ -0,0 +1,227 @@ +/* + * 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 <glib.h> + +#include <thrift/c_glib/thrift_struct.h> +#include <thrift/c_glib/protocol/thrift_protocol.h> +#include <thrift/c_glib/protocol/thrift_binary_protocol.h> +#include <thrift/c_glib/transport/thrift_memory_buffer.h> +#include "gen-c_glib/t_test_optional_required_test_types.h" + +#include "gen-c_glib/t_test_optional_required_test_types.c" + +static void +write_to_read (ThriftStruct *w, ThriftStruct *r, GError **write_error, + GError **read_error) +{ + ThriftMemoryBuffer *tbuffer = NULL; + ThriftProtocol *protocol = NULL; + + tbuffer = g_object_new (THRIFT_TYPE_MEMORY_BUFFER, NULL); + protocol = g_object_new (THRIFT_TYPE_BINARY_PROTOCOL, "transport", + tbuffer, NULL); + + thrift_struct_write (w, protocol, write_error); + thrift_struct_read (r, protocol, read_error); + + g_object_unref (protocol); + g_object_unref (tbuffer); +} + +static void +test_old_school1 (void) +{ + TTestOldSchool *o = NULL; + + o = g_object_new (T_TEST_TYPE_OLD_SCHOOL, NULL); + o->im_int = 10; + o->im_str = g_strdup ("test"); + o->im_big = g_ptr_array_new (); + g_ptr_array_free (o->im_big, TRUE); + o->im_big = NULL; + g_free (o->im_str); + o->im_str = NULL; + g_object_unref (o); +} + +/** + * Write to read with optional fields + */ +static void +test_simple (void) +{ + TTestSimple *s1 = NULL, *s2 = NULL, *s3 = NULL; + + s1 = g_object_new (T_TEST_TYPE_SIMPLE, NULL); + s2 = g_object_new (T_TEST_TYPE_SIMPLE, NULL); + s3 = g_object_new (T_TEST_TYPE_SIMPLE, NULL); + + /* write-to-read with optional fields */ + s1->im_optional = 10; + 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); + 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); + 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); +} + +/** + * Writing between optional and default + */ +static void +test_tricky1 (void) +{ + TTestTricky1 *t1 = NULL; + TTestTricky2 *t2 = NULL; + + t1 = g_object_new (T_TEST_TYPE_TRICKY1, NULL); + t2 = g_object_new (T_TEST_TYPE_TRICKY2, NULL); + + t2->im_optional = 10; + write_to_read (THRIFT_STRUCT (t2), THRIFT_STRUCT (t1), NULL, NULL); + write_to_read (THRIFT_STRUCT (t1), THRIFT_STRUCT (t2), NULL, NULL); + + 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); +} + +/** + * Writing between default and required. + */ +static void +test_tricky2 (void) +{ + TTestTricky1 *t1 = NULL; + TTestTricky3 *t3 = NULL; + + t1 = g_object_new (T_TEST_TYPE_TRICKY1, NULL); + t3 = g_object_new (T_TEST_TYPE_TRICKY3, NULL); + + write_to_read (THRIFT_STRUCT (t1), THRIFT_STRUCT (t3), NULL, NULL); + write_to_read (THRIFT_STRUCT (t3), THRIFT_STRUCT (t1), NULL, NULL); + + g_assert (t1->__isset_im_default == TRUE); + + g_object_unref (t1); + g_object_unref (t3); +} + +/** + * Writing between optional and required. + */ +static void +test_tricky3 (void) +{ + TTestTricky2 *t2 = NULL; + TTestTricky3 *t3 = NULL; + + t2 = g_object_new (T_TEST_TYPE_TRICKY2, NULL); + t3 = g_object_new (T_TEST_TYPE_TRICKY3, NULL); + + t2->__isset_im_optional = TRUE; + + write_to_read (THRIFT_STRUCT (t2), THRIFT_STRUCT (t3), NULL, NULL); + write_to_read (THRIFT_STRUCT (t3), THRIFT_STRUCT (t2), NULL, NULL); + + g_object_unref (t2); + g_object_unref (t3); +} + +/** + * Catch an optional not set exception. To quote the + * C++ test, "Mu-hu-ha-ha-ha!" + */ +static void +test_tricky4 (void) +{ + TTestTricky2 *t2 = NULL; + TTestTricky3 *t3 = NULL; + GError *read_error = NULL; + + t2 = g_object_new (T_TEST_TYPE_TRICKY2, NULL); + t3 = g_object_new (T_TEST_TYPE_TRICKY3, NULL); + + /* throws protocol exception */ + write_to_read (THRIFT_STRUCT (t2), THRIFT_STRUCT (t3), NULL, &read_error); + g_assert (read_error != NULL); + g_error_free (read_error); + + write_to_read (THRIFT_STRUCT (t3), THRIFT_STRUCT (t2), NULL, NULL); + + g_assert (t2->__isset_im_optional); + + g_object_unref (t2); + g_object_unref (t3); +} + +static void +test_non_set_binary (void) +{ + TTestBinaries *b1 = NULL; + TTestBinaries *b2 = NULL; + GError *error = NULL; + + b1 = g_object_new (T_TEST_TYPE_BINARIES, NULL); + b2 = g_object_new (T_TEST_TYPE_BINARIES, NULL); + + write_to_read (THRIFT_STRUCT (b1), THRIFT_STRUCT (b2), NULL, &error); + g_assert(!error); + write_to_read (THRIFT_STRUCT (b2), THRIFT_STRUCT (b1), NULL, &error); + g_assert(!error); + /* OK. No segfault */ + + g_object_unref (b1); + g_object_unref (b2); +} + +int +main(int argc, char *argv[]) +{ +#if (!GLIB_CHECK_VERSION (2, 36, 0)) + g_type_init(); +#endif + + g_test_init (&argc, &argv, NULL); + + g_test_add_func ("/testoptionalrequired/OldSchool", test_old_school1); + g_test_add_func ("/testoptionalrequired/Simple", test_simple); + g_test_add_func ("/testoptionalrequired/Tricky1", test_tricky1); + g_test_add_func ("/testoptionalrequired/Tricky2", test_tricky2); + g_test_add_func ("/testoptionalrequired/Tricky3", test_tricky3); + g_test_add_func ("/testoptionalrequired/Tricky4", test_tricky4); + g_test_add_func ("/testoptionalrequired/Binary", test_non_set_binary); + + return g_test_run (); +} diff --git a/src/jaegertracing/thrift/lib/c_glib/test/testserialization.c b/src/jaegertracing/thrift/lib/c_glib/test/testserialization.c new file mode 100644 index 000000000..67d411de1 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/test/testserialization.c @@ -0,0 +1,95 @@ +#include <thrift/c_glib/protocol/thrift_binary_protocol.h> +#include <thrift/c_glib/protocol/thrift_protocol.h> +#include <thrift/c_glib/transport/thrift_memory_buffer.h> +#include <thrift/c_glib/transport/thrift_transport.h> +#include "gen-c_glib/t_test_debug_proto_test_types.h" +#include "gen-c_glib/t_test_enum_test_types.h" + +static void enum_constants_read_write() { + GError* error = NULL; + ThriftTransport* transport + = THRIFT_TRANSPORT(g_object_new(THRIFT_TYPE_MEMORY_BUFFER, "buf_size", 1024, NULL)); + ThriftProtocol* protocol + = THRIFT_PROTOCOL(g_object_new(THRIFT_TYPE_BINARY_PROTOCOL, "transport", transport, NULL)); + TTestEnumTestStruct* src = T_TEST_ENUM_TEST; + TTestEnumTestStruct* dst = g_object_new(T_TEST_TYPE_ENUM_TEST_STRUCT, NULL); + TTestEnumTestStructClass* cls = T_TEST_ENUM_TEST_STRUCT_GET_CLASS(src); + int write_len; + int read_len; + + write_len = THRIFT_STRUCT_CLASS(cls)->write(THRIFT_STRUCT(src), protocol, &error); + g_assert(!error); + g_assert(write_len > 0); + + read_len = THRIFT_STRUCT_CLASS(cls)->read(THRIFT_STRUCT(dst), protocol, &error); + g_assert(!error); + g_assert_cmpint(write_len, ==, read_len); + + g_object_unref(dst); + g_object_unref(protocol); + g_object_unref(transport); +} + +static void struct_constants_read_write() { + GError* error = NULL; + ThriftTransport* transport + = THRIFT_TRANSPORT(g_object_new(THRIFT_TYPE_MEMORY_BUFFER, "buf_size", 4096, NULL)); + ThriftProtocol* protocol + = THRIFT_PROTOCOL(g_object_new(THRIFT_TYPE_BINARY_PROTOCOL, "transport", transport, NULL)); + TTestCompactProtoTestStruct* src = T_TEST_COMPACT_TEST; + TTestCompactProtoTestStruct* dst = g_object_new(T_TEST_TYPE_COMPACT_PROTO_TEST_STRUCT, NULL); + TTestCompactProtoTestStructClass* cls = T_TEST_COMPACT_PROTO_TEST_STRUCT_GET_CLASS(src); + int write_len; + int read_len; + + write_len = THRIFT_STRUCT_CLASS(cls)->write(THRIFT_STRUCT(src), protocol, &error); + g_assert(!error); + g_assert(write_len > 0); + + read_len = THRIFT_STRUCT_CLASS(cls)->read(THRIFT_STRUCT(dst), protocol, &error); + g_assert(!error); + g_assert_cmpint(write_len, ==, read_len); + + g_object_unref(dst); + g_object_unref(protocol); + g_object_unref(transport); +} + +static void struct_read_write_length_should_equal() { + GError* error = NULL; + ThriftTransport* transport + = THRIFT_TRANSPORT(g_object_new(THRIFT_TYPE_MEMORY_BUFFER, "buf_size", 2048, NULL)); + ThriftProtocol* protocol + = THRIFT_PROTOCOL(g_object_new(THRIFT_TYPE_BINARY_PROTOCOL, "transport", transport, NULL)); + TTestBonk* src = g_object_new(T_TEST_TYPE_BONK, NULL); + TTestBonk* dst = g_object_new(T_TEST_TYPE_BONK, NULL); + TTestBonkClass* cls = T_TEST_BONK_GET_CLASS(src); + int write_len; + int read_len; + + write_len = THRIFT_STRUCT_CLASS(cls)->write(THRIFT_STRUCT(src), protocol, &error); + g_assert(!error); + g_assert(write_len > 0); + + read_len = THRIFT_STRUCT_CLASS(cls)->read(THRIFT_STRUCT(dst), protocol, &error); + g_assert(!error); + g_assert_cmpint(write_len, ==, read_len); + + g_object_unref(dst); + g_object_unref(src); + g_object_unref(protocol); + g_object_unref(transport); +} + +int main(int argc, char* argv[]) { +#if (!GLIB_CHECK_VERSION(2, 36, 0)) + g_type_init(); +#endif + g_test_init(&argc, &argv, NULL); + + g_test_add_func("/testserialization/StructReadWriteLengthShouldEqual", + struct_read_write_length_should_equal); + g_test_add_func("/testserialization/StructConstants", struct_constants_read_write); + g_test_add_func("/testserialization/EnumConstants", enum_constants_read_write); + return g_test_run(); +} diff --git a/src/jaegertracing/thrift/lib/c_glib/test/testsimpleserver.c b/src/jaegertracing/thrift/lib/c_glib/test/testsimpleserver.c new file mode 100755 index 000000000..3c6f2e80d --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/test/testsimpleserver.c @@ -0,0 +1,122 @@ +/* + * 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 <glib.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/wait.h> + +#include <thrift/c_glib/thrift.h> +#include <thrift/c_glib/processor/thrift_processor.h> +#include <thrift/c_glib/transport/thrift_server_socket.h> + +#define TEST_PORT 51199 + +#include <thrift/c_glib/server/thrift_simple_server.c> + +/* create a rudimentary processor */ +#define TEST_PROCESSOR_TYPE (test_processor_get_type ()) + +struct _TestProcessor +{ + ThriftProcessor parent; +}; +typedef struct _TestProcessor TestProcessor; + +struct _TestProcessorClass +{ + ThriftProcessorClass parent; +}; +typedef struct _TestProcessorClass TestProcessorClass; + +G_DEFINE_TYPE(TestProcessor, test_processor, THRIFT_TYPE_PROCESSOR) + +gboolean +test_processor_process (ThriftProcessor *processor, ThriftProtocol *in, + ThriftProtocol *out, GError **error) +{ + THRIFT_UNUSED_VAR (processor); + THRIFT_UNUSED_VAR (in); + THRIFT_UNUSED_VAR (out); + THRIFT_UNUSED_VAR (error); + + return FALSE; +} + +static void +test_processor_init (TestProcessor *p) +{ + THRIFT_UNUSED_VAR (p); +} + +static void +test_processor_class_init (TestProcessorClass *proc) +{ + (THRIFT_PROCESSOR_CLASS(proc))->process = test_processor_process; +} + +static void +test_server (void) +{ + int status; + pid_t pid; + TestProcessor *p = NULL; + ThriftServerSocket *tss = NULL; + ThriftSimpleServer *ss = NULL; + + p = g_object_new (TEST_PROCESSOR_TYPE, NULL); + tss = g_object_new (THRIFT_TYPE_SERVER_SOCKET, "port", TEST_PORT, NULL); + ss = g_object_new (THRIFT_TYPE_SIMPLE_SERVER, "processor", p, + "server_transport", THRIFT_SERVER_TRANSPORT (tss), NULL); + + /* run the server in a child process */ + pid = fork (); + g_assert (pid >= 0); + + if (pid == 0) + { + THRIFT_SERVER_GET_CLASS (THRIFT_SERVER (ss))->serve (THRIFT_SERVER (ss), + NULL); + exit (0); + } else { + sleep (5); + kill (pid, SIGINT); + + g_object_unref (ss); + g_object_unref (tss); + g_object_unref (p); + g_assert (wait (&status) == pid); + g_assert (status == SIGINT); + } +} + +int +main(int argc, char *argv[]) +{ +#if (!GLIB_CHECK_VERSION (2, 36, 0)) + g_type_init(); +#endif + + g_test_init (&argc, &argv, NULL); + + g_test_add_func ("/testsimpleserver/SimpleServer", test_server); + + return g_test_run (); +} diff --git a/src/jaegertracing/thrift/lib/c_glib/test/teststruct.c b/src/jaegertracing/thrift/lib/c_glib/test/teststruct.c new file mode 100755 index 000000000..d120cbcfa --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/test/teststruct.c @@ -0,0 +1,111 @@ +/* + * 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 <glib-object.h> + +#include "../src/thrift/c_glib/thrift_struct.c" + +/* tests to ensure we can extend a ThriftStruct */ + +struct _ThriftTestStruct +{ + ThriftStruct parent; +}; +typedef struct _ThriftTestStruct ThriftTestStruct; + +struct _ThriftTestStructClass +{ + ThriftStructClass parent; +}; +typedef struct _ThriftTestStructClass ThriftTestStructClass; + +GType thrift_test_struct_get_type (void); + +#define THRIFT_TYPE_TEST_STRUCT (thrift_test_struct_get_type ()) +#define THRIFT_TEST_STRUCT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THRIFT_TYPE_TEST_STRUCT, ThriftTestStruct)) +#define THRIFT_TEST_STRUCT_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), THRIFT_TYPE_TEST_STRUCT, ThriftTestStructClass)) +#define THRIFT_IS_TEST_STRUCT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THRIFT_TYPE_TEST_STRUCT)) +#define THRIFT_IS_TEST_STRUCT_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), THRIFT_TYPE_TEST_STRUCT)) +#define THRIFT_TEST_STRUCT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THRIFT_TYPE_TEST_STRUCT, ThriftTestStructClass)) + +G_DEFINE_TYPE(ThriftTestStruct, thrift_test_struct, THRIFT_TYPE_STRUCT) + +gint32 +thrift_test_struct_read (ThriftStruct *object, ThriftProtocol *protocol, + GError **error) +{ + THRIFT_UNUSED_VAR (object); + THRIFT_UNUSED_VAR (protocol); + THRIFT_UNUSED_VAR (error); + + return 0; +} + +gint32 +thrift_test_struct_write (ThriftStruct *object, ThriftProtocol *protocol, + GError **error) +{ + THRIFT_UNUSED_VAR (object); + THRIFT_UNUSED_VAR (protocol); + THRIFT_UNUSED_VAR (error); + + return 0; +} + +static void +thrift_test_struct_class_init (ThriftTestStructClass *cls) +{ + ThriftStructClass *ts_cls = THRIFT_STRUCT_CLASS (cls); + ts_cls->read = thrift_test_struct_read; + ts_cls->write = thrift_test_struct_write; +} + +static void +thrift_test_struct_init (ThriftTestStruct *s) +{ + THRIFT_UNUSED_VAR (s); +} + +static void +test_initialize_object (void) +{ + ThriftTestStruct *t = NULL; + + t = g_object_new (THRIFT_TYPE_TEST_STRUCT, NULL); + 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); + thrift_test_struct_write (THRIFT_STRUCT (t), NULL, NULL); + g_object_unref (t); +} + +int +main(int argc, char *argv[]) +{ +#if (!GLIB_CHECK_VERSION (2, 36, 0)) + g_type_init(); +#endif + + g_test_init (&argc, &argv, NULL); + + g_test_add_func ("/teststruct/InitializeObject", test_initialize_object); + + return g_test_run (); +} diff --git a/src/jaegertracing/thrift/lib/c_glib/test/testthrifttest.c b/src/jaegertracing/thrift/lib/c_glib/test/testthrifttest.c new file mode 100755 index 000000000..23a934db9 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/test/testthrifttest.c @@ -0,0 +1,112 @@ +#include <netdb.h> + +#include <thrift/c_glib/thrift.h> +#include <thrift/c_glib/transport/thrift_server_transport.h> +#include <thrift/c_glib/transport/thrift_server_socket.h> + +#include "t_test_thrift_test_types.h" +#include "thrift_test_handler.h" + +static const char TEST_ADDRESS[] = "localhost"; +static const int TEST_PORT = 64444; + +static void +test_thrift_server (void) +{ + ThriftServerSocket *tsocket = g_object_new (THRIFT_TYPE_SERVER_SOCKET, + "port", TEST_PORT, NULL); + + g_object_unref (tsocket); +} + +static void +set_indicator (gpointer data, GObject *where_the_object_was) { + THRIFT_UNUSED_VAR(where_the_object_was); + + *(gboolean *) data = TRUE; +} + +static void +test_thrift_handler (void) +{ + GError *error; + GHashTable *_return; + TTestInsanity *argument; + gboolean indicator; + + TTestXtruct *xtruct, *xtruct2; + TTestNumberz numberz; + TTestNumberz numberz2; + TTestUserId user_id, *user_id_ptr, *user_id_ptr2; + GHashTable *user_map; + GPtrArray *xtructs; + + error = NULL; + indicator = FALSE; + + user_map = NULL; + xtructs = NULL; + + argument = g_object_new (T_TEST_TYPE_INSANITY, NULL); + g_object_get (argument, + "userMap", &user_map, + "xtructs", &xtructs, + NULL); + + numberz = T_TEST_NUMBERZ_FIVE; + numberz2 = T_TEST_NUMBERZ_EIGHT; + user_id_ptr = g_malloc (sizeof *user_id_ptr); + *user_id_ptr = 5; + user_id_ptr2 = g_malloc (sizeof *user_id_ptr); + *user_id_ptr2 = 8; + g_hash_table_insert (user_map, (gpointer)numberz, user_id_ptr); + g_hash_table_insert (user_map, (gpointer)numberz2, user_id_ptr2); + g_hash_table_unref (user_map); + + xtruct = g_object_new (T_TEST_TYPE_XTRUCT, + "string_thing", "Hello2", + "byte_thing", 2, + "i32_thing", 2, + "i64_thing", 2LL, + NULL); + xtruct2 = g_object_new (T_TEST_TYPE_XTRUCT, + "string_thing", "Goodbye4", + "byte_thing", 4, + "i32_thing", 4, + "i64_thing", 4LL, + NULL); + g_ptr_array_add (xtructs, xtruct2); + g_ptr_array_add (xtructs, xtruct); + g_ptr_array_unref (xtructs); + + _return = g_hash_table_new_full (g_int64_hash, + g_int64_equal, + g_free, + (GDestroyNotify)g_hash_table_unref); + + g_object_weak_ref (G_OBJECT (argument), set_indicator, (gpointer) &indicator); + + g_assert (thrift_test_handler_test_insanity (NULL, &_return, argument, &error)); + g_assert (! indicator); + + g_hash_table_unref (_return); + g_assert (! indicator); + + g_object_unref (argument); + g_assert (indicator); +} + +int +main(int argc, char *argv[]) +{ +#if (!GLIB_CHECK_VERSION (2, 36, 0)) + g_type_init(); +#endif + + g_test_init (&argc, &argv, NULL); + + g_test_add_func ("/testthrift/Server", test_thrift_server); + g_test_add_func ("/testthrift/Handler", test_thrift_handler); + + return g_test_run (); +} diff --git a/src/jaegertracing/thrift/lib/c_glib/test/testthrifttestclient.cpp b/src/jaegertracing/thrift/lib/c_glib/test/testthrifttestclient.cpp new file mode 100644 index 000000000..20fbcdb03 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/test/testthrifttestclient.cpp @@ -0,0 +1,639 @@ +/* + * 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. + */ + +/* test a C client with a C++ server (that makes sense...) */ + +#include <signal.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <thrift/protocol/TBinaryProtocol.h> +#include <thrift/protocol/TDebugProtocol.h> +#include <thrift/server/TSimpleServer.h> +#include <memory> +#include <thrift/transport/TServerSocket.h> +#include "ThriftTest.h" +#include "ThriftTest_types.h" + +#include <iostream> +#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::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 +namespace thrift { namespace test { + +bool Insanity::operator<(thrift::test::Insanity const& other) const { + using apache::thrift::ThriftDebugString; + return ThriftDebugString(*this) < ThriftDebugString(other); +} + +}} + +class TestHandler : public ThriftTestIf { + public: + TestHandler() = default; + + void testVoid() override { + cout << "[C -> C++] testVoid()" << endl; + } + + void testString(string& out, const string &thing) override { + cout << "[C -> C++] testString(\"" << thing << "\")" << endl; + out = thing; + } + + bool testBool(const bool thing) override { + cout << "[C -> C++] testBool(" << (thing ? "true" : "false") << ")" << endl; + return thing; + } + int8_t testByte(const int8_t thing) override { + cout << "[C -> C++] testByte(" << (int)thing << ")" << endl; + return thing; + } + int32_t testI32(const int32_t thing) override { + cout << "[C -> C++] testI32(" << thing << ")" << endl; + return thing; + } + + int64_t testI64(const int64_t thing) override { + cout << "[C -> C++] testI64(" << thing << ")" << endl; + return thing; + } + + double testDouble(const double thing) override { + cout.precision(6); + cout << "[C -> C++] testDouble(" << fixed << thing << ")" << endl; + return thing; + } + + void testBinary(string& out, const string &thing) override { + cout << "[C -> C++] testBinary(\"" << thing << "\")" << endl; + out = thing; + } + + void testStruct(Xtruct& out, const Xtruct &thing) override { + cout << "[C -> C++] testStruct({\"" << thing.string_thing << "\", " << (int)thing.byte_thing << ", " << thing.i32_thing << ", " << thing.i64_thing << "})" << endl; + out = thing; + } + + void testNest(Xtruct2& out, const Xtruct2& nest) override { + const Xtruct &thing = nest.struct_thing; + cout << "[C -> C++] testNest({" << (int)nest.byte_thing << ", {\"" << thing.string_thing << "\", " << (int)thing.byte_thing << ", " << thing.i32_thing << ", " << thing.i64_thing << "}, " << nest.i32_thing << "})" << endl; + out = nest; + } + + void testMap(map<int32_t, int32_t> &out, const map<int32_t, int32_t> &thing) override { + cout << "[C -> C++] testMap({"; + map<int32_t, int32_t>::const_iterator m_iter; + bool first = true; + for (m_iter = thing.begin(); m_iter != thing.end(); ++m_iter) { + if (first) { + first = false; + } else { + cout << ", "; + } + cout << m_iter->first << " => " << m_iter->second; + } + cout << "})" << endl; + out = thing; + } + + void testStringMap(map<std::string, std::string> &out, const map<std::string, std::string> &thing) override { + cout << "[C -> C++] testStringMap({"; + map<std::string, std::string>::const_iterator m_iter; + bool first = true; + for (m_iter = thing.begin(); m_iter != thing.end(); ++m_iter) { + if (first) { + first = false; + } else { + cout << ", "; + } + cout << "\"" << m_iter->first << "\" => \"" << m_iter->second << "\""; + } + cout << "})" << endl; + out = thing; + } + + + void testSet(set<int32_t> &out, const set<int32_t> &thing) override { + cout << "[C -> C++] testSet({"; + set<int32_t>::const_iterator s_iter; + bool first = true; + for (s_iter = thing.begin(); s_iter != thing.end(); ++s_iter) { + if (first) { + first = false; + } else { + cout << ", "; + } + cout << *s_iter; + } + cout << "})" << endl; + out = thing; + } + + void testList(vector<int32_t> &out, const vector<int32_t> &thing) override { + cout << "[C -> C++] testList({"; + vector<int32_t>::const_iterator l_iter; + bool first = true; + for (l_iter = thing.begin(); l_iter != thing.end(); ++l_iter) { + if (first) { + first = false; + } else { + cout << ", "; + } + cout << *l_iter; + } + cout << "})" << endl; + out = thing; + } + + Numberz::type testEnum(const Numberz::type thing) override { + cout << "[C -> C++] testEnum(" << thing << ")" << endl; + return thing; + } + + UserId testTypedef(const UserId thing) override { + cout << "[C -> C++] testTypedef(" << thing << ")" << endl; + return thing; } + + void testMapMap(map<int32_t, map<int32_t,int32_t> > &mapmap, const int32_t hello) override { + cout << "[C -> C++] testMapMap(" << hello << ")" << endl; + + map<int32_t,int32_t> pos; + map<int32_t,int32_t> neg; + for (int i = 1; i < 5; i++) { + pos.insert(make_pair(i,i)); + neg.insert(make_pair(-i,-i)); + } + + mapmap.insert(make_pair(4, pos)); + mapmap.insert(make_pair(-4, neg)); + + } + + void testInsanity(map<UserId, map<Numberz::type,Insanity> > &insane, const Insanity &argument) override { + THRIFT_UNUSED_VARIABLE (argument); + + cout << "[C -> C++] testInsanity()" << endl; + + Xtruct hello; + hello.string_thing = "Hello2"; + hello.byte_thing = 2; + hello.i32_thing = 2; + hello.i64_thing = 2; + + Xtruct goodbye; + goodbye.string_thing = "Goodbye4"; + goodbye.byte_thing = 4; + goodbye.i32_thing = 4; + goodbye.i64_thing = 4; + + Insanity crazy; + crazy.userMap.insert(make_pair(Numberz::EIGHT, 8)); + crazy.xtructs.push_back(goodbye); + + Insanity looney; + crazy.userMap.insert(make_pair(Numberz::FIVE, 5)); + crazy.xtructs.push_back(hello); + + map<Numberz::type, Insanity> first_map; + map<Numberz::type, Insanity> second_map; + + first_map.insert(make_pair(Numberz::TWO, crazy)); + first_map.insert(make_pair(Numberz::THREE, crazy)); + + second_map.insert(make_pair(Numberz::SIX, looney)); + + insane.insert(make_pair(1, first_map)); + insane.insert(make_pair(2, second_map)); + + cout << "return = {"; + map<UserId, map<Numberz::type,Insanity> >::const_iterator i_iter; + for (i_iter = insane.begin(); i_iter != insane.end(); ++i_iter) { + cout << i_iter->first << " => {"; + map<Numberz::type,Insanity>::const_iterator i2_iter; + for (i2_iter = i_iter->second.begin(); + i2_iter != i_iter->second.end(); + ++i2_iter) { + cout << i2_iter->first << " => {"; + map<Numberz::type, UserId> userMap = i2_iter->second.userMap; + map<Numberz::type, UserId>::const_iterator um; + cout << "{"; + for (um = userMap.begin(); um != userMap.end(); ++um) { + cout << um->first << " => " << um->second << ", "; + } + cout << "}, "; + + vector<Xtruct> xtructs = i2_iter->second.xtructs; + vector<Xtruct>::const_iterator x; + cout << "{"; + for (x = xtructs.begin(); x != xtructs.end(); ++x) { + cout << "{\"" << x->string_thing << "\", " << (int)x->byte_thing << ", " << x->i32_thing << ", " << x->i64_thing << "}, "; + } + cout << "}"; + + cout << "}, "; + } + cout << "}, "; + } + cout << "}" << endl; + + + } + + void testMulti(Xtruct &hello, const int8_t arg0, const int32_t arg1, const int64_t arg2, const std::map<int16_t, std::string> &arg3, const Numberz::type arg4, const UserId arg5) override { + THRIFT_UNUSED_VARIABLE (arg3); + THRIFT_UNUSED_VARIABLE (arg4); + THRIFT_UNUSED_VARIABLE (arg5); + + cout << "[C -> C++] testMulti()" << endl; + + hello.string_thing = "Hello2"; + hello.byte_thing = arg0; + hello.i32_thing = arg1; + hello.i64_thing = (int64_t)arg2; + } + + void testException(const std::string &arg) + throw(Xception, apache::thrift::TException) override + { + cout << "[C -> C++] testException(" << arg << ")" << endl; + if (arg.compare("Xception") == 0) { + Xception e; + e.errorCode = 1001; + e.message = arg; + throw e; + } else if (arg.compare("ApplicationException") == 0) { + apache::thrift::TException e; + throw e; + } else { + Xtruct result; + result.string_thing = arg; + return; + } + } + + void testMultiException(Xtruct &result, const std::string &arg0, const std::string &arg1) throw(Xception, Xception2) override { + + cout << "[C -> C++] testMultiException(" << arg0 << ", " << arg1 << ")" << endl; + + if (arg0.compare("Xception") == 0) { + Xception e; + e.errorCode = 1001; + e.message = "This is an Xception"; + throw e; + } else if (arg0.compare("Xception2") == 0) { + Xception2 e; + e.errorCode = 2002; + e.struct_thing.string_thing = "This is an Xception2"; + throw e; + } else { + result.string_thing = arg1; + return; + } + } + + void testOneway(int sleepFor) override { + cout << "testOneway(" << sleepFor << "): Sleeping..." << endl; + sleep(sleepFor); + cout << "testOneway(" << sleepFor << "): done sleeping!" << endl; + } +}; + +// C CLIENT +extern "C" { + +#undef THRIFT_SOCKET /* from lib/cpp */ + +#include "t_test_thrift_test.h" +#include "t_test_thrift_test_types.h" +#include <thrift/c_glib/transport/thrift_socket.h> +#include <thrift/c_glib/protocol/thrift_protocol.h> +#include <thrift/c_glib/protocol/thrift_binary_protocol.h> + +static void +test_thrift_client (void) +{ + ThriftSocket *tsocket = nullptr; + ThriftBinaryProtocol *protocol = nullptr; + TTestThriftTestClient *client = nullptr; + TTestThriftTestIf *iface = nullptr; + GError *error = nullptr; + gchar *string = nullptr; + gint8 byte = 0; + gint16 i16 = 0; + gint32 i32 = 0, another_i32 = 56789; + gint64 i64 = 0; + double dbl = 0.0; + TTestXtruct *xtruct_in, *xtruct_out; + TTestXtruct2 *xtruct2_in, *xtruct2_out; + GHashTable *map_in = nullptr, *map_out = nullptr; + GHashTable *set_in = nullptr, *set_out = nullptr; + GArray *list_in = nullptr, *list_out = nullptr; + TTestNumberz enum_in, enum_out; + TTestUserId user_id_in, user_id_out; + GHashTable *insanity_in = nullptr; + TTestXtruct *xtruct1, *xtruct2; + TTestInsanity *insanity_out = nullptr; + TTestXtruct *multi_in = nullptr; + GHashTable *multi_map_out = nullptr; + TTestXception *xception = nullptr; + TTestXception2 *xception2 = nullptr; + +#if (!GLIB_CHECK_VERSION (2, 36, 0)) + // initialize gobject + g_type_init (); +#endif + + // create a C client + tsocket = (ThriftSocket *) g_object_new (THRIFT_TYPE_SOCKET, + "hostname", "localhost", + "port", TEST_PORT, NULL); + protocol = (ThriftBinaryProtocol *) g_object_new (THRIFT_TYPE_BINARY_PROTOCOL, + "transport", + tsocket, NULL); + client = (TTestThriftTestClient *) g_object_new (T_TEST_TYPE_THRIFT_TEST_CLIENT, "input_protocol", protocol, "output_protocol", protocol, NULL); + iface = T_TEST_THRIFT_TEST_IF (client); + + // open and send + thrift_transport_open (THRIFT_TRANSPORT(tsocket), nullptr); + + assert (t_test_thrift_test_client_test_void (iface, &error) == TRUE); + assert (error == nullptr); + + assert (t_test_thrift_test_client_test_string (iface, &string, "test123", &error) == TRUE); + assert (strcmp (string, "test123") == 0); + g_free (string); + assert (error == nullptr); + + assert (t_test_thrift_test_client_test_byte (iface, &byte, (gint8) 5, &error) == TRUE); + assert (byte == 5); + assert (error == nullptr); + + assert (t_test_thrift_test_client_test_i32 (iface, &i32, 123, &error) == TRUE); + assert (i32 == 123); + assert (error == nullptr); + + assert (t_test_thrift_test_client_test_i64 (iface, &i64, 12345, &error) == TRUE); + assert (i64 == 12345); + assert (error == nullptr); + + assert (t_test_thrift_test_client_test_double (iface, &dbl, 5.6, &error) == TRUE); + assert (dbl == 5.6); + assert (error == nullptr); + + xtruct_out = (TTestXtruct *) g_object_new (T_TEST_TYPE_XTRUCT, nullptr); + xtruct_out->byte_thing = 1; + xtruct_out->__isset_byte_thing = TRUE; + xtruct_out->i32_thing = 15; + xtruct_out->__isset_i32_thing = TRUE; + xtruct_out->i64_thing = 151; + xtruct_out->__isset_i64_thing = TRUE; + xtruct_out->string_thing = g_strdup ("abc123"); + xtruct_out->__isset_string_thing = TRUE; + xtruct_in = (TTestXtruct *) g_object_new(T_TEST_TYPE_XTRUCT, nullptr); + assert (t_test_thrift_test_client_test_struct (iface, &xtruct_in, xtruct_out, &error) == TRUE); + assert (error == nullptr); + + xtruct2_out = (TTestXtruct2 *) g_object_new (T_TEST_TYPE_XTRUCT2, nullptr); + xtruct2_out->byte_thing = 1; + xtruct2_out->__isset_byte_thing = TRUE; + if (xtruct2_out->struct_thing != nullptr) + g_object_unref(xtruct2_out->struct_thing); + xtruct2_out->struct_thing = xtruct_out; + xtruct2_out->__isset_struct_thing = TRUE; + xtruct2_out->i32_thing = 123; + xtruct2_out->__isset_i32_thing = TRUE; + xtruct2_in = (TTestXtruct2 *) g_object_new (T_TEST_TYPE_XTRUCT2, nullptr); + assert (t_test_thrift_test_client_test_nest (iface, &xtruct2_in, xtruct2_out, &error) == TRUE); + assert (error == nullptr); + + g_object_unref (xtruct2_out); + g_object_unref (xtruct2_in); + g_object_unref (xtruct_in); + + map_out = g_hash_table_new (nullptr, nullptr); + map_in = g_hash_table_new (nullptr, nullptr); g_hash_table_insert (map_out, &i32, &i32); + assert (t_test_thrift_test_client_test_map (iface, &map_in, map_out, &error) == TRUE); + assert (error == nullptr); + g_hash_table_destroy (map_out); + g_hash_table_destroy (map_in); + + map_out = g_hash_table_new (nullptr, nullptr); + map_in = g_hash_table_new (nullptr, nullptr); + g_hash_table_insert (map_out, g_strdup ("a"), g_strdup ("123")); + g_hash_table_insert (map_out, g_strdup ("a b"), g_strdup ("with spaces ")); + g_hash_table_insert (map_out, g_strdup ("same"), g_strdup ("same")); + g_hash_table_insert (map_out, g_strdup ("0"), g_strdup ("numeric key")); + assert (t_test_thrift_test_client_test_string_map (iface, &map_in, map_out, &error) == TRUE); + assert (error == nullptr); + g_hash_table_destroy (map_out); + g_hash_table_destroy (map_in); + + set_out = g_hash_table_new (nullptr, nullptr); + set_in = g_hash_table_new (nullptr, nullptr); + g_hash_table_insert (set_out, &i32, &i32); + assert (t_test_thrift_test_client_test_set (iface, &set_in, set_out, &error) == TRUE); + assert (error == nullptr); + g_hash_table_destroy (set_out); + g_hash_table_destroy (set_in); + + list_out = g_array_new(TRUE, TRUE, sizeof(gint32)); + list_in = g_array_new(TRUE, TRUE, sizeof(gint32)); + another_i32 = 456; + g_array_append_val (list_out, i32); + g_array_append_val (list_out, another_i32); + assert (t_test_thrift_test_client_test_list (iface, &list_in, list_out, &error) == TRUE); + assert (error == nullptr); + g_array_free (list_out, TRUE); + g_array_free (list_in, TRUE); + + enum_out = T_TEST_NUMBERZ_ONE; + assert (t_test_thrift_test_client_test_enum (iface, &enum_in, enum_out, &error) == TRUE); + assert (enum_in == enum_out); + assert (error == nullptr); + + user_id_out = 12345; + assert (t_test_thrift_test_client_test_typedef (iface, &user_id_in, user_id_out, &error) == TRUE); + assert (user_id_in == user_id_out); + assert (error == nullptr); + + map_in = g_hash_table_new (nullptr, nullptr); + assert (t_test_thrift_test_client_test_map_map (iface, &map_in, i32, &error) == TRUE); + assert (error == nullptr); + g_hash_table_destroy (map_in); + + // insanity + insanity_out = (TTestInsanity *) g_object_new (T_TEST_TYPE_INSANITY, nullptr); + insanity_out->userMap = g_hash_table_new (nullptr, nullptr); + g_hash_table_insert (insanity_out->userMap, GINT_TO_POINTER (enum_out), &user_id_out); + + xtruct1 = (TTestXtruct *) g_object_new (T_TEST_TYPE_XTRUCT, nullptr); + xtruct1->byte_thing = 1; + xtruct1->__isset_byte_thing = TRUE; + xtruct1->i32_thing = 15; + xtruct1->__isset_i32_thing = TRUE; + xtruct1->i64_thing = 151; + xtruct1->__isset_i64_thing = TRUE; + xtruct1->string_thing = g_strdup ("abc123"); + xtruct1->__isset_string_thing = TRUE; + xtruct2 = (TTestXtruct *) g_object_new (T_TEST_TYPE_XTRUCT, nullptr); + xtruct2->byte_thing = 1; + xtruct2->__isset_byte_thing = TRUE; + xtruct2->i32_thing = 15; + xtruct2->__isset_i32_thing = TRUE; + xtruct2->i64_thing = 151; + xtruct2->__isset_i64_thing = TRUE; + xtruct2->string_thing = g_strdup ("abc123"); + xtruct2->__isset_string_thing = TRUE; + + insanity_in = g_hash_table_new (nullptr, nullptr); + g_ptr_array_add (insanity_out->xtructs, xtruct1); + g_ptr_array_add (insanity_out->xtructs, xtruct2); + assert (t_test_thrift_test_client_test_insanity (iface, &insanity_in, insanity_out, &error) == TRUE); + + g_hash_table_unref (insanity_in); + g_ptr_array_free (insanity_out->xtructs, TRUE); + + multi_map_out = g_hash_table_new (nullptr, nullptr); + string = g_strdup ("abc123"); + g_hash_table_insert (multi_map_out, &i16, string); + multi_in = (TTestXtruct *) g_object_new (T_TEST_TYPE_XTRUCT, nullptr); + assert (t_test_thrift_test_client_test_multi (iface, &multi_in, byte, i32, i64, multi_map_out, enum_out, user_id_out, &error) == TRUE); + assert (multi_in->i32_thing == i32); + assert (multi_in->i64_thing == i64); + g_object_unref (multi_in); + g_hash_table_unref (multi_map_out); + g_free (string); + + assert (t_test_thrift_test_client_test_exception (iface, "Xception", &xception, &error) == FALSE); + assert (xception->errorCode == 1001); + g_error_free (error); + error = nullptr; + g_object_unref (xception); + xception = nullptr; + + assert (t_test_thrift_test_client_test_exception (iface, "ApplicationException", &xception, &error) == FALSE); + g_error_free (error); + error = nullptr; + assert (xception == nullptr); + + assert (t_test_thrift_test_client_test_exception (iface, "Test", &xception, &error) == TRUE); + assert (error == nullptr); + + multi_in = (TTestXtruct*) g_object_new (T_TEST_TYPE_XTRUCT, nullptr); + assert (t_test_thrift_test_client_test_multi_exception (iface, &multi_in, "Xception", nullptr, &xception, &xception2, &error) == FALSE); + assert (xception->errorCode == 1001); + assert (xception2 == nullptr); + g_error_free (error); + error = nullptr; + g_object_unref (xception); + g_object_unref (multi_in); + xception = nullptr; + multi_in = nullptr; + + multi_in = (TTestXtruct*) g_object_new (T_TEST_TYPE_XTRUCT, nullptr); + assert (t_test_thrift_test_client_test_multi_exception (iface, &multi_in, "Xception2", nullptr, &xception, &xception2, &error) == FALSE); + assert (xception2->errorCode == 2002); + assert (xception == nullptr); + g_error_free (error); + error = nullptr; + g_object_unref (xception2); + g_object_unref (multi_in); + xception2 = nullptr; + multi_in = nullptr; + + multi_in = (TTestXtruct*) g_object_new (T_TEST_TYPE_XTRUCT, nullptr); + assert (t_test_thrift_test_client_test_multi_exception (iface, &multi_in, nullptr , nullptr, &xception, &xception2, &error) == TRUE); + assert (error == nullptr); + g_object_unref(multi_in); + multi_in = nullptr; + + assert (t_test_thrift_test_client_test_oneway (iface, 1, &error) == TRUE); + assert (error == nullptr); + + /* sleep to let the oneway call go through */ + sleep (5); + + thrift_transport_close (THRIFT_TRANSPORT(tsocket), nullptr); + g_object_unref (client); + g_object_unref (protocol); + g_object_unref (tsocket); +} + + +} /* extern "C" */ + + +static void +bailout (int signum) +{ + THRIFT_UNUSED_VARIABLE (signum); + + exit (1); +} + +int +main (void) +{ + int status; + int pid = fork (); + assert (pid >= 0); + + if (pid == 0) /* child */ + { + std::shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory()); + std::shared_ptr<TestHandler> testHandler(new TestHandler()); + std::shared_ptr<ThriftTestProcessor> testProcessor(new ThriftTestProcessor(testHandler)); + std::shared_ptr<TServerSocket> serverSocket(new TServerSocket(TEST_PORT)); + std::shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory()); + TSimpleServer simpleServer(testProcessor, serverSocket, transportFactory, protocolFactory); + signal (SIGALRM, bailout); + alarm (60); + simpleServer.serve(); + } else { + sleep (1); + test_thrift_client (); + kill (pid, SIGINT); + assert (wait (&status) == pid); + } + + return 0; +} + diff --git a/src/jaegertracing/thrift/lib/c_glib/test/testtransportsocket.c b/src/jaegertracing/thrift/lib/c_glib/test/testtransportsocket.c new file mode 100755 index 000000000..89c61b910 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/test/testtransportsocket.c @@ -0,0 +1,361 @@ +/* + * 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 <netdb.h> +#include <sys/wait.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> + +#define TEST_DATA { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j' } + +/* 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_socket.c" +#undef socket +#undef recv +#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) +{ + gchar *hostname = NULL; + guint port = 0; + + GObject *object = NULL; + object = g_object_new (THRIFT_TYPE_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_open_and_close(void) +{ + ThriftSocket *tsocket = NULL; + ThriftTransport *transport = NULL; + GError *err = NULL; + int port = 51199; + pid_t pid; + int status; + + pid = fork (); + g_assert ( pid >= 0 ); + + if ( pid == 0 ) + { + /* child listens */ + thrift_socket_server_open (port, 1); + exit (0); + } else { + /* parent connects, wait a bit for the socket to be created */ + sleep (1); + + /* open a connection and close it */ + tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost", + "port", port, NULL); + transport = THRIFT_TRANSPORT (tsocket); + thrift_socket_open (transport, NULL); + g_assert (thrift_socket_is_open (transport) == TRUE); + thrift_socket_close (transport, NULL); + g_assert (thrift_socket_is_open (transport) == FALSE); + + /* test close failure */ + tsocket->sd = -1; + thrift_socket_close (transport, NULL); + g_object_unref (tsocket); + + /* try a hostname lookup failure */ + tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost.broken", + NULL); + transport = THRIFT_TRANSPORT (tsocket); + g_assert (thrift_socket_open (transport, &err) == FALSE); + g_object_unref (tsocket); + g_error_free (err); + err = NULL; + + /* try an error call to socket() */ + tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost", NULL); + transport = THRIFT_TRANSPORT (tsocket); + socket_error = 1; + g_assert (thrift_socket_open (transport, &err) == FALSE); + socket_error = 0; + g_object_unref (tsocket); + g_error_free (err); + g_assert ( wait (&status) == pid ); + g_assert ( status == 0 ); + } +} + +static void +test_read_and_write(void) +{ + ThriftSocket *tsocket = NULL; + ThriftTransport *transport = NULL; + pid_t pid; + int port = 51199; + int status; + guchar buf[10] = TEST_DATA; /* a buffer */ + + pid = fork (); + g_assert ( pid >= 0 ); + + if ( pid == 0 ) + { + /* child listens */ + thrift_socket_server (port); + exit (0); + } else { + /* parent connects, wait a bit for the socket to be created */ + sleep (1); + + tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost", + "port", port, NULL); + transport = THRIFT_TRANSPORT (tsocket); + g_assert (thrift_socket_open (transport, NULL) == TRUE); + g_assert (thrift_socket_is_open (transport)); + thrift_socket_write (transport, buf, 10, NULL); + + /* write fail */ + send_error = 1; + thrift_socket_write (transport, buf, 1, NULL); + send_error = 0; + + thrift_socket_write_end (transport, NULL); + thrift_socket_flush (transport, NULL); + thrift_socket_close (transport, NULL); + g_object_unref (tsocket); + + g_assert ( wait (&status) == pid ); + g_assert ( status == 0 ); + } +} + +/* test ThriftSocket's peek() implementation */ +static void +test_peek(void) +{ + gint status; + pid_t pid; + guint port = 51199; + gchar data = 'A'; + ThriftTransport *client_transport; + GError *error = NULL; + + client_transport = g_object_new (THRIFT_TYPE_SOCKET, + "hostname", "localhost", + "port", port, + NULL); + + /* thrift_transport_peek returns FALSE when the socket is closed */ + g_assert (thrift_transport_is_open (client_transport) == FALSE); + g_assert (thrift_transport_peek (client_transport, &error) == FALSE); + g_assert (error == NULL); + + pid = fork (); + g_assert (pid >= 0); + + if (pid == 0) + { + ThriftServerTransport *server_transport = NULL; + + g_object_unref (client_transport); + + /* child listens */ + server_transport = g_object_new (THRIFT_TYPE_SERVER_SOCKET, + "port", port, + NULL); + g_assert (server_transport != NULL); + + thrift_server_transport_listen (server_transport, &error); + g_assert (error == NULL); + + client_transport = g_object_new + (THRIFT_TYPE_BUFFERED_TRANSPORT, + "transport", thrift_server_transport_accept (server_transport, &error), + "r_buf_size", 0, + "w_buf_size", sizeof data, + NULL); + g_assert (error == NULL); + g_assert (client_transport != NULL); + + /* write exactly one character to the client */ + g_assert (thrift_transport_write (client_transport, + &data, + sizeof data, + &error) == TRUE); + + thrift_transport_flush (client_transport, &error); + thrift_transport_write_end (client_transport, &error); + thrift_transport_close (client_transport, &error); + + g_object_unref (client_transport); + g_object_unref (server_transport); + + exit (0); + } + else { + /* parent connects, wait a bit for the socket to be created */ + sleep (1); + + /* connect to the child */ + thrift_transport_open (client_transport, &error); + g_assert (error == NULL); + g_assert (thrift_transport_is_open (client_transport) == TRUE); + + /* thrift_transport_peek returns TRUE when the socket is open and there is + data available to be read */ + g_assert (thrift_transport_peek (client_transport, &error) == TRUE); + g_assert (error == NULL); + + /* read exactly one character from the server */ + g_assert_cmpint (thrift_transport_read (client_transport, + &data, + sizeof data, + &error), ==, sizeof data); + + /* thrift_transport_peek returns FALSE when the socket is open but there is + no (more) data available to be read */ + g_assert (thrift_transport_is_open (client_transport) == TRUE); + g_assert (thrift_transport_peek (client_transport, &error) == FALSE); + g_assert (error == NULL); + + thrift_transport_read_end (client_transport, &error); + thrift_transport_close (client_transport, &error); + + g_object_unref (client_transport); + + g_assert (wait (&status) == pid); + g_assert (status == 0); + } +} + +static void +thrift_socket_server_open (const int port, int times) +{ + ThriftServerTransport *transport = NULL; + ThriftTransport *client = NULL; + int i; + ThriftServerSocket *tsocket = g_object_new (THRIFT_TYPE_SERVER_SOCKET, + "port", port, NULL); + + transport = THRIFT_SERVER_TRANSPORT (tsocket); + thrift_server_transport_listen (transport, NULL); + for(i=0;i<times;i++){ + client = thrift_server_transport_accept (transport, NULL); + g_assert (client != NULL); + thrift_socket_close (client, NULL); + g_object_unref (client); + } + g_object_unref (tsocket); +} + + +static void +thrift_socket_server (const int port) +{ + int bytes = 0; + 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_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_socket_read (client, buf, 1, NULL); + recv_error = 0; + + thrift_socket_read_end (client, NULL); + thrift_socket_close (client, NULL); + g_object_unref (tsocket); + g_object_unref (client); +} + +int +main(int argc, char *argv[]) +{ +#if (!GLIB_CHECK_VERSION (2, 36, 0)) + g_type_init(); +#endif + + g_test_init (&argc, &argv, NULL); + + g_test_add_func ("/testtransportsocket/CreateAndDestroy", test_create_and_destroy); + g_test_add_func ("/testtransportsocket/OpenAndClose", test_open_and_close); + g_test_add_func ("/testtransportsocket/ReadAndWrite", test_read_and_write); + g_test_add_func ("/testtransportsocket/Peek", test_peek); + + return g_test_run (); +} + diff --git a/src/jaegertracing/thrift/lib/c_glib/test/testtransportsslsocket.c b/src/jaegertracing/thrift/lib/c_glib/test/testtransportsslsocket.c new file mode 100644 index 000000000..3c2644d8d --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/test/testtransportsslsocket.c @@ -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; +} + diff --git a/src/jaegertracing/thrift/lib/c_glib/thrift_c_glib.pc.in b/src/jaegertracing/thrift/lib/c_glib/thrift_c_glib.pc.in new file mode 100644 index 000000000..568c7a25d --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/thrift_c_glib.pc.in @@ -0,0 +1,30 @@ +# +# 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. +# + +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: Thrift +Description: Thrift C API +Version: @VERSION@ +Requires: glib-2.0 gobject-2.0 +Libs: -L${libdir} -lthrift_c_glib +Cflags: -I${includedir} |