2
* $Id: extensions.c,v 1.25 2005/07/27 08:52:25 cbiere Exp $
4
* Copyright (c) 2002-2003, Raphael Manfredi
6
*----------------------------------------------------------------------
7
* This file is part of gtk-gnutella.
9
* gtk-gnutella is free software; you can redistribute it and/or modify
10
* it under the terms of the GNU General Public License as published by
11
* the Free Software Foundation; either version 2 of the License, or
12
* (at your option) any later version.
14
* gtk-gnutella is distributed in the hope that it will be useful,
15
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
* GNU General Public License for more details.
19
* You should have received a copy of the GNU General Public License
20
* along with gtk-gnutella; if not, write to the Free Software
22
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23
*----------------------------------------------------------------------
30
* Gnutella message extension handling.
32
* @author Raphael Manfredi
38
RCSID("$Id: extensions.c,v 1.25 2005/07/27 08:52:25 cbiere Exp $");
40
#include "extensions.h"
43
#include "lib/atoms.h"
45
#include "lib/walloc.h"
46
#include "lib/override.h" /* Must be the last header included */
48
#include "if/gnet_property_priv.h"
50
#define HUGE_FS '\x1c' /**< Field separator (HUGE) */
52
#define GGEP_MAXLEN 65535 /**< Maximum decompressed length */
53
#define GGEP_GROW 512 /**< Minimum chunk growth when resizing */
56
* An extension descriptor.
58
* The extension block is structured thustly:
60
* - <.................len.......................>
61
* - <..headlen.><..........paylen...............>
62
* - +-----------+-------------------------------+
63
* - | header | extension payload |
64
* - +-----------+-------------------------------+
68
* The "<headlen>" part is simply "<len>" - "<paylen>" so it is not stored.
69
* Likewise, we store only the beginning of the payload, the base can be
72
* All those pointers refer DIRECTLY to the message we received, so naturally
73
* one MUST NOT alter the data we can read or we would corrupt the messages
74
* before forwarding them.
76
* There is a slight complication introduced with GGEP extensions, since the
77
* data there can be COBS encoded, and even deflated. Therefore, reading
78
* directly data from ext_phys_payload could yield compressed data, not
79
* something really usable.
81
* Therefore, the extension structure is mostly private, and routines are
82
* provided to access the data. Decompression and decoding of COBS is lazily
83
* performed when they wish to access the extension data.
85
* The ext_phys_xxx fields refer to the physical information about the
86
* extension. The ext_xxx() routines allow access to the virtual information
87
* after decompression and COBS decoding. Naturally, if the extension is
88
* not compressed nor COBS-encoded, the ext_xxx() routine will return the
91
* The structure here refers to the opaque data that is dynamically allocated
92
* each time a new extension is found.
94
typedef struct extdesc {
95
gchar *ext_phys_payload; /**< Start of payload buffer */
96
gchar *ext_payload; /**< "virtual" payload */
97
guint16 ext_phys_len; /**< Extension length (header + payload) */
98
guint16 ext_phys_paylen; /**< Extension payload length */
99
guint16 ext_paylen; /**< "virtual" payload length */
100
guint16 ext_rpaylen; /**< Length of buffer for "virtual" payload */
104
gboolean extu_cobs; /**< Payload is COBS-encoded */
105
gboolean extu_deflate; /**< Payload is deflated */
106
const gchar *extu_id; /**< Extension ID */
112
#define ext_phys_headlen(d) ((d)->ext_phys_len - (d)->ext_phys_paylen)
113
#define ext_phys_base(d) ((d)->ext_phys_payload - ext_phys_headlen(d))
116
* Union access shortcuts.
119
#define ext_ggep_cobs ext_u.extu_ggep.extu_cobs
120
#define ext_ggep_deflate ext_u.extu_ggep.extu_deflate
121
#define ext_ggep_id ext_u.extu_ggep.extu_id
123
static const gchar * const extype[] = {
124
"UNKNOWN", /**< EXT_UNKNOWN */
125
"XML", /**< EXT_XML */
126
"HUGE", /**< EXT_HUGE */
127
"GGEP", /**< EXT_GGEP */
128
"NONE", /**< EXT_NONE */
132
*** Extension name screener.
136
* Reserved word description.
139
const gchar *rw_name; /**< Representation */
140
ext_token_t rw_token; /**< Token value */
143
/** URN name table (sorted) */
144
static const struct rwtable urntable[] =
146
{ "bitprint", EXT_T_URN_BITPRINT },
147
{ "sha1", EXT_T_URN_SHA1 },
150
/** GGEP extension table (sorted) */
151
static const struct rwtable ggeptable[] =
153
#define GGEP_ID(x) { STRINGIFY(x), CAT2(EXT_T_GGEP_,x) }
155
{ "<", EXT_T_GGEP_LIME_XML }, /**< '<' is less that 'A' */
156
GGEP_ID(ALT), /**< Alt-locs in qhits */
157
GGEP_ID(BH), /**< Browseable host indication */
158
GGEP_ID(CT), /**< Resource creation time */
159
GGEP_ID(DU), /**< Average servent uptime */
160
GGEP_ID(GTKGV1), /**< GTKG complete version number (binary) */
161
GGEP_ID(GUE), /**< GUESS support */
162
GGEP_ID(H), /**< Hashes in binary form */
163
GGEP_ID(HNAME), /**< Hostname */
164
GGEP_ID(IP), /**< Ip:Port in ping and pongs (F2F) */
165
GGEP_ID(IPP), /**< IP:Port in pongs (UHC) */
166
GGEP_ID(LF), /**< Large file size in qhits */
167
GGEP_ID(LOC), /**< Locale preferences, for clustering */
168
GGEP_ID(PATH), /**< Shared file path, in query hits */
169
GGEP_ID(PHC), /**< Packed host caches (UHC) in pongs */
170
GGEP_ID(PUSH), /**< Push proxy info, in qhits */
171
GGEP_ID(SCP), /**< Supports cached pongs, in pings (UHC) */
172
GGEP_ID(T), /**< Textual information in qhits */
173
GGEP_ID(UDPHC), /**< Is an UDP hostcache (UHC) , in pongs */
174
GGEP_ID(UP), /**< Ultrapeer information about free slots */
175
GGEP_ID(VC), /**< Vendor code, in pongs */
176
GGEP_ID(u), /**< HUGE URN in ASCII */
182
* Perform a dichotomic search for keywords in the reserved-word table.
183
* The `case_sensitive' parameter governs whether lookup is done with or
184
* without paying attention to case.
186
* @return the keyword token value upon success, EXT_T_UNKNOWN if not found.
187
* If keyword was found, its static shared string is returned in `retkw'.
190
rw_screen(gboolean case_sensitive,
191
const struct rwtable *table, size_t size,
192
const gchar *word, const gchar **retkw)
196
#define GET_KEY(i) (table[(i)].rw_name)
199
*retkw = table[(i)].rw_name; \
200
return table[(i)].rw_token; \
205
BINARY_SEARCH(const gchar *, word, size,
206
strcmp, GET_KEY, FOUND);
208
BINARY_SEARCH(const gchar *, word, size,
209
ascii_strcasecmp, GET_KEY, FOUND);
215
return EXT_T_UNKNOWN;
219
* Ensure the reserved-word table is lexically sorted.
222
rw_is_sorted(const gchar *name,
223
const struct rwtable *table, size_t size)
227
/* Skip the first to have a previous element, tables with a single
228
* element are sorted anyway. */
229
for (i = 1; i < size; i++) {
230
const struct rwtable *prev = &table[i - 1], *e = &table[i];
231
if (strcmp(prev->rw_name, e->rw_name) >= 0)
232
g_error("reserved word table \"%s\" unsorted (near item \"%s\")",
238
* @return the GGEP token value upon success, EXT_T_UNKNOWN_GGEP if not found.
239
* If keyword was found, its static shared string is returned in `retkw'.
242
rw_ggep_screen(gchar *word, const gchar **retkw)
246
t = rw_screen(TRUE, ggeptable, G_N_ELEMENTS(ggeptable), word, retkw);
248
return (t == EXT_T_UNKNOWN) ? EXT_T_UNKNOWN_GGEP : t;
252
* @return the URN token value upon success, EXT_T_UNKNOWN if not found.
253
* If keyword was found, its static shared string is returned in `retkw'.
256
rw_urn_screen(gchar *word, const gchar **retkw)
258
return rw_screen(FALSE, urntable, G_N_ELEMENTS(urntable), word, retkw);
262
*** Extension name atoms.
265
static GHashTable *ext_names = NULL;
268
* Transform the name into a printable form.
270
* @return an atom string of that printable form.
273
ext_name_atom(const gchar *name)
279
* Look whether we already known about this name.
282
atom = g_hash_table_lookup(ext_names, name);
288
* The key is always the raw name we're given.
290
* The value is always a printable form of the name, where non-printable
291
* chars are shown as hexadecimal escapes: \xhh. However, if there is
292
* no escaping, then the name is also the key (same object).
295
key = g_strdup(name);
296
atom = hex_escape(key, TRUE); /* strict escaping */
298
g_hash_table_insert(ext_names, key, atom);
304
* Callback for freeing entries in the `ext_names' hash table.
307
ext_names_kv_free(gpointer key, gpointer value, gpointer unused_udata)
311
if (0 != strcmp((gchar *) key, (gchar *) value))
320
*** Extension parsing.
322
*** All the ext_xxx_parse routines share the same signature and behaviour:
324
*** They extract one extension, as guessed by the leading byte introducing
325
*** those extensions and return the amount of entries they added to the
326
*** supplied extension vector (this will be typically 1 but for GGEP which
327
*** is structured and can therefore grab more than one extension in one call).
329
*** Upon entry, `*retp' points to the start of the extension, and there are
330
*** `len' bytes to parse. There are `exvcnt' slots available in the extension
331
*** vector, starting at `exv'.
333
*** On exit, `p' is updated to the first byte following the last successfully
334
*** parsed byte. If the returned value is 0, then `p' is not updated.
338
* Parses a GGEP block (can hold several extensions).
341
ext_ggep_parse(gchar **retp, gint len, extvec_t *exv, gint exvcnt)
344
gchar *end = p + len;
345
gchar *lastp = p; /* Last parsed point */
348
for (count = 0; count < exvcnt && p < end; /* empty */) {
350
gchar id[GGEP_F_IDLEN + 1];
351
guint id_len, data_length, i;
352
gboolean length_ended = FALSE;
356
g_assert(exv->opaque == NULL);
359
* First byte is GGEP flags.
362
flags = (guchar) *p++;
364
if (flags & GGEP_F_MBZ) /* A byte that Must Be Zero is set */
367
id_len = flags & GGEP_F_IDLEN;
368
g_assert(id_len < sizeof id);
373
if ((size_t) (end - p) < id_len) /* Not enough bytes to store the ID! */
377
* Read ID, and NUL-terminate it.
379
* As a safety precaution, only allow ASCII IDs, and nothing in
380
* the control space. It's not really in the GGEP specs, but it's
381
* safer that way, and should protect us if we parse garbage starting
386
for (i = 0; i < id_len; i++) {
388
if (c == '\0' || !isascii(c) || is_ascii_cntrl(c))
395
* Read the payload length (maximum of 3 bytes).
399
for (i = 0; i < 3 && p < end; i++) {
403
* Either GGEP_L_CONT or GGEP_L_LAST must be set, thereby
404
* ensuring that the byte cannot be NUL.
407
if (((b & GGEP_L_XFLAGS) == GGEP_L_XFLAGS) || !(b & GGEP_L_XFLAGS))
410
data_length = (data_length << GGEP_L_VSHIFT) | (b & GGEP_L_VALUE);
412
if (b & GGEP_L_LAST) {
422
* Ensure we have enough bytes left for the payload. If not, it
423
* means the length is garbage.
426
/* Check whether there are enough bytes for the payload */
427
if ((size_t) (end - p) < data_length)
431
* Some sanity checks:
433
* A COBS-encoded buffer can be trivially validated.
434
* A deflated payload must be at least 6 bytes with a valid header.
437
if (flags & (GGEP_F_COBS|GGEP_F_DEFLATE)) {
438
guint d_len = data_length;
440
if (flags & GGEP_F_COBS) {
441
if (d_len == 0 || !cobs_is_valid(p, d_len))
443
d_len--; /* One byte of overhead */
446
if (flags & GGEP_F_DEFLATE) {
453
* If COBS-ed, since neither the first byte nor the
454
* second byte of the raw deflated payload can be NUL,
455
* the leading COBS code will be at least 3. Then
456
* the next 2 bytes are the raw deflated header.
458
* If not COBS-ed, check whether payload holds a valid
462
if (flags & GGEP_F_COBS) {
465
offset = 1; /* Skip leading byte */
468
if (!zlib_is_valid_header(p + offset, d_len))
474
* OK, at this point we have validated the GGEP header.
477
d = walloc(sizeof *d);
479
d->ext_phys_payload = p;
480
d->ext_phys_paylen = data_length;
481
d->ext_phys_len = (p - lastp) + data_length;
482
d->ext_ggep_cobs = flags & GGEP_F_COBS;
483
d->ext_ggep_deflate = flags & GGEP_F_DEFLATE;
485
if (0 == (flags & (GGEP_F_COBS|GGEP_F_DEFLATE))) {
486
d->ext_payload = d->ext_phys_payload;
487
d->ext_paylen = d->ext_phys_paylen;
489
d->ext_payload = NULL; /* Will lazily compute, if accessed */
493
g_assert(ext_phys_headlen(d) >= 0);
496
* Look whether we know about this extension.
498
* If we do, the name is the ID as well. Otherwise, for tracing
499
* and debugging purposes, save the name away, once.
502
exv->ext_type = EXT_GGEP;
503
exv->ext_token = rw_ggep_screen(id, &name);
504
exv->ext_name = name;
507
d->ext_ggep_id = name;
509
d->ext_ggep_id = ext_name_atom(id);
512
* One more entry, prepare next iteration.
517
lastp = p + data_length;
521
* Was this the last extension?
524
if (flags & GGEP_F_LAST)
528
*retp = lastp; /* Points to first byte after what we parsed */
534
* Cleanup any extension we already parsed.
539
wfree(exv->opaque, sizeof(extdesc_t));
543
return 0; /* Cannot be a GGEP block: leave parsing pointer intact */
547
* Parses a URN block (one URN only).
550
ext_huge_parse(gchar **retp, gint len, extvec_t *exv, gint exvcnt)
553
gchar *end = p + len;
554
gchar *lastp = p; /* Last parsed point */
557
gchar *payload_start = NULL;
558
gint data_length = 0;
559
const gchar *name = NULL;
562
g_assert(exvcnt > 0);
563
g_assert(exv->opaque == NULL);
566
* Make sure we can at least read "urn:", i.e. that we have 4 chars.
576
p = is_strcaseprefix(p, "urn:");
581
* Maybe it's simply a "urn:" empty specification?
584
if (p == end || *p == '\0' || *p == HUGE_FS) {
585
token = EXT_T_URN_EMPTY;
587
g_assert(data_length == 0);
592
* Look for the end of the name, identified by ':'.
603
if (p == end || p == name_start) /* Not found, or empty name */
613
token = rw_urn_screen(name_start, &name);
617
* Now extract the payload (must be made of alphanum chars),
618
* until we reach a delimiter (NUL byte, GGEP header, GEM separator).
619
* NB: of those, only GGEP_MAGIC could be "alnum" under some locales.
626
if (!is_ascii_alnum(c) || c == (guchar) GGEP_MAGIC) {
633
g_assert(data_length == p - payload_start);
636
g_assert(payload_start);
638
d = walloc(sizeof(*d));
640
d->ext_phys_payload = payload_start;
641
d->ext_phys_paylen = data_length;
642
d->ext_phys_len = (payload_start - lastp) + data_length;
643
d->ext_payload = d->ext_phys_payload;
644
d->ext_paylen = d->ext_phys_paylen;
647
exv->ext_type = EXT_HUGE;
648
exv->ext_name = name;
649
exv->ext_token = token;
651
g_assert(ext_phys_headlen(d) >= 0);
652
g_assert(p - lastp == d->ext_phys_len);
654
*retp = p; /* Points to first byte after what we parsed */
660
* Parses a XML block (grabs the whole xml up to the first NUL or separator).
663
ext_xml_parse(gchar **retp, gint len, extvec_t *exv, gint exvcnt)
666
gchar *end = p + len;
667
gchar *lastp = p; /* Last parsed point */
670
g_assert(exvcnt > 0);
671
g_assert(exv->opaque == NULL);
675
if (c == '\0' || c == (guchar) HUGE_FS) {
682
* We don't analyze the XML, encapsulate as one big opaque chunk.
685
d = walloc(sizeof(*d));
687
d->ext_phys_payload = lastp;
688
d->ext_phys_len = d->ext_phys_paylen = p - lastp;
689
d->ext_payload = d->ext_phys_payload;
690
d->ext_paylen = d->ext_phys_paylen;
693
exv->ext_type = EXT_XML;
694
exv->ext_name = NULL;
695
exv->ext_token = EXT_T_XML;
697
g_assert(p - lastp == d->ext_phys_len);
699
*retp = p; /* Points to first byte after what we parsed */
705
* Parses an unknown block, attempting to resynchronize on a known separator.
706
* Everything up to the resync point is wrapped as an "unknown" extension.
708
* If `skip' is TRUE, we don't resync on the first resync point.
711
ext_unknown_parse(gchar **retp, gint len, extvec_t *exv,
712
gint exvcnt, gboolean skip)
715
gchar *end = p + len;
716
gchar *lastp = p; /* Last parsed point */
719
g_assert(exvcnt > 0);
720
g_assert(exv->opaque == NULL);
723
* Try to resync on a NUL byte, the HUGE_FS separator, "urn:" or what
724
* could appear to be the start of a GGEP block or XML.
730
(c == '\0' || c == (guchar) HUGE_FS || c == (guchar) GGEP_MAGIC) ||
732
(c == 'u' || c == 'U') &&
734
is_strcaseprefix(p, "rn:")
736
(c == '<' && (p < end) && is_ascii_alpha((guchar) *p))
748
* Encapsulate as one big opaque chunk.
751
d = walloc(sizeof(*d));
753
d->ext_phys_payload = lastp;
754
d->ext_phys_len = d->ext_phys_paylen = p - lastp;
755
d->ext_payload = d->ext_phys_payload;
756
d->ext_paylen = d->ext_phys_paylen;
759
exv->ext_type = EXT_UNKNOWN;
760
exv->ext_name = NULL;
761
exv->ext_token = EXT_T_UNKNOWN;
763
g_assert(p - lastp == d->ext_phys_len);
765
*retp = p; /* Points to first byte after what we parsed */
771
* Parses a "no extension" block, made of NUL bytes or HUGE field separators
772
* exclusively. Obviously, this is unneeded stuff that simply accounts
775
* If more that one separator in a row is found, they are all wrapped as a
779
ext_none_parse(gchar **retp, gint len, extvec_t *exv, gint exvcnt)
782
gchar *end = p + len;
783
gchar *lastp = p; /* Last parsed point */
786
g_assert(exvcnt > 0);
787
g_assert(exv->opaque == NULL);
791
if (c == '\0' || c == (guchar) HUGE_FS)
793
p--; /* Point back to the non-NULL char */
798
* If we're still at the beginning, it means there was no separator
799
* at all, so we did not find any "null" extension.
806
* Encapsulate as one big opaque chunk.
809
d = walloc(sizeof(*d));
811
d->ext_phys_payload = lastp;
812
d->ext_phys_len = d->ext_phys_paylen = p - lastp;
813
d->ext_payload = d->ext_phys_payload;
814
d->ext_paylen = d->ext_phys_paylen;
817
exv->ext_type = EXT_NONE;
818
exv->ext_name = NULL;
819
exv->ext_token = EXT_T_OVERHEAD;
821
g_assert(p - lastp == d->ext_phys_len);
823
*retp = p; /* Points to first byte after what we parsed */
829
* Merge two consecutive extensions `exv' and `next' into one big happy
830
* extension, in `exv'. The resulting extension type is that of `exv'.
833
ext_merge_adjacent(extvec_t *exv, extvec_t *next)
839
extdesc_t *d = exv->opaque;
840
extdesc_t *nd = next->opaque;
842
g_assert(exv->opaque != NULL);
843
g_assert(next->opaque != NULL);
845
end = d->ext_phys_payload + d->ext_phys_paylen;
846
nbase = ext_phys_base(nd);
847
nend = nd->ext_phys_payload + nd->ext_phys_paylen;
849
g_assert(nbase + nd->ext_phys_len == nend);
850
g_assert(nend > end);
853
* Extensions are adjacent, but can be separated by a single NUL or other
854
* one byte separator.
857
g_assert(nbase == end || nbase == (end + 1));
859
added = nend - end; /* Includes any separator between the two */
862
* By incrementing the total length and the payload length of `exv',
863
* we catenate `next' at the tail of `exv'.
866
d->ext_phys_len += added;
867
d->ext_phys_paylen += added;
869
if (d->ext_payload != NULL) {
870
g_assert(d->ext_payload == d->ext_phys_payload);
872
d->ext_paylen += added;
876
* Get rid of the `next' opaque descriptor.
877
* We should not have computed any "virtual" payload at this point.
881
nd->ext_payload == NULL || nd->ext_payload == nd->ext_phys_payload);
883
wfree(nd, sizeof(*nd));
888
* Parse extension block of `len' bytes starting at `buf' and fill the
889
* supplied extension vector `exv', whose size is `exvcnt' entries.
891
* @return the number of filled entries.
894
ext_parse(gchar *buf, gint len, extvec_t *exv, gint exvcnt)
897
gchar *end = buf + len;
903
g_assert(exvcnt > 0);
904
g_assert(exv->opaque == NULL);
906
while (p < end && exvcnt > 0) {
913
* From now on, all new Gnutella extensions will be done via GGEP.
914
* However, we have to be backward compatible with legacy extensions
915
* that predate GGEP (HUGE and XML) and were not properly encapsulated.
923
found = ext_ggep_parse(&p, len-1, exv, exvcnt);
927
found = ext_huge_parse(&p, len, exv, exvcnt);
930
found = ext_xml_parse(&p, len, exv, exvcnt);
937
found = ext_none_parse(&p, len-1, exv, exvcnt);
940
continue; /* Single separator, no bloat then */
944
found = ext_unknown_parse(&p, len, exv, exvcnt, FALSE);
949
* If parsing did not advance one bit, grab as much as we can as
950
* an "unknown" extension.
953
g_assert(found == 0 || p != old_p);
956
g_assert(*old_p == GGEP_MAGIC || p == old_p);
959
* If we were initially on a GGEP magic byte, and since we did
960
* not find any valid GGEP extension, go back one byte. We're
961
* about to skip the first synchronization point...
964
if (*old_p == GGEP_MAGIC) {
966
g_assert(p == old_p);
969
found = ext_unknown_parse(&p, len, exv, exvcnt, TRUE);
973
g_assert(found <= exvcnt);
974
g_assert(p != old_p);
979
* If we found an "unknown" or "none" extension, and the previous
980
* extension was "unknown", merge them. The result will be "unknown".
984
found == 1 && cnt > 0 &&
985
(exv->ext_type == EXT_UNKNOWN || exv->ext_type == EXT_NONE)
987
extvec_t *prev = exv - 1;
988
if (prev->ext_type == EXT_UNKNOWN) {
989
ext_merge_adjacent(prev, exv);
990
continue; /* Don't move `exv' */
1004
* Inflate `len' bytes starting at `buf', up to GGEP_MAXLEN bytes.
1005
* The payload `name' is given only in case there is an error to report.
1007
* @returns the allocated inflated buffer, and its inflated length in `retlen'.
1008
* @returns NULL on error.
1011
ext_ggep_inflate(gchar *buf, gint len, guint16 *retlen, const gchar *name)
1013
gchar *result; /* Inflated buffer */
1014
gint rsize; /* Result's buffer size */
1017
gint inflated; /* Amount of inflated data so far */
1018
gboolean failed = FALSE;
1025
* Allocate decompressor.
1028
inz = walloc(sizeof(*inz));
1034
ret = inflateInit(inz);
1037
wfree(inz, sizeof(*inz));
1038
g_warning("unable to setup decompressor for GGEP payload \"%s\": %s",
1039
name, zlib_strerror(ret));
1043
rsize = len * 2; /* Assume a 50% compression ratio */
1044
rsize = MIN(rsize, GGEP_MAXLEN);
1045
result = g_malloc(rsize);
1048
* Prepare call to inflate().
1051
inz->next_in = (gpointer) buf;
1052
inz->avail_in = len;
1058
* Resize output buffer if needed.
1059
* Never grow the result buffer to more than MAX_PAYLOAD_LEN bytes.
1062
if (rsize == inflated) {
1063
rsize += MAX(len, GGEP_GROW);
1064
rsize = MIN(rsize, GGEP_MAXLEN);
1066
if (rsize == inflated) { /* Reached maximum size! */
1067
g_warning("GGEP payload \"%s\" would be larger than %d bytes",
1073
g_assert(rsize > inflated);
1075
result = g_realloc(result, rsize);
1078
inz->next_out = (guchar *) result + inflated;
1079
inz->avail_out = rsize - inflated;
1085
ret = inflate(inz, Z_SYNC_FLUSH);
1086
inflated += rsize - inflated - inz->avail_out;
1088
g_assert(inflated <= rsize);
1090
if (ret == Z_STREAM_END) /* All done! */
1094
g_warning("decompression of GGEP payload \"%s\" failed: %s",
1095
name, zlib_strerror(ret));
1102
* Dispose of decompressor.
1105
ret = inflateEnd(inz);
1107
g_warning("while freeing decompressor for GGEP payload \"%s\": %s",
1108
name, zlib_strerror(ret));
1110
wfree(inz, sizeof(*inz));
1113
* @return NULL on error, fill `retlen' if OK.
1117
G_FREE_NULL(result);
1123
g_assert(*retlen == inflated); /* Make sure it was not truncated */
1125
return result; /* OK, successfully inflated */
1129
* Decode the GGEP payload pointed at by `e', allocating a new buffer capable
1130
* of holding the decoded data.
1132
* This is performed only when the GGEP payload is either COBS-encoded or
1136
ext_ggep_decode(const extvec_t *e)
1138
gchar *pbase; /* Current payload base */
1139
size_t plen; /* Curernt payload length */
1140
gchar *uncobs = NULL; /* COBS-decoded buffer */
1141
size_t uncobs_len = 0; /* Length of walloc()'ed buffer */
1142
size_t result; /* Decoded length */
1146
g_assert(e->ext_type == EXT_GGEP);
1147
g_assert(e->opaque != NULL);
1151
g_assert(d->ext_ggep_cobs || d->ext_ggep_deflate);
1152
g_assert(d->ext_payload == NULL);
1154
pbase = d->ext_phys_payload;
1155
plen = d->ext_phys_paylen;
1161
* COBS decoding must be performed before inflation, if any.
1164
if (d->ext_ggep_cobs) {
1165
uncobs = walloc(plen); /* At worse slightly oversized */
1168
if (!d->ext_ggep_deflate) {
1169
if (!cobs_decode_into(pbase, plen, uncobs, plen, &result)) {
1171
g_warning("unable to decode COBS buffer");
1175
g_assert(result <= plen);
1177
d->ext_payload = uncobs;
1178
d->ext_paylen = result;
1179
d->ext_rpaylen = plen; /* Signals it was walloc()'ed */
1183
if (!cobs_decode_into(pbase, plen, uncobs, plen, &result)) {
1185
g_warning("unable to decode COBS buffer");
1189
g_assert(result <= plen);
1192
* Replace current payload base/length with the COBS buffer.
1199
if (plen == 0) /* 0 bytes cannot be a valid deflated payload */
1206
* Payload is deflated, inflate it.
1209
g_assert(d->ext_ggep_deflate);
1211
d->ext_rpaylen = 0; /* Signals it was malloc()'ed */
1213
ext_ggep_inflate(pbase, plen, &d->ext_paylen, d->ext_ggep_id);
1218
wfree(uncobs, uncobs_len);
1221
* If something went wrong, setup a zero-length payload so that we
1222
* don't go through this whole decoding again.
1225
if (d->ext_payload == NULL) {
1226
if (dbg || ggep_debug)
1227
g_warning("unable to get GGEP \"%s\" %d-byte payload (%s)",
1228
d->ext_ggep_id, d->ext_phys_paylen,
1229
(d->ext_ggep_deflate && d->ext_ggep_cobs) ? "COBS + deflated" :
1230
d->ext_ggep_cobs ? "COBS" : "deflated");
1233
d->ext_payload = d->ext_phys_payload;
1238
* @returns a pointer to the extension's payload.
1241
ext_payload(const extvec_t *e)
1243
extdesc_t *d = e->opaque;
1245
g_assert(e->opaque != NULL);
1247
if (d->ext_payload != NULL)
1248
return d->ext_payload;
1251
* GGEP payload is COBS-ed and/or deflated.
1256
return d->ext_payload;
1260
* @returns a pointer to the extension's payload length.
1263
ext_paylen(const extvec_t *e)
1265
extdesc_t *d = e->opaque;
1267
g_assert(e->opaque != NULL);
1269
if (d->ext_payload != NULL)
1270
return d->ext_paylen;
1273
* GGEP payload is COBS-ed and/or deflated.
1278
return d->ext_paylen;
1282
* @returns a pointer to the extension's header.
1284
* @warning the actual "virtual" payload may not be contiguous to the end
1285
* of the header: don't read past the ext_headlen() first bytes of the
1289
ext_base(const extvec_t *e)
1291
extdesc_t *d = e->opaque;
1293
g_assert(e->opaque != NULL);
1295
return ext_phys_base(d);
1299
* @returns the length of the extensions's header.
1302
ext_headlen(const extvec_t *e)
1304
extdesc_t *d = e->opaque;
1306
g_assert(e->opaque != NULL);
1308
return ext_phys_headlen(d);
1312
* @returns the total length of the extension (payload + extension header).
1315
ext_len(const extvec_t *e)
1317
extdesc_t *d = e->opaque;
1320
g_assert(e->opaque != NULL);
1322
headlen = ext_phys_headlen(d);
1324
if (d->ext_payload != NULL)
1325
return headlen + d->ext_paylen;
1327
return headlen + ext_paylen(e); /* Will decompress / COBS decode */
1331
* @returns extension's GGEP ID, or "" if not a GGEP one.
1334
ext_ggep_id_str(const extvec_t *e)
1336
extdesc_t *d = e->opaque;
1338
g_assert(e->opaque != NULL);
1340
if (e->ext_type != EXT_GGEP)
1343
return d->ext_ggep_id;
1347
* @return TRUE if extension is printable.
1350
ext_is_printable(const extvec_t *e)
1352
const gchar *p = ext_payload(e);
1353
gint len = ext_paylen(e);
1366
* @return TRUE if extension is ASCII.
1369
ext_is_ascii(const extvec_t *e)
1371
const gchar *p = ext_payload(e);
1372
gint len = ext_paylen(e);
1385
* @return TRUE if extension is ASCII and contains at least a character.
1388
ext_has_ascii_word(const extvec_t *e)
1390
const gchar *p = ext_payload(e);
1391
gint len = ext_paylen(e);
1392
gboolean has_alnum = FALSE;
1399
if (!has_alnum && is_ascii_alnum(c))
1407
* Dump an extension to specified stdio stream.
1410
ext_dump_one(FILE *f, const extvec_t *e, const gchar *prefix,
1411
const gchar *postfix, gboolean payload)
1415
g_assert(e->ext_type < EXT_TYPE_COUNT);
1416
g_assert(e->opaque != NULL);
1421
fputs(extype[e->ext_type], f);
1422
fprintf(f, " (token=%d) ", e->ext_token);
1425
fprintf(f, "\"%s\" ", e->ext_name);
1427
paylen = ext_paylen(e);
1429
fprintf(f, "%d byte%s", paylen, paylen == 1 ? "" : "s");
1431
if (e->ext_type == EXT_GGEP) {
1432
extdesc_t *d = e->opaque;
1433
fprintf(f, " (ID=\"%s\", COBS: %s, deflate: %s)",
1435
d->ext_ggep_cobs ? "yes" : "no",
1436
d->ext_ggep_deflate ? "yes" : "no");
1442
if (payload && paylen > 0) {
1443
if (ext_is_printable(e)) {
1447
fputs("Payload: ", f);
1448
fwrite(ext_payload(e), paylen, 1, f);
1453
dump_hex(f, "Payload", ext_payload(e), paylen);
1460
* Dump all extensions in vector to specified stdio stream.
1462
* The `prefix' and `postfix' strings, if non-NULL, are emitted before and
1463
* after the extension summary.
1465
* If `payload' is true, the payload is dumped in hexadecimal if it contains
1466
* non-printable characters, as text otherwise.
1469
ext_dump(FILE *fd, const extvec_t *exv, gint exvcnt,
1470
const gchar *prefix, const gchar *postfix, gboolean payload)
1473
ext_dump_one(fd, exv++, prefix, postfix, payload);
1477
* Prepare the vector for parsing, by ensuring the `opaque' pointers are
1481
ext_prepare(extvec_t *exv, gint exvcnt)
1484
(exv++)->opaque = NULL;
1488
* Reset an extension vector by disposing of the opaque structures
1489
* and of any allocated "virtual" payload.
1492
ext_reset(extvec_t *exv, gint exvcnt)
1495
extvec_t *e = exv++;
1498
if (e->opaque == NULL) /* No more allocated extensions */
1503
if (d->ext_payload != NULL && d->ext_payload != d->ext_phys_payload) {
1504
if (d->ext_rpaylen == 0)
1505
g_free(d->ext_payload);
1507
wfree(d->ext_payload, d->ext_rpaylen);
1510
wfree(d, sizeof(*d));
1520
* Initialize the extension subsystem.
1525
ext_names = g_hash_table_new(g_str_hash, g_str_equal);
1527
rw_is_sorted("ggeptable", ggeptable, G_N_ELEMENTS(ggeptable));
1528
rw_is_sorted("urntable", urntable, G_N_ELEMENTS(urntable));
1532
* Free resources used by the extension subsystem.
1537
g_hash_table_foreach_remove(ext_names, ext_names_kv_free, NULL);
1538
g_hash_table_destroy(ext_names);
1541
/* vi: set ts=4 sw=4 cindent: */