/* reads a frame and puts it into the buffer */ gboolean thrift_framed_transport_read_frame (ThriftTransport *transport, GError **error) { ThriftFramedTransport *t = THRIFT_FRAMED_TRANSPORT (transport); guint32 sz; gint32 bytes; gboolean result = FALSE; /* read the size */ if (thrift_transport_read (t->transport, &sz, sizeof (sz), error) == sizeof (sz)) { guchar *tmpdata; sz = ntohl (sz); /* create a buffer to hold the data and read that much data */ tmpdata = g_alloca (sz); bytes = thrift_transport_read (t->transport, tmpdata, sz, error); if (bytes > 0 && (error == NULL || *error == NULL)) { /* add the data to the buffer */ g_byte_array_append (t->r_buf, tmpdata, bytes); result = TRUE; } } return result; }
gint32 my_thrift_transport_read (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 (transport, buf, len, error); } return -1; }
int32_t thrift_binary_protocol_read_u64 (ThriftProtocol *protocol, uint64_t *value, int *error) { int32_t ret; void * b[8]; if ((ret = thrift_transport_read (protocol->transport, b, 8, error)) < 0) { return -1; } *value = os_get_value64((uint8_t *)b); return ret; }
int32_t thrift_binary_protocol_read_byte (ThriftProtocol *protocol, int8_t *value, int *error) { int32_t ret; void * b[1]; if ((ret = thrift_transport_read (protocol->transport, b, 1, error)) < 0) { return -1; } *value = *(int8_t *) b; return ret; }
gint32 thrift_binary_protocol_read_byte (ThriftProtocol *protocol, gint8 *value, GError **error) { g_return_val_if_fail (THRIFT_IS_BINARY_PROTOCOL (protocol), -1); gint32 ret; gpointer b[1]; if ((ret = thrift_transport_read (protocol->transport, b, 1, error)) < 0) { return -1; } *value = *(gint8 *) b; return ret; }
gint32 thrift_binary_protocol_read_i64 (ThriftProtocol *protocol, gint64 *value, GError **error) { g_return_val_if_fail (THRIFT_IS_BINARY_PROTOCOL (protocol), -1); gint32 ret; gpointer b[8]; if ((ret = thrift_transport_read (protocol->transport, b, 8, error)) < 0) { return -1; } *value = *(gint64 *) b; *value = GUINT64_FROM_BE (*value); return ret; }
gint32 thrift_binary_protocol_read_i32 (ThriftProtocol *protocol, gint32 *value, GError **error) { g_return_val_if_fail (THRIFT_IS_BINARY_PROTOCOL (protocol), -1); gint32 ret; gpointer b[4]; if ((ret = thrift_transport_read (protocol->transport, b, 4, error)) < 0) { return -1; } *value = *(gint32 *) b; *value = g_ntohl (*value); return ret; }
gint32 thrift_binary_protocol_read_double (ThriftProtocol *protocol, gdouble *value, GError **error) { g_return_val_if_fail (THRIFT_IS_BINARY_PROTOCOL (protocol), -1); gint32 ret; gpointer b[8]; if ((ret = thrift_transport_read (protocol->transport, b, 8, error)) < 0) { return -1; } guint64 bits = *(guint64 *) b; bits = GUINT64_FROM_BE (bits); *value = thrift_bitwise_cast_gdouble (bits); return ret; }
int32_t thrift_binary_protocol_read_u32 (ThriftProtocol *protocol, u_int32_t *value, int *error) { int32_t ret; union { void * b[4]; u_int32_t all; } bytes; if ((ret = thrift_transport_read (protocol->transport, bytes.b, 4, error)) < 0) { return -1; } *value = ntohl (bytes.all); return ret; }
int32_t thrift_binary_protocol_read_i16 (ThriftProtocol *protocol, int16_t *value, int *error) { int32_t ret; union bytes { void * b[2]; int16_t all; } bytes; if ((ret = thrift_transport_read (protocol->transport, bytes.b, 2, error)) < 0) { return -1; } *value = ntohs (bytes.all); return ret; }
gint32 thrift_binary_protocol_read_binary (ThriftProtocol *protocol, gpointer *buf, guint32 *len, GError **error) { g_return_val_if_fail (THRIFT_IS_BINARY_PROTOCOL (protocol), -1); gint32 ret; gint32 xfer = 0; gint32 read_len = 0; /* read the length into read_len */ if ((ret = thrift_protocol_read_i32 (protocol, &read_len, error)) < 0) { return -1; } xfer += ret; if (read_len > 0) { /* allocate the memory as an array of unsigned char for binary data */ *len = (guint32) read_len; *buf = g_new (guchar, *len); if ((ret = thrift_transport_read (protocol->transport, *buf, *len, error)) < 0) { g_free (*buf); *buf = NULL; *len = 0; return -1; } xfer += ret; } else { *buf = NULL; } return xfer; }
gint32 thrift_binary_protocol_read_string (ThriftProtocol *protocol, gchar **str, GError **error) { g_return_val_if_fail (THRIFT_IS_BINARY_PROTOCOL (protocol), -1); guint32 len; gint32 ret; gint32 xfer = 0; gint32 read_len = 0; /* read the length into read_len */ if ((ret = thrift_protocol_read_i32 (protocol, &read_len, error)) < 0) { return -1; } xfer += ret; if (read_len > 0) { /* allocate the memory for the string */ len = (guint32) read_len + 1; // space for null terminator *str = g_new0 (gchar, len); if ((ret = thrift_transport_read (protocol->transport, *str, read_len, error)) < 0) { g_free (*str); *str = NULL; len = 0; return -1; } xfer += ret; } else { *str = NULL; } return xfer; }
int32_t thrift_binary_protocol_read_binary (ThriftProtocol *protocol, void **buf, u_int32_t *len, int *error) { int32_t ret; int32_t xfer = 0; int32_t read_len = 0; /* read the length into read_len */ if ((ret = thrift_protocol_read_i32 (protocol, &read_len, error)) < 0) { return -1; } xfer += ret; if (read_len > 0) { /* allocate the memory as an array of unsigned char for binary data */ *len = (u_int32_t) read_len; *buf = os_malloc (*len); memset (*buf, 0, *len); if ((ret = thrift_transport_read (protocol->transport, *buf, *len, error)) < 0) { os_free (*buf); *buf = NULL; *len = 0; return -1; } xfer += ret; } else { *buf = NULL; } return xfer; }
int32_t thrift_binary_protocol_read_string (ThriftProtocol *protocol, char **str, int *error) { u_int32_t len; int32_t ret; int32_t xfer = 0; int32_t read_len = 0; /* read the length into read_len */ if ((ret = thrift_protocol_read_i32 (protocol, &read_len, error)) < 0) { return -1; } xfer += ret; if (read_len > 0) { /* allocate the memory for the string */ len = (u_int32_t) read_len + 1; // space for null terminator *str = os_malloc (len); memset (*str, 0, len); if ((ret = thrift_transport_read (protocol->transport, *str, read_len, error)) < 0) { os_free (*str); *str = NULL; len = 0; return -1; } xfer += ret; } else { *str = NULL; } return xfer; }
int32_t thrift_binary_protocol_read_double (ThriftProtocol *protocol, double *value, int *error) { #ifndef __KERNEL__ int32_t ret; union { void * b[8]; u_int64_t all; } bytes; if ((ret = thrift_transport_read (protocol->transport, bytes.b, 8, error)) < 0) { return -1; } *value = thrift_bitwise_cast_double (bytes.all); return ret; #else return -1; #endif }
/* test reading from the transport after the peer has unexpectedly closed the connection */ static void test_read_after_peer_close(void) { int status; pid_t pid; int port = 51199; GError *err = NULL; pid = fork (); g_assert (pid >= 0); if (pid == 0) { ThriftServerTransport *server_transport = NULL; ThriftTransport *client_transport = NULL; /* child listens */ server_transport = g_object_new (THRIFT_TYPE_SERVER_SOCKET, "port", port, NULL); g_assert (server_transport != NULL); thrift_server_transport_listen (server_transport, &err); g_assert (err == NULL); /* wrap the client transport in a ThriftFramedTransport */ client_transport = g_object_new (THRIFT_TYPE_FRAMED_TRANSPORT, "transport", thrift_server_transport_accept (server_transport, &err), "r_buf_size", 0, NULL); g_assert (err == NULL); g_assert (client_transport != NULL); /* close the connection immediately after the client connects */ thrift_transport_close (client_transport, NULL); g_object_unref (client_transport); g_object_unref (server_transport); exit (0); } else { ThriftSocket *tsocket = NULL; ThriftTransport *transport = NULL; guchar buf[10]; /* a buffer */ /* parent connects, wait a bit for the socket to be created */ sleep (1); tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost", "port", port, NULL); transport = g_object_new (THRIFT_TYPE_FRAMED_TRANSPORT, "transport", THRIFT_TRANSPORT (tsocket), "w_buf_size", 0, NULL); g_assert (thrift_transport_open (transport, NULL) == TRUE); g_assert (thrift_transport_is_open (transport)); /* attempting to read from the transport after the peer has closed the connection fails gracefully without generating a critical warning or segmentation fault */ thrift_transport_read (transport, buf, 10, &err); g_assert (err != NULL); g_error_free (err); err = NULL; thrift_transport_read_end (transport, &err); g_assert (err == NULL); thrift_transport_close (transport, &err); g_assert (err == NULL); g_object_unref (transport); g_object_unref (tsocket); g_assert (wait (&status) == pid); g_assert (status == 0); } }