The 'LF' GGEP Extension
==========================

Name: LF (Large File)
Where: Query Hit
Status: Production 
Date: 2004-11-04
Format: Variable-Length Integer 
COBS-Encoding: If neccessary 
Deflate: No

1. OVERVIEW

Due to the wide use of broadband internet connections and increasing amount of
huge content, the transfer of files larger than 4 GiB is no longer utopic. The
standard Gnutella protocol is limited to 32-bit integers to express filesizes.
This limit can easily be removed by a GGEP extension.

2. USAGE

In general, the value of the LF extension overrides the value in the legacy
filesize field of the query hit. The extension should only be used if
necessary. To prevent problems with older clients, using the extension should
be considered if the filesize exceeds 2^31-1 bytes. If the LF extension is
used, the legacy filesize should be set to ~0 i.e., all bits set. This may be
used to detect clients that are not aware of this extension and assume a
different filesize. In order to take advantage of the LF extension, all related
routines (e.g., HTTP parsers) must be able to parse and emit at least 64-bit
values and detect too large values that cannot be handled by them.

3. SPECIFICATION

There is no need to indicate support for this feature at any stage. This
extension is defined as follows:

Due to the location of the LF extension, there must be no NUL bytes in the the
GGEP data. Therefore, the payload must be COBS encoded if it contains any NUL
bytes. The ordering of the bytes is little-endian. To save space, the value is
encoded as a Variable-Length Integer. The byte length is equal to the GGEP
payload size. Trailing zeros must be discarded. If the last byte is a NUL
character, the encoding is invalid. Thus, zero is not a valid filesize in the
context of the GGEP LF extension.

4. EXAMPLE CODE

This example implementation in C uses 64-bit integers, allowing filesizes up to
(2 ^ 64) - 1 bytes. The maximum length of the GGEP payload data is therefore 8
bytes. The decoder is strict i.e., trailing zeros are disallowed. A filesize of
zero bytes, is considered invalid. On failure, both functions return 0.

uint64_t
decode_lf(uint8_t *data, int length)
{
  uint64_t filesize, b;
  int i, j;

  if (length < 1 || length > 8)
    return 0;

  j = i = filesize = 0;
  do {
    b = data[i];
    filesize |= b << j;
    j += 8;
  } while (++i < length);

  if (0 == b)
    return 0;

  return filesize;
}

int
encode_lf(uint64_t filesize, uint8_t *data)
{
  uint8_t *p = data;

  if (0 == filesize)
    return 0;

  do {
    *p++ = filesize;
  } while (0 != (filesize >>= 8));

  return p - data;
}


