예제 #1
0
파일: call.c 프로젝트: sealaunch/baresip
int call_connect(struct call *call, const struct pl *paddr)
{
	struct sip_addr addr;
	int err;

	if (!call || !paddr)
		return EINVAL;

	info("call: connecting to '%r'..\n", paddr);

	call->outgoing = true;

	/* if the peer-address is a full SIP address then we need
	 * to parse it and extract the SIP uri part.
	 */
	if (0 == sip_addr_decode(&addr, paddr) && addr.dname.p) {
		err = pl_strdup(&call->peer_uri, &addr.auri);
	}
	else {
		err = pl_strdup(&call->peer_uri, paddr);
	}
	if (err)
		return err;

	set_state(call, STATE_OUTGOING);

	/* If we are using asyncronous medianat like STUN/TURN, then
	 * wait until completed before sending the INVITE */
	if (!call->acc->mnat)
		err = send_invite(call);

	return err;
}
예제 #2
0
int sdp_media_radd(struct sdp_media **mp, struct sdp_session *sess,
                   const struct pl *name, const struct pl *proto)
{
    struct sdp_media *m;
    int err;

    if (!mp || !sess || !name || !proto)
        return EINVAL;

    err = media_alloc(&m, &sess->medial);
    if (err)
        return err;

    m->disabled = true;

    err  = pl_strdup(&m->name, name);
    err |= pl_strdup(&m->proto, proto);

    if (err)
        mem_deref(m);
    else
        *mp = m;

    return err;
}
예제 #3
0
파일: http.c 프로젝트: muromec/rehttp
void http_init(struct httpc *app, struct request **rpp, char *str_uri)
{
    int ok;
    struct request *request;
    struct pl pl_uri;
    struct url url;

    *rpp = NULL;

    pl_uri.p = NULL;
    str_dup((char**)&pl_uri.p, str_uri);
    pl_uri.l = strlen(str_uri);

    ok = url_decode(&url, &pl_uri);

    if(ok!=0)
        goto err_uri;

    request = mem_zalloc(sizeof(*request), destructor);
    ok = hash_alloc(&request->hdrht, HDR_HASH_SIZE);
    request->err_h = dummy_err;
    request->done_h = http_done;
    request->post = NULL;
    request->form = 0;
    request->www_auth.p = NULL;
    request->www_auth.l = 0;
    request->auth = NULL;

    request->retry = 0;

    pl_strdup(&request->host, &url.host);
    pl_strdup(&request->path, &url.path);
    request->secure = !pl_strcmp(&url.scheme, "https");
    memcpy(&request->meth, "GET", 4);
    request->meth[4] = 0;

    if(url.port)
	request->port = url.port;
    else
        request->port = request->secure ? 443 : 80;

    DEBUG_INFO("secure: %d port %d\n", request->secure, request->port);
    sa_init(&request->dest, AF_INET);
    ok = sa_set_str(&request->dest, request->host, request->port);

    request->state = ok ? START : RESOLVED;

    request->app = app;
    *rpp = request;

err_uri:
    if(pl_uri.p)
        mem_deref((void*)pl_uri.p);

    return;
}
예제 #4
0
파일: cand.c 프로젝트: Issic47/libre
int icem_rcand_add(struct icem *icem, enum cand_type type, uint8_t compid,
		   uint32_t prio, const struct sa *addr,
		   const struct sa *rel_addr, const struct pl *foundation)
{
	struct cand *rcand;
	int err;

	if (!icem || !foundation)
		return EINVAL;

	rcand = mem_zalloc(sizeof(*rcand), cand_destructor);
	if (!rcand)
		return ENOMEM;

	list_append(&icem->rcandl, &rcand->le, rcand);

	rcand->type   = type;
	rcand->compid = compid;
	rcand->prio   = prio;

	sa_cpy(&rcand->addr, addr);
	sa_cpy(&rcand->rel, rel_addr);

	err = pl_strdup(&rcand->foundation, foundation);

	if (err)
		mem_deref(rcand);

	return err;
}
예제 #5
0
int sdp_format_radd(struct sdp_media *m, const struct pl *id)
{
	struct sdp_format *fmt;
	int err;

	if (!m || !id)
		return EINVAL;

	fmt = mem_zalloc(sizeof(*fmt), destructor);
	if (!fmt)
		return ENOMEM;

	list_append(&m->rfmtl, &fmt->le, fmt);

	err = pl_strdup(&fmt->id, id);
	if (err)
		goto out;

	fmt->pt = atoi(fmt->id);

 out:
	if (err)
		mem_deref(fmt);

	return err;
}
예제 #6
0
static bool sdp_attr_handler(const char *name, const char *value, void *arg)
{
	struct menc_st *st = arg;
	struct crypto c;
	(void)name;

	if (sdes_decode_crypto(&c, value))
		return false;

	if (0 != pl_strcmp(&c.key_method, "inline"))
		return false;

	if (!cryptosuite_issupported(&c.suite))
		return false;

	st->crypto_suite = mem_deref(st->crypto_suite);
	pl_strdup(&st->crypto_suite, &c.suite);

	if (start_crypto(st, &c.key_info))
		return false;

	sdp_enc(st, st->sdpm, c.tag, st->crypto_suite);

	return true;
}
예제 #7
0
파일: message.c 프로젝트: AmesianX/baresip
/**
 * Send SIP instant MESSAGE to a peer
 *
 * @param ua    User-Agent object
 * @param peer  Peer SIP Address
 * @param msg   Message to send
 *
 * @return 0 if success, otherwise errorcode
 */
int message_send(struct ua *ua, const char *peer, const char *msg)
{
	struct sip_addr addr;
	struct pl pl;
	char *uri = NULL;
	int err = 0;

	if (!ua || !peer || !msg)
		return EINVAL;

	pl_set_str(&pl, peer);

	err = sip_addr_decode(&addr, &pl);
	if (err)
		return err;

	err = pl_strdup(&uri, &addr.auri);
	if (err)
		return err;

	err = sip_req_send(ua, "MESSAGE", uri, resp_handler, ua,
			   "Accept: text/plain\r\n"
			   "Content-Type: text/plain\r\n"
			   "Content-Length: %zu\r\n"
			   "\r\n%s",
			   str_len(msg), msg);

	mem_deref(uri);

	return err;
}
예제 #8
0
static int attr_decode_rtpmap(struct sdp_media *m, const struct pl *pl)
{
	struct pl id, name, srate, ch;
	struct sdp_format *fmt;
	int err;

	if (!m)
		return 0;

	if (re_regex(pl->p, pl->l, "[^ ]+ [^/]+/[0-9]+[/]*[^]*",
		     &id, &name, &srate, NULL, &ch))
		return EBADMSG;

	fmt = sdp_format_find(&m->rfmtl, &id);
	if (!fmt)
		return 0;

	fmt->name = mem_deref(fmt->name);

	err = pl_strdup(&fmt->name, &name);
	if (err)
		return err;

	fmt->srate = pl_u32(&srate);
	fmt->ch = ch.l ? pl_u32(&ch) : 1;

	return 0;
}
예제 #9
0
파일: contact.c 프로젝트: QXIP/baresip
/**
 * Add a contact
 *
 * @param contactp Pointer to allocated contact (optional)
 * @param addr     Contact in SIP address format
 *
 * @return 0 if success, otherwise errorcode
 */
int contact_add(struct contact **contactp, const struct pl *addr)
{
	struct contact *c;
	struct pl pl;
	int err;

	c = mem_zalloc(sizeof(*c), destructor);
	if (!c)
		return ENOMEM;

	err = pl_strdup(&c->buf, addr);
	if (err)
		goto out;

	pl_set_str(&pl, c->buf);

	err = sip_addr_decode(&c->addr, &pl);
	if (err) {
		warning("contact: decode error '%r'\n", addr);
		goto out;
	}

	c->status = PRESENCE_UNKNOWN;

	list_append(&cl, &c->le, c);

 out:
	if (err)
		mem_deref(c);
	else if (contactp)
		*contactp = c;

	return err;
}
예제 #10
0
파일: cmd.c 프로젝트: czarkoff/baresip
int cmd_process_long(struct commands *commands, const char *str, size_t len,
		     struct re_printf *pf_resp, void *data)
{
	struct cmd_arg arg;
	const struct cmd *cmd_long;
	char *name = NULL, *prm = NULL;
	struct pl pl_name, pl_prm;
	int err;

	if (!str || !len)
		return EINVAL;

	memset(&arg, 0, sizeof(arg));

	err = re_regex(str, len, "[^ ]+[ ]*[~]*", &pl_name, NULL, &pl_prm);
	if (err) {
		return err;
	}

	err = pl_strdup(&name, &pl_name);
	if (pl_isset(&pl_prm))
		err |= pl_strdup(&prm, &pl_prm);
	if (err)
		goto out;

	cmd_long = cmd_find_long(commands, name);
	if (cmd_long) {

		arg.key      = LONG_PREFIX;
		arg.prm      = prm;
		arg.complete = true;
		arg.data     = data;

		if (cmd_long->h)
			err = cmd_long->h(pf_resp, &arg);
	}
	else {
		err = re_hprintf(pf_resp, "command not found (%s)\n", name);
	}

 out:
	mem_deref(name);
	mem_deref(prm);

	return err;
}
예제 #11
0
파일: ua.c 프로젝트: pasichnichenko/baresip
/**
 * Set Public GRUU of a User-Agent (UA)
 *
 * @param ua   User-Agent
 * @param pval Public GRUU
 */
void ua_pub_gruu_set(struct ua *ua, const struct pl *pval)
{
	if (!ua)
		return;

	ua->pub_gruu = mem_deref(ua->pub_gruu);
	(void)pl_strdup(&ua->pub_gruu, pval);
}
예제 #12
0
파일: contact.c 프로젝트: GGGO/baresip
/**
 * Add a contact
 *
 * @param contacts Contacts container
 * @param contactp Pointer to allocated contact (optional)
 * @param addr     Contact in SIP address format
 *
 * @return 0 if success, otherwise errorcode
 */
int contact_add(struct contacts *contacts,
		struct contact **contactp, const struct pl *addr)
{
	struct contact *c;
	struct pl pl;
	int err;

	if (!contacts)
		return EINVAL;

	c = mem_zalloc(sizeof(*c), destructor);
	if (!c)
		return ENOMEM;

	err = pl_strdup(&c->buf, addr);
	if (err)
		goto out;

	pl_set_str(&pl, c->buf);

	err = sip_addr_decode(&c->addr, &pl);
	if (err) {
		warning("contact: decode error '%r'\n", addr);
		goto out;
	}

	if (0 == msg_param_decode(&c->addr.params, "access", &pl)) {

		if (0 == pl_strcasecmp(&pl, "block")) {
			c->access = ACCESS_BLOCK;
		}
		else if (0 == pl_strcasecmp(&pl, "allow")) {
			c->access = ACCESS_ALLOW;
		}
		else {
			warning("contact: unknown 'access=%r' for '%r'\n",
				&pl, addr);
			err = EINVAL;
			goto out;
		}
	}
	else
		c->access = ACCESS_UNKNOWN;

