blob: 343573c8d3fc481a62d43929ed3071e699943ae6 [file] [log] [blame]
#ifndef __dispatch_iterator_h__
#define __dispatch_iterator_h__ 1
/*
* 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 <stdint.h>
#include <stdbool.h>
#include <qpid/dispatch/buffer.h>
/**@file
* Iterate over message buffer chains and address fields.
*
* @defgroup iterator iterator
*
* Used to access fields within a message buffer chain, in particular address
* fields.
*
* Iterator shields the user from the fact that the field may be split across
* one or more physical buffers.
*
* @{
*/
/** \name typedef
* Type Definitions
* @{
*/
typedef struct qd_iterator_t qd_iterator_t;
/**
* Address Hash Prefix Values
*/
#define QD_ITER_HASH_PREFIX_TOPOLOGICAL 'T'
#define QD_ITER_HASH_PREFIX_LOCAL 'L'
#define QD_ITER_HASH_PREFIX_AREA 'A'
#define QD_ITER_HASH_PREFIX_ROUTER 'R'
#define QD_ITER_HASH_PREFIX_MOBILE 'M'
#define QD_ITER_HASH_PREFIX_LINKROUTE_ADDR_IN 'C'
#define QD_ITER_HASH_PREFIX_LINKROUTE_ADDR_OUT 'D'
#define QD_ITER_HASH_PREFIX_LINKROUTE_PATTERN_IN 'E'
#define QD_ITER_HASH_PREFIX_LINKROUTE_PATTERN_OUT 'F'
#define QD_ITER_HASH_PREFIX_GLOBAL_PLACEHOLDER 'G'
#define QD_ITER_HASH_PREFIX_EDGE_SUMMARY 'H'
#define QD_ITER_HASH_PHASE_FALLBACK 'F'
/**
* qd_iterator_view_t
*
* Type of iterator view. Iterator views allow the code traversing an address
* field to see a transformed view of the raw field.
*
* ITER_VIEW_ALL - No transformation of the raw field data
*
* ITER_VIEW_ADDRESS_NO_HOST - Remove the scheme and host fields from the view
*
* amqp://host.domain.com:port/other/address/text
* ^^^^^^^^^^^^^^^^^^
* amqp:/other/address/text
* ^^^^^^^^^^^^^^^^^^
* other/address/text
* ^^^^^^^^^^^^^^^^^^
*
* ITER_VIEW_ADDRESS_HASH - Isolate the hashable part of the address depending on address syntax
*
* amqp:/_local/<local>
* L^^^^^^^
* amqp:/_topo/<area>/<router>/<local>
* A^^^^^^
* amqp:/_topo/<my-area>/<router>/<local>
* R^^^^^^^^
* amqp:/_topo/<my_area>/<my-router>/<local>
* L^^^^^^^
* amqp:/_topo/<area>/all/<local>
* A^^^^^^
* amqp:/_topo/<my-area>/all/<local>
* L^^^^^^^
* amqp:/_topo/all/all/<local>
* L^^^^^^^
* amqp:/<mobile>
* M0^^^^^^^^
* amqp:/_edge/<my-router>/<local>
* L^^^^^^^
* amqp:/_edge/<router>/<local>
* H^^^^^^^^ [ interior mode ]
* L_edge [ edge mode ]
*
* ITER_VIEW_NODE_HASH - Isolate the hashable part of a router-id, used for headers
*
* <area>/<router>
* A^^^^^^
*
* <my_area>/<router>
* R^^^^^^^^
*
* ITER_VIEW_ADDRESS_WITH_SPACE
* Same as ADDRESS_HASH but:
* - Does not show the prefix/phase
* - Does not hash-ize local and topological addresses
* - Does not show namespace on local and topological addresses
*
*/
typedef enum {
ITER_VIEW_ALL,
ITER_VIEW_ADDRESS_NO_HOST,
ITER_VIEW_ADDRESS_HASH,
ITER_VIEW_NODE_HASH,
ITER_VIEW_ADDRESS_WITH_SPACE
} qd_iterator_view_t;
typedef struct {
qd_buffer_t *buffer;
unsigned char *cursor;
int remaining;
} qd_iterator_pointer_t;
/** @} */
/** \name global
* Global Methods
* @{
*/
/**
* Set the area and router names for the local router. These are used to match
* my-area and my-router in address fields. These settings are global and used
* for all iterators in the process.
*
* @param area The name of the router's area
* @param router The identifier of the router in the area
*/
void qd_iterator_set_address(bool edge_mode, const char *area, const char *router);
/** @} */
/** \name lifecycle
* Methods to control iterator lifecycle
* @{
*/
/**
* Create an iterator for a null-terminated string.
*
* The "text" string must stay intact for the whole life of the iterator. The iterator
* does not copy the string, it references it.
*
* @param text A null-terminated character string
* @param view The view for the iterator
* @return A newly allocated iterator that references the text string.
*/
qd_iterator_t* qd_iterator_string(const char *text,
qd_iterator_view_t view);
/**
* Create an iterator from binary data.
*
* The "text" string must stay intact for the whole life of the iterator. The iterator
* does not copy the data, it references it.
*
* @param text Pointer to the first octet in an octet string
* @param length Number of octets in the contiguous octet string
* @param view The view for the iterator
* @return A newly allocated iterator that references the octet string.
*/
qd_iterator_t* qd_iterator_binary(const char *text,
int length,
qd_iterator_view_t view);
/**
* Create an iterator from a field in a buffer chain
*
* The buffer chain must stay intact for the whole life of the iterator. The iterator
* does not copy the buffer, it references it.
*
* @param buffer Pointer to the first buffer in the buffer chain
* @param offset The offset in the first buffer where the first octet of the field is
* @param length Number of octets in the field
* @param view The view for the iterator
* @return A newly allocated iterator that references the field.
*/
qd_iterator_t *qd_iterator_buffer(qd_buffer_t *buffer,
int offset,
int length,
qd_iterator_view_t view);
/**
* Free an allocated iterator
*
* @param iter An allocated iterator that is no longer to be used
*/
void qd_iterator_free(qd_iterator_t *iter);
/** @} */
/** \name normal
* Methods to manipulate and traverse an iterator
* @{
*/
/**
* Reset the iterator to the first octet.
*
* @param iter Pointer to an iterator to be reset
*/
void qd_iterator_reset(qd_iterator_t *iter);
/**
* Reset the iterator and set the view. If the iterator was trimmed, clear the trim state.
*
* @param iter Pointer to an iterator to be reset
* @param view The new view for the iterator
*/
void qd_iterator_reset_view(qd_iterator_t *iter,
qd_iterator_view_t view);
/**
* Return the view for the iterator
*
* @param iter Pointer to an iterator
* @return The view for the iterator
*/
qd_iterator_view_t qd_iterator_get_view(const qd_iterator_t *iter);
/**
* Trims octets from both ends of the iterator's view by reducing the length of the view and by
* resetting the base of the view to the current location.
*
* Note that an iterator may be repeatedly trimmed, but the trimming must always reduce
* the size of the view. Trimming will never increase the size of the view. To re-trim
* with a bigger size, qd_iterator_reset_view must be called to clear the trimmed state.
*
* @param iter The iterator whose length should be trimmed
* @param length The length of the trimmed field. If greater than or equal to the current length,
* then there shall be no effect.
*/
void qd_iterator_trim_view(qd_iterator_t *iter, int length);
/**
* Return the current octet in the iterator's view and step to the next.
*/
unsigned char qd_iterator_octet(qd_iterator_t *iter);
/**
* Return true iff the iterator has no more octets in the view.
*/
bool qd_iterator_end(const qd_iterator_t *iter);
/**
* Return a sub-iterator that equals the supplied iterator except that it
* starts at the supplied iterator's current position.
*/
qd_iterator_t *qd_iterator_sub(const qd_iterator_t *iter, uint32_t length);
/**
* Move the iterator's cursor forward up to length bytes
*/
void qd_iterator_advance(qd_iterator_t *iter, uint32_t length);
/**
* Return the remaining length (in octets) for the iterator.
*
* IMPORTANT: This function returns the limit of the remaining length.
* The actual length *may* be less than indicated, but will
* never be more. This function is safe for allocating memory.
*
* @param iter A field iterator
* @return The number of octets remaining in the view (or more)
*/
uint32_t qd_iterator_remaining(const qd_iterator_t *iter);
/**
* Return the exact length of the iterator's view.
*/
int qd_iterator_length(const qd_iterator_t *iter);
/**
* Compare an input string to the iterator's view. Return true iff they are equal.
*/
bool qd_iterator_equal(qd_iterator_t *iter, const unsigned char *string);
/**
* Return true iff the string matches the characters at the current location in the view.
* This function ignores octets beyond the length of the prefix.
* This function does not alter the position of the iterator if the prefix does not match,
* if it matches, the prefix is consumed.
*/
bool qd_iterator_prefix(qd_iterator_t *iter, const char *prefix);
/**
* Return true iff the prefix string matches the characters addressed by ptr.
* This function ignores octets beyond the length of the prefix.
* Caller's pointer is held constant.
*
* @param ptr buffer chain cursor holding message bytes
* @param skip AMQP housekeeping bytes to skip over before finding the incoming string
* @param prefix the prefix to be matched
* @return true if all bytes of prefix match bytes in user string
*/
bool qd_iterator_prefix_ptr(const qd_iterator_pointer_t *ptr, uint32_t skip, const char *prefix);
/**
* Copy the iterator's view into buffer up to a maximum of n bytes. Cursor is
* advanced by the number of bytes copied. There is no trailing '\0' added.
* @return number of bytes copied.
*/
int qd_iterator_ncopy(qd_iterator_t *iter, unsigned char* buffer, int n);
/**
* Return a new copy of the iterator's view, with a trailing '\0' added. The
* cursor is advanced to the end of the view.
* @return Copy of the view, free with free()
*/
unsigned char *qd_iterator_copy(qd_iterator_t *iter);
/**
* A version of qd_iterator_copy that does NOT modify the iterator
*/
unsigned char *qd_iterator_copy_const(const qd_iterator_t *iter);
uint8_t qd_iterator_uint8(qd_iterator_t *iter);
/**
* Return a new iterator that is a duplicate of the original iterator, referring
* to the same base data. If the input iterator pointer is NULL, the duplicate
* will also be NULL (i.e. no new iterator will be created).
* @param iter Input iterator
* @return Pointer to a new, identical iterator referring to the same data.
*/
qd_iterator_t *qd_iterator_dup(const qd_iterator_t *iter);
/**
* Copy the iterator's view into buffer as a null terminated string,
* up to a maximum of n bytes. Cursor is advanced by the number of bytes
* copied. Useful for log messages.
* @return buffer.
*/
char* qd_iterator_strncpy(qd_iterator_t *iter, char* buffer, int n);
/** @} */
/** \name annotation
* Methods to modify the view annotations of an iterator
* @{
*/
/**
* Set the phase character to annotate a mobile address view.
*
* @param iter Pointer to an iterator
* @param phase A character used to annotate a mobile address view
*/
void qd_iterator_annotate_phase(qd_iterator_t *iter, char phase);
/**
* Override the prefix character for a mobile address view.
*
* @param iter Pointer to an iterator
* @param prefix A character to use as the prefix of a mobile address view
*/
void qd_iterator_annotate_prefix(qd_iterator_t *iter, char prefix);
/**
* Annotate a mobile address view with a tenant namespace.
*
* Note that the space string is not copied into the iterator. It must remain in-place
* and unchanged for the lifetime of the iterator.
*
* @param iter Pointer to an iterator
* @param space Pointer to the first character of a character string representing a namespace
* @param space_len The number of characters in the space string
*/
void qd_iterator_annotate_space(qd_iterator_t *iter, const char* space, int space_len);
/** @} */
/** \name hash
* Methods to calculate hash values for iterator views
*
* All hashing functions use the djb2 algorithm (http://www.cse.yorku.ca/~oz/hash.html).
* @{
*/
/**
* Generate the hash of the view of the iterator.
*
* @param iter A field iterator
* @return The hash value of the iterator's view
*/
uint32_t qd_iterator_hash_view(qd_iterator_t *iter);
/**
* Generate a series of hash values for a segmented view. For example, consider the following view:
*
* "M0policy/org.apache.qpid"
*
* The hash values computed will be for the following strings:
*
* "M0policy/org.apache.qpid"
* "M0policy/org.apache"
* "M0policy/org"
* "M0policy"
*
* These hash values and the sub-views associated with them shall be stored in the iterator.
*
* @param iter An address iterator
*/
void qd_iterator_hash_view_segments(qd_iterator_t *iter);
/**
* Iterate over the segment hash values pre-computed using qd_iterator_hash_view_segments.
*
* This function returns the longest remaining segment hash, removes the hash from the set of
* stored segment values, and adjusts the view so that it includes only the subset of the view
* associated with the hash value.
*
* @param iter A field iterator
* @param hash (output) Hash value for the next segment
* @return True iff there is another segment hash to be compared
*/
bool qd_iterator_next_segment(qd_iterator_t *iter, uint32_t *hash);
/**
* Get an iterator's cursor details.
* Exposes iter's buffer, cursor, and remaining values.
*
* @param iter iter that still has data in its view.
* @param ptr Pointer object which is to receive cursor position
*/
void qd_iterator_get_view_cursor(
const qd_iterator_t *iter,
qd_iterator_pointer_t *ptr);
/** @} */
/** @} */
#endif