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.
This commit is contained in:
Holger Hans Peter Freyther 2016-03-22 16:31:26 +01:00
parent 10e22bd6f4
commit 45f0fa09d2
7 changed files with 104 additions and 0 deletions

View File

@ -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 \

57
src/app.c Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
*
*/
#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;
}

View File

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

View File

@ -19,6 +19,32 @@
*/
#include "call.h"
#include "logging.h"
#include <talloc.h>
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);
}
}

View File

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

View File

@ -6,4 +6,5 @@ enum {
DSIP,
DMNCC,
DAPP,
DCALL,
};

View File

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