This patch implements SIP merged requests according to RFC 3261 section 8.2.2.2.
This commit is contained in:
parent
7f2e6f0edd
commit
c09a7c73ae
7 changed files with 90 additions and 0 deletions
|
@ -18,6 +18,7 @@ struct le *hash_apply(const struct hash *h, list_apply_h *ah, void *arg);
|
||||||
struct list *hash_list(const struct hash *h, uint32_t key);
|
struct list *hash_list(const struct hash *h, uint32_t key);
|
||||||
uint32_t hash_bsize(const struct hash *h);
|
uint32_t hash_bsize(const struct hash *h);
|
||||||
void hash_flush(struct hash *h);
|
void hash_flush(struct hash *h);
|
||||||
|
void hash_clear(struct hash *h);
|
||||||
uint32_t hash_valid_size(uint32_t size);
|
uint32_t hash_valid_size(uint32_t size);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,7 @@ typedef bool (list_sort_h)(struct le *le1, struct le *le2, void *arg);
|
||||||
|
|
||||||
void list_init(struct list *list);
|
void list_init(struct list *list);
|
||||||
void list_flush(struct list *list);
|
void list_flush(struct list *list);
|
||||||
|
void list_clear(struct list *list);
|
||||||
void list_append(struct list *list, struct le *le, void *data);
|
void list_append(struct list *list, struct le *le, void *data);
|
||||||
void list_prepend(struct list *list, struct le *le, void *data);
|
void list_prepend(struct list *list, struct le *le, void *data);
|
||||||
void list_insert_before(struct list *list, struct le *le, struct le *ile,
|
void list_insert_before(struct list *list, struct le *le, struct le *ile,
|
||||||
|
|
|
@ -183,6 +183,23 @@ void hash_flush(struct hash *h)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear a hashmap without dereferencing the elements
|
||||||
|
*
|
||||||
|
* @param h Hashmap table
|
||||||
|
*/
|
||||||
|
void hash_clear(struct hash *h)
|
||||||
|
{
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
if (!h)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (i=0; i<h->bsize; i++)
|
||||||
|
list_clear(&h->bucket[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate a valid hash size from a random size
|
* Calculate a valid hash size from a random size
|
||||||
*
|
*
|
||||||
|
|
|
@ -55,6 +55,31 @@ void list_flush(struct list *list)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear a linked list without dereferencing the elements
|
||||||
|
*
|
||||||
|
* @param list Linked list
|
||||||
|
*/
|
||||||
|
void list_clear(struct list *list)
|
||||||
|
{
|
||||||
|
struct le *le;
|
||||||
|
|
||||||
|
if (!list)
|
||||||
|
return;
|
||||||
|
|
||||||
|
le = list->head;
|
||||||
|
while (le) {
|
||||||
|
struct le *next = le->next;
|
||||||
|
le->list = NULL;
|
||||||
|
le->prev = le->next = NULL;
|
||||||
|
le->data = NULL;
|
||||||
|
le = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
list_init(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Append a list element to a linked list
|
* Append a list element to a linked list
|
||||||
*
|
*
|
||||||
|
|
|
@ -38,7 +38,9 @@ static void destructor(void *arg)
|
||||||
mem_deref(sip->ht_ctrans);
|
mem_deref(sip->ht_ctrans);
|
||||||
|
|
||||||
hash_flush(sip->ht_strans);
|
hash_flush(sip->ht_strans);
|
||||||
|
hash_clear(sip->ht_strans_mrg);
|
||||||
mem_deref(sip->ht_strans);
|
mem_deref(sip->ht_strans);
|
||||||
|
mem_deref(sip->ht_strans_mrg);
|
||||||
|
|
||||||
hash_flush(sip->ht_conn);
|
hash_flush(sip->ht_conn);
|
||||||
mem_deref(sip->ht_conn);
|
mem_deref(sip->ht_conn);
|
||||||
|
|
|
@ -11,6 +11,7 @@ struct sip {
|
||||||
struct list reql;
|
struct list reql;
|
||||||
struct hash *ht_ctrans;
|
struct hash *ht_ctrans;
|
||||||
struct hash *ht_strans;
|
struct hash *ht_strans;
|
||||||
|
struct hash *ht_strans_mrg;
|
||||||
struct hash *ht_conn;
|
struct hash *ht_conn;
|
||||||
struct hash *ht_udpconn;
|
struct hash *ht_udpconn;
|
||||||
struct dnsc *dnsc;
|
struct dnsc *dnsc;
|
||||||
|
|
|
@ -29,6 +29,7 @@ enum state {
|
||||||
|
|
||||||
struct sip_strans {
|
struct sip_strans {
|
||||||
struct le he;
|
struct le he;
|
||||||
|
struct le he_mrg;
|
||||||
struct tmr tmr;
|
struct tmr tmr;
|
||||||
struct tmr tmrg;
|
struct tmr tmrg;
|
||||||
struct sa dst;
|
struct sa dst;
|
||||||
|
@ -48,6 +49,7 @@ static void destructor(void *arg)
|
||||||
struct sip_strans *st = arg;
|
struct sip_strans *st = arg;
|
||||||
|
|
||||||
hash_unlink(&st->he);
|
hash_unlink(&st->he);
|
||||||
|
hash_unlink(&st->he_mrg);
|
||||||
tmr_cancel(&st->tmr);
|
tmr_cancel(&st->tmr);
|
||||||
tmr_cancel(&st->tmrg);
|
tmr_cancel(&st->tmrg);
|
||||||
mem_deref(st->msg);
|
mem_deref(st->msg);
|
||||||
|
@ -112,6 +114,30 @@ static bool cmp_cancel_handler(struct le *le, void *arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool cmp_merge_handler(struct le *le, void *arg)
|
||||||
|
{
|
||||||
|
struct sip_strans *st = le->data;
|
||||||
|
const struct sip_msg *msg = arg;
|
||||||
|
|
||||||
|
if (pl_cmp(&st->msg->cseq.met, &msg->cseq.met))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (st->msg->cseq.num != msg->cseq.num)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (pl_cmp(&st->msg->callid, &msg->callid))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (pl_cmp(&st->msg->from.tag, &msg->from.tag))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (pl_cmp(&st->msg->ruri, &msg->ruri))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void dummy_handler(void *arg)
|
static void dummy_handler(void *arg)
|
||||||
{
|
{
|
||||||
(void)arg;
|
(void)arg;
|
||||||
|
@ -229,6 +255,16 @@ static bool request_handler(const struct sip_msg *msg, void *arg)
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
else if (!pl_isset(&msg->to.tag)) {
|
||||||
|
|
||||||
|
st = list_ledata(hash_lookup(sip->ht_strans_mrg,
|
||||||
|
hash_joaat_pl(&msg->callid),
|
||||||
|
cmp_merge_handler, (void *)msg));
|
||||||
|
if (st) {
|
||||||
|
(void)sip_reply(sip, msg, 482, "Loop Detected");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!pl_strcmp(&msg->met, "CANCEL"))
|
if (!pl_strcmp(&msg->met, "CANCEL"))
|
||||||
return cancel_handler(sip, msg);
|
return cancel_handler(sip, msg);
|
||||||
|
@ -264,6 +300,9 @@ int sip_strans_alloc(struct sip_strans **stp, struct sip *sip,
|
||||||
hash_append(sip->ht_strans, hash_joaat_pl(&msg->via.branch),
|
hash_append(sip->ht_strans, hash_joaat_pl(&msg->via.branch),
|
||||||
&st->he, st);
|
&st->he, st);
|
||||||
|
|
||||||
|
hash_append(sip->ht_strans_mrg, hash_joaat_pl(&msg->callid),
|
||||||
|
&st->he_mrg, st);
|
||||||
|
|
||||||
st->invite = !pl_strcmp(&msg->met, "INVITE");
|
st->invite = !pl_strcmp(&msg->met, "INVITE");
|
||||||
st->msg = mem_ref((void *)msg);
|
st->msg = mem_ref((void *)msg);
|
||||||
st->state = TRYING;
|
st->state = TRYING;
|
||||||
|
@ -367,6 +406,10 @@ int sip_strans_init(struct sip *sip, uint32_t sz)
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
err = hash_alloc(&sip->ht_strans_mrg, sz);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
return hash_alloc(&sip->ht_strans, sz);
|
return hash_alloc(&sip->ht_strans, sz);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue