Beispiel #1
0
static int generate_random_uuid(FILE *f)
{
	if (re_fprintf(f, "%08x-%04x-%04x-%04x-%08x%04x",
		       rand_u32(), rand_u16(), rand_u16(), rand_u16(),
		       rand_u32(), rand_u16()) != UUID_LEN)
		return ENOMEM;

	return 0;
}
TEST_F(cryptoboxtest, send_ten_messages)
{
	struct device *a, *b;

	add_devices(2);

	/* Connect the 2 devices */
	connect_devices();

	a = (struct device *)devicel.head->data;
	b = (struct device *)devicel.tail->data;

	err = device_new_session(a, b);
	ASSERT_EQ(0, err);

	for (int i=0; i<5; i++) {
		size_t len = rand_u16();
		uint8_t *msg = (uint8_t *)mem_alloc(len, NULL);

		rand_bytes(msg, len);

		send_message(a, b, msg, len);

		/* reverse direction */
		send_message(b, a, msg, len);

		mem_deref(msg);
	}
}
Beispiel #3
0
static int alloc(struct vidsrc_st **stp, const struct vidsrc *vs,
		 struct media_ctx **ctx, struct vidsrc_prm *prm,
		 const struct vidsz *size, const char *fmt,
		 const char *dev, vidsrc_frame_h *frameh,
		 vidsrc_error_h *errorh, void *arg)
{
	struct vidsrc_st *st;
	int err = 0;

	(void)ctx;
	(void)fmt;
	(void)dev;
	(void)errorh;

	if (!stp || !prm || !size || !frameh)
		return EINVAL;

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

	st->vs     = vs;
	st->frameh = frameh;
	st->arg    = arg;
	st->prm    = *prm;
	st->size   = *size;

	st->surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
						 size->w, size->h);
	st->cr = cairo_create(st->surface);

	info("cairo: surface with format %d (%d x %d) stride=%d\n",
	     cairo_image_surface_get_format(st->surface),
	     cairo_image_surface_get_width(st->surface),
	     cairo_image_surface_get_height(st->surface),
	     cairo_image_surface_get_stride(st->surface));

	st->step = rand_u16() / 1000.0;

	st->run = true;
	err = pthread_create(&st->thread, NULL, read_thread, st);
	if (err) {
		st->run = false;
		goto out;
	}

 out:
	if (err)
		mem_deref(st);
	else
		*stp = st;

	return err;
}
Beispiel #4
0
static void timeout(void *arg)
{
	struct icem_comp *comp = arg;
	struct candpair *cp;

	tmr_start(&comp->tmr_ka, ICE_DEFAULT_Tr * 1000 + rand_u16() % 1000,
		  timeout, comp);

	/* find selected candidate-pair */
	cp = comp->cp_sel;
	if (!cp)
		return;

	(void)stun_indication(comp->icem->proto, comp->sock, &cp->rcand->addr,
			      (cp->lcand->type == CAND_TYPE_RELAY) ? 4 : 0,
			      STUN_METHOD_BINDING, NULL, 0, true, 0);
}
Beispiel #5
0
int test_sys_rand(void)
{
	char str[64];
	uint8_t buf[64];

	volatile uint16_t u16 = rand_u16();
	volatile uint32_t u32 = rand_u32();
	volatile uint64_t u64 = rand_u64();
	volatile char ch      = rand_char();

	(void)u16;
	(void)u32;
	(void)u64;
	(void)ch;

	rand_str(str, sizeof(str));
	rand_bytes(buf, sizeof(buf));

	return 0;
}
Beispiel #6
0
Datei: rtp.c Projekt: hbowden/re
/**
 * Allocate a new RTP socket
 *
 * @param rsp Pointer to returned RTP socket
 *
 * @return 0 for success, otherwise errorcode
 */
