Skip to content

Commit c09a7c7

Browse files
committed
This patch implements SIP merged requests according to RFC 3261 section 8.2.2.2.
1 parent 7f2e6f0 commit c09a7c7

File tree

7 files changed

+90
-0
lines changed

7 files changed

+90
-0
lines changed

include/re_hash.h

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ struct le *hash_apply(const struct hash *h, list_apply_h *ah, void *arg);
1818
struct list *hash_list(const struct hash *h, uint32_t key);
1919
uint32_t hash_bsize(const struct hash *h);
2020
void hash_flush(struct hash *h);
21+
void hash_clear(struct hash *h);
2122
uint32_t hash_valid_size(uint32_t size);
2223

2324

include/re_list.h

+1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ typedef bool (list_sort_h)(struct le *le1, struct le *le2, void *arg);
5151

5252
void list_init(struct list *list);
5353
void list_flush(struct list *list);
54+
void list_clear(struct list *list);
5455
void list_append(struct list *list, struct le *le, void *data);
5556
void list_prepend(struct list *list, struct le *le, void *data);
5657
void list_insert_before(struct list *list, struct le *le, struct le *ile,

src/hash/hash.c

+17
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,23 @@ void hash_flush(struct hash *h)
183183
}
184184

185185

186+
/**
187+
* Clear a hashmap without dereferencing the elements
188+
*
189+
* @param h Hashmap table
190+
*/
191+
void hash_clear(struct hash *h)
192+
{
193+
uint32_t i;
194+
195+
if (!h)
196+
return;
197+
198+
for (i=0; i<h->bsize; i++)
199+
list_clear(&h->bucket[i]);
200+
}
201+
202+
186203
/**
187204
* Calculate a valid hash size from a random size
188205
*

src/list/list.c

+25
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,31 @@ void list_flush(struct list *list)
5555
}
5656

5757

58+
/**
59+
* Clear a linked list without dereferencing the elements
60+
*
61+
* @param list Linked list
62+
*/
63+
void list_clear(struct list *list)
64+
{
65+
struct le *le;
66+
67+
if (!list)
68+
return;
69+
70+
le = list->head;
71+
while (le) {
72+
struct le *next = le->next;
73+
le->list = NULL;
74+
le->prev = le->next = NULL;
75+
le->data = NULL;
76+
le = next;
77+
}
78+
79+
list_init(list);
80+
}
81+
82+
5883
/**
5984
* Append a list element to a linked list
6085
*

src/sip/sip.c

+2
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,9 @@ static void destructor(void *arg)
3838
mem_deref(sip->ht_ctrans);
3939

4040
hash_flush(sip->ht_strans);
41+
hash_clear(sip->ht_strans_mrg);
4142
mem_deref(sip->ht_strans);
43+
mem_deref(sip->ht_strans_mrg);
4244

4345
hash_flush(sip->ht_conn);
4446
mem_deref(sip->ht_conn);

src/sip/sip.h

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ struct sip {
1111
struct list reql;
1212
struct hash *ht_ctrans;
1313
struct hash *ht_strans;
14+
struct hash *ht_strans_mrg;
1415
struct hash *ht_conn;
1516
struct hash *ht_udpconn;
1617
struct dnsc *dnsc;

src/sip/strans.c

+43
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ enum state {
2929

3030
struct sip_strans {
3131
struct le he;
32+
struct le he_mrg;
3233
struct tmr tmr;
3334
struct tmr tmrg;
3435
struct sa dst;
@@ -48,6 +49,7 @@ static void destructor(void *arg)
4849
struct sip_strans *st = arg;
4950

5051
hash_unlink(&st->he);
52+
hash_unlink(&st->he_mrg);
5153
tmr_cancel(&st->tmr);
5254
tmr_cancel(&st->tmrg);
5355
mem_deref(st->msg);
@@ -112,6 +114,30 @@ static bool cmp_cancel_handler(struct le *le, void *arg)
112114
}
113115

114116

117+
static bool cmp_merge_handler(struct le *le, void *arg)
118+
{
119+
struct sip_strans *st = le->data;
120+
const struct sip_msg *msg = arg;
121+
122+
if (pl_cmp(&st->msg->cseq.met, &msg->cseq.met))
123+
return false;
124+
125+
if (st->msg->cseq.num != msg->cseq.num)
126+
return false;
127+
128+
if (pl_cmp(&st->msg->callid, &msg->callid))
129+
return false;
130+
131+
if (pl_cmp(&st->msg->from.tag, &msg->from.tag))
132+
return false;
133+
134+
if (pl_cmp(&st->msg->ruri, &msg->ruri))
135+
return false;
136+
137+
return true;
138+
}
139+
140+
115141
static void dummy_handler(void *arg)
116142
{
117143
(void)arg;
@@ -229,6 +255,16 @@ static bool request_handler(const struct sip_msg *msg, void *arg)
229255

230256
return true;
231257
}
258+
else if (!pl_isset(&msg->to.tag)) {
259+
260+
st = list_ledata(hash_lookup(sip->ht_strans_mrg,
261+
hash_joaat_pl(&msg->callid),
262+
cmp_merge_handler, (void *)msg));
263+
if (st) {
264+
(void)sip_reply(sip, msg, 482, "Loop Detected");
265+
return true;
266+
}
267+
}
232268

233269
if (!pl_strcmp(&msg->met, "CANCEL"))
234270
return cancel_handler(sip, msg);
@@ -264,6 +300,9 @@ int sip_strans_alloc(struct sip_strans **stp, struct sip *sip,
264300
hash_append(sip->ht_strans, hash_joaat_pl(&msg->via.branch),
265301
&st->he, st);
266302

303+
hash_append(sip->ht_strans_mrg, hash_joaat_pl(&msg->callid),
304+
&st->he_mrg, st);
305+
267306
st->invite = !pl_strcmp(&msg->met, "INVITE");
268307
st->msg = mem_ref((void *)msg);
269308
st->state = TRYING;
@@ -367,6 +406,10 @@ int sip_strans_init(struct sip *sip, uint32_t sz)
367406
if (err)
368407
return err;
369408

409+
err = hash_alloc(&sip->ht_strans_mrg, sz);
410+
if (err)
411+
return err;
412+
370413
return hash_alloc(&sip->ht_strans, sz);
371414
}
372415

0 commit comments

Comments
 (0)