예제 #1
0
/**
 * Encode an RTCP Generic NACK (GNACK) message
 *
 * @param mb  Buffer to encode into
 * @param pid Packet ID
 * @param blp Bitmask of following lost packets (BLP)
 *
 * @return 0 for success, otherwise errorcode
 */
int rtcp_rtpfb_gnack_encode(struct mbuf *mb, uint16_t pid, uint16_t blp)
{
	int err;
	err  = mbuf_write_u16(mb, htons(pid));
	err |= mbuf_write_u16(mb, htons(blp));
	return err;
}
예제 #2
0
파일: play.c 프로젝트: mralexgray/baresip
static int aufile_load(struct mbuf *mb, const char *filename,
		       uint32_t *srate, uint8_t *channels)
{
	struct aufile_prm prm;
	struct aufile *af;
	int err;

	err = aufile_open(&af, &prm, filename, AUFILE_READ);
	if (err)
		return err;

	while (!err) {
		uint8_t buf[4096];
		size_t i, n;

		n = sizeof(buf);

		err = aufile_read(af, buf, &n);
		if (err || !n)
			break;

		switch (prm.fmt) {

		case AUFMT_S16LE:
			err = mbuf_write_mem(mb, buf, n);
			break;

		case AUFMT_PCMA:
			for (i=0; i<n; i++) {
				err |= mbuf_write_u16(mb,
						      g711_alaw2pcm(buf[i]));
			}
			break;

		case AUFMT_PCMU:
			for (i=0; i<n; i++) {
				err |= mbuf_write_u16(mb,
						      g711_ulaw2pcm(buf[i]));
			}
			break;

		default:
			err = ENOSYS;
			break;
		}
	}

	mem_deref(af);

	if (!err) {
		mb->pos = 0;

		*srate    = prm.srate;
		*channels = prm.channels;
	}

	return err;
}
예제 #3
0
static int gnack_encode(struct mbuf *mb, void *arg)
{
	int err = 0, n=3;
	(void)arg;

	while (n--) {
		err |= mbuf_write_u16(mb, htons(0x0123));
		err |= mbuf_write_u16(mb, htons(0x0456));
	}

	return err;
}
예제 #4
0
int stun_hdr_encode(struct mbuf *mb, const struct stun_hdr *hdr)
{
	int err = 0;

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

	err |= mbuf_write_u16(mb, htons(hdr->type & 0x3fff));
	err |= mbuf_write_u16(mb, htons(hdr->len));
	err |= mbuf_write_u32(mb, htonl(hdr->cookie));
	err |= mbuf_write_mem(mb, hdr->tid, sizeof(hdr->tid));

	return err;
}
예제 #5
0
파일: payload.c 프로젝트: alfredh/rew
static int pcp_write_port(struct mbuf *mb, const struct sa *sa)
{
	uint16_t port_be;

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

	switch (sa->u.sa.sa_family) {

	case AF_INET:
		port_be = sa->u.in.sin_port;
		break;

#ifdef HAVE_INET6
	case AF_INET6:
		port_be = sa->u.in6.sin6_port;
		break;
#endif

	default:
		return EAFNOSUPPORT;
	}

	return mbuf_write_u16(mb, port_be);
}
예제 #6
0
파일: rtp.c 프로젝트: hbowden/re
/**
 * Encode the RTP header into a buffer
 *
 * @param mb  Buffer to encode into
 * @param hdr RTP Header to be encoded
 *
 * @return 0 if success, otherwise errorcode
 */
