/* ts: only for accept */ int trice_conn_alloc(struct list *connl, struct trice *icem, unsigned compid, bool active, const struct sa *laddr, const struct sa *peer, struct tcp_sock *ts, int layer, tcpconn_frame_h *frameh, void *arg) { struct ice_tcpconn *conn; int err = 0; if (!connl || !icem || !laddr || !peer || !frameh) return EINVAL; conn = mem_zalloc(sizeof(*conn), conn_destructor); if (!conn) return ENOMEM; conn->icem = icem; conn->active = active; conn->paddr = *peer; conn->compid = compid; conn->layer = layer; conn->frameh = frameh; conn->arg = arg; if (active) { trice_printf(conn->icem, "<%p> TCP connecting" " [laddr=%J paddr=%J] ..\n", icem, laddr, peer); /* This connection is opened from the local candidate of the pair to the remote candidate of the pair. */ err = tcp_conn_alloc(&conn->tc, peer, tcp_estab_handler, NULL, tcp_close_handler, conn); if (err) { DEBUG_WARNING("tcp_conn_alloc [peer=%J] (%m)\n", peer, err); goto out; } err = tcp_conn_bind(conn->tc, laddr); if (err) { DEBUG_WARNING("tcp_conn_bind [laddr=%J paddr=%J]" " (%m)\n", laddr, peer, err); goto out; } err = tcp_conn_connect(conn->tc, peer); if (err) { /* NOTE: this happens sometimes on OSX when * setting up two S-O connections */ if (err == EADDRINUSE) { re_printf("EADDRINUSE\n"); err = 0; } else { DEBUG_NOTICE("tcp_conn_connect [peer=%J]" " (%d/%m)\n", peer, err, err); goto out; } } } else { err = tcp_accept(&conn->tc, ts, tcp_estab_handler, NULL, tcp_close_handler, conn); if (err) { tcp_reject(ts); goto out; } } err = tcp_conn_local_get(conn->tc, &conn->laddr); if (err) goto out; list_append(connl, &conn->le, conn); out: if (err) mem_deref(conn); return err; }
static int media_pwd_decode(struct icem *icem, const char *value) { icem->rpwd = mem_deref(icem->rpwd); return str_dup(&icem->rpwd, value); }
/** * 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; }
int net_rt_list(net_rt_h *rth, void *arg) { /* net.route.0.inet.flags.gateway */ int mib[] = {CTL_NET, PF_ROUTE, 0, AF_UNSPEC, NET_RT_FLAGS, RTF_GATEWAY}; char ifname[IFNAMSIZ], *buf, *p; struct rt_msghdr *rt; struct sockaddr *sa, *sa_tab[RTAX_MAX]; struct sa dst, gw; size_t l; int i, err = 0; if (sysctl(mib, sizeof(mib)/sizeof(int), 0, &l, 0, 0) < 0) return errno; if (!l) return ENOENT; buf = mem_alloc(l, NULL); if (!buf) return ENOMEM; if (sysctl(mib, sizeof(mib)/sizeof(int), buf, &l, 0, 0) < 0) { err = errno; goto out; } for (p = buf; p<buf+l; p += rt->rtm_msglen) { rt = (void *)p; /* buffer is aligned */ sa = (struct sockaddr *)(rt + 1); if (rt->rtm_type != RTM_GET) continue; if (!(rt->rtm_flags & RTF_UP)) continue; for (i=0; i<RTAX_MAX; i++) { if (rt->rtm_addrs & (1 << i)) { sa_tab[i] = sa; sa = (struct sockaddr *) ((char *)sa + ROUNDUP(sa->sa_len)); } else { sa_tab[i] = NULL; } } if ((rt->rtm_addrs & RTA_DST) == RTA_DST) { err = sa_set_sa(&dst, sa_tab[RTAX_DST]); if (err) continue; } if ((rt->rtm_addrs & RTA_GATEWAY) == RTA_GATEWAY) { err = sa_set_sa(&gw, sa_tab[RTAX_GATEWAY]); if (err) continue; } if_indextoname(rt->rtm_index, ifname); if (rth(ifname, &dst, 0, &gw, arg)) break; } out: mem_deref(buf); return err; }
static int mod_gst_close(void) { gst_deinit(); ausrc = mem_deref(ausrc); return 0; }
static void aufilt_elem_destructor(void *arg) { struct aufilt_elem *f = arg; list_unlink(&f->le); mem_deref(f->st); }
static int alloc(struct vidsrc_st **stp, 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; (void)ctx; (void)prm; (void)fmt; (void)errorh; if (!stp || !size || !frameh) return EINVAL; if (!str_isset(dev)) dev = "/dev/video0"; st = mem_zalloc(sizeof(*st), destructor); if (!st) return ENOMEM; st->vs = mem_ref(vs); st->fd = -1; st->size = *size; st->frameh = frameh; st->arg = arg; info("v4l: open: %s (%u x %u)\n", dev, size->w, size->h); err = vd_open(st, dev); if (err) goto out; v4l_get_caps(st); err = v4l_check_palette(st); if (err) goto out; err = v4l_get_win(st->fd, st->size.w, st->size.h); if (err) goto out; /* note: assumes RGB24 */ st->mb = mbuf_alloc(rgb24_size(&st->size)); if (!st->mb) { err = ENOMEM; goto out; } 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; }
int test_stun_req(void) { struct stun_msg *msg = NULL; struct mbuf *mb; struct stun_attr *attr; int err; mb = mbuf_alloc(1024); if (!mb) { err = ENOMEM; goto out; } err = stun_msg_encode(mb, STUN_METHOD_BINDING, STUN_CLASS_REQUEST, tid, NULL, (uint8_t *)password.p, password.l, true, 0x20, 4, STUN_ATTR_SOFTWARE, client_sw, STUN_ATTR_PRIORITY, &ice_prio, STUN_ATTR_CONTROLLED, &ice_contr, STUN_ATTR_USERNAME, username); if (err) goto out; TEST_MEMCMP(req, sizeof(req)-1, mb->buf, mb->end); /* Decode STUN message */ mb->pos = 0; err = stun_msg_decode(&msg, mb, NULL); if (err) goto out; if (STUN_CLASS_REQUEST != stun_msg_class(msg)) goto bad; if (STUN_METHOD_BINDING != stun_msg_method(msg)) goto out; err = stun_msg_chk_mi(msg, (uint8_t *)password.p, password.l); if (err) goto out; err = stun_msg_chk_fingerprint(msg); if (err) goto out; attr = stun_msg_attr(msg, STUN_ATTR_PRIORITY); if (!attr || ice_prio != attr->v.priority) goto bad; attr = stun_msg_attr(msg, STUN_ATTR_CONTROLLED); if (!attr || ice_contr != attr->v.controlled) goto bad; attr = stun_msg_attr(msg, STUN_ATTR_USERNAME); if (!attr || strcmp(username, attr->v.username)) goto bad; attr = stun_msg_attr(msg, STUN_ATTR_SOFTWARE); if (!attr || strcmp(client_sw, attr->v.software)) goto bad; goto out; bad: err = EBADMSG; out: mem_deref(msg); mem_deref(mb); return err; }
static void mbuf_destructor(void *data) { struct mbuf *mb = data; mem_deref(mb->buf); }
static int test_stun_request(int proto, bool natted) { struct stunserver *srv = NULL; struct stun_ctrans *ct = NULL; struct nat *nat = NULL; struct test test; struct sa laddr, public_addr; int err; memset(&test, 0, sizeof(test)); err = stunserver_alloc(&srv); if (err) goto out; err = stun_alloc(&test.stun, NULL, NULL, NULL); if (err) goto out; if (proto == IPPROTO_UDP) { err = sa_set_str(&laddr, "127.0.0.1", 0); TEST_ERR(err); err = udp_listen(&test.us, &laddr, udp_recv_handler, &test); if (err) goto out; err = udp_local_get(test.us, &laddr); TEST_ERR(err); } if (natted) { err = sa_set_str(&public_addr, "4.5.6.7", 0); TEST_ERR(err); err = nat_alloc(&nat, srv->us, &public_addr); if (err) goto out; sa_set_port(&public_addr, sa_port(&laddr)); } else { public_addr = laddr; } err = stun_request(&ct, test.stun, proto, test.us, stunserver_addr(srv, proto), 0, STUN_METHOD_BINDING, NULL, 0, true, stun_resp_handler, &test, 0); if (err) goto out; TEST_ASSERT(ct != NULL); err = re_main_timeout(100); if (err) goto out; if (srv->err) { err = srv->err; goto out; } if (test.err) { err = test.err; goto out; } /* verify results */ TEST_ASSERT(srv->nrecv >= 1); TEST_EQUALS(1, test.n_resp); if (proto == IPPROTO_UDP) { TEST_SACMP(&public_addr, &test.mapped_addr, SA_ALL); } out: mem_deref(test.stun); mem_deref(test.us); mem_deref(nat); mem_deref(srv); return err; }
static int test_stun_req_attributes(void) { struct stun_msg *msg = NULL; struct mbuf *mb; struct stun_attr *attr; const uint64_t rsv_token = 0x1100c0ffee; const uint32_t lifetime = 3600; const uint16_t chan = 0x4000; const uint8_t req_addr_fam = AF_INET; int err; mb = mbuf_alloc(1024); if (!mb) { err = ENOMEM; goto out; } err = stun_msg_encode(mb, STUN_METHOD_BINDING, STUN_CLASS_REQUEST, tid, NULL, NULL, 0, false, 0x00, 4, STUN_ATTR_REQ_ADDR_FAMILY, &req_addr_fam, STUN_ATTR_CHANNEL_NUMBER, &chan, STUN_ATTR_LIFETIME, &lifetime, STUN_ATTR_RSV_TOKEN, &rsv_token); if (err) goto out; /* Decode STUN message */ mb->pos = 0; err = stun_msg_decode(&msg, mb, NULL); if (err) goto out; TEST_EQUALS(STUN_CLASS_REQUEST, stun_msg_class(msg)); TEST_EQUALS(STUN_METHOD_BINDING, stun_msg_method(msg)); /* verify integer attributes of different sizes */ /* 8-bit */ attr = stun_msg_attr(msg, STUN_ATTR_REQ_ADDR_FAMILY); TEST_ASSERT(attr != NULL); TEST_EQUALS(req_addr_fam, attr->v.req_addr_family); /* 16-bit */ attr = stun_msg_attr(msg, STUN_ATTR_CHANNEL_NUMBER); TEST_ASSERT(attr != NULL); TEST_EQUALS(chan, attr->v.channel_number); /* 32-bit */ attr = stun_msg_attr(msg, STUN_ATTR_LIFETIME); TEST_ASSERT(attr != NULL); TEST_EQUALS(lifetime, attr->v.lifetime); /* 64-bit */ attr = stun_msg_attr(msg, STUN_ATTR_RSV_TOKEN); TEST_ASSERT(attr != NULL); TEST_EQUALS(rsv_token, attr->v.rsv_token); out: mem_deref(msg); mem_deref(mb); return err; }
int test_stun_reqltc(void) { struct stun_msg *msg = NULL; struct stun_attr *attr; struct mbuf *mb; uint8_t md5_hash[MD5_SIZE]; int r, err; mb = mbuf_alloc(1024); if (!mb) { err = ENOMEM; goto out; } /* use long-term credentials */ err = md5_printf(md5_hash, "%s:%s:%s", username_ltc, realm_ltc, password_ltc); if (err) goto out; err = stun_msg_encode(mb, STUN_METHOD_BINDING, STUN_CLASS_REQUEST, tid_ltc, NULL, md5_hash, sizeof(md5_hash), false, 0x00, 3, STUN_ATTR_USERNAME, username_ltc, STUN_ATTR_NONCE, nonce_ltc, STUN_ATTR_REALM, realm_ltc); if (err) goto out; r = memcmp(mb->buf, reqltc, mb->end); if ((sizeof(reqltc)-1) != mb->end || 0 != r) { err = EBADMSG; DEBUG_WARNING("compare failed (r=%d)\n", r); (void)re_printf("msg: [%02w]\n", mb->buf, mb->end); (void)re_printf("ref: [%02w]\n", reqltc, sizeof(reqltc)-1); goto out; } /* Decode STUN message */ mb->pos = 0; err = stun_msg_decode(&msg, mb, NULL); if (err) goto out; if (STUN_CLASS_REQUEST != stun_msg_class(msg)) goto bad; if (STUN_METHOD_BINDING != stun_msg_method(msg)) goto bad; err = stun_msg_chk_mi(msg, md5_hash, sizeof(md5_hash)); if (err) goto out; if (EPROTO != stun_msg_chk_fingerprint(msg)) goto bad; attr = stun_msg_attr(msg, STUN_ATTR_USERNAME); if (!attr || strcmp(username_ltc, attr->v.username)) goto bad; attr = stun_msg_attr(msg, STUN_ATTR_NONCE); if (!attr || strcmp(nonce_ltc, attr->v.nonce)) goto bad; attr = stun_msg_attr(msg, STUN_ATTR_REALM); if (!attr || strcmp(realm_ltc, attr->v.realm)) goto bad; goto out; bad: err = EBADMSG; out: mem_deref(msg); mem_deref(mb); return err; }
static int test_resp(const struct pl *resp, const struct sa *addr) { struct stun_msg *msg = NULL; struct stun_attr *attr; struct mbuf *mb = NULL; int err; mb = mbuf_alloc(1024); if (!mb) { err = ENOMEM; goto out; } err = stun_msg_encode(mb, STUN_METHOD_BINDING, STUN_CLASS_SUCCESS_RESP, tid, NULL, (uint8_t *)password.p, password.l, true, 0x20, 2, STUN_ATTR_SOFTWARE, server_sw, STUN_ATTR_XOR_MAPPED_ADDR, addr); if (err) goto out; if (resp->l != mb->end || 0 != memcmp(mb->buf, resp->p, mb->end)) { err = EBADMSG; DEBUG_WARNING("compare failed (%J)\n", addr); (void)re_printf("msg: [%02w]\n", mb->buf, mb->end); (void)re_printf("ref: [%02w]\n", resp->p, resp->l); goto out; } /* Decode STUN message */ mb->pos = 0; err = stun_msg_decode(&msg, mb, NULL); if (err) goto out; if (STUN_CLASS_SUCCESS_RESP != stun_msg_class(msg)) goto bad; if (STUN_METHOD_BINDING != stun_msg_method(msg)) goto bad; err = stun_msg_chk_mi(msg, (uint8_t *)password.p, password.l); if (err) goto out; err = stun_msg_chk_fingerprint(msg); if (err) goto out; attr = stun_msg_attr(msg, STUN_ATTR_XOR_MAPPED_ADDR); if (!attr || !sa_cmp(&attr->v.xor_mapped_addr, addr, SA_ALL)) goto bad; attr = stun_msg_attr(msg, STUN_ATTR_SOFTWARE); if (!attr || strcmp(server_sw, attr->v.software)) goto bad; goto out; bad: err = EBADMSG; out: mem_deref(msg); mem_deref(mb); return err; }
int png_save_vidframe(const struct vidframe *vf, const char *path) { png_byte **png_row_pointers = NULL; png_byte *row; const png_byte *p; png_byte red, green, blue; png_structp png_ptr = NULL; png_infop info_ptr = NULL; FILE *fp = NULL; size_t x, y; unsigned int width = vf->size.w & ~1; unsigned int height = vf->size.h & ~1; unsigned int bytes_per_pixel = 3; /* RGB format */ time_t tnow; struct tm *tmx; char filename_buf[64]; struct vidframe *f2 = NULL; int err = 0; tnow = time(NULL); tmx = localtime(&tnow); if (vf->fmt != VID_FMT_RGB32) { err = vidframe_alloc(&f2, VID_FMT_RGB32, &vf->size); if (err) goto out; vidconv(f2, vf, NULL); vf = f2; } /* Initialize the write struct. */ png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { err = ENOMEM; goto out; } /* Initialize the info struct. */ info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { err = ENOMEM; goto out; } /* Set up error handling. */ if (setjmp(png_jmpbuf(png_ptr))) { err = ENOMEM; goto out; } /* Set image attributes. */ png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); /* Initialize rows of PNG * bytes_per_row = width * bytes_per_pixel; */ png_row_pointers = png_malloc(png_ptr, height * sizeof(png_byte *)); for (y = 0; y < height; ++y) { png_row_pointers[y] = (png_byte *) png_malloc(png_ptr, width * sizeof(uint8_t) * bytes_per_pixel); } p = vf->data[0]; for (y = 0; y < height; ++y) { row = png_row_pointers[y]; for (x = 0; x < width; ++x) { red = *p++; green = *p++; blue = *p++; *row++ = blue; *row++ = green; *row++ = red; ++p; /* skip alpha */ } } /* Write the image data. */ fp = fopen(png_filename(tmx, path, filename_buf, sizeof(filename_buf)), "wb"); if (fp == NULL) { err = errno; goto out; } png_init_io(png_ptr, fp); png_set_rows(png_ptr, info_ptr, png_row_pointers); png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); info("png: wrote %s\n", filename_buf); out: /* Finish writing. */ mem_deref(f2); png_save_free(png_ptr, png_row_pointers, height); png_destroy_write_struct(&png_ptr, &info_ptr); if (fp) fclose(fp); return 0; }
static void oa_reset(struct oa *oa) { oa->alice = mem_deref(oa->alice); oa->bob = mem_deref(oa->bob); }
/** * 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; }
/** Test BFCP in SDP -- RFC 4583 */ int test_sdp_bfcp(void) { static const char *msg_offer = "v=0\r\n" "o=alice 2890844526 2890844526 IN IP4 1.2.3.4\r\n" "s=-\r\n" "c=IN IP4 1.2.3.4\r\n" "t=0 0\r\n" "m=application 50000 TCP/BFCP *\r\n" "a=sendrecv\r\n" "a=setup:passive\r\n" "a=connection:new\r\n" "a=floorctrl:s-only\r\n" "a=confid:4321\r\n" "a=userid:1234\r\n" "a=floorid:1 m-stream:10\r\n" "a=floorid:2 m-stream:11\r\n" "m=audio 50002 RTP/AVP 0\r\n" "a=sendrecv\r\n" "a=label:10\r\n" "m=video 50004 RTP/AVP 31\r\n" "a=sendrecv\r\n" "a=label:11\r\n" ; struct sdp_session *alice = NULL, *bob = NULL; struct sdp_media *bfcp, *audio, *video; struct mbuf *mbo = NULL, *mba = NULL; struct sa laddr; int err; /* create sessions */ (void)sa_set_str(&laddr, "1.2.3.4", 0); err = sdp_session_alloc(&alice, &laddr); if (err) goto out; err = sdp_media_add(&bfcp, alice, "application", 50000, "TCP/BFCP"); if (err) goto out; err |= sdp_media_set_lattr(bfcp, true, "setup", "passive"); err |= sdp_media_set_lattr(bfcp, true, "connection", "new"); err |= sdp_media_set_lattr(bfcp, true, "floorctrl", "s-only"); err |= sdp_media_set_lattr(bfcp, true, "confid", "4321"); err |= sdp_media_set_lattr(bfcp, true, "userid", "1234"); err |= sdp_media_set_lattr(bfcp, false, "floorid", "1 m-stream:10"); sdp_media_del_lattr(bfcp, "floorid"); /* test attr delete */ err |= sdp_media_set_lattr(bfcp, false, "floorid", "1 m-stream:10"); err |= sdp_media_set_lattr(bfcp, false, "floorid", "2 m-stream:11"); if (err) goto out; err = sdp_media_add(&audio, alice, "audio", 50002, "RTP/AVP"); if (err) goto out; err = sdp_media_add(&video, alice, "video", 50004, "RTP/AVP"); if (err) goto out; err |= sdp_media_set_lattr(audio, true, "label", "10"); err |= sdp_media_set_lattr(video, true, "label", "11"); if (err) goto out; err = sdp_format_add(NULL, bfcp, false, "*", NULL, 0, 0, NULL, NULL, NULL, false, NULL); err |= sdp_format_add(NULL, audio, false, "0", NULL, 0, 0, NULL, NULL, NULL, false, NULL); err |= sdp_format_add(NULL, video, false, "31", NULL, 0, 0, NULL, NULL, NULL, false, NULL); if (err) goto out; /* create and send offer, compare offer */ err = sdp_encode(&mbo, alice, true); if (err) goto out; if (!sdp_cmp(mbo, msg_offer)) { DEBUG_WARNING("offer failed:\n%b", mbo->buf, mbo->end); err = EBADMSG; goto out; } out: mem_deref(alice); mem_deref(bob); mem_deref(mbo); mem_deref(mba); return err; }
/** * 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; }
static int alloc(struct menc_media **stp, struct menc_sess *sess, struct rtp_sock *rtp, int proto, void *rtpsock, void *rtcpsock, struct sdp_media *sdpm) { struct menc_st *st; const char *rattr = NULL; int layer = 10; /* above zero */ int err = 0; bool mux = (rtpsock == rtcpsock); (void)sess; (void)rtp; if (!stp || !sdpm) return EINVAL; if (proto != IPPROTO_UDP) return EPROTONOSUPPORT; st = (struct menc_st *)*stp; if (!st) { st = mem_zalloc(sizeof(*st), destructor); if (!st) return ENOMEM; st->sdpm = mem_ref(sdpm); err = sdp_media_set_alt_protos(st->sdpm, 4, "RTP/AVP", "RTP/AVPF", "RTP/SAVP", "RTP/SAVPF"); if (err) goto out; if (rtpsock) { st->rtpsock = mem_ref(rtpsock); err |= udp_register_helper(&st->uh_rtp, rtpsock, layer, send_handler, recv_handler, st); } if (rtcpsock && !mux) { st->rtcpsock = mem_ref(rtcpsock); err |= udp_register_helper(&st->uh_rtcp, rtcpsock, layer, send_handler, recv_handler, st); } if (err) goto out; /* set our preferred crypto-suite */ err |= str_dup(&st->crypto_suite, aes_cm_128_hmac_sha1_80); if (err) goto out; err = setup_srtp(st); if (err) goto out; } /* SDP handling */ if (sdp_media_rattr(st->sdpm, "crypto")) { rattr = sdp_media_rattr_apply(st->sdpm, "crypto", sdp_attr_handler, st); if (!rattr) { DEBUG_WARNING("no valid a=crypto attribute from" " remote peer\n"); } } if (!rattr) err = sdp_enc(st, sdpm, 0, st->crypto_suite); out: if (err) mem_deref(st); else *stp = (struct menc_media *)st; return err; }
/** * 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; }
static int v4l_close(void) { vidsrc = mem_deref(vidsrc); return 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; }
int coreaudio_player_alloc(struct auplay_st **stp, struct auplay *ap, struct auplay_prm *prm, const char *device, auplay_write_h *wh, void *arg) { AudioStreamBasicDescription fmt; struct auplay_st *st; uint32_t sampc, bytc, i; OSStatus status; int err; (void)device; st = mem_zalloc(sizeof(*st), auplay_destructor); if (!st) return ENOMEM; st->ap = mem_ref(ap); st->wh = wh; st->arg = arg; err = pthread_mutex_init(&st->mutex, NULL); if (err) goto out; err = audio_session_enable(); if (err) goto out; fmt.mSampleRate = (Float64)prm->srate; fmt.mFormatID = kAudioFormatLinearPCM; fmt.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked; #ifdef __BIG_ENDIAN__ fmt.mFormatFlags |= kAudioFormatFlagIsBigEndian; #endif fmt.mFramesPerPacket = 1; fmt.mBytesPerFrame = prm->ch * 2; fmt.mBytesPerPacket = prm->ch * 2; fmt.mChannelsPerFrame = prm->ch; fmt.mBitsPerChannel = 16; status = AudioQueueNewOutput(&fmt, play_handler, st, NULL, kCFRunLoopCommonModes, 0, &st->queue); if (status) { warning("coreaudio: AudioQueueNewOutput error: %i\n", status); err = ENODEV; goto out; } sampc = prm->srate * prm->ch * prm->ptime / 1000; bytc = sampc * 2; for (i=0; i<ARRAY_SIZE(st->buf); i++) { status = AudioQueueAllocateBuffer(st->queue, bytc, &st->buf[i]); if (status) { err = ENOMEM; goto out; } st->buf[i]->mAudioDataByteSize = bytc; memset(st->buf[i]->mAudioData, 0, st->buf[i]->mAudioDataByteSize); (void)AudioQueueEnqueueBuffer(st->queue, st->buf[i], 0, NULL); } status = AudioQueueStart(st->queue, NULL); if (status) { warning("coreaudio: AudioQueueStart error %i\n", status); err = ENODEV; goto out; } out: if (err) mem_deref(st); else *stp = st; return err; }
int test_rtcp_encode_afb(void) { uint32_t ssrc_packet_sender, ssrc_media_source; const char *afb_payload = "AFB tull"; struct rtcp_msg *msg = NULL; struct mbuf *mb; int err = 0; mb = mbuf_alloc(512); if (!mb) return ENOMEM; ssrc_packet_sender = 0xbad00bad; ssrc_media_source = 0; /* always 0 */ err = rtcp_encode(mb, RTCP_PSFB, RTCP_PSFB_AFB, ssrc_packet_sender, ssrc_media_source, afb_encode_handler, afb_payload); if (err) goto out; mb->pos = 0; err = rtcp_decode(&msg, mb); if (err) goto out; if (msg->hdr.count != RTCP_PSFB_AFB) { DEBUG_WARNING("expected AFB, got fmt=%u\n", msg->hdr.count); err = EPROTO; goto out; } if (msg->r.fb.ssrc_packet != ssrc_packet_sender || msg->r.fb.ssrc_media != ssrc_media_source) { DEBUG_WARNING("error in SSRC encoding\n"); err = EBADMSG; goto out; } if (!msg->r.fb.fci.afb || mbuf_get_left(msg->r.fb.fci.afb) != strlen(afb_payload)) { DEBUG_WARNING("error in AFB mbuf (left=%u, size=%u)\n", mbuf_get_left(msg->r.fb.fci.afb), strlen(afb_payload)); err = EBADMSG; goto out; } if (0 != memcmp(mbuf_buf(msg->r.fb.fci.afb), afb_payload, strlen(afb_payload))) { DEBUG_WARNING("error in AFB mbuf content\n"); err = EBADMSG; goto out; } /* verify that rtcp_decode() read the whole buffer */ TEST_EQUALS(mb->end, mb->pos); out: mem_deref(mb); mem_deref(msg); return err; }
static int media_ufrag_decode(struct icem *icem, const char *value) { icem->rufrag = mem_deref(icem->rufrag); return str_dup(&icem->rufrag, value); }
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; }
static void recv_handler(struct mbuf *mb, void *arg) { struct http_msg *msg = NULL; struct http_req *req = arg; size_t pos; int err; if (req->data) { if (req->datah) req->datah(mb, req->arg); return; } if (req->mb) { const size_t len = mbuf_get_left(mb); if ((mbuf_get_left(req->mb) + len) > BUFSIZE_MAX) { err = EOVERFLOW; goto out; } pos = req->mb->pos; req->mb->pos = req->mb->end; err = mbuf_write_mem(req->mb, mbuf_buf(mb), len); if (err) goto out; req->mb->pos = pos; } else { req->mb = mem_ref(mb); } pos = req->mb->pos; err = http_msg_decode(&msg, req->mb, false); if (err) { if (err == ENODATA) { req->mb->pos = pos; return; } goto out; } if (req->datah) { tmr_cancel(&req->tmr); req->data = true; if (req->resph) req->resph(0, msg, req->arg); mem_deref(msg); return; } if (mbuf_get_left(req->mb) < msg->clen) { req->mb->pos = pos; mem_deref(msg); return; } req->mb->end = req->mb->pos + msg->clen; out: req_close(req, err, msg); mem_deref(req); mem_deref(msg); }
int test_sdp_all(void) { struct sdp_session *sess = NULL; struct sdp_media *audio = NULL; struct mbuf *desc = NULL; struct sa ref; const struct sdp_format *rc = NULL, *sc; struct sa laddr; int err; (void)sa_set_str(&laddr, ref_host, 0); err = sdp_session_alloc(&sess, &laddr); if (err) goto out; err = sdp_media_add(&audio, sess, sdp_media_audio, 5004, sdp_proto_rtpavp); if (err) goto out; err = sdp_format_add(NULL, audio, false, ref_pt, ref_cname, ref_srate, 1, NULL, NULL, NULL, false, NULL); err |= sdp_format_add(NULL, audio, false, "110", cname_speex, 16000, 2, NULL, NULL, NULL, false, NULL); if (err) goto out; /* find codec - expected */ sc = sdp_media_format(audio, true, NULL, 0, "PCMU", 8000, 1); if (!sc) { DEBUG_WARNING("codec not found\n"); err = ENOENT; goto out; } sc = sdp_media_format(audio, true, NULL, 110, "Speex", 16000, 2); if (!sc) { DEBUG_WARNING("codec not found: speex\n"); err = ENOENT; goto out; } /* find codec - not expected */ sc = sdp_media_format(audio, true, NULL, -1, "Speex", 8000, 1); if (sc) { DEBUG_WARNING("unexpected codec found\n"); err = EINVAL; goto out; } err = sdp_encode(&desc, sess, true); if (err) goto out; if (!sdp_cmp(desc, ref_msg)) { DEBUG_WARNING("ref: %s\n", ref_msg); DEBUG_WARNING("sdp: %b\n", desc->buf, desc->end); err = EBADMSG; goto out; } err = sdp_decode(sess, desc, false); if (err) goto out; rc = sdp_media_rformat(audio, NULL); if (!rc) { err = ENOENT; goto out; } err = sa_set_str(&ref, ref_host, ref_port); if (err) goto out; err = EINVAL; if (!sa_cmp(sdp_media_raddr(audio), &ref, SA_ALL)) goto out; if (!rc) goto out; if (0 != strcmp(rc->id, ref_pt)) goto out; if (0 != strcmp(ref_cname, rc->name)) goto out; if (rc->srate != ref_srate) goto out; err = 0; out: mem_deref(audio); mem_deref(sess); mem_deref(desc); return err; }
static int alloc_handler(struct ausrc_st **stp, const struct ausrc *as, struct media_ctx **ctx, struct ausrc_prm *prm, const char *dev, ausrc_read_h *rh, ausrc_error_h *errh, void *arg) { struct ausrc_st *st; int err; if (!stp || !as || !prm || !rh) return EINVAL; st = mem_zalloc(sizeof(*st), destructor); if (!st) return ENOMEM; st->as = as; st->rh = rh; st->errh = errh; st->arg = arg; st->mp3 = mpg123_new(NULL, &err); if (!st->mp3) { err = ENODEV; goto out; } err = mpg123_open_feed(st->mp3); if (err != MPG123_OK) { warning("rst: mpg123_open_feed: %s\n", mpg123_strerror(st->mp3)); err = ENODEV; goto out; } /* Set wanted output format */ mpg123_format_none(st->mp3); mpg123_format(st->mp3, prm->srate, prm->ch, aufmt_to_encoding(prm->fmt)); mpg123_volume(st->mp3, 0.3); st->sampc = prm->srate * prm->ch * prm->ptime / 1000; st->sampsz = aufmt_sample_size(prm->fmt); st->ptime = prm->ptime; info("rst: audio ptime=%u sampc=%zu aubuf=[%u:%u]\n", st->ptime, st->sampc, prm->srate * prm->ch * 2, prm->srate * prm->ch * 40); /* 1 - 20 seconds of audio */ err = aubuf_alloc(&st->aubuf, prm->srate * prm->ch * st->sampsz, prm->srate * prm->ch * st->sampsz * 20); if (err) goto out; if (ctx && *ctx && (*ctx)->id && !strcmp((*ctx)->id, "rst")) { st->rst = mem_ref(*ctx); } else { err = rst_alloc(&st->rst, dev); if (err) goto out; if (ctx) *ctx = (struct media_ctx *)st->rst; } rst_set_audio(st->rst, st); st->run = true; err = pthread_create(&st->thread, NULL, play_thread, st); if (err) { st->run = false; goto out; } out: if (err) mem_deref(st); else *stp = st; return err; }
/** * Do a DNS Discovery of a STUN Server * * @param dnsp Pointer to allocated DNS Discovery object * @param dnsc DNS Client * @param service Name of service to discover (e.g. "stun") * @param proto Transport protocol (e.g. "udp") * @param af Preferred Address Family * @param domain Domain name or IP address of STUN server * @param port Port number (if 0 do SRV lookup) * @param dnsh DNS Response handler * @param arg Handler argument * * @return 0 if success, otherwise errorcode */ int stun_server_discover(struct stun_dns **dnsp, struct dnsc *dnsc, const char *service, const char *proto, int af, const char *domain, uint16_t port, stun_dns_h *dnsh, void *arg) { struct stun_dns *dns; int err; if (!dnsp || !service || !proto || !domain || !domain[0] || !dnsh) return EINVAL; dns = mem_zalloc(sizeof(*dns), dnsdisc_destructor); if (!dns) return ENOMEM; dns->port = service[strlen(service)-1] == 's' ? STUNS_PORT : STUN_PORT; dns->dnsh = dnsh; dns->arg = arg; dns->dnsc = dnsc; dns->af = af; /* Numeric IP address - no lookup */ if (0 == sa_set_str(&dns->srv, domain, port ? port : dns->port)) { DEBUG_INFO("IP (%s)\n", domain); resolved(dns, 0); err = 0; goto out; /* free now */ } /* Port specified - use AAAA or A lookup */ else if (port) { sa_set_in(&dns->srv, 0, port); DEBUG_INFO("resolving A query: (%s)\n", domain); err = a_or_aaaa_query(dns, domain); if (err) { DEBUG_WARNING("%s: A/AAAA lookup failed (%m)\n", domain, err); goto out; } } /* SRV lookup */ else { char q[256]; str_ncpy(dns->domain, domain, sizeof(dns->domain)); (void)re_snprintf(q, sizeof(q), "_%s._%s.%s", service, proto, domain); DEBUG_INFO("resolving SRV query: (%s)\n", q); err = dnsc_query(&dns->dq, dnsc, q, DNS_TYPE_SRV, DNS_CLASS_IN, true, srv_handler, dns); if (err) { DEBUG_WARNING("%s: SRV lookup failed (%m)\n", q, err); goto out; } } *dnsp = dns; return 0; out: mem_deref(dns); return err; }