diff options
Diffstat (limited to 'src/libmsc/transaction.c')
-rw-r--r-- | src/libmsc/transaction.c | 81 |
1 files changed, 66 insertions, 15 deletions
diff --git a/src/libmsc/transaction.c b/src/libmsc/transaction.c index dba4bed17..d157f5469 100644 --- a/src/libmsc/transaction.c +++ b/src/libmsc/transaction.c @@ -23,25 +23,31 @@ #include <openbsc/mncc.h> #include <openbsc/debug.h> #include <osmocom/core/talloc.h> -#include <openbsc/gsm_subscriber.h> #include <openbsc/gsm_04_08.h> #include <openbsc/mncc.h> #include <openbsc/paging.h> #include <openbsc/osmo_msc.h> +#include <openbsc/vlr.h> void *tall_trans_ctx; void _gsm48_cc_trans_free(struct gsm_trans *trans); +/*! Find a transaction in connection for given protocol + transaction ID + * \param[in] conn Connection in whihc we want to find transaction + * \param[in] proto Protocol of transaction + * \param[in] trans_id Transaction ID of transaction + * \returns Matching transaction, if any + */ struct gsm_trans *trans_find_by_id(struct gsm_subscriber_connection *conn, uint8_t proto, uint8_t trans_id) { struct gsm_trans *trans; struct gsm_network *net = conn->network; - struct gsm_subscriber *subscr = conn->subscr; + struct vlr_subscr *vsub = conn->vsub; llist_for_each_entry(trans, &net->trans_list, entry) { - if (trans->subscr == subscr && + if (trans->vsub == vsub && trans->protocol == proto && trans->transaction_id == trans_id) return trans; @@ -49,6 +55,11 @@ struct gsm_trans *trans_find_by_id(struct gsm_subscriber_connection *conn, return NULL; } +/*! Find a transaction by call reference + * \param[in] net Network in which we should search + * \param[in] callref Call Reference of transaction + * \returns Matching transaction, if any + */ struct gsm_trans *trans_find_by_callref(struct gsm_network *net, uint32_t callref) { @@ -61,21 +72,27 @@ struct gsm_trans *trans_find_by_callref(struct gsm_network *net, return NULL; } +/*! Allocate a new transaction and add it to network list + * \param[in] net Netwokr in which we allocate transaction + * \param[in] subscr Subscriber for which we allocate transaction + * \param[in] protocol Protocol (CC/SMS/...) + * \param[in] callref Call Reference + * \returns Transaction + */ struct gsm_trans *trans_alloc(struct gsm_network *net, - struct gsm_subscriber *subscr, + struct vlr_subscr *vsub, uint8_t protocol, uint8_t trans_id, uint32_t callref) { struct gsm_trans *trans; - DEBUGP(DCC, "subscr=%p, net=%p\n", subscr, net); + DEBUGP(DCC, "subscr=%p, net=%p\n", vsub, net); trans = talloc_zero(tall_trans_ctx, struct gsm_trans); if (!trans) return NULL; - trans->subscr = subscr; - subscr_get(trans->subscr); + trans->vsub = vlr_subscr_get(vsub); trans->protocol = protocol; trans->transaction_id = trans_id; @@ -87,6 +104,9 @@ struct gsm_trans *trans_alloc(struct gsm_network *net, return trans; } +/*! Release a transaction + * \param[in] trans Transaction to be released + */ void trans_free(struct gsm_trans *trans) { switch (trans->protocol) { @@ -103,23 +123,28 @@ void trans_free(struct gsm_trans *trans) trans->paging_request = NULL; } - if (trans->subscr) { - subscr_put(trans->subscr); - trans->subscr = NULL; + if (trans->vsub) { + vlr_subscr_put(trans->vsub); + trans->vsub = NULL; } llist_del(&trans->entry); if (trans->conn) - msc_release_connection(trans->conn); + msc_subscr_conn_put(trans->conn); trans->conn = NULL; talloc_free(trans); } -/* allocate an unused transaction ID for the given subscriber - * in the given protocol using the ti_flag specified */ -int trans_assign_trans_id(struct gsm_network *net, struct gsm_subscriber *subscr, +/*! allocate an unused transaction ID for the given subscriber + * in the given protocol using the ti_flag specified + * \param[in] net GSM network + * \param[in] subscr Subscriber for which to find ID + * \param[in] protocol Protocol for whihc to find ID + * \param[in] ti_flag FIXME + */ +int trans_assign_trans_id(struct gsm_network *net, struct vlr_subscr *vsub, uint8_t protocol, uint8_t ti_flag) { struct gsm_trans *trans; @@ -131,7 +156,7 @@ int trans_assign_trans_id(struct gsm_network *net, struct gsm_subscriber *subscr /* generate bitmask of already-used TIDs for this (subscr,proto) */ llist_for_each_entry(trans, &net->trans_list, entry) { - if (trans->subscr != subscr || + if (trans->vsub != vsub || trans->protocol != protocol || trans->transaction_id == 0xff) continue; @@ -151,6 +176,10 @@ int trans_assign_trans_id(struct gsm_network *net, struct gsm_subscriber *subscr return -1; } +/*! Check if we have any transaction for given connection + * \param[in] conn Connection to check + * \returns 1 in case there is a transaction, 0 otherwise + */ int trans_has_conn(const struct gsm_subscriber_connection *conn) { struct gsm_trans *trans; @@ -161,3 +190,25 @@ int trans_has_conn(const struct gsm_subscriber_connection *conn) return 0; } + +/*! Free all transactions associated with a connection, presumably when the + * conn is being closed. The transaction code will inform the CC or SMS + * facilities, which will then send the necessary release indications. + * \param[in] conn Connection that is going to be closed. + */ +void trans_conn_closed(struct gsm_subscriber_connection *conn) +{ + struct gsm_trans *trans; + + /* As part of the CC REL_IND the remote leg might be released and this + * will trigger another call to trans_free. This is something the llist + * macro can not handle and we need to re-iterate the list every time. + */ +restart: + llist_for_each_entry(trans, &conn->network->trans_list, entry) { + if (trans->conn == conn) { + trans_free(trans); + goto restart; + } + } +} |