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; }
static int print_handler(const char *p, size_t size, void *arg) { struct pl *pl = arg; if (size > pl->l) return ENOMEM; memcpy((void *)pl->p, p, size); pl_advance(pl, size); return 0; }
/** Compare two SDP messages line-by-line (exclude owner) */ static bool sdp_cmp(struct mbuf *mb, const char *msg) { struct pl pl; if (!mb || !msg) return false; pl.p = (char *)mb->buf; pl.l = mb->end; while (pl.l && strlen(msg)) { struct pl n1, v1, n2, v2; if (re_regex(pl.p, pl.l, "[^=]1=[^\r\n]+", &n1, &v1)) return false; if (re_regex(msg, strlen(msg), "[^=]1=[^\r\n]+", &n2, &v2)) return false; pl_advance(&pl, 2 + v1.l + 2); msg += (2 + v2.l + 2); if (0 != pl_cmp(&n1, &n2)) { DEBUG_WARNING("name mismatch: %r=%r\n", &n1, &v1); return false; } /* ignore owner */ if (n1.p[0] == 'o') continue; if (0 != pl_cmp(&v1, &v2)) { DEBUG_WARNING("value mismatch: %r=%r\n", &n1, &v1); return false; } } if (pl.l) { DEBUG_WARNING("%u bytes junk at end: %r\n", pl.l, &pl); } if (strlen(msg)) { DEBUG_WARNING("%u bytes junk at end: %s\n", strlen(msg), msg); } return !pl.l && !strlen(msg); }
/** * Parse a config file, calling handler for each line * * @param filename Config file * @param ch Line handler * @param arg Handler argument * * @return 0 if success, otherwise errorcode */ int conf_parse(const char *filename, confline_h *ch, void *arg) { struct pl pl, val; struct mbuf *mb; int err = 0, fd = open(filename, O_RDONLY); if (fd < 0) return errno; mb = mbuf_alloc(1024); if (!mb) { err = ENOMEM; goto out; } for (;;) { uint8_t buf[1024]; const ssize_t n = read(fd, (void *)buf, sizeof(buf)); if (n < 0) { err = errno; break; } else if (n == 0) break; err |= mbuf_write_mem(mb, buf, n); } pl.p = (const char *)mb->buf; pl.l = mb->end; while (pl.p < ((const char *)mb->buf + mb->end) && !err) { const char *lb = pl_strchr(&pl, '\n'); val.p = pl.p; val.l = lb ? (uint32_t)(lb - pl.p) : pl.l; pl_advance(&pl, val.l + 1); if (!val.l || val.p[0] == '#') continue; err = ch(&val, arg); } out: mem_deref(mb); (void)close(fd); return err; }
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); } }
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); }