<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Kristijan Sedlak</title>
    <description>The latest articles on Forem by Kristijan Sedlak (@xpepermint).</description>
    <link>https://forem.com/xpepermint</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F132864%2F9f962097-0311-4c9e-8134-56ce217405a8.jpeg</url>
      <title>Forem: Kristijan Sedlak</title>
      <link>https://forem.com/xpepermint</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/xpepermint"/>
    <language>en</language>
    <item>
      <title>How do UDP and TCP work?</title>
      <dc:creator>Kristijan Sedlak</dc:creator>
      <pubDate>Wed, 29 Dec 2021 10:59:52 +0000</pubDate>
      <link>https://forem.com/xpepermint/how-do-udp-and-tcp-work-4o95</link>
      <guid>https://forem.com/xpepermint/how-do-udp-and-tcp-work-4o95</guid>
      <description>&lt;p&gt;It seems the deeper we go according to the &lt;a href="https://en.wikipedia.org/wiki/OSI_model"&gt;OSI&lt;/a&gt; classification, the less one deals with this topic. If you are developing applications that communicate over the network, it would be nice to understand how things actually work, right? Let us take a look at how today's computers work and the role that sockets, ports, and processes play.&lt;/p&gt;

&lt;p&gt;As an example, let us take a normal computer that has an operating system (OS). In the OS there is a part called "network stack" which takes care of network communication. In it there is an array of port numbers from &lt;code&gt;0&lt;/code&gt; to &lt;code&gt;65535&lt;/code&gt;, where &lt;code&gt;0-1023&lt;/code&gt; are known ports and &lt;code&gt;1024-65535&lt;/code&gt; are treated as random ports. On the OS there is a part (I call it stage) where processes are handled - i.e. software or applications. When a process communicates over a network stack, the process is called a service. In this way, when we communicate, we define exactly what kind of process it is.&lt;/p&gt;

&lt;p&gt;Let’s take a look at how communication between processes works. The diagram below shows two processes, one of which is a server and the other a client. To make it as understandable as possible, both processes (services) run on the same computer.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌──────────────────────────────────────────────────┐────────────┐
│    ┌────────────┐                                │            │
│    │    ...     │                                │            │
│    ├────────────┤   ┌──────────────────────────┐ │ ┌────────┐ │
│ ┌─▶│ PORT=8080  │◀─▶│  SOCK=10.0.1.10:8080:TCP │◀┼▶│ SERVER │ │
│ │  ├────────────┤   └──────────────────────────┘ │ └────────┘ │
│ │  │    ...     │                                │            │
│ │  ├────────────┤   ┌──────────────────────────┐ │ ┌────────┐ │
│ └─▶│ PORT=50000 │◀─▶│ SOCK=10.0.0.10:50000:TCP │◀┼▶│ CLIENT │ │
│    ├────────────┤   └──────────────────────────┘ │ └────────┘ │
│    │    ...     │                                │            │
│    └────────────┘                                │            │
├──────────────────────────────────────────────────├────────────┤
│                   Network Stack                  │    Stage   │
└──────────────────────────────────────────────────└────────────┘
│                        Operating System                       │
└───────────────────────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a process to communicate over a network with another local process or a process on another computer, it must first ask the OS to create a socket. A socket represents the communication interface between the process and the OS's network stack. It contains information about &lt;code&gt;IP&lt;/code&gt;, &lt;code&gt;port&lt;/code&gt; and communication &lt;code&gt;protocol&lt;/code&gt; (e.g. TCP or UDP).&lt;/p&gt;

&lt;p&gt;The OS thus creates a socket and the process gets a handle to the network stack. In order for the process to actually communicate with other services, it must send a "bind" request to the operating system, which binds the socket to a specific port number. This means that messages are sent over this port and incoming messages from other services that communicate with this service are also sent over the same port.&lt;/p&gt;

&lt;p&gt;This concept applies to both the server and the client. This is the part where application developers get confused, because higher level programming, especially over &lt;code&gt;TCP&lt;/code&gt;, hides all these things and people feel that &lt;code&gt;bind&lt;/code&gt; is synonymous with the function &lt;code&gt;listen&lt;/code&gt; and is exclusively for a server listening and waiting for incoming connections. So the client also needs a socket bound to a port to communicate with the server. The server service usually defines the known port over which it wants to communicate. The client can use a feature of the operating system that is intelligent enough to automatically bind the client to one of the available random ports when it sends the message for the first time, so that the client does not have to perform this step explicitly.&lt;/p&gt;

&lt;p&gt;Now that the server and client are connected to the network stack, both can send a message since the path from server to client is known. Such a unique communication path is also called a 5-tuple.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────┬─────────────┬─────────────┬─────────────┬─────────────┐
│ Local IP    │ Remote IP   │ Local Port  │ Remote Port │ Protocol    │
│ 10.0.0.10   │ 10.0.0.10   │ 8080        │ 50000       │ TCP         │
└─────────────┴─────────────┴─────────────┴─────────────┴─────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;TCP&lt;/code&gt; and &lt;code&gt;UDP&lt;/code&gt; protocol data about the sender and the receiver are appended to the beginning of the header of each message. TCP and UDP both belong to the OSI layer 4 transport protocols. They are similar and at the same time very different.&lt;/p&gt;

&lt;p&gt;TCP is a robust and proven protocol that drives most online communication today. It is reliable and we can trust that packets sent will always arrive at their destination. UDP, on the other hand, is very lightweight, faster than TCP, but unreliable and sent packets can be lost without the sender being informed. TCP is connection-oriented, meaning that the protocol establishes a stateful connection between two endpoints before it can start sending messages. UDP is connectionless, meaning that it simply starts sending messages and is not interested in details.&lt;/p&gt;

&lt;p&gt;TCP is an ordered data transmission and therefore determines the order in which packets sent on the other end must be processed. With UDP, the packets can be sent in the wrong order. TCP has many other features like "error recovery" and "flow control" and hence is popular for HTTP communication. UDP, on the other hand, is mainly used for video streaming or similar cases where it does not matter if a packet is lost.&lt;/p&gt;

&lt;p&gt;The main argument for using TCP is that we can trust it to deliver the packet to the designated location. However, UDP can also be given similar properties with some additional programming. An example of this is &lt;a href="https://en.wikipedia.org/wiki/QUIC"&gt;QUIC&lt;/a&gt;, the protocol we associate with the upcoming HTTP/3, which is otherwise intended for general use.&lt;/p&gt;

