#include "common.h"
#include "extensions.h"
#include "ggep.h"
#include "lib/atoms.h"
#include "lib/misc.h"
#include "lib/walloc.h"
#include "lib/override.h"
#include "if/gnet_property_priv.h"
Data Structures | |
struct | extdesc |
An extension descriptor. More... | |
struct | rwtable |
Reserved word description. More... | |
Defines | |
#define | HUGE_FS '\x1c' /**< Field separator (HUGE) */ |
Field separator (HUGE). | |
#define | GGEP_MAXLEN 65535 /**< Maximum decompressed length */ |
Maximum decompressed length. | |
#define | GGEP_GROW 512 /**< Minimum chunk growth when resizing */ |
Minimum chunk growth when resizing. | |
#define | ext_phys_headlen(d) ((d)->ext_phys_len - (d)->ext_phys_paylen) |
#define | ext_phys_base(d) ((d)->ext_phys_payload - ext_phys_headlen(d)) |
#define | ext_ggep_cobs ext_u.extu_ggep.extu_cobs |
#define | ext_ggep_deflate ext_u.extu_ggep.extu_deflate |
#define | ext_ggep_id ext_u.extu_ggep.extu_id |
#define | GGEP_ID(x) { STRINGIFY(x), CAT2(EXT_T_GGEP_,x) } |
#define | GGEP_GTKG_ID(x) { "GTKG." STRINGIFY(x), CAT2(EXT_T_GGEP_GTKG_,x) } |
#define | GET_KEY(i) (table[(i)].rw_name) |
#define | FOUND(i) |
Typedefs | |
typedef extdesc | extdesc_t |
An extension descriptor. | |
Functions | |
RCSID ("$Id:extensions.c, v 1.31 2005/09/10 08:17:28 daichik Exp $") | |
ext_token_t | rw_screen (gboolean case_sensitive, const struct rwtable *table, size_t size, const gchar *word, const gchar **retkw) |
Perform a dichotomic search for keywords in the reserved-word table. | |
void | rw_is_sorted (const gchar *name, const struct rwtable *table, size_t size) |
Ensure the reserved-word table is lexically sorted. | |
ext_token_t | rw_ggep_screen (gchar *word, const gchar **retkw) |
ext_token_t | rw_urn_screen (gchar *word, const gchar **retkw) |
gchar * | ext_name_atom (const gchar *name) |
Transform the name into a printable form. | |
gboolean | ext_names_kv_free (gpointer key, gpointer value, gpointer unused_udata) |
Callback for freeing entries in the `ext_names' hash table. | |
gint | ext_ggep_parse (gchar **retp, gint len, extvec_t *exv, gint exvcnt) |
Parses a GGEP block (can hold several extensions). | |
gint | ext_huge_parse (gchar **retp, gint len, extvec_t *exv, gint exvcnt) |
Parses a URN block (one URN only). | |
gint | ext_xml_parse (gchar **retp, gint len, extvec_t *exv, gint exvcnt) |
Parses a XML block (grabs the whole xml up to the first NUL or separator). | |
gint | ext_unknown_parse (gchar **retp, gint len, extvec_t *exv, gint exvcnt, gboolean skip) |
Parses an unknown block, attempting to resynchronize on a known separator. | |
gint | ext_none_parse (gchar **retp, gint len, extvec_t *exv, gint exvcnt) |
Parses a "no extension" block, made of NUL bytes or HUGE field separators exclusively. | |
void | ext_merge_adjacent (extvec_t *exv, extvec_t *next) |
Merge two consecutive extensions `exv' and `next' into one big happy extension, in `exv'. | |
gint | ext_parse (gchar *buf, gint len, extvec_t *exv, gint exvcnt) |
Parse extension block of `len' bytes starting at `buf' and fill the supplied extension vector `exv', whose size is `exvcnt' entries. | |
gchar * | ext_ggep_inflate (gchar *buf, gint len, guint16 *retlen, const gchar *name) |
Inflate `len' bytes starting at `buf', up to GGEP_MAXLEN bytes. | |
void | ext_ggep_decode (const extvec_t *e) |
Decode the GGEP payload pointed at by `e', allocating a new buffer capable of holding the decoded data. | |
const gchar * | ext_payload (const extvec_t *e) |
guint16 | ext_paylen (const extvec_t *e) |
const gchar * | ext_base (const extvec_t *e) |
guint16 | ext_headlen (const extvec_t *e) |
guint16 | ext_len (const extvec_t *e) |
const gchar * | ext_ggep_id_str (const extvec_t *e) |
gboolean | ext_is_printable (const extvec_t *e) |
gboolean | ext_is_ascii (const extvec_t *e) |
gboolean | ext_has_ascii_word (const extvec_t *e) |
void | ext_dump_one (FILE *f, const extvec_t *e, const gchar *prefix, const gchar *postfix, gboolean payload) |
Dump an extension to specified stdio stream. | |
void | ext_dump (FILE *fd, const extvec_t *exv, gint exvcnt, const gchar *prefix, const gchar *postfix, gboolean payload) |
Dump all extensions in vector to specified stdio stream. | |
void | ext_prepare (extvec_t *exv, gint exvcnt) |
Prepare the vector for parsing, by ensuring the `opaque' pointers are all set to NULL. | |
void | ext_reset (extvec_t *exv, gint exvcnt) |
Reset an extension vector by disposing of the opaque structures and of any allocated "virtual" payload. | |
const gchar * | ext_ggep_name (ext_token_t id) |
void | ext_init (void) |
Initialize the extension subsystem. | |
void | ext_close (void) |
Free resources used by the extension subsystem. | |
Variables | |
const gchar *const | extype [] |
const struct rwtable | urntable [] |
URN name table (sorted). | |
const struct rwtable | ggeptable [] |
GGEP extension table (sorted). | |
GHashTable * | ext_names = NULL |
|
|
|
|
|
|
|
|
|
|
|
Value: G_STMT_START { \ *retkw = table[(i)].rw_name; \ return table[(i)].rw_token; \ /* NOTREACHED */ \ } G_STMT_END |
|
|
|
Minimum chunk growth when resizing.
|
|
|
|
|
|
Maximum decompressed length.
|
|
Field separator (HUGE).
|
|
An extension descriptor. The extension block is structured thustly:
The "<headlen>" part is simply "<len>" - "<paylen>" so it is not stored. Likewise, we store only the beginning of the payload, the base can be computed if needed. All those pointers refer DIRECTLY to the message we received, so naturally one MUST NOT alter the data we can read or we would corrupt the messages before forwarding them. There is a slight complication introduced with GGEP extensions, since the data there can be COBS encoded, and even deflated. Therefore, reading directly data from ext_phys_payload could yield compressed data, not something really usable. Therefore, the extension structure is mostly private, and routines are provided to access the data. Decompression and decoding of COBS is lazily performed when they wish to access the extension data. The ext_phys_xxx fields refer to the physical information about the extension. The ext_xxx() routines allow access to the virtual information after decompression and COBS decoding. Naturally, if the extension is not compressed nor COBS-encoded, the ext_xxx() routine will return the physical data. The structure here refers to the opaque data that is dynamically allocated each time a new extension is found. |
|
|
|
Free resources used by the extension subsystem.
|
|
Dump all extensions in vector to specified stdio stream. The `prefix' and `postfix' strings, if non-NULL, are emitted before and after the extension summary. If `payload' is true, the payload is dumped in hexadecimal if it contains non-printable characters, as text otherwise. |
|
Dump an extension to specified stdio stream.
|
|
Decode the GGEP payload pointed at by `e', allocating a new buffer capable of holding the decoded data. This is performed only when the GGEP payload is either COBS-encoded or deflated. |
|
|
|
Inflate `len' bytes starting at `buf', up to GGEP_MAXLEN bytes. The payload `name' is given only in case there is an error to report.
|
|
|
|
Parses a GGEP block (can hold several extensions).
|
|
|
|
|
|
Parses a URN block (one URN only).
|
|
Initialize the extension subsystem.
|
|
|
|
|
|
|
|
Merge two consecutive extensions `exv' and `next' into one big happy extension, in `exv'. The resulting extension type is that of `exv'. |
|
Transform the name into a printable form.
|
|
Callback for freeing entries in the `ext_names' hash table.
|
|
Parses a "no extension" block, made of NUL bytes or HUGE field separators exclusively. Obviously, this is unneeded stuff that simply accounts for overhead! If more that one separator in a row is found, they are all wrapped as a "none" extension. |
|
Parse extension block of `len' bytes starting at `buf' and fill the supplied extension vector `exv', whose size is `exvcnt' entries.
|
|
|
|
|
|
Prepare the vector for parsing, by ensuring the `opaque' pointers are all set to NULL.
|
|
Reset an extension vector by disposing of the opaque structures and of any allocated "virtual" payload.
|
|
Parses an unknown block, attempting to resynchronize on a known separator. Everything up to the resync point is wrapped as an "unknown" extension. If `skip' is TRUE, we don't resync on the first resync point. |
|
Parses a XML block (grabs the whole xml up to the first NUL or separator).
|
|
|
|
|
|
Ensure the reserved-word table is lexically sorted.
|
|
Perform a dichotomic search for keywords in the reserved-word table. The `case_sensitive' parameter governs whether lookup is done with or without paying attention to case.
|
|
|
|
|
|
Initial value: { "UNKNOWN", "XML", "HUGE", "GGEP", "NONE", } |
|
GGEP extension table (sorted).
|
|
Initial value: { { "bitprint", EXT_T_URN_BITPRINT }, { "sha1", EXT_T_URN_SHA1 }, }
|