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.
kamailio/obsolete/presence_b2b/events_uac.c

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();
}