</description>
      <category>networking</category>
      <category>protocol</category>
      <category>http</category>
      <category>internet</category>
    </item>
    <item>
      <title>Deep dive into the binary algorithm of Protocol Buffers</title>
      <dc:creator>Kristijan Sedlak</dc:creator>
      <pubDate>Tue, 21 Sep 2021 21:52:11 +0000</pubDate>
      <link>https://forem.com/xpepermint/deep-dive-into-the-binary-algorithm-of-protocol-buffers-7j2</link>
      <guid>https://forem.com/xpepermint/deep-dive-into-the-binary-algorithm-of-protocol-buffers-7j2</guid>
      <description>&lt;p&gt;When a human-understandable format is not a priority, it is best to think binary. &lt;a href="https://en.wikipedia.org/wiki/Protocol_Buffers"&gt;Protocol Buffers&lt;/a&gt;, also know as protobufs or protos, is an open-source interface description language originally developed by Google and a library that allows JSON-like data messages to be transmitted over the wire without unnecessary ballast. Today, it is most relevant in the context of &lt;a href="https://grpc.io/"&gt;gRPC&lt;/a&gt;, where &lt;a href="https://en.wikipedia.org/wiki/Remote_procedure_call"&gt;RPC&lt;/a&gt; server and client code for arbitrary programming languages is generated based on Protocol Buffers descriptions.&lt;/p&gt;

&lt;p&gt;Protocol Buffers were developed primarily with the goal of speeding up the transmission of strongly typed key-value message objects over the network, which in turn means reducing the amount of data that needs to be transmitted over the wire from A to B. In this article, I focus on the process of encoding and decoding data, i.e. at the wire protocol level.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Representational_state_transfer"&gt;REST&lt;/a&gt; and &lt;a href="https://en.wikipedia.org/wiki/Remote_procedure_call"&gt;RPC&lt;/a&gt; are two concepts that are now considered a kind of de facto way of developing APIs in web development. Communication between the client and the server is mostly about transferring data in &lt;a href="https://en.wikipedia.org/wiki/JSON"&gt;JSON&lt;/a&gt; format. This is user-friendly but highly suboptimal at the network level. So people have developed compression mechanisms like that and others, but if you really want to optimize something, you have to start from scratch at the network layer and work your way up from there to the user part, not the other way around.&lt;/p&gt;

&lt;p&gt;There are a variety of alternatives to sending JSON-like data such as Apache &lt;a href="https://dev.toused%20by%20Facebook"&gt;Thrift&lt;/a&gt;, &lt;a href="https://dev.todeveloped%20by%20Amazon"&gt;Ion&lt;/a&gt;, the &lt;a href="https://github.com/microsoft/bond"&gt;Bond&lt;/a&gt; protocol (Microsoft), Apache &lt;a href="https://dev.toKafka"&gt;Avro&lt;/a&gt;, &lt;a href="https://github.com/FIXTradingCommunity/fix-simple-binary-encoding"&gt;SBE&lt;/a&gt;, &lt;a href="https://github.com/bincode-org/bincode"&gt;Bincode&lt;/a&gt;, &lt;a href="http://cbor.io/"&gt;CBir&lt;/a&gt;, &lt;a href="https://msgpack.org/"&gt;MsgPack&lt;/a&gt;, &lt;a href="https://capnproto.org"&gt;Cap'n Proto&lt;/a&gt;, &lt;a href="http://google.github.io/flatbuffers/"&gt;Flatbuffers&lt;/a&gt; and others could be enumerated. All of these are solutions to the same problem, at least at the network level. In terms of strongly-typed messages over the wire, Protocol Buffers are one of the most optimized protocols and are also growing in popularity, especially in the world of &lt;a href="https://kubernetes.io/"&gt;Kubernetes&lt;/a&gt; and similar communities. In fact, it is a good and popular solution, which makes it an obvious choice.&lt;/p&gt;




&lt;p&gt;Protocol Buffers is a simple protocol that can be explained on a plain sheet of paper. The documentation is quite loosely formulated but does not answer all the questions you might encounter during implementation. Protocol Buffers is, fortunately, open source and any doubts can be cleared by looking at the source code written by the main authors.&lt;/p&gt;

&lt;p&gt;The encoder and decoder convert messages from input keys to a shrunken binary format and back. Property names are represented in the Protocol Buffers by unique numbers rather than strings. Compared to the raw JSON format, this already has a significant impact on the final size of the message that is then sent over the wire.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;+-------------------+------------------+-------------------+
+      1. JSON      +   2. Transform   +     3. Encode     + 
+-------------------+------------------+-------------------+
+ {                 +                  +                   +
+   "name": "John", + 1, John          + 0a 04 4a 6f 68 6e +
+   "age": 35       + 2, 35            + 10 23             +
+ }                 +                  +                   +
+-------------------+------------------+-------------------+
+      6. JSON      +    5. Rebuild    +     4. Decode     + 
+-------------------+------------------+-------------------+
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In addition, Protocol Buffers cover &lt;code&gt;4&lt;/code&gt; wire types, allowing &lt;code&gt;18&lt;/code&gt; data types to be represented.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;th&gt;Used For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;Varint&lt;/td&gt;
&lt;td&gt;int32, int64, uint32, uint64, sint32, sint64, bool, enum&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;64-bit&lt;/td&gt;
&lt;td&gt;fixed64, sfixed64, double&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Length-delimited&lt;/td&gt;
&lt;td&gt;string, bytes, embedded messages, packed repeated fields&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;32-bit&lt;/td&gt;
&lt;td&gt;fixed32, sfixed32, float&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The encoder converts the message into a binary format. The message is then represented on the wire as a kind of flattened sequence of encoded key-value properties. The key and the value are encoded separately. Each wire type has its own rules and therefore its own way of encoding.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[key1][value1][key2][value2] ... [keyN][valueN]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key is encoded as a &lt;code&gt;uint32&lt;/code&gt; varint type, and in the last &lt;code&gt;3&lt;/code&gt; bits (&lt;code&gt;T&lt;/code&gt;) contains the wire type. The key's field tag can thus be between &lt;code&gt;1&lt;/code&gt; and &lt;code&gt;2^29 - 1&lt;/code&gt; = &lt;code&gt;536,870,911&lt;/code&gt; (&lt;code&gt;0&lt;/code&gt; is not a valid tag number).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tag = 12345 (unsigned 32-bit), type = 1 (Varint)

11001000 10000011 00000110 ... on the wire
CNNNNNNN CNNNNNNN CNNNNTTT ... bits per type

C = Contiunation, X = Number, T = Type
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Varints are a method for serializing integers with one or more bytes. The algorithm used here is known as &lt;a href="https://en.wikipedia.org/wiki/LEB128"&gt;LEB128&lt;/a&gt;. All bytes except the last have the most significant bit (MSB) set (&lt;code&gt;C&lt;/code&gt;), so that the decoder can determine where the value ends. The other &lt;code&gt;7&lt;/code&gt; bits (&lt;code&gt;N&lt;/code&gt;) of each byte are intended to represent the number.&lt;/p&gt;

