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 29, 2023
1 parent cc44939 commit a55bdba
Show file tree
Hide file tree
Showing 11 changed files with 237 additions and 125 deletions.
10 changes: 10 additions & 0 deletions include/re_sipsess.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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);
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
70 changes: 50 additions & 20 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,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) :
Expand All @@ -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;
Expand All @@ -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);
Expand Down
53 changes: 32 additions & 21 deletions src/sipsess/listen.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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);
}

Expand All @@ -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;
Expand All @@ -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);
Expand All @@ -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];
Expand All @@ -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"
Expand All @@ -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,
Expand Down
Loading

0 comments on commit a55bdba

Please sign in to comment.