Skip to content

Commit

Permalink
sipsess: PRACK refactoring
Browse files Browse the repository at this point in the history
Add awaiting_sdp_prack bool to sipsess to be able to check whether the
sipsess is still awaiting a PRACK to a 1xx response with SDP. Further,
refactor PRACK logic to remove ht_prack which was unused and unneeded.
  • Loading branch information
maximilianfridrich committed Jan 19, 2023
1 parent 591d450 commit acc21aa
Show file tree
Hide file tree
Showing 8 changed files with 275 additions and 97 deletions.
2 changes: 2 additions & 0 deletions include/re_sipsess.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ int sipsess_modify(struct sipsess *sess, struct mbuf *desc);
int sipsess_info(struct sipsess *sess, const char *ctype, struct mbuf *body,
sip_resp_h *resph, void *arg);
int sipsess_set_close_headers(struct sipsess *sess, const char *hdrs, ...);
bool sipsess_awaiting_prack(struct sipsess *sess);
bool sipsess_refresh_allowed(struct sipsess *sess);
void sipsess_close_all(struct sipsess_sock *sock);
struct sip_dialog *sipsess_dialog(const struct sipsess *sess);
void sipsess_abort(struct sipsess *sess);
15 changes: 8 additions & 7 deletions src/sipsess/listen.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ static void destructor(void *arg)
mem_deref(sock->ht_sess);
hash_flush(sock->ht_ack);
mem_deref(sock->ht_ack);
hash_flush(sock->ht_prack);
mem_deref(sock->ht_prack);
}


Expand Down Expand Up @@ -174,10 +172,12 @@ static void prack_handler(struct sipsess_sock *sock, const struct sip_msg *msg)
struct sipsess *sess;
struct mbuf *desc = NULL;
bool awaiting_answer = false;
bool awaiting_prack = false;

sess = sipsess_find(sock, msg);

