Ejemplo n.º 1
0
static void sipsess_info_handler(struct sip *sip, const struct sip_msg *msg,
				 void *arg)
{
	struct call *call = arg;

	if (msg_ctype_cmp(&msg->ctyp, "application", "dtmf-relay")) {

		struct pl body, sig, dur;
		int err;

		pl_set_mbuf(&body, msg->mb);

		err  = re_regex(body.p, body.l, "Signal=[0-9]+", &sig);
		err |= re_regex(body.p, body.l, "Duration=[0-9]+", &dur);

		if (err) {
			(void)sip_reply(sip, msg, 400, "Bad Request");
		}
		else {
			char s = pl_u32(&sig);
			uint32_t duration = pl_u32(&dur);

			if (s == 10) s = '*';
			else if (s == 11) s = '#';
			else s += '0';

			info("received DTMF: '%c' (duration=%r)\n", s, &dur);

			(void)sip_reply(sip, msg, 200, "OK");

			if (call->dtmfh) {
				tmr_start(&call->tmr_dtmf, duration,
					  dtmfend_handler, call);
				call->dtmfh(call, s, call->arg);
			}
		}
	}
#ifdef USE_VIDEO
	else if (msg_ctype_cmp(&msg->ctyp,
			       "application", "media_control+xml")) {
		call_handle_info_req(call, msg);
		(void)sip_reply(sip, msg, 200, "OK");
	}
#endif
	else {
		(void)sip_reply(sip, msg, 488, "Not Acceptable Here");
	}
}
Ejemplo n.º 2
0
static inline int hdr_add(struct http_msg *msg, const struct pl *name,
			  enum http_hdrid id, const char *p, ssize_t l)
{
	struct http_hdr *hdr;

	hdr = mem_zalloc(sizeof(*hdr), hdr_destructor);
	if (!hdr)
		return ENOMEM;

	hdr->name  = *name;
	hdr->val.p = p;
	hdr->val.l = MAX(l, 0);
	hdr->id    = id;

	list_append(&msg->hdrl, &hdr->le, hdr);

	/* parse common headers */
	switch (id) {

	case HTTP_HDR_CONTENT_TYPE:
		msg->ctype = hdr->val;
		break;

	case HTTP_HDR_CONTENT_LENGTH:
		msg->clen = pl_u32(&hdr->val);
		break;

	default:
		break;
	}

