Apache Software Foundation | Jakarta Project | Apache Tomcat
An overview of the WARP protocol

WARP was inspired by the great effort made by the Apache JServ team in finding an efficent transport protocol allowing to connect over a reliable full-duplex transmission channel (such as TCP over IP, bi-directional pipes or UNIX sockets) a servlet container and an HTTP protocol stack (normally, a web server).

Note, this revision of the WARP protocol has not been adopted yet by the WebApp module for the Apache Web Server or by Apache Tomcat.


Maximum WARP, engage! (Tales about a name)

First of all, for non science fiction fanatics, WARP is an acronym and means, (to use a syntax similar to Perl regular expressions) "Web Application Remote (Access|Control)+ Protocol".

In "Star Trek" terms, WARP is a measuring unit for speed, such as "miles per hour" or "meters per seconds". Always in "Star Trek" terms, Radio Free Tomorrow gives us a very nice description about what exactly the term "WARP" means (you can see the full text here):

  • [...] Warping space as a means of traveling faster than light is a method based in solid fact, and physicists have devised a mathematical model of the universe which would allow it to work.
    The idea behind warp drive is this: you bend a small section of space to the extent that it completely encloses your starship, effectively isolating it from the outside universe. You then move this isolated pocket of space time to your destination, and allow it to rejoin normal space.
    Because it's not moving through normal physical space, the lightspeed limit doesn't apply to the warp. It can travel as fast as you want it to. And because space itself is being bent, the starship technically isn't moving at all, so restrictions on normal Newtonian motion don't affect it.

In other terms, then, WARP is all about "bending" something (space), to allow something else (the spaceship) to move faster from one point to another.

How does this applies to our case? Given that we can't "bend" your OS kernel to transmit data faster over a reliable full-duplex connection, neither we can "bend" the data included into the HTTP request to be transmitted from one point to another, the WARP protocol "bends" the rules of HTTP, transmitting an HTTP request, with all operational data attached to it, into a different and more efficent manner, to minimize the computational time required by both parties to process it.

To simplify, although HTTP version 1.1 is a great protocol for hypertext data, it is not suited to encapsulate a pre-parsed half-processed HTTP request and transmit it to another party for further elaboration.

And by all means, we hope that when you fire up your servlet container, you won't stand up in your cubicle sticking your index finger out and screaming "Maximum WARP, engage!".


The Warp 1.0 packet structure

Compared to previous releases of the WARP protocol, the new packet structure looses its "packet lenght" field. This was done to allow progressive memory allocation during process (we don't require the packet to be fully read before starting to put data in the right places) and because (apart from when raw data was transfered), its value could be easily gathered by the content of the packet itself.

The new structure of the WARP packet is therefore defined as follows:


  • Packet Type: is a unique one-byte value detailing what is contained in the packet's payload.
  • Packet Payload: is a variable-length set of bytes containing the data actually included in this packet. Its length and content vary depending on the type of the packet.

The Warp 1.0 packet payload structure

Depending on the type of the packet, the payload can contain zero or more fields (each packet type specifies exactly what or where those fields appear in the payload). Here listed are all payload fields recognized by the Warp 1.0 protocol, their field identifier is a reference for the below mentioned packet type descriptions:

Numeric packet payload fields:

  • signed/unsigned byte: is represented as a 8 bits sequence of data. Its value can range between 0 and 255 decimal if unsigned and between -128 and 127 decimal if signed, with the most significant bit representing the sign. (field identifier: BYTE/UBYTE)
  • signed/unsigned short integer: is represented as a 16 bits sequence of data, encoded in network-byte-order (most significant bytes come first). Its value can range between 0 and 65535 decimal if unsigned and between -32768 and 32767 when signed, with the most significant bit representing the sign (field identifier: SHORT/USHORT).
  • signed/unsigned integer: exactly as for short integers, apart from the fact that it is represented as a sequence of 32 bits, therefore its value can range between -2147483648 and 2147483647 decimal when signed or between 0 and 4294967295 when unsigned (field identifier INT/UINT).
  • signed/unsigned long integer: exactly as short and integer, but it is represented as a sequence of 64 bits (you do the maths). (field identifier LONG/ULONG).

Variable-length packet payload fields:

  • raw data: a chunk of raw data is transferred following this structure: a USHORT field representing the number of bytes that will be transfered, or if this value is 65535 decimal (0xffff) the "null" sequence of bytes, followed by a serie of bytes (zero or more). (field identifier RAW).
  • generic string: a generic string follows the same structure defined for RAW, but the byte sequence is a US-ASCII encoded representation of a string, as outlined in the HTTP/1.1 specification (RFC-2616) for everything but request and response bodies and header values (field identifier STRING).
  • mime string: a mime string is exactly as a generic string, but its byte-representation is supposed to be ISO-8859-1 encoded, and must follow the rules defined by the HTTP/1.1 protocol specification section 2.2 for TEXT (used by header values) referring to RFC-2047 (Message Header Extension for Non-ASCII Text). Thus (for example) the string "I love Japan" with the word "Japan" translated in Japanese ("Nihon") written in Kanji (in Unicode characters this would look like U65E5 + U672C) and encoded in Shift_JIS would be represented as "I love =?Shift_JIS?q?=93=fa=96=7b?=" or if encoded in UTF-8 would look like "I love =?UTF-8?q?=e6=97=a5=e6=9c=ac?=". (field identifier MIME).


For simplicity's sake, this is how one of the three above mentioned variable-length packet payload fields should be transfered (given that the three characters F, o and X have the same value in ISO-8859-1 and US-ASCII, and their hexadecimal value is respectively 0x46, 0x6f and 0x58):