int rtp_hdr_encode(struct mbuf *mb, const struct rtp_header *hdr)
{
	uint8_t buf[2];
	int err, i;

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

	buf[0]  = (hdr->ver & 0x02) << 6;
	buf[0] |= (hdr->pad & 0x01) << 5;
	buf[0] |= (hdr->ext & 0x01) << 4;
	buf[0] |= (hdr->cc  & 0x0f) << 0;
	buf[1]  = (hdr->m   & 0x01) << 7;
	buf[1] |= (hdr->pt  & 0x7f) << 0;

	err  = mbuf_write_mem(mb, buf, sizeof(buf));
	err |= mbuf_write_u16(mb, htons(hdr->seq));
	err |= mbuf_write_u32(mb, htonl(hdr->ts));
	err |= mbuf_write_u32(mb, htonl(hdr->ssrc));

	for (i=0; i<hdr->cc; i++) {
		err |= mbuf_write_u32(mb, htonl(hdr->csrc[i]));
	}

	return err;
}
예제 #7
0
static int test_rtcp_decode_badmsg(void)
{
	struct rtcp_msg *msg = NULL;
	uint32_t ssrc = 0xcafebabe;
	struct mbuf *mb;
	int err = 0;

	mb = mbuf_alloc(128);
	if (!mb) {
		err = ENOMEM;
		goto out;
	}

	err = rtcp_encode(mb, RTCP_PSFB, RTCP_PSFB_SLI,
			  ssrc, ssrc, NULL, NULL);
	if (err)
		goto out;

	/* simulate a corrupt RTCP packet */
	mb->pos = 2;
	(void)mbuf_write_u16(mb, htons(0));

	mb->pos = 0;

	if (EBADMSG != rtcp_decode(&msg, mb)) {
		err = EBADMSG;
		goto out;
	}

 out:
	mem_deref(msg);
	mem_deref(mb);

	return err;
}
예제 #8
0
/* Receive packet on the "relayed" address -- relay to the client */
static void relay_udp_recv(const struct sa *src, struct mbuf *mb, void *arg)
{
	struct turnserver *turn = arg;
	struct channel *chan;
	int err = 0;

	++turn->n_recv;

	chan = find_channel_peer(turn, src);
	if (chan) {
		uint16_t len = mbuf_get_left(mb);
		size_t start;

		if (mb->pos < 4) {
			DEBUG_WARNING("relay_udp_recv: mb pos < 4\n");
			return;
		}

		mb->pos -= 4;
		start = mb->pos;

		(void)mbuf_write_u16(mb, htons(chan->nr));
		(void)mbuf_write_u16(mb, htons(len));

		mb->pos = start;

		err = udp_send(turn->us, &turn->cli, mb);
	}
	else {
		err = stun_indication(IPPROTO_UDP, turn->us,
				      &turn->cli, 0, STUN_METHOD_DATA,
				      NULL, 0, false, 2,
				      STUN_ATTR_XOR_PEER_ADDR, src,
				      STUN_ATTR_DATA, mb);
	}

	if (err) {
		DEBUG_WARNING("relay_udp_recv: error %m\n", err);
	}
}
예제 #9
0
파일: pkt.c 프로젝트: kaija/libre
/**
 * Encode the RTCP Header
 *
 * @param mb     Buffer to encode into
 * @param count  Number of sub-elemements
 * @param type   RTCP Packet type
 * @param length Packet length in words
 *
 * @return 0 for success, otherwise errorcode
 */
int rtcp_hdr_encode(struct mbuf *mb, uint8_t count, enum rtcp_type type,
		    uint16_t length)
{
	int err;

	if (!mb)
		return EINVAL;

	err  = mbuf_write_u8(mb, RTCP_VERSION<<6 | count);
	err |= mbuf_write_u8(mb, type);
	err |= mbuf_write_u16(mb, htons(length));

	return err;
}
예제 #10
0
파일: payload.c 프로젝트: alfredh/rew
static int pcp_map_encode(struct mbuf *mb, const struct pcp_map *map)
{
	int err = 0;

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

	err |= mbuf_write_mem(mb, map->nonce, sizeof(map->nonce));
	err |= mbuf_write_u8(mb, map->proto);
	err |= mbuf_fill(mb, 0x00, 3);
	err |= mbuf_write_u16(mb, htons(map->int_port));
	err |= pcp_write_port(mb, &map->ext_addr);
	err |= pcp_ipaddr_encode(mb, &map->ext_addr);

	return err;
}
예제 #11
0
/* responsible for adding the SHIM header
   - assumes that the sent MBUF contains a complete packet
 */