	return 0;
}
Ejemplo n.º 3
0
static int decode_sdpparam_h263(struct videnc_state *st, const struct pl *name,
				const struct pl *val)
{
	enum h263_fmt fmt = h263_fmt(name);
	const int mpi = pl_u32(val);

	if (fmt == H263_FMT_OTHER) {
		info("h263: unknown param '%r'\n", name);
		return 0;
	}
	if (mpi < 1 || mpi > 32) {
		info("h263: %r: MPI out of range %d\n", name, mpi);
		return 0;
	}

	if (st->u.h263.picszn >= ARRAY_SIZE(st->u.h263.picszv)) {
		info("h263: picszv overflow: %r\n", name);
		return 0;
	}

	st->u.h263.picszv[st->u.h263.picszn].fmt = fmt;
	st->u.h263.picszv[st->u.h263.picszn].mpi = mpi;

	++st->u.h263.picszn;

	return 0;
}
Ejemplo n.º 4
0
static uint32_t wait_term(const struct sipevent_substate *substate)
{
	uint32_t wait;

	switch (substate->reason) {

	case SIPEVENT_DEACTIVATED:
	case SIPEVENT_TIMEOUT:
		wait = 5;
		break;

	case SIPEVENT_REJECTED:
	case SIPEVENT_NORESOURCE:
		wait = 3600;
		break;

	case SIPEVENT_PROBATION:
	case SIPEVENT_GIVEUP:
	default:
		wait = 300;
		if (pl_isset(&substate->retry_after))
			wait = max(wait, pl_u32(&substate->retry_after));
		break;
	}

	return wait;
}
Ejemplo n.º 5
0
static void sipsub_notify_handler(struct sip *sip, const struct sip_msg *msg,
				  void *arg)
{
	struct call *call = arg;
	struct pl scode, reason;
	uint32_t sc;

	if (re_regex((char *)mbuf_buf(msg->mb), mbuf_get_left(msg->mb),
		     "SIP/2.0 [0-9]+ [^\r\n]+", &scode, &reason)) {
		(void)sip_reply(sip, msg, 400, "Bad sipfrag");
		return;
	}

	(void)sip_reply(sip, msg, 200, "OK");

	sc = pl_u32(&scode);

	if (sc >= 300) {
		warning("call: transfer failed: %u %r\n", sc, &reason);
		call_event_handler(call, CALL_EVENT_TRANSFER_FAILED,
				   "%u %r", sc, &reason);
	}
	else if (sc >= 200) {
		call_event_handler(call, CALL_EVENT_CLOSED, "Call transfered");
	}
}
Ejemplo n.º 6
0
static void httpd_handler(const struct pl *uri, struct mbuf *mb)
{
	struct pl cmd, params, r;
	uint32_t refresh = 0;

	if (re_regex(uri->p, uri->l, "/[^?]*[^]*", &cmd, &params))
		return;

	if (!re_regex(params.p, params.l, "[?&]1r=[0-9]+", NULL, &r))
		refresh = pl_u32(&r);

	mbuf_write_str(mb, "<html>\n<head>\n");
	mbuf_write_str(mb, " <title>Restund Server Status</title>\n");

	if (refresh)
		mbuf_printf(mb,
			    " <meta http-equiv=\"refresh\" content=\"%u\">\n",
			    refresh);

	mbuf_write_str(mb, "</head>\n<body>\n");
	mbuf_write_str(mb, "<h2>Restund Server Status</h2>\n");
	server_info(mb);
	mbuf_write_str(mb, "<hr size=\"1\"/>\n<pre>\n");
	restund_cmd(&cmd, mb);
	mbuf_write_str(mb, "</pre>\n</body>\n</html>\n");
}
Ejemplo n.º 7
0
static void decode_param(const struct pl *name, const struct pl *val,
			 void *arg)
{
	struct aucodec_st *st = arg;
	int err;

	if (0 == pl_strcasecmp(name, "bitrate")) {
		st->bitrate = pl_u32(val) * 1000;
	}
	else if (0 == pl_strcasecmp(name, "frame-size")) {
		st->frame_size = pl_u32(val);

		if (st->frame_size & 0x1) {
			DEBUG_WARNING("frame-size is NOT even: %u\n",
				      st->frame_size);
		}
	}
	else if (0 == pl_strcasecmp(name, "low-overhead")) {
		struct pl fs, bpfv;
		uint32_t i;

		st->low_overhead = true;

		err = re_regex(val->p, val->l, "[0-9]+/[0-9,]+", &fs, &bpfv);
		if (err)
			return;

		st->frame_size = pl_u32(&fs);

		for (i=0; i<ARRAY_SIZE(st->bpfv) && bpfv.l > 0; i++) {
			struct pl bpf, co;

			co.l = 0;
			if (re_regex(bpfv.p, bpfv.l, "[0-9]+[,]*", &bpf, &co))
				break;

			pl_advance(&bpfv, bpf.l + co.l);

			st->bpfv[i] = pl_u32(&bpf);
		}
		st->bpfn = i;
	}
	else {
		DEBUG_NOTICE("unknown param: %r = %r\n", name, val);
	}
}
Ejemplo n.º 8
0
static void tcp_recv_handler(struct mbuf *mb, void *arg)
{
    struct request *request = arg;
    int ok;

    struct pl ver;
    struct pl code;
    struct pl phrase;
    struct pl headers;
    struct pl body;

    DEBUG_INFO("recv data[%d]\n", mbuf_get_left(mb));

    if(request->state == STREAM) {
        request->stream_h(request, HTTP_STREAM_DATA, mb, request->arg);
        return;
    }

    if(request->body) {
        ok = mbuf_write_mem(request->body, mbuf_buf(mb), mbuf_get_left(mb));

        goto clen;
    }

    ok = re_regex((const char*)mbuf_buf(mb), mbuf_get_left(mb),
	"HTTP/[^ \t\r\n]+ [0-9]+ [^\t\r\n]+\r\n[^]1",
	&ver, &code, &phrase, &headers);

    // XXX: check ok
    // XXX: check headers.l

    request->status = pl_u32(&code);
    headers.l = mbuf_get_left(mb) - (headers.p - (const char*)mbuf_buf(mb));
    body.l = 0;
    parse_headers(request, (char*)headers.p, headers.l, &body);
    if(body.l) {
        request->body = mbuf_alloc(body.l);
        mbuf_write_mem(request->body, (const unsigned char*)body.p, body.l);
    }

    request->response = mem_ref(mb);

clen:
    if(request->body && request->clen > request->body->end)
	    return;

    if(request->status >= 200 || request->stream_h == NULL) {
        request->done_h(request, request->status, request->arg);
        request->state = END;
        mem_deref(request);
        return;
    }

    request->state = STREAM;
    request->stream_h(request, HTTP_STREAM_EST, mb, request->arg);
}
Ejemplo n.º 9
0
static int attr_decode_rtcp(struct sdp_media *m, const struct pl *pl)
{
	struct pl port, addr;
	int err = 0;

	if (!m)
		return 0;

	if (!re_regex(pl->p, pl->l, "[0-9]+ IN IP[46]1 [^ ]+",
		      &port, NULL, &addr)) {
		(void)sa_set(&m->raddr_rtcp, &addr, pl_u32(&port));
	}
	else if (!re_regex(pl->p, pl->l, "[0-9]+", &port)) {
		sa_set_port(&m->raddr_rtcp, pl_u32(&port));
	}
	else
		err = EBADMSG;

	return err;
}
Ejemplo n.º 10
0
Archivo: ilbc.c Proyecto: GGGO/baresip
static void decoder_fmtp_decode(struct audec_state *st, const char *fmtp)
{
	struct pl mode;

	if (!fmtp)
		return;

	if (re_regex(fmtp, strlen(fmtp), "mode=[0-9]+", &mode))
		return;

	set_decoder_mode(st, pl_u32(&mode));
}
Ejemplo n.º 11
0
static int media_decode(struct sdp_media **mp, struct sdp_session *sess,
			bool offer, const struct pl *pl)
{
	struct pl name, port, proto, fmtv, fmt;
	struct sdp_media *m;
	int err;

	if (re_regex(pl->p, pl->l, "[a-z]+ [^ ]+ [^ ]+[^]*",
		     &name, &port, &proto, &fmtv))
		return EBADMSG;

	m = list_ledata(*mp ? (*mp)->le.next : sess->medial.head);
	if (!m) {
		if (!offer)
			return EPROTO;

		m = sdp_media_find(sess, &name, &proto);
		if (!m) {
			err = sdp_media_radd(&m, sess, &name, &proto);
			if (err)
				return err;
		}
		else {
			list_unlink(&m->le);
			list_append(&sess->medial, &m->le, m);
		}
	}
	else {
		if (pl_strcmp(&name, m->name))
			return offer ? ENOTSUP : EPROTO;

		if (pl_strcmp(&proto, m->proto))
			return ENOTSUP;
	}

	while (!re_regex(fmtv.p, fmtv.l, " [^ ]+", &fmt)) {

		pl_advance(&fmtv, fmt.p + fmt.l - fmtv.p);

		err = sdp_format_radd(m, &fmt);
		if (err)
			return err;
	}

	m->raddr = sess->raddr;
	sa_set_port(&m->raddr, pl_u32(&port));

	m->rdir = sess->rdir;

	*mp = m;

	return 0;
}
Ejemplo n.º 12
0
static void start_outbound(struct sipreg *reg, const struct sip_msg *msg)
{
	const struct sip_hdr *flowtimer;

	if (!sip_msg_hdr_has_value(msg, SIP_HDR_REQUIRE, "outbound"))
		return;

	flowtimer = sip_msg_hdr(msg, SIP_HDR_FLOW_TIMER);

	(void)sip_keepalive_start(&reg->ka, reg->sip, msg,
				  flowtimer ? pl_u32(&flowtimer->val) : 0,
				  keepalive_handler, reg);
}
Ejemplo n.º 13
0
uint32_t vp8_max_fs(const char *fmtp)
{
	struct pl pl, max_fs;

	if (!fmtp)
		return 0;

	pl_set_str(&pl, fmtp);

	if (fmt_param_get(&pl, "max-fs", &max_fs))
		return pl_u32(&max_fs);

	return 0;
}
Ejemplo n.º 14
0
static uint32_t packetization_mode(const char *fmtp)
{
	struct pl pl, mode;

	if (!fmtp)
		return 0;

	pl_set_str(&pl, fmtp);

	if (fmt_param_get(&pl, "packetization-mode", &mode))
		return pl_u32(&mode);

	return 0;
}
Ejemplo n.º 15
0
int conf_get_range(const struct conf *conf, const char *name,
		   struct range *rng)
{
	struct pl r, min, max;
	uint32_t v;
	int err;

