diff options
| author | Ted Ross <tross@apache.org> | 2013-05-09 19:06:32 +0000 |
|---|---|---|
| committer | Ted Ross <tross@apache.org> | 2013-05-09 19:06:32 +0000 |
| commit | 9b2bcff0a85ab36c547da2001616a2b0dd13146a (patch) | |
| tree | 67ac9f890598a340d751f974eda8000decc942c6 /qpid/extras/dispatch/src/iterator.c | |
| parent | 8fc7c8e492a0b8e594dcf08c8649976b7a6d4753 (diff) | |
| download | qpid-python-9b2bcff0a85ab36c547da2001616a2b0dd13146a.tar.gz | |
NO-JIRA - Dispatch work-in-progress.
- Added Map validation and access for in-buffer fields
Note that 'iterator' and 'message' require some refactoring and cleanup
- Added Agent handler for 'get' requests.
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@1480739 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'qpid/extras/dispatch/src/iterator.c')
| -rw-r--r-- | qpid/extras/dispatch/src/iterator.c | 286 |
1 files changed, 285 insertions, 1 deletions
diff --git a/qpid/extras/dispatch/src/iterator.c b/qpid/extras/dispatch/src/iterator.c index 92a7a1f479..44cc152bd9 100644 --- a/qpid/extras/dispatch/src/iterator.c +++ b/qpid/extras/dispatch/src/iterator.c @@ -20,10 +20,13 @@ #include <qpid/dispatch/iterator.h> #include <qpid/dispatch/ctools.h> #include <qpid/dispatch/alloc.h> +#include <qpid/dispatch/log.h> #include "message_private.h" #include <stdio.h> #include <string.h> +static const char *log_module = "FIELD"; + typedef enum { MODE_TO_END, MODE_TO_SLASH @@ -44,13 +47,35 @@ struct dx_field_iterator_t { unsigned char prefix; int at_prefix; int view_prefix; + unsigned char tag; }; - ALLOC_DECLARE(dx_field_iterator_t); ALLOC_DEFINE(dx_field_iterator_t); +typedef struct dx_field_pair_t { + DEQ_LINKS(struct dx_field_pair_t); + dx_field_iterator_t *key_iter; + dx_field_iterator_t *value_iter; +} dx_field_pair_t; + +DEQ_DECLARE(dx_field_pair_t, dx_field_pair_list_t); + +ALLOC_DECLARE(dx_field_pair_t); +ALLOC_DEFINE(dx_field_pair_t); + + +struct dx_field_map_t { + dx_field_iterator_t *outer; + int key_count; + dx_field_pair_list_t pairs; +}; + +ALLOC_DECLARE(dx_field_map_t); +ALLOC_DEFINE(dx_field_map_t); + + typedef enum { STATE_START, STATE_SLASH_LEFT, @@ -238,6 +263,7 @@ dx_field_iterator_t* dx_field_iterator_string(const char *text, dx_iterator_view if (!iter) return 0; + iter->tag = 0; iter->start_pointer.buffer = 0; iter->start_pointer.cursor = (unsigned char*) text; iter->start_pointer.length = strlen(text); @@ -254,6 +280,7 @@ dx_field_iterator_t *dx_field_iterator_buffer(dx_buffer_t *buffer, int offset, i if (!iter) return 0; + iter->tag = 0; iter->start_pointer.buffer = buffer; iter->start_pointer.cursor = dx_buffer_base(buffer) + offset; iter->start_pointer.length = length; @@ -360,6 +387,81 @@ int dx_field_iterator_prefix(dx_field_iterator_t *iter, const char *prefix) } +static dx_field_iterator_t *dx_field_parse_amqp_value(dx_field_iterator_t *iter, unsigned int *available) +{ + if (*available < 1) + return 0; + + unsigned int start = *available; + dx_field_iterator_t *value = new_dx_field_iterator_t(); + value->start_pointer = iter->pointer; + value->view = ITER_VIEW_ALL; + value->mode = MODE_TO_END; + value->at_prefix = 0; + value->view_prefix = 0; + + unsigned char tag = dx_field_iterator_octet(iter); + unsigned int length; + unsigned int length_size = 0; + + (*available)--; + + switch (tag & 0xF0) { + case 0x40: length = 0; break; + case 0x50: length = 1; break; + case 0x60: length = 2; break; + case 0x70: length = 4; break; + case 0x80: length = 8; break; + case 0x90: length = 16; break; + case 0xA0: + case 0xC0: + case 0xE0: length_size = 1; break; + case 0xB0: + case 0xD0: + case 0xF0: length_size = 4; break; + default: + free_dx_field_iterator_t(value); + return 0; + } + + if (*available < length_size) { + free_dx_field_iterator_t(value); + return 0; + } + + if (length_size == 1) { + length = (unsigned int) dx_field_iterator_octet(iter); + } else if (length_size == 4) { + length = ((unsigned int) dx_field_iterator_octet(iter)) << 24; + length += ((unsigned int) dx_field_iterator_octet(iter)) << 16; + length += ((unsigned int) dx_field_iterator_octet(iter)) << 8; + length += (unsigned int) dx_field_iterator_octet(iter); + } + + if (*available < length) { + free_dx_field_iterator_t(value); + return 0; + } + + for (unsigned int idx = 0; idx < length; idx++) + (void) dx_field_iterator_octet(iter); + (*available) -= (length + length_size); + + value->start_pointer.length = start - *available; + value->view_start_pointer = value->start_pointer; + value->pointer = value->start_pointer; + value->tag = tag; + + return value; +} + + +static int dx_tag_is_string(unsigned char tag) +{ + return (tag == 0xa1 || tag == 0xb1); +} + + unsigned char *dx_field_iterator_copy(dx_field_iterator_t *iter) { int length = 0; @@ -381,3 +483,185 @@ unsigned char *dx_field_iterator_copy(dx_field_iterator_t *iter) return copy; } + +dx_field_map_t *dx_field_map(dx_field_iterator_t *iter, int string_keys_only) +{ + dx_field_iterator_reset(iter); + unsigned char tag = dx_field_iterator_octet(iter); + + // + // If this field is not a map, return 0; + // + if (tag != 0xc1 && tag != 0xd1) { + dx_log(log_module, LOG_TRACE, "dx_field_map - Invalid Map, Unexpected tag: %02x", tag); + return 0; + } + + // + // Validate the map. Ensure the following: + // - There are an even number of fields in the compound structure + // - There are anough octets in the field to account for all of the contents + // - The field count matches the number of fields present + // - The keys are strings (if string_keys_only) + // + unsigned int length; + unsigned int count; + + if (tag == 0xc1) { + length = (unsigned int) dx_field_iterator_octet(iter); + count = (unsigned int) dx_field_iterator_octet(iter); + length -= 1; // Account for the 'count' octet + } else { + length = ((unsigned int) dx_field_iterator_octet(iter)) << 24; + length += ((unsigned int) dx_field_iterator_octet(iter)) << 16; + length += ((unsigned int) dx_field_iterator_octet(iter)) << 8; + length += (unsigned int) dx_field_iterator_octet(iter); + + count = ((unsigned int) dx_field_iterator_octet(iter)) << 24; + count += ((unsigned int) dx_field_iterator_octet(iter)) << 16; + count += ((unsigned int) dx_field_iterator_octet(iter)) << 8; + count += (unsigned int) dx_field_iterator_octet(iter); + + length -= 4; // Account for the 'count' octets + } + + // + // The map is not valid if count is not an even number. + // + if (count & 1) { + dx_log(log_module, LOG_TRACE, "dx_field_map - Invalid Map, odd number of fields: %d", count); + return 0; + } + + dx_field_map_t *map = new_dx_field_map_t(); + if (!map) + return 0; + + map->outer = iter; + map->key_count = count >> 1; + DEQ_INIT(map->pairs); + + unsigned int idx; + for (idx = 0; idx < map->key_count; idx++) { + dx_field_iterator_t *key = dx_field_parse_amqp_value(iter, &length); + dx_field_iterator_t *value = dx_field_parse_amqp_value(iter, &length); + + if (key == 0 || value == 0) { + dx_field_map_free(map); + return 0; + } + + if (string_keys_only && !dx_tag_is_string(key->tag)) { + dx_log(log_module, LOG_TRACE, "dx_field_map - Invalid Map, key tag is not a string: %02x", key->tag); + dx_field_map_free(map); + return 0; + } + + dx_field_pair_t *pair = new_dx_field_pair_t(); + if (!pair) { + dx_field_map_free(map); + return 0; + } + + DEQ_ITEM_INIT(pair); + pair->key_iter = key; + pair->value_iter = value; + DEQ_INSERT_TAIL(map->pairs, pair); + } + + return map; +} + + +void dx_field_map_free(dx_field_map_t *map) +{ + if (!map) + return; + + dx_field_pair_t *pair = DEQ_HEAD(map->pairs); + while (pair) { + DEQ_REMOVE_HEAD(map->pairs); + free_dx_field_iterator_t(pair->key_iter); + free_dx_field_iterator_t(pair->value_iter); + free_dx_field_pair_t(pair); + pair = DEQ_HEAD(map->pairs); + } + + free_dx_field_map_t(map); +} + + +dx_field_iterator_t *dx_field_map_by_key(dx_field_map_t *map, const char *key) +{ + dx_field_iterator_t *key_string; + dx_field_iterator_t *value = 0; + dx_field_pair_t *pair = DEQ_HEAD(map->pairs); + + while (pair && !value) { + key_string = dx_field_string(pair->key_iter); + if (dx_field_iterator_equal(key_string, (const unsigned char*) key)) + value = pair->value_iter; + free_dx_field_iterator_t(key_string); + pair = DEQ_NEXT(pair); + } + + return value; +} + + +static unsigned int dx_field_get_length(dx_field_iterator_t *iter, unsigned char tag) { + unsigned long length = 0; + + switch (tag & 0xF0) { + case 0x40: return 0; + case 0x50: return 1; + case 0x60: return 2; + case 0x70: return 4; + case 0x80: return 8; + case 0x90: return 16; + case 0xB0: + case 0xD0: + case 0xF0: + length += ((unsigned int) dx_field_iterator_octet(iter)) << 24; + length += ((unsigned int) dx_field_iterator_octet(iter)) << 16; + length += ((unsigned int) dx_field_iterator_octet(iter)) << 8; + // fall through to the next case + + case 0xA0: + case 0xC0: + case 0xE0: + length += (unsigned int) dx_field_iterator_octet(iter); + break; + + default: + return 0; + } + + return length; +} + + +dx_field_iterator_t *dx_field_string(dx_field_iterator_t *iter) +{ + dx_field_iterator_reset(iter); + unsigned char tag = dx_field_iterator_octet(iter); + if (!dx_tag_is_string(tag)) + return 0; + unsigned int length = dx_field_get_length(iter, tag); + + dx_field_iterator_t *result = new_dx_field_iterator_t(); + if (!result) + return 0; + result->start_pointer = iter->pointer; + result->start_pointer.length = length; + result->view_start_pointer = result->start_pointer; + result->pointer = result->start_pointer; + result->view = ITER_VIEW_ALL; + result->mode = MODE_TO_END; + result->at_prefix = 0; + result->view_prefix = 0; + result->tag = 0; + + return result; +} + |