static bool shim_send_handler(int *err, struct mbuf *mb, void *arg)
{
	struct shim *shim = arg;
	size_t len;
	(void)shim;

	if (mb->pos < SHIM_HDR_SIZE) {
		DEBUG_WARNING("send: not enough space for SHIM header\n");
		*err = ENOMEM;
		return true;
	}

	len = mbuf_get_left(mb);

	mb->pos -= SHIM_HDR_SIZE;
	*err = mbuf_write_u16(mb, htons(len));
	mb->pos -= SHIM_HDR_SIZE;

	++shim->n_tx;

	return false;
}
예제 #12
0
파일: tone.c 프로젝트: soramimi/qSIP
/**
 * Generate a dual-tone sine wave into a PCM buffer
 *
 * @param mb    Buffer for PCM samples
 * @param srate Sample rate in [Hz]
 * @param f1    Frequency number one
 * @param l1    Level of f1 from 0-100
 * @param f2    Frequency number two
 * @param l2    Level of f2 from 0-100
 *
 * @return 0 for success, otherwise error code
 */
int autone_sine(struct mbuf *mb, uint32_t srate,
		uint32_t f1, int l1, uint32_t f2, int l2)
{
	double d1, d2;
	uint32_t i;
	int err = 0;

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

	d1 = 1.0f * f1 / srate;
	d2 = 1.0f * f2 / srate;

	for (i=0; i<srate; i++) {
		int16_t s1, s2;

		s1 = (int16_t)(SCALE * l1 / 100.0f * sin(2 * M_PI * d1 * i));
		s2 = (int16_t)(SCALE * l2 / 100.0f * sin(2 * M_PI * d2 * i));

		err |= mbuf_write_u16(mb, saturate_add16(s1, s2));
	}

	return err;
}
예제 #13
0
파일: payload.c 프로젝트: alfredh/rew
static int pcp_peer_encode(struct mbuf *mb, const struct pcp_peer *peer)
{
	int err;

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

	/* Protocol MUST NOT be zero.
	 * Internal port MUST NOT be zero.
	 */
	if (!peer->map.proto || !peer->map.int_port)
		return EPROTO;

	/* note: the MAP and PEER opcodes are quite similar */
	err = pcp_map_encode(mb, &peer->map);
	if (err)
		return err;

	err  = pcp_write_port(mb, &peer->remote_addr);
	err |= mbuf_write_u16(mb, 0x0000);
	err |= pcp_ipaddr_encode(mb, &peer->remote_addr);

	return err;
}
예제 #14
0
int stun_attr_encode(struct mbuf *mb, uint16_t type, const void *v,
		     const uint8_t *tid, uint8_t padding)
{
	const struct stun_change_req *ch_req = v;
	const struct stun_errcode *err_code = v;
	const struct stun_unknown_attr *ua = v;
	const unsigned int *num = v;
	const struct mbuf *mbd = v;
	size_t start, len;
	uint32_t i, n;
	int err = 0;

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

	mb->pos += 4;
	start = mb->pos;

	switch (type) {

	case STUN_ATTR_MAPPED_ADDR:
	case STUN_ATTR_ALT_SERVER:
	case STUN_ATTR_RESP_ORIGIN:
	case STUN_ATTR_OTHER_ADDR:
		tid = NULL;
		/*@fallthrough@*/
	case STUN_ATTR_XOR_PEER_ADDR:
	case STUN_ATTR_XOR_RELAY_ADDR:
	case STUN_ATTR_XOR_MAPPED_ADDR:
		err |= stun_addr_encode(mb, v, tid);
		break;

	case STUN_ATTR_CHANGE_REQ:
		n = (uint32_t)ch_req->ip << 2 | (uint32_t)ch_req->port << 1;
		err |= mbuf_write_u32(mb, htonl(n));
		break;

	case STUN_ATTR_USERNAME:
	case STUN_ATTR_REALM:
	case STUN_ATTR_NONCE:
	case STUN_ATTR_SOFTWARE:
		err |= mbuf_write_str(mb, v);
		break;

	case STUN_ATTR_MSG_INTEGRITY:
		err |= mbuf_write_mem(mb, v, 20);
		break;

	case STUN_ATTR_ERR_CODE:
		err |= mbuf_write_u16(mb, 0x00);
		err |= mbuf_write_u8(mb,  err_code->code/100);
		err |= mbuf_write_u8(mb,  err_code->code%100);
		err |= mbuf_write_str(mb, err_code->reason);
		break;

	case STUN_ATTR_UNKNOWN_ATTR:
		for (i=0; i<ua->typec; i++)
			err |= mbuf_write_u16(mb, htons(ua->typev[i]));
		break;

	case STUN_ATTR_CHANNEL_NUMBER:
	case STUN_ATTR_RESP_PORT:
		err |= mbuf_write_u16(mb, htons(*num));
		err |= mbuf_write_u16(mb, 0x0000);
		break;

	case STUN_ATTR_LIFETIME:
	case STUN_ATTR_PRIORITY:
	case STUN_ATTR_FINGERPRINT:
		err |= mbuf_write_u32(mb, htonl(*num));
		break;

	case STUN_ATTR_DATA:
	case STUN_ATTR_PADDING:
		if (mb == mbd) {
			mb->pos = mb->end;
			break;
		}
		err |= mbuf_write_mem(mb, mbuf_buf(mbd), mbuf_get_left(mbd));
		break;

	case STUN_ATTR_REQ_ADDR_FAMILY:
	case STUN_ATTR_REQ_TRANSPORT:
		err |= mbuf_write_u8(mb, *num);
		err |= mbuf_write_u8(mb, 0x00);
		err |= mbuf_write_u16(mb, 0x0000);
		break;

	case STUN_ATTR_EVEN_PORT:
		err |= mbuf_write_u8(mb, ((struct stun_even_port *)v)->r << 7);
		break;

	case STUN_ATTR_DONT_FRAGMENT:
	case STUN_ATTR_USE_CAND:
		 /* no value */
		break;

	case STUN_ATTR_RSV_TOKEN:
	case STUN_ATTR_CONTROLLED:
	case STUN_ATTR_CONTROLLING:
		err |= mbuf_write_u64(mb, sys_htonll(*(uint64_t *)v));
		break;

	default:
		err = EINVAL;
		break;
	}

	/* header */
	len = mb->pos - start;

	mb->pos = start - 4;
	err |= mbuf_write_u16(mb, htons(type));
	err |= mbuf_write_u16(mb, htons(len));
	mb->pos += len;

	/* padding */
	while ((mb->pos - start) & 0x03)
		err |= mbuf_write_u8(mb, padding);

	return err;
}
예제 #15
0
파일: option.c 프로젝트: alfredh/rew
int pcp_option_encode(struct mbuf *mb, enum pcp_option_code code,
		      const void *v)
{
	const struct sa *sa = v;
	const struct pcp_option_filter *filt = v;
	size_t start, len;
	int err = 0;

	if (!mb)
		return EINVAL;

	mb->pos += 4;
	start = mb->pos;

	switch (code) {

	case PCP_OPTION_THIRD_PARTY:
		if (!sa)
			return EINVAL;
		err |= pcp_ipaddr_encode(mb, sa);
		break;

	case PCP_OPTION_PREFER_FAILURE:
		/* no payload */
		break;

	case PCP_OPTION_FILTER:
		if (!filt)
			return EINVAL;
		err |= mbuf_write_u8(mb, 0x00);
		err |= mbuf_write_u8(mb, filt->prefix_length);
		err |= mbuf_write_u16(mb, htons(sa_port(&filt->remote_peer)));
		err |= pcp_ipaddr_encode(mb, &filt->remote_peer);
		break;

	case PCP_OPTION_DESCRIPTION:
		if (!v)
			return EINVAL;
		err |= mbuf_write_str(mb, v);
		break;

	default:
		(void)re_fprintf(stderr,
				 "pcp: unsupported option %d\n", code);
		return EINVAL;
	}

	/* header */
	len = mb->pos - start;

	mb->pos = start - 4;
	err |= mbuf_write_u8(mb, code);
	err |= mbuf_write_u8(mb, 0x00);
	err |= mbuf_write_u16(mb, htons(len));
	mb->pos += len;

	/* padding */
	while ((mb->pos - start) & 0x03)
		err |= mbuf_write_u8(mb, 0x00);

	return err;
}
예제 #16
0
static int query(struct dns_query **qp, struct dnsc *dnsc, uint8_t opcode,
		 const char *name, uint16_t type, uint16_t dnsclass,
		 const struct dnsrr *ans_rr, int proto,
		 const struct sa *srvv, const uint32_t *srvc,
		 bool aa, bool rd, dns_query_h *qh, void *arg)
{
	struct dns_query *q = NULL;
	struct dnshdr hdr;
	int err = 0;
	uint32_t i;

	if (!dnsc || !name || !srvv || !srvc || !(*srvc))
		return EINVAL;

	if (DNS_QTYPE_AXFR == type)
		proto = IPPROTO_TCP;

	q = mem_zalloc(sizeof(*q), query_destructor);
	if (!q)
		goto nmerr;

	hash_append(dnsc->ht_query, hash_joaat_str_ci(name), &q->le, q);
	tmr_init(&q->tmr);
	mbuf_init(&q->mb);

	for (i=0; i<ARRAY_SIZE(q->rrlv); i++)
		list_init(&q->rrlv[i]);

	err = str_dup(&q->name, name);
	if (err)
		goto error;

	q->srvv = srvv;
	q->srvc = srvc;
	q->id   = rand_u16();
	q->type = type;
	q->opcode = opcode;
	q->dnsclass = dnsclass;
	q->dnsc = dnsc;

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

	hdr.id = q->id;
	hdr.opcode = q->opcode;
	hdr.aa = aa;
	hdr.rd = rd;
	hdr.nq = 1;
	hdr.nans = ans_rr ? 1 : 0;

	if (proto == IPPROTO_TCP)
		q->mb.pos += 2;

	err = dns_hdr_encode(&q->mb, &hdr);
	if (err)
		goto error;

	err = dns_dname_encode(&q->mb, name, NULL, 0, false);
	if (err)
		goto error;

	err |= mbuf_write_u16(&q->mb, htons(type));
	err |= mbuf_write_u16(&q->mb, htons(dnsclass));
	if (err)
		goto error;

	if (ans_rr) {
		err = dns_rr_encode(&q->mb, ans_rr, 0, NULL, 0);
		if (err)
			goto error;
	}

	q->qh  = qh;
	q->arg = arg;

	switch (proto) {

	case IPPROTO_TCP:
		q->mb.pos = 0;
		(void)mbuf_write_u16(&q->mb, htons(q->mb.end - 2));

		err = send_tcp(q);
		if (err)
			goto error;

		tmr_start(&q->tmr, 60 * 1000, tcp_timeout_handler, q);
		break;

	case IPPROTO_UDP:
		err = send_udp(q);
		if (err)
			goto error;

		tmr_start(&q->tmr, 500, udp_timeout_handler, q);
		break;

	default:
		err = EPROTONOSUPPORT;
		goto error;
	}

	if (qp) {
		q->qp = qp;
		*qp = q;
	}

	return 0;

 nmerr:
	err = ENOMEM;
 error:
	mem_deref(q);

	return err;
}
예제 #17
0
static inline int dname_encode_pointer(struct mbuf *mb, size_t pos)
{
	return mbuf_write_u16(mb, htons(pos | (COMP_MASK<<8)));
}
예제 #18
0
파일: pkt.c 프로젝트: kaija/libre
int rtcp_vencode(struct mbuf *mb, enum rtcp_type type, uint32_t count,
		 va_list ap)
{
	size_t i, pos;
	uint16_t len;
	const uint8_t *data;
	size_t data_len;
	const uint32_t *srcv;
	const char *reason;
	rtcp_encode_h *ench;
	void *arg;
	int err = 0;

	if (!mb)
		return EINVAL;

	pos = mb->pos;

	/* Skip header - encoded last */
	mb->pos = mb->end = (mb->pos + RTCP_HDR_SIZE);

	switch (type) {

	case RTCP_SR:
		for (i=0; i<6; i++)
			err |= mbuf_write_u32(mb, htonl(va_arg(ap, uint32_t)));
		ench = va_arg(ap, rtcp_encode_h *);
		arg = va_arg(ap, void *);
		if (ench)
			err |= ench(mb, arg);
		break;

	case RTCP_RR:
		err = mbuf_write_u32(mb, htonl(va_arg(ap, uint32_t)));
		ench = va_arg(ap, rtcp_encode_h *);
		arg = va_arg(ap, void *);
		if (ench)
			err |= ench(mb, arg);
		break;

	case RTCP_SDES:
		ench = va_arg(ap, rtcp_encode_h *);
		arg = va_arg(ap, void *);
		if (ench)
			err |= ench(mb, arg);
		break;

	case RTCP_BYE:
		srcv   = va_arg(ap, uint32_t *);
		reason = va_arg(ap, char *);
		for (i=0; i<count && !err; i++) {
			err = mbuf_write_u32(mb, htonl(srcv[i]));
		}
		if (reason) {
			err |= mbuf_write_u8(mb, strlen(reason));
			err |= mbuf_write_str(mb, reason);
		}
		break;

	case RTCP_APP:
		err  = mbuf_write_u32(mb, htonl(va_arg(ap, uint32_t)));
		err |= mbuf_write_mem(mb, va_arg(ap, uint8_t *), 4);
		data = va_arg(ap, const uint8_t *);
		data_len = va_arg(ap, size_t);
		if (data) {
			if (data_len % 4) {
				DEBUG_WARNING("not a multiple of 32bits\n");
				return EBADMSG;
			}
			err |= mbuf_write_mem(mb, data, data_len);
		}
		break;

	case RTCP_FIR:
		err  = mbuf_write_u32(mb, htonl(va_arg(ap, uint32_t)));
		break;

	case RTCP_NACK:
		err  = mbuf_write_u32(mb, htonl(va_arg(ap, uint32_t)));
		err |= mbuf_write_u16(mb, htons(va_arg(ap, uint32_t)));
		err |= mbuf_write_u16(mb, htons(va_arg(ap, uint32_t)));
		break;

	case RTCP_RTPFB:
	case RTCP_PSFB:
		err  = mbuf_write_u32(mb, htonl(va_arg(ap, uint32_t)));
		err |= mbuf_write_u32(mb, htonl(va_arg(ap, uint32_t)));
		ench = va_arg(ap, rtcp_encode_h *);
		arg = va_arg(ap, void *);
		if (ench)
			err |= ench(mb, arg);
		break;

	default:
		return EINVAL;
	}
	if (err)
		return err;

	/* padding to 32 bits */
	while ((mb->end - pos) & 0x3)
		err |= mbuf_write_u8(mb, 0x00);
	if (err)
		return err;

	/* Encode RTCP Header */
	mb->pos = pos;
	len = (mb->end - pos - RTCP_HDR_SIZE)/sizeof(uint32_t);
	err = rtcp_hdr_encode(mb, count, type, len);
	if (err)
		return err;

	mb->pos = mb->end;

	return 0;
}