int rtp_alloc(struct rtp_sock **rsp)
{
	struct rtp_sock *rs;

	if (!rsp)
		return EINVAL;

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

	sa_init(&rs->rtcp_peer, AF_UNSPEC);

	rs->enc.seq  = rand_u16() & 0x7fff;
	rs->enc.ssrc = rand_u32();

	*rsp = rs;

	return 0;
}
Beispiel #7
0
Datei: rtp.c Projekt: hbowden/re
static int udp_range_listen(struct rtp_sock *rs, const struct sa *ip,
			    uint16_t min_port, uint16_t max_port)
{
	struct sa rtcp;
	int tries = 64;
	int err = 0;

	rs->local = rtcp = *ip;

	/* try hard */
	while (tries--) {
		struct udp_sock *us_rtp, *us_rtcp;
		uint16_t port;

		port = (min_port + (rand_u16() % (max_port - min_port)));
		port &= 0xfffe;

		sa_set_port(&rs->local, port);
		err = udp_listen(&us_rtp, &rs->local, udp_recv_handler, rs);
		if (err)
			continue;

		sa_set_port(&rtcp, port + 1);
		err = udp_listen(&us_rtcp, &rtcp, rtcp_recv_handler, rs);
		if (err) {
			mem_deref(us_rtp);
			continue;
		}

		/* OK */
		rs->sock_rtp = us_rtp;
		rs->sock_rtcp = us_rtcp;
		break;
	}

	return err;
}
Beispiel #8
0
int audio_alloc(struct audio **ap, const struct config *cfg,
		struct call *call, struct sdp_session *sdp_sess, int label,
		const struct mnat *mnat, struct mnat_sess *mnat_sess,
		const struct menc *menc, struct menc_sess *menc_sess,
		uint32_t ptime, const struct list *aucodecl,
		audio_event_h *eventh, audio_err_h *errh, void *arg)
{
	struct audio *a;
	struct autx *tx;
	struct aurx *rx;
	struct le *le;
	int err;

	if (!ap || !cfg)
		return EINVAL;

	a = mem_zalloc(sizeof(*a), audio_destructor);
	if (!a)
		return ENOMEM;

	MAGIC_INIT(a);

	a->cfg = cfg->audio;
	tx = &a->tx;
	rx = &a->rx;

	err = stream_alloc(&a->strm, &cfg->avt, call, sdp_sess,
			   "audio", label,
			   mnat, mnat_sess, menc, menc_sess,
			   call_localuri(call),
			   stream_recv_handler, NULL, a);
	if (err)
		goto out;

	if (cfg->avt.rtp_bw.max) {
		stream_set_bw(a->strm, AUDIO_BANDWIDTH);
	}

	err = sdp_media_set_lattr(stream_sdpmedia(a->strm), true,
				  "ptime", "%u", ptime);
	if (err)
		goto out;

	/* Audio codecs */
	for (le = list_head(aucodecl); le; le = le->next) {
		err = add_audio_codec(a, stream_sdpmedia(a->strm), le->data);
		if (err)
			goto out;
	}

	tx->mb = mbuf_alloc(STREAM_PRESZ + 4096);
	tx->sampv = mem_zalloc(AUDIO_SAMPSZ * 2, NULL);
	rx->sampv = mem_zalloc(AUDIO_SAMPSZ * 2, NULL);
	if (!tx->mb || !tx->sampv || !rx->sampv) {
		err = ENOMEM;
		goto out;
	}

	err = telev_alloc(&a->telev, TELEV_PTIME);
	if (err)
		goto out;

	err = add_telev_codec(a);
	if (err)
		goto out;

	auresamp_init(&tx->resamp);
	str_ncpy(tx->device, a->cfg.src_dev, sizeof(tx->device));
	tx->ptime  = ptime;
	tx->ts     = rand_u16();
	tx->marker = true;

	auresamp_init(&rx->resamp);
	str_ncpy(rx->device, a->cfg.play_dev, sizeof(rx->device));
	rx->pt     = -1;
	rx->ptime  = ptime;

	a->eventh  = eventh;
	a->errh    = errh;
	a->arg     = arg;

	if (a->cfg.txmode == AUDIO_MODE_TMR)
		tmr_init(&tx->u.tmr);

 out:
	if (err)
		mem_deref(a);
	else
		*ap = a;

	return err;
}
Beispiel #9
0
/**
 * Accept and create a SIP Dialog from an incoming SIP Message
 *
 * @param dlgp Pointer to allocated SIP Dialog
 * @param msg  SIP Message
 *
 * @return 0 if success, otherwise errorcode
 */
