From 4b337fe0fa1f733b679014aa1e3b036ccbcd7635 Mon Sep 17 00:00:00 2001 From: Alan Antonuk Date: Tue, 25 Jul 2017 22:25:30 -0700 Subject: Lib: simplify the byte-swap code --- librabbitmq/amqp_connection.c | 44 +++++---- librabbitmq/amqp_private.h | 214 +++++++++++++++++++----------------------- 2 files changed, 123 insertions(+), 135 deletions(-) diff --git a/librabbitmq/amqp_connection.c b/librabbitmq/amqp_connection.c index 85a248d..9d4ebbe 100644 --- a/librabbitmq/amqp_connection.c +++ b/librabbitmq/amqp_connection.c @@ -287,13 +287,13 @@ int amqp_handle_input(amqp_connection_state_t state, decoded_frame->channel = 0; decoded_frame->payload.protocol_header.transport_high - = amqp_d8(raw_frame, 4); + = amqp_d8(amqp_offset(raw_frame, 4)); decoded_frame->payload.protocol_header.transport_low - = amqp_d8(raw_frame, 5); + = amqp_d8(amqp_offset(raw_frame, 5)); decoded_frame->payload.protocol_header.protocol_version_major - = amqp_d8(raw_frame, 6); + = amqp_d8(amqp_offset(raw_frame, 6)); decoded_frame->payload.protocol_header.protocol_version_minor - = amqp_d8(raw_frame, 7); + = amqp_d8(amqp_offset(raw_frame, 7)); return_to_idle(state); return (int)bytes_consumed; @@ -306,10 +306,10 @@ int amqp_handle_input(amqp_connection_state_t state, amqp_channel_t channel; amqp_pool_t *channel_pool; /* frame length is 3 bytes in */ - channel = amqp_d16(raw_frame, 1); + channel = amqp_d16(amqp_offset(raw_frame, 1)); state->target_size - = amqp_d32(raw_frame, 3) + HEADER_SIZE + FOOTER_SIZE; + = amqp_d32(amqp_offset(raw_frame, 3)) + HEADER_SIZE + FOOTER_SIZE; if ((size_t)state->frame_max < state->target_size) { return AMQP_STATUS_BAD_AMQP_DATA; @@ -346,12 +346,13 @@ int amqp_handle_input(amqp_connection_state_t state, amqp_pool_t *channel_pool; /* Check frame end marker (footer) */ - if (amqp_d8(raw_frame, state->target_size - 1) != AMQP_FRAME_END) { + if (amqp_d8(amqp_offset(raw_frame, state->target_size - 1)) != + AMQP_FRAME_END) { return AMQP_STATUS_BAD_AMQP_DATA; } - decoded_frame->frame_type = amqp_d8(raw_frame, 0); - decoded_frame->channel = amqp_d16(raw_frame, 1); + decoded_frame->frame_type = amqp_d8(amqp_offset(raw_frame, 0)); + decoded_frame->channel = amqp_d16(amqp_offset(raw_frame, 1)); channel_pool = amqp_get_or_create_channel_pool(state, decoded_frame->channel); if (NULL == channel_pool) { @@ -360,7 +361,8 @@ int amqp_handle_input(amqp_connection_state_t state, switch (decoded_frame->frame_type) { case AMQP_FRAME_METHOD: - decoded_frame->payload.method.id = amqp_d32(raw_frame, HEADER_SIZE); + decoded_frame->payload.method.id = + amqp_d32(amqp_offset(raw_frame, HEADER_SIZE)); encoded.bytes = amqp_offset(raw_frame, HEADER_SIZE + 4); encoded.len = state->target_size - HEADER_SIZE - 4 - FOOTER_SIZE; @@ -375,10 +377,10 @@ int amqp_handle_input(amqp_connection_state_t state, case AMQP_FRAME_HEADER: decoded_frame->payload.properties.class_id - = amqp_d16(raw_frame, HEADER_SIZE); + = amqp_d16(amqp_offset(raw_frame, HEADER_SIZE)); /* unused 2-byte weight field goes here */ decoded_frame->payload.properties.body_size - = amqp_d64(raw_frame, HEADER_SIZE + 4); + = amqp_d64(amqp_offset(raw_frame, HEADER_SIZE + 4)); encoded.bytes = amqp_offset(raw_frame, HEADER_SIZE + 12); encoded.len = state->target_size - HEADER_SIZE - 12 - FOOTER_SIZE; decoded_frame->payload.properties.raw = encoded; @@ -476,8 +478,8 @@ static int amqp_frame_to_bytes(const amqp_frame_t *frame, amqp_bytes_t buffer, size_t out_frame_len; int res; - amqp_e8(out_frame, 0, frame->frame_type); - amqp_e16(out_frame, 1, frame->channel); + amqp_e8(frame->frame_type, amqp_offset(out_frame, 0)); + amqp_e16(frame->channel, amqp_offset(out_frame, 1)); switch (frame->frame_type) { case AMQP_FRAME_BODY: { @@ -491,7 +493,7 @@ static int amqp_frame_to_bytes(const amqp_frame_t *frame, amqp_bytes_t buffer, case AMQP_FRAME_METHOD: { amqp_bytes_t method_encoded; - amqp_e32(out_frame, HEADER_SIZE, frame->payload.method.id); + amqp_e32(frame->payload.method.id, amqp_offset(out_frame, HEADER_SIZE)); method_encoded.bytes = amqp_offset(out_frame, HEADER_SIZE + 4); method_encoded.len = buffer.len - HEADER_SIZE - 4 - FOOTER_SIZE; @@ -509,9 +511,11 @@ static int amqp_frame_to_bytes(const amqp_frame_t *frame, amqp_bytes_t buffer, case AMQP_FRAME_HEADER: { amqp_bytes_t properties_encoded; - amqp_e16(out_frame, HEADER_SIZE, frame->payload.properties.class_id); - amqp_e16(out_frame, HEADER_SIZE + 2, 0); /* "weight" */ - amqp_e64(out_frame, HEADER_SIZE + 4, frame->payload.properties.body_size); + amqp_e16(frame->payload.properties.class_id, + amqp_offset(out_frame, HEADER_SIZE)); + amqp_e16(0, amqp_offset(out_frame, HEADER_SIZE + 2)); /* "weight" */ + amqp_e64(frame->payload.properties.body_size, + amqp_offset(out_frame, HEADER_SIZE + 4)); properties_encoded.bytes = amqp_offset(out_frame, HEADER_SIZE + 12); properties_encoded.len = buffer.len - HEADER_SIZE - 12 - FOOTER_SIZE; @@ -535,8 +539,8 @@ static int amqp_frame_to_bytes(const amqp_frame_t *frame, amqp_bytes_t buffer, return AMQP_STATUS_INVALID_PARAMETER; } - amqp_e32(out_frame, 3, (uint32_t)out_frame_len); - amqp_e8(out_frame, HEADER_SIZE + out_frame_len, AMQP_FRAME_END); + amqp_e32((uint32_t)out_frame_len, amqp_offset(out_frame, 3)); + amqp_e8(AMQP_FRAME_END, amqp_offset(out_frame, HEADER_SIZE + out_frame_len)); encoded->bytes = out_frame; encoded->len = out_frame_len + HEADER_SIZE + FOOTER_SIZE; diff --git a/librabbitmq/amqp_private.h b/librabbitmq/amqp_private.h index 31ce4ea..e02ae76 100644 --- a/librabbitmq/amqp_private.h +++ b/librabbitmq/amqp_private.h @@ -222,130 +222,114 @@ static inline void *amqp_offset(void *data, size_t offset) /* This macro defines the encoding and decoding functions associated with a simple type. */ -#define DECLARE_CODEC_BASE_TYPE(bits, htonx, ntohx) \ - \ - static inline void amqp_e##bits(void *data, size_t offset, \ - uint##bits##_t val) \ - { \ - /* The AMQP data might be unaligned. So we encode and then copy the \ - result into place. */ \ - uint##bits##_t res = htonx(val); \ - memcpy(amqp_offset(data, offset), &res, bits/8); \ - } \ - \ - static inline uint##bits##_t amqp_d##bits(void *data, size_t offset) \ - { \ - /* The AMQP data might be unaligned. So we copy the source value \ - into a variable and then decode it. */ \ - uint##bits##_t val; \ - memcpy(&val, amqp_offset(data, offset), bits/8); \ - return ntohx(val); \ - } \ - \ - static inline int amqp_encode_##bits(amqp_bytes_t encoded, size_t *offset, \ - uint##bits##_t input) \ - \ - { \ - size_t o = *offset; \ - if ((*offset = o + bits / 8) <= encoded.len) { \ - amqp_e##bits(encoded.bytes, o, input); \ - return 1; \ - } \ - else { \ - return 0; \ - } \ - } \ - \ - static inline int amqp_decode_##bits(amqp_bytes_t encoded, size_t *offset, \ - uint##bits##_t *output) \ - \ - { \ - size_t o = *offset; \ - if ((*offset = o + bits / 8) <= encoded.len) { \ - *output = amqp_d##bits(encoded.bytes, o); \ - return 1; \ - } \ - else { \ - return 0; \ - } \ +#define DECLARE_CODEC_BASE_TYPE(bits) \ + \ + static inline int amqp_encode_##bits(amqp_bytes_t encoded, size_t *offset, \ + uint##bits##_t input) { \ + size_t o = *offset; \ + if ((*offset = o + bits / 8) <= encoded.len) { \ + amqp_e##bits(input, amqp_offset(encoded.bytes, o)); \ + return 1; \ + } \ + return 0; \ + } \ + \ + static inline int amqp_decode_##bits(amqp_bytes_t encoded, size_t *offset, \ + uint##bits##_t *output) { \ + size_t o = *offset; \ + if ((*offset = o + bits / 8) <= encoded.len) { \ + *output = amqp_d##bits(amqp_offset(encoded.bytes, o)); \ + return 1; \ + } \ + return 0; \ } -/* Determine byte order */ -#if defined(__GLIBC__) -# include -# if (__BYTE_ORDER == __LITTLE_ENDIAN) -# define AMQP_LITTLE_ENDIAN -# elif (__BYTE_ORDER == __BIG_ENDIAN) -# define AMQP_BIG_ENDIAN -# else -/* Don't define anything */ -# endif -#elif defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN) || \ - defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__) -# define AMQP_BIG_ENDIAN -#elif defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN) || \ - defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__) -# define AMQP_LITTLE_ENDIAN -#elif defined(__hppa__) || defined(__HPPA__) || defined(__hppa) || \ - defined(_POWER) || defined(__powerpc__) || defined(__ppc___) || \ - defined(_MIPSEB) || defined(__s390__) || \ - defined(__sparc) || defined(__sparc__) -# define AMQP_BIG_ENDIAN -#elif defined(__alpha__) || defined(__alpha) || defined(_M_ALPHA) || \ - defined(__amd64__) || defined(__x86_64__) || defined(_M_X64) || \ - defined(__ia64) || defined(__ia64__) || defined(_M_IA64) || \ - defined(__arm__) || defined(_M_ARM) || \ - defined(__i386__) || defined(_M_IX86) -# define AMQP_LITTLE_ENDIAN -#else -/* Don't define anything */ -#endif +static inline int is_bigendian(void) { + union { + uint32_t i; + char c[4]; + } bint = {0x01020304}; + return bint.c[0] == 1; +} + +static inline void amqp_e8(uint8_t val, void *data) { + memcpy(data, &val, sizeof(val)); +} -#if defined(AMQP_LITTLE_ENDIAN) - -#define DECLARE_XTOXLL(func) \ - static inline uint64_t func##ll(uint64_t val) \ - { \ - union { \ - uint64_t whole; \ - uint32_t halves[2]; \ - } u; \ - uint32_t t; \ - u.whole = val; \ - t = u.halves[0]; \ - u.halves[0] = func##l(u.halves[1]); \ - u.halves[1] = func##l(t); \ - return u.whole; \ +static inline uint8_t amqp_d8(void *data) { + uint8_t val; + memcpy(&val, data, sizeof(val)); + return val; +} + +static inline void amqp_e16(uint16_t val, void *data) { + if (!is_bigendian()) { + val = ((val & 0xFF00u) >> 8u) | ((val & 0x00FFu) << 8u); } + memcpy(data, &val, sizeof(val)); +} -#elif defined(AMQP_BIG_ENDIAN) - -#define DECLARE_XTOXLL(func) \ - static inline uint64_t func##ll(uint64_t val) \ - { \ - union { \ - uint64_t whole; \ - uint32_t halves[2]; \ - } u; \ - u.whole = val; \ - u.halves[0] = func##l(u.halves[0]); \ - u.halves[1] = func##l(u.halves[1]); \ - return u.whole; \ +static inline uint16_t amqp_d16(void *data) { + uint16_t val; + memcpy(&val, data, sizeof(val)); + if (!is_bigendian()) { + val = ((val & 0xFF00u) >> 8u) | ((val & 0x00FFu) << 8u); } + return val; +} -#else -# error Endianness not known -#endif +static inline void amqp_e32(uint32_t val, void* data) { + if (!is_bigendian()) { + val = ((val & 0xFF000000u) >> 24u) | ((val & 0x00FF0000u) >> 8u) | + ((val & 0x0000FF00u) << 8u) | ((val & 0x000000FFu) << 24u); + } + memcpy(data, &val, sizeof(val)); +} -#ifndef HAVE_HTONLL -DECLARE_XTOXLL(hton) -DECLARE_XTOXLL(ntoh) -#endif +static inline uint32_t amqp_d32(void *data) { + uint32_t val; + memcpy(&val, data, sizeof(val)); + if (!is_bigendian()) { + val = ((val & 0xFF000000u) >> 24u) | ((val & 0x00FF0000u) >> 8u) | + ((val & 0x0000FF00u) << 8u) | ((val & 0x000000FFu) << 24u); + } + return val; +} + +static inline void amqp_e64(uint64_t val, void *data) { + if (!is_bigendian()) { + val = ((val & 0xFF00000000000000u) >> 56u) | + ((val & 0x00FF000000000000u) >> 40u) | + ((val & 0x0000FF0000000000u) >> 24u) | + ((val & 0x000000FF00000000u) >> 8u) | + ((val & 0x00000000FF000000u) << 8u) | + ((val & 0x0000000000FF0000u) << 24u) | + ((val & 0x000000000000FF00u) << 40u) | + ((val & 0x00000000000000FFu) << 56u); + } + memcpy(data, &val, sizeof(val)); +} + +static inline uint64_t amqp_d64(void *data) { + uint64_t val; + memcpy(&val, data, sizeof(val)); + if (!is_bigendian()) { + val = ((val & 0xFF00000000000000u) >> 56u) | + ((val & 0x00FF000000000000u) >> 40u) | + ((val & 0x0000FF0000000000u) >> 24u) | + ((val & 0x000000FF00000000u) >> 8u) | + ((val & 0x00000000FF000000u) << 8u) | + ((val & 0x0000000000FF0000u) << 24u) | + ((val & 0x000000000000FF00u) << 40u) | + ((val & 0x00000000000000FFu) << 56u); + } + return val; +} -DECLARE_CODEC_BASE_TYPE(8, (uint8_t), (uint8_t)) -DECLARE_CODEC_BASE_TYPE(16, htons, ntohs) -DECLARE_CODEC_BASE_TYPE(32, htonl, ntohl) -DECLARE_CODEC_BASE_TYPE(64, htonll, ntohll) +DECLARE_CODEC_BASE_TYPE(8) +DECLARE_CODEC_BASE_TYPE(16) +DECLARE_CODEC_BASE_TYPE(32) +DECLARE_CODEC_BASE_TYPE(64) static inline int amqp_encode_bytes(amqp_bytes_t encoded, size_t *offset, amqp_bytes_t input) -- cgit v1.2.1