	c->status = PRESENCE_UNKNOWN;

	list_append(&contacts->cl, &c->le, c);
	hash_append(contacts->cht, hash_joaat_pl(&c->addr.auri), &c->he, c);

 out:
	if (err)
		mem_deref(c);
	else if (contactp)
		*contactp = c;

	return err;
}
예제 #13
0
static int str_ldup(char **dst, const char *src, int len)
{
	struct pl pl;

	pl.p = src;
	pl.l = len < 0 ? str_len(src) : (size_t)len;

	return pl_strdup(dst, &pl);
}
예제 #14
0
int rst_alloc(struct rst **rstp, const char *dev)
{
	struct pl host, port, path;
	struct rst *rst;
	int err;

	if (!rstp || !dev)
		return EINVAL;

	if (re_regex(dev, strlen(dev), "http://[^:/]+[:]*[0-9]*[^]+",
		     &host, NULL, &port, &path)) {
		re_printf("rst: bad http url: %s\n", dev);
		return EBADMSG;
	}

	rst = mem_zalloc(sizeof(*rst), destructor);
	if (!rst)
		return ENOMEM;

	rst->id = "rst";

	err = pl_strdup(&rst->host, &host);
	if (err)
		goto out;

	err = pl_strdup(&rst->path, &path);
	if (err)
		goto out;

	rst->port = pl_u32(&port);
	rst->port = rst->port ? rst->port : 80;

	err = rst_connect(rst);
	if (err)
		goto out;

 out:
	if (err)
		mem_deref(rst);
	else
		*rstp = rst;

	return err;
}
예제 #15
0
void tcsipcall_send(struct tcsipcall*call)
{
    struct mbuf *mb;
    int err;

    char *to_uri, *to_user;
    char *from_uri, *from_name;

    pl_strdup(&to_uri, &call->remote->auri);
    pl_strdup(&to_user, &call->remote->uri.user);

    pl_strdup(&from_uri, &call->local->auri);
    if(call->local->dname.l)
        pl_strdup(&from_name, &call->local->dname);
    else
	pl_strdup(&from_name, &call->local->uri.user);

    char date[100];
    struct tm *tv;
    tv = gmtime(&call->tv.tv_sec);

    strftime(date, sizeof(date), "Date: %a, %d %b %Y %H:%M:%S GMT\r\n", tv);
    tcmedia_get_offer(call->media, &mb);

    err = sipsess_connect(&call->sess, call->uac->sock, to_uri, from_name,
                          from_uri, to_user,
                          NULL, 0, "application/sdp", mb,
                          NULL, call, false,
                          offer_handler, answer_handler,
                          progress_handler, establish_handler,
                          NULL, NULL, close_handler, call, date);
    mem_deref(mb); /* free SDP buffer */

    if(err)
	call->cstate |= CSTATE_ERR;
    else
        call->cstate |= CSTATE_OUT_RING;

    mem_deref(to_uri);
    mem_deref(to_user);
    mem_deref(from_uri);
    mem_deref(from_name);

}
예제 #16
0
파일: http.c 프로젝트: muromec/rehttp
bool hdr_fetch(struct le *le, void *arg)
{
    int err = 0;
    struct http_hdr *hdr = le->data;
    struct hdr_fetch *op = arg;

    if(pl_strcasecmp(&hdr->name, op->name) == 0) {
        err = pl_strdup(op->val, &hdr->val);
        return true;
    }

    return false;
}
예제 #17
0
파일: publisher.c 프로젝트: GGGO/baresip
static void response_handler(int err, const struct sip_msg *msg, void *arg)
{
	struct publisher *pub = arg;
	const struct sip_hdr *etag_hdr;

	if (err)
		return;

	if (msg->scode < 200) {
		return;
	}

	if (msg->scode < 300) {

		if (pub->expires == 0)
			return;

		etag_hdr = sip_msg_xhdr(msg, "SIP-ETag");
		if (etag_hdr) {
			mem_deref(pub->etag);
			pl_strdup(&(pub->etag), &(etag_hdr->val));
			pub->refresh = 1;
			tmr_start(&pub->tmr, pub->expires * 900,
				  tmr_handler, pub);
		}
		else {
			warning("%s: publisher got 200 OK without etag\n",
				ua_aor(pub->ua));
		}
	}
	else if (msg->scode == 412) {

		mem_deref(pub->etag);
		pub->etag = NULL;
		pub->refresh = 0;
		publish(pub);

	}
	else {
		warning("%s: publisher got error response %u %r\n",
			ua_aor(pub->ua), msg->scode, &msg->reason);
	}

	return;
}
예제 #18
0
void tcsipcall_accept(struct tcsipcall*call)
{

    int err;
    char *my_user;
    pl_strdup(&my_user, &call->local->uri.user);

    err = sipsess_accept(&call->sess, call->uac->sock, call->msg, 180, "Ringing",
                         my_user, "application/sdp", NULL,
                         NULL, call, false,
                         offer_handler, answer_handler,
                         establish_handler, NULL, NULL,
                         close_handler, call, NULL);
    if(err)
        call->cstate |= CSTATE_ERR;

    mem_deref(my_user);
}
예제 #19
0
static int attr_decode_fmtp(struct sdp_media *m, const struct pl *pl)
{
	struct sdp_format *fmt;
	struct pl id, params;

	if (!m)
		return 0;

	if (re_regex(pl->p, pl->l, "[^ ]+ [^]*", &id, &params))
		return EBADMSG;

	fmt = sdp_format_find(&m->rfmtl, &id);
	if (!fmt)
		return 0;

	fmt->params = mem_deref(fmt->params);

	return pl_strdup(&fmt->params, &params);
}
예제 #20
0
파일: dialog.c 프로젝트: soramimi/qSIP
/**
 * Update an existing SIP Dialog from a SIP Message
 *
 * @param dlg SIP Dialog to update
 * @param msg SIP Message
 *
 * @return 0 if success, otherwise errorcode
 */
int sip_dialog_update(struct sip_dialog *dlg, const struct sip_msg *msg)
{
	const struct sip_hdr *contact;
	struct sip_addr addr;
	char *uri;
	int err;

	if (!dlg || !msg)
		return EINVAL;

	contact = sip_msg_hdr(msg, SIP_HDR_CONTACT);
	if (!contact)
		return EBADMSG;

	if (sip_addr_decode(&addr, &contact->val))
		return EBADMSG;

	err = pl_strdup(&uri, &addr.auri);
	if (err)
		return err;

	if (dlg->route.scheme.p == dlg->uri) {

		struct uri tmp;
		struct pl pl;

		pl_set_str(&pl, uri);
		err = uri_decode(&tmp, &pl);
		if (err)
			goto out;

		dlg->route = tmp;
	}

	mem_deref(dlg->uri);
	dlg->uri = mem_ref(uri);

 out:
	mem_deref(uri);

	return err;
}
예제 #21
0
int version_cmp(char *have, const struct pl *want_pl) {
    char *hdr = NULL, *want = NULL;
    unsigned int uhave, uwant;

    if(pl_strdup(&hdr, want_pl)) {
        return -1;
    }

    if(strncmp(hdr, "Version=", sizeof("Version=")-1)) {
        return -1;
    }

    want = hdr + sizeof("Version=")-1;

    uhave = str_ver(have);
    uwant = str_ver(want);

out:
    mem_deref(hdr);

    return uhave - uwant;
};
예제 #22
0
파일: call.c 프로젝트: sealaunch/baresip
int call_accept(struct call *call, struct sipsess_sock *sess_sock,
		const struct sip_msg *msg)
{
	bool got_offer;
	int err;

	if (!call || !msg)
		return EINVAL;

	call->outgoing = false;

	got_offer = (mbuf_get_left(msg->mb) > 0);

	err = pl_strdup(&call->peer_uri, &msg->from.auri);
	if (err)
		return err;

	if (pl_isset(&msg->from.dname)) {
		err = pl_strdup(&call->peer_name, &msg->from.dname);
		if (err)
			return err;
	}

	if (got_offer) {
		struct sdp_media *m;
		const struct sa *raddr;

		err = sdp_decode(call->sdp, msg->mb, true);
		if (err)
			return err;

		call->got_offer = true;

		/*
		 * Each media description in the SDP answer MUST
		 * use the same network type as the corresponding
		 * media description in the offer.
		 *
		 * See RFC 6157
		 */
		m = stream_sdpmedia(audio_strm(call->audio));
		raddr = sdp_media_raddr(m);

		if (sa_af(raddr) != call->af) {
			info("call: incompatible address-family"
			     " (local=%s, remote=%s)\n",
			     net_af2name(call->af),
			     net_af2name(sa_af(raddr)));

			sip_treply(NULL, uag_sip(), msg,
				   488, "Not Acceptable Here");

			call_event_handler(call, CALL_EVENT_CLOSED,
					   "Wrong address family");
			return 0;
		}

		/* Check if we have any common audio codecs, after
		 * the SDP offer has been parsed
		 */
		if (!have_common_audio_codecs(call)) {
			info("call: no common audio codecs - rejected\n");

			sip_treply(NULL, uag_sip(), msg,
				   488, "Not Acceptable Here");

			call_event_handler(call, CALL_EVENT_CLOSED,
					   "No audio codecs");

			return 0;
		}
	}

	err = sipsess_accept(&call->sess, sess_sock, msg, 180, "Ringing",
			     ua_cuser(call->ua), "application/sdp", NULL,
			     auth_handler, call->acc, true,
			     sipsess_offer_handler, sipsess_answer_handler,
			     sipsess_estab_handler, sipsess_info_handler,
			     sipsess_refer_handler, sipsess_close_handler,
			     call, "Allow: %s\r\n", uag_allowed_methods());
	if (err) {
		warning("call: sipsess_accept: %m\n", err);
		return err;
	}

	set_state(call, STATE_INCOMING);

	/* New call */
	tmr_start(&call->tmr_inv, LOCAL_TIMEOUT*1000, invite_timeout, call);

	if (!call->acc->mnat)
		call_event_handler(call, CALL_EVENT_INCOMING, call->peer_uri);

	return err;
}
예제 #23
0
/**
 * Send a SIP request
 *
 * @param reqp     Pointer to allocated SIP request object
 * @param sip      SIP Stack
 * @param stateful Stateful client transaction
 * @param met      SIP Method string
 * @param metl     Length of SIP Method string
 * @param uri      Request URI
 * @param uril     Length of Request URI string
 * @param route    Next hop route URI
 * @param mb       Buffer containing SIP request
 * @param sendh    Send handler
 * @param resph    Response handler
 * @param arg      Handler argument
 *
 * @return 0 if success, otherwise errorcode
 */
int sip_request(struct sip_request **reqp, struct sip *sip, bool stateful,
		const char *met, int metl, const char *uri, int uril,
		const struct uri *route, struct mbuf *mb,
		sip_send_h *sendh, sip_resp_h *resph, void *arg)
{
	struct sip_request *req;
	struct sa dst;
	struct pl pl;
	int err;

	if (!sip || !met || !uri || !route || !mb)
		return EINVAL;

	if (pl_strcasecmp(&route->scheme, "sip"))
		return ENOSYS;

	req = mem_zalloc(sizeof(*req), destructor);
	if (!req)
		return ENOMEM;

	list_append(&sip->reql, &req->le, req);

	err = str_ldup(&req->met, met, metl);
	if (err)
		goto out;

	err = str_ldup(&req->uri, uri, uril);
	if (err)
		goto out;

	if (sip_param_decode(&route->params, "maddr", &pl))
		pl = route->host;

	err = pl_strdup(&req->host, &pl);
	if (err)
		goto out;

	req->stateful = stateful;
	req->mb    = mem_ref(mb);
	req->sip   = sip;
	req->sendh = sendh;
	req->resph = resph;
	req->arg   = arg;

	if (!sip_param_decode(&route->params, "transport", &pl)) {

		if (!pl_strcasecmp(&pl, "udp"))
			req->tp = SIP_TRANSP_UDP;
		else if (!pl_strcasecmp(&pl, "tcp"))
			req->tp = SIP_TRANSP_TCP;
		else if (!pl_strcasecmp(&pl, "tls"))
			req->tp = SIP_TRANSP_TLS;
		else {
			err = EPROTONOSUPPORT;
			goto out;
		}

		if (!sip_transp_supported(sip, req->tp, AF_UNSPEC)) {
			err = EPROTONOSUPPORT;
			goto out;
		}

		req->tp_selected = true;
	}
	else {
		req->tp = SIP_TRANSP_NONE;
		if (!transp_next(sip, &req->tp)) {
			err = EPROTONOSUPPORT;
			goto out;
		}

		req->tp_selected = false;
	}

	if (!sa_set_str(&dst, req->host,
			sip_transp_port(req->tp, route->port))) {

		err = request(req, req->tp, &dst);
		if (!req->stateful) {
			mem_deref(req);
			return err;
		}
	}
	else if (route->port) {

		req->port = sip_transp_port(req->tp, route->port);
		err = addr_lookup(req, req->host);
	}
	else if (req->tp_selected) {

		err = srv_lookup(req, req->host);
	}
	else {
	        err = dnsc_query(&req->dnsq, sip->dnsc, req->host,
				 DNS_TYPE_NAPTR, DNS_CLASS_IN, true,
				 naptr_handler, req);
	}

 out:
	if (err)
		mem_deref(req);
	else if (reqp) {
		req->reqp = reqp;
		*reqp = req;
	}

	return err;
}
예제 #24
0
int sipevent_accept(struct sipnot **notp, struct sipevent_sock *sock,
		    const struct sip_msg *msg, struct sip_dialog *dlg,
		    const struct sipevent_event *event,
		    uint16_t scode, const char *reason, uint32_t expires_min,
		    uint32_t expires_dfl, uint32_t expires_max,
		    const char *cuser, const char *ctype,
		    sip_auth_h *authh, void *aarg, bool aref,
		    sipnot_close_h *closeh, void *arg, const char *fmt, ...)
{
	struct sipnot *not;
	uint32_t expires;
	int err;

	if (!notp || !sock || !msg || !scode || !reason || !expires_dfl ||
	    !expires_max || !cuser || !ctype || expires_dfl < expires_min)
		return EINVAL;

	not = mem_zalloc(sizeof(*not), destructor);
	if (!not)
		return ENOMEM;

	if (!pl_strcmp(&msg->met, "REFER")) {

		err = str_dup(&not->event, "refer");
		if (err)
			goto out;

		err = re_sdprintf(&not->id, "%u", msg->cseq.num);
		if (err)
			goto out;
	}
	else {
		if (!event) {
			err = EINVAL;
			goto out;
		}

		err = pl_strdup(&not->event, &event->event);
		if (err)
			goto out;

		if (pl_isset(&event->id)) {

			err = pl_strdup(&not->id, &event->id);
			if (err)
				goto out;
		}
	}

	if (dlg) {
		not->dlg = mem_ref(dlg);
	}
	else {
		err = sip_dialog_accept(&not->dlg, msg);
		if (err)
			goto out;
	}

	hash_append(sock->ht_not,
		    hash_joaat_str(sip_dialog_callid(not->dlg)),
		    &not->he, not);

	err = sip_auth_alloc(&not->auth, authh, aarg, aref);
	if (err)
		goto out;

	err = str_dup(&not->cuser, cuser);
	if (err)
		goto out;

	err = str_dup(&not->ctype, ctype);
	if (err)
		goto out;

	if (fmt) {
		va_list ap;

		va_start(ap, fmt);
		err = re_vsdprintf(&not->hdrs, fmt, ap);
		va_end(ap);
		if (err)
			goto out;
	}

	not->expires_min = expires_min;
	not->expires_dfl = expires_dfl;
	not->expires_max = expires_max;
	not->substate = SIPEVENT_PENDING;
	not->sock   = mem_ref(sock);
	not->sip    = mem_ref(sock->sip);
	not->closeh = closeh ? closeh : internal_close_handler;
	not->arg    = arg;

	if (pl_isset(&msg->expires))
		expires = pl_u32(&msg->expires);
	else
		expires = not->expires_dfl;

	sipnot_refresh(not, expires);

	err = sipnot_reply(not, msg, scode, reason);
	if (err)
		goto out;

	not->subscribed = true;

 out:
	if (err)
		mem_deref(not);
	else
		*notp = not;

	return err;
}
예제 #25
0
파일: dialog.c 프로젝트: soramimi/qSIP
/**
 * Initialize a SIP Dialog from an incoming SIP Message
 *
 * @param dlg SIP Dialog to initialize
 * @param msg SIP Message
 *
 * @return 0 if success, otherwise errorcode
 */
int sip_dialog_create(struct sip_dialog *dlg, const struct sip_msg *msg)
{
	char *uri = NULL, *rtag = NULL;
	const struct sip_hdr *contact;
	struct route_enc renc;
	struct sip_addr addr;
	struct pl pl;
	int err;

	if (!dlg || dlg->rtag || !dlg->cpos || !msg)
		return EINVAL;

	contact = sip_msg_hdr(msg, SIP_HDR_CONTACT);

	if (!contact)
		return EBADMSG;

	if (sip_addr_decode(&addr, &contact->val))
		return EBADMSG;

	renc.mb = mbuf_alloc(512);
	if (!renc.mb)
		return ENOMEM;

	err = pl_strdup(&uri, &addr.auri);
	if (err)
		goto out;

	err = pl_strdup(&rtag, msg->req ? &msg->from.tag : &msg->to.tag);
	if (err)
		goto out;

	renc.end = 0;

	err |= sip_msg_hdr_apply(msg, msg->req, SIP_HDR_RECORD_ROUTE,
				 record_route_handler, &renc) ? ENOMEM : 0;
	err |= mbuf_printf(renc.mb, "To: %r\r\n",
			   msg->req ? &msg->from.val : &msg->to.val);

	dlg->mb->pos = dlg->cpos;
	err |= mbuf_write_mem(renc.mb, mbuf_buf(dlg->mb),
			      mbuf_get_left(dlg->mb));
	dlg->mb->pos = 0;

	if (err)
		goto out;

	renc.mb->pos = 0;

	if (renc.end) {
		pl.p = (const char *)mbuf_buf(renc.mb) + ROUTE_OFFSET;
		pl.l = renc.end - ROUTE_OFFSET;
		err = sip_addr_decode(&addr, &pl);
		if (err)
			goto out;

		dlg->route = addr.uri;
	}
	else {
		struct uri tmp;

		pl_set_str(&pl, uri);
		err = uri_decode(&tmp, &pl);
		if (err)
			goto out;

		dlg->route = tmp;
	}

	mem_deref(dlg->mb);
	mem_deref(dlg->uri);

	dlg->mb   = mem_ref(renc.mb);
	dlg->rtag = mem_ref(rtag);
	dlg->uri  = mem_ref(uri);
	dlg->rseq = msg->req ? msg->cseq.num : 0;
	dlg->cpos = 0;

 out:
	mem_deref(renc.mb);
	mem_deref(rtag);
	mem_deref(uri);

	return err;
}
예제 #26
0
파일: dialog.c 프로젝트: soramimi/qSIP
/**
 * Fork a SIP Dialog from an incoming SIP Message
 *
 * @param dlgp Pointer to allocated SIP Dialog
 * @param odlg Original SIP Dialog
 * @param msg  SIP Message
 *
 * @return 0 if success, otherwise errorcode
 */
int sip_dialog_fork(struct sip_dialog **dlgp, struct sip_dialog *odlg,
		    const struct sip_msg *msg)
{
	const struct sip_hdr *contact;
	struct sip_dialog *dlg;
	struct route_enc renc;
	struct sip_addr addr;
	struct pl pl;
	int err;

	if (!dlgp || !odlg || !odlg->cpos || !msg)
		return EINVAL;

	contact = sip_msg_hdr(msg, SIP_HDR_CONTACT);

	if (!contact || !msg->callid.p)
		return EBADMSG;

	if (sip_addr_decode(&addr, &contact->val))
		return EBADMSG;

	dlg = mem_zalloc(sizeof(*dlg), destructor);
	if (!dlg)
		return ENOMEM;

	dlg->callid = mem_ref(odlg->callid);
	dlg->ltag   = mem_ref(odlg->ltag);
	dlg->lseq   = odlg->lseq;
	dlg->rseq   = msg->req ? msg->cseq.num : 0;

	err = pl_strdup(&dlg->uri, &addr.auri);
	if (err)
		goto out;

	err = pl_strdup(&dlg->rtag, msg->req ? &msg->from.tag : &msg->to.tag);
	if (err)
		goto out;

	dlg->mb = mbuf_alloc(512);
	if (!dlg->mb) {
		err = ENOMEM;
		goto out;
	}

	renc.mb  = dlg->mb;
	renc.end = 0;

	err |= sip_msg_hdr_apply(msg, msg->req, SIP_HDR_RECORD_ROUTE,
				 record_route_handler, &renc) ? ENOMEM : 0;
	err |= mbuf_printf(dlg->mb, "To: %r\r\n",
			   msg->req ? &msg->from.val : &msg->to.val);

	odlg->mb->pos = odlg->cpos;
	err |= mbuf_write_mem(dlg->mb, mbuf_buf(odlg->mb),
			      mbuf_get_left(odlg->mb));
	odlg->mb->pos = 0;

	if (err)
		goto out;

	dlg->mb->pos = 0;

	if (renc.end) {
		pl.p = (const char *)mbuf_buf(dlg->mb) + ROUTE_OFFSET;
		pl.l = renc.end - ROUTE_OFFSET;
		err = sip_addr_decode(&addr, &pl);
		dlg->route = addr.uri;
	}
	else {
		pl_set_str(&pl, dlg->uri);
		err = uri_decode(&dlg->route, &pl);
	}

 out:
	if (err)
		mem_deref(dlg);
	else
		*dlgp = dlg;

	return err;
}
예제 #27
0
파일: location.c 프로젝트: clehner/baresip
int location_update(struct list *locl, const struct sip_msg *msg,
                    const struct sip_addr *contact, uint32_t expires)
{
    struct location *loc, *loc_new = NULL;
    struct loctmp *tmp;
    struct pl pl;
    int err;

    if (!locl || !msg || !contact)
        return EINVAL;

    loc = list_ledata(list_apply(locl, true, cmp_handler,
                                 (void *)&contact->uri));
    if (!loc) {
        if (expires == 0)
            return 0;

        loc = loc_new = mem_zalloc(sizeof(*loc), destructor_location);
        if (!loc)
            return ENOMEM;

        list_append(locl, &loc->le, loc);
    }
    else {
        if (!pl_strcmp(&msg->callid, loc->callid) &&
                msg->cseq.num <= loc->cseq)
            return EPROTO;

        if (expires == 0) {
            loc->rm = true;
            return 0;
        }
    }

    tmp = mem_zalloc(sizeof(*tmp), destructor_loctmp);
    if (!tmp) {
        err = ENOMEM;
        goto out;
    }

    err = pl_strdup(&tmp->uri, &contact->auri);
    if (err)
        goto out;

    pl_set_str(&pl, tmp->uri);

    if (uri_decode(&tmp->duri, &pl)) {
        err = EBADMSG;
        goto out;
    }

    err = pl_strdup(&tmp->callid, &msg->callid);
    if (err)
        goto out;


    if (!msg_param_decode(&contact->params, "q", &pl))
        tmp->q = pl_float(&pl);
    else
        tmp->q = 1;

    tmp->cseq    = msg->cseq.num;
    tmp->expires = expires;
    tmp->src     = msg->src;

out:
    if (err) {
        mem_deref(loc_new);
        mem_deref(tmp);
    }
    else {
        mem_deref(loc->tmp);
        loc->tmp = tmp;
    }

    return err;
}
예제 #28
0
static void recv_handler(struct mbuf *mb, void *arg)
{
	struct rst *rst = arg;
	size_t n;

	if (!rst->head_recv) {

		struct pl hdr, name, metaint, eoh;

		if (rst->mb) {
			size_t pos;
			int err;

			pos = rst->mb->pos;

			rst->mb->pos = rst->mb->end;

			err = mbuf_write_mem(rst->mb, mbuf_buf(mb),
					     mbuf_get_left(mb));
			if (err) {
				re_printf("rst: buffer write error: %m\n",
					  err);
				rst->tc = mem_deref(rst->tc);
				tmr_start(&rst->tmr, RETRY_WAIT,
					  reconnect, rst);
				return;
			}

			rst->mb->pos = pos;
		}
		else {
			rst->mb = mem_ref(mb);
		}

		if (re_regex((const char *)mbuf_buf(rst->mb),
			     mbuf_get_left(rst->mb),
			     "[^\r\n]1\r\n\r\n", &eoh))
			return;

		rst->head_recv = true;

		hdr.p = (const char *)mbuf_buf(rst->mb);
		hdr.l = eoh.p + 5 - hdr.p;

		if (!re_regex(hdr.p, hdr.l, "icy-name:[ \t]*[^\r\n]+\r\n",
			      NULL, &name))
			(void)pl_strdup(&rst->name, &name);

		if (!re_regex(hdr.p, hdr.l, "icy-metaint:[ \t]*[0-9]+\r\n",
			      NULL, &metaint))
			rst->metaint = pl_u32(&metaint);

		if (rst->metaint == 0) {
			re_printf("rst: icy meta interval not available\n");
			rst->tc = mem_deref(rst->tc);
			tmr_start(&rst->tmr, RETRY_WAIT, reconnect, rst);
			return;
		}

		rst_video_update(rst->vidsrc_st, rst->name, NULL);

		rst->mb->pos += hdr.l;

		re_printf("rst: name='%s' metaint=%zu\n",
			  rst->name, rst->metaint);

		if (rst->mb->pos >= rst->mb->end)
			return;

		mb = rst->mb;
	}

	while (mb->pos < mb->end) {

		if (rst->metasz > 0) {

			n = min(mbuf_get_left(mb), rst->metasz - rst->bytec);

			if (rst->meta)
				mbuf_read_mem(mb,
					     (uint8_t *)&rst->meta[rst->bytec],
					      n);
			else
				mb->pos += n;

			rst->bytec += n;
#if 0
			re_printf("rst: metadata %zu bytes\n", n);
#endif
			if (rst->bytec >= rst->metasz) {
#if 0
				re_printf("rst: metadata: [%s]\n", rst->meta);
#endif
				rst->metasz = 0;
				rst->bytec  = 0;

				rst_video_update(rst->vidsrc_st, rst->name,
						 rst->meta);
			}
		}
		else if (rst->bytec < rst->metaint) {

			n = min(mbuf_get_left(mb), rst->metaint - rst->bytec);

			rst_audio_feed(rst->ausrc_st, mbuf_buf(mb), n);

			rst->bytec += n;
			mb->pos    += n;
#if 0
			re_printf("rst: mp3data %zu bytes\n", n);
#endif
		}
		else {
			rst->metasz = mbuf_read_u8(mb) * 16;
			rst->bytec  = 0;

			rst->meta = mem_deref(rst->meta);
			rst->meta = mem_zalloc(rst->metasz + 1, NULL);
#if 0
			re_printf("rst: metalength %zu bytes\n", rst->metasz);
#endif
		}
	}
}
예제 #29
0
파일: client.c 프로젝트: chk-jxcn/libre
/**
 * Send an HTTP request
 *
 * @param reqp      Pointer to allocated HTTP request object
 * @param cli       HTTP Client
 * @param met       Request method
 * @param uri       Request URI
 * @param resph     Response handler
 * @param datah     Content handler (optional)
 * @param arg       Handler argument
 * @param fmt       Formatted HTTP headers and body (optional)
 *
 * @return 0 if success, otherwise errorcode
 */