&lt;p&gt;LEB128 is an algorithm for encoding integers of arbitrary length in which the bytes are arranged in a little-endian sequence. However, the Protocol Buffers limit the size of the numbers to the supported data types.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;value = 150 (unsigned 32-bit)

Standard varint encoding:
   XXXXXXXX 10010110 ... Number 150 in bytes.
   X0000001 X0010110 ... Split to 7-bit sequence.
   X0010110 X0000001 ... Revert the array of bytes.
   10010110 00000001 ... Add MSB (1=continuation, 0=last byte).

Standard varint decoding:
   10010110 00000001 ... Encoded number.
   00000001 10010110 ... Revert the array of bytes.
   X0000001 X0010110 ... Remove MSB.
   XXXXXXXX 10010110 ... Merge bits together (number 150 in bytes).
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is a big difference between signed integer types (&lt;code&gt;sint32&lt;/code&gt; and &lt;code&gt;sint64&lt;/code&gt;) and the "standard" integer types (&lt;code&gt;int32&lt;/code&gt; and &lt;code&gt;int64&lt;/code&gt;). If you use &lt;code&gt;int32&lt;/code&gt; or &lt;code&gt;int64&lt;/code&gt; as the type for a negative number, the result is always ten bytes long, which makes a very large unsigned integer. In case you know that the value will most likely be negative, you can optimize the result and use one of the signed types, where the resulting varint uses &lt;a href="https://en.wikipedia.org/wiki/Variable-length_quantity#Zigzag_encoding"&gt;ZigZag&lt;/a&gt; encoding for efficiency. Essentially, this means that the positive and negative integers are zigzagged through so that &lt;code&gt;-1&lt;/code&gt; is encoded as &lt;code&gt;1&lt;/code&gt;, &lt;code&gt;1&lt;/code&gt; as &lt;code&gt;2&lt;/code&gt;, &lt;code&gt;-2&lt;/code&gt; as &lt;code&gt;3&lt;/code&gt;, and so on.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;value = -12345 (signed 32-bit)

Signed 32-bit varint encoding:
   -12345 ... Unsigned 32-bit integer.
    24689 ... ZigZag value using (value &amp;lt;&amp;lt; 1) ^ (value &amp;gt;&amp;gt; 31).
          ... Continue with the standard varint encoding.
Signed 32-bit varint decoding:
          ... Start with the standard varint decoding.
    24689 ... ZigZag value using (value &amp;gt;&amp;gt; 1) ^ -(value &amp;amp; 1).
   -12345 ... Unsigned 32-bit integer.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;value = -54321 (signed 64-bit)

Signed 64-bit varint encoding:
   -54321 ... Unsigned 64-bit integer.
   108641 ... ZigZag value using (val &amp;lt;&amp;lt; 1) ^ (val &amp;gt;&amp;gt; 63).
          ... Continue with the standard varint encoding.
Signed 64-bit varint decoding:
          ... Start with the standard varint decoding.
   108641 ... ZigZag value using (value &amp;gt;&amp;gt; 1) ^ -(value &amp;amp; 1).
   -54321 ... Unsigned 64-bit integer.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Numbers can also be represented by the wire types &lt;code&gt;1&lt;/code&gt; or &lt;code&gt;5&lt;/code&gt;. These are &lt;code&gt;32-bit&lt;/code&gt; data types &lt;code&gt;float&lt;/code&gt;, &lt;code&gt;fixed32&lt;/code&gt; and &lt;code&gt;sfixed32&lt;/code&gt; and &lt;code&gt;64-bit&lt;/code&gt; data types &lt;code&gt;double&lt;/code&gt;, &lt;code&gt;fixed64&lt;/code&gt; and &lt;code&gt;sfixed64&lt;/code&gt;. These numbers are simply represented by bytes in little-endian byte order (so in a reversed order).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;value = 12345 (signed 32-bit)

Fixed-size encoding:
   00000000 00000000 00110000 00111001 ... Value in (big-endian) bytes.
   00111001 00110000 00000000 00000000 ... Reverse bytes to little-endian order.
Fixed-size decoding:
   00111001 00110000 00000000 00000000 ... Encoded value in (little-endian) order.
   00000000 00000000 00110000 00111001 ... Value in (big-endian) bytes.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What about wire type &lt;code&gt;2&lt;/code&gt;? "Length-delimited" means that the value is a varint encoded length, followed by the specified number of bytes of data. This describes &lt;code&gt;strings&lt;/code&gt;, &lt;code&gt;embedded&lt;/code&gt; messages (nested objects), and raw &lt;code&gt;bytes&lt;/code&gt; data type.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;value = "foo"

Length-delimited encoding:
   00000011 XXXXXXXX XXXXXXXX XXXXXXXX ... Encode message size (3 bytes) as standard 32-bit varint.
   00000011 01100110 01101111 01101111 ... Append string (foo) in bytes.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, let us mention repeated fields. These represent arrays of one data type. There are no special encoding rules other than the rule that each element in an array is sent as a separate key-value encoded stream, with all of these fields having the same tag number.&lt;/p&gt;

&lt;p&gt;Well, not everything above is completely true. If the array contains elements of numeric types, the array can be shrunk into what is called a "packed" encoding, where the key is sent only once, followed by the encrypted numbers in sequence. Do you remember how numbers are encoded? For numbers, this is possible because the decoder can always determine where a single number ends. With strings and related data types, this is not possible.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Packed repeated fields:
   [key][value1][value2]...[valueN]

Unpacked repeated fields:
   [key][value1][key][value2]...[key][valueN]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, Protocol Buffers deals in-depth with optimizing the representation of data types on the wire so that as little data as possible is transmitted between client and server.&lt;/p&gt;

&lt;p&gt;As with most of my blogs, these are again my personal notes and insights I gained while implementing protocol buffers in &lt;a href="https://www.rust-lang.org/"&gt;Rust&lt;/a&gt;. I hope they will be of use to others as well. The library is again released as an open-source package and the source code is available on &lt;a href="https://github.com/xpepermint/httlib-rs/tree/main/protobufs"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>binary</category>
      <category>protocol</category>
      <category>encoder</category>
      <category>decoder</category>
    </item>
    <item>
      <title>HPACK: The secret ingredient of HTTP/2</title>
      <dc:creator>Kristijan Sedlak</dc:creator>
      <pubDate>Wed, 11 Nov 2020 13:17:13 +0000</pubDate>
      <link>https://forem.com/xpepermint/hpack-the-secret-ingredient-of-http-2-4np6</link>
      <guid>https://forem.com/xpepermint/hpack-the-secret-ingredient-of-http-2-4np6</guid>
      <description>&lt;p&gt;Many protocols are now being used in a way, not at all envisioned at the time of their creation. HTTP is no exception to this. Since the amount of transferred data is getting higher each year, the HTTP protocol is regularly adopting its functioning to enhance the speed of data transfer over the wire. &lt;/p&gt;

