libosmo-tcap/src/dialogue.c

189 lines
4.8 KiB
C

/* (C) 2010 by Harald Welte <laforge@gnumonks.org>
* (C) 2010 by On-Waves
*
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <unistd.h>
#include <stdint.h>
#include <errno.h>
#include <osmocore/linuxlist.h>
#include <osmocore/talloc.h>
#include <osmocore/utils.h>
#include <osmocore/logging.h>
#include "tcap.h"
static LLIST_HEAD(tcap_dialogues);
static uint32_t dialg_id_ctr = 0x4000;
static uint32_t trans_id_ctr = 0x8000;
void *tall_tcap_dialg_ctx;
uint32_t tcap_dialg_id_alloc(void)
{
uint32_t dialg_id;
dialg_id = dialg_id_ctr++;
while (tcap_dialg_by_dialg_id(dialg_id))
dialg_id = dialg_id_ctr++;
printf("found free Dialogue ID 0x%08x\n", dialg_id);
return dialg_id;
}
struct tcap_dialogue *tcap_dialg_by_dialg_id(uint32_t dialogue_id)
{
struct tcap_dialogue *td;
llist_for_each_entry(td, &tcap_dialogues, list) {
if (td->dialogue_id == dialogue_id)
return td;
}
return NULL;
}
static void _comp_seq_elem_free(Component_t *comp)
{
asn_DEF_Component.free_struct(&asn_DEF_Component, comp, 0);
}
/* Add a single component to the list of pending components of this dialogue */
int tcap_dialg_comp_add(struct tcap_dialogue *td, Component_t *comp)
{
if (!td->pend_comp) {
td->pend_comp = talloc_zero(td, struct ComponentPortion);
if (!td->pend_comp)
return -ENOMEM;
td->pend_comp->list.free = _comp_seq_elem_free;
}
ASN_SEQUENCE_ADD(&td->pend_comp->list, comp);
}
struct tcap_dialogue *tcap_dialg_alloc(uint32_t dialogue_id)
{
struct tcap_dialogue *td = talloc_zero(tall_tcap_dialg_ctx, struct tcap_dialogue);
if (!td)
return NULL;
td->dialogue_id = dialogue_id;
td->trans.state = TCAP_TS_IDLE;
td->trans.tid_local = tcap_trans_id_alloc();
INIT_LLIST_HEAD(&td->ism_list);
llist_add(&td->list, &tcap_dialogues);
printf("allocated Dialogue with ID 0x%08x\n", dialogue_id);
return td;
}
void tcap_dialg_free(struct tcap_dialogue *td)
{
printf("freeing Dialogue with ID 0x%08x\n", td->dialogue_id);
/* Delete from global list of all dialogues */
llist_del(&td->list);
/* No need to iterate over pending component list, talloc is hierarchical */
/* No need to iterate over ISM list, talloc is hierarchical */
talloc_free(td);
}
/* allocate a transaction (by allocating a dialogue) */
struct tcap_transaction *tcap_transaction_alloc(void)
{
uint32_t dialg_id = tcap_dialg_id_alloc();
struct tcap_dialogue *td = tcap_dialg_alloc(dialg_id);
return &td->trans;
}
struct tcap_transaction *tcap_transaction_by_remote_tid(uint32_t tid_remote)
{
struct tcap_dialogue *td;
llist_for_each_entry(td, &tcap_dialogues, list) {
if (td->trans.tid_remote == tid_remote)
return &td->trans;
}
return NULL;
}
struct tcap_transaction *tcap_transaction_by_local_tid(uint32_t tid_local)
{
struct tcap_dialogue *td;
llist_for_each_entry(td, &tcap_dialogues, list) {
if (td->trans.tid_local == tid_local)
return &td->trans;
}
return NULL;
}
uint32_t tcap_trans_id_alloc(void)
{
uint32_t trans_id;
trans_id = trans_id_ctr++;
while (tcap_transaction_by_local_tid(trans_id))
trans_id = trans_id_ctr++;
return trans_id;
}
static const struct value_string trans_state_name[] = {
{ TCAP_TS_INVALID, "TS-Invalid" },
{ TCAP_TS_IDLE, "TS-Idle" },
{ TCAP_TS_INIT_RECV, "TS-Initiation-Received" },
{ TCAP_TS_INIT_SENT, "TS-Initiation-Sent" },
{ TCAP_TS_ACTIVE, "TS-Active" },
{ 0, NULL }
};
static const struct value_string inv_state_name[] = {
{ TCAP_IS_INVALID, "IS-Invalid" },
{ TCAP_IS_IDLE, "IS-Idle" },
{ TCAP_IS_OP_SENT_CL1, "IS-Operation-Sent-CL1" },
{ TCAP_IS_OP_SENT_CL2, "IS-Operation-Sent-CL2" },
{ TCAP_IS_OP_SENT_CL3, "IS-Operation-Sent-CL3" },
{ TCAP_IS_OP_SENT_CL4, "IS-Operation-Sent-CL4" },
{ TCAP_IS_WAIT_REJECT, "IS-Wait-Reject" },
{ 0, NULL }
};
const char *tcap_trans_state_name(enum tcap_transaction_state ts)
{
return get_value_string(trans_state_name, ts);
}
const char *tcap_inv_state_name(enum tcap_invocation_state is)
{
return get_value_string(inv_state_name, is);
}
void tcap_trans_set_state(struct tcap_transaction *tt, enum tcap_transaction_state st)
{
printf("Transaction 0x%08x old_state=%s, new_state=%s\n", tt->tid_local,
tcap_trans_state_name(tt->state), tcap_trans_state_name(st));
tt->state = st;
}