int http_request(struct http_req **reqp, struct http_cli *cli, const char *met,
		 const char *uri, http_resp_h *resph, http_data_h *datah,
		 void *arg, const char *fmt, ...)
{
	struct pl scheme, host, port, path;
	struct http_req *req;
	uint16_t defport;
	bool secure;
	va_list ap;
	int err;

	if (!reqp || !cli || !met || !uri)
		return EINVAL;

	if (re_regex(uri, strlen(uri), "[a-z]+://[^:/]+[:]*[0-9]*[^]+",
		     &scheme, &host, NULL, &port, &path) || scheme.p != uri)
		return EINVAL;

	if (!pl_strcasecmp(&scheme, "http") ||
	    !pl_strcasecmp(&scheme, "ws")) {
		secure  = false;
		defport = 80;
	}
#ifdef USE_TLS
	else if (!pl_strcasecmp(&scheme, "https") ||
		 !pl_strcasecmp(&scheme, "wss")) {
		secure  = true;
		defport = 443;
	}
#endif
	else
		return ENOTSUP;

	req = mem_zalloc(sizeof(*req), req_destructor);
	if (!req)
		return ENOMEM;

	req->tls    = mem_ref(cli->tls);
	req->secure = secure;
	req->port   = pl_isset(&port) ? pl_u32(&port) : defport;
	req->resph  = resph;
	req->datah  = datah;
	req->arg    = arg;

	err = pl_strdup(&req->host, &host);
	if (err)
		goto out;

	req->mbreq = mbuf_alloc(1024);
	if (!req->mbreq) {
		err = ENOMEM;
		goto out;
	}

	err = mbuf_printf(req->mbreq,
			  "%s %r HTTP/1.1\r\n"
			  "Host: %r\r\n",
			  met, &path, &host);
	if (fmt) {
		va_start(ap, fmt);
		err |= mbuf_vprintf(req->mbreq, fmt, ap);
		va_end(ap);
	}
	else {
		err |= mbuf_write_str(req->mbreq, "\r\n");
	}
	if (err)
		goto out;

	req->mbreq->pos = 0;

	if (!sa_set_str(&req->srvv[0], req->host, req->port)) {

		req->srvc = 1;

		err = req_connect(req);
		if (err)
			goto out;
	}
	else {
		err = dnsc_query(&req->dq, cli->dnsc, req->host,
				 DNS_TYPE_A, DNS_CLASS_IN, true,
				 query_handler, req);
		if (err)
			goto out;
	}

 out:
	if (err)
		mem_deref(req);
	else {
		req->reqp = reqp;
		*reqp = req;
	}

	return err;
}
예제 #30
0
파일: call.c 프로젝트: aKlausKranz/baresip
int call_accept(struct call *call, struct sipsess_sock *sess_sock,
		const struct sip_msg *msg)
{
	bool got_offer;
	int err;

	if (!call || !msg)
		return EINVAL;

	got_offer = (mbuf_get_left(msg->mb) > 0);

	err = pl_strdup(&call->peer_uri, &msg->from.auri);
	if (err)
		return err;

	if (pl_isset(&msg->from.dname)) {
		err = pl_strdup(&call->peer_name, &msg->from.dname);
		if (err)
			return err;
	}

	if (got_offer) {

		err = sdp_decode(call->sdp, msg->mb, true);
		if (err)
			return err;

		call->got_offer = true;

		/* Check if we have any common audio codecs, after
		 * the SDP offer has been parsed
		 */
		if (!have_common_audio_codecs(call)) {
			info("call: no common audio codecs - rejected\n");

			sip_treply(NULL, uag_sip(), msg,
				   488, "Not Acceptable Here");

			call_event_handler(call, CALL_EVENT_CLOSED,
					   "No audio codecs");

			return 0;
		}
	}

	err = sipsess_accept(&call->sess, sess_sock, msg, 180, "Ringing",
			     ua_cuser(call->ua), "application/sdp", NULL,
			     auth_handler, call->acc, true,
			     sipsess_offer_handler, sipsess_answer_handler,
			     sipsess_estab_handler, sipsess_info_handler,
			     sipsess_refer_handler, sipsess_close_handler,
			     call, "Allow: %s\r\n", uag_allowed_methods());
	if (err) {
		warning("call: sipsess_accept: %m\n", err);
		return err;
	}

	set_state(call, STATE_INCOMING);

	/* New call */
	tmr_start(&call->tmr_inv, LOCAL_TIMEOUT*1000, invite_timeout, call);

	if (!call->acc->mnat)
		call_event_handler(call, CALL_EVENT_INCOMING, call->peer_uri);

	return err;
}