A C implementation of HPACK: Header Compression for HTTP/2 as specified in RFC 7541.
- HPACK integer encoding and decoding (RFC 7541 §5.1)
- Huffman string encoding, decoding, and length calculation (RFC 7541 §5.2)
- HPACK string literal encoding and decoding with automatic Huffman optimisation
- Shared library (
.so), static library (.a), and pkg-config support - No runtime dependencies beyond the C standard library
| Component | Detail |
|---|---|
| Language | C (compiled with GCC) |
| Build system | GNU Make |
| Code generation | Ruby (Huffman tables) |
| Packaging | Debian (.deb), RPM (.spec), tarballs |
| CI/CD | GitHub Actions |
| Licence | ISC |
make # build shared and static libraries into lib/
make check # build and run tests
make install # install to /usr/local (or set PREFIX)Link against the library using pkg-config:
gcc -o myapp myapp.c $(pkg-config --cflags --libs mkhpack)These examples use static linking:
#include <stdio.h>
#include <stdint.h>
#include "lib/mkhpack.h"
MKHPACK_INT_T i = 987; /* number to encode */
size_t nbits = 6; /* number of bits to occupy in the first byte */
uint8_t pbits = 0x40; /* initial value of the first byte */
#define BUFFER_SIZE 4321
uint8_t buffer[BUFFER_SIZE];
size_t written; /* will hold the number of bytes written */
int error = mkhpack_encode_int(i, nbits, pbits, buffer, BUFFER_SIZE, &written);
if (error) {
fprintf(stderr, "Error encoding integer: %d\n", error);
} else {
printf("Encoded integer in %zu bytes\n", written);
}#include <stdio.h>
#include <stdint.h>
#include "lib/mkhpack.h"
#define CODE_LENGTH 10
uint8_t code[CODE_LENGTH] = "\xFF\xF2\x81\xC0\x80\x01XYZ";
size_t consumed; /* will hold the number of bytes read */
size_t nbits = 6; /* number of bits to occupy in the first byte */
MKHPACK_INT_T i; /* decoded integer */
uint8_t pbits; /* will hold remainder of the first byte */
int error = mkhpack_decode_int(code, CODE_LENGTH, &consumed, nbits, &i, &pbits);
if (error) {
fprintf(stderr, "Error decoding integer: %d\n", error);
} else {
printf("Decoded integer[%lu] from %zu bytes, prefix was %02x\n",
(unsigned long)i, consumed, pbits);
}#include <stdio.h>
#include <stdint.h>
#include "lib/mkhpack.h"
#define STRING_LENGTH 16
uint8_t string[STRING_LENGTH] = "www.example.com";
#define BUFFER_SIZE 4321
uint8_t buffer[BUFFER_SIZE];
size_t written; /* will hold the number of bytes written */
int error = huffman_encode(string, STRING_LENGTH, NULL, buffer, BUFFER_SIZE, &written);
if (error) {
fprintf(stderr, "Error encoding string: %d\n", error);
} else {
printf("Encoded %d-byte string in %zu bytes\n", STRING_LENGTH, written);
}#include <stdio.h>
#include <stdint.h>
#include "lib/mkhpack.h"
#define CODE_LENGTH 16
uint8_t code[CODE_LENGTH] = "\xE7\xCF\x9B\xEB\xE8\x9B\x6F\xB1\x6F\xA9\xB6\xFFXYZ";
size_t consumed; /* will hold the number of bytes read */
#define BUFFER_SIZE 4321
uint8_t buffer[BUFFER_SIZE];
size_t written; /* will hold the number of bytes written */
int error = huffman_decode(code, CODE_LENGTH, &consumed, buffer, BUFFER_SIZE, &written);
if (error) {
fprintf(stderr, "Error decoding string: %d\n", error);
} else {
printf("Decoded %zu-byte string from %zu bytes\n", written, consumed);
}| Resource | URL |
|---|---|
| Repository | github.com/phluid61/mk-hpack |
| Issue Tracker | GitHub Issues |
| GitHub Pages | phluid61.github.io/mk-hpack |
| Documentation | docs/ |
| Audience | Start Here |
|---|---|
| New developers | Developer Guide |
| Architecture overview | Architecture |
| API reference | API |
| Build & release | Deployment |
| Configuration | Configuration |
| All documents | Documentation Index |
We require all contributors to comply with the Developer Certificate of Origin. This ensures that all contributions are properly licensed and attributed.
This repository is subject to a Contributor Code of Conduct adapted from the Contributor Covenant, version 3.0, available at https://www.contributor-covenant.org/version/3/0/
This project is licensed under the ISC licence. See LICENSE for details.