libosmo-tcap/src/tcu.c

235 lines
6.1 KiB
C

/* TC-User */
/* (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 <stdint.h>
#include <errno.h>
#include <osmocore/msgb.h>
#include <osmocore/utils.h>
#include <osmocom/tcap/Parameter.h>
#include "tcap.h"
#include "tcap_user.h"
static const struct value_string tcap_prim_names[] = {
/* dialogue handling */
{ TCAP_PR_TC_UNI, "TC-UNI" },
{ TCAP_PR_TC_BEGIN, "TC-BEGIN" },
{ TCAP_PR_TC_CONTINUE, "TC-CONTINUE" },
{ TCAP_PR_TC_END, "TC-END" },
{ TCAP_PR_TC_U_ABORT, "TC-U-ABORT" },
{ TCAP_PR_TC_NOTICE, "TC-NOTICE" },
/* component handling */
{ TCAP_PR_TC_INVOKE, "TC-INVOKE" },
{ TCAP_PR_TC_RESULT_L, "TC-RESULT-L" },
{ TCAP_PR_TC_RESULT_NL, "TC-RESULT-NL" },
{ TCAP_PR_TC_U_ERROR, "TC-U-ERROR" },
{ TCAP_PR_TC_U_REJECT, "TC-U-REJECT" },
{ TCAP_PR_TC_CANCEL, "TC-CANCEL" },
{ TCAP_PR_TC_L_REJECT, "TC-L-REJECT" },
{ TCAP_PR_TC_R_REJECT, "TC-R-REJECT" },
{ TCAP_PR_TC_P_ABORT, "TC-P-ABORT" },
{ 0, NULL }
};
LIB_EXPORTED const char *tcap_prim_name(enum tcap_primitive prim)
{
return get_value_string(tcap_prim_names, prim);
}
/* Table 10 / Q.771 : TC-INVOKE.ind */
int tcap_tcu_tc_invoke_ind(struct tcap_invocation *ti, struct OPERATION *oper, Parameter_t *param, int last)
{
struct tcap_component_ind tcci;
memset(&tcci, 0, sizeof(tcci));
tcci.dialg_id = ti->dialogue->dialogue_id;
tcci.invoke_id = ti->invoke_id;
if (ti->linked_id) {
tcci._linked_id = ti->_linked_id;
tcci.linked_id = &tcci._linked_id;
}
memcpy(&tcci.operation, oper, sizeof(tcci.operation));
tcci.last_component = last;
return tcap_user_ind_comp(TCAP_PR_TC_INVOKE, &tcci);
}
/* TC-L-REJECT.ind */
int tcap_tcu_tc_l_rej_ind(struct tcap_invocation *ti, int8_t *invoke_id, uint32_t problem)
{
}
/* TC-R-REJECT.ind */
int tcap_tcu_tc_r_rej_ind(struct tcap_invocation *ti, int8_t *invoke_id, uint32_t problem)
{
}
/* TC-BEGIN.ind from DHA */
int tcap_tcu_begin_ind(struct tcap_dialogue *td, void *app_ctx_name, void *user_info, int comp_present)
{
struct tcap_dialg_ind tcdi;
memset(&tcdi, 0, sizeof(tcdi));
tcdi.dialg_id = td->dialogue_id;
tcdi.app_ctx_name = app_ctx_name;
tcdi.user_info = user_info;
tcdi.components_present = comp_present;
return tcap_user_ind_dialg(TCAP_PR_TC_BEGIN, &tcdi);
}
/* TC-UNI.ind from DHA */
int tcap_tcu_uni_ind(struct tcap_dialogue *td, void *app_ctx_name, void *user_info, int comp_present)
{
}
/* TC-CONT.ind from DHA */
int tcap_tcu_cont_ind(struct tcap_dialogue *td, void *app_ctx_name, void *user_info, int comp_present)
{
struct tcap_dialg_ind tcdi;
memset(&tcdi, 0, sizeof(tcdi));
tcdi.dialg_id = td->dialogue_id;
tcdi.app_ctx_name;
tcdi.user_info;
tcdi.components_present = comp_present;
return tcap_user_ind_dialg(TCAP_PR_TC_CONTINUE, &tcdi);
}
/* TC-END.ind from DHA */
int tcap_tcu_end_ind(struct tcap_dialogue *td, void *app_ctx_name, void *user_info, int comp_present)
{
struct tcap_dialg_ind tcdi;
memset(&tcdi, 0, sizeof(tcdi));
tcdi.dialg_id = td->dialogue_id;
tcdi.app_ctx_name;
tcdi.user_info;
tcdi.components_present = comp_present;
return tcap_user_ind_dialg(TCAP_PR_TC_END, &tcdi);
}
/* TC-ABORT.ind from DHA */
int tcap_tcu_abort_ind(struct tcap_dialogue *td, void *app_ctx_name, void *user_info)
{
}
/* TC-NOTICE.ind from DHA */
int tcap_tcu_notice_ind(struct tcap_dialogue *td, uint32_t cause)
{
}
/* TC-RESULT-L.ind from ISM */
int tcap_tcu_result_l_ind()
{
}
/* TC-RESULT-NL.ind from ISM */
int tcap_tcu_result_nl_ind()
{
}
LIB_EXPORTED int tcap_user_req_comp(enum tcap_primitive prim, struct tcap_component_ind *tcci)
{
struct tcap_dialogue *td;
int rc = 0;
/* Resolve (or allocate) the dialogue/transaction state */
td = tcap_dialg_by_dialg_id(tcci->dialg_id);
if (!td) {
switch (prim) {
case TCAP_PR_TC_INVOKE:
td = tcap_dialg_alloc(tcci->dialg_id);
td->trans.tid_local = tcap_trans_id_alloc();
break;
default:
return -EINVAL;
}
}
/* Actually dispatch the primitive */
switch (prim) {
case TCAP_PR_TC_INVOKE:
rc = tcap_cha_tc_invoke_req(td, tcci->op_class, tcci->invoke_id, tcci->linked_id, &tcci->operation,
tcci->parameter.buf, tcci->parameter.size, tcci->timeout_secs);
break;
case TCAP_PR_TC_RESULT_L:
rc = tcap_cha_tc_result_req(td, tcci->invoke_id, 1, &tcci->operation, &tcci->parameter.buf,
tcci->parameter.buf);
break;
case TCAP_PR_TC_RESULT_NL:
rc = tcap_cha_tc_result_req(td, tcci->invoke_id, 0, &tcci->operation, tcci->parameter.buf,
tcci->parameter.buf);
break;
default:
fprintf(stderr, "unsupported dialogue primitive %s\n", tcap_prim_name(prim));
return -EINVAL;
}
return rc;
}
LIB_EXPORTED int tcap_user_req_dialg(enum tcap_primitive prim, struct tcap_dialg_ind *tcdi)
{
struct tcap_dialogue *td;
int rc = 0;
/* Resolve (or allocate) the dialogue/transaction state */
td = tcap_dialg_by_dialg_id(tcdi->dialg_id);
if (!td) {
switch (prim) {
case TCAP_PR_TC_BEGIN:
td = tcap_dialg_alloc(tcdi->dialg_id);
if (!td)
return -EINVAL;
break;
default:
return -EINVAL;
}
}
switch (prim) {
case TCAP_PR_TC_BEGIN:
td->transp_ent = tcdi->transp_ent;
rc = tcap_csl_tc_begin_req(td, tcdi->app_ctx_name, tcdi->user_info);
break;
case TCAP_PR_TC_CONTINUE:
fprintf(stdout, "TC-CONTINUE.req\n");
rc = tcap_csl_tc_cont_req(td, tcdi->app_ctx_name, tcdi->user_info);
break;
case TCAP_PR_TC_END:
rc = tcap_csl_tc_end_req(td, tcdi->app_ctx_name, tcdi->user_info, tcdi->prearranged_end);
break;
default:
fprintf(stderr, "unsupported component primitive %s\n", tcap_prim_name(prim));
return -EINVAL;
}
return rc;
}