int sip_dialog_accept(struct sip_dialog **dlgp, 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 || !msg || !msg->req)
		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->lseq = rand_u16();
	dlg->rseq = msg->cseq.num;

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

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

	err = x64_strdup(&dlg->ltag, msg->tag);
	if (err)
		goto out;

	err = pl_strdup(&dlg->rtag, &msg->from.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, true, SIP_HDR_RECORD_ROUTE,
				 record_route_handler, &renc) ? ENOMEM : 0;
	err |= mbuf_printf(dlg->mb, "To: %r\r\n", &msg->from.val);
	err |= mbuf_printf(dlg->mb, "From: %r;tag=%016llx\r\n", &msg->to.val,
			   msg->tag);
	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;
}
Beispiel #10
0
int audio_alloc2(struct audio **ap, const struct config *cfg,
		const char* forced_src_mod, const char* forced_dev_name,
		struct sdp_media * sdp,
		uint32_t ptime,
		audio_event_h *eventh, audio_err_h *errh, void *arg)
{
	struct audio *a;
	struct autx *tx;
	struct aurx *rx;
	struct le *le;
	int err;

	if (!ap || !cfg) return EINVAL;

	a = mem_zalloc(sizeof(*a), audio_destructor);
	if (!a) return ENOMEM;

	MAGIC_INIT(a);

	a->cfg = cfg->audio;
	if (forced_src_mod) {
		str_ncpy(a->cfg.src_mod, forced_src_mod, sizeof(a->cfg.src_mod));
	}
	if (forced_dev_name) {
    	str_ncpy(a->cfg.src_dev, forced_dev_name, sizeof(a->cfg.src_dev));
	}

	tx = &a->tx;
	rx = &a->rx;

	err = stream_alloc2(&a->strm, &cfg->avt, sdp, AF_INET, "audio", 0, stream_recv_handler, NULL, a);
	if (err) goto out;

	stream_set_bw(a->strm, AUDIO_BANDWIDTH);

	tx->mb = mbuf_alloc(STREAM_PRESZ + 4096);
	tx->sampv = mem_zalloc(AUDIO_SAMPSZ * 2, NULL);
	rx->sampv = mem_zalloc(AUDIO_SAMPSZ * 2, NULL);
	if (!tx->mb || !tx->sampv || !rx->sampv) {
		err = ENOMEM;
		goto out;
	}

	str_ncpy(tx->device, a->cfg.src_dev, sizeof(tx->device));
	tx->ptime  = ptime;
	tx->ts     = rand_u16();
	tx->marker = true;

	str_ncpy(rx->device, a->cfg.play_dev, sizeof(rx->device));
	rx->pt     = -1;
	rx->ptime  = ptime;

	a->eventh  = eventh;
	a->errh    = errh;
	a->arg     = arg;

	if (a->cfg.txmode == AUDIO_MODE_TMR) {
		tmr_init(&tx->u.tmr);
	}

 out:
	if (err) {
		mem_deref(a);
	} else {
		*ap = a;
	}

	return err;
}
Beispiel #11
0
/**
 * Allocate a SIP Dialog
 *
 * @param dlgp      Pointer to allocated SIP Dialog
 * @param uri       Target URI
 * @param to_uri    To URI
 * @param from_name From displayname (optional)
 * @param from_uri  From URI
 * @param routev    Route vector
 * @param routec    Route count
 *
 * @return 0 if success, otherwise errorcode
 */
int sip_dialog_alloc(struct sip_dialog **dlgp,
		     const char *uri, const char *to_uri,
		     const char *from_name, const char *from_uri,
		     const char *routev[], uint32_t routec)
{
	const uint64_t ltag = rand_u64();
	struct sip_dialog *dlg;
	struct sip_addr addr;
	size_t rend = 0;
	struct pl pl;
	uint32_t i;
	int err;

	if (!dlgp || !uri || !to_uri || !from_uri)
		return EINVAL;

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

	dlg->lseq = rand_u16();

	err = str_dup(&dlg->uri, uri);
	if (err)
		goto out;

	err = x64_strdup(&dlg->callid, rand_u64());
	if (err)
		goto out;

	err = x64_strdup(&dlg->ltag, ltag);
	if (err)
		goto out;

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

	for (i=0; i<routec; i++) {
		err |= mbuf_printf(dlg->mb, "Route: <%s;lr>\r\n", routev[i]);
		if (i == 0)
			rend = dlg->mb->pos - 2;
	}
	err |= mbuf_printf(dlg->mb, "To: <%s>\r\n", to_uri);
	dlg->cpos = dlg->mb->pos;
	err |= mbuf_printf(dlg->mb, "From: %s%s%s<%s>;tag=%016llx\r\n",
			   from_name ? "\"" : "", from_name,
			   from_name ? "\" " : "",
			   from_uri, ltag);
	if (err)
		goto out;

	dlg->mb->pos = 0;

	if (rend) {
		pl.p = (const char *)mbuf_buf(dlg->mb) + ROUTE_OFFSET;
		pl.l = rend - 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;
}
Beispiel #12
0
static uint32_t failwait(uint32_t failc)
{
	return min(1800, (30 * (1<<min(failc, 6)))) * (500 + rand_u16() % 501);
}
Beispiel #13
0
int test_rtp(void)
{
	struct rtp_sock *rtp = NULL;
	struct mbuf *mb = NULL;
	uint8_t payload[PAYLOAD_SIZE];
	int j;
	int err;

	memset(payload, 0, sizeof(payload));

	mb = mbuf_alloc(RTP_HEADER_SIZE);
	if (!mb)
		return ENOMEM;

	err = rtp_alloc(&rtp);
	if (err)
		goto out;

	for (j=0; j<100; j++) {
		struct rtp_header hdr, hdr2;

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

		hdr.m  = rand_u16() & 0x01;
		hdr.pt = rand_u16() & 0x7f;
		hdr.ts = rand_u32();
		rand_bytes(payload, sizeof(payload));

		mb->pos = mb->end = RTP_HEADER_SIZE;
		err = mbuf_write_mem(mb, payload, sizeof(payload));
		if (err)
			break;

		mb->pos = 0;
		err = rtp_encode(rtp, hdr.m, hdr.pt, hdr.ts, mb);
		if (err)
			break;

		mb->pos = 0;

		err = rtp_decode(rtp, mb, &hdr2);
		if (err)
			break;

		if (hdr.m != hdr2.m) {
			DEBUG_WARNING("marker bit mismatch (%d != %d)\n",
				      hdr.m, hdr2.m);
			err = EBADMSG;
			break;
		}

		if (hdr.pt != hdr2.pt) {
			DEBUG_WARNING("payload type mismatch (%u != %u)\n",
				      hdr.pt, hdr2.pt);
			err = EBADMSG;
			break;
		}

		if (hdr.ts != hdr2.ts) {
			DEBUG_WARNING("timestamp mismatch (%lu != %lu)\n",
				      hdr.ts, hdr2.ts);
			err = EBADMSG;
			break;
		}

		if (hdr2.pad) {
			DEBUG_WARNING("unexpected padding bit\n");
			err = EBADMSG;
			break;
		}

		if (hdr2.ext) {
			DEBUG_WARNING("unexpected extension bit\n");
			err = EBADMSG;
			break;
		}

		if (RTP_HEADER_SIZE != mb->pos ||
		    (RTP_HEADER_SIZE + PAYLOAD_SIZE) != mb->end) {
			DEBUG_WARNING("invalid mbuf size (pos=%u end=%u)\n",
				      mb->pos, mb->end);
			err = EBADMSG;
			break;
		}

		if (0 != memcmp(mbuf_buf(mb), payload, sizeof(payload))) {
			DEBUG_WARNING("RTP payload mismatch\n");
			err = EBADMSG;
			break;
		}
	}

 out:
	mem_deref(rtp);
	mem_deref(mb);

	return err;
}
Beispiel #14
0
int main()
{
    alloc_init();

    flog_config_modes(LOG_MODE_ERROR | LOG_MODE_WARN);
    flog_config_destinations(LOG_DEST_STDF);

    assert_data_folder_exists();


    fprintf(stderr, "This process aims to reduce the bit distribution variance \
of the data.\nWhen you are satisfied press ENTER\n\n");

    u64 iv[TOTAL_BOARD_SIZ][2];
    memset(iv, 0, TOTAL_BOARD_SIZ * sizeof(u64));

    u32 table_size = TOTAL_BOARD_SIZ * 2;
    u64 * table = (u64 *)malloc(table_size * sizeof(u64));
    u32 bits[64];
    double best_variance = 999999.0;
    fd_set readfs;
    memset(&readfs, 0, sizeof(fd_set));

    while(best_variance > 0.0)
    {
        rand_reinit();
        for(u32 attempts = 0; attempts < 100; ++attempts)
        {
            for(u32 i = 0; i < table_size; ++i)
            {
                do
                {
                    table[i] = 0;
                    for(u32 j = 0; j < 64; ++j)
                        table[i] = (table[i] << 1) | rand_u16(2);

                    bool found = false;
                    for(u32 j = 0; j < i; ++j)
                        if(table[i] == table[j])
                        {
                            found = true;
                            break;
                        }
                    if(found)
                        continue;
                }
                while(count_bits(table[i]) != 32);
            }

            memset(bits, 0, sizeof(u32) * 64);
            for(u32 i = 0; i < table_size; ++i)
                for(u32 b = 0; b < 64; ++b)
                    if((table[i] >> b) & 1)
                        ++bits[b];


            u32 total = 0;
            for(u32 b = 0; b < 64; ++b)
                total += bits[b];
            double average = ((double)total) / ((double)64);

            double variance = 0.0;
            for(u32 b = 0; b < 64; ++b)
                variance += (((double)bits[b]) - average) * (((double)bits[b]) -
                    average);
            variance = variance / ((double)64);

            if(variance < best_variance)
            {
                best_variance = variance;
                memcpy(iv, table, sizeof(u64) * table_size);
                fprintf(stderr, "\rBest variance=%5f ", best_variance);
                fflush(stderr);
            }
        }

        FD_ZERO(&readfs);
        FD_SET(STDIN_FILENO, &readfs);
        struct timeval tm;
        tm.tv_sec = 0;
        tm.tv_usec = 0;

        int ready = select(STDIN_FILENO + 1, &readfs, NULL, NULL, &tm);
        if(ready > 0)
            break;
    }

    free(table);

    fprintf(stderr, "\nSearch stopped.\n");

    char * filename = alloc();
    snprintf(filename, MAX_PAGE_SIZ, "%s%ux%u.zt.new", data_folder(),
        BOARD_SIZ, BOARD_SIZ);


    FILE * h = fopen(filename, "wb");
    if(h == NULL)
    {
        fprintf(stderr, "Error: failed to open file %s for writing\n",
            filename);
        release(filename);
        exit(EXIT_FAILURE);
    }

    size_t w = fwrite(iv, sizeof(u64), TOTAL_BOARD_SIZ * 2, h);
    if(w != TOTAL_BOARD_SIZ * 2)
    {
        fprintf(stderr, "Error: unexpected number of bytes written\n");
        release(filename);
        exit(EXIT_FAILURE);
    }

    fclose(h);

    fprintf(stderr, "Zobrist table written to %s\n", filename);
    release(filename);
    return EXIT_SUCCESS;
}
Beispiel #15
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;
}
Beispiel #16
0
uint64_t sip_keepalive_wait(uint32_t interval)
{
    return interval * (800 + rand_u16() % 201);
}
Beispiel #17
0
int bfcp_alloc(struct bfcp **bfcpp, struct sdp_session *sdp_sess,
	       const char *proto, bool offerer,
	       const struct mnat *mnat, struct mnat_sess *mnat_sess)
{
	struct bfcp *bfcp;
	struct sa laddr;
	enum bfcp_transp transp;
	int err;

	if (!bfcpp || !sdp_sess)
		return EINVAL;

	transp = str2tp(proto);

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

	bfcp->active = offerer;

	sa_init(&laddr, AF_INET);

	err = bfcp_listen(&bfcp->conn, transp, &laddr, uag_tls(),
			  bfcp_msg_handler, bfcp);
	if (err)
		goto out;

	err = sdp_media_add(&bfcp->sdpm, sdp_sess, "application",
			    sa_port(&laddr), bfcp_sdp_transp(transp));
	if (err)
		goto out;

	err = sdp_format_add(NULL, bfcp->sdpm, false, "*", NULL,
			     0, 0, NULL, NULL, NULL, false, NULL);
	if (err)
		goto out;

	err |= sdp_media_set_lattr(bfcp->sdpm, true, "floorctrl", "c-s");
	err |= sdp_media_set_lattr(bfcp->sdpm, true, "setup",
				   bfcp->active ? "active" : "actpass");

	if (bfcp->active) {
		err |= sdp_media_set_lattr(bfcp->sdpm, true,
					   "connection", "new");
	}
	else {
		bfcp->lconfid = 1000 + (rand_u16() & 0xf);
		bfcp->luserid = 1    + (rand_u16() & 0x7);

		err |= sdp_media_set_lattr(bfcp->sdpm, true, "confid",
					   "%u", bfcp->lconfid);
		err |= sdp_media_set_lattr(bfcp->sdpm, true, "userid",
					   "%u", bfcp->luserid);
	}

	if (err)
		goto out;

	if (mnat) {
		info("bfcp: enabled medianat '%s' on UDP socket\n", mnat->id);

		err = mnat->mediah(&bfcp->mnat_st, mnat_sess, IPPROTO_UDP,
				   bfcp_sock(bfcp->conn), NULL, bfcp->sdpm);
		if (err)
			goto out;
	}

	info("bfcp: %s BFCP agent protocol '%s' on port %d\n",
	     bfcp->active ? "Active" : "Passive",
	     proto, sa_port(&laddr));

 out:
	if (err)
		mem_deref(bfcp);
	else
		*bfcpp = bfcp;

	return err;
}