Skip to content

Commit fa2d3f2

Browse files
committed
dialog PRACK: Enhance auto-prack mode with failure handling
1 parent 90c7891 commit fa2d3f2

1 file changed

Lines changed: 196 additions & 0 deletions

File tree

modules/dialog/dlg_req_within.c

Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include "../../parser/contact/parse_contact.h"
3535
#include "../tm/dlg.h"
3636
#include "../tm/tm_load.h"
37+
#include "../tm/t_hooks.h"
3738
#include "../../ipc.h"
3839
#include "dlg_hash.h"
3940
#include "dlg_req_within.h"
@@ -44,6 +45,185 @@
4445

4546
extern str dlg_extra_hdrs;
4647

48+
#define DLG_AUTO_PRACK_FR_TIMEOUT 2
49+
#define DLG_TM_TID_LEN ((sizeof(int) * 2) + 1 + (sizeof(int) * 2))
50+
51+
struct dlg_auto_prack_ctx {
52+
unsigned int invite_hash_index;
53+
unsigned int invite_label;
54+
str invite_tid;
55+
str invite_totag;
56+
};
57+
58+
static void dlg_auto_prack_free(void *ctx)
59+
{
60+
shm_free(ctx);
61+
}
62+
63+
static void dlg_auto_prack_reply_failure(struct dlg_auto_prack_ctx *ctx)
64+
{
65+
str reason = str_init("Bad Gateway");
66+
struct cell *invite_t;
67+
int rc;
68+
69+
rc = d_tmb.t_lookup_ident(&invite_t, ctx->invite_hash_index,
70+
ctx->invite_label);
71+
if (rc < 0) {
72+
LM_ERR("failed to lookup correlated INVITE transaction <%.*s> for auto PRACK failure handling\n",
73+
ctx->invite_tid.len, ctx->invite_tid.s);
74+
return;
75+
}
76+
77+
LM_DBG("auto PRACK failure: sending native 502 reply on correlated INVITE transaction <%.*s>, to-tag <%.*s>\n",
78+
ctx->invite_tid.len, ctx->invite_tid.s,
79+
ctx->invite_totag.len, ctx->invite_totag.s);
80+
rc = d_tmb.t_reply_with_body(invite_t, 502, &reason, NULL, NULL,
81+
&ctx->invite_totag);
82+
d_tmb.unref_cell(invite_t);
83+
84+
if (rc < 0)
85+
LM_ERR("failed to send native 502 reply on correlated INVITE transaction <%.*s>\n",
86+
ctx->invite_tid.len, ctx->invite_tid.s);
87+
else
88+
LM_DBG("native 502 reply sent on correlated INVITE transaction <%.*s>\n",
89+
ctx->invite_tid.len, ctx->invite_tid.s);
90+
}
91+
92+
static int dlg_format_trans_id(unsigned int hash_index, unsigned int label,
93+
str *out, char *buf, unsigned int size)
94+
{
95+
char *p;
96+
int left;
97+
98+
if (size < DLG_TM_TID_LEN)
99+
return -1;
100+
101+
p = buf;
102+
left = size;
103+
int2reverse_hex(&p, &left, label);
104+
*(p++) = '.';
105+
left--;
106+
int2reverse_hex(&p, &left, hash_index);
107+
108+
out->s = buf;
109+
out->len = p - buf;
110+
return 0;
111+
}
112+
113+
static void dlg_auto_prack_tmcb(struct cell *t, int type, struct tmcb_params *ps)
114+
{
115+
char prack_tid_buf[DLG_TM_TID_LEN];
116+
str prack_tid = STR_NULL;
117+
struct dlg_auto_prack_ctx *ctx;
118+
int rc = 0;
119+
120+
if (!ps || !ps->param || !(*ps->param))
121+
return;
122+
123+
ctx = (struct dlg_auto_prack_ctx *)(*ps->param);
124+
if (dlg_format_trans_id(t->hash_index, t->label, &prack_tid, prack_tid_buf,
125+
sizeof(prack_tid_buf)) < 0) {
126+
LM_ERR("failed to format auto PRACK transaction id for [%u:%u]\n",
127+
t->hash_index, t->label);
128+
return;
129+
}
130+
131+
switch (type) {
132+
case TMCB_LOCAL_COMPLETED:
133+
LM_DBG("auto PRACK local transaction <%.*s> completed with code %d; correlated INVITE tid <%.*s>, to-tag <%.*s>\n",
134+
prack_tid.len, prack_tid.s, ps->code, ctx->invite_tid.len,
135+
ctx->invite_tid.s, ctx->invite_totag.len, ctx->invite_totag.s);
136+
if (ps->code < 300)
137+
break;
138+
LM_DBG("auto PRACK local transaction <%.*s> completed negatively with code %d; triggering correlated INVITE failure handling\n",
139+
prack_tid.len, prack_tid.s, ps->code);
140+
rc = 1;
141+
break;
142+
case TMCB_ON_FAILURE:
143+
LM_DBG("auto PRACK local transaction <%.*s> failed with code %d; correlated INVITE tid <%.*s>, to-tag <%.*s>\n",
144+
prack_tid.len, prack_tid.s, ps->code, ctx->invite_tid.len,
145+
ctx->invite_tid.s, ctx->invite_totag.len, ctx->invite_totag.s);
146+
rc = 1;
147+
break;
148+
}
149+
150+
if (rc)
151+
dlg_auto_prack_reply_failure(ctx);
152+
}
153+
154+
static void dlg_auto_prack_t_created(struct cell *t, void *param)
155+
{
156+
char prack_tid_buf[DLG_TM_TID_LEN];
157+
str prack_tid = STR_NULL;
158+
struct dlg_auto_prack_ctx *ctx = param;
159+
160+
t->fr_timeout = DLG_AUTO_PRACK_FR_TIMEOUT;
161+
162+
if (dlg_format_trans_id(t->hash_index, t->label, &prack_tid, prack_tid_buf,
163+
sizeof(prack_tid_buf)) < 0) {
164+
LM_ERR("failed to format newly created auto PRACK transaction id for [%u:%u]\n",
165+
t->hash_index, t->label);
166+
} else {
167+
LM_DBG("auto PRACK created local transaction <%.*s>; correlated INVITE tid <%.*s>, to-tag <%.*s>; fr_timeout=%d\n",
168+
prack_tid.len, prack_tid.s, ctx->invite_tid.len, ctx->invite_tid.s,
169+
ctx->invite_totag.len, ctx->invite_totag.s, t->fr_timeout);
170+
}
171+
172+
if (d_tmb.register_tmcb(NULL, t, TMCB_LOCAL_COMPLETED | TMCB_ON_FAILURE,
173+
dlg_auto_prack_tmcb, ctx, dlg_auto_prack_free) < 0) {
174+
LM_ERR("failed to register TM callbacks for auto PRACK local transaction [%u:%u]\n",
175+
t->hash_index, t->label);
176+
}
177+
}
178+
179+
static struct dlg_auto_prack_ctx *dlg_build_auto_prack_ctx(struct sip_msg *rpl)
180+
{
181+
char invite_tid_buf[DLG_TM_TID_LEN];
182+
struct dlg_auto_prack_ctx *ctx;
183+
unsigned int hash_index, label;
184+
unsigned int size;
185+
char *p;
186+
str invite_tid = STR_NULL;
187+
str invite_totag = STR_NULL;
188+
189+
if (d_tmb.t_get_trans_ident(rpl, &hash_index, &label) < 0) {
190+
LM_ERR("failed to fetch correlated INVITE transaction id for auto PRACK\n");
191+
return NULL;
192+
}
193+
if ((!rpl->to && parse_headers(rpl, HDR_TO_F, 0) < 0) || !rpl->to) {
194+
LM_ERR("failed to parse To header while building auto PRACK correlation context\n");
195+
return NULL;
196+
}
197+
198+
if (dlg_format_trans_id(hash_index, label, &invite_tid, invite_tid_buf,
199+
sizeof(invite_tid_buf)) < 0) {
200+
LM_ERR("failed to format correlated INVITE transaction id for auto PRACK\n");
201+
return NULL;
202+
}
203+
invite_totag = get_to(rpl)->tag_value;
204+
205+
size = sizeof(*ctx) + invite_tid.len + invite_totag.len;
206+
ctx = shm_malloc(size);
207+
if (!ctx) {
208+
LM_ERR("oom for auto PRACK correlation context\n");
209+
return NULL;
210+
}
211+
212+
p = (char *)(ctx + 1);
213+
ctx->invite_hash_index = hash_index;
214+
ctx->invite_label = label;
215+
ctx->invite_tid.s = p;
216+
ctx->invite_tid.len = invite_tid.len;
217+
memcpy(p, invite_tid.s, invite_tid.len);
218+
p += invite_tid.len;
219+
220+
ctx->invite_totag.s = p;
221+
ctx->invite_totag.len = invite_totag.len;
222+
memcpy(p, invite_totag.s, invite_totag.len);
223+
224+
return ctx;
225+
}
226+
47227
int free_tm_dlg(dlg_t *td)
48228
{
49229
if(td)
@@ -1215,6 +1395,7 @@ int send_prack_indialog_request(struct dlg_cell *dlg, struct sip_msg *rpl,
12151395
str method = str_init("PRACK");
12161396
str extra_headers = STR_NULL;
12171397
struct dlg_indialog_req_param *p = NULL;
1398+
struct dlg_auto_prack_ctx *auto_prack_ctx = NULL;
12181399
context_p old_ctx;
12191400
context_p *new_ctx;
12201401
dlg_t *dialog_info = NULL;
@@ -1251,10 +1432,23 @@ int send_prack_indialog_request(struct dlg_cell *dlg, struct sip_msg *rpl,
12511432
p->release = release;
12521433
p->leg = dstleg;
12531434

1435+
auto_prack_ctx = dlg_build_auto_prack_ctx(rpl);
1436+
if (!auto_prack_ctx)
1437+
LM_ERR("failed to build internal auto PRACK correlation context\n");
1438+
else {
1439+
LM_DBG("built internal auto PRACK correlation context for INVITE tid <%.*s>, to-tag <%.*s>\n",
1440+
auto_prack_ctx->invite_tid.len, auto_prack_ctx->invite_tid.s,
1441+
auto_prack_ctx->invite_totag.len, auto_prack_ctx->invite_totag.s);
1442+
dialog_info->t_created_cb = dlg_auto_prack_t_created;
1443+
dialog_info->t_created_cb_param = auto_prack_ctx;
1444+
}
1445+
12541446
if (push_new_processing_context(dlg, &old_ctx, &new_ctx, NULL) != 0) {
12551447
pkg_free(extra_headers.s);
12561448
free_tm_dlg(dialog_info);
12571449
shm_free(p);
1450+
if (auto_prack_ctx)
1451+
shm_free(auto_prack_ctx);
12581452
return -1;
12591453
}
12601454

@@ -1281,6 +1475,8 @@ int send_prack_indialog_request(struct dlg_cell *dlg, struct sip_msg *rpl,
12811475
LM_ERR("failed to send the PRACK request\n");
12821476
unref_dlg(dlg, 1);
12831477
shm_free(p);
1478+
if (auto_prack_ctx)
1479+
shm_free(auto_prack_ctx);
12841480
return -1;
12851481
}
12861482

0 commit comments

Comments
 (0)