YAACC - UPNP Client and Server
Loading...
Searching...
No Matches
de.yaacc.share.ByteRangeResolver Class Reference

Turns the Range header of a request into the one answer a single-range server gives: status 200, 206 or 416, the bytes to send and the Content-Range text. More...

Collaboration diagram for de.yaacc.share.ByteRangeResolver:
Collaboration graph

Classes

class  Range
 One requested range, immutable.
 
class  Result
 The answer for one request, immutable.
 

Static Public Member Functions

static List< Range > parseHeader (String rangeHeader)
 Parses the raw Range header value.
 
static Result resolve (List< Range > requested, long totalLength)
 Resolves the requested ranges against the resource length.
 

Static Public Attributes

static final int MAX_HEADER_LENGTH = 1024
 A header longer than this is ignored (a request line is capped by the server anyway).
 
static final long OPEN = -1L
 The last-position value that means "open" (bytes=100-).
 

Detailed Description

Turns the Range header of a request into the one answer a single-range server gives: status 200, 206 or 416, the bytes to send and the Content-Range text.

Plain Java (no android.*), long arithmetic only, and nothing here throws for any input: the header is attacker-controlled.

Decisions (RFC 9110 section 14):

  • No usable Range header gives 200 with the whole resource and no Content-Range. "Not usable" means: null, empty, a unit other than bytes (compared ignoring ASCII case), or a syntactically invalid header (a malformed piece, a range whose last position is below its first, a header longer than MAX_HEADER_LENGTH). An invalid header is IGNORED, never answered with 416.
  • A syntactically valid header that selects nothing gives 416 with bytes */len: the first position is at or beyond the length, a suffix of length 0, or any range on an empty resource (also a suffix: nothing to select).
  • More than one range is not served (no multipart/byteranges): 200 with the whole resource.
  • A satisfiable single range gives 206, also when it covers the whole resource (bytes 0-999/1000). A last position at or beyond the length is clipped to length - 1; a suffix longer than the resource gives everything from 0.
  • Digits that overflow long saturate at Long#MAX_VALUE (they only ever mean "far beyond any length"); they never throw.
  • An unknown (negative) total length cannot be ranged: 200, length() is -1.
  • The header may have leading and trailing spaces or tabs (and only those: a line break or other control character makes it invalid). List elements are separated by commas with optional spaces or tabs around them; empty elements are ignored (RFC 9110 5.6.1.2); whitespace anywhere else (inside 0-99, after =) makes the header invalid. Digits are ASCII only, leading zeros are fine.

Member Function Documentation

◆ parseHeader()

static List< Range > de.yaacc.share.ByteRangeResolver.parseHeader ( String rangeHeader)
static

Parses the raw Range header value.

Never throws, never returns null.

Parameters
rangeHeaderthe header value, may be null
Returns
the requested ranges in header order; EMPTY (= serve 200 and ignore the header) for null, empty, a unit other than bytes, a header longer than MAX_HEADER_LENGTH, a header without any range (bytes=, bytes=,) and ANY syntactically invalid piece (the whole header is then ignored, e.g. bytes=0-9,x or bytes=10-5). Numbers that overflow long saturate at Long#MAX_VALUE.

◆ resolve()

static Result de.yaacc.share.ByteRangeResolver.resolve ( List< Range > requested,
long totalLength )
static

Resolves the requested ranges against the resource length.

Never throws.

Parameters
requestedthe ranges from parseHeader(String); null or empty means no range (200, whole resource); more than one range, a null element or an invalid range (Range#isValid()) also gives 200 with the whole resource
totalLengththe length of the resource in bytes; negative means unknown (200)

The documentation for this class was generated from the following file: