re/src/sip/sip.c
2011-02-25 09:17:21 +00:00

185 lines
2.9 KiB
C

/**
* @file sip.c SIP Core
*
* Copyright (C) 2010 Creytiv.com
*/
#include <re_types.h>
#include <re_mem.h>
#include <re_mbuf.h>
#include <re_sa.h>
#include <re_list.h>
#include <re_hash.h>
#include <re_fmt.h>
#include <re_uri.h>
#include <re_sys.h>
#include <re_tmr.h>
#include <re_udp.h>
#include <re_stun.h>
#include <re_sip.h>
#include "sip.h"
static void destructor(void *arg)
{
struct sip *sip = arg;
if (sip->closing) {
sip->closing = false;
mem_ref(sip);
if (sip->exith)
sip->exith(sip->arg);
return;
}
sip_request_close(sip);
sip_request_close(sip);
hash_flush(sip->ht_ctrans);
mem_deref(sip->ht_ctrans);
hash_flush(sip->ht_strans);
mem_deref(sip->ht_strans);
hash_flush(sip->ht_conn);
mem_deref(sip->ht_conn);
hash_flush(sip->ht_udpconn);
mem_deref(sip->ht_udpconn);
list_flush(&sip->transpl);
list_flush(&sip->lsnrl);
mem_deref(sip->software);
mem_deref(sip->dnsc);
mem_deref(sip->stun);
}
static void lsnr_destructor(void *arg)
{
struct sip_lsnr *lsnr = arg;
if (lsnr->lsnrp)
*lsnr->lsnrp = NULL;
list_unlink(&lsnr->le);
}
int sip_alloc(struct sip **sipp, struct dnsc *dnsc, uint32_t ctsz,
uint32_t stsz, uint32_t tcsz, const char *software,
sip_exit_h *exith, void *arg)
{
struct sip *sip;
int err;
if (!sipp)
return EINVAL;
sip = mem_zalloc(sizeof(*sip), destructor);
if (!sip)
return ENOMEM;
err = sip_transp_init(sip, tcsz);
if (err)
goto out;
err = sip_ctrans_init(sip, ctsz);
if (err)
goto out;
err = sip_strans_init(sip, stsz);
if (err)
goto out;
err = hash_alloc(&sip->ht_udpconn, tcsz);
if (err)
goto out;
err = stun_alloc(&sip->stun, NULL, NULL, NULL);
if (err)
goto out;
if (software) {
err = str_dup(&sip->software, software);
if (err)
goto out;
}
sip->dnsc = mem_ref(dnsc);
sip->exith = exith;
sip->arg = arg;
out:
if (err)
mem_deref(sip);
else
*sipp = sip;
return err;
}
void sip_close(struct sip *sip, bool force)
{
if (!sip)
return;
if (force) {
sip_request_close(sip);
sip_request_close(sip);
}
else if (!sip->closing) {
sip->closing = true;
mem_deref(sip);
}
}
int sip_send(struct sip *sip, void *sock, enum sip_transp tp,
const struct sa *dst, struct mbuf *mb)
{
return sip_transp_send(NULL, sip, sock, tp, dst, mb, NULL, NULL);
}
int sip_listen(struct sip_lsnr **lsnrp, struct sip *sip, bool req,
sip_msg_h *msgh, void *arg)
{
struct sip_lsnr *lsnr;
if (!sip || !msgh)
return EINVAL;
lsnr = mem_zalloc(sizeof(*lsnr), lsnr_destructor);
if (!lsnr)
return ENOMEM;
list_append(&sip->lsnrl, &lsnr->le, lsnr);
lsnr->msgh = msgh;
lsnr->arg = arg;
lsnr->req = req;
if (lsnrp) {
lsnr->lsnrp = lsnrp;
*lsnrp = lsnr;
}
return 0;
}
int sip_debug(struct re_printf *pf, const struct sip *sip)
{
int err;
if (!sip)
return 0;
err = sip_transp_debug(pf, sip);
err |= sip_ctrans_debug(pf, sip);
err |= sip_strans_debug(pf, sip);
return err;
}