if (!sess || sipsess_reply_ack(sess, msg, &awaiting_answer)) {
if (!sess || sipsess_reply_prack(sess, msg, &awaiting_answer,
&awaiting_prack)) {
(void)sip_reply(sock->sip, msg, 481,
"Transaction Does Not Exist");
return;
Expand All @@ -192,6 +192,11 @@ 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;
}

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

Expand Down Expand Up @@ -379,10 +384,6 @@ int sipsess_listen(struct sipsess_sock **sockp, struct sip *sip,
if (err)
goto out;

err = hash_alloc(&sock->ht_prack, htsize);
if (err)
goto out;

sock->sip = sip;
sock->connh = connh ? connh : internal_connect_handler;
sock->arg = connh ? arg : sock;
Expand Down
3 changes: 2 additions & 1 deletion src/sipsess/modify.c
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,8 @@ int sipsess_reinvite(struct sipsess *sess, bool reset_ls)
*/
int sipsess_modify(struct sipsess *sess, struct mbuf *desc)
{
if (!sess || (sess->st && sess->established) || sess->terminated)
if (!sess || (!sess->established && !sess->refresh_allowed)
|| sess->terminated || sess->awaiting_answer)
return EINVAL;

mem_deref(sess->desc);
Expand Down
188 changes: 122 additions & 66 deletions src/sipsess/prack.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,78 +19,147 @@


struct sipsess_prack {
struct le he;
struct tmr tmr;
struct sa dst;
struct sip_request *req;
struct sip_dialog *dlg;
struct sipsess_sock *sock;
struct mbuf *mb;
enum sip_transp tp;
uint32_t cseq;
uint32_t rseq;
char *met;
struct sipsess_request *req;
};


static int prack_request(struct sipsess_prack *prack);


static void destructor(void *arg)
{
struct sipsess_prack *prack = arg;

hash_unlink(&prack->he);
tmr_cancel(&prack->tmr);
mem_deref(prack->met);
mem_deref(prack->req);
mem_deref(prack->dlg);
mem_deref(prack->sock);
mem_deref(prack->mb);
}


static void tmr_handler(void *arg)
{
struct sipsess_prack *prack = arg;
int err;

mem_deref(prack);
}


static int send_handler(enum sip_transp tp, struct sa *src,
const struct sa *dst, struct mbuf *mb,
struct mbuf **contp, void *arg)
{
struct sipsess_prack *prack = arg;
(void)src;
(void)contp;

mem_deref(prack->mb);
prack->mb = mem_ref(mb);
prack->dst = *dst;
prack->tp = tp;
if (!prack)
return;

tmr_start(&prack->tmr, 64 * SIP_T1, tmr_handler, prack);
return 0;
err = prack_request(prack);
if (err)
mem_deref(prack);
}


static void resp_handler(int err, const struct sip_msg *msg, void *arg)
static void prack_resp_handler(int err, const struct sip_msg *msg, void *arg)
{
struct sipsess *sess;
struct sipsess_prack *prack = arg;
if (err || !msg)
goto out;
struct sipsess_request *req = prack->req;
const struct sip_hdr *hdr;

sess = sipsess_find(prack->sock, msg);
if (!sess || sess->terminated)
if (!msg || err || sip_request_loops(&req->ls, msg->scode))
goto out;

if (sess->prackh)
sess->prackh(msg, sess->arg);
if (msg->scode < 200) {
return;
}
else if (msg->scode < 300) {
(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;
(void)req->sess->answerh(msg, req->sess->arg);
}

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

switch (msg->scode) {

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

err = prack_request(prack);
if (err)
break;

return;
case 408:
case 491:
tmr_start(&req->tmr, req->sess->owner ? 3000 : 1000,
tmr_handler, req);
return;
case 500:
hdr = sip_msg_hdr(msg, SIP_HDR_RETRY_AFTER);
if (!hdr)
break;

tmr_start(&req->tmr, pl_u32(&hdr->val) * 1000,
tmr_handler, req);
return;
}
}

out:
if (!req->sess->terminated) {
if (err == ETIMEDOUT)
sipsess_terminate(req->sess, err, NULL);
}

mem_deref(prack);
}


static int prack_request(struct sipsess_prack *prack)
{
struct sipsess_request *req = prack->req;
char rack_header[256];
int err;

if (!req || req->tmr.th)
return EINVAL;

err = re_snprintf(rack_header, sizeof(rack_header), "%d %d %s",
prack->rseq, prack->cseq, prack->met);
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,
"RAck: %s\n"
"%s%s%s"
"Content-Length: %zu\r\n"
"\r\n"
"%b",
rack_header,
req->body ? "Content-Type: " : "",
req->body ? req->sess->ctype : "",
req->body ? "\r\n" : "",
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);
}


/**
* Send PRACK message (RFC 3262)
* Send PRACK request (RFC 3262)
*
* @param sess SIP Session
* @param cseq CSeq number to be written in RAck header
Expand All @@ -104,42 +173,29 @@ int sipsess_prack(struct sipsess *sess, uint32_t cseq, uint32_t rseq,
const struct pl *met, struct mbuf *desc)
{
struct sipsess_prack *prack;
char rack_header[256];
char method[64];
int err;

if (!sess || sess->terminated)
return EINVAL;

prack = mem_zalloc(sizeof(*prack), destructor);
if (!prack)
return ENOMEM;

hash_append(sess->sock->ht_prack,
hash_joaat_str(sip_dialog_callid(sess->dlg)),
&prack->he, prack);
err = sipsess_request_alloc(&prack->req, sess, sess->ctype, desc,
NULL, prack);
if (err)
goto out;

prack->dlg = mem_ref(sess->dlg);
prack->sock = mem_ref(sess->sock);
prack->cseq = cseq;
prack->rseq = rseq;
err = pl_strdup(&prack->met, met);
if (err)
goto out;

(void)pl_strcpy(met, method, sizeof(method));
re_snprintf(rack_header, sizeof(rack_header), "%d %d %s", rseq, cseq,
method);

err = sip_drequestf(&prack->req, sess->sock->sip, true, "PRACK",
sess->dlg, cseq, sess->auth, send_handler,
resp_handler, prack,
"RAck: %s\n"
"%s%s%s"
"Content-Length: %zu\r\n"
"\r\n"
"%b",
rack_header,
desc ? "Content-Type: " : "",
desc ? sess->ctype : "",
desc ? "\r\n" : "",
desc ? mbuf_get_left(desc) : (size_t)0,
desc ? mbuf_buf(desc) : NULL,
desc ? mbuf_get_left(desc) : (size_t)0);
err = prack_request(prack);

out:
if (err)
mem_deref(prack);

Expand Down
Loading

0 comments on commit acc21aa

Please sign in to comment.