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);