Skip to content

Commit

Permalink
sip: add RFC 331 support
Browse files Browse the repository at this point in the history
  • Loading branch information
maximilianfridrich committed Jul 7, 2022
1 parent 3f725d5 commit 15c261f
Show file tree
Hide file tree
Showing 5 changed files with 165 additions and 6 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ legend:
* [RFC 2915](https://tools.ietf.org/html/rfc2915) - The Naming Authority Pointer (NAPTR) DNS Resource Record
* [RFC 3261](https://tools.ietf.org/html/rfc3261) - SIP: Session Initiation Protocol
* [RFC 3262](https://tools.ietf.org/html/rfc3262) - SIP Reliability of Provisional Responses
* [RFC 3311](https://tools.ietf.org/html/rfc3311) - The SIP UPDATE Method
* [RFC 3263](https://tools.ietf.org/html/rfc3263) - Locating SIP Servers
* [RFC 3264](https://tools.ietf.org/html/rfc3264) - An Offer/Answer Model with SDP
* [RFC 3265](https://tools.ietf.org/html/rfc3265) - SIP-Specific Event Notification
Expand Down
52 changes: 52 additions & 0 deletions src/sipsess/listen.c
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,54 @@ static void reinvite_handler(struct sipsess_sock *sock,
}


static void update_handler(struct sipsess_sock *sock, const struct sip_msg *msg)
{
struct sip *sip = sock->sip;
struct sipsess *sess;
struct mbuf *desc;
char m[256];
int err;

sess = sipsess_find(sock, msg);
if (!sess || sess->terminated) {
(void)sip_treply(NULL, sip, msg, 481, "Call Does Not Exist");
return;
}

if (!sip_dialog_rseq_valid(sess->dlg, msg)) {
(void)sip_treply(NULL, sip, msg, 500, "Server Internal Error");
return;
}

if (sess->st || sess->awaiting_answer) {
(void)sip_treplyf(NULL, NULL, sip, msg, false,
500, "Server Internal Error",
"Retry-After: 5\r\n"
"Content-Length: 0\r\n"
"\r\n");
return;
}

err = sess->offerh(&desc, msg, sess->arg);
if (err) {
(void)sip_reply(sip, msg, 488, str_error(err, m, sizeof(m)));
return;
}

sess->received_update = true;

(void)sip_dialog_update(sess->dlg, msg);
(void)sipsess_reply_2xx(sess, msg, 200, "OK", desc, NULL, NULL);

/* pending modifications considered outdated;
* sdp may have changed in above exchange */
sess->desc = mem_deref(sess->desc);
sess->modify_pending = false;
tmr_cancel(&sess->tmr);
mem_deref(desc);
}


static void invite_handler(struct sipsess_sock *sock,
const struct sip_msg *msg)
{
Expand All @@ -293,6 +341,10 @@ static bool request_handler(const struct sip_msg *msg, void *arg)

return true;
}
else if (!pl_strcmp(&msg->met, "UPDATE")) {
update_handler(sock, msg);
return true;
}
else if (!pl_strcmp(&msg->met, "ACK")) {
ack_handler(sock, msg);
return true;
Expand Down
110 changes: 107 additions & 3 deletions src/sipsess/modify.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,82 @@ static void reinvite_resp_handler(int err, const struct sip_msg *msg,
}


static void update_resp_handler(int err, const struct sip_msg *msg, void *arg)
{
struct sipsess *sess = arg;
const struct sip_hdr *hdr;
struct mbuf *desc = NULL;

if (err || sip_request_loops(&sess->ls, msg->scode))
goto out;

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);
}

mem_deref(desc);
}
else {
if (sess->terminated)
goto out;

switch (msg->scode) {

case 401:
case 407:
err = sip_auth_authenticate(sess->auth, msg);
if (err) {
err = (err == EAUTH) ? 0 : err;
break;
}

err = sipsess_update(sess, false);
if (err)
break;

return;

case 408:
case 481:
sipsess_terminate(sess, 0, msg);
return;

case 491:
tmr_start(&sess->tmr, sess->owner ? 3000 : 1000,
tmr_handler, sess);
return;

case 500:
hdr = sip_msg_hdr(msg, SIP_HDR_RETRY_AFTER);
if (!hdr)
break;

tmr_start(&sess->tmr, pl_u32(&hdr->val) * 1000,
tmr_handler, sess);
return;
}
}
out:
if (sess->terminated)
mem_deref(sess);
else if (err == ETIMEDOUT)
sipsess_terminate(sess, err, NULL);
else if (sess->modify_pending)
(void)sipsess_update(sess, true);
else
sess->desc = mem_deref(sess->desc);
}


static int send_handler(enum sip_transp tp, struct sa *src,
const struct sa *dst, struct mbuf *mb,
struct mbuf **contp, void *arg)
Expand Down Expand Up @@ -148,6 +224,30 @@ int sipsess_reinvite(struct sipsess *sess, bool reset_ls)
}


int sipsess_update(struct sipsess *sess, bool reset_ls)
{
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, "UPDATE",
sess->dlg, 0, sess->auth,
send_handler, update_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);
}


/**
* Modify an established SIP Session sending Re-INVITE or UPDATE
*
Expand All @@ -158,16 +258,20 @@ int sipsess_reinvite(struct sipsess *sess, bool reset_ls)
*/
int sipsess_modify(struct sipsess *sess, struct mbuf *desc)
{
if (!sess || sess->st || sess->terminated)
if (!sess || (sess->st && sess->established) || sess->terminated)
return EINVAL;

mem_deref(sess->desc);
sess->desc = mem_ref(desc);

if (sess->req || sess->tmr.th || sess->replyl.head) {
if (sess->tmr.th || sess->replyl.head ||
(sess->req && sess->established)) {
sess->modify_pending = true;
return 0;
}

return sipsess_reinvite(sess, true);
if (sess->established)
return sipsess_reinvite(sess, true);
else
return sipsess_update(sess, true);
}
6 changes: 3 additions & 3 deletions src/sipsess/reply.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,8 @@ int sipsess_reply_2xx(struct sipsess *sess, const struct sip_msg *msg,

sip_contact_set(&contact, sess->cuser, &msg->dst, msg->tp);

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

if (pl_strcmp(&msg->met, "PRACK")) {
if (pl_strcmp(&msg->met, "PRACK") && pl_strcmp(&msg->met, "UPDATE")) {
tmr_start(&reply->tmr, 64 * SIP_T1, tmr_handler, reply);
tmr_start(&reply->tmrg, SIP_T1, retransmit_handler, reply);
}
Expand Down
2 changes: 2 additions & 0 deletions src/sipsess/sipsess.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ struct sipsess {
bool established;
bool peerterm;
bool rel100_supported;
bool received_update;
int terminated;
};

Expand Down Expand Up @@ -97,6 +98,7 @@ 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);
int sipsess_reinvite(struct sipsess *sess, bool reset_ls);
int sipsess_update(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,
const char *ctype, struct mbuf *body,
Expand Down

0 comments on commit 15c261f

Please sign in to comment.