&lt;p&gt;In this article, I dive into one of the key features, based on which the &lt;a href="https://tools.ietf.org/html/rfc7540"&gt;HTTP/2&lt;/a&gt; protocol significantly reduces the amount of transferred data from one entity to another. This feature is the header compression format, called &lt;a href="https://tools.ietf.org/html/rfc7541"&gt;HPACK&lt;/a&gt;. The older versions of HTTP protocol support data compression, but the HPACK introduces a whole new level of compression. &lt;/p&gt;

&lt;p&gt;HPACK introduces a completely new approach to header packaging and management. Websites today require dozens or hundreds of requests and the redundant header fields in these requests consume bandwidth unnecessarily. Therefore, HPACK is a compressor, which's main function is to eliminate redundant header fields. &lt;/p&gt;

&lt;p&gt;HPACK specification is rather short, but as it goes for other HTTP/2 related specifications, this one is also often unclear and ambiguous, creating numerous issues and uncertainty for implementers. It is also written with an experienced developer in mind and focuses primarily on the decoder functioning and assumes that the implementor will be knowledgeable enough to add all details he sees are needed for the working product. &lt;/p&gt;

&lt;p&gt;On top of that, a significant shift in thinking is required from the implementer of the HTTP/2 protocol. It’s not only a single request/response session that a connection in HTTP/2 represents. We can start multiple simultaneous streams in one connection, representing multiple request/response sessions, which was not possible in the previous versions of the HTTP protocol. The HPACK compressor uses this characteristic of HTTP/2 by indexing headers considering the whole connection and not per stream, which might seem somewhat unusual. Since I was well acquainted with the HTTP protocol, I somehow missed this particular information during my first read, that’s why I’m specifically addressing it here. So please take a moment to let this last paragraph sink in before you continue reading. &lt;/p&gt;




&lt;p&gt;Specification quickly goes into a very technical level of the HPACK decoding so it gives the impression that HPACK is very complex and contains a lot of “unnecessary” rules. While in fact, the implementation of HPACK contains three main parts of the process: &lt;code&gt;Indexing table&lt;/code&gt;, &lt;code&gt;Encoder&lt;/code&gt;, and &lt;code&gt;Decoder&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Indexing table
&lt;/h3&gt;

&lt;p&gt;Indexing table is a list, to which the HPACK saves the commonly used headers. Each entity indexes headers per connection, separately for incoming (decoding) and for outgoing (encoding) data.&lt;/p&gt;

&lt;p&gt;The numbering of entries starts with index &lt;code&gt;1&lt;/code&gt; and the first 61 headers are static items, keeping their position in the table. These are specific headers, provided by the HPACK specification, based on their statistical relevance, and therefore deserve their permanent position in the table. &lt;/p&gt;

&lt;p&gt;Other headers are listed in the table from position 62 onwards and are called dynamic headers. Header entries are ordered as FIFO (first-in, first-out) and duplicated entries are allowed. Dynamic headers are always inserted at index 62, which shifts all indexes of the existing custom headers one step lower. For the dynamic part of the table, we need to set a limit of how many bytes of the dynamic headers the table is allowed to store. When, while adding a header, this limit is crossed, the headers are evicted from the back of the table, so the table never exceeds the limit.&lt;/p&gt;

&lt;p&gt;This specific functioning is addressed in the HPACk specification as two separate tables, to which it refers as the static and the dynamic table. However, we are dealing with a single list, where two tables are combined into a single address space for defining index values.&lt;/p&gt;

&lt;p&gt;The illustration below shows the structure of the indexing table.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;---------- Index Address Space ---------&amp;gt;
&amp;lt;    Static Table   &amp;gt;&amp;lt;   Dynamic Table   &amp;gt;
+--+-------------+--++--+-------------+--+
|01|     ...     |61||62|     ...     |XX|
+--+-------------+--++II+-------------+DD+

II = Insertion point
DD = Dropping point
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's see how such a table is used by entities. When a client sends the request, it can indicate in the header block that a particular header and potentially also its value, should be indexed. The table for outgoing headers on the client's side would thus look something like this: &lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Index&lt;/th&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;01&lt;/td&gt;
&lt;td&gt;:authority&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;02&lt;/td&gt;
&lt;td&gt;:method&lt;/td&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;..&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;62&lt;/td&gt;
&lt;td&gt;name1&lt;/td&gt;
&lt;td&gt;value1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;63&lt;/td&gt;
&lt;td&gt;value2&lt;/td&gt;
&lt;td&gt;value2&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;On the server’s side, when it reads the headers it would create a table that would look exactly the same. If the next client request would send the same headers, it could simply send a header block including only header indexes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;62 63
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The server will then look up and expand into the full headers what those indexes represent. This essentially explains the whole concept. The mechanism is innovative and highly efficient. I guess no added discussion on its effects on the performance is necessary since there are plenty of benchmarks, proving its efficacy available online.&lt;/p&gt;

&lt;h3&gt;
  
  
  Encoder
&lt;/h3&gt;

&lt;p&gt;The encoder performs the task of data compression. It converts the data from its original readable form into an optimized byte sequence by applying the rules defined in the &lt;a href="https://tools.ietf.org/html/rfc7541"&gt;HPACK&lt;/a&gt; specification. As explained earlier, the specification is interspersed with rules, and is best to take notes and map these rules out to understand how the compressor performs each task. This way we can understand what needs to be implemented and, most importantly, how to start the implementation process itself. &lt;/p&gt;

&lt;p&gt;The HPACK encoding has specific rules for representing integer and string primitive types. Usually, the implementer will start with this part, since all other encoding rules are based on these primitive type representations. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://tools.ietf.org/html/rfc7541#section-5.1"&gt;Integer representation&lt;/a&gt; defines the rules for encoding integer numbers. Integers are used to represent name indexes, header field indexes, or character string lengths.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://tools.ietf.org/html/rfc7541#section-5.2"&gt;String literal representation&lt;/a&gt; defines the rules for encoding string literals. With these, we encode the header name and value literals. The content of these rules can be written in plain text format or encoded with the &lt;a href="https://dev.to/xpepermint/hpack-huffman-encoder-3i7c"&gt;Huffman algorithm&lt;/a&gt;. &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With these basic rules, HPACK defines the binary formats for the representation of the actual headers. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://tools.ietf.org/html/rfc7541#section-6.1"&gt;Indexed header field representation&lt;/a&gt; represents fully indexed headers. These are the headers that are stored in the indexing table under specific index numbers. Since both the header name and value are stored in the indexing table, only this index number is encoded. Such headers are really minimal and therefore optimal in terms of performance. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://tools.ietf.org/html/rfc7541#section-6.2"&gt;Literal header field representation&lt;/a&gt; defines headers that are not or only partially indexed. If the header field name matches the header field name of an entry stored in the static or dynamic table, the header field name can be displayed using the index of this entry. Otherwise, the header field name is displayed as a string literal. Header values are always displayed as a string literal. Such headers can be marked as "index", "do not index" or  "never index". The latter tells us that the data is sensitive and that the entity should handle it with some restrictions (e.g.: protect it with a password). &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;HPACK is designed as a single-standing mechanism that can also be used outside the HTTP/2 protocol. For this reason, the specification provides a rule for signaling changes related to the allowed size of the dynamic table. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://tools.ietf.org/html/rfc7541#section-6.3"&gt;Dynamic table size update&lt;/a&gt; defines the rule for signaling changes in the size of the dynamic table. Such a change is signaled by the encoder, while the limit must be less than or equal to the limit determined by the protocol using HPACK. In HTTP/2 this limit is the last value of the &lt;a href="https://tools.ietf.org/html/rfc7540#section-6.5.2"&gt;SETTINGS_HEADER_TABLE_SIZE&lt;/a&gt; received by the decoder and acknowledged by the encoder. Encoder and decoder use the HTTP/2 protocol to communicate the change in table size and if the change is accepted at both ends, the encoder applies the change and reports it to the decoder using the HPACK mechanism.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These five rules, with some additional conditional rules as described in the HPACK specification, define the HPACK encoder. &lt;/p&gt;

&lt;h3&gt;
  
  
  Decoder
&lt;/h3&gt;

&lt;p&gt;The decoder takes over the task of the decompressor, i.e. it executes the commands inversely to the encoder. It converts the data back into its readable form, ensuring that the indexing table is identical to that on the encoder side. &lt;/p&gt;

&lt;p&gt;The decoder is usually the one that determines how many resources can be used for the purposes of HPACK compression, among others. The decoder signals this to the encoder in the HTTP/2 protocol with the parameter &lt;code&gt;SETTINGS_HEADER_TABLE_SIZE&lt;/code&gt; using the &lt;code&gt;SETTINGS&lt;/code&gt; frame. This change is made when the settings are confirmed by both sides in a way that the HTTP/2 protocol requires. In fact, the encoder is the one that actually requires a change in the size of the dynamic table to meet the requirements of the values agreed upon via the HTTP/2 protocol.&lt;/p&gt;




&lt;p&gt;Experiments show that HPACK works very well, especially on pages with large, repetitive headers (e.g. cookies). Since most of the headers sent from entity to entity for a given website are duplicated, HPACK's table lookup mechanisms effectively eliminate these duplicate bytes from communication.&lt;/p&gt;

&lt;p&gt;In order to get an easy to read and understand the text, I intentionally kept back with some details described in the &lt;a href="https://tools.ietf.org/html/rfc7541"&gt;HPACK&lt;/a&gt; specifications. However, I strongly recommend that you also read the official HPACK documentation. Hopefully, this will be much easier to understand thanks to this blog. I have also written a complete HPACK implementation for HTTP/2 in &lt;a href="https://www.rust-lang.org/"&gt;Rust&lt;/a&gt;. It is publicly available on &lt;a href="https://github.com/xpepermint/httlib-rs/tree/main/huffman"&gt;GitHub&lt;/a&gt; as an open-source project. The source code is well documented and therefore a good additional source of information for all who want to know all details and tricks of HPACK.&lt;/p&gt;

</description>
      <category>hpack</category>
      <category>http</category>
      <category>encoder</category>
      <category>decoder</category>
    </item>
    <item>
      <title>HPACK: Huffman decoder</title>
      <dc:creator>Kristijan Sedlak</dc:creator>
      <pubDate>Tue, 20 Oct 2020 09:38:13 +0000</pubDate>
      <link>https://forem.com/xpepermint/hpack-huffman-decoder-52el</link>
      <guid>https://forem.com/xpepermint/hpack-huffman-decoder-52el</guid>
      <description>&lt;p&gt;This is the last of a series of articles, in which I examined in detail the Huffman algorithm and its connection to &lt;a href="https://tools.ietf.org/html/rfc7541"&gt;HPACK&lt;/a&gt; for &lt;a href="https://tools.ietf.org/html/rfc7540"&gt;HTTP/2&lt;/a&gt;. In previous ones, I explained what the Huffman algorithm is, and started to explain how the encoding process of messages works, and in the last article &lt;a href="https://dev.to/xpepermint/hpack-huffman-translation-matrix-64c"&gt;HPACK: Huffman translation matrix&lt;/a&gt;. I already started the topic of decoding and have described the first part of the decoding process. &lt;/p&gt;

&lt;p&gt;The algorithm for decoding the &lt;a href="https://en.wikipedia.org/wiki/Canonical_Huffman_code"&gt;canonical Huffman&lt;/a&gt; algorithm for &lt;a href="https://tools.ietf.org/html/rfc7541"&gt;HPACK&lt;/a&gt; is being executed based on a matrix, where the Huffman tree is shown in the form of the 2-dimensional table and is made for a specific number of bits being read at the time. &lt;/p&gt;

&lt;p&gt;In this last article, we decided that our decoder will decode the Huffman sequence by reading 2 bits at a time. For this purpose, we created a matrix, which will enable us to reverse the coded message back to the original content. &lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Path&lt;/th&gt;
&lt;th&gt;ID&lt;/th&gt;
&lt;th&gt;SYM&lt;/th&gt;
&lt;th&gt;LFT&lt;/th&gt;
&lt;th&gt;00&lt;/th&gt;
&lt;th&gt;01&lt;/th&gt;
&lt;th&gt;10&lt;/th&gt;
&lt;th&gt;11&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;//&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;//00&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;A&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;//01&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;B&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;//10&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;B&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;//10&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;//100X&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;C&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;//101X&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;D&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;//11&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;E&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;As an example we are using a sequence of characters in the order: A, D, and B.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ADE = 0010101
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Huffman sequence will be decoded by reading 2 bits at a time. Every reading begins at the root symbol &lt;code&gt;//&lt;/code&gt;. First, we read the first two bits &lt;code&gt;00&lt;/code&gt;. In line one of the matrix at &lt;code&gt;ID=0&lt;/code&gt;, we need to check where this code leads, or if it corresponds to any of the characters. Read bits lead to the second line with &lt;code&gt;ID=1&lt;/code&gt; and they represent the letter A. &lt;/p&gt;

&lt;p&gt;The process is repeated for the next 2 bits &lt;code&gt;10&lt;/code&gt;. This code leads us to the line with &lt;code&gt;ID=3&lt;/code&gt; which doesn’t represent a character, so we continue the process for the next 2 bits &lt;code&gt;10&lt;/code&gt;. This code then leads us to line 5, representing the letter D. Here we can see that the value of the column &lt;code&gt;LFT=1&lt;/code&gt;, meaning that there is a leftover 1. This means that in order to continue reading bits we have to shift to one bit back and continue the process there. &lt;/p&gt;

&lt;p&gt;We position ourselves back to the root position while keeping the last bit &lt;code&gt;0&lt;/code&gt;, and keep reading until we reach the sum of 2 bits. This means that we need to read only 1 bit &lt;code&gt;1&lt;/code&gt;. Code &lt;code&gt;01&lt;/code&gt; corresponds with character B and with this we conclude the decoding process.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;00XXXXX =&amp;gt; A
XX10XXX =&amp;gt; continue
XXXX10X =&amp;gt; D
XXXXX01 =&amp;gt; B
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the use of the translation matrix, which we created to read 2 bits at a time, we successfully decoded the Huffman sequence back into readable characters. This is how &lt;a href="https://tools.ietf.org/html/rfc7541"&gt;HPACK&lt;/a&gt; in &lt;a href="https://tools.ietf.org/html/rfc7540"&gt;HTTP/2&lt;/a&gt; decodes header literal values. The process is optimal, while it is best for web servers to read more bits at a time. Considering that the shortest Huffman code for an individual character is 5 bits long, it’s optimal, for the best ratio between speed and used resources, to read 4 bits at a time. More bits at a time mean faster decoding but at the same time a larger translation table and with it a higher memory footprint. &lt;/p&gt;

&lt;p&gt;I made a complete decoder implemented in &lt;a href="https://www.rust-lang.org/"&gt;Rust&lt;/a&gt;. It is available open-source at the public &lt;a href="https://github.com/xpepermint/httlib-rs/tree/main/huffman"&gt;Github repository&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>huffman</category>
      <category>decoding</category>
      <category>hpack</category>
      <category>http2</category>
    </item>
    <item>
      <title>HPACK: Huffman translation matrix</title>
      <dc:creator>Kristijan Sedlak</dc:creator>
      <pubDate>Sun, 18 Oct 2020 08:07:51 +0000</pubDate>
      <link>https://forem.com/xpepermint/hpack-huffman-translation-matrix-64c</link>
      <guid>https://forem.com/xpepermint/hpack-huffman-translation-matrix-64c</guid>
      <description>&lt;p&gt;To achieve a maximum decrease in the amount of data, which is being transferred with each web request and response, &lt;a href="https://tools.ietf.org/html/rfc7540"&gt;HTTP/2&lt;/a&gt; protocol uses &lt;a href="https://tools.ietf.org/html/rfc7541"&gt;HPACK&lt;/a&gt; format for encoding headers and Hoffman algorithm for its literal values. &lt;/p&gt;

&lt;p&gt;In our previous article &lt;a href="https://dev.to/xpepermint/hpack-huffman-encoder-3i7c"&gt;HAPCK: Huffman encoder&lt;/a&gt; I explained what Huffman coding is and how exactly the algorithm is used to encode the content. I continue explaining this by looking at this process from a reversed point of view. Meaning; how can we convert the encoded data back to its original form, again optimally and sustainably performance-wise. For clarity, and since there is a lot of content to cover, I’ve decided to split this into two parts, also because encoding itself entails two separate procedures. &lt;/p&gt;

&lt;p&gt;If you search the web you won’t find a lot of information about the Huffman decoding process, and there are even less concrete examples describing the actual process. Such information can be found in scientific articles, which are hardly readable for the general public. So I have been researching this question extensively. Luckily my friend &lt;a href="https://github.com/fulldecent"&gt;William Entriken&lt;/a&gt; guided me in the search for the optimal solutions by sharing how he used this kind of approach while playing chess. The trick was in The Huffman data tree being flattened to a 2-dimensional table of transitions.&lt;/p&gt;

&lt;p&gt;When the web server receives a header, for which it determines that it contains content encoded with the &lt;a href="https://en.wikipedia.org/wiki/Canonical_Huffman_code"&gt;canonical Huffman&lt;/a&gt; algorithm, it has to decode this content in the shortest possible time with as few resources as possible. The execution speed of this “simple“ task will contribute significantly to the server’s response time, and this time must be as short as possible.&lt;/p&gt;

&lt;p&gt;Encoded Huffman data represents a bit-sequence of zeros and ones. This is where we are faced with the question number. 1: Which and how many ones and zeros represent what character? &lt;/p&gt;

&lt;p&gt;Reading and decoding bit by bit appears to be inadequate performance-wise. I guess we all know how to read the data with reader or stream objects, thus we are aware that reading in buffered chunks outperforms reading bit by bit. So the first trick of fast Huffman decoding is reading N-bits at a time. However, this information alone does not help us much, since we cannot determine how the seemingly “random” Huffman sequence corresponds to actual data. The solution is not just in the flattening of the Huffman tree into a two-dimensional table, but to create such a matrix that enables decoding N-bits at a time. Note that we can create such a matrix for an arbitrary number of bits that the decoder will read at a time. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://tools.ietf.org/html/rfc7541"&gt;HPACK&lt;/a&gt; documentation provides an already prepared and for the web optimized Huffman code for all &lt;a href="https://en.wikipedia.org/wiki/ASCII"&gt;ASCII&lt;/a&gt; characters. To implement the Huffman algorithm for &lt;a href="https://tools.ietf.org/html/rfc7541"&gt;HPACK&lt;/a&gt; we’ll have to first flatten this table to a two-dimensional matrix as mentioned above. This would allow for reversing the encoded Huffman sequence back into the readable characters. &lt;/p&gt;

&lt;p&gt;First, let’s look at such flattening on a very simple example. Our algorithm will enable the conversion of letters A, B, C, D, and E into a Huffman sequence. The Huffman code for each letter is shown in the table below.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Character&lt;/th&gt;
&lt;th&gt;Huffman code&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;A&lt;/td&gt;
&lt;td&gt;00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;B&lt;/td&gt;
&lt;td&gt;01&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;D&lt;/td&gt;
&lt;td&gt;101&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;E&lt;/td&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;We have decided to flatten the Huffman table into a matrix, enabling the decoder to read Huffman bit-sequence 2-bits at a time. The illustration below shows the table structure we need to fill in. &lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;PATH&lt;/th&gt;
&lt;th&gt;ID&lt;/th&gt;
&lt;th&gt;SYM&lt;/th&gt;
&lt;th&gt;LFT&lt;/th&gt;
&lt;th&gt;00&lt;/th&gt;
&lt;th&gt;01&lt;/th&gt;
&lt;th&gt;10&lt;/th&gt;
&lt;th&gt;11&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;//&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The first column PATH will serve for our notes in which we’ll store read bits so we will know what sequence refers to what table row. Reading of each character’s code always starts in the root row marked with &lt;code&gt;//&lt;/code&gt;. The column &lt;code&gt;ID&lt;/code&gt; will store the unique name of the row. The first row is marked with &lt;code&gt;0&lt;/code&gt;. The column &lt;code&gt;SYM&lt;/code&gt; will store characters (e.g. A). Field &lt;code&gt;LFT&lt;/code&gt; will store the information about the leftover bits. A leftover bit is a number of bits, missing to reach the full bit chunk (in our case 2 bits). For example, letter C and D have a leftover of 1, because to reach a round number of bits, which is in our case 2 bits * N, 1 bit remains. Letters A, B, and E have no leftover. The remaining columns represent the read chunk of 2 bits for all its possible values ranging from &lt;code&gt;00&lt;/code&gt; (0) to &lt;code&gt;11&lt;/code&gt; (3). &lt;/p&gt;