	err = conf_get(conf, name, &r);
	if (err)
		return err;

	err = re_regex(r.p, r.l, "[0-9]+-[0-9]+", &min, &max);
	if (err) {
		/* fallback to non-range numeric value */
		err = conf_get_u32(conf, name, &v);
		if (err) {
			warning("conf: %s: could not parse range: (%r)\n",
				name, &r);
			return err;
		}

		rng->min = rng->max = v;

		return err;
	}

	rng->min = pl_u32(&min);
	rng->max = pl_u32(&max);

	if (rng->min > rng->max) {
		warning("conf: %s: invalid range (%u - %u)\n",
			name, rng->min, rng->max);
		return EINVAL;
	}

	return 0;
}
Ejemplo n.º 16
0
static int bandwidth_decode(int32_t *bwv, const struct pl *pl)
{
	struct pl type, bw;

	if (re_regex(pl->p, pl->l, "[^:]+:[0-9]+", &type, &bw))
		return EBADMSG;

	if (!pl_strcmp(&type, "CT"))
		bwv[SDP_BANDWIDTH_CT] = pl_u32(&bw);

	else if (!pl_strcmp(&type, "AS"))
		bwv[SDP_BANDWIDTH_AS] = pl_u32(&bw);

	else if (!pl_strcmp(&type, "RS"))
		bwv[SDP_BANDWIDTH_RS] = pl_u32(&bw);

	else if (!pl_strcmp(&type, "RR"))
		bwv[SDP_BANDWIDTH_RR] = pl_u32(&bw);

	else if (!pl_strcmp(&type, "TIAS"))
		bwv[SDP_BANDWIDTH_TIAS] = pl_u32(&bw);

	return 0;
}
Ejemplo n.º 17
0
static unsigned int str_ver(char *version) {
    int shift = 24;
    unsigned int ret = 0;
    struct pl ver;
    char *part = version;

    while(*version) {
        if(*version == '.') {
            ver.p = part;
            ver.l = version - part;
            ret |= pl_u32(&ver) << shift;
            shift -= 8;
            part = version+1;
        }
        version ++;
    }

    ver.p = part;
    ver.l = version - part;
    ret |= pl_u32(&ver) << shift;
    part = version+1;

    return ret;
};
Ejemplo n.º 18
0
/*
  decode sdpparameter for h264
*/
static void param_handler(const struct pl *name, const struct pl *val,
			  void *arg)
{
	struct videnc_state *st = arg;

	if (0 == pl_strcasecmp(name, "packetization-mode")) {
		st->h264.packetization_mode = pl_u32(val);

		if (st->h264.packetization_mode != 0) {
			warning("gst_video: illegal packetization-mode %u\n",
				st->h264.packetization_mode);
			return;
		}
	}
	else if (0 == pl_strcasecmp(name, "profile-level-id")) {
		struct pl prof = *val;
		if (prof.l != 6) {
			warning("gst_video: invalid profile-level-id (%r)\n",
				val);
			return;
		}

		prof.l = 2;
		st->h264.profile_idc = pl_x32(&prof); prof.p += 2;
		st->h264.profile_iop = pl_x32(&prof); prof.p += 2;
		st->h264.level_idc   = pl_x32(&prof);
	}
	else if (0 == pl_strcasecmp(name, "max-fs")) {
		st->h264.max_fs = pl_u32(val);
	}
	else if (0 == pl_strcasecmp(name, "max-smbps")) {
		st->h264.max_smbps = pl_u32(val);
	}

	return;
}
Ejemplo n.º 19
0
/**
 * Get the numeric value of a configuration item
 *
 * @param conf Configuration object
 * @param name Name of config item key
 * @param num  Returned numeric value of config item, if present
 *
 * @return 0 if success, otherwise errorcode
 */
