diff --git a/include/re_sip.h b/include/re_sip.h index d638ea9..c7db95e 100644 --- a/include/re_sip.h +++ b/include/re_sip.h @@ -306,6 +306,7 @@ int sip_dialog_fork(struct sip_dialog **dlgp, struct sip_dialog *odlg, int sip_dialog_update(struct sip_dialog *dlg, const struct sip_msg *msg); bool sip_dialog_rseq_valid(struct sip_dialog *dlg, const struct sip_msg *msg); const char *sip_dialog_callid(const struct sip_dialog *dlg); +uint32_t sip_dialog_lseq(const struct sip_dialog *dlg); bool sip_dialog_established(const struct sip_dialog *dlg); bool sip_dialog_cmp(const struct sip_dialog *dlg, const struct sip_msg *msg); bool sip_dialog_cmp_half(const struct sip_dialog *dlg, diff --git a/src/sip/dialog.c b/src/sip/dialog.c index 45869a5..1516a8a 100644 --- a/src/sip/dialog.c +++ b/src/sip/dialog.c @@ -511,6 +511,12 @@ const char *sip_dialog_callid(const struct sip_dialog *dlg) } +uint32_t sip_dialog_lseq(const struct sip_dialog *dlg) +{ + return dlg ? dlg->lseq : 0; +} + + bool sip_dialog_established(const struct sip_dialog *dlg) { return dlg && dlg->rtag; diff --git a/src/sipevent/listen.c b/src/sipevent/listen.c index 02254a5..0efae54 100644 --- a/src/sipevent/listen.c +++ b/src/sipevent/listen.c @@ -37,7 +37,8 @@ static void destructor(void *arg) static bool event_cmp(const struct sipevent_event *evt, - const char *event, const char *id) + const char *event, const char *id, + int32_t refer_cseq) { if (pl_strcmp(&evt->event, event)) return false; @@ -45,9 +46,16 @@ static bool event_cmp(const struct sipevent_event *evt, if (!pl_isset(&evt->id) && !id) return true; - if (!pl_isset(&evt->id) || !id) + if (!pl_isset(&evt->id)) return false; + if (!id) { + if (refer_cseq >= 0 && (int32_t)pl_u32(&evt->id) == refer_cseq) + return true; + + return false; + } + if (pl_strcmp(&evt->id, id)) return false; @@ -70,7 +78,8 @@ static bool sub_cmp_handler(struct le *le, void *arg) struct sipsub *sub = le->data; return sip_dialog_cmp(sub->dlg, cmp->msg) && - (!cmp->evt || event_cmp(cmp->evt, sub->event, sub->id)); + (!cmp->evt || event_cmp(cmp->evt, sub->event, sub->id, + sub->refer_cseq)); } @@ -81,7 +90,8 @@ static bool sub_cmp_half_handler(struct le *le, void *arg) return sip_dialog_cmp_half(sub->dlg, cmp->msg) && !sip_dialog_established(sub->dlg) && - (!cmp->evt || event_cmp(cmp->evt, sub->event, sub->id)); + (!cmp->evt || event_cmp(cmp->evt, sub->event, sub->id, + sub->refer_cseq)); } @@ -175,6 +185,15 @@ static void notify_handler(struct sipevent_sock *sock, (void)sip_dialog_update(sub->dlg, msg); } + if (sub->refer_cseq >= 0 && !sub->id && pl_isset(&event.id)) { + + err = pl_strdup(&sub->id, &event.id); + if (err) { + (void)sip_treply(NULL, sip, msg, 500, strerror(err)); + return; + } + } + re_printf("notify: %s (%r)\n", sipevent_substate_name(state.state), &state.params); diff --git a/src/sipevent/sipevent.h b/src/sipevent/sipevent.h index 1f581ca..e171d4b 100644 --- a/src/sipevent/sipevent.h +++ b/src/sipevent/sipevent.h @@ -46,6 +46,7 @@ struct sipsub { sipevent_notify_h *notifyh; sipevent_close_h *closeh; void *arg; + int32_t refer_cseq; uint32_t expires; uint32_t failc; bool subscribed; diff --git a/src/sipevent/subscribe.c b/src/sipevent/subscribe.c index 7ee472c..1ac12d3 100644 --- a/src/sipevent/subscribe.c +++ b/src/sipevent/subscribe.c @@ -306,6 +306,8 @@ static int request(struct sipsub *sub, bool reset_ls) if (sub->refer) { + sub->refer_cseq = sip_dialog_lseq(sub->dlg); + return sip_drequestf(&sub->req, sub->sip, true, "REFER", sub->dlg, 0, sub->auth, send_handler, response_handler, sub, @@ -396,6 +398,7 @@ static int sipsub_alloc(struct sipsub **subp, struct sipevent_sock *sock, goto out; } + sub->refer_cseq = -1; sub->refer = refer; sub->sock = mem_ref(sock); sub->sip = mem_ref(sock->sip);