&lt;p&gt;The table above will now be filled with data of sample Huffman coding. As mentioned previously, we are reading the Hoffman code 2-bits at a time. Let’s see how to insert data to the table for the first letter A.  &lt;/p&gt;

&lt;p&gt;Letter A is represented with code &lt;code&gt;00&lt;/code&gt;. Since there is no path &lt;code&gt;//00&lt;/code&gt; for this code in the first column, we create a new line with a new &lt;code&gt;ID&lt;/code&gt;. There is no leftover, and in the root line to column &lt;code&gt;00&lt;/code&gt; we write the &lt;code&gt;ID&lt;/code&gt; of the newly established line. Since we read all the bits for the letter A, we also write character A in the &lt;code&gt;SYM&lt;/code&gt; column. &lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Path&lt;/th&gt;
&lt;th&gt;ID&lt;/th&gt;
&lt;th&gt;SYM&lt;/th&gt;
&lt;th&gt;LFT&lt;/th&gt;
&lt;th&gt;00&lt;/th&gt;
&lt;th&gt;01&lt;/th&gt;
&lt;th&gt;10&lt;/th&gt;
&lt;th&gt;11&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;//&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;//00&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;A&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;We then repeat this process for the letter B. The letter B is represented with code &lt;code&gt;01&lt;/code&gt;. Since there is no path &lt;code&gt;//01&lt;/code&gt; for this code, we create a new line with a new &lt;code&gt;ID&lt;/code&gt;. There is no leftover, and in the root line in column &lt;code&gt;01&lt;/code&gt; we write the &lt;code&gt;ID&lt;/code&gt; of the newly established line. Since we read all the bits for the letter B, we also write character B to the &lt;code&gt;SYM&lt;/code&gt; column.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Path&lt;/th&gt;
&lt;th&gt;ID&lt;/th&gt;
&lt;th&gt;SYM&lt;/th&gt;
&lt;th&gt;LFT&lt;/th&gt;
&lt;th&gt;00&lt;/th&gt;
&lt;th&gt;01&lt;/th&gt;
&lt;th&gt;10&lt;/th&gt;
&lt;th&gt;11&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;//&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;//00&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;A&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;//01&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;B&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The process for the letter C is somewhat different since its number of bits doesn’t correspond to 2-bits * N. The final bit is therefore missing, so we claim that it has a leftover of 1. First, we read the first 2 bits and insert them in the table following the same process as before. After that, we read the remaining bit, while assuming that all the possible variations of the missing bit exist. This is marked with &lt;code&gt;X&lt;/code&gt;. Since one bit is missing, we note this in the column &lt;code&gt;LFT&lt;/code&gt;. &lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Path&lt;/th&gt;
&lt;th&gt;ID&lt;/th&gt;
&lt;th&gt;SYM&lt;/th&gt;
&lt;th&gt;LFT&lt;/th&gt;
&lt;th&gt;00&lt;/th&gt;
&lt;th&gt;01&lt;/th&gt;
&lt;th&gt;10&lt;/th&gt;
&lt;th&gt;11&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;//&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;//00&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;A&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;//01&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;B&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;//10&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;B&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;//10&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;//100X&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;C&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;We repeat the process for letters D and E. The final table should look like this: &lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Path&lt;/th&gt;
&lt;th&gt;ID&lt;/th&gt;
&lt;th&gt;SYM&lt;/th&gt;
&lt;th&gt;LFT&lt;/th&gt;
&lt;th&gt;00&lt;/th&gt;
&lt;th&gt;01&lt;/th&gt;
&lt;th&gt;10&lt;/th&gt;
&lt;th&gt;11&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;//&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;//00&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;A&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;//01&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;B&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;//10&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;B&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;//10&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;//100X&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;C&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;//101X&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;D&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;//11&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;E&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Note that it would be correct to replace the variants marked with X with actual possible paths.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Path&lt;/th&gt;
&lt;th&gt;ID&lt;/th&gt;
&lt;th&gt;SYM&lt;/th&gt;
&lt;th&gt;LFT&lt;/th&gt;
&lt;th&gt;00&lt;/th&gt;
&lt;th&gt;01&lt;/th&gt;
&lt;th&gt;10&lt;/th&gt;
&lt;th&gt;11&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;//&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;//00&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;A&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;//01&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;B&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;//10&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;B&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;//10&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;//1000&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;C&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;//1001&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;C&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;//1010&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;D&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;//1011&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;D&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;//11&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;E&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The flattened form of the Huffman tree in the form of a matrix plays a crucial role in the process of decoding. I wrote a complete implementation of such a flattener for generating translation matrixes with the support for N-bits. It's written in &lt;a href="https://www.rust-lang.org/"&gt;Rust&lt;/a&gt; and is available open-source on &lt;a href="https://github.com/xpepermint/httlib-rs/tree/main/huffman"&gt;GitHub&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;We now have an idea of what the process of decoding looks like, using this matrix. I’ll be talking about this in the next article, where we’ll look at the decoding process in detail. &lt;/p&gt;

&lt;p&gt;The next article &lt;a href="https://dev.to/xpepermint/hpack-huffman-decoder-52el"&gt;HPACK: Huffman decoder&lt;/a&gt; continues here and describes the full decoding process.&lt;/p&gt;

</description>
      <category>huffman</category>
      <category>decoding</category>
      <category>hpack</category>
      <category>http2</category>
    </item>
    <item>
      <title>HPACK: Huffman encoder</title>
      <dc:creator>Kristijan Sedlak</dc:creator>
      <pubDate>Fri, 16 Oct 2020 11:38:36 +0000</pubDate>
      <link>https://forem.com/xpepermint/hpack-huffman-encoder-3i7c</link>
      <guid>https://forem.com/xpepermint/hpack-huffman-encoder-3i7c</guid>
      <description>&lt;p&gt;Header Compression format for &lt;a href="https://tools.ietf.org/html/rfc7540"&gt;HTTP/2&lt;/a&gt;, known as &lt;a href="https://tools.ietf.org/html/rfc7541"&gt;HPACK&lt;/a&gt;, foresees the use of the Huffman algorithm for encoding header literal values. This contributes to the additional decrease in the quantity of data, transferred with each web request and response.&lt;/p&gt;

