1
0
mirror of https://github.com/stefanocasazza/ULib.git synced 2025-09-28 19:05:55 +08:00
ULib/tests/ulib/http2/hdecode.cpp
stefanocasazza b6ee1e71fd fix
2017-07-25 12:41:44 +02:00

255 lines
6.4 KiB
C++

// hdecode.cpp
#include <ulib/utility/http2.h>
#undef PACKAGE
#define PACKAGE "hdecode"
#define ARGS "[dump file...]" // The file contains a dump of HPACK octets
#define U_OPTIONS \
"purpose 'simple HPACK decoder'\n" \
"option e expect-error 1 '<ERR>' ''\n" \
"option d decoding-spec 1 'Spec format: <letter><size>' ''\n" \
"option t table-size 1 'Default table size: 4096' ''\n"
#include <ulib/application.h>
#define WRT(buf, len) cout.write(buf, len)
#define OUT(msg) cout.write(msg, strlen(msg))
class Application : public UApplication {
public:
Application()
{
U_TRACE(5, "Application::Application()")
}
~Application()
{
U_TRACE(5, "Application::~Application()")
}
/*
static bool print(UStringRep* key, void* value)
{
U_TRACE(5, "Application::print(%V,%p)", key, value)
OUT("\n");
WRT(key->data(), key->size());
OUT(": ");
WRT(((UStringRep*)value)->data(), ((UStringRep*)value)->size());
U_RETURN(true);
}
*/
static void TST_decode(const UString& content, const UString& spec, int exp)
{
U_TRACE(5, "Application::TST_decode(%V,%V,%d)", content.rep, spec.rep, exp)
bool cut, resize;
int32_t index_cut = 0;
const char* pspec = spec.data();
uint32_t len = 0, sz = 0, clen = content.size();
unsigned char* cbuf = (unsigned char*)content.data();
UHashMap<UString>* table = &(UHTTP2::pConnection->itable);
UHTTP2::HpackDynamicTable* idyntbl = &(UHTTP2::pConnection->idyntbl);
OUT("Decoded header list:\n");
/**
* Spec format: <letter><size>
*
* d - decode <size> bytes from the dump
* p - decode a partial block of <size> bytes
* r - resize the dynamic table to <size> bytes
*
* The last empty spec decodes the rest of the dump
*/
do {
cut =
resize = false;
switch (*pspec)
{
case '\0': len = clen; break;
case 'r': resize = true; // resize the dynamic table to <size> bytes
case 'p': cut = true; // decode a partial block of <size> bytes
case 'd': len = u_atoi(++pspec); break;
default: U_ERROR("Invalid spec");
}
if (*pspec != '\0') pspec = strchr(pspec, ',') + 1;
if (resize) UHTTP2::setHpackDynTblCapacity(idyntbl, len);
else
{
UHTTP2::nerror =
UHTTP2::hpack_errno = 0;
UHTTP2::index_ptr = 0;
UHTTP2::decodeHeaders(table, idyntbl, cbuf-index_cut, cbuf+len);
U_INTERNAL_DUMP("UHTTP2::hpack_errno = %d UHTTP2::nerror = %d cut = %b len = %u", UHTTP2::hpack_errno, UHTTP2::nerror, cut, len)
if (exp &&
exp == UHTTP2::hpack_errno)
{
return;
}
index_cut = 0;
if (cut)
{
if (UHTTP2::nerror == UHTTP2::COMPRESSION_ERROR)
{
if (UHTTP2::index_ptr)
{
uint32_t advance = UHTTP2::index_ptr - cbuf;
U_INTERNAL_DUMP("UHTTP2::index_ptr = %p advance = %u", UHTTP2::index_ptr, advance)
if (len > advance) index_cut = (len - advance);
}
if (index_cut == 0) index_cut = (sz += len);
}
else
{
if (UHTTP2::index_ptr)
{
uint32_t advance = UHTTP2::index_ptr - cbuf;
U_INTERNAL_DUMP("UHTTP2::index_ptr = %p advance = %u", UHTTP2::index_ptr, advance)
if (len < advance) index_cut = (len - advance);
}
}
U_INTERNAL_DUMP("index_cut = %d", index_cut)
}
else
{
if (UHTTP2::nerror != 0 &&
UHTTP2::hpack_errno == 0)
{
return;
}
}
cbuf += len;
clen -= len;
}
}
while (clen > 0);
OUT("\n\n");
}
void run(int argc, char* argv[], char* env[])
{
U_TRACE(5, "Application::run(%d,%p,%p)", argc, argv, env)
UApplication::run(argc, argv, env);
// manage arg
UString filename = UString(argv[optind]);
if (filename.empty()) U_ERROR("missing argument");
UString content = UFile::contentOf(filename);
if (content.empty()) U_ERROR("empty file");
// manage options
int exp = 0;
UString spec;
UHTTP2::btest = true;
UHTTP2::ctor();
if (UApplication::isOptions())
{
spec = opt['d'];
UString tmp = opt['t'];
if (tmp)
{
UHTTP2::pConnection->idyntbl.hpack_capacity =
UHTTP2::pConnection->idyntbl.hpack_max_capacity =
UHTTP2::pConnection->odyntbl.hpack_capacity =
UHTTP2::pConnection->odyntbl.hpack_max_capacity = tmp.strtoul();
}
tmp = opt['e'];
if (tmp)
{
for (int i = 0; i < 11; ++i)
{
if (tmp.equal(UHTTP2::hpack_error[i].str, 3))
{
exp = UHTTP2::hpack_error[i].value;
goto next;
}
}
U_ERROR("Unknown error");
}
}
next: TST_decode(content, spec, exp);
U_INTERNAL_DUMP("UHTTP2::hpack_errno = %d exp = %d", UHTTP2::hpack_errno, exp)
/*
UHashMap<UString>* table = &(UHTTP2::pConnection->itable);
if (table->empty() == false)
{
UHTTP2::bhash = true;
table->callForAllEntrySorted(print);
UHTTP2::bhash = false;
}
*/
cout.write(U_CONSTANT_TO_PARAM("Dynamic Table (after decoding):"));
UHTTP2::printHpackInputDynTable();
if (UHTTP2::hpack_errno != 0)
{
char buffer[256];
cerr.write(buffer, u__snprintf(buffer, sizeof(buffer), U_CONSTANT_TO_PARAM("main: hpack result: %s (%d)\n"), UHTTP2::hpack_strerror(), UHTTP2::hpack_errno));
}
if (UHTTP2::hpack_errno != exp) UApplication::exit_value = 1;
}
private:
#ifndef U_COVERITY_FALSE_POSITIVE
U_DISALLOW_COPY_AND_ASSIGN(Application)
#endif
};
U_MAIN