mirror of https://github.com/sipwise/kamailio.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
175 lines
4.3 KiB
175 lines
4.3 KiB
#include "events_uac.h"
|
|
#include "euac_internals.h" /* for debugging purposes */
|
|
#include "../../dprint.h"
|
|
|
|
#include <cds/sstr.h>
|
|
#include <cds/dstring.h>
|
|
#include <cds/sync.h>
|
|
#include <cds/hash_table.h>
|
|
#include "euac_funcs.h"
|
|
#include "euac_internals.h"
|
|
#include "euac_state_machine.h"
|
|
|
|
void remove_uac_from_list(events_uac_t *uac)
|
|
{
|
|
if (uac->next) uac->next->prev = uac->prev;
|
|
else euac_internals->last_uac = uac->prev;
|
|
if (uac->prev) uac->prev->next = uac->next;
|
|
else euac_internals->first_uac = uac->next;
|
|
}
|
|
|
|
void insert_uac_to_list(events_uac_t *uac)
|
|
{
|
|
if (euac_internals->last_uac) euac_internals->last_uac->next = uac;
|
|
else euac_internals->first_uac = uac;
|
|
uac->prev = euac_internals->last_uac;
|
|
uac->next = NULL;
|
|
euac_internals->last_uac = uac;
|
|
}
|
|
|
|
void free_events_uac(events_uac_t *uac)
|
|
{
|
|
/* TRACE("freeing EUAC %p\n", uac); */
|
|
|
|
str_free_content(&uac->headers);
|
|
str_free_content(&uac->local_uri);
|
|
str_free_content(&uac->remote_uri);
|
|
str_free_content(&uac->route);
|
|
str_free_content(&uac->outbound_proxy);
|
|
/* if the dialog is not freed we should free it */
|
|
if (uac->dialog) {
|
|
euac_internals->tmb.free_dlg(uac->dialog);
|
|
/* TRACE("freeing dialog for EUAC %p\n", uac); */
|
|
}
|
|
mem_free(uac);
|
|
}
|
|
|
|
events_uac_t *create_events_uac(str *remote_uri, str *local_uri, const str *events,
|
|
notify_callback_func cb, /* callback function for processing NOTIFY messages (parsing, ...) */
|
|
void *cbp, /* parameter for callback function */
|
|
const str *other_headers, str *route, str *outbound_proxy)
|
|
{
|
|
events_uac_t *uac;
|
|
dstring_t dstr;
|
|
int res = 0;
|
|
|
|
if ((!remote_uri) || (!local_uri)) {
|
|
ERR("invalid parameters\n");
|
|
return NULL;
|
|
}
|
|
|
|
uac = (events_uac_t*)mem_alloc(sizeof(*uac));
|
|
if (!uac) return NULL;
|
|
|
|
/* compose headers */
|
|
dstr_init(&dstr, 256);
|
|
dstr_append_zt(&dstr, "Event: ");
|
|
dstr_append_str(&dstr, events);
|
|
dstr_append_zt(&dstr, "\r\n");
|
|
|
|
/* required by RFC 3261 */
|
|
dstr_append_zt(&dstr, "Max-Forwards: 70\r\n");
|
|
/* needed for SUBSCRIBE via TCP - if not given the message is not parsed by ser!!! */
|
|
dstr_append_zt(&dstr, "Content-Length: 0\r\n");
|
|
|
|
if (other_headers) dstr_append_str(&dstr, other_headers);
|
|
/* should get Accpet headers as parameter too? */
|
|
if (dstr_get_str(&dstr, &uac->headers) != 0) {
|
|
ERR("can't generate headers (no mem)\n");
|
|
dstr_destroy(&dstr);
|
|
mem_free(uac);
|
|
return NULL;
|
|
}
|
|
dstr_destroy(&dstr);
|
|
|
|
uac->dialog = NULL;
|
|
init_reference_counter(euac_internals->rc_grp, &uac->ref_cntr); /* main reference - removed in "destroyed" status */
|
|
add_reference(&uac->ref_cntr); /* add reference for client */
|
|
/*TRACE("[%s]: added reference (%d)\n", "???",
|
|
uac->ref_cntr.cntr);*/
|
|
uac->status = euac_unconfirmed;
|
|
res = str_dup(&uac->local_uri, local_uri);
|
|
if (res == 0) res = str_dup(&uac->remote_uri, remote_uri);
|
|
else str_clear(&uac->remote_uri);
|
|
if (res == 0) res = str_dup(&uac->route, route);
|
|
else str_clear(&uac->route);
|
|
if (res == 0) res = str_dup(&uac->outbound_proxy, outbound_proxy);
|
|
else str_clear(&uac->outbound_proxy);
|
|
uac->timer_started = 0;
|
|
uac->cb = cb;
|
|
uac->cbp = cbp;
|
|
|
|
if (res != 0) {
|
|
ERR("can't duplicate parameters\n");
|
|
free_events_uac(uac);
|
|
return NULL;
|
|
}
|
|
|
|
lock_events_uac();
|
|
sprintf(uac->id, "%p:%x:%x", uac, (unsigned int)time(NULL), rand());
|
|
euac_internals->create_cnt++;
|
|
insert_uac_to_list(uac);
|
|
euac_start(uac);
|
|
unlock_events_uac();
|
|
|
|
return uac;
|
|
}
|
|
|
|
int destroy_events_uac(events_uac_t *uac)
|
|
{
|
|
if (!uac) {
|
|
ERR("BUG: destroying empty uac\n");
|
|
return -1;
|
|
}
|
|
|
|
lock_events_uac();
|
|
euac_internals->destroy_cnt++;
|
|
|
|
DBG("destroying uac %d from: %d\n",
|
|
euac_internals->destroy_cnt,
|
|
euac_internals->create_cnt);
|
|
|
|
/* do not receive any other status/service messages */
|
|
uac->cb = NULL;
|
|
uac->cbp = NULL;
|
|
|
|
/* remove our reference, after unlock can be
|
|
* the uac structure removed from memory by anybody !*/
|
|
if (!remove_euac_reference_nolock(uac)) {
|
|
euac_do_step(act_destroy, NULL, uac);
|
|
}
|
|
|
|
unlock_events_uac();
|
|
|
|
return 0;
|
|
}
|
|
|
|
int process_euac_notify(struct sip_msg* m)
|
|
{
|
|
events_uac_t *uac;
|
|
|
|
lock_events_uac();
|
|
uac = find_euac_nolock(m);
|
|
if (!uac) {
|
|
unlock_events_uac();
|
|
return -1;
|
|
}
|
|
euac_do_step(act_notify, m, uac);
|
|
unlock_events_uac();
|
|
return 0;
|
|
}
|
|
|
|
/* ---- INITIALIZATION/DESTRUCTION ---- */
|
|
|
|
int events_uac_init()
|
|
{
|
|
if (!euac_internals) return init_events_uac_internals();
|
|
else return 0;
|
|
}
|
|
|
|
void events_uac_destroy()
|
|
{
|
|
if (euac_internals) destroy_events_uac_internals();
|
|
}
|
|
|