From 45f0fa09d2ae8f4c15a2096e37c05be5d283d027 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Tue, 22 Mar 2016 16:31:26 +0100 Subject: call/app: Hook the MNCC disconnect event in the app and release calls In case the MNCC server is crashing we need to release all calls, use the event emitted by the MNCC connection and iterate over all calls and call the release function. --- src/Makefile.am | 1 + src/app.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/app.h | 3 +++ src/call.c | 26 ++++++++++++++++++++++++++ src/call.h | 10 ++++++++++ src/logging.h | 1 + src/main.c | 6 ++++++ 7 files changed, 104 insertions(+) create mode 100644 src/app.c diff --git a/src/Makefile.am b/src/Makefile.am index 0c04d50..5fb445d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -6,6 +6,7 @@ noinst_HEADERS = \ evpoll.h vty.h mncc_protocol.h app.h mncc.h sip.h call.h osmo_sip_connector_SOURCES = \ + app.c \ call.c \ sip.c \ mncc.c \ diff --git a/src/app.c b/src/app.c new file mode 100644 index 0000000..80bd3af --- /dev/null +++ b/src/app.c @@ -0,0 +1,57 @@ +/* + * (C) 2016 by Holger Hans Peter Freyther + * + * 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 Affero General Public License + * along with this program. If not, see . + * + */ + +#include "app.h" +#include "call.h" +#include "logging.h" +#include "mncc.h" + +void app_mncc_disconnected(struct mncc_connection *conn) +{ + struct call *call, *tmp; + + llist_for_each_entry_safe(call, tmp, &g_call_list, entry) { + int has_mncc = 0; + + if (call->initial && call->initial->type == CALL_TYPE_MNCC) + has_mncc = 1; + if (call->remote && call->remote->type == CALL_TYPE_MNCC) + has_mncc = 1; + + if (!has_mncc) + continue; + + /* + * this call has a MNCC component and we will release it. + */ + LOGP(DAPP, LOGL_NOTICE, + "Going to release call(%u) due MNCC.\n", call->id); + call_leg_release(call, call->initial); + call_leg_release(call, call->remote); + } +} + +/* + * I hook SIP and MNCC together. + */ +void app_setup(struct app_config *cfg) +{ + cfg->mncc.conn.on_disconnect = app_mncc_disconnected; +} diff --git a/src/app.h b/src/app.h index c6305c0..4e5b3fa 100644 --- a/src/app.h +++ b/src/app.h @@ -22,3 +22,6 @@ struct app_config { }; extern struct app_config g_app; + +void app_setup(struct app_config *cfg); +void app_mncc_disconnected(struct mncc_connection *conn); diff --git a/src/call.c b/src/call.c index 464530f..5e0e726 100644 --- a/src/call.c +++ b/src/call.c @@ -19,6 +19,32 @@ */ #include "call.h" +#include "logging.h" + +#include LLIST_HEAD(g_call_list); + +void calls_init(void) +{} + +void call_leg_release(struct call *call, struct call_leg *leg) +{ + if (leg == call->initial) + call->initial = NULL; + else if (leg == call->remote) + call->remote = NULL; + else { + LOGP(DAPP, LOGL_ERROR, "call(%u) with unknown leg(%p/%d)\n", + call->id, leg, leg->type); + return; + } + + talloc_free(leg); + if (!call->initial && !call->remote) { + LOGP(DAPP, LOGL_DEBUG, "call(%u) releasing.\n", call->id); + llist_del(&call->entry); + talloc_free(call); + } +} diff --git a/src/call.h b/src/call.h index 4e8e662..ea2c847 100644 --- a/src/call.h +++ b/src/call.h @@ -15,6 +15,7 @@ struct call_leg; struct call { struct llist_head entry; + unsigned int id; struct call_leg *initial; struct call_leg *remote; }; @@ -27,6 +28,12 @@ enum { struct call_leg { int type; + + /** + * Set by the call_leg implementation and will be called + * by the application to release the call. + */ + void (*release_call)(struct call *, struct call_leg *); }; struct sip_call_leg { @@ -43,3 +50,6 @@ struct mncc_call_leg { extern struct llist_head g_call_list; void calls_init(void); + + +void call_leg_release(struct call *call, struct call_leg *leg); diff --git a/src/logging.h b/src/logging.h index 2ac7906..05ae5c9 100644 --- a/src/logging.h +++ b/src/logging.h @@ -6,4 +6,5 @@ enum { DSIP, DMNCC, DAPP, + DCALL, }; diff --git a/src/main.c b/src/main.c index 3e5e08a..cf045cb 100644 --- a/src/main.c +++ b/src/main.c @@ -64,6 +64,11 @@ static struct log_info_cat mncc_sip_categories[] = { .description = "Application interface", .enabled = 1, .loglevel = LOGL_NOTICE, }, + [DCALL] = { + .name = "DCALL", + .description = "Call management", + .enabled = 1, .loglevel = LOGL_NOTICE, + }, }; static const struct log_info mncc_sip_info = { @@ -149,6 +154,7 @@ int main(int argc, char **argv) } calls_init(); + app_setup(&g_app); /* marry sofia-sip to glib and glib to libosmocore */ loop = g_main_loop_new(NULL, FALSE); -- cgit v1.2.3