From f4577f5cd58f66576f366272b2a921c8ebdec0bf Mon Sep 17 00:00:00 2001 From: Christian Spielberger Date: Fri, 13 Dec 2024 08:42:26 +0100 Subject: [PATCH] ua prevent double call accept (#3236) * ua,call: prevent double ua_accept API function ua_accept() can be called by multiple modules which handle the shortly added UA_EVENT_SIPSESS_CONN. This commit prevents that multiple call/sipsess/sip_dialog objects are created for a single SIP INVITE message * menu,test: bevent_stop after ua_accept After accepting a call the bevent should not be handled by following event handlers * call,ua: add checks and change warning * call: use sip_msg getter to compare --- include/baresip.h | 2 ++ modules/menu/menu.c | 1 + src/call.c | 9 +++++++++ src/ua.c | 21 +++++++++++++++++++++ test/call.c | 2 ++ 5 files changed, 35 insertions(+) diff --git a/include/baresip.h b/include/baresip.h index 8c2dc94f6..474e16d70 100644 --- a/include/baresip.h +++ b/include/baresip.h @@ -236,6 +236,7 @@ bool call_has_video(const struct call *call); bool call_early_video_available(const struct call *call); bool call_refresh_allowed(const struct call *call); bool call_ack_pending(const struct call *call); +bool call_sess_cmp(const struct call *call, const struct sip_msg *msg); int call_transfer(struct call *call, const char *uri); int call_replace_transfer(struct call *target_call, struct call *source_call); int call_status(struct re_printf *pf, const struct call *call); @@ -963,6 +964,7 @@ int ua_call_alloc(struct call **callp, struct ua *ua, struct call *xcall, const char *local_uri, bool use_rtp); struct call *ua_find_call_state(const struct ua *ua, enum call_state st); +struct call *ua_find_call_msg(struct ua *ua, const struct sip_msg *msg); int ua_raise(struct ua *ua); int ua_set_autoanswer_value(struct ua *ua, const char *value); void ua_add_extension(struct ua *ua, const char *extension); diff --git a/modules/menu/menu.c b/modules/menu/menu.c index 3e35bf337..29ba991a6 100644 --- a/modules/menu/menu.c +++ b/modules/menu/menu.c @@ -710,6 +710,7 @@ static void event_handler(enum ua_event ev, struct bevent *event, void *arg) return; } + bevent_stop(event); break; case UA_EVENT_CALL_INCOMING: diff --git a/src/call.c b/src/call.c index 0ddf2574b..ff7139f87 100644 --- a/src/call.c +++ b/src/call.c @@ -2294,6 +2294,15 @@ int call_accept(struct call *call, struct sipsess_sock *sess_sock, } +bool call_sess_cmp(const struct call *call, const struct sip_msg *msg) +{ + if (!call || !msg) + return false; + + return sipsess_msg(call->sess) == msg; +} + + static void delayed_answer_handler(void *arg) { struct call *call = arg; diff --git a/src/ua.c b/src/ua.c index cd2b8e39a..84a432b32 100644 --- a/src/ua.c +++ b/src/ua.c @@ -504,6 +504,22 @@ struct call *ua_find_active_call(struct ua *ua) } +struct call *ua_find_call_msg(struct ua *ua, const struct sip_msg *msg) +{ + if (!ua || !msg) + return NULL; + + struct le *le = NULL; + for (le = list_tail(&ua->calls); le; le = le->prev) { + struct call *call = le->data; + if (call_sess_cmp(call, msg)) + break; + } + + return le ? le->data : NULL; +} + + static void call_event_handler(struct call *call, enum call_event ev, const char *str, void *arg) { @@ -786,6 +802,11 @@ int ua_accept(struct ua *ua, const struct sip_msg *msg) if (!ua || !msg) return EINVAL; + if (ua_find_call_msg(ua, msg)) { + warning("ua: call was already created\n"); + return EINVAL; + } + err = pl_strdup(&to_uri, &msg->to.auri); if (err) goto error; diff --git a/test/call.c b/test/call.c index 38fb98d50..f2e7e4907 100644 --- a/test/call.c +++ b/test/call.c @@ -659,6 +659,8 @@ static void event_handler(enum ua_event ev, struct bevent *event, void *arg) err); return; } + + bevent_stop(event); } if (ua == f->a.ua)