Skip to content

Commit

Permalink
sipsess: fix PRACK offer/answer behavior (#430)
Browse files Browse the repository at this point in the history
* sipsess: fix PRACK offer/answer behavior

According to RFC 3262, PRACKs and reliable 1xx responses can contain
both SDP answers and offers. E.g. if a reliable 1xx response contains an
offer, the PRACK MUST contain an answer.

* sipsess: handle stateless reply_2xx correctly

Co-authored-by: Christian Spielberger <c.spielberger@commend.com>
  • Loading branch information
maximilianfridrich and cspiel1 authored Jul 12, 2022
1 parent 4dfae41 commit 26ce397
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 49 deletions.
16 changes: 15 additions & 1 deletion src/sipsess/connect.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,21 @@ 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) {

err = sip_dialog_established(sess->dlg) ?
if (msg && mbuf_get_left(msg->mb)) {
if (sess->sent_offer) {
sess->awaiting_answer = false;
err = sess->answerh(msg, sess->arg);
if (err)
goto out;
}
else {
sess->modify_pending = false;
err = sess->offerh(&desc, msg,
sess->arg);
}
}

err |= sip_dialog_established(sess->dlg) ?
sip_dialog_update(sess->dlg, msg) :
sip_dialog_create(sess->dlg, msg);
err |= sipsess_prack(sess, msg->cseq.num, msg->rel_seq,
Expand Down
16 changes: 10 additions & 6 deletions src/sipsess/listen.c
Original file line number Diff line number Diff line change
Expand Up @@ -190,12 +190,12 @@ 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)
{
struct sipsess *sess;
bool awaiting_answer;
int err = 0;
struct mbuf *desc = NULL;
bool awaiting_answer = false;

sess = sipsess_find(sock, msg);

if (!sess || sipsess_reply_prack(sess, msg, &awaiting_answer)) {
if (!sess || sipsess_reply_ack(sess, msg, &awaiting_answer)) {
(void)sip_reply(sock->sip, msg, 481,
"Transaction Does Not Exist");
return;
Expand All @@ -212,11 +212,15 @@ static void prack_handler(struct sipsess_sock *sock, const struct sip_msg *msg)

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

if (err)
sipsess_terminate(sess, err, NULL);
(void)sipsess_reply_2xx(sess, msg, 200, "OK", desc, NULL, NULL);

mem_deref(desc);
}


Expand Down
60 changes: 20 additions & 40 deletions src/sipsess/reply.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,25 +87,28 @@ int sipsess_reply_2xx(struct sipsess *sess, const struct sip_msg *msg,
uint16_t scode, const char *reason, struct mbuf *desc,
const char *fmt, va_list *ap)
{
struct sipsess_reply *reply;
struct sipsess_reply *reply = NULL;
struct sip_contact contact;
bool is_prack = false;
int err = ENOMEM;
bool is_prack = !pl_strcmp(&msg->met, "PRACK");

reply = mem_zalloc(sizeof(*reply), destructor);
if (!reply)
goto out;
if (!is_prack) {
reply = mem_zalloc(sizeof(*reply), destructor);
if (!reply)
goto out;

list_append(&sess->replyl, &reply->le, reply);
reply->rel_seq = 0;
reply->seq = msg->cseq.num;
reply->msg = mem_ref((void *)msg);
reply->sess = sess;
list_append(&sess->replyl, &reply->le, reply);

reply->rel_seq = 0;
reply->seq = msg->cseq.num;
reply->msg = mem_ref((void *)msg);
reply->sess = sess;
}

is_prack = !pl_strcmp(&msg->met, "PRACK");
sip_contact_set(&contact, sess->cuser, &msg->dst, msg->tp);

err = sip_treplyf(is_prack ? NULL : &sess->st, &reply->mb, sess->sip,
err = sip_treplyf(is_prack ? NULL : &sess->st,
reply ? &reply->mb : NULL, sess->sip,
msg, true, scode, reason,
"%H"
"%v"
Expand All @@ -125,17 +128,14 @@ int sipsess_reply_2xx(struct sipsess *sess, const struct sip_msg *msg,
if (err)
goto out;

if (!is_prack) {
if (reply) {
tmr_start(&reply->tmr, 64 * SIP_T1, tmr_handler, reply);
tmr_start(&reply->tmrg, SIP_T1, retransmit_handler, reply);
}
else {
mem_deref(reply);
}

if (!mbuf_get_left(msg->mb) && desc) {
reply->awaiting_answer = true;
sess->awaiting_answer = true;
if (!mbuf_get_left(msg->mb) && desc) {
reply->awaiting_answer = true;
sess->awaiting_answer = true;
}
}

out:
Expand Down Expand Up @@ -283,23 +283,3 @@ int sipsess_reply_ack(struct sipsess *sess, const struct sip_msg *msg,

return 0;
}


int sipsess_reply_prack(struct sipsess *sess, const struct sip_msg *msg,
bool *awaiting_answer)
{
struct sipsess_reply *reply;
int err;

reply = list_ledata(list_apply(&sess->replyl, false, cmp_handler,
(void *)msg));
if (!reply)
return ENOENT;

*awaiting_answer = reply->awaiting_answer;
err = sipsess_reply_2xx(sess, msg, 200, "OK", NULL, NULL, NULL);

mem_deref(reply);

return err;
}
2 changes: 0 additions & 2 deletions src/sipsess/sipsess.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,6 @@ int sipsess_reply_1xx(struct sipsess *sess, const struct sip_msg *msg,
const char *fmt, va_list *ap);
int sipsess_reply_ack(struct sipsess *sess, const struct sip_msg *msg,
bool *awaiting_answer);
int sipsess_reply_prack(struct sipsess *sess, const struct sip_msg *msg,
bool *awaiting_answer);
int sipsess_reinvite(struct sipsess *sess, bool reset_ls);
int sipsess_bye(struct sipsess *sess, bool reset_ls);
int sipsess_request_alloc(struct sipsess_request **reqp, struct sipsess *sess,
Expand Down

0 comments on commit 26ce397

Please sign in to comment.