bring libosm-tcap more in line with libasn1c's use of talloc

libasn1c expects all data structures to be heap-allocated, whereas
we used to allocate some of them on the stack, which causes problems
at free() time.

As a side-effect, we had to remove the 'struct tcap_component' and
replace its list_head in tcap_dialogue with a 'struct ComponentPortion'
This commit is contained in:
Harald Welte 2010-07-19 15:09:23 +02:00
parent 5a7afc24a7
commit a764e40c80
6 changed files with 58 additions and 79 deletions

View File

@ -77,7 +77,6 @@ int tcap_cha_tc_invoke_req(struct tcap_dialogue *td, uint8_t op_class, int8_t in
{
/* allocate new Invocation State Machine, link it with dialogue */
struct tcap_invocation *ti = tcap_ism_alloc(td, inv_id);
struct tcap_component *tcomp;
struct Component *comp;
struct Invoke *inv;
@ -94,10 +93,9 @@ int tcap_cha_tc_invoke_req(struct tcap_dialogue *td, uint8_t op_class, int8_t in
ti->op_class = op_class;
/* Allocate a new component structure */
tcomp = talloc_zero(td, struct tcap_component);
if (!tcomp)
comp = talloc_zero(td, struct Component);
if (!comp)
return -ENOMEM;
comp = &tcomp->comp;
comp->present = Component_PR_invoke;
/* Assemble INV component */
@ -110,10 +108,10 @@ int tcap_cha_tc_invoke_req(struct tcap_dialogue *td, uint8_t op_class, int8_t in
}
memcpy(&inv->opCode, op, sizeof(inv->opCode));
if (param && param_len)
inv->parameter = gen_param(tcomp, param, param_len);
inv->parameter = gen_param(comp, param, param_len);
/* Make component available for this Dialogue ID */
llist_add_tail(&tcomp->list, &td->pend_comp_list);
asn_sequence_add(&td->pend_comp->list, comp);
return 0;
}
@ -140,7 +138,6 @@ int tcap_cha_tc_result_req(struct tcap_dialogue *td, int8_t inv_id, int last,
struct OPERATION *op, uint8_t *param, uint32_t param_len)
{
struct tcap_invocation *ti = tcap_ism_lookup(td, inv_id);
struct tcap_component *tcomp;
struct Component *comp;
struct ReturnResult *res;
struct resultretres *retres;
@ -149,10 +146,9 @@ int tcap_cha_tc_result_req(struct tcap_dialogue *td, int8_t inv_id, int last,
return -ENOENT;
/* Allocate a new component structure */
tcomp = talloc_zero(td, struct tcap_component);
if (!tcomp)
comp = talloc_zero(td, struct Component);
if (!comp)
return -ENOMEM;
comp = &tcomp->comp;
/* Assemble requested component */
if (last) {
@ -167,10 +163,10 @@ int tcap_cha_tc_result_req(struct tcap_dialogue *td, int8_t inv_id, int last,
res->resultretres = retres;
memcpy(&retres->opCode, op, sizeof(retres->opCode));
if (param && param_len)
retres->parameter = gen_param(tcomp, param, param_len);
retres->parameter = gen_param(comp, param, param_len);
/* Mark component available for this dialogue ID */
llist_add_tail(&tcomp->list, &td->pend_comp_list);
asn_sequence_add(&td->pend_comp->list, comp);
return 0;
}

View File

@ -43,33 +43,6 @@ static BIT_STRING_t dial_version1 = {
.bits_unused = 7,
};
/* Assemble the list (sequence) of pending components for a dialogue */
static ComponentPortion_t *assemble_components(ComponentPortion_t *cp, struct tcap_dialogue *td)
{
struct tcap_component *tcomp;
unsigned int comp_count = 0;
memset(cp, 0, sizeof(*cp));
llist_for_each_entry(tcomp, &td->pend_comp_list, list) {
ASN_SEQUENCE_ADD(&cp->list, &tcomp->comp);
comp_count++;
}
if (comp_count)
return cp;
return NULL;
}
static void release_components(struct tcap_dialogue *td)
{
struct tcap_component *tcomp, *tcomp2;
llist_for_each_entry_safe(tcomp, tcomp2, &td->pend_comp_list, list) {
llist_del(&tcomp->list);
talloc_free(tcomp);
}
}
/* Extract the Application Context Name and User Info from a DialoguePDU */
static int extract_appctx_uinfo(OBJECT_IDENTIFIER_t **app_ctx_name, struct user_information **user_info,
struct DialoguePDU *dial_pdu)
@ -129,7 +102,9 @@ int tcap_csl_tc_uni_req(struct tcap_dialogue *td, OBJECT_IDENTIFIER_t *app_ctx,
/* Request components to CHA */
/* Process components */
/* Assemble TSL user data */
assemble_components(&tcm.choice.unidirectional.components, td);
memcpy(&tcm.choice.unidirectional.components, td->pend_comp, sizeof(*td->pend_comp));
talloc_free(td->pend_comp);
td->pend_comp = talloc_zero(td, struct ComponentPortion);
/* TR-UNI-REQ to TSL */
rc = tcap_tco_tr_uni_req(&td->trans, &tcm);
@ -148,7 +123,6 @@ int tcap_csl_tc_begin_req(struct tcap_dialogue *td, OBJECT_IDENTIFIER_t *app_ctx
struct ComponentPortion cp;
ExternalPDU_t ext;
DialoguePDU_t dial;
ANY_t any;
struct tcap_invocation *ti;
uint32_t trans_id;
int rc;
@ -158,6 +132,7 @@ int tcap_csl_tc_begin_req(struct tcap_dialogue *td, OBJECT_IDENTIFIER_t *app_ctx
if (app_ctx) {
AARQ_apdu_t *aarq;
ANY_t *any;
memset(&dial, 0, sizeof(dial));
dial.present = DialoguePDU_PR_dialogueRequest;
@ -178,16 +153,14 @@ int tcap_csl_tc_begin_req(struct tcap_dialogue *td, OBJECT_IDENTIFIER_t *app_ctx
rc = ANY_fromType((ANY_t *) &ext.dialog, &asn_DEF_DialoguePDU, &dial);
if (rc < 0)
fprintf(stderr, "Error encoding DialoguePDU portion\n");
memset(&any, 0, sizeof(any));
rc = ANY_fromType(&any, &asn_DEF_ExternalPDU, &ext);
if (rc < 0)
fprintf(stderr, "Error encoding ExternalPDU portion\n");
tcm.choice.begin.dialoguePortion = (OCTET_STRING_t *) &any;
any = ANY_new_fromType(&asn_DEF_ExternalPDU, &ext);
tcm.choice.begin.dialoguePortion = (OCTET_STRING_t *) any;
}
/* Request components to CHA */
/* Process components */
/* Assemble TSL user data */
tcm.choice.begin.components = assemble_components(&cp, td);
tcm.choice.begin.components = td->pend_comp;
td->pend_comp = talloc_zero(td, struct ComponentPortion);
/* Assign local transaction ID */
trans_id = ntohl(td->trans.tid_local);
@ -199,7 +172,7 @@ int tcap_csl_tc_begin_req(struct tcap_dialogue *td, OBJECT_IDENTIFIER_t *app_ctx
tcap_trans_set_state(&td->trans, TCAP_TS_INIT_SENT);
release_components(td);
asn_DEF_TCMessage.free_struct(&asn_DEF_TCMessage, &tcm, 1);
return rc;
}
@ -399,7 +372,8 @@ int tcap_csl_tc_cont_req(struct tcap_dialogue *td, OBJECT_IDENTIFIER_t *app_ctx,
/* Request components to CHA */
/* Process components */
/* Assemble TSL user data */
tcm.choice.Continue.components = assemble_components(&cp, td);
tcm.choice.Continue.components = td->pend_comp;
td->pend_comp = talloc_zero(td, struct ComponentPortion);
/* Assign local transaction ID */
trans_id = htonl(td->trans.tid_local);
@ -417,8 +391,6 @@ int tcap_csl_tc_cont_req(struct tcap_dialogue *td, OBJECT_IDENTIFIER_t *app_ctx,
tcap_trans_set_state(&td->trans, TCAP_TS_ACTIVE);
release_components(td);
return rc;
}
@ -469,7 +441,8 @@ int tcap_csl_tc_end_req(struct tcap_dialogue *td, OBJECT_IDENTIFIER_t *app_ctx,
/* Request component to CHA */
/* Process components */
/* Assemble TLS user data */
tcm.choice.end.components = assemble_components(&cp, td);
tcm.choice.end.components = td->pend_comp;
talloc_zero(td, struct ComponentPortion);
/* TR-END.req to TSL */
rc = tcap_tco_tr_end_req(&td->trans, &tcm);
/* Dialogue terminated to CHA */

View File

@ -62,12 +62,18 @@ struct tcap_dialogue *tcap_dialg_alloc(uint32_t dialogue_id)
if (!td)
return NULL;
td->pend_comp = talloc_zero(td, struct ComponentPortion);
if (!td->pend_comp) {
talloc_free(td);
return NULL;
}
td->dialogue_id = dialogue_id;
td->trans.state = TCAP_TS_IDLE;
td->trans.tid_local = tcap_trans_id_alloc();
llist_add(&td->list, &tcap_dialogues);
INIT_LLIST_HEAD(&td->ism_list);
INIT_LLIST_HEAD(&td->pend_comp_list);
llist_add(&td->list, &tcap_dialogues);
printf("allocated Dialogue with ID 0x%08x\n", dialogue_id);

View File

@ -38,12 +38,6 @@
#define LIB_EXPORTED
#endif
struct tcap_component {
struct llist_head list;
struct Component comp; /* Invoke Component */
};
enum tcap_transaction_state {
TCAP_TS_INVALID,
TCAP_TS_IDLE,
@ -73,7 +67,7 @@ struct tcap_dialogue {
struct llist_head ism_list;
/* list of pending components for this dialogue */
struct llist_head pend_comp_list;
struct ComponentPortion *pend_comp;
/* There is a 1:1 mapping of transactions to dialogues */
struct tcap_transaction trans;

View File

@ -33,6 +33,7 @@
#include "tcap_user.h"
static struct {
int mode_sender;
struct tcap_transport_entity *tte;
unsigned int begin_rcvd:1;
uint32_t dialg_id;
@ -167,6 +168,9 @@ int main(int argc, char **argv)
struct sockaddr_storage ss;
struct sockaddr_in *sin = (struct sockaddr_in *)&ss;
if (argc > 1)
test_state.mode_sender = 1;
talloc_enable_leak_report_full();
signal(SIGINT, &signal_handler);
signal(SIGSEGV, &signal_handler);
@ -174,7 +178,10 @@ int main(int argc, char **argv)
ss.ss_family = AF_INET;
sin->sin_addr.s_addr = INADDR_ANY;
sin->sin_port = htons(4242);
if (test_state.mode_sender)
sin->sin_port = htons(4242);
else
sin->sin_port = htons(4243);
test_state.tte = tcap_transp_udp_create(&ss);
if (!test_state.tte) {
@ -183,12 +190,19 @@ int main(int argc, char **argv)
}
/* make sure we sent messages to ourselves */
inet_aton("127.0.0.1", &sin->sin_addr);
if (!test_state.mode_sender)
sin->sin_port = htons(4242);
else
sin->sin_port = htons(4243);
memcpy(&test_state.tte->remote_addr, &ss, sizeof(test_state.tte->remote_addr));
send_invoke(0x1234, 0, gprs_loc_upd_param, sizeof(gprs_loc_upd_param));
send_invoke(0x1234, 1, NULL, 0);
send_invoke(0x1234, -1, NULL, 0);
send_begin(0x1234, &gprsLocationUpdateContext_v3);
if (test_state.mode_sender) {
/* sender mode, send primitives */
send_invoke(0x1234, 0, gprs_loc_upd_param, sizeof(gprs_loc_upd_param));
send_invoke(0x1234, 1, NULL, 0);
send_invoke(0x1234, -1, NULL, 0);
send_begin(0x1234, &gprsLocationUpdateContext_v3);
}
while (1) {
bsc_select_main(0);

View File

@ -242,11 +242,9 @@ LIB_EXPORTED int tcap_user_req_comp(enum tcap_primitive prim, struct tcap_compon
LIB_EXPORTED int tcap_user_req_dialg(enum tcap_primitive prim, struct tcap_dialg_ind *tcdi)
{
/* Allocate some structures on the stack */
OBJECT_IDENTIFIER_t _app_ctx;
OBJECT_IDENTIFIER_t *app_ctx = NULL;
EXTERNAL_t ext;
struct user_information _user_info;
struct user_information *user_info = NULL;
OBJECT_IDENTIFIER_t *app_ctx;
EXTERNAL_t *ext;
struct user_information *user_info;
struct tcap_dialogue *td;
int rc = 0;
@ -268,8 +266,7 @@ LIB_EXPORTED int tcap_user_req_dialg(enum tcap_primitive prim, struct tcap_dialg
/* Parse the tcap_dialg_ind into something that the asn1c code understands */
if (tcdi->app_ctx_present) {
app_ctx = &_app_ctx;
memset(app_ctx, 0, sizeof(&app_ctx));
app_ctx = talloc_zero(td, OBJECT_IDENTIFIER_t);
OBJECT_IDENTIFIER_set_arcs(app_ctx, &tcdi->app_ctx_name.arc,
sizeof(tcdi->app_ctx_name.arc[0]),
tcdi->app_ctx_name.num_arcs);
@ -277,12 +274,11 @@ LIB_EXPORTED int tcap_user_req_dialg(enum tcap_primitive prim, struct tcap_dialg
/* Parse the tcap_dialg_ind into something that the asn1c code understands */
if (tcdi->user_info_present) {
user_info = &_user_info;
memset(&ext, 0, sizeof(ext));
memset(user_info, 0, sizeof(*user_info));
ext.buf = tcdi->user_info.data;
ext.size = tcdi->user_info.data_len;
ASN_SEQUENCE_ADD(&user_info->list, &ext);
ext = talloc_zero(td, EXTERNAL_t);
ext->buf = tcdi->user_info.data;
ext->size = tcdi->user_info.data_len;
user_info = talloc_zero(ext, struct user_information);
ASN_SEQUENCE_ADD(&user_info->list, ext);
}
switch (prim) {