blob: 13a875c2ee13183695a9cf06232f6354d14728d7 [file] [log] [blame]
James Kuszmaul82f6c042021-01-17 11:30:16 -08001/**
2 * @file strans.c SIP Server Transaction
3 *
4 * Copyright (C) 2010 Creytiv.com
5 */
6#include <re_types.h>
7#include <re_mem.h>
8#include <re_mbuf.h>
9#include <re_sa.h>
10#include <re_list.h>
11#include <re_hash.h>
12#include <re_fmt.h>
13#include <re_uri.h>
14#include <re_sys.h>
15#include <re_tmr.h>
16#include <re_udp.h>
17#include <re_msg.h>
18#include <re_sip.h>
19#include "sip.h"
20
21
22enum state {
23 TRYING,
24 PROCEEDING,
25 ACCEPTED,
26 COMPLETED,
27 CONFIRMED,
28};
29
30
31struct sip_strans {
32 struct le he;
33 struct le he_mrg;
34 struct tmr tmr;
35 struct tmr tmrg;
36 struct sa dst;
37 struct sip *sip;
38 struct sip_msg *msg;
39 struct mbuf *mb;
40 sip_cancel_h *cancelh;
41 void *arg;
42 enum state state;
43 uint32_t txc;
44 bool invite;
45};
46
47
48static void destructor(void *arg)
49{
50 struct sip_strans *st = arg;
51
52 hash_unlink(&st->he);
53 hash_unlink(&st->he_mrg);
54 tmr_cancel(&st->tmr);
55 tmr_cancel(&st->tmrg);
56 mem_deref(st->msg);
57 mem_deref(st->mb);
58}
59
60
61static bool strans_cmp(const struct sip_msg *msg1, const struct sip_msg *msg2)
62{
63 if (pl_cmp(&msg1->via.branch, &msg2->via.branch))
64 return false;
65
66 if (pl_cmp(&msg1->via.sentby, &msg2->via.sentby))
67 return false;
68
69 return true;
70}
71
72
73static bool cmp_handler(struct le *le, void *arg)
74{
75 struct sip_strans *st = le->data;
76 const struct sip_msg *msg = arg;
77
78 if (!strans_cmp(st->msg, msg))
79 return false;
80
81 if (pl_cmp(&st->msg->cseq.met, &msg->cseq.met))
82 return false;
83
84 return true;
85}
86
87
88static bool cmp_ack_handler(struct le *le, void *arg)
89{
90 struct sip_strans *st = le->data;
91 const struct sip_msg *msg = arg;
92
93 if (!strans_cmp(st->msg, msg))
94 return false;
95
96 if (pl_strcmp(&st->msg->cseq.met, "INVITE"))
97 return false;
98
99 return true;
100}
101
102
103static bool cmp_cancel_handler(struct le *le, void *arg)
104{
105 struct sip_strans *st = le->data;
106 const struct sip_msg *msg = arg;
107
108 if (!strans_cmp(st->msg, msg))
109 return false;
110
111 if (!pl_strcmp(&st->msg->cseq.met, "CANCEL"))
112 return false;
113
114 return true;
115}
116
117
118static bool cmp_merge_handler(struct le *le, void *arg)
119{
120 struct sip_strans *st = le->data;
121 const struct sip_msg *msg = arg;
122
123 if (pl_cmp(&st->msg->cseq.met, &msg->cseq.met))
124 return false;
125
126 if (st->msg->cseq.num != msg->cseq.num)
127 return false;
128
129 if (pl_cmp(&st->msg->callid, &msg->callid))
130 return false;
131
132 if (pl_cmp(&st->msg->from.tag, &msg->from.tag))
133 return false;
134
135 if (pl_cmp(&st->msg->ruri, &msg->ruri))
136 return false;
137
138 return true;
139}
140
141
142static void dummy_handler(void *arg)
143{
144 (void)arg;
145}
146
147
148static void tmr_handler(void *arg)
149{
150 struct sip_strans *st = arg;
151
152 mem_deref(st);
153}
154
155
156static void retransmit_handler(void *arg)
157{
158 struct sip_strans *st = arg;
159
160 (void)sip_send(st->sip, st->msg->sock, st->msg->tp, &st->dst,
161 st->mb);
162
163 st->txc++;
164 tmr_start(&st->tmrg, MIN(SIP_T1<<st->txc, SIP_T2), retransmit_handler,
165 st);
166}
167
168
169static bool ack_handler(struct sip *sip, const struct sip_msg *msg)
170{
171 struct sip_strans *st;
172
173 st = list_ledata(hash_lookup(sip->ht_strans,
174 hash_joaat_pl(&msg->via.branch),
175 cmp_ack_handler, (void *)msg));
176 if (!st)
177 return false;
178
179 switch (st->state) {
180
181 case ACCEPTED:
182 /* make sure ACKs for 2xx are passed to TU */
183 return false;
184
185 case COMPLETED:
186 if (sip_transp_reliable(st->msg->tp)) {
187 mem_deref(st);
188 break;
189 }
190
191 tmr_start(&st->tmr, SIP_T4, tmr_handler, st);
192 tmr_cancel(&st->tmrg);
193 st->state = CONFIRMED;
194 break;
195
196 default:
197 break;
198 }
199
200 return true;
201}
202
203
204static bool cancel_handler(struct sip *sip, const struct sip_msg *msg)
205{
206 struct sip_strans *st;
207
208 st = list_ledata(hash_lookup(sip->ht_strans,
209 hash_joaat_pl(&msg->via.branch),
210 cmp_cancel_handler, (void *)msg));
211 if (!st)
212 return false;
213
214 ((struct sip_msg *)msg)->tag = st->msg->tag;
215
216 (void)sip_reply(sip, msg, 200, "OK");
217
218 switch (st->state) {
219
220 case TRYING:
221 case PROCEEDING:
222 st->cancelh(st->arg);
223 break;
224
225 default:
226 break;
227 }
228
229 return true;
230}
231
232
233static bool request_handler(const struct sip_msg *msg, void *arg)
234{
235 struct sip_strans *st;
236 struct sip *sip = arg;
237
238 if (!pl_strcmp(&msg->met, "ACK"))
239 return ack_handler(sip, msg);
240
241 st = list_ledata(hash_lookup(sip->ht_strans,
242 hash_joaat_pl(&msg->via.branch),
243 cmp_handler, (void *)msg));
244 if (st) {
245 switch (st->state) {
246
247 case PROCEEDING:
248 case COMPLETED:
249 (void)sip_send(st->sip, st->msg->sock, st->msg->tp,
250 &st->dst, st->mb);
251 break;
252
253 default:
254 break;
255 }
256
257 return true;
258 }
259 else if (!pl_isset(&msg->to.tag)) {
260
261 st = list_ledata(hash_lookup(sip->ht_strans_mrg,
262 hash_joaat_pl(&msg->callid),
263 cmp_merge_handler, (void *)msg));
264 if (st) {
265 (void)sip_reply(sip, msg, 482, "Loop Detected");
266 return true;
267 }
268 }
269
270 if (!pl_strcmp(&msg->met, "CANCEL"))
271 return cancel_handler(sip, msg);
272
273 return false;
274}
275
276
277/**
278 * Allocate a SIP Server Transaction
279 *
280 * @param stp Pointer to allocated SIP Server Transaction
281 * @param sip SIP Stack instance
282 * @param msg Incoming SIP message
283 * @param cancelh Cancel handler
284 * @param arg Handler argument
285 *
286 * @return 0 if success, otherwise errorcode
287 */
288int sip_strans_alloc(struct sip_strans **stp, struct sip *sip,
289 const struct sip_msg *msg, sip_cancel_h *cancelh,
290 void *arg)
291{
292 struct sip_strans *st;
293
294 if (!stp || !sip || !msg)
295 return EINVAL;
296
297 st = mem_zalloc(sizeof(*st), destructor);
298 if (!st)
299 return ENOMEM;
300
301 hash_append(sip->ht_strans, hash_joaat_pl(&msg->via.branch),
302 &st->he, st);
303
304 hash_append(sip->ht_strans_mrg, hash_joaat_pl(&msg->callid),
305 &st->he_mrg, st);
306
307 st->invite = !pl_strcmp(&msg->met, "INVITE");
308 st->msg = mem_ref((void *)msg);
309 st->state = TRYING;
310 st->cancelh = cancelh ? cancelh : dummy_handler;
311 st->arg = arg;
312 st->sip = sip;
313
314 *stp = st;
315
316 return 0;
317}
318
319
320/**
321 * Reply using a SIP Server Transaction
322 *
323 * @param stp Pointer to allocated SIP Server Transaction
324 * @param sip SIP Stack instance
325 * @param msg Incoming SIP message
326 * @param dst Destination network address
327 * @param scode Response status code
328 * @param mb Buffer containing SIP response
329 *
330 * @return 0 if success, otherwise errorcode
331 */
332int sip_strans_reply(struct sip_strans **stp, struct sip *sip,
333 const struct sip_msg *msg, const struct sa *dst,
334 uint16_t scode, struct mbuf *mb)
335{
336 struct sip_strans *st = NULL;
337 int err;
338
339 if (!sip || !mb || !dst || (scode < 200 && !stp))
340 return EINVAL;
341
342 if (stp)
343 st = *stp;
344
345 if (!st) {
346 err = sip_strans_alloc(&st, sip, msg, NULL, NULL);
347 if (err)
348 return err;
349 }
350
351 mem_deref(st->mb);
352 st->mb = mem_ref(mb);
353 st->dst = *dst;
354
355 err = sip_send(sip, st->msg->sock, st->msg->tp, dst, mb);
356
357 if (stp)
358 *stp = (err || scode >= 200) ? NULL : st;
359
360 if (err) {
361 mem_deref(st);
362 return err;
363 }
364
365 if (st->invite) {
366 if (scode < 200) {
367 st->state = PROCEEDING;
368 }
369 else if (scode < 300) {
370 tmr_start(&st->tmr, 64 * SIP_T1, tmr_handler, st);
371 st->state = ACCEPTED;
372 }
373 else {
374 tmr_start(&st->tmr, 64 * SIP_T1, tmr_handler, st);
375 st->state = COMPLETED;
376
377 if (!sip_transp_reliable(st->msg->tp))
378 tmr_start(&st->tmrg, SIP_T1,
379 retransmit_handler, st);
380 }
381 }
382 else {
383 if (scode < 200) {
384 st->state = PROCEEDING;
385 }
386 else {
387 if (!sip_transp_reliable(st->msg->tp)) {
388 tmr_start(&st->tmr, 64 * SIP_T1, tmr_handler,
389 st);
390 st->state = COMPLETED;
391 }
392 else {
393 mem_deref(st);
394 }
395 }
396 }
397
398 return 0;
399}
400
401
402int sip_strans_init(struct sip *sip, uint32_t sz)
403{
404 int err;
405
406 err = sip_listen(NULL, sip, true, request_handler, sip);
407 if (err)
408 return err;
409
410 err = hash_alloc(&sip->ht_strans_mrg, sz);
411 if (err)
412 return err;
413
414 return hash_alloc(&sip->ht_strans, sz);
415}
416
417
418static const char *statename(enum state state)
419{
420 switch (state) {
421
422 case TRYING: return "TRYING";
423 case PROCEEDING: return "PROCEEDING";
424 case ACCEPTED: return "ACCEPTED";
425 case COMPLETED: return "COMPLETED";
426 case CONFIRMED: return "CONFIRMED";
427 default: return "???";
428 }
429}
430
431
432static bool debug_handler(struct le *le, void *arg)
433{
434 struct sip_strans *st = le->data;
435 struct re_printf *pf = arg;
436
437 (void)re_hprintf(pf, " %-10r %-10s %2llus (%r)\n",
438 &st->msg->met,
439 statename(st->state),
440 tmr_get_expire(&st->tmr)/1000,
441 &st->msg->via.branch);
442
443 return false;
444}
445
446
447int sip_strans_debug(struct re_printf *pf, const struct sip *sip)
448{
449 int err;
450
451 err = re_hprintf(pf, "server transactions:\n");
452 hash_apply(sip->ht_strans, debug_handler, pf);
453
454 return err;
455}