235 lines
6.1 KiB
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;
|
|
}
|