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 */ /* allocate new Invocation State Machine, link it with dialogue */
struct tcap_invocation *ti = tcap_ism_alloc(td, inv_id); struct tcap_invocation *ti = tcap_ism_alloc(td, inv_id);
struct tcap_component *tcomp;
struct Component *comp; struct Component *comp;
struct Invoke *inv; 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; ti->op_class = op_class;
/* Allocate a new component structure */ /* Allocate a new component structure */
tcomp = talloc_zero(td, struct tcap_component); comp = talloc_zero(td, struct Component);
if (!tcomp) if (!comp)
return -ENOMEM; return -ENOMEM;
comp = &tcomp->comp;
comp->present = Component_PR_invoke; comp->present = Component_PR_invoke;
/* Assemble INV component */ /* 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)); memcpy(&inv->opCode, op, sizeof(inv->opCode));
if (param && param_len) 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 */ /* 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; 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 OPERATION *op, uint8_t *param, uint32_t param_len)
{ {
struct tcap_invocation *ti = tcap_ism_lookup(td, inv_id); struct tcap_invocation *ti = tcap_ism_lookup(td, inv_id);
struct tcap_component *tcomp;
struct Component *comp; struct Component *comp;
struct ReturnResult *res; struct ReturnResult *res;
struct resultretres *retres; 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; return -ENOENT;
/* Allocate a new component structure */ /* Allocate a new component structure */
tcomp = talloc_zero(td, struct tcap_component); comp = talloc_zero(td, struct Component);
if (!tcomp) if (!comp)
return -ENOMEM; return -ENOMEM;
comp = &tcomp->comp;
/* Assemble requested component */ /* Assemble requested component */
if (last) { 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; res->resultretres = retres;
memcpy(&retres->opCode, op, sizeof(retres->opCode)); memcpy(&retres->opCode, op, sizeof(retres->opCode));
if (param && param_len) 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 */ /* 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; return 0;
} }

View File

@ -43,33 +43,6 @@ static BIT_STRING_t dial_version1 = {
.bits_unused = 7, .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 */ /* 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, static int extract_appctx_uinfo(OBJECT_IDENTIFIER_t **app_ctx_name, struct user_information **user_info,
struct DialoguePDU *dial_pdu) 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 */ /* Request components to CHA */
/* Process components */ /* Process components */
/* Assemble TSL user data */ /* 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 */ /* TR-UNI-REQ to TSL */
rc = tcap_tco_tr_uni_req(&td->trans, &tcm); 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; struct ComponentPortion cp;
ExternalPDU_t ext; ExternalPDU_t ext;
DialoguePDU_t dial; DialoguePDU_t dial;
ANY_t any;
struct tcap_invocation *ti; struct tcap_invocation *ti;
uint32_t trans_id; uint32_t trans_id;
int rc; int rc;
@ -158,6 +132,7 @@ int tcap_csl_tc_begin_req(struct tcap_dialogue *td, OBJECT_IDENTIFIER_t *app_ctx
if (app_ctx) { if (app_ctx) {
AARQ_apdu_t *aarq; AARQ_apdu_t *aarq;
ANY_t *any;
memset(&dial, 0, sizeof(dial)); memset(&dial, 0, sizeof(dial));
dial.present = DialoguePDU_PR_dialogueRequest; 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); rc = ANY_fromType((ANY_t *) &ext.dialog, &asn_DEF_DialoguePDU, &dial);
if (rc < 0) if (rc < 0)
fprintf(stderr, "Error encoding DialoguePDU portion\n"); fprintf(stderr, "Error encoding DialoguePDU portion\n");
memset(&any, 0, sizeof(any)); any = ANY_new_fromType(&asn_DEF_ExternalPDU, &ext);
rc = ANY_fromType(&any, &asn_DEF_ExternalPDU, &ext); tcm.choice.begin.dialoguePortion = (OCTET_STRING_t *) any;
if (rc < 0)
fprintf(stderr, "Error encoding ExternalPDU portion\n");
tcm.choice.begin.dialoguePortion = (OCTET_STRING_t *) &any;
} }
/* Request components to CHA */ /* Request components to CHA */
/* Process components */ /* Process components */
/* Assemble TSL user data */ /* 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 */ /* Assign local transaction ID */
trans_id = ntohl(td->trans.tid_local); 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); 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; 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 */ /* Request components to CHA */
/* Process components */ /* Process components */
/* Assemble TSL user data */ /* 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 */ /* Assign local transaction ID */
trans_id = htonl(td->trans.tid_local); 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); tcap_trans_set_state(&td->trans, TCAP_TS_ACTIVE);
release_components(td);
return rc; 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 */ /* Request component to CHA */
/* Process components */ /* Process components */
/* Assemble TLS user data */ /* 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 */ /* TR-END.req to TSL */
rc = tcap_tco_tr_end_req(&td->trans, &tcm); rc = tcap_tco_tr_end_req(&td->trans, &tcm);
/* Dialogue terminated to CHA */ /* Dialogue terminated to CHA */