int conf_get_u32(const struct conf *conf, const char *name, uint32_t *num)
{
	struct pl pl;
	int err;

	if (!conf || !name || !num)
		return EINVAL;

	err = conf_get(conf, name, &pl);
	if (err)
		return err;

	*num = pl_u32(&pl);

	return 0;
}
Ejemplo n.º 20
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;
}
Ejemplo n.º 21
0
/**
 * Decode a pointer-length string into a SIP Via header
 *
 * @param via SIP Via header
 * @param pl  Pointer-length string
 *
 * @return 0 for success, otherwise errorcode
 */
int sip_via_decode(struct sip_via *via, const struct pl *pl)
{
    struct pl transp, host, port;
    int err;

    if (!via || !pl)
        return EINVAL;

    err = re_regex(pl->p, pl->l,
                   "SIP[  \t\r\n]*/[ \t\r\n]*2.0[ \t\r\n]*/[ \t\r\n]*"
                   "[A-Z]+[ \t\r\n]*[^; \t\r\n]+[ \t\r\n]*[^]*",
                   NULL, NULL, NULL, NULL, &transp,
                   NULL, &via->sentby, NULL, &via->params);
    if (err)
        return err;

    if (!pl_strcmp(&transp, "TCP"))
        via->tp = SIP_TRANSP_TCP;
    else if (!pl_strcmp(&transp, "TLS"))
        via->tp = SIP_TRANSP_TLS;
    else if (!pl_strcmp(&transp, "UDP"))
        via->tp = SIP_TRANSP_UDP;
    else
        via->tp = SIP_TRANSP_NONE;

    err = decode_hostport(&via->sentby, &host, &port);
    if (err)
        return err;

    sa_init(&via->addr, AF_INET);

    (void)sa_set(&via->addr, &host, 0);

    if (pl_isset(&port))
        sa_set_port(&via->addr, pl_u32(&port));

    via->val = *pl;

    return msg_param_decode(&via->params, "branch", &via->branch);
}
Ejemplo n.º 22
0
void hdr_add(struct request *req, enum http_hdr_id id, struct pl *name, struct pl *val)
{
    struct http_hdr *hdr;
    switch(id) {
    case HTTP_CONTENT_LENGTH:
        req->clen = pl_u32(val);
        break;
    case HTTP_WWW_AUTH:
        req->www_auth.l = val->l;
        req->www_auth.p = val->p;
        break;
    default:
        ;;
    }

    hdr = mem_zalloc(sizeof(struct http_hdr), hdr_destruct);
    hdr->name.l = name->l;
    hdr->name.p = name->p;
    hdr->val.l = val->l;
    hdr->val.p = val->p;

    hash_append(req->hdrht, id, &hdr->he, hdr);
}
Ejemplo n.º 23
0
int ice_cand_attr_decode(struct ice_cand_attr *cand, const char *val)
{
	struct pl pl_fnd, pl_compid, pl_transp, pl_prio, pl_addr, pl_port;
	struct pl pl_type, pl_raddr, pl_rport, pl_opt = PL_INIT;
	size_t len;
	char type[8];
	int err;

	if (!cand || !val)
		return EINVAL;

	memset(cand, 0, sizeof(*cand));

	len = str_len(val);

	err = re_regex(val, len,
		       "[^ ]+ [0-9]+ [a-z]+ [0-9]+ [^ ]+ [0-9]+ typ [a-z]+"
		       "[^]*",
		       &pl_fnd, &pl_compid, &pl_transp, &pl_prio,
		       &pl_addr, &pl_port, &pl_type, &pl_opt);
	if (err)
		return err;

	(void)pl_strcpy(&pl_fnd, cand->foundation, sizeof(cand->foundation));

	if (0 == pl_strcasecmp(&pl_transp, "UDP"))
		cand->proto = IPPROTO_UDP;
	else if (0 == pl_strcasecmp(&pl_transp, "TCP"))
		cand->proto = IPPROTO_TCP;
	else
		cand->proto = 0;

	err = sa_set(&cand->addr, &pl_addr, pl_u32(&pl_port));
	if (err)
		return err;

	cand->compid = pl_u32(&pl_compid);
	cand->prio   = pl_u32(&pl_prio);

	(void)pl_strcpy(&pl_type, type, sizeof(type));

	cand->type = ice_cand_name2type(type);

	/* optional */

	if (0 == re_regex(pl_opt.p, pl_opt.l, "raddr [^ ]+ rport [0-9]+",
			  &pl_raddr, &pl_rport)) {

		err = sa_set(&cand->rel_addr, &pl_raddr, pl_u32(&pl_rport));
		if (err)
			return err;
	}

	if (cand->proto == IPPROTO_TCP) {

		struct pl tcptype;

		err = re_regex(pl_opt.p, pl_opt.l, "tcptype [^ ]+",
			       &tcptype);
		if (err)
			return err;

		cand->tcptype = ice_tcptype_resolve(&tcptype);
	}

	return 0;
}
Ejemplo n.º 24
0
Archivo: msg.c Proyecto: Issic47/libre
/**
 * Decode a SIP message
 *
 * @param msgp Pointer to allocated SIP Message
 * @param mb   Buffer containing SIP Message
 *
 * @return 0 if success, otherwise errorcode
 */
int sip_msg_decode(struct sip_msg **msgp, struct mbuf *mb)
{
	struct pl x, y, z, e, name;
	const char *p, *v, *cv;
	struct sip_msg *msg;
	bool comsep, quote;
	enum sip_hdrid id = SIP_HDR_NONE;
	uint32_t ws, lf;
	size_t l;
	int err;

	if (!msgp || !mb)
		return EINVAL;

	p = (const char *)mbuf_buf(mb);
	l = mbuf_get_left(mb);

	if (re_regex(p, l, "[^ \t\r\n]+ [^ \t\r\n]+ [^\r\n]*[\r]*[\n]1",
		     &x, &y, &z, NULL, &e) || x.p != (char *)mbuf_buf(mb))
		return (l > STARTLINE_MAX) ? EBADMSG : ENODATA;

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

	err = hash_alloc(&msg->hdrht, HDR_HASH_SIZE);
	if (err)
		goto out;

	msg->tag = rand_u64();
	msg->mb  = mem_ref(mb);
	msg->req = (0 == pl_strcmp(&z, "SIP/2.0"));

	if (msg->req) {

		msg->met = x;
		msg->ruri = y;
		msg->ver = z;

		if (uri_decode(&msg->uri, &y)) {
			err = EBADMSG;
			goto out;
		}
	}
	else {
		msg->ver    = x;
		msg->scode  = pl_u32(&y);
		msg->reason = z;

		if (!msg->scode) {
			err = EBADMSG;
			goto out;
		}
	}

	l -= e.p + e.l - p;
	p = e.p + e.l;

	name.p = v = cv = NULL;
	name.l = ws = lf = 0;
	comsep = false;
	quote = false;

	for (; l > 0; p++, l--) {

		switch (*p) {

		case ' ':
		case '\t':
			lf = 0; /* folding */
			++ws;
			break;

		case '\r':
			++ws;
			break;

		case '\n':
			++ws;

			if (!lf++)
				break;

			++p; --l; /* eoh */

			/*@fallthrough@*/

		default:
			if (lf || (*p == ',' && comsep && !quote)) {

				if (!name.l) {
					err = EBADMSG;
					goto out;
				}

				err = hdr_add(msg, &name, id, cv ? cv : p,
					      cv ? p - cv - ws : 0,
					      true, cv == v && lf);
				if (err)
					goto out;

				if (!lf) { /* comma separated */
					cv = NULL;
					break;
				}

				if (cv != v) {
					err = hdr_add(msg, &name, id,
						      v ? v : p,
						      v ? p - v - ws : 0,
						      false, true);
					if (err)
						goto out;
				}

				if (lf > 1) { /* eoh */
					err = 0;
					goto out;
				}

				comsep = false;
				name.p = NULL;
				cv = v = NULL;
				lf = 0;
			}

			if (!name.p) {
				name.p = p;
				name.l = 0;
				ws = 0;
			}

			if (!name.l) {
				if (*p != ':') {
					ws = 0;
					break;
				}

				name.l = MAX((int)(p - name.p - ws), 0);
				if (!name.l) {
					err = EBADMSG;
					goto out;
				}

				id = hdr_hash(&name);
				comsep = hdr_comma_separated(id);
				break;
			}

			if (!cv) {
				quote = false;
				cv = p;
			}

			if (!v) {
				v = p;
			}

			if (*p == '"')
				quote = !quote;

			ws = 0;
			break;
		}
	}

	err = ENODATA;

 out:
	if (err)
		mem_deref(msg);
	else {
		*msgp = msg;
		mb->pos = mb->end - l;
	}

	return err;
}
Ejemplo n.º 25
0
static int cand_decode(struct icem *icem, const char *val)
{
	struct pl foundation, compid, transp, prio, addr, port, cand_type;
	struct pl extra = pl_null;
	struct sa caddr, rel_addr;
	char type[8];
	uint8_t cid;
	int err;

	sa_init(&rel_addr, AF_INET);

	err = re_regex(val, strlen(val),
		       "[^ ]+ [0-9]+ [^ ]+ [0-9]+ [^ ]+ [0-9]+ typ [a-z]+[^]*",
		       &foundation, &compid, &transp, &prio,
		       &addr, &port, &cand_type, &extra);
	if (err)
		return err;

	if (ICE_TRANSP_NONE == transp_resolve(&transp)) {
		DEBUG_NOTICE("<%s> ignoring candidate with"
			     " unknown transport=%r (%r:%r)\n",
			     icem->name, &transp, &cand_type, &addr);
		return 0;
	}

	if (pl_isset(&extra)) {

		struct pl name, value;

		/* Loop through " SP attr SP value" pairs */
		while (!re_regex(extra.p, extra.l, " [^ ]+ [^ ]+",
				 &name, &value)) {

			pl_advance(&extra, value.p + value.l - extra.p);

			if (0 == pl_strcasecmp(&name, rel_addr_str)) {
				err = sa_set(&rel_addr, &value,
					     sa_port(&rel_addr));
				if (err)
					break;
			}
			else if (0 == pl_strcasecmp(&name, rel_port_str)) {
				sa_set_port(&rel_addr, pl_u32(&value));
			}
		}
	}

	err = sa_set(&caddr, &addr, pl_u32(&port));
	if (err)
		return err;

	cid = pl_u32(&compid);

	/* add only if not exist */
	if (icem_cand_find(&icem->rcandl, cid, &caddr))
		return 0;

	(void)pl_strcpy(&cand_type, type, sizeof(type));

	return icem_rcand_add(icem, ice_cand_name2type(type), cid,
			      pl_u32(&prio), &caddr, &rel_addr, &foundation);
}
Ejemplo n.º 26
0
static void response_handler(int err, const struct sip_msg *msg, void *arg)
{
	const struct sip_hdr *minexp;
	struct sipreg *reg = arg;

	reg->wait = failwait(reg->failc + 1);

	if (err || sip_request_loops(&reg->ls, msg->scode)) {
		reg->failc++;
		goto out;
	}

	if (msg->scode < 200) {
		return;
	}
	else if (msg->scode < 300) {
		reg->registered = true;
		reg->wait = reg->expires;
		sip_msg_hdr_apply(msg, true, SIP_HDR_CONTACT, contact_handler,
				  reg);
		reg->wait *= 900;
		reg->failc = 0;

		if (reg->regid > 0 && !reg->terminated && !reg->ka)
			start_outbound(reg, msg);
	}
	else {
		if (reg->terminated && !reg->registered)
			goto out;

		switch (msg->scode) {

		case 401:
		case 407:
			err = sip_auth_authenticate(reg->auth, msg);
			if (err) {
				err = (err == EAUTH) ? 0 : err;
				break;
			}

			err = request(reg, false);
			if (err)
				break;

			return;

		case 403:
			sip_auth_reset(reg->auth);
			break;

		case 423:
			minexp = sip_msg_hdr(msg, SIP_HDR_MIN_EXPIRES);
			if (!minexp || !pl_u32(&minexp->val) || !reg->expires)
				break;

			reg->expires = pl_u32(&minexp->val);

			err = request(reg, false);
			if (err)
				break;

			return;
		}

		++reg->failc;
	}

 out:
	if (!reg->expires) {
		mem_deref(reg);
	}
	else if (reg->terminated) {
		if (!reg->registered || request(reg, true))
			mem_deref(reg);
	}
	else {
		tmr_start(&reg->tmr, reg->wait, tmr_handler, reg);
		reg->resph(err, msg, reg->arg);
	}
}
Ejemplo n.º 27
0
static int decode_param(struct auenc_state *st, const struct pl *name,
			const struct pl *val)
{
	int ret;

	/* mode: List supported Speex decoding modes.  The valid modes are
	   different for narrowband and wideband, and are defined as follows:

	   {1,2,3,4,5,6,7,8,any} for narrowband
	   {0,1,2,3,4,5,6,7,8,9,10,any} for wideband and ultra-wideband
	 */
	if (0 == pl_strcasecmp(name, "mode")) {
		struct pl v;
		int mode;

		/* parameter is quoted */
		if (re_regex(val->p, val->l, "\"[^\"]+\"", &v))
			v = *val;

		if (0 == pl_strcasecmp(&v, "any"))
			return 0;

		mode = pl_u32(&v);

		ret = speex_encoder_ctl(st->enc, SPEEX_SET_MODE, &mode);
		if (ret) {
			warning("speex: SPEEX_SET_MODE: ret=%d\n", ret);
		}
	}
	/* vbr: variable bit rate - either 'on' 'off' or 'vad' */
	else if (0 == pl_strcasecmp(name, "vbr")) {
		int vbr = 0, vad = 0;

		if (0 == pl_strcasecmp(val, "on"))
			vbr = 1;
		else if (0 == pl_strcasecmp(val, "off"))
			vbr = 0;
		else if (0 == pl_strcasecmp(val, "vad"))
			vad = 1;
		else {
			warning("speex: invalid vbr value %r\n", val);
		}

		debug("speex: setting VBR=%d VAD=%d\n", vbr, vad);
		ret = speex_encoder_ctl(st->enc, SPEEX_SET_VBR, &vbr);
		if (ret) {
			warning("speex: SPEEX_SET_VBR: ret=%d\n", ret);
		}
		ret = speex_encoder_ctl(st->enc, SPEEX_SET_VAD, &vad);
		if (ret) {
			warning("speex: SPEEX_SET_VAD: ret=%d\n", ret);
		}
	}
	else if (0 == pl_strcasecmp(name, "cng")) {
		int dtx = 0;

		if (0 == pl_strcasecmp(val, "on"))
			dtx = 0;
		else if (0 == pl_strcasecmp(val, "off"))
			dtx = 1;

		ret = speex_encoder_ctl(st->enc, SPEEX_SET_DTX, &dtx);
		if (ret) {
			warning("speex: SPEEX_SET_DTX: ret=%d\n", ret);
		}
	}
	else {
		debug("speex: unknown Speex param: %r=%r\n", name, val);
	}

	return 0;
}
Ejemplo n.º 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
		}
	}
}
Ejemplo n.º 29
0
/**
 * Decode a HTTP message
 *
 * @param msgp Pointer to allocated HTTP Message
 * @param mb   Buffer containing HTTP Message
 * @param req  True for request, false for response
 *
 * @return 0 if success, otherwise errorcode
 */
