/*
 * (C) 2019 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
 * All rights reserved.
 *
 * Author: Pau Espin Pedrol <pespin@sysmocom.de>
 *
 * Released under the terms of GNU General Public License, Version 2 or
 * (at your option) any later version.
 */

module OSMUX_Types {

import from General_Types all;
import from Misc_Helpers all;

import from AMR_Types all;

external function enc_OSMUX_PDU ( in OSMUX_PDU msg ) return octetstring
        with { extension "prototype(convert) encode(RAW)" };
external function dec_OSMUX_PDU ( in octetstring msg ) return OSMUX_PDU
        with { extension "prototype(convert) decode(RAW)" };

type INT1 OsmuxCID	(0 .. 255);

type enumerated OsmuxFT {
  OSMUX_FT_LAPD,
  OSMUX_FT_AMR,
  OSMUX_FT_DUMMY
};

type record Osmux_AMR_header {
  BIT1                 marker,
  INT2b                ft,
  INT3b                ctr,
  BIT1                 amr_f,
  BIT1                 amr_q,
  INT1                 seq,
  OsmuxCID             cid,
  INT4b                amr_ft,
  INT4b                amr_cmr
} with {
  variant "FIELDORDER(msb)"
}

type record PDU_Osmux_AMR {
  Osmux_AMR_header     header,
  octetstring          data
} with {
  variant "FIELDORDER(msb)"
};

type record PDU_Osmux_DUMMY {
  Osmux_AMR_header     header,
  octetstring          data
} with {
  variant "FIELDORDER(msb)"
};

type record Osmux_session_par {
  integer               id optional,
  charstring            local_address optional,
  integer               local_port optional,
  charstring            dest_address optional,
  integer               dest_port optional
}

type record ASP_Osmux_Open_session {
  Osmux_session_par       session_id
}

type record ASP_Osmux_Open_session_result {
  Osmux_session_par       session_id
}

type record ASP_Osmux_Close_session {
  Osmux_session_par       session_id
}

type union OSMUX_PDU {
  PDU_Osmux_AMR               osmux_amr,
  PDU_Osmux_DUMMY             osmux_dummy
} with {
  variant "TAG (
    osmux_amr, header.ft = 1;
    osmux_dummy, header.ft = 2;
  )"
};

template (present) OSMUX_PDU tr_PDU_Osmux_AMR(template (present) BIT1 marker := ?,
						  template (present) INT3b ctr := ?,
						  template (present) BIT1 amr_f := ?,
						  template (present) BIT1 amr_q := ?,
						  template (present) INT1 seq := ?,
						  template (present) OsmuxCID cid := ?,
						  template (present) INT4b amr_ft := ?,
						  template (present) INT4b amr_cmr := ?,
						  template (present) octetstring payload := ?) := {
	osmux_amr := {
		header := {
			marker := marker,
			ft := 1,
			ctr := ctr,
			amr_f := amr_f,
			amr_q := amr_q,
			seq := seq,
			cid := cid,
			amr_ft := amr_ft,
			amr_cmr := amr_cmr
		},
		data := payload
	}
}

/* Get Nth AMR payload of osmux AMR frame (starting from 0) */
function f_osmux_amr_get_nth_amr_payload(PDU_Osmux_AMR osmux_amr, integer nth) return octetstring
{
	var integer amr_pl_len := f_amrft_payload_len(osmux_amr.header.amr_ft);
	if (nth > osmux_amr.header.ctr) {
		Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "nth > ctr");
		return ''O;
	}
	if (amr_pl_len * (nth+1) > lengthof(osmux_amr.data)) {
		Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "osmux payload too short");
	}
	var octetstring pl := substr(osmux_amr.data, amr_pl_len * nth, amr_pl_len);
	return pl;
}

} with { encode "RAW"}
