Skip to content

Commit

Permalink
sipsess: refactor and simplify SDP negotiation state
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
maximilianfridrich committed Nov 23, 2023
1 parent e097b7f commit ff2fef0
Show file tree
Hide file tree
Showing 11 changed files with 173 additions and 84 deletions.
8 changes: 8 additions & 0 deletions include/re_sipsess.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@
struct sipsess_sock;
struct sipsess;

/* SDP Negotiation state */
enum sdp_neg_state {
SDP_NEG_NONE = 0,
SDP_NEG_LOCAL_OFFER, /** SDP offer sent */
SDP_NEG_REMOTE_OFFER, /** SDP offer received */
SDP_NEG_DONE /** 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,
Expand Down
3 changes: 3 additions & 0 deletions src/sipsess/accept.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
41 changes: 28 additions & 13 deletions src/sipsess/connect.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -89,12 +91,13 @@ 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 (sdp && sess->sent_offer) {
sess->awaiting_answer = false;
if (sdp && sess->neg_state == SDP_NEG_LOCAL_OFFER) {
sess->neg_state = SDP_NEG_DONE;
err = sess->answerh(msg, sess->arg);
if (err)
goto out;
Expand All @@ -110,8 +113,8 @@ static void invite_resp_handler(int err, const struct sip_msg *msg, void *arg)

if (sip_msg_hdr_has_value(msg, SIP_HDR_REQUIRE, "100rel")
&& sess->rel100_supported) {
if (sdp && !sess->sent_offer) {
sess->modify_pending = false;
if (sdp && sess->neg_state == SDP_NEG_NONE) {
sess->neg_state = SDP_NEG_REMOTE_OFFER;
err = sess->offerh(&desc, msg, sess->arg);
}

Expand All @@ -135,15 +138,27 @@ 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);
}

if (err)
goto out;
}

err |= sipsess_ack(sess->sock, sess->dlg, msg->cseq.num,
sess->auth, sess->ctype, desc);
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;

sess->established = true;
mem_deref(desc);
Expand Down
11 changes: 6 additions & 5 deletions src/sipsess/listen.c
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ static void ack_handler(struct sipsess_sock *sock, const struct sip_msg *msg)
}

if (awaiting_answer) {
sess->awaiting_answer = false;
sess->neg_state = SDP_NEG_DONE;
err = sess->answerh(msg, sess->arg);
}

Expand Down Expand Up @@ -193,18 +193,18 @@ static void prack_handler(struct sipsess_sock *sock, const struct sip_msg *msg)
}

if (awaiting_prack) {
sess->awaiting_prack = false;
sess->refresh_allowed = true;
--sess->prack_waiting_cnt;
}

if (sess->prackh)
sess->prackh(msg, sess->arg);

if (awaiting_answer) {
sess->awaiting_answer = false;
sess->neg_state = SDP_NEG_DONE;
(void)sess->answerh(msg, sess->arg);
}
else if (msg && mbuf_get_left(msg->mb)) {
sess->neg_state = SDP_NEG_REMOTE_OFFER;
(void)sess->offerh(&desc, msg, sess->arg);
}

Expand Down Expand Up @@ -239,7 +239,8 @@ static void target_refresh_handler(struct sipsess_sock *sock,
return;
}

if ((is_invite && sess->st) || sess->awaiting_answer) {
if ((is_invite && sess->st)
|| sess->neg_state == SDP_NEG_LOCAL_OFFER) {
(void)sip_treplyf(NULL, NULL, sip, msg, false,
500, "Server Internal Error",
"Retry-After: 5\r\n"
Expand Down
76 changes: 49 additions & 27 deletions src/sipsess/modify.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,31 +32,47 @@ 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;
}
else if (msg->scode < 300) {

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

Expand Down Expand Up @@ -126,28 +142,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;
}


Expand All @@ -161,12 +184,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);
Expand Down
9 changes: 2 additions & 7 deletions src/sipsess/prack.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down Expand Up @@ -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,
Expand Down
33 changes: 18 additions & 15 deletions src/sipsess/reply.c
Original file line number Diff line number Diff line change
Expand Up @@ -115,11 +115,12 @@ 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->prack_waiting_cnt > 0)
return EINVAL;

reply = mem_zalloc(sizeof(*reply), destructor);
Expand Down Expand Up @@ -160,14 +161,18 @@ 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 (desc) {
if (sdp) {
sess->neg_state = SDP_NEG_DONE;
} else {
reply->awaiting_answer = true;
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:
Expand Down Expand Up @@ -269,16 +274,14 @@ int sipsess_reply_1xx(struct sipsess *sess, const struct sip_msg *msg,
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;
reply->awaiting_prack = true;
if (reliably) {
++sess->prack_waiting_cnt;
reply->awaiting_prack = true;
if (desc) {
reply->awaiting_answer = !mbuf_get_left(msg->mb);
sess->neg_state = mbuf_get_left(msg->mb) ?
SDP_NEG_DONE : SDP_NEG_LOCAL_OFFER;
}

}

out:
Expand Down
Loading

0 comments on commit ff2fef0

Please sign in to comment.