169 lines
3.6 KiB
Perl
Executable File
169 lines
3.6 KiB
Perl
Executable File
#!/usr/bin/env perl
|
|
#
|
|
# Generate C file that contains version strings
|
|
|
|
($header # This is lsquic.h that contains version enum which we parse
|
|
, $outfile # This is destination C file
|
|
) = @ARGV;
|
|
|
|
open HEADER, $header
|
|
or die "cannot open $header for reading: $!";
|
|
open OUT, ">$outfile"
|
|
or die "cannot open $outfile for writing: $!";
|
|
|
|
while (<HEADER>) {
|
|
if (/^enum lsquic_version$/ .. /^}/) {
|
|
if (/^\s*(LSQVER_0*(\d+)),\s*$/ && $1 ne 'LSQVER_098') {
|
|
if ($2 < 50) {
|
|
push @enums, $1;
|
|
push @versions, $2;
|
|
}
|
|
push @all_versions, $1;
|
|
push @all_alpns, "h3-Q0$2";
|
|
}
|
|
if (/^\s*(LSQVER_ID(\d+))\b/) {
|
|
push @draft_versions, $2;
|
|
push @all_versions, $1;
|
|
push @all_alpns, "h3-$2";
|
|
}
|
|
if (/^\s*(LSQVER_I(\d{3}))\b/) {
|
|
push @all_versions, $1;
|
|
if (not grep 'h3' eq $_, @all_alpns) {
|
|
push @all_alpns, "h3";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
close HEADER;
|
|
|
|
$timestamp = localtime;
|
|
|
|
print OUT <<C_CODE;
|
|
/*
|
|
* Auto-generated by $0 on $timestamp
|
|
*/
|
|
|
|
#include <assert.h>
|
|
#include <string.h>
|
|
|
|
#include "lsquic.h"
|
|
|
|
struct lsquic_engine;
|
|
|
|
static const char *const versions_to_string[ 1 << N_LSQVER ] = {
|
|
C_CODE
|
|
|
|
$max_mask = (1 << @versions) - 1;
|
|
|
|
for ($mask = 0; $mask <= $max_mask; ++$mask) {
|
|
my @indexes;
|
|
for ($i = 0; $i < @versions; ++$i) {
|
|
if ($mask & (1 << $i)) {
|
|
push @indexes, $i;
|
|
}
|
|
}
|
|
print OUT " [",
|
|
join('|', map "(1<<$_)", @enums[@indexes]) || 0,
|
|
"] = \"",
|
|
join(',', @versions[@indexes]),
|
|
"\",\n";
|
|
}
|
|
|
|
$enums = join '|', map "(1<<$_)", sort @enums;
|
|
|
|
print OUT <<"C_CODE";
|
|
};
|
|
|
|
|
|
const char *
|
|
lsquic_get_alt_svc_versions (unsigned versions)
|
|
{
|
|
/* Limit to versions in versions_to_string: */
|
|
versions &= ($enums);
|
|
return versions_to_string[ versions ];
|
|
}
|
|
|
|
C_CODE
|
|
|
|
|
|
$all_version_count_and_null = scalar(@all_versions) + 1;
|
|
|
|
print OUT <<"C_CODE";
|
|
static const struct {
|
|
unsigned versions;
|
|
const char *h3_alpns[$all_version_count_and_null];
|
|
} vers_2_h3_alnps[] = {
|
|
{ 0, { NULL }},
|
|
C_CODE
|
|
|
|
for ($i = 0; $i < (1 << @all_versions); ++$i)
|
|
{
|
|
my (@vers, @alpns);
|
|
for ($j = 0; $j < @all_versions; ++$j)
|
|
{
|
|
if ($i & (1 << $j))
|
|
{
|
|
push @vers, $all_versions[$j];
|
|
push @alpns, $all_alpns[$j];
|
|
}
|
|
}
|
|
if (@vers) {
|
|
print OUT " {", join("|", map "(1<<$_)", @vers), ", ",
|
|
"{ ", join(", ", (map qq("$_"), @alpns), "NULL"), " }},\n";
|
|
}
|
|
}
|
|
|
|
$all_versions = join "|", map "(1<<$_)", @all_versions;
|
|
|
|
print OUT <<"C_CODE";
|
|
};
|
|
|
|
const char *const *
|
|
lsquic_get_h3_alpns (unsigned versions)
|
|
{
|
|
unsigned i;
|
|
|
|
versions &= ($all_versions);
|
|
|
|
for (i = 0; i < sizeof(vers_2_h3_alnps) / sizeof(vers_2_h3_alnps[0]); ++i)
|
|
if (versions == vers_2_h3_alnps[i].versions)
|
|
return vers_2_h3_alnps[i].h3_alpns;
|
|
|
|
assert(0);
|
|
return vers_2_h3_alnps[0].h3_alpns;
|
|
}
|
|
C_CODE
|
|
|
|
|
|
print OUT <<'C_CODE';
|
|
|
|
enum lsquic_version
|
|
lsquic_alpn2ver (const char *alpn, size_t len)
|
|
{
|
|
static const struct el {
|
|
size_t len;
|
|
char alpn[10];
|
|
enum lsquic_version version;
|
|
} map[] = {
|
|
C_CODE
|
|
|
|
for ($i = 0; $i < @all_alpns; ++$i) {
|
|
print OUT " {sizeof(\"$all_alpns[$i]\")-1,\"$all_alpns[$i]\", $all_versions[$i]},\n";
|
|
}
|
|
|
|
print OUT <<'C_CODE';
|
|
};
|
|
const struct el *el;
|
|
|
|
if (alpn)
|
|
for (el = map; el < map + sizeof(map) / sizeof(map[0]); ++el)
|
|
if (el->len == len && 0 == strncmp(el->alpn, alpn, len))
|
|
return el->version;
|
|
|
|
return -1;
|
|
}
|
|
C_CODE
|
|
|
|
close OUT;
|