View File

@ -62,12 +62,18 @@ struct tcap_dialogue *tcap_dialg_alloc(uint32_t dialogue_id)
if (!td) if (!td)
return NULL; 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->dialogue_id = dialogue_id;
td->trans.state = TCAP_TS_IDLE; td->trans.state = TCAP_TS_IDLE;
td->trans.tid_local = tcap_trans_id_alloc(); td->trans.tid_local = tcap_trans_id_alloc();
llist_add(&td->list, &tcap_dialogues);
INIT_LLIST_HEAD(&td->ism_list); 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); printf("allocated Dialogue with ID 0x%08x\n", dialogue_id);

View File

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

View File

@ -33,6 +33,7 @@
#include "tcap_user.h" #include "tcap_user.h"
static struct { static struct {
int mode_sender;
struct tcap_transport_entity *tte; struct tcap_transport_entity *tte;
unsigned int begin_rcvd:1; unsigned int begin_rcvd:1;
uint32_t dialg_id; uint32_t dialg_id;
@ -167,6 +168,9 @@ int main(int argc, char **argv)
struct sockaddr_storage ss; struct sockaddr_storage ss;
struct sockaddr_in *sin = (struct sockaddr_in *)&ss; struct sockaddr_in *sin = (struct sockaddr_in *)&ss;
if (argc > 1)
test_state.mode_sender = 1;
talloc_enable_leak_report_full(); talloc_enable_leak_report_full();
signal(SIGINT, &signal_handler); signal(SIGINT, &signal_handler);
signal(SIGSEGV, &signal_handler); signal(SIGSEGV, &signal_handler);
@ -174,7 +178,10 @@ int main(int argc, char **argv)
ss.ss_family = AF_INET; ss.ss_family = AF_INET;
sin->sin_addr.s_addr = INADDR_ANY; 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); test_state.tte = tcap_transp_udp_create(&ss);
if (!test_state.tte) { if (!test_state.tte) {
@ -183,12 +190,19 @@ int main(int argc, char **argv)
} }
/* make sure we sent messages to ourselves */ /* make sure we sent messages to ourselves */
inet_aton("127.0.0.1", &sin->sin_addr); 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)); 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)); if (test_state.mode_sender) {
send_invoke(0x1234, 1, NULL, 0); /* sender mode, send primitives */
send_invoke(0x1234, -1, NULL, 0); send_invoke(0x1234, 0, gprs_loc_upd_param, sizeof(gprs_loc_upd_param));
send_begin(0x1234, &gprsLocationUpdateContext_v3); send_invoke(0x1234, 1, NULL, 0);
send_invoke(0x1234, -1, NULL, 0);
send_begin(0x1234, &gprsLocationUpdateContext_v3);
}
while (1) { while (1) {
bsc_select_main(0); 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) LIB_EXPORTED int tcap_user_req_dialg(enum tcap_primitive prim, struct tcap_dialg_ind *tcdi)
{ {
/* Allocate some structures on the stack */ /* Allocate some structures on the stack */
OBJECT_IDENTIFIER_t _app_ctx; OBJECT_IDENTIFIER_t *app_ctx;
OBJECT_IDENTIFIER_t *app_ctx = NULL; EXTERNAL_t *ext;
EXTERNAL_t ext; struct user_information *user_info;
struct user_information _user_info;
struct user_information *user_info = NULL;
struct tcap_dialogue *td; struct tcap_dialogue *td;
int rc = 0; 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 */ /* Parse the tcap_dialg_ind into something that the asn1c code understands */
if (tcdi->app_ctx_present) { if (tcdi->app_ctx_present) {
app_ctx = &_app_ctx; app_ctx = talloc_zero(td, OBJECT_IDENTIFIER_t);
memset(app_ctx, 0, sizeof(&app_ctx));
OBJECT_IDENTIFIER_set_arcs(app_ctx, &tcdi->app_ctx_name.arc, OBJECT_IDENTIFIER_set_arcs(app_ctx, &tcdi->app_ctx_name.arc,
sizeof(tcdi->app_ctx_name.arc[0]), sizeof(tcdi->app_ctx_name.arc[0]),
tcdi->app_ctx_name.num_arcs); 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 */ /* Parse the tcap_dialg_ind into something that the asn1c code understands */
if (tcdi->user_info_present) { if (tcdi->user_info_present) {
user_info = &_user_info; ext = talloc_zero(td, EXTERNAL_t);
memset(&ext, 0, sizeof(ext)); ext->buf = tcdi->user_info.data;
memset(user_info, 0, sizeof(*user_info)); ext->size = tcdi->user_info.data_len;
ext.buf = tcdi->user_info.data; user_info = talloc_zero(ext, struct user_information);
ext.size = tcdi->user_info.data_len; ASN_SEQUENCE_ADD(&user_info->list, ext);
ASN_SEQUENCE_ADD(&user_info->list, &ext);
} }
switch (prim) { switch (prim) {