From c80b8bbe703f593d1aa47941bd6b61f7726068bd Mon Sep 17 00:00:00 2001 From: zeshuai007 <51382517@qq.com> Date: Thu, 23 Jul 2020 09:43:41 +0800 Subject: THRIFT-5237 Implement MAX_MESSAGE_SIZE and consolidate limits into a TConfiguration class Client: c_glib Patch: Zezeng Wang This closes #2208 --- lib/c_glib/CMakeLists.txt | 1 + lib/c_glib/Makefile.am | 4 +- .../c_glib/protocol/thrift_binary_protocol.c | 65 +++++ .../c_glib/protocol/thrift_binary_protocol.h | 3 + .../c_glib/protocol/thrift_compact_protocol.c | 63 ++++- .../src/thrift/c_glib/protocol/thrift_protocol.c | 16 +- .../src/thrift/c_glib/protocol/thrift_protocol.h | 5 + .../src/thrift/c_glib/thrift_configuration.c | 132 ++++++++++ .../src/thrift/c_glib/thrift_configuration.h | 69 +++++ .../c_glib/transport/thrift_buffered_transport.c | 70 ++++- .../thrift/c_glib/transport/thrift_fd_transport.c | 72 +++++- .../c_glib/transport/thrift_framed_transport.c | 69 ++++- .../thrift/c_glib/transport/thrift_memory_buffer.c | 68 ++++- .../thrift/c_glib/transport/thrift_server_socket.c | 67 ++++- .../c_glib/transport/thrift_server_transport.c | 190 ++++++++++++++ .../c_glib/transport/thrift_server_transport.h | 9 + .../src/thrift/c_glib/transport/thrift_socket.c | 63 ++++- .../thrift/c_glib/transport/thrift_ssl_socket.c | 86 ++++++- .../src/thrift/c_glib/transport/thrift_transport.c | 207 +++++++++++++++ .../src/thrift/c_glib/transport/thrift_transport.h | 14 +- lib/c_glib/test/Makefile.am | 94 ++++++- lib/c_glib/test/testthriftbinaryreadcheck.c | 281 +++++++++++++++++++++ lib/c_glib/test/testthriftbufferedreadcheck.c | 224 ++++++++++++++++ lib/c_glib/test/testthriftcompactreadcheck.c | 275 ++++++++++++++++++++ lib/c_glib/test/testthriftfdreadcheck.c | 182 +++++++++++++ lib/c_glib/test/testthriftframedreadcheck.c | 222 ++++++++++++++++ lib/c_glib/test/testthriftmemorybufferreadcheck.c | 96 +++++++ 27 files changed, 2607 insertions(+), 40 deletions(-) create mode 100644 lib/c_glib/src/thrift/c_glib/thrift_configuration.c create mode 100644 lib/c_glib/src/thrift/c_glib/thrift_configuration.h create mode 100644 lib/c_glib/test/testthriftbinaryreadcheck.c create mode 100755 lib/c_glib/test/testthriftbufferedreadcheck.c create mode 100644 lib/c_glib/test/testthriftcompactreadcheck.c create mode 100755 lib/c_glib/test/testthriftfdreadcheck.c create mode 100755 lib/c_glib/test/testthriftframedreadcheck.c create mode 100755 lib/c_glib/test/testthriftmemorybufferreadcheck.c diff --git a/lib/c_glib/CMakeLists.txt b/lib/c_glib/CMakeLists.txt index d9dc21768..3a1f1880c 100644 --- a/lib/c_glib/CMakeLists.txt +++ b/lib/c_glib/CMakeLists.txt @@ -31,6 +31,7 @@ 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 diff --git a/lib/c_glib/Makefile.am b/lib/c_glib/Makefile.am index fd7f93d76..7619fb4cb 100755 --- a/lib/c_glib/Makefile.am +++ b/lib/c_glib/Makefile.am @@ -32,6 +32,7 @@ AM_CFLAGS = -Wall -Wextra -pedantic 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 \ @@ -67,7 +68,8 @@ 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_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 \ diff --git a/lib/c_glib/src/thrift/c_glib/protocol/thrift_binary_protocol.c b/lib/c_glib/src/thrift/c_glib/protocol/thrift_binary_protocol.c index 7c2d017e1..9e80e107c 100644 --- a/lib/c_glib/src/thrift/c_glib/protocol/thrift_binary_protocol.c +++ b/lib/c_glib/src/thrift/c_glib/protocol/thrift_binary_protocol.c @@ -17,6 +17,7 @@ * under the License. */ +#include #include #include @@ -529,6 +530,9 @@ thrift_binary_protocol_read_map_begin (ThriftProtocol *protocol, 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; @@ -557,6 +561,14 @@ thrift_binary_protocol_read_map_begin (ThriftProtocol *protocol, 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; } @@ -582,6 +594,9 @@ thrift_binary_protocol_read_list_begin (ThriftProtocol *protocol, 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; @@ -603,6 +618,13 @@ thrift_binary_protocol_read_list_begin (ThriftProtocol *protocol, 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; } @@ -855,6 +877,48 @@ thrift_binary_protocol_read_binary (ThriftProtocol *protocol, 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) { @@ -908,4 +972,5 @@ thrift_binary_protocol_class_init (ThriftBinaryProtocolClass *klass) 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; } diff --git a/lib/c_glib/src/thrift/c_glib/protocol/thrift_binary_protocol.h b/lib/c_glib/src/thrift/c_glib/protocol/thrift_binary_protocol.h index 5230bcced..bd8b84eff 100644 --- a/lib/c_glib/src/thrift/c_glib/protocol/thrift_binary_protocol.h +++ b/lib/c_glib/src/thrift/c_glib/protocol/thrift_binary_protocol.h @@ -67,6 +67,9 @@ struct _ThriftBinaryProtocolClass /* 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 */ diff --git a/lib/c_glib/src/thrift/c_glib/protocol/thrift_compact_protocol.c b/lib/c_glib/src/thrift/c_glib/protocol/thrift_compact_protocol.c index cae4749f0..0aa9a6fe6 100644 --- a/lib/c_glib/src/thrift/c_glib/protocol/thrift_compact_protocol.c +++ b/lib/c_glib/src/thrift/c_glib/protocol/thrift_compact_protocol.c @@ -1051,6 +1051,8 @@ thrift_compact_protocol_read_map_begin (ThriftProtocol *protocol, gint32 msize; ThriftCompactProtocol *cp; + ThriftProtocol *tp = THRIFT_PROTOCOL (protocol); + ThriftTransportClass *ttc = THRIFT_TRANSPORT_GET_CLASS (tp->transport); g_return_val_if_fail (THRIFT_IS_COMPACT_PROTOCOL (protocol), -1); @@ -1106,6 +1108,14 @@ thrift_compact_protocol_read_map_begin (ThriftProtocol *protocol, return -1; } + if(!ttc->checkReadBytesAvailable (THRIFT_TRANSPORT (tp->transport), + msize * thrift_protocol_get_min_serialized_size (protocol, *key_type, error) + + msize * thrift_protocol_get_min_serialized_size (protocol, *value_type, error), + error)) + { + return -1; + } + return xfer; } @@ -1124,7 +1134,8 @@ thrift_compact_protocol_read_list_begin (ThriftProtocol *protocol, guint32 *size, GError **error) { ThriftCompactProtocol *cp; - + ThriftProtocol *tp = THRIFT_PROTOCOL (protocol); + ThriftTransportClass *ttc = THRIFT_TRANSPORT_GET_CLASS (tp->transport); gint32 ret; gint32 xfer; @@ -1172,6 +1183,13 @@ thrift_compact_protocol_read_list_begin (ThriftProtocol *protocol, *element_type = ret; *size = (guint32) lsize; + if(!ttc->checkReadBytesAvailable (THRIFT_TRANSPORT (tp->transport), + (lsize * thrift_protocol_get_min_serialized_size (protocol, *element_type, error)), + error)) + { + return -1; + } + return xfer; } @@ -1479,6 +1497,48 @@ thrift_compact_protocol_read_binary (ThriftProtocol *protocol, return xfer; } +gint +thrift_compact_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_DOUBLE: + return 8; + case T_BYTE: + return sizeof(gint8); + case T_I16: + return sizeof(gint8); + case T_I32: + return sizeof(gint8); + case T_I64: + return sizeof(gint8); + case T_STRING: + return sizeof(gint8); + case T_STRUCT: + return 0; + case T_MAP: + return sizeof(gint8); + case T_SET: + return sizeof(gint8); + case T_LIST: + return sizeof(gint8); + default: + g_set_error(error, + THRIFT_PROTOCOL_ERROR, + THRIFT_PROTOCOL_ERROR_INVALID_DATA, + "unrecognized type"); + return -1; + } +} + /* property accessor */ void thrift_compact_protocol_get_property (GObject *object, guint property_id, @@ -1600,6 +1660,7 @@ thrift_compact_protocol_class_init (ThriftCompactProtocolClass *klass) cls->read_double = thrift_compact_protocol_read_double; cls->read_string = thrift_compact_protocol_read_string; cls->read_binary = thrift_compact_protocol_read_binary; + cls->get_min_serialized_size = thrift_compact_protocol_get_min_serialized_size; } static void diff --git a/lib/c_glib/src/thrift/c_glib/protocol/thrift_protocol.c b/lib/c_glib/src/thrift/c_glib/protocol/thrift_protocol.c index 6e6ae4d9a..252f4bec9 100644 --- a/lib/c_glib/src/thrift/c_glib/protocol/thrift_protocol.c +++ b/lib/c_glib/src/thrift/c_glib/protocol/thrift_protocol.c @@ -419,6 +419,13 @@ thrift_protocol_read_binary (ThriftProtocol *protocol, gpointer *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); \ @@ -598,10 +605,10 @@ thrift_protocol_class_init (ThriftProtocolClass *cls) 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)); + 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; @@ -643,4 +650,5 @@ thrift_protocol_class_init (ThriftProtocolClass *cls) 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; } diff --git a/lib/c_glib/src/thrift/c_glib/protocol/thrift_protocol.h b/lib/c_glib/src/thrift/c_glib/protocol/thrift_protocol.h index 58fe5e0af..d9369a66d 100644 --- a/lib/c_glib/src/thrift/c_glib/protocol/thrift_protocol.h +++ b/lib/c_glib/src/thrift/c_glib/protocol/thrift_protocol.h @@ -86,6 +86,7 @@ struct _ThriftProtocol /* protected */ ThriftTransport *transport; + }; typedef struct _ThriftProtocolClass ThriftProtocolClass; @@ -171,6 +172,7 @@ struct _ThriftProtocolClass 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 */ @@ -317,6 +319,9 @@ 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); diff --git a/lib/c_glib/src/thrift/c_glib/thrift_configuration.c b/lib/c_glib/src/thrift/c_glib/thrift_configuration.c new file mode 100644 index 000000000..5b9ed1493 --- /dev/null +++ b/lib/c_glib/src/thrift/c_glib/thrift_configuration.c @@ -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 +#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); +} diff --git a/lib/c_glib/src/thrift/c_glib/thrift_configuration.h b/lib/c_glib/src/thrift/c_glib/thrift_configuration.h new file mode 100644 index 000000000..87f2e3ed6 --- /dev/null +++ b/lib/c_glib/src/thrift/c_glib/thrift_configuration.h @@ -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 + +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 */ diff --git a/lib/c_glib/src/thrift/c_glib/transport/thrift_buffered_transport.c b/lib/c_glib/src/thrift/c_glib/transport/thrift_buffered_transport.c index f13c5a329..30aa95caf 100644 --- a/lib/c_glib/src/thrift/c_glib/transport/thrift_buffered_transport.c +++ b/lib/c_glib/src/thrift/c_glib/transport/thrift_buffered_transport.c @@ -17,6 +17,7 @@ * under the License. */ +#include #include #include #include @@ -33,7 +34,10 @@ 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_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) @@ -82,6 +86,7 @@ thrift_buffered_transport_read_slow (ThriftTransport *transport, gpointer buf, 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); @@ -142,6 +147,11 @@ 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 */ @@ -243,6 +253,12 @@ 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) { @@ -296,6 +312,8 @@ thrift_buffered_transport_get_property (GObject *object, guint property_id, { ThriftBufferedTransport *transport = THRIFT_BUFFERED_TRANSPORT (object); + ThriftTransport *tt = THRIFT_TRANSPORT (object); + THRIFT_UNUSED_VAR (pspec); switch (property_id) @@ -309,6 +327,15 @@ thrift_buffered_transport_get_property (GObject *object, guint property_id, 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; } } @@ -319,6 +346,8 @@ thrift_buffered_transport_set_property (GObject *object, guint property_id, { ThriftBufferedTransport *transport = THRIFT_BUFFERED_TRANSPORT (object); + ThriftTransport *tt = THRIFT_TRANSPORT (object); + THRIFT_UNUSED_VAR (pspec); switch (property_id) @@ -332,6 +361,15 @@ thrift_buffered_transport_set_property (GObject *object, guint property_id, 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; } } @@ -379,6 +417,36 @@ thrift_buffered_transport_class_init (ThriftBufferedTransportClass *cls) 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; diff --git a/lib/c_glib/src/thrift/c_glib/transport/thrift_fd_transport.c b/lib/c_glib/src/thrift/c_glib/transport/thrift_fd_transport.c index 14abff7a4..1e2712c32 100644 --- a/lib/c_glib/src/thrift/c_glib/transport/thrift_fd_transport.c +++ b/lib/c_glib/src/thrift/c_glib/transport/thrift_fd_transport.c @@ -26,6 +26,7 @@ #include #include +#include #include #include @@ -33,7 +34,10 @@ enum _ThriftFDTransportProperties { PROP_0, - PROP_THRIFT_FD_TRANSPORT_FD + 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) @@ -87,6 +91,12 @@ thrift_fd_transport_read (ThriftTransport *transport, gpointer buf, 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, @@ -157,6 +167,12 @@ 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, @@ -194,10 +210,21 @@ thrift_fd_transport_get_property (GObject *object, guint property_id, 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; @@ -215,10 +242,21 @@ thrift_fd_transport_set_property (GObject *object, guint property_id, 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; @@ -253,6 +291,38 @@ thrift_fd_transport_class_init (ThriftFDTransportClass *cls) 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; diff --git a/lib/c_glib/src/thrift/c_glib/transport/thrift_framed_transport.c b/lib/c_glib/src/thrift/c_glib/transport/thrift_framed_transport.c index c54824635..1faf16ecb 100644 --- a/lib/c_glib/src/thrift/c_glib/transport/thrift_framed_transport.c +++ b/lib/c_glib/src/thrift/c_glib/transport/thrift_framed_transport.c @@ -17,6 +17,7 @@ * under the License. */ +#include #include #include #include @@ -26,6 +27,7 @@ #include #include +#include #include #include @@ -35,7 +37,10 @@ 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_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) @@ -152,6 +157,12 @@ 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 */ @@ -224,9 +235,15 @@ 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); @@ -286,6 +303,7 @@ 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); @@ -300,6 +318,15 @@ thrift_framed_transport_get_property (GObject *object, guint property_id, 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; } } @@ -309,6 +336,7 @@ 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); @@ -323,6 +351,15 @@ thrift_framed_transport_set_property (GObject *object, guint property_id, 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); + 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; } } @@ -370,6 +407,36 @@ thrift_framed_transport_class_init (ThriftFramedTransportClass *cls) 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; diff --git a/lib/c_glib/src/thrift/c_glib/transport/thrift_memory_buffer.c b/lib/c_glib/src/thrift/c_glib/transport/thrift_memory_buffer.c index 91818e91a..d38d494b6 100644 --- a/lib/c_glib/src/thrift/c_glib/transport/thrift_memory_buffer.c +++ b/lib/c_glib/src/thrift/c_glib/transport/thrift_memory_buffer.c @@ -17,6 +17,7 @@ * under the License. */ +#include #include #include #include @@ -24,6 +25,7 @@ #include #include +#include #include #include @@ -33,7 +35,10 @@ enum _ThriftMemoryBufferProperties PROP_0, PROP_THRIFT_MEMORY_BUFFER_BUFFER_SIZE, PROP_THRIFT_MEMORY_BUFFER_BUFFER, - PROP_THRIFT_MEMORY_BUFFER_OWNER + 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) @@ -70,9 +75,14 @@ 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; - THRIFT_UNUSED_VAR (error); + 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 */ @@ -168,6 +178,8 @@ 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); @@ -182,6 +194,15 @@ thrift_memory_buffer_get_property (GObject *object, guint property_id, 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; @@ -195,6 +216,8 @@ thrift_memory_buffer_set_property (GObject *object, guint property_id, { ThriftMemoryBuffer *t = THRIFT_MEMORY_BUFFER (object); + ThriftTransport *tt = THRIFT_TRANSPORT (object); + THRIFT_UNUSED_VAR (pspec); switch (property_id) @@ -208,6 +231,15 @@ thrift_memory_buffer_set_property (GObject *object, guint property_id, 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; @@ -272,6 +304,38 @@ thrift_memory_buffer_class_init (ThriftMemoryBufferClass *cls) 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; diff --git a/lib/c_glib/src/thrift/c_glib/transport/thrift_server_socket.c b/lib/c_glib/src/thrift/c_glib/transport/thrift_server_socket.c index 438b38d60..1abd615f0 100644 --- a/lib/c_glib/src/thrift/c_glib/transport/thrift_server_socket.c +++ b/lib/c_glib/src/thrift/c_glib/transport/thrift_server_socket.c @@ -38,7 +38,10 @@ enum _ThriftServerSocketProperties PROP_0, PROP_THRIFT_SERVER_SOCKET_PORT, PROP_THRIFT_SERVER_SOCKET_PATH, - PROP_THRIFT_SERVER_SOCKET_BACKLOG + 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 */ @@ -141,6 +144,7 @@ thrift_server_socket_accept (ThriftServerTransport *transport, GError **error) 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) { @@ -151,7 +155,16 @@ thrift_server_socket_accept (ThriftServerTransport *transport, GError **error) return NULL; } - socket = g_object_new (THRIFT_TYPE_SOCKET, 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); @@ -207,6 +220,7 @@ 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) { @@ -219,6 +233,15 @@ thrift_server_socket_get_property (GObject *object, guint property_id, 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; @@ -231,6 +254,7 @@ 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) { @@ -246,6 +270,15 @@ thrift_server_socket_set_property (GObject *object, guint property_id, 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; @@ -298,6 +331,36 @@ thrift_server_socket_class_init (ThriftServerSocketClass *cls) 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; diff --git a/lib/c_glib/src/thrift/c_glib/transport/thrift_server_transport.c b/lib/c_glib/src/thrift/c_glib/transport/thrift_server_transport.c index c25d1384f..687301194 100644 --- a/lib/c_glib/src/thrift/c_glib/transport/thrift_server_transport.c +++ b/lib/c_glib/src/thrift/c_glib/transport/thrift_server_transport.c @@ -21,15 +21,205 @@ #include #include +/* 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_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); + 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; + c->updateKnownMessageSize = thrift_server_transport_updateKnownMessageSize; + c->checkReadBytesAvailable = thrift_server_transport_checkReadBytesAvailable; + c->resetConsumedMessageSize = thrift_server_transport_resetConsumedMessageSize; + c->countConsumedMessageBytes = thrift_server_transport_countConsumedMessageBytes; } static void diff --git a/lib/c_glib/src/thrift/c_glib/transport/thrift_server_transport.h b/lib/c_glib/src/thrift/c_glib/transport/thrift_server_transport.h index 98a9191bd..0fb55c001 100644 --- a/lib/c_glib/src/thrift/c_glib/transport/thrift_server_transport.h +++ b/lib/c_glib/src/thrift/c_glib/transport/thrift_server_transport.h @@ -43,6 +43,11 @@ typedef struct _ThriftServerTransport ThriftServerTransport; struct _ThriftServerTransport { GObject parent; + + /* protected */ + ThriftConfiguration *configuration; + glong remainingMessageSize_; + glong knowMessageSize_; }; typedef struct _ThriftServerTransportClass ThriftServerTransportClass; @@ -58,6 +63,10 @@ struct _ThriftServerTransportClass gboolean (*listen) (ThriftServerTransport *transport, GError **error); ThriftTransport *(*accept) (ThriftServerTransport *transport, GError **error); gboolean (*close) (ThriftServerTransport *transport, 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_SERVER_TRANSPORT */ diff --git a/lib/c_glib/src/thrift/c_glib/transport/thrift_socket.c b/lib/c_glib/src/thrift/c_glib/transport/thrift_socket.c index b7b413910..cc746aacd 100644 --- a/lib/c_glib/src/thrift/c_glib/transport/thrift_socket.c +++ b/lib/c_glib/src/thrift/c_glib/transport/thrift_socket.c @@ -27,6 +27,7 @@ #include #include +#include #include #include @@ -36,7 +37,10 @@ enum _ThriftSocketProperties PROP_0, PROP_THRIFT_SOCKET_HOSTNAME, PROP_THRIFT_SOCKET_PORT, - PROP_THRIFT_SOCKET_PATH + 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) @@ -151,7 +155,7 @@ thrift_socket_open (ThriftTransport *transport, GError **error) /* open a connection */ if (connect (tsocket->sd, (struct sockaddr *) &pin, sizeof(pin)) == -1) { - thrift_socket_close(tsocket, NULL); + 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)); @@ -214,6 +218,11 @@ thrift_socket_read (ThriftTransport *transport, gpointer buf, 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) { @@ -327,6 +336,7 @@ 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); @@ -341,6 +351,15 @@ thrift_socket_get_property (GObject *object, guint property_id, 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; } } @@ -350,6 +369,7 @@ 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); @@ -370,6 +390,14 @@ thrift_socket_set_property (GObject *object, guint property_id, } 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); } } @@ -414,6 +442,37 @@ thrift_socket_class_init (ThriftSocketClass *cls) 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; diff --git a/lib/c_glib/src/thrift/c_glib/transport/thrift_ssl_socket.c b/lib/c_glib/src/thrift/c_glib/transport/thrift_ssl_socket.c index dcb2f8681..0835891b9 100644 --- a/lib/c_glib/src/thrift/c_glib/transport/thrift_ssl_socket.c +++ b/lib/c_glib/src/thrift/c_glib/transport/thrift_ssl_socket.c @@ -31,6 +31,7 @@ #include #include +#include #include #include #include @@ -57,7 +58,10 @@ enum _ThriftSSLSocketProperties { PROP_THRIFT_SSL_SOCKET_CONTEXT = 3, - PROP_THRIFT_SSL_SELF_SIGNED + 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 */ @@ -294,6 +298,11 @@ thrift_ssl_socket_read (ThriftTransport *transport, gpointer buf, 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++) { @@ -369,8 +378,15 @@ 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); @@ -588,6 +604,8 @@ 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) @@ -595,6 +613,15 @@ thrift_ssl_socket_get_property (GObject *object, guint 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; } } @@ -604,6 +631,7 @@ 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) @@ -619,6 +647,15 @@ thrift_ssl_socket_set_property (GObject *object, guint property_id, 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); */ @@ -683,18 +720,45 @@ thrift_ssl_socket_class_init (ThriftSSLSocketClass *cls) 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); + "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); param_spec = g_param_spec_boolean ("ssl_accept_selfsigned", - "Accept Self Signed", - "Whether or not accept self signed certificate", - FALSE, - G_PARAM_READWRITE); + "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); + 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; diff --git a/lib/c_glib/src/thrift/c_glib/transport/thrift_transport.c b/lib/c_glib/src/thrift/c_glib/transport/thrift_transport.c index 9dd267143..b876b076d 100644 --- a/lib/c_glib/src/thrift/c_glib/transport/thrift_transport.c +++ b/lib/c_glib/src/thrift/c_glib/transport/thrift_transport.c @@ -17,8 +17,20 @@ * under the License. */ +#include +#include #include #include +#include + +/* 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" @@ -129,6 +141,142 @@ thrift_transport_real_read_all (ThriftTransport *transport, gpointer buf, 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) @@ -136,10 +284,64 @@ 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; + + 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; @@ -153,6 +355,11 @@ thrift_transport_class_init (ThriftTransportClass *cls) /* 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 diff --git a/lib/c_glib/src/thrift/c_glib/transport/thrift_transport.h b/lib/c_glib/src/thrift/c_glib/transport/thrift_transport.h index 94bb6f507..83fb5da19 100644 --- a/lib/c_glib/src/thrift/c_glib/transport/thrift_transport.h +++ b/lib/c_glib/src/thrift/c_glib/transport/thrift_transport.h @@ -22,6 +22,8 @@ #include +#include + G_BEGIN_DECLS /*! \file thrift_transport.h @@ -50,6 +52,11 @@ typedef struct _ThriftTransport ThriftTransport; struct _ThriftTransport { GObject parent; + + /* protected */ + ThriftConfiguration *configuration; + glong remainingMessageSize_; + glong knowMessageSize_; }; typedef struct _ThriftTransportClass ThriftTransportClass; @@ -75,6 +82,10 @@ struct _ThriftTransportClass 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 */ @@ -161,7 +172,8 @@ typedef enum THRIFT_TRANSPORT_ERROR_CONNECT, THRIFT_TRANSPORT_ERROR_SEND, THRIFT_TRANSPORT_ERROR_RECEIVE, - THRIFT_TRANSPORT_ERROR_CLOSE + THRIFT_TRANSPORT_ERROR_CLOSE, + THRIFT_TRANSPORT_ERROR_MAX_MESSAGE_SIZE_REACHED } ThriftTransportError; /* define an error domain for GError to use */ diff --git a/lib/c_glib/test/Makefile.am b/lib/c_glib/test/Makefile.am index c99e0da83..3ff48a316 100755 --- a/lib/c_glib/test/Makefile.am +++ b/lib/c_glib/test/Makefile.am @@ -58,7 +58,13 @@ check_PROGRAMS = \ testsimpleserver \ testdebugproto \ testoptionalrequired \ - testthrifttest + testthrifttest \ + testthriftbinaryreadcheck \ + testthriftcompactreadcheck \ + testthriftbufferedreadcheck \ + testthriftfdreadcheck \ + testthriftframedreadcheck \ + testthriftmemorybufferreadcheck if WITH_CPP BUILT_SOURCES += gen-cpp/ThriftTest_types.cpp @@ -69,6 +75,7 @@ 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 @@ -76,7 +83,8 @@ 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/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 = \ @@ -92,14 +100,16 @@ testcontainertest_LDADD = \ $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_server_transport.o \ $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_server_socket.o \ $(top_builddir)/lib/c_glib/src/thrift/c_glib/server/libthrift_c_glib_la-thrift_server.o \ - libtestgenc.la + $(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/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 @@ -108,7 +118,8 @@ testtransportsslsocket_LDADD = \ $(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/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 @@ -118,7 +129,8 @@ testbinaryprotocol_LDADD = \ $(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/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 = \ @@ -127,35 +139,41 @@ testcompactprotocol_LDADD = \ $(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/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/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/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/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/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/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 = \ @@ -169,7 +187,8 @@ testsimpleserver_LDADD = \ $(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/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 @@ -178,6 +197,7 @@ 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 @@ -185,6 +205,54 @@ 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 diff --git a/lib/c_glib/test/testthriftbinaryreadcheck.c b/lib/c_glib/test/testthriftbinaryreadcheck.c new file mode 100644 index 000000000..36454ca44 --- /dev/null +++ b/lib/c_glib/test/testthriftbinaryreadcheck.c @@ -0,0 +1,281 @@ +/* + * 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 +#define __NO_STRING_INLINES 1 +#endif + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#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(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; + gint32 ret = 0; + guint32 size = 0; + glong tempsize = 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 (); +} diff --git a/lib/c_glib/test/testthriftbufferedreadcheck.c b/lib/c_glib/test/testthriftbufferedreadcheck.c new file mode 100755 index 000000000..147207294 --- /dev/null +++ b/lib/c_glib/test/testthriftbufferedreadcheck.c @@ -0,0 +1,224 @@ +/* + * 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 +#include +#include + +#include +#include +#include +#include + +#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) +{ + ThriftConfiguration *tconfiguration = NULL; + 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 +#endif + +#ifdef __GLIBC__ +#define __NO_STRING_INLINES 1 +#endif + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#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, field_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 (); +} diff --git a/lib/c_glib/test/testthriftfdreadcheck.c b/lib/c_glib/test/testthriftfdreadcheck.c new file mode 100755 index 000000000..986b70d71 --- /dev/null +++ b/lib/c_glib/test/testthriftfdreadcheck.c @@ -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 +#include +#include +#include + +#include +#include + +#include +#include + +#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 (); +} diff --git a/lib/c_glib/test/testthriftframedreadcheck.c b/lib/c_glib/test/testthriftframedreadcheck.c new file mode 100755 index 000000000..95e853f87 --- /dev/null +++ b/lib/c_glib/test/testthriftframedreadcheck.c @@ -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 +#include + +#include +#include +#include +#include + +#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 + +#include +#include +#include +#include + +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 (); +} -- cgit v1.2.1