源码提交
This commit is contained in:
+118
@@ -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.
|
||||
#
|
||||
|
||||
SUBDIRS = json xml
|
||||
PRECROSS_TARGET =
|
||||
|
||||
if WITH_CPP
|
||||
SUBDIRS += cpp
|
||||
endif
|
||||
|
||||
if WITH_C_GLIB
|
||||
SUBDIRS += c_glib
|
||||
endif
|
||||
|
||||
if WITH_JAVA
|
||||
SUBDIRS += java
|
||||
PRECROSS_TARGET += precross-java
|
||||
# JavaScript unit test depends on java
|
||||
# so test only if java, ant & co is available
|
||||
SUBDIRS += js
|
||||
endif
|
||||
|
||||
if WITH_KOTLIN
|
||||
SUBDIRS += kotlin
|
||||
PRECROSS_TARGET += precross-kotlin
|
||||
endif
|
||||
|
||||
if WITH_PYTHON
|
||||
SUBDIRS += py
|
||||
endif
|
||||
|
||||
if WITH_ERLANG
|
||||
SUBDIRS += erl
|
||||
endif
|
||||
|
||||
if WITH_RUBY
|
||||
SUBDIRS += rb
|
||||
endif
|
||||
|
||||
if WITH_PERL
|
||||
SUBDIRS += perl
|
||||
endif
|
||||
|
||||
if WITH_PHP
|
||||
SUBDIRS += php
|
||||
endif
|
||||
|
||||
if WITH_DART
|
||||
SUBDIRS += dart
|
||||
endif
|
||||
|
||||
if WITH_DOTNET
|
||||
SUBDIRS += netstd
|
||||
endif
|
||||
|
||||
if WITH_GO
|
||||
SUBDIRS += go
|
||||
endif
|
||||
|
||||
if WITH_D
|
||||
SUBDIRS += d
|
||||
PRECROSS_TARGET += precross-d
|
||||
endif
|
||||
|
||||
if WITH_NODEJS
|
||||
SUBDIRS += nodejs
|
||||
PRECROSS_TARGET += precross-nodejs
|
||||
SUBDIRS += nodets
|
||||
endif
|
||||
|
||||
if WITH_LUA
|
||||
SUBDIRS += lua
|
||||
endif
|
||||
|
||||
if WITH_RS
|
||||
SUBDIRS += rs
|
||||
endif
|
||||
|
||||
if WITH_CL
|
||||
SUBDIRS += cl
|
||||
endif
|
||||
|
||||
if WITH_SWIFT
|
||||
SUBDIRS += swift
|
||||
endif
|
||||
|
||||
# All of the libs that don't use Automake need to go in here
|
||||
# so they will end up in our release tarballs.
|
||||
EXTRA_DIST = \
|
||||
d \
|
||||
dart \
|
||||
delphi \
|
||||
haxe \
|
||||
javame \
|
||||
js \
|
||||
ocaml \
|
||||
st \
|
||||
ts
|
||||
|
||||
precross-%:
|
||||
$(MAKE) -C $* precross
|
||||
precross: $(PRECROSS_TARGET)
|
||||
@@ -0,0 +1,121 @@
|
||||
#
|
||||
# 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
|
||||
list(APPEND 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/thrift_configuration.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
|
||||
)
|
||||
|
||||
set(thrift_c_glib_zlib_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/thrift_configuration.c
|
||||
src/thrift/c_glib/transport/thrift_transport.c
|
||||
src/thrift/c_glib/transport/thrift_transport_factory.c
|
||||
src/thrift/c_glib/transport/thrift_zlib_transport.c
|
||||
src/thrift/c_glib/transport/thrift_zlib_transport_factory.c
|
||||
)
|
||||
|
||||
# If OpenSSL is not found just ignore the OpenSSL stuff
|
||||
if(OPENSSL_FOUND AND WITH_OPENSSL)
|
||||
list(APPEND thrift_c_glib_SOURCES
|
||||
src/thrift/c_glib/transport/thrift_ssl_socket.c
|
||||
)
|
||||
if(TARGET OpenSSL::SSL OR TARGET OpenSSL::Crypto)
|
||||
if(TARGET OpenSSL::SSL)
|
||||
list(APPEND SYSLIBS OpenSSL::SSL)
|
||||
endif()
|
||||
if(TARGET OpenSSL::Crypto)
|
||||
list(APPEND SYSLIBS OpenSSL::Crypto)
|
||||
endif()
|
||||
else()
|
||||
include_directories(SYSTEM "${OPENSSL_INCLUDE_DIR}")
|
||||
list(APPEND SYSLIBS "${OPENSSL_LIBRARIES}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
# Contains the thrift specific ADD_LIBRARY_THRIFT macro
|
||||
include(ThriftMacros)
|
||||
|
||||
ADD_LIBRARY_THRIFT(thrift_c_glib ${thrift_c_glib_SOURCES})
|
||||
target_link_libraries(thrift_c_glib PUBLIC ${SYSLIBS})
|
||||
|
||||
# If Zlib is not found just ignore the Zlib stuff
|
||||
if(WITH_ZLIB)
|
||||
ADD_LIBRARY_THRIFT(thrift_c_glib_zlib ${thrift_c_glib_zlib_SOURCES})
|
||||
target_link_libraries(thrift_c_glib_zlib PUBLIC ${SYSLIBS})
|
||||
target_link_libraries(thrift_c_glib_zlib PUBLIC thrift_c_glib)
|
||||
|
||||
if(TARGET ZLIB::ZLIB)
|
||||
target_link_libraries(thrift_c_glib_zlib PUBLIC ZLIB::ZLIB)
|
||||
else()
|
||||
include_directories(SYSTEM ${ZLIB_INCLUDE_DIRS})
|
||||
target_link_libraries(thrift_c_glib_zlib PUBLIC ${ZLIB_LIBRARIES})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# 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()
|
||||
@@ -0,0 +1,124 @@
|
||||
#
|
||||
# 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/thrift_configuration.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_zlib_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_zlib_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) $(ZLIB_LDFLAGS) $(ZLIB_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 \
|
||||
src/thrift/c_glib/thrift_configuration.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_zlib_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 \
|
||||
src/thrift/c_glib/transport/thrift_zlib_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
|
||||
@@ -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.
|
||||
@@ -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)
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 */
|
||||
@@ -0,0 +1,342 @@
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
THRIFT_UNUSED_VAR (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);
|
||||
|
||||
}
|
||||
|
||||
if (stored_message_protocol != NULL) {
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -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_ */
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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 */
|
||||
@@ -0,0 +1,976 @@
|
||||
/*
|
||||
* 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 <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);
|
||||
|
||||
ThriftProtocol *tp = THRIFT_PROTOCOL (protocol);
|
||||
ThriftTransportClass *ttc = THRIFT_TRANSPORT_GET_CLASS (tp->transport);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if(!ttc->checkReadBytesAvailable (THRIFT_TRANSPORT(tp->transport),
|
||||
sizei * thrift_binary_protocol_get_min_serialized_size(protocol, k, error) +
|
||||
sizei * thrift_binary_protocol_get_min_serialized_size(protocol, v, error),
|
||||
error))
|
||||
{
|
||||
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);
|
||||
|
||||
ThriftProtocol *tp = THRIFT_PROTOCOL (protocol);
|
||||
ThriftTransportClass *ttc = THRIFT_TRANSPORT_GET_CLASS (tp->transport);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if(!ttc->checkReadBytesAvailable (THRIFT_TRANSPORT(tp->transport),
|
||||
(sizei * thrift_binary_protocol_get_min_serialized_size(protocol, e, error)),
|
||||
error))
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
gint
|
||||
thrift_binary_protocol_get_min_serialized_size(ThriftProtocol *protocol, ThriftType type, GError **error)
|
||||
{
|
||||
THRIFT_UNUSED_VAR (protocol);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case T_STOP:
|
||||
return 0;
|
||||
case T_VOID:
|
||||
return 0;
|
||||
case T_BOOL:
|
||||
return sizeof(gint8);
|
||||
case T_BYTE:
|
||||
return sizeof(gint8);
|
||||
case T_DOUBLE:
|
||||
return sizeof(double);
|
||||
case T_I16:
|
||||
return sizeof(short);
|
||||
case T_I32:
|
||||
return sizeof(int);
|
||||
case T_I64:
|
||||
return sizeof(long);
|
||||
case T_STRING:
|
||||
return sizeof(int);
|
||||
case T_STRUCT:
|
||||
return 0;
|
||||
case T_MAP:
|
||||
return sizeof(int);
|
||||
case T_SET:
|
||||
return sizeof(int);
|
||||
case T_LIST:
|
||||
return sizeof(int);
|
||||
default:
|
||||
g_set_error(error,
|
||||
THRIFT_PROTOCOL_ERROR,
|
||||
THRIFT_PROTOCOL_ERROR_INVALID_DATA,
|
||||
"unrecognized type");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
cls->get_min_serialized_size = thrift_binary_protocol_get_min_serialized_size;
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* 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);
|
||||
|
||||
gint
|
||||
thrift_binary_protocol_get_min_serialized_size(ThriftProtocol *protocol, ThriftType type, GError **error);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* _THRIFT_BINARY_PROTOCOL_H */
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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 */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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 */
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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 */
|
||||
@@ -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 (ThriftProtocol *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);
|
||||
}
|
||||
@@ -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 */
|
||||
@@ -0,0 +1,654 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
|
||||
gint
|
||||
thrift_protocol_get_min_serialized_size (ThriftProtocol *protocol, ThriftType type, GError ** error)
|
||||
{
|
||||
return THRIFT_PROTOCOL_GET_CLASS (protocol)->get_min_serialized_size (protocol,
|
||||
type, 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;
|
||||
cls->get_min_serialized_size = thrift_protocol_get_min_serialized_size;
|
||||
}
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
#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);
|
||||
gint (*get_min_serialized_size) (ThriftProtocol *protocol, ThriftType type, 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);
|
||||
|
||||
gint thrift_protocol_get_min_serialized_size (ThriftProtocol *protocol,
|
||||
ThriftType type, 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 */
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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_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);
|
||||
|
||||
gint32 thrift_protocol_decorator_write_message_begin (ThriftProtocol *protocol,
|
||||
const gchar *name,
|
||||
const ThriftMessageType message_type,
|
||||
const gint32 seqid, GError **error);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* _THRIFT_PROTOCOL_DECORATOR_H */
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 */
|
||||
@@ -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 = g_strdup (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);
|
||||
}
|
||||
@@ -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 */
|
||||
@@ -0,0 +1,201 @@
|
||||
/*
|
||||
* 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:
|
||||
g_clear_object (&server->processor);
|
||||
server->processor = g_value_dup_object (value);
|
||||
break;
|
||||
case PROP_THRIFT_SERVER_SERVER_TRANSPORT:
|
||||
g_clear_object (&server->server_transport);
|
||||
server->server_transport = g_value_dup_object (value);
|
||||
break;
|
||||
case PROP_THRIFT_SERVER_INPUT_TRANSPORT_FACTORY:
|
||||
g_clear_object (&server->input_transport_factory);
|
||||
server->input_transport_factory = g_value_dup_object (value);
|
||||
break;
|
||||
case PROP_THRIFT_SERVER_OUTPUT_TRANSPORT_FACTORY:
|
||||
g_clear_object (&server->output_transport_factory);
|
||||
server->output_transport_factory = g_value_dup_object (value);
|
||||
break;
|
||||
case PROP_THRIFT_SERVER_INPUT_PROTOCOL_FACTORY:
|
||||
g_clear_object (&server->input_protocol_factory);
|
||||
server->input_protocol_factory = g_value_dup_object (value);
|
||||
break;
|
||||
case PROP_THRIFT_SERVER_OUTPUT_PROTOCOL_FACTORY:
|
||||
g_clear_object (&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;
|
||||
}
|
||||
@@ -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 */
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* 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);
|
||||
g_object_unref (input_transport);
|
||||
g_object_unref (output_transport);
|
||||
g_object_unref (input_protocol);
|
||||
g_object_unref (output_protocol);
|
||||
}
|
||||
if ((*error) != NULL) {
|
||||
g_message ("thrift_simple_server_serve : %s", (*error)->message);
|
||||
g_clear_error (error);
|
||||
}
|
||||
if (t != NULL)
|
||||
{
|
||||
g_object_unref (t);
|
||||
}
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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 */
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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 */
|
||||
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* 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 distuributed 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_configuration.h"
|
||||
|
||||
/* object properties */
|
||||
enum _ThriftConfigurationProperties
|
||||
{
|
||||
PROP_0,
|
||||
PROP_THRIFT_CONFIGURATION_MAX_MESSAGE_SIZE,
|
||||
PROP_THRIFT_CONFIGURATION_MAX_FRAME_SIZE,
|
||||
PROP_THRIFT_CONFIGURATION_RECURSION_LIMIT
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(ThriftConfiguration, thrift_configuration, G_TYPE_OBJECT)
|
||||
|
||||
/* property accessor */
|
||||
void
|
||||
thrift_configuration_get_property(GObject *object, guint property_id,
|
||||
GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
ThriftConfiguration *configuration = THRIFT_CONFIGURATION(object);
|
||||
|
||||
THRIFT_UNUSED_VAR (pspec);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_THRIFT_CONFIGURATION_MAX_MESSAGE_SIZE:
|
||||
g_value_set_int(value, configuration->maxMessageSize_);
|
||||
break;
|
||||
case PROP_THRIFT_CONFIGURATION_MAX_FRAME_SIZE:
|
||||
g_value_set_int(value, configuration->maxFrameSize_);
|
||||
break;
|
||||
case PROP_THRIFT_CONFIGURATION_RECURSION_LIMIT:
|
||||
g_value_set_int(value, configuration->recursionLimit_);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* property mutator */
|
||||
void
|
||||
thrift_configuration_set_property(GObject *object, guint property_id,
|
||||
const GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
ThriftConfiguration *configuration = THRIFT_CONFIGURATION (object);
|
||||
|
||||
THRIFT_UNUSED_VAR (pspec);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_THRIFT_CONFIGURATION_MAX_MESSAGE_SIZE:
|
||||
configuration->maxMessageSize_ = g_value_get_int (value);
|
||||
break;
|
||||
case PROP_THRIFT_CONFIGURATION_MAX_FRAME_SIZE:
|
||||
configuration->maxFrameSize_ = g_value_get_int (value);
|
||||
break;
|
||||
case PROP_THRIFT_CONFIGURATION_RECURSION_LIMIT:
|
||||
configuration->recursionLimit_ = g_value_get_int (value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
thrift_configuration_class_init (ThriftConfigurationClass *cls)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (cls);
|
||||
GParamSpec *param_spec = NULL;
|
||||
|
||||
/* setup accessors and mutators */
|
||||
gobject_class->get_property = thrift_configuration_get_property;
|
||||
gobject_class->set_property = thrift_configuration_set_property;
|
||||
|
||||
param_spec = g_param_spec_int ("max_message_size",
|
||||
"max_message_size (construct)",
|
||||
"Set the max size of the message",
|
||||
0, /* min */
|
||||
G_MAXINT32, /* max */
|
||||
DEFAULT_MAX_MESSAGE_SIZE, /* default by convention */
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_READWRITE);
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_THRIFT_CONFIGURATION_MAX_MESSAGE_SIZE,
|
||||
param_spec);
|
||||
|
||||
param_spec = g_param_spec_int ("max_frame_size",
|
||||
"max_frame_size (construct)",
|
||||
"Set the max size of the frame",
|
||||
0, /* min */
|
||||
G_MAXINT32, /* max */
|
||||
DEFAULT_MAX_FRAME_SIZE, /* default by convention */
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_READWRITE);
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_THRIFT_CONFIGURATION_MAX_FRAME_SIZE,
|
||||
param_spec);
|
||||
|
||||
param_spec = g_param_spec_int ("recursion_limit",
|
||||
"recursion_limit (construct)",
|
||||
"Set the limit of the resursion",
|
||||
0, /* min */
|
||||
G_MAXINT32, /* max */
|
||||
DEFAULT_RECURSION_DEPTH, /* default by convention */
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_READWRITE);
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_THRIFT_CONFIGURATION_RECURSION_LIMIT,
|
||||
param_spec);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
thrift_configuration_init (ThriftConfiguration *configuration)
|
||||
{
|
||||
THRIFT_UNUSED_VAR (configuration);
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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_CONFIGURATION_H
|
||||
#define _THRIFT_CONFIGURATION_H
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/* type macros */
|
||||
#define THRIFT_TYPE_CONFIGURATION (thrift_configuration_get_type ())
|
||||
#define THRIFT_CONFIGURATION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THRIFT_TYPE_CONFIGURATION, ThriftConfiguration))
|
||||
#define THRIFT_IS_CONFIGURATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THRIFT_TYPE_CONFIGURATION))
|
||||
#define THRIFT_CONFIGURATTION_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), THRIFT_TYPE_CONFIGURATION, ThriftConfigurationClass))
|
||||
#define THRIFT_IS_CONFIGURATION_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), THRIFT_TYPE_CONFIGURATION))
|
||||
#define THRIFT_CONFIGURATION_GET_CLASS(obj) (G_TYPE_INSTAANCE_GET_CLASS ((obj), THRIFT_TYPE_CONFIGURATION, ThriftconfigurationClass))
|
||||
|
||||
typedef struct _ThriftConfiguration ThriftConfiguration;
|
||||
|
||||
/*!
|
||||
* Thrift Configuration object
|
||||
*/
|
||||
struct _ThriftConfiguration
|
||||
{
|
||||
GObject parent;
|
||||
|
||||
/* private */
|
||||
int maxMessageSize_;
|
||||
int maxFrameSize_;
|
||||
int recursionLimit_;
|
||||
};
|
||||
|
||||
typedef struct _ThriftConfigurationClass ThriftConfigurationClass;
|
||||
|
||||
/*!
|
||||
* Thrift Configuration class
|
||||
*/
|
||||
struct _ThriftConfigurationClass
|
||||
{
|
||||
GObjectClass parent;
|
||||
};
|
||||
|
||||
/* used by THRIFT_TYPE_CONFIGURATION */
|
||||
GType thrift_configuration_get_type(void);
|
||||
|
||||
#define DEFAULT_MAX_MESSAGE_SIZE (100 * 1024 * 1024)
|
||||
#define DEFAULT_MAX_FRAME_SIZE (16384000)
|
||||
#define DEFAULT_RECURSION_DEPTH (64)
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* #ifndef _THRIFT_CONFIGURATION_H */
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -0,0 +1,461 @@
|
||||
/*
|
||||
* 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 <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,
|
||||
PROP_THRIFT_BUFFERED_TRANSPORT_CONFIGURATION,
|
||||
PROP_THRIFT_BUFFERED_TRANSPORT_REMAINING_MESSAGE_SIZE,
|
||||
PROP_THRIFT_BUFFERED_TRANSPORT_KNOW_MESSAGE_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_new0 (guchar, 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) {
|
||||
g_free (tmpdata);
|
||||
return ret;
|
||||
}
|
||||
got += ret;
|
||||
|
||||
/* copy the data starting from where we left off */
|
||||
memcpy ((guint8 *)buf + have, tmpdata, got);
|
||||
g_free (tmpdata);
|
||||
return got + have;
|
||||
} else {
|
||||
guint32 give;
|
||||
|
||||
if ((ret = THRIFT_TRANSPORT_GET_CLASS (t->transport)->read (t->transport,
|
||||
tmpdata,
|
||||
want,
|
||||
error)) < 0) {
|
||||
g_free (tmpdata);
|
||||
return ret;
|
||||
}
|
||||
got += ret;
|
||||
t->r_buf = g_byte_array_append (t->r_buf, tmpdata, got);
|
||||
g_free (tmpdata);
|
||||
/* 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);
|
||||
ThriftTransportClass *ttc = THRIFT_TRANSPORT_GET_CLASS (transport);
|
||||
if(!ttc->checkReadBytesAvailable (transport, len, error))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
ThriftTransportClass *ttc = THRIFT_TRANSPORT_GET_CLASS (transport);
|
||||
|
||||
if(!ttc->resetConsumedMessageSize (transport, -1, error))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
ThriftTransport *tt = THRIFT_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;
|
||||
case PROP_THRIFT_BUFFERED_TRANSPORT_CONFIGURATION:
|
||||
g_value_set_object (value, tt->configuration);
|
||||
break;
|
||||
case PROP_THRIFT_BUFFERED_TRANSPORT_REMAINING_MESSAGE_SIZE:
|
||||
g_value_set_long (value, tt->remainingMessageSize_);
|
||||
break;
|
||||
case PROP_THRIFT_BUFFERED_TRANSPORT_KNOW_MESSAGE_SIZE:
|
||||
g_value_set_long (value, tt->knowMessageSize_);
|
||||
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);
|
||||
|
||||
ThriftTransport *tt = THRIFT_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;
|
||||
case PROP_THRIFT_BUFFERED_TRANSPORT_CONFIGURATION:
|
||||
tt->configuration = g_value_dup_object (value);
|
||||
break;
|
||||
case PROP_THRIFT_BUFFERED_TRANSPORT_REMAINING_MESSAGE_SIZE:
|
||||
tt->remainingMessageSize_ = g_value_get_long (value);
|
||||
break;
|
||||
case PROP_THRIFT_BUFFERED_TRANSPORT_KNOW_MESSAGE_SIZE:
|
||||
tt->knowMessageSize_ = g_value_get_long (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);
|
||||
|
||||
param_spec = g_param_spec_object ("configuration",
|
||||
"configuration (construct)",
|
||||
"Thrift Configuration",
|
||||
THRIFT_TYPE_CONFIGURATION,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_THRIFT_BUFFERED_TRANSPORT_CONFIGURATION,
|
||||
param_spec);
|
||||
|
||||
param_spec = g_param_spec_long ("remainingmessagesize",
|
||||
"remainingmessagesize (construct)",
|
||||
"Set the remaining message size",
|
||||
0, /* min */
|
||||
G_MAXINT32, /* max */
|
||||
DEFAULT_MAX_MESSAGE_SIZE, /* default by construct */
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_THRIFT_BUFFERED_TRANSPORT_REMAINING_MESSAGE_SIZE,
|
||||
param_spec);
|
||||
|
||||
param_spec = g_param_spec_long ("knowmessagesize",
|
||||
"knowmessagesize (construct)",
|
||||
"Set the known size of the message",
|
||||
0, /* min */
|
||||
G_MAXINT32, /* max */
|
||||
DEFAULT_MAX_MESSAGE_SIZE, /* default by construct */
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_THRIFT_BUFFERED_TRANSPORT_KNOW_MESSAGE_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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 */
|
||||
@@ -0,0 +1,335 @@
|
||||
/*
|
||||
* 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/thrift_configuration.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,
|
||||
PROP_THRIFT_FD_TRANSPORT_CONFIGURATION,
|
||||
PROP_THRIFT_FD_TRANSPORT_REMAINING_MESSAGE_SIZE,
|
||||
PROP_THRIFT_FD_TRANSPORT_KNOW_MESSAGE_SIZE,
|
||||
};
|
||||
|
||||
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);
|
||||
ThriftTransportClass *ttc = THRIFT_TRANSPORT_GET_CLASS (transport);
|
||||
if(!ttc->checkReadBytesAvailable(transport, len, error))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
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);
|
||||
ThriftTransportClass *ttc = THRIFT_TRANSPORT_GET_CLASS (transport);
|
||||
if(!ttc->resetConsumedMessageSize (transport, -1, error))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
ThriftTransport *tt = THRIFT_TRANSPORT (object);
|
||||
|
||||
switch (property_id) {
|
||||
case PROP_THRIFT_FD_TRANSPORT_FD:
|
||||
g_value_set_int (value, t->fd);
|
||||
break;
|
||||
case PROP_THRIFT_FD_TRANSPORT_CONFIGURATION:
|
||||
g_value_set_object (value, tt->configuration);
|
||||
break;
|
||||
case PROP_THRIFT_FD_TRANSPORT_REMAINING_MESSAGE_SIZE:
|
||||
g_value_set_long (value, tt->remainingMessageSize_);
|
||||
break;
|
||||
case PROP_THRIFT_FD_TRANSPORT_KNOW_MESSAGE_SIZE:
|
||||
g_value_set_long (value, tt->knowMessageSize_);
|
||||
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);
|
||||
|
||||
ThriftTransport *tt = THRIFT_TRANSPORT (object);
|
||||
|
||||
switch (property_id) {
|
||||
case PROP_THRIFT_FD_TRANSPORT_FD:
|
||||
t->fd = g_value_get_int (value);
|
||||
break;
|
||||
case PROP_THRIFT_FD_TRANSPORT_CONFIGURATION:
|
||||
tt->configuration = g_value_dup_object (value);
|
||||
break;
|
||||
case PROP_THRIFT_FD_TRANSPORT_REMAINING_MESSAGE_SIZE:
|
||||
tt->remainingMessageSize_ = g_value_get_long (value);
|
||||
break;
|
||||
case PROP_THRIFT_FD_TRANSPORT_KNOW_MESSAGE_SIZE:
|
||||
tt->knowMessageSize_ = g_value_get_long (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);
|
||||
|
||||
param_spec = g_param_spec_object ("configuration",
|
||||
"configuration (construct)",
|
||||
"Thrift Configuration",
|
||||
THRIFT_TYPE_CONFIGURATION,
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_READWRITE);
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_THRIFT_FD_TRANSPORT_CONFIGURATION,
|
||||
param_spec);
|
||||
|
||||
param_spec = g_param_spec_long ("remainingmessagesize",
|
||||
"remainingmessagesize (construct)",
|
||||
"Set the remaining message size",
|
||||
0, /* min */
|
||||
G_MAXINT32, /* max */
|
||||
DEFAULT_MAX_MESSAGE_SIZE, /* default by construct */
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_THRIFT_FD_TRANSPORT_REMAINING_MESSAGE_SIZE,
|
||||
param_spec);
|
||||
|
||||
param_spec = g_param_spec_long ("knowmessagesize",
|
||||
"knowmessagesize (construct)",
|
||||
"Set the known size of the message",
|
||||
0, /* min */
|
||||
G_MAXINT32, /* max */
|
||||
DEFAULT_MAX_MESSAGE_SIZE, /* default by construct */
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_THRIFT_FD_TRANSPORT_KNOW_MESSAGE_SIZE,
|
||||
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;
|
||||
}
|
||||
@@ -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 */
|
||||
@@ -0,0 +1,464 @@
|
||||
/*
|
||||
* 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 <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/thrift_configuration.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,
|
||||
PROP_THRIFT_FRAMED_TRANSPORT_REMAINING_MESSAGE_SIZE,
|
||||
PROP_THRIFT_FRAMED_TRANSPORT_KNOW_MESSAGE_SIZE,
|
||||
PROP_THRIFT_FRAMED_TRANSPORT_CONFIGURATION
|
||||
};
|
||||
|
||||
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);
|
||||
if (sz > t->max_frame_size)
|
||||
{
|
||||
g_set_error (error,
|
||||
THRIFT_TRANSPORT_ERROR,
|
||||
THRIFT_TRANSPORT_ERROR_MAX_MESSAGE_SIZE_REACHED,
|
||||
"Recived an oversized frame,");
|
||||
return result;
|
||||
}
|
||||
|
||||
/* create a buffer to hold the data and read that much data */
|
||||
tmpdata = g_new0 (guchar, 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;
|
||||
}
|
||||
g_free (tmpdata);
|
||||
}
|
||||
|
||||
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);
|
||||
ThriftTransportClass *ttc = THRIFT_TRANSPORT_GET_CLASS (transport);
|
||||
|
||||
if(!ttc->checkReadBytesAvailable (transport, len, error))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
ThriftTransportClass *ttc = THRIFT_TRANSPORT_GET_CLASS (transport);
|
||||
gint32 sz_hbo, sz_nbo;
|
||||
guchar *tmpdata;
|
||||
|
||||
if(!ttc->resetConsumedMessageSize (transport, -1, error))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* 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_new0 (guchar, 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);
|
||||
g_free (tmpdata);
|
||||
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 ();
|
||||
transport->max_frame_size = DEFAULT_MAX_FRAME_SIZE;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
ThriftTransport *tt = THRIFT_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;
|
||||
case PROP_THRIFT_FRAMED_TRANSPORT_CONFIGURATION:
|
||||
g_value_set_object (value, tt->configuration);
|
||||
break;
|
||||
case PROP_THRIFT_FRAMED_TRANSPORT_REMAINING_MESSAGE_SIZE:
|
||||
g_value_set_long (value, tt->remainingMessageSize_);
|
||||
break;
|
||||
case PROP_THRIFT_FRAMED_TRANSPORT_KNOW_MESSAGE_SIZE:
|
||||
g_value_set_long (value, tt->knowMessageSize_);
|
||||
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);
|
||||
ThriftTransport *tt = THRIFT_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;
|
||||
case PROP_THRIFT_FRAMED_TRANSPORT_CONFIGURATION:
|
||||
tt->configuration = g_value_dup_object (value);
|
||||
if (tt->configuration != NULL)
|
||||
{
|
||||
transport->max_frame_size = tt->configuration->maxFrameSize_;
|
||||
}
|
||||
break;
|
||||
case PROP_THRIFT_FRAMED_TRANSPORT_REMAINING_MESSAGE_SIZE:
|
||||
tt->remainingMessageSize_ = g_value_get_long (value);
|
||||
break;
|
||||
case PROP_THRIFT_FRAMED_TRANSPORT_KNOW_MESSAGE_SIZE:
|
||||
tt->knowMessageSize_ = g_value_get_long (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);
|
||||
|
||||
param_spec = g_param_spec_object ("configuration", "configuration (construct)",
|
||||
"Thrift Configuration",
|
||||
THRIFT_TYPE_CONFIGURATION,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_THRIFT_FRAMED_TRANSPORT_CONFIGURATION,
|
||||
param_spec);
|
||||
|
||||
param_spec = g_param_spec_long ("remainingmessagesize",
|
||||
"remainingmessagesize (construct)",
|
||||
"Set the remaining message size",
|
||||
0, /* min */
|
||||
G_MAXINT32, /* max */
|
||||
DEFAULT_MAX_MESSAGE_SIZE, /* default by construct */
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_THRIFT_FRAMED_TRANSPORT_REMAINING_MESSAGE_SIZE,
|
||||
param_spec);
|
||||
|
||||
param_spec = g_param_spec_long ("knowmessagesize",
|
||||
"knowmessagesize (construct)",
|
||||
"Set the known size of the message",
|
||||
0, /* min */
|
||||
G_MAXINT32, /* max */
|
||||
DEFAULT_MAX_MESSAGE_SIZE, /* default by construct */
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_THRIFT_FRAMED_TRANSPORT_KNOW_MESSAGE_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;
|
||||
}
|
||||
@@ -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_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 */
|
||||
guint32 max_frame_size;
|
||||
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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 */
|
||||
@@ -0,0 +1,349 @@
|
||||
/*
|
||||
* 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 <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <thrift/c_glib/thrift.h>
|
||||
#include <thrift/c_glib/thrift_configuration.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,
|
||||
PROP_THRIFT_MEMORY_BUFFER_CONFIGURATION,
|
||||
PROP_THRIFT_MEMORY_BUFFER_REMAINING_MESSAGE_SIZE,
|
||||
PROP_THRIFT_MEMORY_BUFFER_KNOW_MESSAGE_SIZE
|
||||
};
|
||||
|
||||
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);
|
||||
ThriftTransportClass *ttc = THRIFT_TRANSPORT_GET_CLASS (transport);
|
||||
|
||||
guint32 give = len;
|
||||
|
||||
if(!ttc->checkReadBytesAvailable (transport, len, error))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
|
||||
ThriftTransport *tt = THRIFT_TRANSPORT (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;
|
||||
case PROP_THRIFT_MEMORY_BUFFER_CONFIGURATION:
|
||||
g_value_set_object (value, tt->configuration);
|
||||
break;
|
||||
case PROP_THRIFT_MEMORY_BUFFER_REMAINING_MESSAGE_SIZE:
|
||||
g_value_set_long (value, tt->remainingMessageSize_);
|
||||
break;
|
||||
case PROP_THRIFT_MEMORY_BUFFER_KNOW_MESSAGE_SIZE:
|
||||
g_value_set_long (value, tt->knowMessageSize_);
|
||||
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);
|
||||
|
||||
ThriftTransport *tt = THRIFT_TRANSPORT (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;
|
||||
case PROP_THRIFT_MEMORY_BUFFER_CONFIGURATION:
|
||||
tt->configuration = g_value_dup_object (value);
|
||||
break;
|
||||
case PROP_THRIFT_MEMORY_BUFFER_REMAINING_MESSAGE_SIZE:
|
||||
tt->remainingMessageSize_ = g_value_get_long (value);
|
||||
break;
|
||||
case PROP_THRIFT_MEMORY_BUFFER_KNOW_MESSAGE_SIZE:
|
||||
tt->knowMessageSize_ = g_value_get_long (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);
|
||||
|
||||
param_spec = g_param_spec_object ("configuration",
|
||||
"configuration (construct)",
|
||||
"Thrift Configuration",
|
||||
THRIFT_TYPE_CONFIGURATION,
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_READWRITE);
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_THRIFT_MEMORY_BUFFER_CONFIGURATION,
|
||||
param_spec);
|
||||
|
||||
param_spec = g_param_spec_long ("remainingmessagesize",
|
||||
"remainingmessagesize (construct)",
|
||||
"Set the remaining message size",
|
||||
0, /* min */
|
||||
G_MAXINT32, /* max */
|
||||
DEFAULT_MAX_MESSAGE_SIZE, /* default by construct */
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_THRIFT_MEMORY_BUFFER_REMAINING_MESSAGE_SIZE,
|
||||
param_spec);
|
||||
|
||||
param_spec = g_param_spec_long ("knowmessagesize",
|
||||
"knowmessagesize (construct)",
|
||||
"Set the known size of the message",
|
||||
0, /* min */
|
||||
G_MAXINT32, /* max */
|
||||
DEFAULT_MAX_MESSAGE_SIZE, /* default by construct */
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_THRIFT_MEMORY_BUFFER_KNOW_MESSAGE_SIZE,
|
||||
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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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_ */
|
||||
@@ -0,0 +1,377 @@
|
||||
/*
|
||||
* 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,
|
||||
PROP_THRIFT_SERVER_SOCKET_CONFIGURATION,
|
||||
PROP_THRIFT_SERVER_SOCKET_REMAINING_MESSAGE_SIZE,
|
||||
PROP_THRIFT_SERVER_SOCKET_KNOW_MESSAGE_SIZE
|
||||
};
|
||||
|
||||
/* 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));
|
||||
close (tsocket->sd);
|
||||
tsocket->sd = THRIFT_INVALID_SOCKET;
|
||||
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));
|
||||
close (tsocket->sd);
|
||||
tsocket->sd = THRIFT_INVALID_SOCKET;
|
||||
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));
|
||||
close (tsocket->sd);
|
||||
tsocket->sd = THRIFT_INVALID_SOCKET;
|
||||
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 listen to path %s: - %s",
|
||||
tsocket->path, strerror(errno));
|
||||
}
|
||||
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));
|
||||
}
|
||||
close (tsocket->sd);
|
||||
tsocket->sd = THRIFT_INVALID_SOCKET;
|
||||
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);
|
||||
ThriftServerTransport *tst = THRIFT_SERVER_TRANSPORT (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 NULL;
|
||||
}
|
||||
|
||||
if(tst->configuration != NULL)
|
||||
{
|
||||
socket = g_object_new (THRIFT_TYPE_SOCKET, "configuration", tst->configuration,
|
||||
"remainingmessagesize", tst->configuration->maxMessageSize_,
|
||||
"knowmessagesize", tst->configuration->maxMessageSize_, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
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);
|
||||
ThriftServerTransport *transport = THRIFT_SERVER_TRANSPORT (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;
|
||||
case PROP_THRIFT_SERVER_SOCKET_CONFIGURATION:
|
||||
g_value_set_object (value, transport->configuration);
|
||||
break;
|
||||
case PROP_THRIFT_SERVER_SOCKET_REMAINING_MESSAGE_SIZE:
|
||||
g_value_set_long (value, transport->remainingMessageSize_);
|
||||
break;
|
||||
case PROP_THRIFT_SERVER_SOCKET_KNOW_MESSAGE_SIZE:
|
||||
g_value_set_long (value, transport->knowMessageSize_);
|
||||
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);
|
||||
ThriftServerTransport *transport = THRIFT_SERVER_TRANSPORT (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;
|
||||
case PROP_THRIFT_SERVER_SOCKET_CONFIGURATION:
|
||||
transport->configuration = g_value_dup_object (value);
|
||||
break;
|
||||
case PROP_THRIFT_SERVER_SOCKET_REMAINING_MESSAGE_SIZE:
|
||||
transport->remainingMessageSize_ = g_value_get_long (value);
|
||||
break;
|
||||
case PROP_THRIFT_SERVER_SOCKET_KNOW_MESSAGE_SIZE:
|
||||
transport->knowMessageSize_ = g_value_get_long (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);
|
||||
|
||||
param_spec = g_param_spec_object ("configuration",
|
||||
"configuration (construct)",
|
||||
"Thtift Configuration",
|
||||
THRIFT_TYPE_CONFIGURATION,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_THRIFT_SERVER_SOCKET_CONFIGURATION,
|
||||
param_spec);
|
||||
|
||||
param_spec = g_param_spec_long ("remainingmessagesize",
|
||||
"remainingmessagesize (construct)",
|
||||
"Set the remaining message size",
|
||||
0, /* min */
|
||||
G_MAXINT32, /* max */
|
||||
DEFAULT_MAX_MESSAGE_SIZE, /* default by construct */
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_THRIFT_SERVER_SOCKET_REMAINING_MESSAGE_SIZE,
|
||||
param_spec);
|
||||
|
||||
param_spec = g_param_spec_long ("knowmessagesize",
|
||||
"knowmessagesize (construct)",
|
||||
"Set the known size of the message",
|
||||
0, /* min */
|
||||
G_MAXINT32, /* max */
|
||||
DEFAULT_MAX_MESSAGE_SIZE, /* default by construct */
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_THRIFT_SERVER_SOCKET_KNOW_MESSAGE_SIZE,
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -0,0 +1,253 @@
|
||||
/*
|
||||
* 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>
|
||||
|
||||
/* object properties */
|
||||
enum _ThriftServerTransportProperties
|
||||
{
|
||||
PROP_0,
|
||||
PROP_THRIFT_SERVER_TRANSPORT_CONFIGURATION,
|
||||
PROP_THRIFT_SERVER_TRANSPORT_REMAINING_MESSAGE_SIZE,
|
||||
PROP_THRIFT_SERVER_TRANSPORT_KNOW_MESSAGE_SIZE
|
||||
};
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE(ThriftServerTransport, thrift_server_transport, G_TYPE_OBJECT)
|
||||
|
||||
gboolean
|
||||
thrift_server_transport_updateKnownMessageSize(ThriftServerTransport *transport, glong size, GError **error)
|
||||
{
|
||||
gboolean boolean = TRUE;
|
||||
ThriftServerTransport *tst = THRIFT_SERVER_TRANSPORT (transport);
|
||||
ThriftServerTransportClass *tstc = THRIFT_SERVER_TRANSPORT_GET_CLASS (transport);
|
||||
glong consumed = tst->knowMessageSize_ - tst->remainingMessageSize_;
|
||||
if(!tstc->resetConsumedMessageSize (transport, size, error))
|
||||
{
|
||||
boolean = FALSE;
|
||||
}
|
||||
if(!tstc->countConsumedMessageBytes (transport, consumed, error))
|
||||
{
|
||||
boolean = FALSE;
|
||||
}
|
||||
return boolean;
|
||||
}
|
||||
|
||||
gboolean
|
||||
thrift_server_transport_checkReadBytesAvailable(ThriftServerTransport *transport, glong numBytes, GError **error)
|
||||
{
|
||||
gboolean boolean = TRUE;
|
||||
ThriftServerTransport *tst = THRIFT_SERVER_TRANSPORT (transport);
|
||||
if(tst->remainingMessageSize_ < numBytes)
|
||||
{
|
||||
g_set_error(error,
|
||||
THRIFT_TRANSPORT_ERROR,
|
||||
THRIFT_TRANSPORT_ERROR_MAX_MESSAGE_SIZE_REACHED,
|
||||
"MaxMessageSize reached");
|
||||
boolean = FALSE;
|
||||
}
|
||||
|
||||
return boolean;
|
||||
}
|
||||
|
||||
gboolean
|
||||
thrift_server_transport_resetConsumedMessageSize(ThriftServerTransport *transport, glong newSize, GError **error)
|
||||
{
|
||||
ThriftServerTransport *tst = THRIFT_SERVER_TRANSPORT (transport);
|
||||
if(newSize < 0)
|
||||
{
|
||||
if(tst->configuration != NULL)
|
||||
{
|
||||
tst->knowMessageSize_ = tst->configuration->maxMessageSize_;
|
||||
tst->remainingMessageSize_ = tst->configuration->maxMessageSize_;
|
||||
}
|
||||
else
|
||||
{
|
||||
tst->knowMessageSize_ = DEFAULT_MAX_MESSAGE_SIZE;
|
||||
tst->remainingMessageSize_ = DEFAULT_MAX_MESSAGE_SIZE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
/* update only: message size can shrink, but not grow */
|
||||
if(newSize > tst->knowMessageSize_)
|
||||
{
|
||||
g_set_error(error,
|
||||
THRIFT_TRANSPORT_ERROR,
|
||||
THRIFT_TRANSPORT_ERROR_MAX_MESSAGE_SIZE_REACHED,
|
||||
"MaxMessageSize reached");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
tst->knowMessageSize_ = newSize;
|
||||
tst->remainingMessageSize_ = newSize;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
thrift_server_transport_countConsumedMessageBytes(ThriftServerTransport *transport, glong numBytes, GError **error)
|
||||
{
|
||||
ThriftServerTransport *tst = THRIFT_SERVER_TRANSPORT (transport);
|
||||
if(tst->remainingMessageSize_ > numBytes)
|
||||
{
|
||||
tst->remainingMessageSize_ -= numBytes;
|
||||
}
|
||||
else
|
||||
{
|
||||
tst->remainingMessageSize_ = 0;
|
||||
if(*error == NULL)
|
||||
{
|
||||
g_set_error(error,
|
||||
THRIFT_TRANSPORT_ERROR,
|
||||
THRIFT_TRANSPORT_ERROR_MAX_MESSAGE_SIZE_REACHED,
|
||||
"MaxMessageSize reached");
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* property accesor */
|
||||
void
|
||||
thrift_server_transport_get_property(GObject *object, guint property_id,
|
||||
GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
ThriftServerTransport *transport = THRIFT_SERVER_TRANSPORT (object);
|
||||
|
||||
THRIFT_UNUSED_VAR (pspec);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_THRIFT_SERVER_TRANSPORT_CONFIGURATION:
|
||||
g_value_set_object (value, transport->configuration);
|
||||
break;
|
||||
case PROP_THRIFT_SERVER_TRANSPORT_REMAINING_MESSAGE_SIZE:
|
||||
g_value_set_long (value, transport->remainingMessageSize_);
|
||||
break;
|
||||
case PROP_THRIFT_SERVER_TRANSPORT_KNOW_MESSAGE_SIZE:
|
||||
g_value_set_long (value, transport->knowMessageSize_);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* property mutator */
|
||||
void
|
||||
thrift_server_transport_set_property (GObject *object, guint property_id,
|
||||
const GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
ThriftServerTransport *transport = THRIFT_SERVER_TRANSPORT (object);
|
||||
|
||||
THRIFT_UNUSED_VAR (pspec);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_THRIFT_SERVER_TRANSPORT_CONFIGURATION:
|
||||
transport->configuration = g_value_dup_object (value);
|
||||
break;
|
||||
case PROP_THRIFT_SERVER_TRANSPORT_REMAINING_MESSAGE_SIZE:
|
||||
transport->remainingMessageSize_ = g_value_get_long (value);
|
||||
break;
|
||||
case PROP_THRIFT_SERVER_TRANSPORT_KNOW_MESSAGE_SIZE:
|
||||
transport->knowMessageSize_ = g_value_get_long (value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* base initializer for the server transport interface */
|
||||
static void
|
||||
thrift_server_transport_class_init (ThriftServerTransportClass *c)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (c);
|
||||
ThriftServerTransportClass *tstc = THRIFT_SERVER_TRANSPORT_CLASS (c);
|
||||
GParamSpec *param_spec = NULL;
|
||||
|
||||
/* setup accessors and mutators */
|
||||
gobject_class->get_property = thrift_server_transport_get_property;
|
||||
gobject_class->set_property = thrift_server_transport_set_property;
|
||||
|
||||
param_spec = g_param_spec_object ("configuration",
|
||||
"configuration (construct)",
|
||||
"Thrift Configuration",
|
||||
THRIFT_TYPE_CONFIGURATION,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_THRIFT_SERVER_TRANSPORT_CONFIGURATION,
|
||||
param_spec);
|
||||
|
||||
param_spec = g_param_spec_long ("remainingmessagesize",
|
||||
"remainingmessagesize (construct)",
|
||||
"Set the remaining message size",
|
||||
0, /* min */
|
||||
G_MAXINT32, /* max */
|
||||
DEFAULT_MAX_MESSAGE_SIZE, /* default by construct */
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_THRIFT_SERVER_TRANSPORT_REMAINING_MESSAGE_SIZE,
|
||||
param_spec);
|
||||
|
||||
param_spec = g_param_spec_long ("knowmessagesize",
|
||||
"knowmessagesize (construct)",
|
||||
"Set the known size of the message",
|
||||
0, /* min */
|
||||
G_MAXINT32, /* max */
|
||||
DEFAULT_MAX_MESSAGE_SIZE, /* default by construct */
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_THRIFT_SERVER_TRANSPORT_KNOW_MESSAGE_SIZE,
|
||||
param_spec);
|
||||
|
||||
c->listen = thrift_server_transport_listen;
|
||||
c->accept = thrift_server_transport_accept;
|
||||
c->close = thrift_server_transport_close;
|
||||
tstc->updateKnownMessageSize = thrift_server_transport_updateKnownMessageSize;
|
||||
tstc->checkReadBytesAvailable = thrift_server_transport_checkReadBytesAvailable;
|
||||
tstc->resetConsumedMessageSize = thrift_server_transport_resetConsumedMessageSize;
|
||||
tstc->countConsumedMessageBytes = thrift_server_transport_countConsumedMessageBytes;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/* protected */
|
||||
ThriftConfiguration *configuration;
|
||||
glong remainingMessageSize_;
|
||||
glong knowMessageSize_;
|
||||
};
|
||||
|
||||
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);
|
||||
gboolean (*updateKnownMessageSize) (ThriftServerTransport *transport, glong size, GError **error);
|
||||
gboolean (*checkReadBytesAvailable) (ThriftServerTransport *transport, glong numBytes, GError **error);
|
||||
gboolean (*resetConsumedMessageSize) (ThriftServerTransport *transport, glong newSize, GError **error);
|
||||
gboolean (*countConsumedMessageBytes) (ThriftServerTransport *transport, glong numBytes, 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 */
|
||||
@@ -0,0 +1,489 @@
|
||||
/*
|
||||
* 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/thrift_configuration.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,
|
||||
PROP_THRIFT_SOCKET_CONFIGURATION,
|
||||
PROP_THRIFT_SOCKET_REMAINING_MESSAGE_SIZE,
|
||||
PROP_THRIFT_SOCKET_KNOW_MESSAGE_SIZE
|
||||
};
|
||||
|
||||
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;
|
||||
int errno_copy;
|
||||
#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)
|
||||
{
|
||||
errno_copy = errno;
|
||||
thrift_socket_close(transport, NULL);
|
||||
g_set_error (error, THRIFT_TRANSPORT_ERROR, THRIFT_TRANSPORT_ERROR_CONNECT,
|
||||
"failed to connect to path %s: - %s",
|
||||
tsocket->path, strerror(errno_copy));
|
||||
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)
|
||||
{
|
||||
errno_copy = errno;
|
||||
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_copy));
|
||||
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);
|
||||
ThriftTransportClass *ttc = THRIFT_TRANSPORT_GET_CLASS (transport);
|
||||
if(!ttc->checkReadBytesAvailable (transport, len, error))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
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);
|
||||
ThriftTransport *tt = THRIFT_TRANSPORT (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;
|
||||
case PROP_THRIFT_SOCKET_CONFIGURATION:
|
||||
g_value_set_object (value, tt->configuration);
|
||||
break;
|
||||
case PROP_THRIFT_SOCKET_REMAINING_MESSAGE_SIZE:
|
||||
g_value_set_long (value, tt->remainingMessageSize_);
|
||||
break;
|
||||
case PROP_THRIFT_SOCKET_KNOW_MESSAGE_SIZE:
|
||||
g_value_set_long (value, tt->knowMessageSize_);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* property mutator */
|
||||
void
|
||||
thrift_socket_set_property (GObject *object, guint property_id,
|
||||
const GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
ThriftSocket *socket = THRIFT_SOCKET (object);
|
||||
ThriftTransport *tt = THRIFT_TRANSPORT (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;
|
||||
case PROP_THRIFT_SOCKET_CONFIGURATION:
|
||||
tt->configuration = g_value_dup_object (value);
|
||||
break;
|
||||
case PROP_THRIFT_SOCKET_REMAINING_MESSAGE_SIZE:
|
||||
tt->remainingMessageSize_ = g_value_get_long (value);
|
||||
break;
|
||||
case PROP_THRIFT_SOCKET_KNOW_MESSAGE_SIZE:
|
||||
tt->knowMessageSize_ = g_value_get_long (value);
|
||||
}
|
||||
}
|
||||
|
||||
/* 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);
|
||||
|
||||
param_spec = g_param_spec_object ("configuration",
|
||||
"configuration",
|
||||
"Thrift Configuration",
|
||||
THRIFT_TYPE_CONFIGURATION,
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_READWRITE);
|
||||
g_object_class_install_property (gobject_class, PROP_THRIFT_SOCKET_CONFIGURATION,
|
||||
param_spec);
|
||||
|
||||
param_spec = g_param_spec_long ("remainingmessagesize",
|
||||
"remainingmessagesize (construct)",
|
||||
"Set the remaining message size",
|
||||
0, /* min */
|
||||
G_MAXINT32, /* max */
|
||||
DEFAULT_MAX_MESSAGE_SIZE, /* default by construct */
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_THRIFT_SOCKET_REMAINING_MESSAGE_SIZE,
|
||||
param_spec);
|
||||
|
||||
param_spec = g_param_spec_long ("knowmessagesize",
|
||||
"knowmessagesize (construct)",
|
||||
"Set the known size of the message",
|
||||
0, /* min */
|
||||
G_MAXINT32, /* max */
|
||||
DEFAULT_MAX_MESSAGE_SIZE, /* default by construct */
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_THRIFT_SOCKET_KNOW_MESSAGE_SIZE,
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* Check if the socket is open and ready to send and receive
|
||||
* @param transport
|
||||
* @return true if open
|
||||
*/
|
||||
gboolean
|
||||
thrift_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_socket_open (ThriftTransport *transport, GError **error);
|
||||
|
||||
/**
|
||||
* Close connection if required
|
||||
* @param transport
|
||||
* @param error
|
||||
* @return true if operation was correct
|
||||
*/
|
||||
gboolean
|
||||
thrift_socket_close (ThriftTransport *transport, GError **error);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,870 @@
|
||||
/*
|
||||
* 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/thrift_configuration.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,
|
||||
PROP_THRIFT_SSL_SOCKET_CONFIGURATION,
|
||||
PROP_THRIFT_SSL_SOCKET_REMAINING_MESSAGE_SIZE,
|
||||
PROP_THRIFT_SSL_SOCKET_KNOW_MESSAGE_SIZE,
|
||||
};
|
||||
|
||||
/* 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;
|
||||
|
||||
gboolean
|
||||
thrift_ssl_socket_authorize(ThriftTransport * transport, GError **error);
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
THRIFT_UNUSED_VAR (unk);
|
||||
THRIFT_UNUSED_VAR (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 gchar *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, "%X -> %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, "%X -> %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, "%X -> %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 gchar *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, (const guchar*)"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)
|
||||
{
|
||||
ThriftSSLSocket *ssl_socket = THRIFT_SSL_SOCKET(transport);
|
||||
if(ssl_socket!=NULL && ssl_socket->ssl) {
|
||||
SSL_shutdown(ssl_socket->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);
|
||||
gint32 bytes = 0;
|
||||
guint retries = 0;
|
||||
ThriftSocket *socket = THRIFT_SOCKET (transport);
|
||||
ThriftTransportClass *ttc = THRIFT_TRANSPORT_GET_CLASS (transport);
|
||||
if(!ttc->checkReadBytesAvailable (transport, len, error))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
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, (const guchar*)"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, (const guchar*)"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);
|
||||
|
||||
ThriftTransportClass *ttc = THRIFT_TRANSPORT_GET_CLASS (transport);
|
||||
if(!ttc->resetConsumedMessageSize(transport, -1, error))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_return_val_if_fail (socket->sd != THRIFT_INVALID_SOCKET && ssl_socket->ssl!=NULL, FALSE);
|
||||
|
||||
BIO* bio = SSL_get_wbio(ssl_socket->ssl);
|
||||
if (bio == NULL) {
|
||||
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, (const guchar*)"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);
|
||||
ThriftTransport *tt = THRIFT_TRANSPORT (object);
|
||||
|
||||
THRIFT_UNUSED_VAR (pspec);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_THRIFT_SSL_SOCKET_CONTEXT:
|
||||
g_value_set_pointer (value, socket->ctx);
|
||||
break;
|
||||
case PROP_THRIFT_SSL_SOCKET_CONFIGURATION:
|
||||
g_value_set_object (value, tt->configuration);
|
||||
break;
|
||||
case PROP_THRIFT_SSL_SOCKET_REMAINING_MESSAGE_SIZE:
|
||||
g_value_set_long (value, tt->remainingMessageSize_);
|
||||
break;
|
||||
case PROP_THRIFT_SSL_SOCKET_KNOW_MESSAGE_SIZE:
|
||||
g_value_set_long (value, tt->knowMessageSize_);
|
||||
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);
|
||||
ThriftTransport *tt = THRIFT_TRANSPORT (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;
|
||||
case PROP_THRIFT_SSL_SOCKET_CONFIGURATION:
|
||||
tt->configuration = g_value_dup_object (value);
|
||||
break;
|
||||
case PROP_THRIFT_SSL_SOCKET_REMAINING_MESSAGE_SIZE:
|
||||
tt->remainingMessageSize_ = g_value_get_long (value);
|
||||
break;
|
||||
case PROP_THRIFT_SSL_SOCKET_KNOW_MESSAGE_SIZE:
|
||||
tt->knowMessageSize_ = g_value_get_long (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);
|
||||
param_spec = g_param_spec_object ("configuration",
|
||||
"configuration (construct)",
|
||||
"Set the conguration of the transport",
|
||||
THRIFT_TYPE_CONFIGURATION, /* default value */
|
||||
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
|
||||
g_object_class_install_property (gobject_class, PROP_THRIFT_SSL_SOCKET_CONFIGURATION,
|
||||
param_spec);
|
||||
param_spec = g_param_spec_long ("remainingmessagesize",
|
||||
"remainingmessagesize (construct)",
|
||||
"Set the remaining message size",
|
||||
0, /* min */
|
||||
G_MAXINT32, /* max */
|
||||
DEFAULT_MAX_MESSAGE_SIZE, /* default by construct */
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_THRIFT_SSL_SOCKET_REMAINING_MESSAGE_SIZE,
|
||||
param_spec);
|
||||
param_spec = g_param_spec_long ("knowmessagesize",
|
||||
"knowmessagesize (construct)",
|
||||
"Set the known size of the message",
|
||||
0, /* min */
|
||||
G_MAXINT32, /* max */
|
||||
DEFAULT_MAX_MESSAGE_SIZE, /* default by construct */
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_THRIFT_SSL_SOCKET_KNOW_MESSAGE_SIZE,
|
||||
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((const guchar*)"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;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,230 @@
|
||||
/*
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* Close connection if required
|
||||
* @param transport
|
||||
* @param error
|
||||
* @return true if operation was correct
|
||||
*/
|
||||
gboolean
|
||||
thrift_ssl_socket_close (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);
|
||||
|
||||
gboolean
|
||||
thrift_ssl_socket_authorize(ThriftTransport * transport, GError **error);
|
||||
|
||||
G_END_DECLS
|
||||
#endif
|
||||
@@ -0,0 +1,370 @@
|
||||
/*
|
||||
* 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 <glib.h>
|
||||
#include <thrift/c_glib/thrift.h>
|
||||
#include <thrift/c_glib/transport/thrift_transport.h>
|
||||
#include <thrift/c_glib/thrift_configuration.h>
|
||||
|
||||
/* object properties */
|
||||
enum _ThriftTransportProperties
|
||||
{
|
||||
PROP_0,
|
||||
PROP_THRIFT_TRANSPORT_CONFIGURATION,
|
||||
PROP_THRIFT_TRANSPORT_REMAINING_MESSAGE_SIZE,
|
||||
PROP_THRIFT_TRANSPORT_KNOW_MESSAGE_SIZE
|
||||
};
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
gboolean
|
||||
thrift_transport_updateKnownMessageSize(ThriftTransport *transport, glong size, GError **error)
|
||||
{
|
||||
gboolean boolean = TRUE;
|
||||
ThriftTransport *tt = THRIFT_TRANSPORT (transport);
|
||||
ThriftTransportClass *ttc = THRIFT_TRANSPORT_GET_CLASS (transport);
|
||||
glong consumed = tt->knowMessageSize_ - tt->remainingMessageSize_;
|
||||
if(!ttc->resetConsumedMessageSize (transport, size, error))
|
||||
{
|
||||
boolean = FALSE;
|
||||
}
|
||||
if(!ttc->countConsumedMessageBytes (transport, consumed, error))
|
||||
{
|
||||
boolean = FALSE;
|
||||
}
|
||||
return boolean;
|
||||
}
|
||||
|
||||
gboolean
|
||||
thrift_transport_checkReadBytesAvailable(ThriftTransport *transport, glong numBytes, GError **error)
|
||||
{
|
||||
gboolean boolean = TRUE;
|
||||
ThriftTransport *tt = THRIFT_TRANSPORT (transport);
|
||||
if(tt->remainingMessageSize_ < numBytes)
|
||||
{
|
||||
g_set_error(error,
|
||||
THRIFT_TRANSPORT_ERROR,
|
||||
THRIFT_TRANSPORT_ERROR_MAX_MESSAGE_SIZE_REACHED,
|
||||
"MaxMessageSize reached");
|
||||
boolean = FALSE;
|
||||
}
|
||||
|
||||
return boolean;
|
||||
}
|
||||
|
||||
gboolean
|
||||
thrift_transport_resetConsumedMessageSize(ThriftTransport *transport, glong newSize, GError **error)
|
||||
{
|
||||
ThriftTransport *tt = THRIFT_TRANSPORT (transport);
|
||||
if(newSize < 0)
|
||||
{
|
||||
if(tt->configuration != NULL)
|
||||
{
|
||||
tt->knowMessageSize_ = tt->configuration->maxMessageSize_;
|
||||
tt->remainingMessageSize_ = tt->configuration->maxMessageSize_;
|
||||
}
|
||||
else
|
||||
{
|
||||
tt->knowMessageSize_ = DEFAULT_MAX_MESSAGE_SIZE;
|
||||
tt->remainingMessageSize_ = DEFAULT_MAX_MESSAGE_SIZE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
/* update only: message size can shrink, but not grow */
|
||||
if(newSize > tt->knowMessageSize_)
|
||||
{
|
||||
g_set_error(error,
|
||||
THRIFT_TRANSPORT_ERROR,
|
||||
THRIFT_TRANSPORT_ERROR_MAX_MESSAGE_SIZE_REACHED,
|
||||
"MaxMessageSize reached");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
tt->knowMessageSize_ = newSize;
|
||||
tt->remainingMessageSize_ = newSize;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
thrift_transport_countConsumedMessageBytes(ThriftTransport *transport, glong numBytes, GError **error)
|
||||
{
|
||||
ThriftTransport *tt = THRIFT_TRANSPORT (transport);
|
||||
if(tt->remainingMessageSize_ > numBytes)
|
||||
{
|
||||
tt->remainingMessageSize_ -= numBytes;
|
||||
}
|
||||
else
|
||||
{
|
||||
tt->remainingMessageSize_ = 0;
|
||||
g_set_error(error,
|
||||
THRIFT_TRANSPORT_ERROR,
|
||||
THRIFT_TRANSPORT_ERROR_MAX_MESSAGE_SIZE_REACHED,
|
||||
"MaxMessageSize reached");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* property accesor */
|
||||
void
|
||||
thrift_transport_get_property(GObject *object, guint property_id,
|
||||
GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
ThriftTransport *transport = THRIFT_TRANSPORT (object);
|
||||
|
||||
THRIFT_UNUSED_VAR (pspec);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_THRIFT_TRANSPORT_CONFIGURATION:
|
||||
g_value_set_object (value, transport->configuration);
|
||||
break;
|
||||
case PROP_THRIFT_TRANSPORT_REMAINING_MESSAGE_SIZE:
|
||||
g_value_set_long (value, transport->remainingMessageSize_);
|
||||
break;
|
||||
case PROP_THRIFT_TRANSPORT_KNOW_MESSAGE_SIZE:
|
||||
g_value_set_long (value, transport->knowMessageSize_);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* property mutator */
|
||||
void
|
||||
thrift_transport_set_property (GObject *object, guint property_id,
|
||||
const GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
ThriftTransport *transport = THRIFT_TRANSPORT (object);
|
||||
|
||||
THRIFT_UNUSED_VAR (pspec);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_THRIFT_TRANSPORT_CONFIGURATION:
|
||||
transport->configuration = g_value_get_object (value);
|
||||
break;
|
||||
case PROP_THRIFT_TRANSPORT_REMAINING_MESSAGE_SIZE:
|
||||
transport->remainingMessageSize_ = g_value_get_long (value);
|
||||
break;
|
||||
case PROP_THRIFT_TRANSPORT_KNOW_MESSAGE_SIZE:
|
||||
transport->knowMessageSize_ = g_value_get_long (value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* define the GError domain for Thrift transports */
|
||||
GQuark
|
||||
thrift_transport_error_quark (void)
|
||||
{
|
||||
return g_quark_from_static_string (THRIFT_TRANSPORT_ERROR_DOMAIN);
|
||||
}
|
||||
|
||||
static void
|
||||
thrift_transport_dispose (GObject *gobject)
|
||||
{
|
||||
ThriftTransport *self = THRIFT_TRANSPORT (gobject);
|
||||
|
||||
if(self->configuration != NULL)
|
||||
g_clear_object (&self->configuration);
|
||||
|
||||
/* 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_transport_parent_class)->dispose (gobject);
|
||||
}
|
||||
|
||||
/* class initializer for ThriftTransport */
|
||||
static void
|
||||
thrift_transport_class_init (ThriftTransportClass *cls)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (cls);
|
||||
GParamSpec *param_spec = NULL;
|
||||
|
||||
/* setup accessors and mutators */
|
||||
gobject_class->get_property = thrift_transport_get_property;
|
||||
gobject_class->set_property = thrift_transport_set_property;
|
||||
gobject_class->dispose = thrift_transport_dispose;
|
||||
|
||||
param_spec = g_param_spec_object ("configuration",
|
||||
"configuration (construct)",
|
||||
"Thrift Configuration",
|
||||
THRIFT_TYPE_CONFIGURATION,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_THRIFT_TRANSPORT_CONFIGURATION,
|
||||
param_spec);
|
||||
|
||||
param_spec = g_param_spec_long ("remainingmessagesize",
|
||||
"remainingmessagesize (construct)",
|
||||
"Set the remaining message size",
|
||||
0, /* min */
|
||||
G_MAXINT32, /* max */
|
||||
DEFAULT_MAX_MESSAGE_SIZE, /* default by construct */
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_THRIFT_TRANSPORT_REMAINING_MESSAGE_SIZE,
|
||||
param_spec);
|
||||
|
||||
param_spec = g_param_spec_long ("knowmessagesize",
|
||||
"knowmessagesize (construct)",
|
||||
"Set the known size of the message",
|
||||
0, /* min */
|
||||
G_MAXINT32, /* max */
|
||||
DEFAULT_MAX_MESSAGE_SIZE, /* default by construct */
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_THRIFT_TRANSPORT_KNOW_MESSAGE_SIZE,
|
||||
param_spec);
|
||||
|
||||
|
||||
/* 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;
|
||||
|
||||
cls->updateKnownMessageSize = thrift_transport_updateKnownMessageSize;
|
||||
cls->checkReadBytesAvailable = thrift_transport_checkReadBytesAvailable;
|
||||
cls->resetConsumedMessageSize = thrift_transport_resetConsumedMessageSize;
|
||||
cls->countConsumedMessageBytes = thrift_transport_countConsumedMessageBytes;
|
||||
}
|
||||
|
||||
static void
|
||||
thrift_transport_init (ThriftTransport *transport)
|
||||
{
|
||||
THRIFT_UNUSED_VAR (transport);
|
||||
}
|
||||
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
* 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>
|
||||
|
||||
#include <thrift/c_glib/thrift_configuration.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;
|
||||
|
||||
/* protected */
|
||||
ThriftConfiguration *configuration;
|
||||
glong remainingMessageSize_;
|
||||
glong knowMessageSize_;
|
||||
};
|
||||
|
||||
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);
|
||||
gboolean (*updateKnownMessageSize) (ThriftTransport *transport, glong size, GError **error);
|
||||
gboolean (*checkReadBytesAvailable) (ThriftTransport *transport, glong numBytes, GError **error);
|
||||
gboolean (*resetConsumedMessageSize) (ThriftTransport *transport, glong newSize, GError **error);
|
||||
gboolean (*countConsumedMessageBytes) (ThriftTransport *transport, glong numBytes, 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,
|
||||
THRIFT_TRANSPORT_ERROR_MAX_MESSAGE_SIZE_REACHED
|
||||
} 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 */
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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 */
|
||||
@@ -0,0 +1,783 @@
|
||||
/*
|
||||
* 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 <stdio.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_zlib_transport.h>
|
||||
|
||||
#define DEFAULT_URBUF_SIZE 128
|
||||
#define DEFAULT_CRBUF_SIZE 1024
|
||||
#define DEFAULT_UWBUF_SIZE 128
|
||||
#define DEFAULT_CWBUF_SIZE 1024
|
||||
#define MIN_DIRECT_DEFLATE_SIZE 32
|
||||
|
||||
/* object properties */
|
||||
enum _ThriftZlibTransportProperties
|
||||
{
|
||||
PROP_0,
|
||||
PROP_THRIFT_ZLIB_TRANSPORT_TRANSPORT,
|
||||
PROP_THRIFT_ZLIB_TRANSPORT_URBUF_SIZE,
|
||||
PROP_THRIFT_ZLIB_TRANSPORT_CRBUF_SIZE,
|
||||
PROP_THRIFT_ZLIB_TRANSPORT_UWBUF_SIZE,
|
||||
PROP_THRIFT_ZLIB_TRANSPORT_CWBUF_SIZE,
|
||||
PROP_THRIFT_ZLIB_TRANSPORT_COMP_LEVEL,
|
||||
PROP_THRIFT_ZLIB_TRANSPORT_CONFIGURATION,
|
||||
PROP_THRIFT_ZLIB_TRANSPORT_REMAINING_MESSAGE_SIZE,
|
||||
PROP_THRIFT_ZLIB_TRANSPORT_KNOW_MESSAGE_SIZE
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (ThriftZlibTransport, thrift_zlib_transport, THRIFT_TYPE_TRANSPORT)
|
||||
|
||||
/*! READING STRATEGY
|
||||
* We have two buffers for reading: one containing the compressed data (crbuf)
|
||||
* and one containing the uncompressed data (urbuf). When read is called,
|
||||
* we repeat the following steps until we have satisfied the request:
|
||||
* - Copy data from urbuf into the caller's buffer.
|
||||
* - If we had enough, return.
|
||||
* - If urbuf is empty, read some data into it from the underlying transport.
|
||||
* - Inflate data from crbuf into urbuf.
|
||||
*
|
||||
* In standalone object, we set input_end to true when inflate returns
|
||||
* Z_STREAM_END. This allows to make sure that a checksum was verified.
|
||||
*/
|
||||
int
|
||||
thrift_zlib_transport_read_avail (ThriftTransport *transport)
|
||||
{
|
||||
ThriftZlibTransport *t = THRIFT_ZLIB_TRANSPORT (transport);
|
||||
return t->urbuf_size - t->rstream->avail_out - t->urpos;
|
||||
}
|
||||
|
||||
/* overrides thrift_transport_is_open */
|
||||
gboolean
|
||||
thrift_zlib_transport_is_open (ThriftTransport *transport)
|
||||
{
|
||||
ThriftZlibTransport *t = THRIFT_ZLIB_TRANSPORT (transport);
|
||||
return (thrift_zlib_transport_read_avail (transport) > 0) || \
|
||||
(t->rstream->avail_in > 0) || THRIFT_TRANSPORT_GET_CLASS (t->transport)->is_open (t->transport);
|
||||
}
|
||||
|
||||
/* overrides thrift_transport_peek */
|
||||
gboolean
|
||||
thrift_zlib_transport_peek (ThriftTransport *transport, GError **error)
|
||||
{
|
||||
ThriftZlibTransport *t = THRIFT_ZLIB_TRANSPORT (transport);
|
||||
return (thrift_zlib_transport_read_avail (transport) > 0) || \
|
||||
(t->rstream->avail_in > 0) || THRIFT_TRANSPORT_GET_CLASS (t->transport)->peek (t->transport, error);
|
||||
}
|
||||
|
||||
/* implements thrift_transport_open */
|
||||
gboolean
|
||||
thrift_zlib_transport_open (ThriftTransport *transport, GError **error)
|
||||
{
|
||||
ThriftZlibTransport *t = THRIFT_ZLIB_TRANSPORT (transport);
|
||||
return THRIFT_TRANSPORT_GET_CLASS (t->transport)->open (t->transport, error);
|
||||
}
|
||||
|
||||
/* implements thrift_transport_close */
|
||||
gboolean
|
||||
thrift_zlib_transport_close (ThriftTransport *transport, GError **error)
|
||||
{
|
||||
ThriftZlibTransport *t = THRIFT_ZLIB_TRANSPORT (transport);
|
||||
return THRIFT_TRANSPORT_GET_CLASS (t->transport)->close (t->transport, error);
|
||||
}
|
||||
|
||||
gint32
|
||||
thrift_zlib_transport_read_from_zlib(ThriftTransport *transport, GError **error)
|
||||
{
|
||||
ThriftZlibTransport *t = THRIFT_ZLIB_TRANSPORT (transport);
|
||||
gint32 got = 0;
|
||||
int zlib_rv = Z_OK;
|
||||
|
||||
if (t->input_ended) {
|
||||
/* If input end return error */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* If we don't have any more compressed data available,
|
||||
* read some from the underlying transport.
|
||||
*/
|
||||
got = THRIFT_TRANSPORT_GET_CLASS(t->transport)->read (t->transport, t->crbuf, 1, error);
|
||||
if (got < 0) {
|
||||
return -1;
|
||||
}
|
||||
t->rstream->next_in = t->crbuf;
|
||||
t->rstream->avail_in = got;
|
||||
|
||||
/* We have some compressed data now. Uncompress it. */
|
||||
zlib_rv = inflate (t->rstream, Z_SYNC_FLUSH);
|
||||
if (zlib_rv == Z_STREAM_END) {
|
||||
t->input_ended = TRUE;
|
||||
inflateEnd(t->rstream);
|
||||
return 0;
|
||||
} else {
|
||||
if (zlib_rv != Z_OK) {
|
||||
g_set_error (error, THRIFT_TRANSPORT_ERROR, THRIFT_TRANSPORT_ERROR_RECEIVE,
|
||||
"zlib error: %d (status = %s)", zlib_rv, t->rstream->msg);
|
||||
/* It must to return error */
|
||||
return -1;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* return 1 to continue to read */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* implements thrift_transport_read */
|
||||
gint32
|
||||
thrift_zlib_transport_read_slow (ThriftTransport *transport, gpointer buf,
|
||||
GError **error)
|
||||
{
|
||||
ThriftZlibTransport *t = THRIFT_ZLIB_TRANSPORT (transport);
|
||||
gint *buf_tmp = buf;
|
||||
gint32 need = 1;
|
||||
gint give;
|
||||
gint32 ret = 0;
|
||||
|
||||
while(TRUE)
|
||||
{
|
||||
if ((guint32)thrift_zlib_transport_read_avail (transport) < 1) {
|
||||
give = thrift_zlib_transport_read_avail (transport);
|
||||
} else {
|
||||
give = need;
|
||||
}
|
||||
memcpy (buf_tmp, t->urbuf+t->urpos, give);
|
||||
if (give > need) {
|
||||
need = 0;
|
||||
} else {
|
||||
need -= give;
|
||||
}
|
||||
buf_tmp += give;
|
||||
t->urpos += give;
|
||||
|
||||
/* If they were satisfied, we are done. */
|
||||
if (need == 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* If we will need to read from the underlying transport to get more data,
|
||||
* but we already have some data available, return it now. Reading from
|
||||
* the underlying transport may block, and read() is only allowed to block
|
||||
* when no data is available.
|
||||
*/
|
||||
if (need < 1 && t->rstream->avail_in == 0) {
|
||||
return give;
|
||||
}
|
||||
|
||||
/* If we get to this point, we need to get some more data. */
|
||||
|
||||
/* If zlib has reported the end of a stream, we can't really do any more. */
|
||||
if (t->input_ended) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* The uncompressed read buffer is empty, so reset the stream fields. */
|
||||
t->rstream->next_out = t->urbuf;
|
||||
t->rstream->avail_out = t->urbuf_size;
|
||||
t->urpos = 0;
|
||||
|
||||
/* Call inflate() to uncompress some more data. */
|
||||
if ((ret = thrift_zlib_transport_read_from_zlib(transport, error)) == 0) {
|
||||
/* no data available from underlying transport */
|
||||
return 1;
|
||||
} else {
|
||||
if (ret < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Okay. The read buffer should have whatever we can give it now. */
|
||||
/* Loop back to the start and try to give some more. */
|
||||
}
|
||||
|
||||
gint32
|
||||
thrift_zlib_transport_read (ThriftTransport *transport, gpointer buf,
|
||||
guint32 len, GError **error)
|
||||
{
|
||||
ThriftZlibTransport *t = THRIFT_ZLIB_TRANSPORT (transport);
|
||||
ThriftTransportClass *ttc = THRIFT_TRANSPORT_GET_CLASS (transport);
|
||||
guint32 i;
|
||||
gint32 ret;
|
||||
|
||||
if (!ttc->checkReadBytesAvailable (transport, len, error)){
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i=0; i < len; i=i+ret) {
|
||||
if ((ret = thrift_zlib_transport_read_slow (transport, ((char*)buf)+i, error)) < 0) {
|
||||
return ret;
|
||||
}
|
||||
if (t->input_ended)
|
||||
break;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/* implements thrift_transport_read_end
|
||||
* called when read is complete. nothing to do on our end. */
|
||||
gboolean
|
||||
thrift_zlib_transport_read_end (ThriftTransport *transport, GError **error)
|
||||
{
|
||||
/* satisfy -Wall */
|
||||
THRIFT_UNUSED_VAR (error);
|
||||
THRIFT_UNUSED_VAR (transport);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
thrift_zlib_transport_flush_to_zlib (ThriftTransport *transport, const gint8* buf,
|
||||
gint len, gint flush, GError **error)
|
||||
{
|
||||
ThriftZlibTransport *t = THRIFT_ZLIB_TRANSPORT (transport);
|
||||
t->wstream->next_in = (guchar*)buf;
|
||||
t->wstream->avail_in = len;
|
||||
|
||||
while (TRUE) {
|
||||
if ((flush == Z_NO_FLUSH || flush == Z_BLOCK) && t->wstream->avail_in == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* If our output buffer is full, flush to the underlying transport. */
|
||||
if (t->wstream->avail_out == 0) {
|
||||
THRIFT_TRANSPORT_GET_CLASS (t->transport)->write (t->transport,
|
||||
t->cwbuf, t->cwbuf_size, error);
|
||||
t->wstream->next_out = t->cwbuf;
|
||||
t->wstream->avail_out = t->cwbuf_size;
|
||||
break;
|
||||
}
|
||||
|
||||
int zlib_rv = deflate(t->wstream, flush);
|
||||
|
||||
if (flush == Z_FINISH && zlib_rv == Z_STREAM_END) {
|
||||
if (t->wstream->avail_in != 0) {
|
||||
g_set_error (error, THRIFT_TRANSPORT_ERROR, THRIFT_TRANSPORT_ERROR_SEND,
|
||||
"wstream->avail_in != 0");
|
||||
return FALSE;
|
||||
}
|
||||
deflateEnd(t->wstream);
|
||||
t->output_finished = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (zlib_rv != Z_OK) {
|
||||
g_set_error (error, THRIFT_TRANSPORT_ERROR, THRIFT_TRANSPORT_ERROR_SEND,
|
||||
"zlib error: %d (status = %s)", zlib_rv, t->wstream->msg);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ((flush == Z_SYNC_FLUSH || flush == Z_FULL_FLUSH) && t->wstream->avail_in ==0
|
||||
&& t->wstream->avail_out != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* implements thrift_transport_write
|
||||
* WRITING STRATEGY
|
||||
* We buffer up small writes before sending them to zlib, so our logic is:
|
||||
* - Is the write big?
|
||||
* - Send the buffer to zlib.
|
||||
* - Send this data to zlib.
|
||||
* - Is the write small?
|
||||
* - Is there insufficient space in the buffer for it?
|
||||
* - Send the buffer to zlib.
|
||||
* - Copy the data to the buffer.
|
||||
*
|
||||
* We have two buffers for writing also: the uncompressed buffer (mentioned
|
||||
* above) and the compressed buffer. When sending data to zlib we loop over
|
||||
* the following until the source (uncompressed buffer or big write) is empty:
|
||||
* - Is there no more space in the compressed buffer?
|
||||
* - Write the compressed buffer to the underkying transport.
|
||||
* - Deflate from the source into the compressed buffer. */
|
||||
gboolean
|
||||
thrift_zlib_transport_write (ThriftTransport *transport,
|
||||
const gpointer buf,
|
||||
const guint32 len, GError **error)
|
||||
{
|
||||
ThriftZlibTransport *t = THRIFT_ZLIB_TRANSPORT (transport);
|
||||
|
||||
if (t->output_finished) {
|
||||
g_set_error (error, THRIFT_TRANSPORT_ERROR, THRIFT_TRANSPORT_ERROR_SEND,
|
||||
"write() called after write_end(): %s",
|
||||
strerror(errno));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* zlib's "deflate" function has enough logic in it that I think
|
||||
* we're better off (performance-wise) buffering up small writes. */
|
||||
if (len > MIN_DIRECT_DEFLATE_SIZE) {
|
||||
if (!thrift_zlib_transport_flush_to_zlib (transport, (gint8*)t->uwbuf, t->uwpos, Z_NO_FLUSH, error)) {
|
||||
return FALSE;
|
||||
}
|
||||
t->uwpos = 0;
|
||||
if (!thrift_zlib_transport_flush_to_zlib (transport, buf, len, Z_NO_FLUSH, error)) {
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
} else if (len > 0) {
|
||||
if ((guint32)(t->uwbuf_size - t->uwpos) < len) {
|
||||
if (!thrift_zlib_transport_flush_to_zlib (transport, (gint8*)t->uwbuf, t->uwpos, Z_NO_FLUSH, error)) {
|
||||
return FALSE;
|
||||
}
|
||||
t->uwpos = 0;
|
||||
}
|
||||
memcpy (t->uwbuf + t->uwpos, buf, len);
|
||||
t->uwpos += len;
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
thrift_zlib_transport_flush_to_transport (ThriftTransport *transport, gint flush, GError **error)
|
||||
{
|
||||
ThriftZlibTransport *t = THRIFT_ZLIB_TRANSPORT (transport);
|
||||
|
||||
/* write pending data in uwbuf to zlib */
|
||||
if (!thrift_zlib_transport_flush_to_zlib (transport, (gint8*)t->uwbuf, t->uwpos, flush, error)) {
|
||||
return FALSE;
|
||||
}
|
||||
t->uwpos = 0;
|
||||
|
||||
/* write all available data from zlib to the transport */
|
||||
if (!THRIFT_TRANSPORT_GET_CLASS (t->transport)->write (t->transport,
|
||||
t->cwbuf, (t->cwbuf_size - t->wstream->avail_out),
|
||||
error)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
t->wstream->next_out = t->cwbuf;
|
||||
t->wstream->avail_out = t->cwbuf_size;
|
||||
|
||||
/* flush the transport */
|
||||
if (!THRIFT_TRANSPORT_GET_CLASS (t->transport)->flush(t->transport, error)) {
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* implements thrift_transport_write_end
|
||||
* called when write is complete. nothing to do on our end. */
|
||||
gboolean
|
||||
thrift_zlib_transport_write_end (ThriftTransport *transport, GError **error)
|
||||
{
|
||||
THRIFT_UNUSED_VAR (error);
|
||||
THRIFT_UNUSED_VAR (transport);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* implements thrift_transport_flush */
|
||||
gboolean
|
||||
thrift_zlib_transport_flush (ThriftTransport *transport, GError **error)
|
||||
{
|
||||
ThriftZlibTransport *t = THRIFT_ZLIB_TRANSPORT (transport);
|
||||
ThriftTransportClass *ttc = THRIFT_TRANSPORT_GET_CLASS (transport);
|
||||
|
||||
if (t->output_finished) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
thrift_zlib_transport_flush_to_zlib (transport, (gint8*)t->uwbuf, t->uwpos, Z_NO_FLUSH, error);
|
||||
t->uwpos = 0;
|
||||
|
||||
if (t->wstream->avail_out < 6) {
|
||||
if (!THRIFT_TRANSPORT_GET_CLASS (t->transport)->write(t->transport,
|
||||
t->cwbuf, t->cwbuf_size - t->wstream->avail_out,
|
||||
error)) {
|
||||
return FALSE;
|
||||
}
|
||||
t->wstream->next_out = t->cwbuf;
|
||||
t->wstream->avail_out = t->cwbuf_size;
|
||||
}
|
||||
|
||||
if (!thrift_zlib_transport_flush_to_transport (transport, Z_FULL_FLUSH, error)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!ttc->resetConsumedMessageSize (transport, -1, error)) {
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
thrift_zlib_transport_verify_checksum(ThriftTransport *transport, GError **error)
|
||||
{
|
||||
ThriftZlibTransport *t = THRIFT_ZLIB_TRANSPORT (transport);
|
||||
|
||||
/* If zlib has already reported the end of the stream,
|
||||
* it has verified the checksum. */
|
||||
if (t->input_ended) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* This should only be called when reading is complete.
|
||||
* If the caller still has unread data, throw an exception. */
|
||||
if (thrift_zlib_transport_read_avail (transport) > 0) {
|
||||
g_set_error (error, THRIFT_TRANSPORT_ERROR, THRIFT_TRANSPORT_ERROR_RECEIVE,
|
||||
"thrift_zlib_transport_verify_checksum() called bufore end of zlib stream.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Reset the rsteam fields, in case avail_out is 0.
|
||||
* (Since thrift_zlib_transport_read_avail() is 0, we know there is no unread data in urbuf) */
|
||||
t->rstream->next_out = t->urbuf;
|
||||
t->rstream->avail_out = t->urbuf_size;
|
||||
t->urpos = 0;
|
||||
|
||||
/* Call inflate()
|
||||
* This will set the error if the checksum is bad. */
|
||||
gboolean performed_inflate = thrift_zlib_transport_read_from_zlib (transport, error);
|
||||
if (!performed_inflate) {
|
||||
g_set_error (error, THRIFT_TRANSPORT_ERROR, THRIFT_TRANSPORT_ERROR_RECEIVE,
|
||||
"checksum not available yet in thrift_zlib_transport_verify_checksum ()");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* If input_ended is TRUE now, the checksum has been verified */
|
||||
if (t->input_ended) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* The caller invoked us before the actual end of the data stream */
|
||||
if (t->rstream->avail_out < (guint)t->urbuf_size) {
|
||||
g_set_error (error, THRIFT_TRANSPORT_ERROR, THRIFT_TRANSPORT_ERROR_RECEIVE,
|
||||
"rstream->avail_out >= urbuf_size");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_set_error (error, THRIFT_TRANSPORT_ERROR, THRIFT_TRANSPORT_ERROR_RECEIVE,
|
||||
"thrift_zlib_transport_verify_checksum() called bufore end of zlib stream.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
thrift_zlib_transport_finish(ThriftTransport *transport, GError **error)
|
||||
{
|
||||
ThriftZlibTransport *t = THRIFT_ZLIB_TRANSPORT (transport);
|
||||
|
||||
if (t->output_finished) {
|
||||
g_set_error (error, THRIFT_TRANSPORT_ERROR, THRIFT_TRANSPORT_ERROR_SEND,
|
||||
"finish() called more than once");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!thrift_zlib_transport_flush_to_transport (transport, Z_FINISH, error)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* initializes the instance */
|
||||
static void
|
||||
thrift_zlib_transport_init (ThriftZlibTransport *transport)
|
||||
{
|
||||
transport->transport = NULL;
|
||||
transport->urpos = 0;
|
||||
transport->uwpos = 0;
|
||||
transport->input_ended = FALSE;
|
||||
transport->output_finished = FALSE;
|
||||
|
||||
transport->rstream = g_new0 (struct z_stream_s, 1);
|
||||
transport->wstream = g_new0 (struct z_stream_s, 1);
|
||||
|
||||
transport->rstream->zalloc = Z_NULL;
|
||||
transport->wstream->zalloc = Z_NULL;
|
||||
transport->rstream->zfree = Z_NULL;
|
||||
transport->wstream->zfree = Z_NULL;
|
||||
transport->rstream->opaque = Z_NULL;
|
||||
transport->wstream->opaque = Z_NULL;
|
||||
|
||||
transport->rstream->avail_in = 0;
|
||||
transport->wstream->avail_in = 0;
|
||||
}
|
||||
|
||||
/* destructor */
|
||||
static void
|
||||
thrift_zlib_transport_finalize (GObject *object)
|
||||
{
|
||||
ThriftZlibTransport *t = THRIFT_ZLIB_TRANSPORT (object);
|
||||
inflateEnd (t->rstream);
|
||||
deflateEnd (t->wstream);
|
||||
|
||||
if (t->urbuf != NULL) {
|
||||
g_free (t->urbuf);
|
||||
}
|
||||
if (t->crbuf != NULL) {
|
||||
g_free (t->crbuf);
|
||||
}
|
||||
if (t->uwbuf != NULL) {
|
||||
g_free (t->uwbuf);
|
||||
}
|
||||
if (t->cwbuf != NULL) {
|
||||
g_free (t->cwbuf);
|
||||
}
|
||||
if (t->rstream != NULL) {
|
||||
g_free (t->rstream);
|
||||
}
|
||||
if (t->wstream != NULL) {
|
||||
g_free (t->wstream);
|
||||
}
|
||||
}
|
||||
|
||||
/* property accessor */
|
||||
void
|
||||
thrift_zlib_transport_get_property (GObject *object, guint property_id,
|
||||
GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
ThriftZlibTransport *transport = NULL;
|
||||
ThriftTransport *tt = NULL;
|
||||
|
||||
THRIFT_UNUSED_VAR (pspec);
|
||||
|
||||
transport = THRIFT_ZLIB_TRANSPORT (object);
|
||||
tt = THRIFT_TRANSPORT (object);
|
||||
|
||||
switch (property_id) {
|
||||
case PROP_THRIFT_ZLIB_TRANSPORT_TRANSPORT:
|
||||
g_value_set_object (value, transport->transport);
|
||||
break;
|
||||
case PROP_THRIFT_ZLIB_TRANSPORT_URBUF_SIZE:
|
||||
g_value_set_int (value, transport->urbuf_size);
|
||||
break;
|
||||
case PROP_THRIFT_ZLIB_TRANSPORT_CRBUF_SIZE:
|
||||
g_value_set_int (value, transport->crbuf_size);
|
||||
break;
|
||||
case PROP_THRIFT_ZLIB_TRANSPORT_UWBUF_SIZE:
|
||||
g_value_set_int (value, transport->uwbuf_size);
|
||||
break;
|
||||
case PROP_THRIFT_ZLIB_TRANSPORT_CWBUF_SIZE:
|
||||
g_value_set_int (value, transport->cwbuf_size);
|
||||
break;
|
||||
case PROP_THRIFT_ZLIB_TRANSPORT_COMP_LEVEL:
|
||||
g_value_set_int (value, transport->comp_level);
|
||||
break;
|
||||
case PROP_THRIFT_ZLIB_TRANSPORT_CONFIGURATION:
|
||||
g_value_set_object (value, tt->configuration);
|
||||
break;
|
||||
case PROP_THRIFT_ZLIB_TRANSPORT_REMAINING_MESSAGE_SIZE:
|
||||
g_value_set_long (value, tt->remainingMessageSize_);
|
||||
break;
|
||||
case PROP_THRIFT_ZLIB_TRANSPORT_KNOW_MESSAGE_SIZE:
|
||||
g_value_set_long (value, tt->knowMessageSize_);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* property mutator */
|
||||
void
|
||||
thrift_zlib_transport_set_property (GObject *object, guint property_id,
|
||||
const GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
ThriftZlibTransport *transport = NULL;
|
||||
ThriftTransport *tt = NULL;
|
||||
|
||||
THRIFT_UNUSED_VAR (pspec);
|
||||
|
||||
transport = THRIFT_ZLIB_TRANSPORT (object);
|
||||
tt = THRIFT_TRANSPORT (object);
|
||||
|
||||
switch (property_id) {
|
||||
case PROP_THRIFT_ZLIB_TRANSPORT_TRANSPORT:
|
||||
transport->transport = g_value_get_object (value);
|
||||
break;
|
||||
case PROP_THRIFT_ZLIB_TRANSPORT_URBUF_SIZE:
|
||||
transport->urbuf_size = g_value_get_int (value);
|
||||
transport->urbuf = g_new0 (guint8, transport->urbuf_size);
|
||||
transport->rstream->next_out = transport->urbuf;
|
||||
transport->rstream->avail_out = transport->urbuf_size;
|
||||
break;
|
||||
case PROP_THRIFT_ZLIB_TRANSPORT_CRBUF_SIZE:
|
||||
transport->crbuf_size = g_value_get_int (value);
|
||||
transport->crbuf = g_new0 (guint8, transport->crbuf_size);
|
||||
transport->rstream->next_in = transport->crbuf;
|
||||
break;
|
||||
case PROP_THRIFT_ZLIB_TRANSPORT_UWBUF_SIZE:
|
||||
transport->uwbuf_size = g_value_get_int (value);
|
||||
transport->uwbuf = g_new0 (guint8, transport->uwbuf_size);
|
||||
transport->wstream->next_in = transport->uwbuf;
|
||||
break;
|
||||
case PROP_THRIFT_ZLIB_TRANSPORT_CWBUF_SIZE:
|
||||
transport->cwbuf_size = g_value_get_int (value);
|
||||
transport->cwbuf = g_new0 (guint8, transport->cwbuf_size);
|
||||
transport->wstream->next_out = transport->cwbuf;
|
||||
transport->wstream->avail_out = transport->cwbuf_size;
|
||||
break;
|
||||
case PROP_THRIFT_ZLIB_TRANSPORT_COMP_LEVEL:
|
||||
transport->comp_level = g_value_get_int (value);
|
||||
if(inflateInit(transport->rstream) != Z_OK) {
|
||||
printf("inflate_init fail \n");
|
||||
return;
|
||||
}
|
||||
if(deflateInit (transport->wstream, transport->comp_level) != Z_OK) {
|
||||
printf("deflate init fail\n");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case PROP_THRIFT_ZLIB_TRANSPORT_CONFIGURATION:
|
||||
tt->configuration = g_value_dup_object (value);
|
||||
break;
|
||||
case PROP_THRIFT_ZLIB_TRANSPORT_REMAINING_MESSAGE_SIZE:
|
||||
tt->remainingMessageSize_ = g_value_get_long (value);
|
||||
break;
|
||||
case PROP_THRIFT_ZLIB_TRANSPORT_KNOW_MESSAGE_SIZE:
|
||||
tt->knowMessageSize_ = g_value_get_long (value);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* initialize the class */
|
||||
static void
|
||||
thrift_zlib_transport_class_init (ThriftZlibTransportClass *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_zlib_transport_get_property;
|
||||
gobject_class->set_property = thrift_zlib_transport_set_property;
|
||||
|
||||
param_spec = g_param_spec_object ("transport", "transport (construct)",
|
||||
"Thrift transport",
|
||||
THRIFT_TYPE_TRANSPORT,
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_READWRITE);
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_THRIFT_ZLIB_TRANSPORT_TRANSPORT,
|
||||
param_spec);
|
||||
|
||||
param_spec = g_param_spec_int ("urbuf_size", "urbuf_size (construct)",
|
||||
"Uncompressed buffer size for reading",
|
||||
0, /* min */
|
||||
G_MAXINT, /* max */
|
||||
DEFAULT_URBUF_SIZE, /* default value */
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_READWRITE);
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_THRIFT_ZLIB_TRANSPORT_URBUF_SIZE,
|
||||
param_spec);
|
||||
|
||||
param_spec = g_param_spec_int ("crbuf_size", "crbuf_size (construct)",
|
||||
"Compressed buffer size for reading",
|
||||
0, /* min */
|
||||
G_MAXINT, /* max */
|
||||
DEFAULT_CRBUF_SIZE, /* default value */
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_READWRITE);
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_THRIFT_ZLIB_TRANSPORT_CRBUF_SIZE,
|
||||
param_spec);
|
||||
|
||||
param_spec = g_param_spec_int ("uwbuf_size", "uwbuf_size (construct)",
|
||||
"Uncompressed buffer size for writing",
|
||||
MIN_DIRECT_DEFLATE_SIZE, /* min */
|
||||
G_MAXINT, /* max */
|
||||
DEFAULT_UWBUF_SIZE, /* default value */
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_READWRITE);
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_THRIFT_ZLIB_TRANSPORT_UWBUF_SIZE,
|
||||
param_spec);
|
||||
|
||||
param_spec = g_param_spec_int ("cwbuf_size", "cwbuf_size (construct)",
|
||||
"Compressed buffer size of writing",
|
||||
0, /* min */
|
||||
G_MAXINT, /* max */
|
||||
DEFAULT_CWBUF_SIZE, /* default value */
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_READWRITE);
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_THRIFT_ZLIB_TRANSPORT_CWBUF_SIZE,
|
||||
param_spec);
|
||||
|
||||
param_spec = g_param_spec_int ("comp_level", "comp_level (construct)",
|
||||
"Compression level (0=none[fast], 6=default, 9=max[slow])",
|
||||
Z_DEFAULT_COMPRESSION, /* min */
|
||||
Z_BEST_COMPRESSION, /* max */
|
||||
Z_DEFAULT_COMPRESSION, /* default value */
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_READWRITE);
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_THRIFT_ZLIB_TRANSPORT_COMP_LEVEL,
|
||||
param_spec);
|
||||
|
||||
param_spec = g_param_spec_object ("configuration", "configuration (construct)",
|
||||
"Thrift Configuration",
|
||||
THRIFT_TYPE_CONFIGURATION,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_THRIFT_ZLIB_TRANSPORT_CONFIGURATION,
|
||||
param_spec);
|
||||
|
||||
param_spec = g_param_spec_long ("remainingmessagesize", "remainingmessagesize (construct)",
|
||||
"Set the size of the remaining message",
|
||||
0, /* min */
|
||||
G_MAXINT32, /* max */
|
||||
DEFAULT_MAX_MESSAGE_SIZE, /* default by construct */
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_THRIFT_ZLIB_TRANSPORT_REMAINING_MESSAGE_SIZE,
|
||||
param_spec);
|
||||
|
||||
param_spec = g_param_spec_long ("knowmessagesize", "knowmessagesize (construct)",
|
||||
"Set the size of the know message",
|
||||
G_MININT, /* min */
|
||||
G_MAXINT32, /* max */
|
||||
DEFAULT_MAX_MESSAGE_SIZE, /* default by construct */
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_THRIFT_ZLIB_TRANSPORT_KNOW_MESSAGE_SIZE,
|
||||
param_spec);
|
||||
|
||||
gobject_class->finalize = thrift_zlib_transport_finalize;
|
||||
ttc->is_open = thrift_zlib_transport_is_open;
|
||||
ttc->peek = thrift_zlib_transport_peek;
|
||||
ttc->open = thrift_zlib_transport_open;
|
||||
ttc->close = thrift_zlib_transport_close;
|
||||
ttc->read = thrift_zlib_transport_read;
|
||||
ttc->read_end = thrift_zlib_transport_read_end;
|
||||
ttc->write = thrift_zlib_transport_write;
|
||||
ttc->write_end = thrift_zlib_transport_write_end;
|
||||
ttc->flush = thrift_zlib_transport_flush;
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* 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_ZLIB_TRANSPORT_H
|
||||
#define _THRIFT_ZLIB_TRANSPORT_H
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib-object.h>
|
||||
#include <zlib.h>
|
||||
|
||||
#include "thrift_transport.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/*! \file thrift_zlib_transport.h
|
||||
* \brief Class for Thrift file descriptor transports.
|
||||
*/
|
||||
|
||||
/* type macros */
|
||||
#define THRIFT_TYPE_ZLIB_TRANSPORT (thrift_zlib_transport_get_type ())
|
||||
#define THRIFT_ZLIB_TRANSPORT(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST ((obj), THRIFT_TYPE_ZLIB_TRANSPORT, \
|
||||
ThriftZlibTransport))
|
||||
#define THRIFT_IS_ZLIB_TRANSPORT(obj) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE ((obj), THRIFT_TYPE_ZLIB_TRANSPORT))
|
||||
#define THRIFT_ZLIB_TRANSPORT_CLASS(c) \
|
||||
(G_TYPE_CHECK_CLASS_CAST ((c), THRIFT_TYPE_ZLIB_TRANSPORT, \
|
||||
ThriftZlibTransportClass))
|
||||
#define THRIFT_IS_ZLIB_TRANSPORT_CLASS(c) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE ((c), THRIFT_TYPE_ZLIB_TRANSPORT))
|
||||
#define THRIFT_ZLIB_TRANSPORT_GET_CLASS(obj) \
|
||||
(G_TYPE_INSTANCE_GET_CLASS ((obj), THRIFT_TYPE_ZLIB_TRANSPORT, \
|
||||
ThriftZlibTransportClass))
|
||||
|
||||
typedef struct _ThriftZlibTransport ThriftZlibTransport;\
|
||||
|
||||
struct _ThriftZlibTransport
|
||||
{
|
||||
ThriftTransport parent;
|
||||
|
||||
/* protected */
|
||||
ThriftTransport *transport;
|
||||
gint urbuf_size;
|
||||
gint crbuf_size;
|
||||
gint uwbuf_size;
|
||||
gint cwbuf_size;
|
||||
gint comp_level;
|
||||
ThriftConfiguration *configuration;
|
||||
glong remainingMessageSize_;
|
||||
glong knowMessageSize_;
|
||||
|
||||
/* private */
|
||||
gint urpos;
|
||||
gint uwpos;
|
||||
gboolean input_ended; /* TRUE iff zlib has reached the end of the input stream*/
|
||||
gboolean output_finished; /* TRUE iff we have finished the ouput stream*/
|
||||
guint8* urbuf;
|
||||
guint8* crbuf;
|
||||
guint8* uwbuf;
|
||||
guint8* cwbuf;
|
||||
struct z_stream_s* rstream;
|
||||
struct z_stream_s* wstream;
|
||||
};
|
||||
|
||||
typedef struct _ThriftZlibTransportClass ThriftZlibTransportClass;
|
||||
|
||||
/*!
|
||||
* Thrift Transport class
|
||||
*/
|
||||
struct _ThriftZlibTransportClass
|
||||
{
|
||||
ThriftTransportClass parent;
|
||||
};
|
||||
|
||||
/* used by THRIFT_TYPE_ZLIB_TRANSPORT */
|
||||
GType thrift_zlib_transport_get_type (void);
|
||||
|
||||
gboolean
|
||||
thrift_zlib_transport_verify_checksum(ThriftTransport *transport, GError **error);
|
||||
|
||||
gboolean
|
||||
thrift_zlib_transport_finish(ThriftTransport *transport, GError **error);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* _THRIFT_ZLIB_TRANSPORT_H */
|
||||
|
||||
@@ -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_zlib_transport.h>
|
||||
#include <thrift/c_glib/transport/thrift_zlib_transport_factory.h>
|
||||
|
||||
G_DEFINE_TYPE (ThriftZlibTransportFactory,
|
||||
thrift_zlib_transport_factory,
|
||||
THRIFT_TYPE_TRANSPORT_FACTORY)
|
||||
|
||||
/* Wraps a transport with a ThriftZlibTransport. */
|
||||
ThriftTransport *
|
||||
thrift_zlib_transport_factory_get_transport (ThriftTransportFactory *factory,
|
||||
ThriftTransport *transport)
|
||||
{
|
||||
THRIFT_UNUSED_VAR (factory);
|
||||
|
||||
return THRIFT_TRANSPORT (g_object_new (THRIFT_TYPE_ZLIB_TRANSPORT,
|
||||
"transport", transport,
|
||||
NULL));
|
||||
}
|
||||
|
||||
static void
|
||||
thrift_zlib_transport_factory_init (ThriftZlibTransportFactory *self)
|
||||
{
|
||||
THRIFT_UNUSED_VAR (self);
|
||||
}
|
||||
|
||||
static void
|
||||
thrift_zlib_transport_factory_class_init (ThriftZlibTransportFactoryClass *klass)
|
||||
{
|
||||
ThriftTransportFactoryClass *base_class =
|
||||
THRIFT_TRANSPORT_FACTORY_CLASS (klass);
|
||||
|
||||
base_class->get_transport =
|
||||
klass->get_transport =
|
||||
thrift_zlib_transport_factory_get_transport;
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* 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_ZLIB_TRANSPORT_FACTORY_H
|
||||
#define _THRIFT_ZLIB_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_zlib_transport_factory.h
|
||||
* \brief Wraps a transport with a ThriffZlibTransport.
|
||||
*/
|
||||
|
||||
/* type macros */
|
||||
#define THRIFT_TYPE_ZLIB_TRANSPORT_FACTORY (thrift_zlib_transport_factory_get_type())
|
||||
#define THRIFT_ZLIB_TRANSPORT_FACTORY(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST ((obj), \
|
||||
THRIFT_TYPE_ZLIB_TRANSPORT_FACTORY, \
|
||||
ThriftZlibTransportFactory))
|
||||
#define THRIFT_IS_ZLIB_TRANSPORT_FACTORY(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
|
||||
THRIFT_TYPE_ZLIB_TRANSPORT_FACTORY))
|
||||
#define THRIFT_ZLIB_TRANSPORT_FACTORY_CLASS(c) \
|
||||
(G_TYPE_CHECK_CLASS_CAST ((c), \
|
||||
THRIFT_TYPE_ZLIB_TRANSPORT_FACTORY, \
|
||||
ThriftZlibTransportFactoryClass))
|
||||
#define THRIFT_IS_ZLIB_TRANSPORT_FACTORY_CLASS(c) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE ((c), \
|
||||
THRIFT_TYPE_ZLIB_TRANSPORT_FACTORY)
|
||||
#define THRIFT_ZLIB_TRANSPORT_FACTORY_GET_CLASS(obj) \
|
||||
(G_TYPE_INSTANCE_GET_CLASS ((obj), \
|
||||
THRIFT_TYPE_ZLIB_TRANSPORT_FACTORY, \
|
||||
ThriftZlibTransportFactoryClass))
|
||||
|
||||
typedef struct _ThriftZlibTransportFactory ThriftZlibTransportFactory;
|
||||
|
||||
/* Thrift Zlib-Transport Factory instance */
|
||||
struct _ThriftZlibTransportFactory
|
||||
{
|
||||
ThriftTransportFactory parent;
|
||||
};
|
||||
|
||||
typedef struct _ThriftZlibTransportFactoryClass ThriftZlibTransportFactoryClass;
|
||||
|
||||
/* Thrift Zlib-Transport Factory class */
|
||||
struct _ThriftZlibTransportFactoryClass
|
||||
{
|
||||
ThriftTransportFactoryClass parent;
|
||||
|
||||
/* vtable */
|
||||
ThriftTransport *(*get_transport) (ThriftTransportFactory *factory,
|
||||
ThriftTransport *transport);
|
||||
};
|
||||
|
||||
/* USED BY THRIFT_TYPE_ZLIB_TRANSPORT_FACTORY */
|
||||
GType thrift_zlib_transport_factory_get_type (void);
|
||||
|
||||
/* virtual public methods */
|
||||
ThriftTransport *
|
||||
thrift_zlib_transport_factory_get_transport (ThriftTransportFactory *factory,
|
||||
ThriftTransport *transport);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* _THRIFT_ZLIB_TANSPORT_FACTORY_H */
|
||||
@@ -0,0 +1,237 @@
|
||||
#
|
||||
# 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")
|
||||
|
||||
# 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})
|
||||
target_link_libraries(testgenc thrift_c_glib)
|
||||
|
||||
|
||||
add_executable(testserialization testserialization.c)
|
||||
target_link_libraries(testserialization testgenc)
|
||||
target_link_libraries(testserialization thrift_c_glib)
|
||||
add_test(NAME testserialization COMMAND testserialization)
|
||||
|
||||
add_executable(testapplicationexception testapplicationexception.c)
|
||||
target_link_libraries(testapplicationexception thrift_c_glib)
|
||||
add_test(NAME testapplicationexception COMMAND testapplicationexception)
|
||||
|
||||
add_executable(testtransportsocket testtransportsocket.c)
|
||||
target_link_libraries(testtransportsocket thrift_c_glib)
|
||||
add_test(NAME testtransportsocket COMMAND testtransportsocket)
|
||||
|
||||
add_executable(testbinaryprotocol testbinaryprotocol.c)
|
||||
target_link_libraries(testbinaryprotocol thrift_c_glib)
|
||||
add_test(NAME testbinaryprotocol COMMAND testbinaryprotocol)
|
||||
|
||||
add_executable(testcompactprotocol testcompactprotocol.c)
|
||||
target_link_libraries(testcompactprotocol thrift_c_glib)
|
||||
add_test(NAME testcompactprotocol COMMAND testcompactprotocol)
|
||||
|
||||
add_executable(testbufferedtransport testbufferedtransport.c)
|
||||
target_link_libraries(testbufferedtransport thrift_c_glib)
|
||||
add_test(NAME testbufferedtransport COMMAND testbufferedtransport)
|
||||
|
||||
add_executable(testframedtransport testframedtransport.c)
|
||||
target_link_libraries(testframedtransport thrift_c_glib)
|
||||
add_test(NAME testframedtransport COMMAND testframedtransport)
|
||||
|
||||
add_executable(testfdtransport testfdtransport.c)
|
||||
target_link_libraries(testfdtransport thrift_c_glib)
|
||||
add_test(NAME testfdtransport COMMAND testfdtransport)
|
||||
|
||||
add_executable(testmemorybuffer testmemorybuffer.c)
|
||||
target_link_libraries(testmemorybuffer thrift_c_glib)
|
||||
add_test(NAME testmemorybuffer COMMAND testmemorybuffer)
|
||||
|
||||
add_executable(testsimpleserver testsimpleserver.c)
|
||||
target_link_libraries(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)
|
||||
|
||||
add_executable(testthriftbinaryreadcheck testthriftbinaryreadcheck.c)
|
||||
target_link_libraries(testthriftbinaryreadcheck testgenc)
|
||||
add_test(NAME testthriftbinaryreadcheck COMMAND testthriftbinaryreadcheck)
|
||||
|
||||
add_executable(testthriftbufferedreadcheck testthriftbufferedreadcheck.c)
|
||||
target_link_libraries(testthriftbufferedreadcheck testgenc)
|
||||
add_test(NAME testthriftbufferedreadcheck COMMAND testthriftbufferedreadcheck)
|
||||
|
||||
add_executable(testthriftcompactreadcheck testthriftcompactreadcheck.c)
|
||||
target_link_libraries(testthriftcompactreadcheck testgenc)
|
||||
add_test(NAME testthriftcompactreadcheck COMMAND testthriftcompactreadcheck)
|
||||
|
||||
add_executable(testthriftframedreadcheck testthriftframedreadcheck.c)
|
||||
target_link_libraries(testthriftframedreadcheck testgenc)
|
||||
add_test(NAME testthriftframedreadcheck COMMAND testthriftframedreadcheck)
|
||||
|
||||
add_executable(testthriftfdreadcheck testthriftfdreadcheck.c)
|
||||
target_link_libraries(testthriftfdreadcheck testgenc)
|
||||
add_test(NAME testthriftfdreadcheck COMMAND testthriftfdreadcheck)
|
||||
|
||||
add_executable(testthriftmemorybufferreadcheck testthriftmemorybufferreadcheck.c)
|
||||
target_link_libraries(testthriftmemorybufferreadcheck testgenc)
|
||||
add_test(NAME testthriftmemorybufferreadcheck COMMAND testthriftmemorybufferreadcheck)
|
||||
|
||||
if(WITH_ZLIB)
|
||||
include_directories(SYSTEM "${ZLIB_INCLUDE_DIRS}")
|
||||
add_executable(testzlibtransport testzlibtransport.c)
|
||||
target_link_libraries(testzlibtransport testgenc ${ZLIB_LIBRARIES})
|
||||
target_link_libraries(testzlibtransport thrift_c_glib_zlib)
|
||||
add_test(NAME testzlibtransport COMMAND testzlibtransport)
|
||||
endif(WITH_ZLIB)
|
||||
|
||||
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})
|
||||
target_link_libraries(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)
|
||||
|
||||
if(WITH_ZLIB)
|
||||
add_executable(testthrifttestzlibclient testthrifttestzlibclient.cpp)
|
||||
target_link_libraries(testthrifttestzlibclient testgenc testgenc_cpp thriftz thrift_c_glib_zlib ${ZLIB_LIBRARIES})
|
||||
add_test(NAME testthrifttestzlibclient COMMAND testthrifttestzlibclient)
|
||||
endif(WITH_ZLIB)
|
||||
|
||||
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/v0.16/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/v0.16/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/v0.16/ThriftTest.thrift
|
||||
)
|
||||
|
||||
# TODO: Add memory checks using ctest_memcheck or similar
|
||||
@@ -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();
|
||||
}
|
||||
@@ -0,0 +1,407 @@
|
||||
#
|
||||
# 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) $(ZLIB_LIBS) @GCOV_LDFLAGS@
|
||||
|
||||
check_PROGRAMS = \
|
||||
testserialization \
|
||||
testapplicationexception \
|
||||
testcontainertest \
|
||||
testtransportsocket \
|
||||
testtransportsslsocket \
|
||||
testbinaryprotocol \
|
||||
testcompactprotocol \
|
||||
testbufferedtransport \
|
||||
testframedtransport \
|
||||
testzlibtransport \
|
||||
testfdtransport \
|
||||
testmemorybuffer \
|
||||
teststruct \
|
||||
testsimpleserver \
|
||||
testdebugproto \
|
||||
testoptionalrequired \
|
||||
testthrifttest \
|
||||
testthriftbinaryreadcheck \
|
||||
testthriftcompactreadcheck \
|
||||
testthriftbufferedreadcheck \
|
||||
testthriftfdreadcheck \
|
||||
testthriftframedreadcheck \
|
||||
testthriftmemorybufferreadcheck
|
||||
|
||||
if WITH_CPP
|
||||
BUILT_SOURCES += gen-cpp/ThriftTest_types.cpp
|
||||
check_PROGRAMS += testthrifttestclient \
|
||||
testthrifttestzlibclient
|
||||
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 \
|
||||
$(top_builddir)/lib/c_glib/src/thrift/c_glib/libthrift_c_glib_la-thrift_configuration.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 \
|
||||
$(top_builddir)/lib/c_glib/src/thrift/c_glib/libthrift_c_glib_la-thrift_configuration.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 \
|
||||
$(top_builddir)/lib/c_glib/src/thrift/c_glib/libthrift_c_glib_la-thrift_configuration.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 \
|
||||
$(top_builddir)/lib/c_glib/src/thrift/c_glib/libthrift_c_glib_la-thrift_configuration.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 \
|
||||
$(top_builddir)/lib/c_glib/src/thrift/c_glib/libthrift_c_glib_la-thrift_configuration.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 \
|
||||
$(top_builddir)/lib/c_glib/src/thrift/c_glib/libthrift_c_glib_la-thrift_configuration.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 \
|
||||
$(top_builddir)/lib/c_glib/src/thrift/c_glib/libthrift_c_glib_la-thrift_configuration.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 \
|
||||
$(top_builddir)/lib/c_glib/src/thrift/c_glib/libthrift_c_glib_la-thrift_configuration.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 \
|
||||
$(top_builddir)/lib/c_glib/src/thrift/c_glib/libthrift_c_glib_la-thrift_configuration.o
|
||||
|
||||
testzlibtransport_SOURCES = testzlibtransport.c
|
||||
testzlibtransport_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 \
|
||||
$(top_builddir)/lib/c_glib/src/thrift/c_glib/libthrift_c_glib_la-thrift_configuration.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 \
|
||||
$(top_builddir)/lib/c_glib/src/thrift/c_glib/libthrift_c_glib_la-thrift_configuration.o
|
||||
|
||||
testmemorybuffer_SOURCES = testmemorybuffer.c
|
||||
testmemorybuffer_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/libthrift_c_glib_la-thrift_configuration.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 \
|
||||
$(top_builddir)/lib/c_glib/src/thrift/c_glib/libthrift_c_glib_la-thrift_configuration.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 \
|
||||
$(top_builddir)/lib/c_glib/src/thrift/c_glib/libthrift_c_glib_la-thrift_configuration.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 \
|
||||
$(top_builddir)/lib/c_glib/src/thrift/c_glib/libthrift_c_glib_la-thrift_configuration.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)
|
||||
|
||||
testthriftbinaryreadcheck_SOURCES = testthriftbinaryreadcheck.c
|
||||
testthriftbinaryreadcheck_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 \
|
||||
$(top_builddir)/lib/c_glib/src/thrift/c_glib/libthrift_c_glib_la-thrift_configuration.o
|
||||
|
||||
testthriftcompactreadcheck_SOURCES = testthriftcompactreadcheck.c
|
||||
testthriftcompactreadcheck_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 \
|
||||
$(top_builddir)/lib/c_glib/src/thrift/c_glib/libthrift_c_glib_la-thrift_configuration.o
|
||||
|
||||
testthriftbufferedreadcheck_SOURCES = testthriftbufferedreadcheck.c
|
||||
testthriftbufferedreadcheck_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 \
|
||||
$(top_builddir)/lib/c_glib/src/thrift/c_glib/libthrift_c_glib_la-thrift_configuration.o
|
||||
|
||||
testthriftfdreadcheck_SOURCES = testthriftfdreadcheck.c
|
||||
testthriftfdreadcheck_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 \
|
||||
$(top_builddir)/lib/c_glib/src/thrift/c_glib/libthrift_c_glib_la-thrift_configuration.o
|
||||
|
||||
testthriftframedreadcheck_SOURCES = testthriftframedreadcheck.c
|
||||
testthriftframedreadcheck_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 \
|
||||
$(top_builddir)/lib/c_glib/src/thrift/c_glib/libthrift_c_glib_la-thrift_configuration.o
|
||||
|
||||
testthriftmemorybufferreadcheck_SOURCES = testthriftmemorybufferreadcheck.c
|
||||
testthriftmemorybufferreadcheck_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/libthrift_c_glib_la-thrift_configuration.o
|
||||
|
||||
|
||||
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)
|
||||
|
||||
testthrifttestzlibclient_SOURCES = testthrifttestzlibclient.cpp
|
||||
testthrifttestzlibclient_CPPFLAGS = -I../../cpp/src $(BOOST_CPPFLAGS) -I./gen-cpp -I../src -I./gen-c_glib $(GLIB_CFLAGS)
|
||||
testthrifttestzlibclient_LDADD = ../../cpp/.libs/libthrift.la ../../cpp/.libs/libthriftz.la ../libthrift_c_glib.la libtestgenc.la libtestgencpp.la
|
||||
testthrifttestzlibclient_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/v0.16/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/v0.16/ThriftTest.thrift $(THRIFT)
|
||||
$(THRIFT) --gen c_glib $<
|
||||
|
||||
gen-cpp/ThriftTest.cpp gen-cpp/ThriftTest_constants.cpp gen-cpp/ThriftTest_types.cpp: ../../../test/v0.16/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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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 ();
|
||||
}
|
||||
@@ -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 ();
|
||||
}
|
||||
@@ -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 ();
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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 ();
|
||||
}
|
||||
@@ -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 ();
|
||||
}
|
||||
@@ -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 ();
|
||||
}
|
||||
@@ -0,0 +1,222 @@
|
||||
/*
|
||||
* 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;
|
||||
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 ();
|
||||
}
|
||||
@@ -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 ();
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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 ();
|
||||
}
|
||||
@@ -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 ();
|
||||
}
|
||||
@@ -0,0 +1,279 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
#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
|
||||
|
||||
#define MAX_MESSAGE_SIZE 4
|
||||
|
||||
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_complex_types (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)
|
||||
{
|
||||
ThriftConfiguration *tconfiguration = NULL;
|
||||
ThriftSocket *tsocket = NULL;
|
||||
ThriftBinaryProtocol *bprotocol = NULL;
|
||||
ThriftSocket *temp = NULL;
|
||||
ThriftConfiguration *tempconf = NULL;
|
||||
|
||||
glong tempsize = 0;
|
||||
|
||||
/* create a ThriftConfiguration */
|
||||
tconfiguration = g_object_new (THRIFT_TYPE_CONFIGURATION, "max_message_size", MAX_MESSAGE_SIZE,
|
||||
"max_frame_size", MAX_MESSAGE_SIZE, NULL);
|
||||
g_assert (tconfiguration != NULL);
|
||||
/* create a ThriftTransport */
|
||||
tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost",
|
||||
"port", 51188, "path", NULL,
|
||||
"configuration", tconfiguration,
|
||||
"remainingmessagesize", tconfiguration->maxMessageSize_, NULL);
|
||||
g_assert (tsocket != NULL);
|
||||
/* fetch the properties */
|
||||
g_object_get (G_OBJECT (tconfiguration), "max_message_size", &tempsize, NULL);
|
||||
g_assert (tempsize == MAX_MESSAGE_SIZE);
|
||||
/* fetch the properties */
|
||||
g_object_get (G_OBJECT (tsocket), "remainingmessagesize", &tempsize, NULL);
|
||||
g_assert (tempsize == MAX_MESSAGE_SIZE);
|
||||
/* fetch the properties */
|
||||
g_object_get (G_OBJECT (tsocket), "configuration", &tempconf, NULL);
|
||||
g_object_unref (tempconf);
|
||||
/* create a ThriftBinaryProtocol using Transport */
|
||||
bprotocol = g_object_new (THRIFT_TYPE_BINARY_PROTOCOL, "transport", tsocket, NULL);
|
||||
g_assert (bprotocol != NULL);
|
||||
/* fetch the properties */
|
||||
g_object_get (G_OBJECT (bprotocol), "transport", &temp, NULL);
|
||||
g_object_unref (temp);
|
||||
|
||||
/* clean up memory */
|
||||
g_object_unref (bprotocol);
|
||||
g_object_unref (tsocket);
|
||||
g_object_unref (tconfiguration);
|
||||
}
|
||||
|
||||
void
|
||||
test_read_and_wirte_complex_types (void)
|
||||
{
|
||||
int status;
|
||||
pid_t pid;
|
||||
ThriftConfiguration *tconfiguration = NULL;
|
||||
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 ThriftConfiguration */
|
||||
tconfiguration = g_object_new (THRIFT_TYPE_CONFIGURATION, "max_message_size", MAX_MESSAGE_SIZE,
|
||||
"max_frame_size", MAX_MESSAGE_SIZE, NULL);
|
||||
g_assert (tconfiguration != NULL);
|
||||
|
||||
/* create a ThriftSocket */
|
||||
tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost",
|
||||
"port", port, "path", NULL,
|
||||
"configuration", tconfiguration, NULL);
|
||||
transport = THRIFT_TRANSPORT (tsocket);
|
||||
THRIFT_TRANSPORT_GET_CLASS (tsocket)->resetConsumedMessageSize(THRIFT_TRANSPORT (tsocket), -1, NULL);
|
||||
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 1st write failure on a map */
|
||||
g_assert (thrift_binary_protocol_write_map_begin (protocol, T_VOID, T_BYTE,
|
||||
1, NULL) > 0);
|
||||
g_assert (thrift_binary_protocol_write_map_end (protocol, NULL) == 0);
|
||||
|
||||
g_assert (thrift_binary_protocol_write_map_begin (protocol, T_I32, T_BYTE,
|
||||
1, NULL) > 0);
|
||||
g_assert (thrift_binary_protocol_write_map_end (protocol, NULL) == 0);
|
||||
|
||||
/* test list operations */
|
||||
g_assert (thrift_binary_protocol_write_list_begin (protocol, T_BYTE,
|
||||
1, NULL) > 0);
|
||||
g_assert (thrift_binary_protocol_write_list_end (protocol, NULL) == 0);
|
||||
|
||||
g_assert (thrift_binary_protocol_write_list_begin (protocol, T_I32,
|
||||
10, NULL) > 0);
|
||||
g_assert (thrift_binary_protocol_write_list_end (protocol, NULL) == 0);
|
||||
|
||||
/* clean up */
|
||||
thrift_transport_close (transport, NULL);
|
||||
g_object_unref (tsocket);
|
||||
g_object_unref (protocol);
|
||||
g_object_unref (tconfiguration);
|
||||
g_assert (wait (&status) == pid);
|
||||
g_assert (status == 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
thrift_server_complex_types (const int port)
|
||||
{
|
||||
ThriftServerTransport *transport = NULL;
|
||||
ThriftTransport *client = NULL;
|
||||
ThriftBinaryProtocol *tbp = NULL;
|
||||
ThriftProtocol *protocol = NULL;
|
||||
ThriftType element_type = T_VOID,
|
||||
key_type = T_VOID,
|
||||
value_type = T_VOID;
|
||||
guint32 size = 0;
|
||||
|
||||
ThriftConfiguration *tconfiguration = g_object_new (THRIFT_TYPE_CONFIGURATION,
|
||||
"max_message_size", MAX_MESSAGE_SIZE,
|
||||
"max_frame_size", MAX_MESSAGE_SIZE, NULL);
|
||||
|
||||
ThriftServerSocket *tsocket = g_object_new (THRIFT_TYPE_SERVER_SOCKET, "port", port,
|
||||
"configuration", tconfiguration, NULL);
|
||||
transport = THRIFT_SERVER_TRANSPORT (tsocket);
|
||||
THRIFT_SERVER_TRANSPORT_GET_CLASS (tsocket)->resetConsumedMessageSize(transport, -1, NULL);
|
||||
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_map_begin (protocol, &key_type, &value_type,
|
||||
&size, NULL) > 0);
|
||||
g_assert (thrift_binary_protocol_read_map_end (protocol, NULL) == 0);
|
||||
|
||||
g_assert (thrift_binary_protocol_read_map_begin (protocol, &key_type, &value_type,
|
||||
&size, NULL) == -1);
|
||||
g_assert (thrift_binary_protocol_read_map_end (protocol, NULL) == 0);
|
||||
|
||||
/* test read failure */
|
||||
g_assert (thrift_binary_protocol_read_list_begin (protocol, &element_type,
|
||||
&size, NULL) > 0);
|
||||
g_assert (thrift_binary_protocol_read_list_end(protocol, NULL) == 0);
|
||||
|
||||
g_assert (thrift_binary_protocol_read_list_begin (protocol, &element_type,
|
||||
&size, NULL) == -1);
|
||||
g_assert (thrift_binary_protocol_read_list_end(protocol, NULL) == 0);
|
||||
|
||||
g_object_unref (client);
|
||||
/* TODO: investigate g_object_unref (tbp); */
|
||||
g_object_unref (tsocket);
|
||||
g_object_unref (tconfiguration);
|
||||
}
|
||||
|
||||
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 ("/testthriftbinaryreadcheck/CreateAndDestroy", test_create_and_destroy);
|
||||
g_test_add_func ("/testthriftbinaryreadcheck/Initialize", test_initialize);
|
||||
g_test_add_func ("/testthriftbinaryreadcheck/test_read_and_write_complex_types", test_read_and_wirte_complex_types);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
@@ -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 <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' }
|
||||
|
||||
#define MAX_MESSAGE_SIZE 3
|
||||
|
||||
#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);
|
||||
|
||||
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[3] = 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 3 bytes */
|
||||
thrift_buffered_transport_write (transport, buf, 3, NULL);
|
||||
|
||||
/* write 4 bytes */
|
||||
thrift_buffered_transport_write (transport, buf, 4, 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;
|
||||
|
||||
ThriftConfiguration *tconfiguration = g_object_new (THRIFT_TYPE_CONFIGURATION, "max_message_size", MAX_MESSAGE_SIZE,
|
||||
"max_frame_size", MAX_MESSAGE_SIZE, NULL);
|
||||
|
||||
ThriftServerSocket *tsocket = g_object_new (THRIFT_TYPE_SERVER_SOCKET, "port", port,
|
||||
"configuration", tconfiguration, NULL);
|
||||
|
||||
transport = THRIFT_SERVER_TRANSPORT (tsocket);
|
||||
THRIFT_SERVER_TRANSPORT_GET_CLASS (tsocket)->resetConsumedMessageSize(transport, -1, NULL);
|
||||
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);
|
||||
g_object_unref (tconfiguration);
|
||||
g_assert(tconfiguration != NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
thrift_server (const int port)
|
||||
{
|
||||
int bytes = 0;
|
||||
ThriftServerTransport *transport = NULL;
|
||||
ThriftTransport *client = NULL;
|
||||
guchar buf[3]; /* a buffer */
|
||||
guchar match[3] = TEST_DATA;
|
||||
|
||||
ThriftConfiguration *tconfiguration = g_object_new (THRIFT_TYPE_CONFIGURATION, "max_message_size", MAX_MESSAGE_SIZE,
|
||||
"max_frame_size", MAX_MESSAGE_SIZE, NULL);
|
||||
|
||||
ThriftServerSocket *tsocket = g_object_new (THRIFT_TYPE_SERVER_SOCKET,
|
||||
"port", port, "configuration", tconfiguration, 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 3 bytes */
|
||||
bytes = thrift_buffered_transport_read (client, buf, 3, NULL);
|
||||
g_assert (bytes == 3); /* make sure we've read 10 bytes */
|
||||
g_assert ( memcmp (buf, match, 3) == 0 ); /* make sure what we got matches */
|
||||
|
||||
bytes = thrift_buffered_transport_read (client, buf, 4, NULL);
|
||||
g_assert (bytes == -1);
|
||||
|
||||
thrift_buffered_transport_read_end (client, NULL);
|
||||
thrift_buffered_transport_close (client, NULL);
|
||||
g_object_unref (client);
|
||||
g_object_unref (tsocket);
|
||||
g_object_unref (tconfiguration);
|
||||
}
|
||||
|
||||
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 ("/testthriftbufferedreadcheck/OpenAndClose", test_open_and_close);
|
||||
g_test_add_func ("/testthriftbufferedreadcheck/ReadAndWrite", test_read_and_write);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,275 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
#define MAX_MESSAGE_SIZE 2
|
||||
|
||||
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_complex_types (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;
|
||||
ThriftConfiguration *tconfiguration = NULL;
|
||||
ThriftConfiguration *tempconf = NULL;
|
||||
glong tempsize = 0;
|
||||
|
||||
/* create a ThriftConfiguration */
|
||||
tconfiguration = g_object_new (THRIFT_TYPE_CONFIGURATION, "max_message_size", MAX_MESSAGE_SIZE,
|
||||
"max_frame_size", MAX_MESSAGE_SIZE, NULL);
|
||||
/* create a ThriftTransport */
|
||||
tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost",
|
||||
"port", 51188, "configuration", tconfiguration,
|
||||
"remainingmessagesize", MAX_MESSAGE_SIZE, NULL);
|
||||
g_assert (tsocket != NULL);
|
||||
/* fetch the properties */
|
||||
g_object_get (G_OBJECT (tconfiguration), "max_message_size", &tempsize, NULL);
|
||||
g_assert (tempsize == MAX_MESSAGE_SIZE);
|
||||
/* fetch the properties */
|
||||
g_object_get (G_OBJECT (tsocket), "remainingmessagesize", &tempsize, NULL);
|
||||
g_assert (tempsize == MAX_MESSAGE_SIZE);
|
||||
/* fetch the properties */
|
||||
g_object_get (G_OBJECT (tsocket), "configuration", &tempconf, NULL);
|
||||
g_object_unref (tempconf);
|
||||
/* 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_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);
|
||||
|
||||
g_assert (thrift_compact_protocol_write_map_begin (protocol, T_VOID, T_BYTE,
|
||||
1, NULL) > 0);
|
||||
g_assert (thrift_compact_protocol_write_map_end (protocol, NULL) == 0);
|
||||
|
||||
g_assert (thrift_compact_protocol_write_map_begin (protocol, T_VOID, T_BYTE,
|
||||
3, NULL) > 0);
|
||||
g_assert (thrift_compact_protocol_write_map_end (protocol, NULL) == 0);
|
||||
|
||||
g_assert (thrift_compact_protocol_write_list_begin (protocol, T_BYTE,
|
||||
1, NULL) > 0);
|
||||
g_assert (thrift_compact_protocol_write_list_end (protocol, NULL) == 0);
|
||||
|
||||
g_assert (thrift_compact_protocol_write_list_begin (protocol, T_I32,
|
||||
3, NULL) > 0);
|
||||
g_assert (thrift_compact_protocol_write_list_end (protocol, NULL) == 0);
|
||||
|
||||
/* 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
|
||||
thrift_server_complex_types (const int port)
|
||||
{
|
||||
ThriftServerTransport *transport = NULL;
|
||||
ThriftTransport *client = NULL;
|
||||
ThriftCompactProtocol *tc = NULL;
|
||||
ThriftProtocol *protocol = NULL;
|
||||
ThriftType element_type, key_type, value_type;
|
||||
guint32 size = 0;
|
||||
|
||||
ThriftConfiguration *tconfiguration = g_object_new (THRIFT_TYPE_CONFIGURATION, "max_message_size", MAX_MESSAGE_SIZE,
|
||||
"max_frame_size", MAX_MESSAGE_SIZE, NULL);
|
||||
ThriftServerSocket *tsocket = g_object_new (THRIFT_TYPE_SERVER_SOCKET,
|
||||
"port", port, "configuration", tconfiguration, NULL);
|
||||
transport = THRIFT_SERVER_TRANSPORT (tsocket);
|
||||
THRIFT_SERVER_TRANSPORT_GET_CLASS (tsocket)->resetConsumedMessageSize(transport, -1, NULL);
|
||||
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_map_begin (protocol, &key_type, &value_type,
|
||||
&size, NULL) > 0);
|
||||
g_assert (thrift_compact_protocol_read_map_end (protocol, NULL) == 0);
|
||||
|
||||
g_assert (thrift_compact_protocol_read_map_begin (protocol, &key_type, &value_type,
|
||||
&size, NULL) == -1);
|
||||
g_assert (thrift_compact_protocol_read_map_end (protocol, NULL) == 0);
|
||||
|
||||
g_assert (thrift_compact_protocol_read_list_begin (protocol, &element_type,
|
||||
&size, NULL) > 0);
|
||||
g_assert (thrift_compact_protocol_read_list_end (protocol, NULL) == 0);
|
||||
|
||||
g_assert (thrift_compact_protocol_read_list_begin (protocol, &element_type,
|
||||
&size, NULL) == -1);
|
||||
g_assert (thrift_compact_protocol_read_list_end (protocol, NULL) == 0);
|
||||
|
||||
g_object_unref (client);
|
||||
g_object_unref (tsocket);
|
||||
g_object_unref (tconfiguration);
|
||||
}
|
||||
|
||||
|
||||
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 ("/testthriftcompactreadcheck/CreateAndDestroy",
|
||||
test_create_and_destroy);
|
||||
g_test_add_func ("/testthriftcompactreadcheck/Initialize", test_initialize);
|
||||
g_test_add_func ("/testthriftcompactreadcheck/ReadAndWriteComplexTypes",
|
||||
test_read_and_write_complex_types);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
* 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>
|
||||
|
||||
#define MAX_MESSAGE_SIZE 2
|
||||
|
||||
static const gchar TEST_DATA[12] = "abcde01234!";
|
||||
|
||||
static void
|
||||
test_open_and_close (void)
|
||||
{
|
||||
ThriftConfiguration *configuration;
|
||||
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);
|
||||
|
||||
configuration = g_object_new (THRIFT_TYPE_CONFIGURATION, "max_message_size", MAX_MESSAGE_SIZE,
|
||||
"max_frame_size", MAX_MESSAGE_SIZE, NULL);
|
||||
|
||||
transport = THRIFT_TRANSPORT (g_object_new (THRIFT_TYPE_FD_TRANSPORT,
|
||||
"configuration", configuration, "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_object_unref (configuration);
|
||||
|
||||
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;
|
||||
ThriftConfiguration *configuration;
|
||||
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);
|
||||
|
||||
configuration = g_object_new (THRIFT_TYPE_CONFIGURATION, "max_message_size", MAX_MESSAGE_SIZE,
|
||||
"max_frame_size", MAX_MESSAGE_SIZE, NULL);
|
||||
/* write */
|
||||
transport = THRIFT_TRANSPORT (g_object_new (THRIFT_TYPE_FD_TRANSPORT,
|
||||
"configuration", configuration, "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,
|
||||
"configuration", configuration,
|
||||
"remainingmessagesize", MAX_MESSAGE_SIZE,
|
||||
"fd", fd,
|
||||
NULL));
|
||||
klass = THRIFT_TRANSPORT_GET_CLASS (transport);
|
||||
|
||||
memset(out_buf, 0, 8);
|
||||
b = out_buf;
|
||||
want = 2;
|
||||
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, 2) == 0);
|
||||
|
||||
memset(out_buf, 0, 8);
|
||||
b = out_buf;
|
||||
want = 4;
|
||||
got = klass->read (transport, (gpointer) b, want, &error);
|
||||
g_assert (got < 0);
|
||||
|
||||
g_assert (klass->close (transport, &error));
|
||||
g_object_unref (transport);
|
||||
g_object_unref (configuration);
|
||||
|
||||
/* 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/OpenAndClose", test_open_and_close);
|
||||
g_test_add_func ("/testfdtransport/ReadAndWrite", test_read_and_write);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
@@ -0,0 +1,222 @@
|
||||
/*
|
||||
* 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' }
|
||||
#define MAX_MESSAGE_SIZE 2
|
||||
|
||||
#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);
|
||||
|
||||
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 2 bytes */
|
||||
thrift_framed_transport_write (transport, buf, 2, NULL);
|
||||
thrift_framed_transport_flush (transport, NULL);
|
||||
|
||||
thrift_framed_transport_write (transport, buf, 3, 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 );
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
thrift_socket_server_open (const int port, int times)
|
||||
{
|
||||
ThriftServerTransport *transport = NULL;
|
||||
ThriftTransport *client = NULL;
|
||||
int i;
|
||||
|
||||
ThriftConfiguration *tconfiguration = g_object_new (THRIFT_TYPE_CONFIGURATION,
|
||||
"max_message_size", MAX_MESSAGE_SIZE,
|
||||
"max_frame_size", MAX_MESSAGE_SIZE, NULL);
|
||||
|
||||
ThriftServerSocket *tsocket = g_object_new (THRIFT_TYPE_SERVER_SOCKET,
|
||||
"port", port, "configuration", tconfiguration, 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);
|
||||
g_object_unref (tconfiguration);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
ThriftConfiguration *tconfiguration = g_object_new (THRIFT_TYPE_CONFIGURATION,
|
||||
"max_message_size", MAX_MESSAGE_SIZE,
|
||||
"max_frame_size", MAX_MESSAGE_SIZE,
|
||||
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_FRAMED_TRANSPORT, "transport",
|
||||
thrift_server_transport_accept (transport, NULL),
|
||||
"r_buf_size", 5, "configuration", tconfiguration,
|
||||
"remainingmessagesize", MAX_MESSAGE_SIZE, NULL);
|
||||
g_assert (client != NULL);
|
||||
|
||||
/* read 2 bytes */
|
||||
bytes = thrift_framed_transport_read (client, buf, 2, NULL);
|
||||
g_assert (bytes == 2); /* make sure we've read 2 bytes */
|
||||
g_assert ( memcmp (buf, match, 1) == 0 ); /* make sure what we got matches */
|
||||
|
||||
bytes = thrift_framed_transport_read (client, buf, 3, NULL);
|
||||
g_assert (bytes == -1);
|
||||
|
||||
thrift_framed_transport_read_end (client, NULL);
|
||||
thrift_framed_transport_close (client, NULL);
|
||||
g_object_unref (client);
|
||||
g_object_unref (tsocket);
|
||||
g_object_unref (tconfiguration);
|
||||
}
|
||||
|
||||
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/OpenAndClose", test_open_and_close);
|
||||
g_test_add_func ("/testframedtransport/ReadAndWrite", test_read_and_write);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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"
|
||||
|
||||
#define MAX_MESSAGE_SIZE 2
|
||||
|
||||
static void
|
||||
test_open_and_close (void)
|
||||
{
|
||||
ThriftMemoryBuffer *tbuffer = NULL;
|
||||
ThriftConfiguration *tconfiguration = NULL;
|
||||
|
||||
/* create a ThriftConfiguration */
|
||||
tconfiguration = g_object_new (THRIFT_TYPE_CONFIGURATION,
|
||||
"max_message_size", MAX_MESSAGE_SIZE,
|
||||
"max_frame_size", MAX_MESSAGE_SIZE,
|
||||
NULL);
|
||||
/* create a ThriftMemoryBuffer */
|
||||
tbuffer = g_object_new (THRIFT_TYPE_MEMORY_BUFFER, "configuration", tconfiguration, 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);
|
||||
g_object_unref (tconfiguration);
|
||||
}
|
||||
|
||||
static void
|
||||
test_read_and_write (void)
|
||||
{
|
||||
ThriftConfiguration *tconfiguration = NULL;
|
||||
ThriftMemoryBuffer *tbuffer = NULL;
|
||||
gint got, want;
|
||||
gchar read[10];
|
||||
gchar *b;
|
||||
GError *error = NULL;
|
||||
|
||||
tconfiguration = g_object_new (THRIFT_TYPE_CONFIGURATION, "max_message_size", MAX_MESSAGE_SIZE, NULL);
|
||||
tbuffer = g_object_new (THRIFT_TYPE_MEMORY_BUFFER, "buf_size", 15, "configuration", tconfiguration, NULL);
|
||||
THRIFT_TRANSPORT_GET_CLASS (tbuffer)->resetConsumedMessageSize(THRIFT_TRANSPORT(tbuffer), -1, 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;
|
||||
got = thrift_memory_buffer_read (THRIFT_TRANSPORT (tbuffer),
|
||||
(gpointer) b, want, &error);
|
||||
g_assert (got < 0);
|
||||
g_object_unref (tbuffer);
|
||||
g_object_unref (tconfiguration);
|
||||
}
|
||||
|
||||
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 ("/testthriftmemorybufferreadcheck/OpenAndClose", test_open_and_close);
|
||||
g_test_add_func ("/testthriftmemorybufferreadcheck/ReadAndWrite", test_read_and_write);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
@@ -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 ();
|
||||
}
|
||||
@@ -0,0 +1,645 @@
|
||||
/*
|
||||
* 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 <thrift/config.h>
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#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)
|
||||
noexcept(false) 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) noexcept(false) 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, nullptr);
|
||||
protocol = (ThriftBinaryProtocol *) g_object_new (THRIFT_TYPE_BINARY_PROTOCOL,
|
||||
"transport",
|
||||
tsocket, nullptr);
|
||||
client = (TTestThriftTestClient *) g_object_new (T_TEST_TYPE_THRIFT_TEST_CLIENT, "input_protocol", protocol, "output_protocol", protocol, nullptr);
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,645 @@
|
||||
/*
|
||||
* 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 <thrift/transport/TZlibTransport.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/transport/thrift_zlib_transport.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;
|
||||
ThriftZlibTransport *transport = 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, nullptr);
|
||||
transport = (ThriftZlibTransport *) g_object_new (THRIFT_TYPE_ZLIB_TRANSPORT,
|
||||
"transport", tsocket, nullptr);
|
||||
protocol = (ThriftBinaryProtocol *) g_object_new (THRIFT_TYPE_BINARY_PROTOCOL,
|
||||
"transport",
|
||||
transport, nullptr);
|
||||
client = (TTestThriftTestClient *) g_object_new (T_TEST_TYPE_THRIFT_TEST_CLIENT, "input_protocol", protocol, "output_protocol", protocol, nullptr);
|
||||
iface = T_TEST_THRIFT_TEST_IF (client);
|
||||
|
||||
// open and send
|
||||
thrift_transport_open (THRIFT_TRANSPORT(transport), 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<TZlibTransportFactory> transportFactory(new TZlibTransportFactory());
|
||||
//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;
|
||||
}
|
||||
|
||||
@@ -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 ();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,543 @@
|
||||
/*
|
||||
* 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 = (GObject *)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;
|
||||
|
||||
/* 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((struct sockaddr*)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]", ((guint32)(p->ai_addrlen)), 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((const char*)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((const char*)serial_number, tmp, strlen((const char*)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);
|
||||
THRIFT_UNUSED_VAR (error);
|
||||
THRIFT_UNUSED_VAR (sslSocket);
|
||||
|
||||
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, (const char*)issuer, strlen(ISSUER_CN_PINNING))){
|
||||
g_warning("The Issuer of the certificate is not valid");
|
||||
valid=FALSE;
|
||||
}
|
||||
OPENSSL_free((void*)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, (const char*)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((char*)subject, addr)){
|
||||
g_info("Verified subject");
|
||||
}else{
|
||||
g_info("Cannot verify subject");
|
||||
valid=FALSE;
|
||||
}
|
||||
OPENSSL_free((void*)subject);
|
||||
|
||||
if(!valid)
|
||||
return valid;
|
||||
}
|
||||
|
||||
if(!verify_certificate_sn(cert, (const unsigned char*)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[] = 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;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,231 @@
|
||||
/*
|
||||
* 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', \
|
||||
'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', \
|
||||
'u', 'v', 'w', 'x', 'y', 'z', '1', '2', '3', '4', \
|
||||
'5', '6', '7', '8', '9', '0' }
|
||||
|
||||
#include "../src/thrift/c_glib/transport/thrift_zlib_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;
|
||||
gint urbuf_size = 0;
|
||||
gint crbuf_size = 0;
|
||||
gint uwbuf_size = 0;
|
||||
gint cwbuf_size = 0;
|
||||
gint comp_level = 0;
|
||||
|
||||
GObject *object = NULL;
|
||||
object = g_object_new (THRIFT_TYPE_ZLIB_TRANSPORT, NULL);
|
||||
g_assert (object != NULL);
|
||||
g_object_get (G_OBJECT (object), "transport", &transport,
|
||||
"urbuf_size", &urbuf_size,
|
||||
"crbuf_size", &crbuf_size,
|
||||
"uwbuf_size", &uwbuf_size,
|
||||
"cwbuf_size", &cwbuf_size,
|
||||
"comp_level", &comp_level, 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 ZlibTransport wrapper of the Socket */
|
||||
transport = g_object_new (THRIFT_TYPE_ZLIB_TRANSPORT,
|
||||
"transport", THRIFT_TRANSPORT (tsocket), NULL);
|
||||
|
||||
/* this shouldn't work */
|
||||
g_assert (thrift_zlib_transport_open (transport, NULL) == TRUE);
|
||||
g_assert (thrift_zlib_transport_is_open (transport) == TRUE);
|
||||
g_assert (thrift_zlib_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 ZlibTransport wrapper of the Socket */
|
||||
transport = g_object_new (THRIFT_TYPE_ZLIB_TRANSPORT,
|
||||
"transport", THRIFT_TRANSPORT (tsocket), NULL);
|
||||
|
||||
g_assert (thrift_zlib_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;
|
||||
gchar buf[36] = TEST_DATA;
|
||||
|
||||
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_ZLIB_TRANSPORT,
|
||||
"transport", THRIFT_TRANSPORT (tsocket), NULL);
|
||||
|
||||
g_assert (thrift_zlib_transport_open (transport, NULL) == TRUE);
|
||||
g_assert (thrift_zlib_transport_is_open (transport));
|
||||
|
||||
thrift_zlib_transport_write (transport, buf, 36, NULL);
|
||||
thrift_zlib_transport_flush (transport, NULL);
|
||||
thrift_zlib_transport_write_end (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;
|
||||
gboolean check_sum = FALSE;
|
||||
ThriftServerTransport *transport = NULL;
|
||||
ThriftTransport *client = NULL;
|
||||
gchar buf[36]; /* a buffer */
|
||||
gchar match[36] = 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 ZlibTransport */
|
||||
client = g_object_new (THRIFT_TYPE_ZLIB_TRANSPORT, "transport",
|
||||
thrift_server_transport_accept (transport, NULL),
|
||||
NULL);
|
||||
g_assert (client != NULL);
|
||||
|
||||
/* read 36 bytes */
|
||||
thrift_zlib_transport_read (client, buf, 36, NULL);
|
||||
g_assert (memcmp(buf, match, 36) == 0 );
|
||||
|
||||
thrift_zlib_transport_read_end (client, NULL);
|
||||
|
||||
check_sum = thrift_zlib_transport_verify_checksum (client, NULL);
|
||||
g_assert (!check_sum);
|
||||
|
||||
thrift_zlib_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 ("/testzlibtransport/CreateAndDestroy", test_create_and_destroy);
|
||||
g_test_add_func ("/testzlibtransport/OpenAndClose", test_open_and_close);
|
||||
g_test_add_func ("/testzlibtransport/ReadAndWrite", test_read_and_write);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
@@ -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}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user