gnss-sdr/src/core/libs/supl/asn-rrlp/per_opentype.c

451 lines
12 KiB
C

/*
* Copyright (c) 2007 Lev Walkin <vlm@lionet.info>. All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include <asn_internal.h>
#include <constr_TYPE.h>
#include <per_opentype.h>
#include <per_support.h>
typedef struct uper_ugot_key
{
asn_per_data_t oldpd; /* Old per data source */
size_t unclaimed;
size_t ot_moved; /* Number of bits moved by OT processing */
int repeat;
} uper_ugot_key;
static int uper_ugot_refill(asn_per_data_t *pd);
static int per_skip_bits(asn_per_data_t *pd, int skip_nbits);
static asn_dec_rval_t uper_sot_suck(asn_codec_ctx_t * /*ctx*/,
asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints,
void **sptr, asn_per_data_t *pd);
int asn_debug_indent;
/*
* Encode an "open type field".
* #10.1, #10.2
*/
int uper_open_type_put(asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints, void *sptr,
asn_per_outp_t *po)
{
void *buf;
void *bptr;
ssize_t size;
size_t toGo;
ASN_DEBUG("Open type put %s ...", td->name);
size = uper_encode_to_new_buffer(td, constraints, sptr, &buf);
if (size <= 0)
{
return -1;
}
for (bptr = buf, toGo = size; toGo;)
{
ssize_t maySave = uper_put_length(po, toGo);
if (maySave < 0)
{
break;
}
if (per_put_many_bits(po, bptr, maySave * 8))
{
break;
}
bptr = (char *)bptr + maySave;
toGo -= maySave;
}
FREEMEM(buf);
if (toGo)
{
return -1;
}
ASN_DEBUG("Open type put %s of length %d + overhead (1byte?)", td->name,
size);
return 0;
}
static asn_dec_rval_t uper_open_type_get_simple(
asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd)
{
asn_dec_rval_t rv;
ssize_t chunk_bytes;
int repeat;
uint8_t *buf = 0;
size_t bufLen = 0;
size_t bufSize = 0;
asn_per_data_t spd;
size_t padding;
_ASN_STACK_OVERFLOW_CHECK(ctx);
ASN_DEBUG("Getting open type %s...", td->name);
do
{
chunk_bytes = uper_get_length(pd, -1, &repeat);
if (chunk_bytes < 0)
{
FREEMEM(buf);
_ASN_DECODE_STARVED;
}
if (bufLen + chunk_bytes > bufSize)
{
void *ptr;
bufSize = chunk_bytes + (bufSize << 2);
ptr = REALLOC(buf, bufSize);
if (!ptr)
{
FREEMEM(buf);
_ASN_DECODE_FAILED;
}
buf = ptr;
}
if (per_get_many_bits(pd, buf + bufLen, 0, chunk_bytes << 3))
{
FREEMEM(buf);
_ASN_DECODE_STARVED;
}
bufLen += chunk_bytes;
}
while (repeat);
ASN_DEBUG("Getting open type %s encoded in %d bytes", td->name, bufLen);
memset(&spd, 0, sizeof(spd));
spd.buffer = buf;
spd.nbits = bufLen << 3;
asn_debug_indent += 4;
rv = td->uper_decoder(ctx, td, constraints, sptr, &spd);
asn_debug_indent -= 4;
if (rv.code == RC_OK)
{
/* Check padding validity */
padding = spd.nbits - spd.nboff;
if (padding < 8 && per_get_few_bits(&spd, padding) == 0)
{
/* Everything is cool */
FREEMEM(buf);
return rv;
}
FREEMEM(buf);
if (padding >= 8)
{
ASN_DEBUG("Too large padding %d in open type", padding);
_ASN_DECODE_FAILED;
}
else
{
ASN_DEBUG("Non-zero padding");
_ASN_DECODE_FAILED;
}
}
else
{
FREEMEM(buf);
/* rv.code could be RC_WMORE, nonsense in this context */
rv.code = RC_FAIL; /* Noone would give us more */
}
return rv;
}
static asn_dec_rval_t GCC_NOTUSED uper_open_type_get_complex(
asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd)
{
uper_ugot_key arg;
asn_dec_rval_t rv;
ssize_t padding;
_ASN_STACK_OVERFLOW_CHECK(ctx);
ASN_DEBUG("Getting open type %s from %s", td->name, per_data_string(pd));
arg.oldpd = *pd;
arg.unclaimed = 0;
arg.ot_moved = 0;
arg.repeat = 1;
pd->refill = uper_ugot_refill;
pd->refill_key = &arg;
pd->nbits = pd->nboff; /* 0 good bits at this point, will refill */
pd->moved = 0; /* This now counts the open type size in bits */
asn_debug_indent += 4;
rv = td->uper_decoder(ctx, td, constraints, sptr, pd);
asn_debug_indent -= 4;
#define UPDRESTOREPD \
do \
{ \
/* buffer and nboff are valid, preserve them. */ \
pd->nbits = arg.oldpd.nbits - (pd->moved - arg.ot_moved); \
pd->moved = arg.oldpd.moved + (pd->moved - arg.ot_moved); \
pd->refill = arg.oldpd.refill; \
pd->refill_key = arg.oldpd.refill_key; \
} \
while (0)
if (rv.code != RC_OK)
{
UPDRESTOREPD;
return rv;
}
ASN_DEBUG("OpenType %s pd%s old%s unclaimed=%d, repeat=%d", td->name,
per_data_string(pd), per_data_string(&arg.oldpd), arg.unclaimed,
arg.repeat);
padding = pd->moved % 8;
if (padding)
{
int32_t pvalue;
if (padding > 7)
{
ASN_DEBUG("Too large padding %d in open type", padding);
rv.code = RC_FAIL;
UPDRESTOREPD;
return rv;
}
padding = 8 - padding;
ASN_DEBUG("Getting padding of %d bits", padding);
pvalue = per_get_few_bits(pd, padding);
switch (pvalue)
{
case -1:
ASN_DEBUG("Padding skip failed");
UPDRESTOREPD;
_ASN_DECODE_STARVED;
case 0:
break;
default:
ASN_DEBUG("Non-blank padding (%d bits 0x%02x)", padding,
(int)pvalue);
UPDRESTOREPD;
_ASN_DECODE_FAILED;
}
}
if (pd->nboff != pd->nbits)
{
ASN_DEBUG("Open type %s overhead pd%s old%s", td->name,
per_data_string(pd), per_data_string(&arg.oldpd));
if (1)
{
UPDRESTOREPD;
_ASN_DECODE_FAILED;
}
else
{
arg.unclaimed += pd->nbits - pd->nboff;
}
}
/* Adjust pd back so it points to original data */
UPDRESTOREPD;
/* Skip data not consumed by the decoder */
if (arg.unclaimed)
{
ASN_DEBUG("Getting unclaimed %d", arg.unclaimed);
}
if (arg.unclaimed)
{
switch (per_skip_bits(pd, arg.unclaimed))
{
case -1:
ASN_DEBUG("Claim of %d failed", arg.unclaimed);
_ASN_DECODE_STARVED;
case 0:
ASN_DEBUG("Got claim of %d", arg.unclaimed);
break;
default:
/* Padding must be blank */
ASN_DEBUG("Non-blank unconsumed padding");
_ASN_DECODE_FAILED;
}
arg.unclaimed = 0;
}
if (arg.repeat)
{
ASN_DEBUG("Not consumed the whole thing");
rv.code = RC_FAIL;
return rv;
}
return rv;
}
asn_dec_rval_t uper_open_type_get(asn_codec_ctx_t *ctx,
asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints,
void **sptr, asn_per_data_t *pd)
{
return uper_open_type_get_simple(ctx, td, constraints, sptr, pd);
}
int uper_open_type_skip(asn_codec_ctx_t *ctx, asn_per_data_t *pd)
{
asn_TYPE_descriptor_t s_td;
asn_dec_rval_t rv;
s_td.name = "<unknown extension>";
s_td.uper_decoder = uper_sot_suck;
rv = uper_open_type_get(ctx, &s_td, 0, 0, pd);
if (rv.code != RC_OK)
{
return -1;
}
else
{
return 0;
}
}
/*
* Internal functions.
*/
static asn_dec_rval_t uper_sot_suck(asn_codec_ctx_t *ctx,
asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints,
void **sptr, asn_per_data_t *pd)
{
asn_dec_rval_t rv;
(void)ctx;
(void)td;
(void)constraints;
(void)sptr;
while (per_get_few_bits(pd, 24) >= 0)
{
;
}
rv.code = RC_OK;
rv.consumed = pd->moved;
return rv;
}
static int uper_ugot_refill(asn_per_data_t *pd)
{
uper_ugot_key *arg = pd->refill_key;
ssize_t next_chunk_bytes;
ssize_t next_chunk_bits;
ssize_t avail;
asn_per_data_t *oldpd = &arg->oldpd;
ASN_DEBUG("REFILLING pd->moved=%d, oldpd->moved=%d", pd->moved,
oldpd->moved);
/* Advance our position to where pd is */
oldpd->buffer = pd->buffer;
oldpd->nboff = pd->nboff;
oldpd->nbits -= pd->moved - arg->ot_moved;
oldpd->moved += pd->moved - arg->ot_moved;
arg->ot_moved = pd->moved;
if (arg->unclaimed)
{
/* Refill the container */
if (per_get_few_bits(oldpd, 1))
{
return -1;
}
if (oldpd->nboff == 0)
{
assert(0);
return -1;
}
pd->buffer = oldpd->buffer;
pd->nboff = oldpd->nboff - 1;
pd->nbits = oldpd->nbits;
ASN_DEBUG("UNCLAIMED <- return from (pd->moved=%d)", pd->moved);
return 0;
}
if (!arg->repeat)
{
ASN_DEBUG("Want more but refill doesn't have it");
return -1;
}
next_chunk_bytes = uper_get_length(oldpd, -1, &arg->repeat);
ASN_DEBUG("Open type LENGTH %d bytes at off %d, repeat %d",
next_chunk_bytes, oldpd->moved, arg->repeat);
if (next_chunk_bytes < 0)
{
return -1;
}
if (next_chunk_bytes == 0)
{
pd->refill = 0; /* No more refills, naturally */
assert(!arg->repeat); /* Implementation guarantee */
}
next_chunk_bits = next_chunk_bytes << 3;
avail = oldpd->nbits - oldpd->nboff;
if (avail >= next_chunk_bits)
{
pd->nbits = oldpd->nboff + next_chunk_bits;
arg->unclaimed = 0;
ASN_DEBUG("!+Parent frame %d bits, alloting %d [%d..%d] (%d)",
next_chunk_bits, oldpd->moved, oldpd->nboff, oldpd->nbits,
oldpd->nbits - oldpd->nboff);
}
else
{
pd->nbits = oldpd->nbits;
arg->unclaimed = next_chunk_bits - avail;
ASN_DEBUG("!-Parent frame %d, require %d, will claim %d", avail,
next_chunk_bits, arg->unclaimed);
}
pd->buffer = oldpd->buffer;
pd->nboff = oldpd->nboff;
ASN_DEBUG("Refilled pd%s old%s", per_data_string(pd),
per_data_string(oldpd));
return 0;
}
static int per_skip_bits(asn_per_data_t *pd, int skip_nbits)
{
int hasNonZeroBits = 0;
while (skip_nbits > 0)
{
int skip = 0;
if (skip_nbits < skip)
{
skip = skip_nbits;
}
else
{
skip = 24;
}
skip_nbits -= skip;
switch (per_get_few_bits(pd, skip))
{
case -1:
return -1; /* Starving */
case 0:
continue; /* Skipped empty space */
default:
hasNonZeroBits = 1;
continue;
}
}
return hasNonZeroBits;
}