int http_msg_decode(struct http_msg **msgp, struct mbuf *mb, bool req)
{
	struct pl b, s, e, name, scode;
	const char *p, *cv;
	struct http_msg *msg;
	bool comsep, quote;
	enum http_hdrid id = HTTP_HDR_NONE;
	uint32_t ws, lf;
	size_t l;
	int err;

	if (!msgp || !mb)
		return EINVAL;

	p = (const char *)mbuf_buf(mb);
	l = mbuf_get_left(mb);

	if (re_regex(p, l, "[\r\n]*[^\r\n]+[\r]*[\n]1", &b, &s, NULL, &e))
		return (l > STARTLINE_MAX) ? EBADMSG : ENODATA;

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

	msg->mb = mem_ref(mb);

	if (req) {
		if (re_regex(s.p, s.l, "[a-z]+ [^? ]+[^ ]* HTTP/[0-9.]+",
			     &msg->met, &msg->path, &msg->prm, &msg->ver) ||
		    msg->met.p != s.p) {
			err = EBADMSG;
			goto out;
		}
	}
	else {
		if (re_regex(s.p, s.l, "HTTP/[0-9.]+ [0-9]+ [^]*",
			     &msg->ver, &scode, &msg->reason) ||
		    msg->ver.p != s.p + 5) {
			err = EBADMSG;
			goto out;
		}

		msg->scode = pl_u32(&scode);
	}

	l -= e.p + e.l - p;
	p = e.p + e.l;

	name.p = cv = NULL;
	name.l = ws = lf = 0;
	comsep = false;
	quote = false;

	for (; l > 0; p++, l--) {

		switch (*p) {

		case ' ':
		case '\t':
			lf = 0; /* folding */
			++ws;
			break;

		case '\r':
			++ws;
			break;

		case '\n':
			++ws;

			if (!name.p) {
				++p; --l; /* no headers */
				err = 0;
				goto out;
			}

			if (!lf++)
				break;

			++p; --l; /* eoh */

			/*@fallthrough@*/

		default:
			if (lf || (*p == ',' && comsep && !quote)) {

				if (!name.l) {
					err = EBADMSG;
					goto out;
				}

				err = hdr_add(msg, &name, id, cv ? cv : p,
					      cv ? p - cv - ws : 0);
				if (err)
					goto out;

				if (!lf) { /* comma separated */
					cv = NULL;
					break;
				}

				if (lf > 1) { /* eoh */
					err = 0;
					goto out;
				}

				comsep = false;
				name.p = NULL;
				cv = NULL;
				lf = 0;
			}

			if (!name.p) {
				name.p = p;
				name.l = 0;
				ws = 0;
			}

			if (!name.l) {
				if (*p != ':') {
					ws = 0;
					break;
				}

				name.l = MAX((int)(p - name.p - ws), 0);
				if (!name.l) {
					err = EBADMSG;
					goto out;
				}

				id = hdr_hash(&name);
				comsep = hdr_comma_separated(id);
				break;
			}

			if (!cv) {
				quote = false;
				cv = p;
			}

			if (*p == '"')
				quote = !quote;

			ws = 0;
			break;
		}
	}

	err = ENODATA;

 out:
	if (err)
		mem_deref(msg);
	else {
		*msgp = msg;
		mb->pos = mb->end - l;
	}

	return err;
}
Ejemplo n.º 30
0
/**
 * 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;
}