osmo-teletex/src/t62.c

130 lines
3.5 KiB
C

#include <osmocom/core/utils.h>
#include "t62.h"
/* T.61 Table 1 */
const struct value_string t62_session_element_id_str[] = {
{ T62_SID_CSS, "Command Session Start" },
{ T62_SID_CSE, "Command Session End" },
{ T62_SID_CSA, "Command Session Abort" },
{ T62_SID_CSCC, "Command Session Change Control" },
{ T62_SID_CSUI, "Command Session User Information" },
{ T62_SID_RSSP, "Response Session Start Positive" },
{ T62_SID_RSSN, "Response Session Start Negative" },
{ T62_SID_RSEP, "Response Session End Positive" },
{ T62_SID_RSAP, "Response Session Abort Positive" },
{ T62_SID_RSCCP,"Response Session Change Control Positive" },
{ T62_SID_RSUI, "Response Session User Information" },
{ 0, NULL }
};
/* T.62 Table 2 */
const struct value_string t62_command_resp_str[] = {
{ T62_DCID_CDS, "Command Document Start" },
{ T62_DCID_CDC, "Command Document Continue" },
{ T62_DCID_CDE, "Command Document End" },
{ T62_DCID_CDR, "Command Document Resynchronize" },
{ T62_DCID_CDD, "Command Document Discard" },
{ T62_DCID_CDPB, "Command Document Page Boundary" },
{ T62_DCID_CDCL, "Command Document Capability List" },
{ T62_DCID_CDUI, "Command Document User Information" },
{ T62_DRID_RDEP, "Response Document End Positive" },
{ T62_DRID_RDRP, "Response Document Resynchronize Positive" },
{ T62_DRID_RDDP, "Response Document Discard Positive" },
{ T62_DRID_RDPBP, "Response Document Page Boundary Positive" },
{ T62_DRID_RDPBN, "Response Document Page Boundary Negative" },
{ T62_DRID_RDCLP, "Response Document Capability List Positive" },
{ T62_DRID_RDGR, "Response Document General Reject" },
{ 0, NULL }
};
struct t62_part {
struct llist_head list;
struct t62_part *parent;
uint8_t id;
const uint8_t *data;
uint16_t data_len;
struct llist_head children;
};
static struct t62_part *t62_part_alloc(void *ctx, struct t62_part *parent)
{
struct t62_part *part = talloc_zero(ctx, struct t62_part);
if (!part)
return NULL;
if (parent) {
part->parent = parent;
llist_add_tail(&part->list, &parent->children);
}
INIT_LLIST_HEAD(&part->children);
return part;
}
static void t62_part_free(struct t62_part *part)
{
if (part->parent)
llist_del(&part->list);
talloc_free(part);
}
/*! parse one T.62 parameter from msg starting at cur. Recurse if parameter is Parameter Group.
* \param[in] msg message buffer holding input data
* \param[in] cur pointer pointing to first byte of param (PI/PGI) inside msg
* \param[in] parent optional pointer to parent t62_part (in case of nesting)
* \returns parsed t62_param or NULL in case of error. */
struct t62_part *t62_parse_param(struct msgb *msg, uint8_t *cur, struct llist_head *parent)
{
struct t62_part *part = t62_part_alloc(parent, parent);
uint8_t pi;
uint16_t len;
/* FIXME: check msgb->length overflow everywhere below */
pi = *cur++;
if (*cur <= 254) {
/* 8-bit length */
len = *cur++;
} else {
/* 16-bit length */
cur++;
len = *cur++ << 8;
len |= *cur++;
}
part->id = pi;
if (len) {
part->data = cur;
part->data_len = len;
if (is_pgi(pi)) {
/* recurse if it's a group */
rc = t62_parse_param(msg, cur, part);
if (rc < 0) {
t62_part_free(part);
return NULL;
}
}
}
return part;
}
int t62_parse(struct msgb *msg, struct llist_head *parent)
{
uint8_t *cur;
uint8_t ci;
uint16_t len;
cur = msgb_l3h(msg);
root_part = t62_parse_param(msg, cur, NULL);
if (!root_part)
return -1;
/* check if there's user information after all (recursive) parts */
if (cur + root_part->data_len < msgb_l3len(msg)) {
/* FIXME */
}
}