&lt;p&gt;A Huffman code is a particular type of optimal prefix code that is commonly used for lossless data compression. The process of finding or using such a code proceeds by means of Huffman coding, an algorithm developed by David A. Huffman. The output from Huffman’s algorithm can be viewed as a variable-length code table for encoding a source symbol (such as a character in a file). The algorithm derives this table from the estimated probability or frequency of occurrence (weight) for each possible value of the source symbol. As in other entropy encoding methods, more common symbols are generally represented using fewer bits than less common symbols. Huffman’s method can be efficiently implemented, finding a code in time linear to the number of input weights if these weights are sorted. (Source: &lt;a href="https://en.wikipedia.org/wiki/Huffman_coding"&gt;Wikipedia&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://tools.ietf.org/html/rfc7541"&gt;HPACK&lt;/a&gt; compression entails a pre-created &lt;a href="https://en.wikipedia.org/wiki/Canonical_Huffman_code"&gt;canonical Huffman&lt;/a&gt; code table for encoding &lt;a href="https://en.wikipedia.org/wiki/ASCII"&gt;ASCII&lt;/a&gt; characters to the Huffman sequence. A canonical Huffman code is a particular type of Huffman code with unique properties that allow it to be described in a very compact manner. In the aforementioned table are the Huffman codes for each ASCII character with a length up to 32 bits (4x by 8 fields with value 0 or 1), in the form of base-2 integer, aligned on the most significant bit (MSB is the bit farthest to the left).&lt;/p&gt;

&lt;p&gt;Encoding is relatively easy since we are replacing the individual characters with the Huffman code. We add the EOS sign at the end to always fill the entire octet.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[add "!"]     1111111000
[add "$"]     11111110001111111111001
[add "%"]     11111110001111111111001010101 (fix length)
[add "&amp;amp;"]     1111111000111111111100101010111111000
[add "A"]     1111111000111111111100101010111111000100001
[add EOS]     1111111000111111111100101010111111000100001111111111111111111111111111111

[result]      [254   ][63    ][242   ][175   ][196   ][63    ]
              111111100011111111110010101011111100010000111111
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The illustration shows how the encoder iterates through all the &lt;a href="https://en.wikipedia.org/wiki/ASCII"&gt;ASCII&lt;/a&gt; characters and replaces them with the Huffman code. Each line ends with the EOS character which serves as (up to 7 bits) padding.&lt;/p&gt;

&lt;p&gt;While adding the Hoffman code to the sequence, the length of the added code must exactly match the number of bits specified in the documentation. Working with Huffman codes in bytes and then converting them to other types, such as strings, could remove the prepended zeros. In such cases, we have to do some plumbing to ensure all bits are there (an example of this would be the character “%”).&lt;/p&gt;

&lt;p&gt;Implementation could be achieved by manipulating a string of ones and zeros. However, for more complex systems such as high-performance web servers, this would not be sustainable from the performance perspective. To manage resources accordingly, we require innovation so the investments are protected.&lt;/p&gt;

&lt;p&gt;A replacement of the string with characters such as numbers, which are more appropriate for computers, and the use of bitwise operators gives a significant increase in performance. Before this can be done, we need to have an understanding of how the numbers are added. Although we are all aware of what “1+2=3” is, or what is a concatenation of a string such as “aa+bb=aabb”, in bit operations, these rules are not quite so obvious. Let’s see an example of the addition with bits directly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;       1 +        2 =        3
00000001 | 00000010 = 00000011
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the sum of two bit numbers, we used the bitwise operator OR denoted by the "|" symbol which serves as a sign for addition "+" in our example. Its rule is to trace the bits of both numbers and, if a 0 or a 1 is found on the same spot, change their value to 1, while setting the value to 0 in other cases. This understanding now enables us to re-implement the example above.&lt;/p&gt;

&lt;p&gt;Instead of a string, we will use a u64 data type storing a string of 64 bits. We could also use a data type with a larger capacity (such as u128), but u64 is sufficient. The storage requirement is 32 bits, which is the maximum length of the individual Huffman code plus an extra byte (8) for the surplus cell, meaning that we need 40 bits of storage altogether.&lt;/p&gt;

&lt;p&gt;The illustration below shows individual steps for encoding a string of characters as in the example above, while the encoding is carried out with the use of numbers and bitwise operators.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[add "!"]     111111100000000000000000000000000000000000000000
[add "$"]     11111110001111111111001000000000000000000000000000000000
[add "%"]     1111111000111111111100101010100000000000000000000000000000000000 (fix length)
[add "&amp;amp;"]               11111111110010101011111100000000000000000000000000000000000000
[add "A"]                     1111001010101111110001000010000000000000000000000000000000000000
[add EOS]                     1111001010101111110001000011111111111111111111111111111110000000

[result]      [254   ][63    ][242   ][175   ][196   ][63    ]
              111111100011111111110010101011111100010000111111
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Although the illustration is quite similar to the previous one, it is much more colorful. It is also apparent that a string of bits is getting shorter on the left and longer on the right end.&lt;/p&gt;

&lt;p&gt;When the Huffman code is added to the string for the individual character, the algorithm immediately ensures 32 free bit spaces where the next character will be added. This is achieved by the so-called shifting bits using the “&amp;lt;&amp;lt;” bitwise operator. Since we are dealing with bit numbers, we always rotate for 1 or more bytes, dependent on the required capacity, meaning for 8*N bits. It might not be obvious but it is interesting that, by rotating bits and adding the new Huffman character, we are adding numbers in the same way as we did in the simple example previously presented.&lt;/p&gt;

&lt;p&gt;I implemented the full encoder in &lt;a href="https://www.rust-lang.org/"&gt;Rust&lt;/a&gt; and is available at the public &lt;a href="https://github.com/xpepermint/httlib-rs/tree/main/huffman"&gt;GitHub repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If looked at separately, the Huffman algorithm is quite simple. But when we don’t intend to only implement it, but we are, instead, interested in the maximization of the performance and lowering of used resources, things get more complicated. The performance and quality of this solution are, therefore, comparable to the implementation in some well-known web servers.&lt;/p&gt;

&lt;p&gt;In my next article &lt;a href="https://dev.to/xpepermint/hpack-huffman-translation-matrix-64c"&gt;HPACK: Huffman translation matrix&lt;/a&gt; I dive into the decoding process.&lt;/p&gt;

</description>
      <category>huffman</category>
      <category>encoding</category>
      <category>hpack</category>
      <category>http2</category>
    </item>
  </channel>
</rss>
