From 755bdb7379ad39010c3431610fc7c166a97333d7 Mon Sep 17 00:00:00 2001 From: Maximilian Fridrich Date: Thu, 23 Nov 2023 14:46:33 +0100 Subject: [PATCH] sipsess: refactor and simplify SDP negotiation state The SDP negotiation state is now tracked in a single enum which is used as a state machine to keep track of the current state of the SDP negotiation. --- include/re_sipsess.h | 10 ++++++ src/sipsess/accept.c | 3 ++ src/sipsess/connect.c | 70 ++++++++++++++++++++++++++++----------- src/sipsess/listen.c | 53 +++++++++++++++++------------ src/sipsess/modify.c | 77 ++++++++++++++++++++++++++++--------------- src/sipsess/prack.c | 9 ++--- src/sipsess/reply.c | 75 ++++++++++++++++++++++++++--------------- src/sipsess/sess.c | 18 ++++++++-- src/sipsess/sipsess.h | 11 +++---- src/sipsess/update.c | 17 +++++++--- test/sipsess.c | 22 ++++++++----- 11 files changed, 240 insertions(+), 125 deletions(-) diff --git a/include/re_sipsess.h b/include/re_sipsess.h index 87006197b..d80e429b3 100644 --- a/include/re_sipsess.h +++ b/include/re_sipsess.h @@ -7,6 +7,15 @@ struct sipsess_sock; struct sipsess; +/* SDP Negotiation state */ +enum sdp_neg_state { + SDP_NEG_NONE = 0, + SDP_NEG_LOCAL_OFFER = (1 << 0), /** SDP offer sent */ + SDP_NEG_REMOTE_OFFER = (1 << 1), /** SDP offer received */ + SDP_NEG_PREVIEW_ANSWER = (1 << 2), /** SDP preview answer sent */ + SDP_NEG_DONE = (1 << 3) /** SDP negotiation done */ +}; + typedef void (sipsess_conn_h)(const struct sip_msg *msg, void *arg); typedef int (sipsess_desc_h)(struct mbuf **descp, const struct sa *src, @@ -74,3 +83,4 @@ void sipsess_close_all(struct sipsess_sock *sock); struct sip_dialog *sipsess_dialog(const struct sipsess *sess); void sipsess_abort(struct sipsess *sess); bool sipsess_ack_pending(const struct sipsess *sess); +enum sdp_neg_state sipsess_sdp_neg_state(const struct sipsess *sess); diff --git a/src/sipsess/accept.c b/src/sipsess/accept.c index ab50daeff..1f506dc7e 100644 --- a/src/sipsess/accept.c +++ b/src/sipsess/accept.c @@ -99,6 +99,9 @@ int sipsess_accept(struct sipsess **sessp, struct sipsess_sock *sock, if (err) goto out; + if (mbuf_get_left(msg->mb)) + sess->neg_state = SDP_NEG_REMOTE_OFFER; + va_start(ap, fmt); if (scode > 100 && scode < 200) { diff --git a/src/sipsess/connect.c b/src/sipsess/connect.c index 7a67d1e13..feebb7d6f 100644 --- a/src/sipsess/connect.c +++ b/src/sipsess/connect.c @@ -68,7 +68,9 @@ static int send_handler(enum sip_transp tp, struct sa *src, *contp = cont; out: - sess->sent_offer = desc != NULL; + if (desc) + sess->neg_state = SDP_NEG_LOCAL_OFFER; + mem_deref(desc); return err; } @@ -89,20 +91,14 @@ static void invite_resp_handler(int err, const struct sip_msg *msg, void *arg) if (!msg || err || sip_request_loops(&sess->ls, msg->scode)) goto out; + sdp = mbuf_get_left(msg->mb) > 0; + if (msg->scode < 200) { sess->progrh(msg, sess->arg); - sdp = mbuf_get_left(msg->mb) > 0; if (msg->scode == 100) return; - if (sdp && sess->sent_offer) { - sess->awaiting_answer = false; - err = sess->answerh(msg, sess->arg); - if (err) - goto out; - } - if (pl_isset(&msg->to.tag)) { err = sip_dialog_established(sess->dlg) ? sip_dialog_update(sess->dlg, msg) : @@ -111,19 +107,40 @@ static void invite_resp_handler(int err, const struct sip_msg *msg, void *arg) goto out; } + if (sdp && sess->neg_state == SDP_NEG_LOCAL_OFFER) { + err = sess->answerh(msg, sess->arg); + if (err) + goto out; + } + if (sip_msg_hdr_has_value(msg, SIP_HDR_REQUIRE, "100rel") && sess->rel100_supported) { - if (sdp && !sess->sent_offer) { - sess->modify_pending = false; - err = sess->offerh(&desc, msg, sess->arg); + + if (sess->neg_state == SDP_NEG_NONE && !sdp) + goto out; + + if (sdp) { + if (sess->neg_state == SDP_NEG_LOCAL_OFFER) { + sess->neg_state = SDP_NEG_DONE; + } + else if (sess->neg_state == SDP_NEG_NONE) { + sess->neg_state = SDP_NEG_REMOTE_OFFER; + err = sess->offerh(&desc, msg, + sess->arg); + } } err |= sipsess_prack(sess, msg->cseq.num, msg->rel_seq, &msg->cseq.met, desc); - mem_deref(desc); - sess->desc = mem_deref(sess->desc); if (err) goto out; + + if (sess->neg_state == SDP_NEG_REMOTE_OFFER + && mbuf_get_left(desc)) + sess->neg_state = SDP_NEG_DONE; + + mem_deref(desc); + sess->desc = mem_deref(sess->desc); } return; @@ -138,15 +155,28 @@ static void invite_resp_handler(int err, const struct sip_msg *msg, void *arg) if (err) goto out; - if (sess->sent_offer) - err = sess->answerh(msg, sess->arg); - else { - sess->modify_pending = false; - err = sess->offerh(&desc, msg, sess->arg); + if (sdp) { + if (sess->neg_state == SDP_NEG_LOCAL_OFFER) { + sess->neg_state = SDP_NEG_DONE; + err = sess->answerh(msg, sess->arg); + } + else if (sess->neg_state == SDP_NEG_NONE) { + sess->neg_state = SDP_NEG_REMOTE_OFFER; + err = sess->offerh(&desc, msg, sess->arg); + } } err |= sipsess_ack(sess->sock, sess->dlg, msg->cseq.num, - sess->auth, sess->ctype, desc); + sess->auth, sess->ctype, desc); + if (err) + goto out; + + if (sess->neg_state == SDP_NEG_NONE && !sdp) + goto out; + + if (sess->neg_state == SDP_NEG_REMOTE_OFFER + && mbuf_get_left(desc)) + sess->neg_state = SDP_NEG_DONE; sess->established = true; mem_deref(desc); diff --git a/src/sipsess/listen.c b/src/sipsess/listen.c index a47fda866..d81a7dfe2 100644 --- a/src/sipsess/listen.c +++ b/src/sipsess/listen.c @@ -128,14 +128,13 @@ static void bye_handler(struct sipsess_sock *sock, const struct sip_msg *msg) static void ack_handler(struct sipsess_sock *sock, const struct sip_msg *msg) { struct sipsess *sess; - bool awaiting_answer; int err = 0; sess = sipsess_find(sock, msg); if (!sess) return; - if (sipsess_reply_ack(sess, msg, &awaiting_answer)) + if (sipsess_reply_ack(sess, msg)) return; if (sess->terminated) { @@ -146,8 +145,13 @@ static void ack_handler(struct sipsess_sock *sock, const struct sip_msg *msg) return; } - if (awaiting_answer) { - sess->awaiting_answer = false; + if (sess->neg_state == SDP_NEG_LOCAL_OFFER) { + if (!mbuf_get_left(msg->mb)) { + sipsess_terminate(sess, EPROTO, NULL); + return; + } + + sess->neg_state = SDP_NEG_DONE; err = sess->answerh(msg, sess->arg); } @@ -169,15 +173,14 @@ static void ack_handler(struct sipsess_sock *sock, const struct sip_msg *msg) static void prack_handler(struct sipsess_sock *sock, const struct sip_msg *msg) { + bool sdp; struct sipsess *sess; struct mbuf *desc = NULL; - bool awaiting_answer = false; bool awaiting_prack = false; sess = sipsess_find(sock, msg); - if (!sess || sipsess_reply_prack(sess, msg, &awaiting_answer, - &awaiting_prack)) { + if (!sess || sipsess_reply_prack(sess, msg, &awaiting_prack)) { (void)sip_reply(sock->sip, msg, 481, "Transaction Does Not Exist"); return; @@ -192,22 +195,28 @@ static void prack_handler(struct sipsess_sock *sock, const struct sip_msg *msg) return; } - if (awaiting_prack) { - sess->awaiting_prack = false; - sess->refresh_allowed = true; - } + sdp = mbuf_get_left(msg->mb); - if (sess->prackh) - sess->prackh(msg, sess->arg); + if (awaiting_prack) + --sess->prack_waiting_cnt; - if (awaiting_answer) { - sess->awaiting_answer = false; + if (sess->neg_state == SDP_NEG_LOCAL_OFFER) { + if (!sdp) { + sipsess_terminate(sess, EPROTO, NULL); + return; + } + + sess->neg_state = SDP_NEG_DONE; (void)sess->answerh(msg, sess->arg); } - else if (msg && mbuf_get_left(msg->mb)) { + else if (sess->neg_state == SDP_NEG_DONE && sdp) { + sess->neg_state = SDP_NEG_REMOTE_OFFER; (void)sess->offerh(&desc, msg, sess->arg); } + if (sess->prackh) + sess->prackh(msg, sess->arg); + (void)sipsess_reply_2xx(sess, msg, 200, "OK", desc, NULL, NULL); mem_deref(desc); @@ -219,7 +228,7 @@ static void target_refresh_handler(struct sipsess_sock *sock, { struct sip *sip = sock->sip; bool is_invite; - bool got_offer; + bool sdp; struct sipsess *sess; struct mbuf *desc = NULL; char m[256]; @@ -232,14 +241,15 @@ static void target_refresh_handler(struct sipsess_sock *sock, } is_invite = !pl_strcmp(&msg->met, "INVITE"); - got_offer = (mbuf_get_left(msg->mb) > 0); + sdp = (mbuf_get_left(msg->mb) > 0); if (!sip_dialog_rseq_valid(sess->dlg, msg)) { (void)sip_treply(NULL, sip, msg, 500, "Server Internal Error"); return; } - if ((is_invite && sess->st) || sess->awaiting_answer) { + if ((is_invite && sess->st) + || (sdp && sess->neg_state == SDP_NEG_LOCAL_OFFER)) { (void)sip_treplyf(NULL, NULL, sip, msg, false, 500, "Server Internal Error", "Retry-After: 5\r\n" @@ -253,12 +263,13 @@ static void target_refresh_handler(struct sipsess_sock *sock, return; } - if (got_offer && !sipsess_refresh_allowed(sess)) { + if (sdp && !sipsess_refresh_allowed(sess)) { (void)sip_reply(sip, msg, 488, "Not Acceptable Here"); return; } - if (is_invite || got_offer) { + if (sdp) { + sess->neg_state = SDP_NEG_REMOTE_OFFER; err = sess->offerh(&desc, msg, sess->arg); if (err) { (void)sip_reply(sip, msg, 488, diff --git a/src/sipsess/modify.c b/src/sipsess/modify.c index 3f7872be8..6bb0e1fbc 100644 --- a/src/sipsess/modify.c +++ b/src/sipsess/modify.c @@ -32,10 +32,13 @@ static void reinvite_resp_handler(int err, const struct sip_msg *msg, struct sipsess *sess = arg; const struct sip_hdr *hdr; struct mbuf *desc = NULL; + bool sdp; if (!msg || err || sip_request_loops(&sess->ls, msg->scode)) goto out; + sdp = mbuf_get_left(msg->mb) > 0; + if (msg->scode < 200) { return; } @@ -43,20 +46,34 @@ static void reinvite_resp_handler(int err, const struct sip_msg *msg, (void)sip_dialog_update(sess->dlg, msg); - if (sess->sent_offer) { - (void)sess->answerh(msg, sess->arg); - } - else { - sess->modify_pending = false; - (void)sess->offerh(&desc, msg, sess->arg); + if (sdp) { + if (sess->neg_state == SDP_NEG_LOCAL_OFFER) { + sess->neg_state = SDP_NEG_DONE; + err = sess->answerh(msg, sess->arg); + } + else if (sess->neg_state == SDP_NEG_NONE) { + sess->neg_state = SDP_NEG_REMOTE_OFFER; + err = sess->offerh(&desc, msg, sess->arg); + } + + if (err) + goto out; } - (void)sipsess_ack(sess->sock, sess->dlg, msg->cseq.num, + err = sipsess_ack(sess->sock, sess->dlg, msg->cseq.num, sess->auth, sess->ctype, desc); + if (err) + goto out; + + if (sess->neg_state == SDP_NEG_REMOTE_OFFER + && mbuf_get_left(desc)) + sess->neg_state = SDP_NEG_DONE; mem_deref(desc); } else { + sess->neg_state = SDP_NEG_DONE; + if (sess->terminated) goto out; @@ -126,28 +143,35 @@ static int send_handler(enum sip_transp tp, struct sa *src, int sipsess_reinvite(struct sipsess *sess, bool reset_ls) { + int err; + if (sess->req) return EPROTO; - sess->sent_offer = sess->desc ? true : false; - sess->modify_pending = false; - if (reset_ls) sip_loopstate_reset(&sess->ls); - return sip_drequestf(&sess->req, sess->sip, true, "INVITE", - sess->dlg, 0, sess->auth, - send_handler, reinvite_resp_handler, sess, - "%s%s%s" - "Content-Length: %zu\r\n" - "\r\n" - "%b", - sess->desc ? "Content-Type: " : "", - sess->desc ? sess->ctype : "", - sess->desc ? "\r\n" : "", - sess->desc ? mbuf_get_left(sess->desc) :(size_t)0, - sess->desc ? mbuf_buf(sess->desc) : NULL, - sess->desc ? mbuf_get_left(sess->desc):(size_t)0); + err = sip_drequestf(&sess->req, sess->sip, true, "INVITE", + sess->dlg, 0, sess->auth, + send_handler, reinvite_resp_handler, sess, + "%s%s%s" + "Content-Length: %zu\r\n" + "\r\n" + "%b", + sess->desc ? "Content-Type: " : "", + sess->desc ? sess->ctype : "", + sess->desc ? "\r\n" : "", + sess->desc ? mbuf_get_left(sess->desc) :(size_t)0, + sess->desc ? mbuf_buf(sess->desc) : NULL, + sess->desc ? mbuf_get_left(sess->desc):(size_t)0); + + if (!err) { + sess->modify_pending = false; + if (sess->desc) + sess->neg_state = SDP_NEG_LOCAL_OFFER; + } + + return err; } @@ -161,12 +185,11 @@ int sipsess_reinvite(struct sipsess *sess, bool reset_ls) */ int sipsess_modify(struct sipsess *sess, struct mbuf *desc) { - if (!sess || sess->terminated || sess->awaiting_answer - || !sip_dialog_established(sess->dlg)) + if (!sess || sess->terminated || !sip_dialog_established(sess->dlg)) return EINVAL; - if (!sess->established && !sess->refresh_allowed - && mbuf_get_left(desc)) + if (mbuf_get_left(desc) && (sess->neg_state != SDP_NEG_DONE + && sess->neg_state != SDP_NEG_NONE)) return EPROTO; mem_deref(sess->desc); diff --git a/src/sipsess/prack.c b/src/sipsess/prack.c index cb23d6f8f..81a59712e 100644 --- a/src/sipsess/prack.c +++ b/src/sipsess/prack.c @@ -68,9 +68,8 @@ static void prack_resp_handler(int err, const struct sip_msg *msg, void *arg) (void)sip_dialog_update(req->sess->dlg, msg); if (mbuf_get_left(msg->mb)) { - if (req->sess->sent_offer) { - req->sess->awaiting_answer = false; - req->sess->refresh_allowed = true; + if (req->sess->neg_state == SDP_NEG_LOCAL_OFFER) { + req->sess->neg_state = SDP_NEG_DONE; (void)req->sess->answerh(msg, req->sess->arg); } @@ -136,10 +135,6 @@ static int prack_request(struct sipsess_prack *prack) if (err == -1) return err; - if (req->sess->sent_offer && !req->sess->awaiting_answer - && (!req->body || !mbuf_get_left(req->body))) - req->sess->refresh_allowed = true; - return sip_drequestf(&req->req, req->sess->sip, true, "PRACK", req->sess->dlg, 0, req->sess->auth, NULL, prack_resp_handler, prack, diff --git a/src/sipsess/reply.c b/src/sipsess/reply.c index efb89089b..33f63f271 100644 --- a/src/sipsess/reply.c +++ b/src/sipsess/reply.c @@ -26,7 +26,6 @@ struct sipsess_reply { const struct sip_msg *msg; struct mbuf *mb; struct sipsess *sess; - bool awaiting_answer; bool awaiting_prack; uint16_t scode; uint32_t seq; @@ -115,11 +114,18 @@ int sipsess_reply_2xx(struct sipsess *sess, const struct sip_msg *msg, struct sipsess_reply *reply = NULL; struct sip_contact contact; int err = ENOMEM; + bool sdp = mbuf_get_left(msg->mb) > 0; bool non_invite = !pl_strcmp(&msg->met, "PRACK") || !pl_strcmp(&msg->met, "UPDATE"); if (!non_invite) { - if (sess->awaiting_prack) + if (sess->neg_state == SDP_NEG_NONE && !mbuf_get_left(desc)) + return EINVAL; + else if (sess->neg_state == SDP_NEG_DONE + && mbuf_get_left(desc)) + desc = NULL; + + if (sess->prack_waiting_cnt > 0) return EINVAL; reply = mem_zalloc(sizeof(*reply), destructor); @@ -134,6 +140,10 @@ int sipsess_reply_2xx(struct sipsess *sess, const struct sip_msg *msg, reply->sess = sess; } + if (non_invite && sess->neg_state != SDP_NEG_REMOTE_OFFER + && mbuf_get_left(desc)) + desc = NULL; + sip_contact_set(&contact, sess->cuser, &msg->dst, msg->tp); err = sip_treplyf(non_invite ? NULL : &sess->st, reply ? &reply->mb : NULL, sess->sip, @@ -160,14 +170,16 @@ int sipsess_reply_2xx(struct sipsess *sess, const struct sip_msg *msg, (void)list_ledata(list_apply(&sess->replyl, false, cancel_1xx_timers, NULL)); + if (mbuf_get_left(desc)) { + if (sdp) + sess->neg_state = SDP_NEG_DONE; + else if (!non_invite) + sess->neg_state = SDP_NEG_LOCAL_OFFER; + } + if (reply) { tmr_start(&reply->tmr, 64 * SIP_T1, tmr_handler, reply); tmr_start(&reply->tmrg, SIP_T1, retransmit_handler, reply); - - if (!mbuf_get_left(msg->mb) && desc) { - reply->awaiting_answer = true; - sess->awaiting_answer = true; - } } out: @@ -205,16 +217,33 @@ int sipsess_reply_1xx(struct sipsess *sess, const struct sip_msg *msg, 421, "Extension required", "Require: 100rel\r\n" "Content-Length: 0\r\n\r\n"); - return -1; + return EPROTO; } else if (rel100_peer == REL100_REQUIRED && !rel100) { (void)sip_treplyf(&sess->st, NULL, sess->sip, msg, false, 420, "Bad Extension", "Unsupported: 100rel\r\n" "Content-Length: 0\r\n\r\n"); - return -1; + return EPROTO; } reliably = rel100 && rel100_peer && scode != 100; + + if (reliably && sess->neg_state == SDP_NEG_NONE + && !mbuf_get_left(desc)) + return EINVAL; + + if (sess->neg_state == SDP_NEG_NONE) { + if (reliably && !mbuf_get_left(desc)) + return EINVAL; + else if (!reliably && mbuf_get_left(desc)) + desc = NULL; + } + else if ((sess->neg_state == SDP_NEG_DONE + || sess->neg_state == SDP_NEG_LOCAL_OFFER) + && mbuf_get_left(desc)) { + desc = NULL; + } + if (rel100 != REL100_REQUIRED && reliably) { pl_set_str(&require_header, "Require: 100rel\r\n"); } @@ -264,21 +293,19 @@ int sipsess_reply_1xx(struct sipsess *sess, const struct sip_msg *msg, if (reliably) { tmr_start(&reply->tmr, 64 * SIP_T1, tmr_handler, reply); tmr_start(&reply->tmrg, SIP_T1, retransmit_handler, reply); - } - else { - mem_deref(reply); - } - if (desc) { - if (!mbuf_get_left(msg->mb)) { - reply->awaiting_answer = true; - sess->awaiting_answer = true; - } - if (reliably) { - sess->awaiting_prack = true; + if (desc) { + ++sess->prack_waiting_cnt; reply->awaiting_prack = true; + sess->neg_state = mbuf_get_left(msg->mb) ? + SDP_NEG_DONE : SDP_NEG_LOCAL_OFFER; } + } + else { + if (desc && sess->neg_state == SDP_NEG_REMOTE_OFFER) + sess->neg_state = SDP_NEG_PREVIEW_ANSWER; + mem_deref(reply); } out: @@ -312,7 +339,7 @@ static bool cmp_handler(struct le *le, void *arg) int sipsess_reply_prack(struct sipsess *sess, const struct sip_msg *msg, - bool *awaiting_answer, bool *awaiting_prack) + bool *awaiting_prack) { struct sipsess_reply *reply; @@ -321,7 +348,6 @@ int sipsess_reply_prack(struct sipsess *sess, const struct sip_msg *msg, if (!reply) return ENOENT; - *awaiting_answer = reply->awaiting_answer; *awaiting_prack = reply->awaiting_prack; mem_deref(reply); @@ -330,8 +356,7 @@ int sipsess_reply_prack(struct sipsess *sess, const struct sip_msg *msg, } -int sipsess_reply_ack(struct sipsess *sess, const struct sip_msg *msg, - bool *awaiting_answer) +int sipsess_reply_ack(struct sipsess *sess, const struct sip_msg *msg) { struct sipsess_reply *reply; @@ -340,8 +365,6 @@ int sipsess_reply_ack(struct sipsess *sess, const struct sip_msg *msg, if (!reply) return ENOENT; - *awaiting_answer = reply->awaiting_answer; - mem_deref(reply); return 0; diff --git a/src/sipsess/sess.c b/src/sipsess/sess.c index bb62db33c..f394ec92c 100644 --- a/src/sipsess/sess.c +++ b/src/sipsess/sess.c @@ -333,7 +333,7 @@ void sipsess_abort(struct sipsess *sess) */ bool sipsess_awaiting_prack(const struct sipsess *sess) { - return sess ? sess->awaiting_prack : false; + return sess ? sess->prack_waiting_cnt > 0 : false; } @@ -349,8 +349,7 @@ bool sipsess_refresh_allowed(const struct sipsess *sess) if (!sess) return false; - return ((sess->established || sess->refresh_allowed) - && !sess->terminated && !sess->awaiting_answer); + return !sess->terminated && sess->neg_state == SDP_NEG_DONE; } @@ -366,3 +365,16 @@ bool sipsess_ack_pending(const struct sipsess *sess) { return sess && sess->replyl.head ? true : false; } + + +/** + * Get the SDP negotiation state of a SIP Session + * + * @param sess SIP Session + * + * @return SDP negotiation state + */ +enum sdp_neg_state sipsess_sdp_neg_state(const struct sipsess *sess) +{ + return sess ? sess->neg_state : SDP_NEG_NONE; +} diff --git a/src/sipsess/sipsess.h b/src/sipsess/sipsess.h index 884d03705..591bf0329 100644 --- a/src/sipsess/sipsess.h +++ b/src/sipsess/sipsess.h @@ -36,15 +36,13 @@ struct sipsess { void *arg; uint32_t rel_seq; bool owner; - bool sent_offer; - bool awaiting_answer; bool modify_pending; bool established; bool peerterm; bool rel100_supported; - bool awaiting_prack; - bool refresh_allowed; + int prack_waiting_cnt; int terminated; + enum sdp_neg_state neg_state; }; @@ -95,10 +93,9 @@ int sipsess_reply_1xx(struct sipsess *sess, const struct sip_msg *msg, uint16_t scode, const char *reason, enum rel100_mode rel100, struct mbuf *desc, const char *fmt, va_list *ap); -int sipsess_reply_ack(struct sipsess *sess, const struct sip_msg *msg, - bool *awaiting_answer); +int sipsess_reply_ack(struct sipsess *sess, const struct sip_msg *msg); int sipsess_reply_prack(struct sipsess *sess, const struct sip_msg *msg, - bool *awaiting_answer, bool *awaiting_prack); + bool *awaiting_prack); int sipsess_reinvite(struct sipsess *sess, bool reset_ls); int sipsess_update(struct sipsess *sess); int sipsess_bye(struct sipsess *sess, bool reset_ls); diff --git a/src/sipsess/update.c b/src/sipsess/update.c index fbbf25eea..1e982f858 100644 --- a/src/sipsess/update.c +++ b/src/sipsess/update.c @@ -46,15 +46,17 @@ static void update_resp_handler(int err, const struct sip_msg *msg, void *arg) else if (msg->scode < 300) { (void)sip_dialog_update(req->sess->dlg, msg); - if (req->sess->sent_offer) { + if (req->sess->neg_state == SDP_NEG_LOCAL_OFFER) { (void)req->sess->answerh(msg, req->sess->arg); - req->sess->awaiting_answer = false; + req->sess->neg_state = SDP_NEG_DONE; } } else { if (req->sess->terminated) goto out; + req->sess->neg_state = SDP_NEG_DONE; + switch (msg->scode) { case 401: @@ -120,10 +122,12 @@ static int send_handler(enum sip_transp tp, struct sa *src, static int update_request(struct sipsess_request *req) { + int err; + if (!req || req->tmr.th) return -1; - return sip_drequestf(&req->req, req->sess->sip, true, "UPDATE", + err = sip_drequestf(&req->req, req->sess->sip, true, "UPDATE", req->sess->dlg, 0, req->sess->auth, send_handler, update_resp_handler, req, "%s%s%s" @@ -136,6 +140,11 @@ static int update_request(struct sipsess_request *req) req->body ? mbuf_get_left(req->body) :(size_t)0, req->body ? mbuf_buf(req->body) : NULL, req->body ? mbuf_get_left(req->body):(size_t)0); + + if (!err && req->sess->desc) + req->sess->neg_state = SDP_NEG_LOCAL_OFFER; + + return err; } @@ -165,8 +174,6 @@ int sipsess_update(struct sipsess *sess) return err; } - sess->sent_offer = sess->desc ? true : false; - sess->awaiting_answer = sess->sent_offer; sess->modify_pending = false; return err; diff --git a/test/sipsess.c b/test/sipsess.c index c0051fb0b..fdd2dd068 100644 --- a/test/sipsess.c +++ b/test/sipsess.c @@ -16,7 +16,7 @@ typedef void (prack_func)(void *arg); -enum sdp_neg_state { +enum neg_state { INITIAL = 0, OFFER_RECEIVED, ANSWER_RECEIVED, @@ -56,7 +56,7 @@ struct test { bool offer_b; enum rel100_mode rel100_a; enum rel100_mode rel100_b; - enum sdp_neg_state sdp_state; + enum neg_state sdp_state; enum rel100_state rel100_state_a; enum rel100_state rel100_state_b; enum connect_action conn_action; @@ -454,7 +454,7 @@ static void conn_handler(const struct sip_msg *msg, void *arg) else if (test->conn_action & CONN_ANSWER) { err = sipsess_accept(&test->b, test->sock, msg, 200, "OK", test->rel100_b, "b", "application/sdp", - NULL, NULL, NULL, false, offer_handler_b, + desc, NULL, NULL, false, offer_handler_b, answer_handler_b, estab_handler_b, NULL, NULL, close_handler, test, hdrs); if (err != test->answ_ret_code) { @@ -556,7 +556,7 @@ int test_sipsess(void) err = sipsess_connect(&test.a, test.sock, to_uri, NULL, "sip:a@127.0.0.1", "a", NULL, 0, "application/sdp", NULL, NULL, false, - callid, desc_handler, + callid, desc_handler_a, offer_handler_a, answer_handler_a, NULL, estab_handler_a, NULL, NULL, close_handler, &test, NULL); @@ -578,7 +578,9 @@ int test_sipsess(void) ASSERT_TRUE(test.estab_b); ASSERT_TRUE(test.desc); ASSERT_TRUE(test.answr_a); - ASSERT_TRUE(!test.offer_b); + ASSERT_TRUE(test.offer_b); + ASSERT_TRUE(!test.offer_a); + ASSERT_TRUE(!test.answr_b); out: test.a = mem_deref(test.a); @@ -715,7 +717,7 @@ int test_sipsess_blind_transfer(void) err = sipsess_connect(&test.a, test.sock, to_uri, NULL, "sip:a@127.0.0.1", "a", NULL, 0, "application/sdp", NULL, NULL, false, - callid, desc_handler, + callid, desc_handler_a, offer_handler_a, answer_handler_a, NULL, estab_handler_a, NULL, NULL, close_handler, &test, NULL); @@ -738,7 +740,9 @@ int test_sipsess_blind_transfer(void) ASSERT_TRUE(test.estab_b); ASSERT_TRUE(test.desc); ASSERT_TRUE(test.answr_a); - ASSERT_TRUE(!test.offer_b); + ASSERT_TRUE(test.offer_b); + ASSERT_TRUE(!test.offer_a); + ASSERT_TRUE(!test.answr_b); out: test.a = mem_deref(test.a); @@ -1054,7 +1058,7 @@ int test_sipsess_100rel_420(void) err = re_main_timeout(200); TEST_ERR(err); - ASSERT_TRUE(test.err == EINVAL); + ASSERT_TRUE(test.err == EPROTO); /* okay here -- verify */ ASSERT_TRUE(!test.b); @@ -1127,7 +1131,7 @@ int test_sipsess_100rel_421(void) err = re_main_timeout(200); TEST_ERR(err); - ASSERT_TRUE(test.err == EINVAL); + ASSERT_TRUE(test.err == EPROTO); /* okay here -- verify */ ASSERT_TRUE(!test.b);