Main Page | Modules | Alphabetical List | Data Structures | File List | Data Fields | Globals | Related Pages

extensions.c File Reference


Detailed Description

Gnutella message extension handling.

Author:
Raphael Manfredi
Date:
2002-2003

#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


Define Documentation

#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 ext_phys_base  )     ((d)->ext_phys_payload - ext_phys_headlen(d))
 

#define ext_phys_headlen  )     ((d)->ext_phys_len - (d)->ext_phys_paylen)
 

#define FOUND  ) 
 

Value:

G_STMT_START { \
        *retkw = table[(i)].rw_name; \
        return table[(i)].rw_token; \
        /* NOTREACHED */ \
    } G_STMT_END

#define GET_KEY  )     (table[(i)].rw_name)
 

#define GGEP_GROW   512 /**< Minimum chunk growth when resizing */
 

Minimum chunk growth when resizing.

#define GGEP_GTKG_ID  )     { "GTKG." STRINGIFY(x), CAT2(EXT_T_GGEP_GTKG_,x) }
 

#define GGEP_ID  )     { STRINGIFY(x), CAT2(EXT_T_GGEP_,x) }
 

#define GGEP_MAXLEN   65535 /**< Maximum decompressed length */
 

Maximum decompressed length.

#define HUGE_FS   '\x1c' /**< Field separator (HUGE) */
 

Field separator (HUGE).


Typedef Documentation

typedef struct extdesc extdesc_t
 

An extension descriptor.

The extension block is structured thustly:

  • <.................len.......................>
  • <..headlen.><..........paylen...............>
  • +-----------+-------------------------------+
  • | header | extension payload |
  • +-----------+-------------------------------+
  • ^ ^
  • base payload

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.


Function Documentation

const gchar* ext_base const extvec_t e  ) 
 

Returns:
a pointer to the extension's header.
Warning:
the actual "virtual" payload may not be contiguous to the end of the header: don't read past the ext_headlen() first bytes of the header.

void ext_close void   ) 
 

Free resources used by the extension subsystem.

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.

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.

void ext_dump_one FILE *  f,
const extvec_t e,
const gchar *  prefix,
const gchar *  postfix,
gboolean  payload
[static]
 

Dump an extension to specified stdio stream.

void ext_ggep_decode const extvec_t e  )  [static]
 

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.

const gchar* ext_ggep_id_str const extvec_t e  ) 
 

Returns:
extension's GGEP ID, or "" if not a GGEP one.

gchar* ext_ggep_inflate gchar *  buf,
gint  len,
guint16 *  retlen,
const gchar *  name
[static]
 

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.

Returns:
the allocated inflated buffer, and its inflated length in `retlen'.

NULL on error.

const gchar* ext_ggep_name ext_token_t  id  ) 
 

gint ext_ggep_parse gchar **  retp,
gint  len,
extvec_t exv,
gint  exvcnt
[static]
 

Parses a GGEP block (can hold several extensions).

gboolean ext_has_ascii_word const extvec_t e  ) 
 

Returns:
TRUE if extension is ASCII and contains at least a character.

guint16 ext_headlen const extvec_t e  ) 
 

Returns:
the length of the extensions's header.

gint ext_huge_parse gchar **  retp,
gint  len,
extvec_t exv,
gint  exvcnt
[static]
 

Parses a URN block (one URN only).

void ext_init void   ) 
 

Initialize the extension subsystem.

gboolean ext_is_ascii const extvec_t e  ) 
 

Returns:
TRUE if extension is ASCII.

gboolean ext_is_printable const extvec_t e  ) 
 

Returns:
TRUE if extension is printable.

guint16 ext_len const extvec_t e  ) 
 

Returns:
the total length of the extension (payload + extension header).

void ext_merge_adjacent extvec_t exv,
extvec_t next
[static]
 

Merge two consecutive extensions `exv' and `next' into one big happy extension, in `exv'.

The resulting extension type is that of `exv'.

gchar* ext_name_atom const gchar *  name  )  [static]
 

Transform the name into a printable form.

Returns:
an atom string of that printable form.

gboolean ext_names_kv_free gpointer  key,
gpointer  value,
gpointer  unused_udata
[static]
 

Callback for freeing entries in the `ext_names' hash table.

gint ext_none_parse gchar **  retp,
gint  len,
extvec_t exv,
gint  exvcnt
[static]
 

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.

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.

Returns:
the number of filled entries.

guint16 ext_paylen const extvec_t e  ) 
 

Returns:
a pointer to the extension's payload length.

const gchar* ext_payload const extvec_t e  ) 
 

Returns:
a pointer to the extension's payload.

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.

gint ext_unknown_parse gchar **  retp,
gint  len,
extvec_t exv,
gint  exvcnt,
gboolean  skip
[static]
 

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.

gint ext_xml_parse gchar **  retp,
gint  len,
extvec_t exv,
gint  exvcnt
[static]
 

Parses a XML block (grabs the whole xml up to the first NUL or separator).

RCSID "$Id:extensions.  c,
v 1.31 2005/09/10 08:17:28 daichik Exp $" 
 

ext_token_t rw_ggep_screen gchar *  word,
const gchar **  retkw
[static]
 

Returns:
the GGEP token value upon success, EXT_T_UNKNOWN_GGEP if not found. If keyword was found, its static shared string is returned in `retkw'.

void rw_is_sorted const gchar *  name,
const struct rwtable table,
size_t  size
[static]
 

Ensure the reserved-word table is lexically sorted.

ext_token_t rw_screen gboolean  case_sensitive,
const struct rwtable table,
size_t  size,
const gchar *  word,
const gchar **  retkw
[static]
 

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.

Returns:
the keyword token value upon success, EXT_T_UNKNOWN if not found. If keyword was found, its static shared string is returned in `retkw'.

ext_token_t rw_urn_screen gchar *  word,
const gchar **  retkw
[static]
 

Returns:
the URN token value upon success, EXT_T_UNKNOWN if not found. If keyword was found, its static shared string is returned in `retkw'.


Variable Documentation

GHashTable* ext_names = NULL [static]
 

const gchar* const extype[] [static]
 

Initial value:

 {
    "UNKNOWN",                  
    "XML",                      
    "HUGE",                     
    "GGEP",                     
    "NONE",                     
}

const struct rwtable ggeptable[] [static]
 

GGEP extension table (sorted).

const struct rwtable urntable[] [static]
 

Initial value:

{
    { "bitprint",       EXT_T_URN_BITPRINT },
    { "sha1",           EXT_T_URN_SHA1 },
}
URN name table (sorted).


Generated on Sun Feb 12 10:50:00 2006 for Gtk-Gnutella by doxygen 1.3.6