static bool cryptosuite_issupported(const struct pl *suite) { if (0 == pl_strcasecmp(suite, aes_cm_128_hmac_sha1_32)) return true; if (0 == pl_strcasecmp(suite, aes_cm_128_hmac_sha1_80)) return true; return false; }
int decode_sdpparam_h264(struct videnc_state *st, const struct pl *name, const struct pl *val) { if (0 == pl_strcasecmp(name, "packetization-mode")) { st->u.h264.packetization_mode = pl_u32(val); if (st->u.h264.packetization_mode != 0) { warning("avcodec: illegal packetization-mode %u\n", st->u.h264.packetization_mode); return EPROTO; } } else if (0 == pl_strcasecmp(name, "profile-level-id")) { struct pl prof = *val; if (prof.l != 6) { warning("avcodec: invalid profile-level-id (%r)\n", val); return EPROTO; } prof.l = 2; st->u.h264.profile_idc = pl_x32(&prof); prof.p += 2; st->u.h264.profile_iop = pl_x32(&prof); prof.p += 2; st->u.h264.level_idc = pl_x32(&prof); } else if (0 == pl_strcasecmp(name, "max-fs")) { st->u.h264.max_fs = pl_u32(val); } else if (0 == pl_strcasecmp(name, "max-smbps")) { st->u.h264.max_smbps = pl_u32(val); } return 0; }
static enum ice_tcptype ice_tcptype_resolve(const struct pl *pl) { if (0 == pl_strcasecmp(pl, "active")) return ICE_TCP_ACTIVE; if (0 == pl_strcasecmp(pl, "passive")) return ICE_TCP_PASSIVE; if (0 == pl_strcasecmp(pl, "so")) return ICE_TCP_SO; return (enum ice_tcptype)-1; }
static enum h263_fmt h263_fmt(const struct pl *name) { if (0 == pl_strcasecmp(name, "sqcif")) return H263_FMT_SQCIF; if (0 == pl_strcasecmp(name, "qcif")) return H263_FMT_QCIF; if (0 == pl_strcasecmp(name, "cif")) return H263_FMT_CIF; if (0 == pl_strcasecmp(name, "cif4")) return H263_FMT_4CIF; if (0 == pl_strcasecmp(name, "cif16")) return H263_FMT_16CIF; return H263_FMT_OTHER; }
/** * Add a contact * * @param contacts Contacts container * @param contactp Pointer to allocated contact (optional) * @param addr Contact in SIP address format * * @return 0 if success, otherwise errorcode */ int contact_add(struct contacts *contacts, struct contact **contactp, const struct pl *addr) { struct contact *c; struct pl pl; int err; if (!contacts) return EINVAL; c = mem_zalloc(sizeof(*c), destructor); if (!c) return ENOMEM; err = pl_strdup(&c->buf, addr); if (err) goto out; pl_set_str(&pl, c->buf); err = sip_addr_decode(&c->addr, &pl); if (err) { warning("contact: decode error '%r'\n", addr); goto out; } if (0 == msg_param_decode(&c->addr.params, "access", &pl)) { if (0 == pl_strcasecmp(&pl, "block")) { c->access = ACCESS_BLOCK; } else if (0 == pl_strcasecmp(&pl, "allow")) { c->access = ACCESS_ALLOW; } else { warning("contact: unknown 'access=%r' for '%r'\n", &pl, addr); err = EINVAL; goto out; } } else c->access = ACCESS_UNKNOWN; c->status = PRESENCE_UNKNOWN; list_append(&contacts->cl, &c->le, c); hash_append(contacts->cht, hash_joaat_pl(&c->addr.auri), &c->he, c); out: if (err) mem_deref(c); else if (contactp) *contactp = c; return err; }
enum cand_type ice_cand_name2type(const struct pl *name) { if (0 == pl_strcasecmp(name, "host")) return CAND_TYPE_HOST; if (0 == pl_strcasecmp(name, "srflx")) return CAND_TYPE_SRFLX; if (0 == pl_strcasecmp(name, "prflx")) return CAND_TYPE_PRFLX; if (0 == pl_strcasecmp(name, "relay")) return CAND_TYPE_RELAY; return (enum cand_type)-1; }
static enum aufmt resolve_aufmt(const struct pl *fmt) { if (0 == pl_strcasecmp(fmt, "s16")) return AUFMT_S16LE; if (0 == pl_strcasecmp(fmt, "s16le")) return AUFMT_S16LE; if (0 == pl_strcasecmp(fmt, "float")) return AUFMT_FLOAT; if (0 == pl_strcasecmp(fmt, "s24_3le")) return AUFMT_S24_3LE; return (enum aufmt)-1; }
static void notify_handler(struct sip *sip, const struct sip_msg *msg, void *arg) { enum presence_status status = PRESENCE_CLOSED; struct presence *pres = arg; const struct sip_hdr *hdr; struct pl pl; pres->failc = 0; hdr = sip_msg_hdr(msg, SIP_HDR_CONTENT_TYPE); if (!hdr || 0 != pl_strcasecmp(&hdr->val, "application/pidf+xml")) { if (hdr) (void)re_printf("presence: unsupported" " content-type: '%r'\n", &hdr->val); sip_treplyf(NULL, NULL, sip, msg, false, 415, "Unsupported Media Type", "Accept: application/pidf+xml\r\n" "Content-Length: 0\r\n" "\r\n"); return; } if (!re_regex((const char *)mbuf_buf(msg->mb), mbuf_get_left(msg->mb), "<status>[^<]*<basic>[^<]*</basic>[^<]*</status>", NULL, &pl, NULL)) { if (!pl_strcasecmp(&pl, "open")) status = PRESENCE_OPEN; } if (!re_regex((const char *)mbuf_buf(msg->mb), mbuf_get_left(msg->mb), "<rpid:away/>")) { status = PRESENCE_CLOSED; } else if (!re_regex((const char *)mbuf_buf(msg->mb), mbuf_get_left(msg->mb), "<rpid:busy/>")) { status = PRESENCE_BUSY; } else if (!re_regex((const char *)mbuf_buf(msg->mb), mbuf_get_left(msg->mb), "<rpid:on-the-phone/>")) { status = PRESENCE_BUSY; } (void)sip_treply(NULL, sip, msg, 200, "OK"); contact_set_presence(pres->contact, status); }
static int module_init(void) { struct pl pl; if (conf_get(conf_cur(), "video_selfview", &pl)) return 0; if (0 == pl_strcasecmp(&pl, "window")) vidfilt_register(&selfview_win); else if (0 == pl_strcasecmp(&pl, "pip")) vidfilt_register(&selfview_pip); return 0; }
int sipevent_substate_decode(struct sipevent_substate *ss, const struct pl *pl) { struct pl state, param; int err; if (!ss || !pl) return EINVAL; err = re_regex(pl->p, pl->l, "[a-z]+[ \t\r\n]*[^]*", &state, NULL, &ss->params); if (err) return EBADMSG; if (!pl_strcasecmp(&state, "active")) ss->state = SIPEVENT_ACTIVE; else if (!pl_strcasecmp(&state, "pending")) ss->state = SIPEVENT_PENDING; else if (!pl_strcasecmp(&state, "terminated")) ss->state = SIPEVENT_TERMINATED; else ss->state = -1; if (!msg_param_decode(&ss->params, "reason", ¶m)) { if (!pl_strcasecmp(¶m, "deactivated")) ss->reason = SIPEVENT_DEACTIVATED; else if (!pl_strcasecmp(¶m, "probation")) ss->reason = SIPEVENT_PROBATION; else if (!pl_strcasecmp(¶m, "rejected")) ss->reason = SIPEVENT_REJECTED; else if (!pl_strcasecmp(¶m, "timeout")) ss->reason = SIPEVENT_TIMEOUT; else if (!pl_strcasecmp(¶m, "giveup")) ss->reason = SIPEVENT_GIVEUP; else if (!pl_strcasecmp(¶m, "noresource")) ss->reason = SIPEVENT_NORESOURCE; else ss->reason = -1; } else { ss->reason = -1; } if (!msg_param_decode(&ss->params, "expires", ¶m)) ss->expires = param; else ss->expires = pl_null; if (!msg_param_decode(&ss->params, "retry-after", ¶m)) ss->retry_after = param; else ss->retry_after = pl_null; return 0; }
static int module_init(void) { struct pl pl = PL("pip"); (void)conf_get(conf_cur(), "video_selfview", &pl); if (0 == pl_strcasecmp(&pl, "window")) vidfilt_register(&selfview_win); else if (0 == pl_strcasecmp(&pl, "pip")) vidfilt_register(&selfview_pip); (void)conf_get_vidsz(conf_cur(), "selfview_size", &selfview_size); return 0; }
static bool value_handler(const struct sip_hdr *hdr, const struct sip_msg *msg, void *arg) { (void)msg; return 0 == pl_strcasecmp(&hdr->val, (const char *)arg); }
static enum ice_transp transp_resolve(const struct pl *transp) { if (!pl_strcasecmp(transp, "UDP")) return ICE_TRANSP_UDP; return ICE_TRANSP_NONE; }
static void reload_handler(struct mbuf *mb) { bool dbg = force_debug; struct conf *lconf; struct pl opt; int err; (void)mb; err = conf_alloc(&lconf, configfile); if (err) { restund_error("error loading configuration: %s: %m\n", configfile, err); return; } conf = mem_deref(conf); conf = lconf; if (!conf_get(conf, "debug", &opt) && !pl_strcasecmp(&opt, "yes")) dbg = true; restund_log_enable_debug(dbg); restund_info("configuration reloaded from %s (debug%s)\n", configfile, dbg ? " enabled" : " disabled"); }
static int conf_get_vidfmt(const struct conf *conf, const char *name, int *fmtp) { struct pl pl; int fmt; int err; err = conf_get(conf, name, &pl); if (err) return err; for (fmt=0; fmt<VID_FMT_N; fmt++) { const char *str = vidfmt_name(fmt); if (0 == pl_strcasecmp(&pl, str)) { *fmtp = fmt; return 0; } } warning("config: %s: pixel format not supported (%r)\n", name, &pl); return ENOENT; }
/** * Find a User-Agent (UA) which has certain address parameter and/or value * * @param name SIP Address parameter name * @param value SIP Address parameter value (optional) * * @return User-Agent (UA) if found, otherwise NULL */ struct ua *uag_find_param(const char *name, const char *value) { struct le *le; for (le = uag.ual.head; le; le = le->next) { struct ua *ua = le->data; struct sip_addr *laddr = account_laddr(ua->acc); struct pl val; if (value) { if (0 == msg_param_decode(&laddr->params, name, &val) && 0 == pl_strcasecmp(&val, value)) { return ua; } } else { if (0 == msg_param_exists(&laddr->params, name, &val)) return ua; } } return NULL; }
static int notifier_add(struct sipevent_sock *sock, const struct sip_msg *msg, struct ua *ua) { const struct sip_hdr *hdr; struct sipevent_event se; struct notifier *not; int err; hdr = sip_msg_hdr(msg, SIP_HDR_EVENT); if (!hdr) return EPROTO; err = sipevent_event_decode(&se, &hdr->val); if (err) return err; if (pl_strcasecmp(&se.event, "presence")) { info("presence: unexpected event '%r'\n", &se.event); return EPROTO; } err = notifier_alloc(¬, sock, msg, &se, ua); if (err) return err; (void)notify(not, my_status); return 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); } }
static bool cmp_handler(struct le *le, void *arg) { struct realm *realm = le->data; struct pl *chrealm = arg; /* handle multiple authenticate headers with equal realm value */ if (realm->nc == 1) return false; return 0 == pl_strcasecmp(chrealm, realm->realm); }
bool hdr_fetch(struct le *le, void *arg) { int err = 0; struct http_hdr *hdr = le->data; struct hdr_fetch *op = arg; if(pl_strcasecmp(&hdr->name, op->name) == 0) { err = pl_strdup(op->val, &hdr->val); return true; } return false; }
/** * Get the boolean value of a configuration item * * @param conf Configuration object * @param name Name of config item key * @param val Returned boolean value of config item, if present * * @return 0 if success, otherwise errorcode */ int conf_get_bool(const struct conf *conf, const char *name, bool *val) { struct pl pl; int err; if (!conf || !name || !val) return EINVAL; err = conf_get(conf, name, &pl); if (err) return err; if (!pl_strcasecmp(&pl, "true")) *val = true; else if (!pl_strcasecmp(&pl, "yes")) *val = true; else if (!pl_strcasecmp(&pl, "1")) *val = true; else *val = false; return 0; }
static int module_init(void) { int err = 0; #ifdef MODULE_CONF struct pl pl; if (!conf_get(conf_cur(), "opus_application", &pl)) { if (!pl_strcasecmp(&pl, "voip")) opus.app = OPUS_APPLICATION_VOIP; else if (!pl_strcasecmp(&pl, "audio")) opus.app = OPUS_APPLICATION_AUDIO; else { DEBUG_WARNING("unknown application: %r\n", &pl); } } if (!conf_get(conf_cur(), "opus_bandwidth", &pl)) { if (!pl_strcasecmp(&pl, "narrowband")) opus.bandwidth = OPUS_BANDWIDTH_NARROWBAND; else if (!pl_strcasecmp(&pl, "mediumband")) opus.bandwidth = OPUS_BANDWIDTH_MEDIUMBAND; else if (!pl_strcasecmp(&pl, "wideband")) opus.bandwidth = OPUS_BANDWIDTH_WIDEBAND; else if (!pl_strcasecmp(&pl, "superwideband")) opus.bandwidth = OPUS_BANDWIDTH_SUPERWIDEBAND; else if (!pl_strcasecmp(&pl, "fullband")) opus.bandwidth = OPUS_BANDWIDTH_FULLBAND; else { DEBUG_WARNING("unknown bandwidth: %r\n", &pl); } } conf_get_u32(conf_cur(), "opus_complexity", &opus.complex); conf_get_u32(conf_cur(), "opus_bitrate", &opus.bitrate); conf_get_bool(conf_cur(), "opus_vbr", &opus.vbr); #endif err |= aucodec_register(&codecv[0], NULL, "opus", 48000, 2, NULL, alloc, encode, decode, NULL); err |= aucodec_register(&codecv[1], NULL, "opus", 48000, 1, NULL, alloc, encode, decode, NULL); #if 0 err |= aucodec_register(&codecv[2], NULL, "opus", 32000, 1, NULL, alloc, encode, decode, NULL); #endif return err; }
/* 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; }
static void http_req_handler(struct http_conn *conn, const struct http_msg *msg, void *arg) { (void)arg; if (0 == pl_strcasecmp(&msg->path, "/")) { http_creply(conn, 200, "OK", "text/html;charset=UTF-8", "%H", html_print_cmd, msg); } else { http_ereply(conn, 404, "Not Found"); } }
static const struct mod_export *lookup_static_module(const struct pl *pl) { struct pl name; uint32_t i; if (re_regex(pl->p, pl->l, "[^.]+.[^]*", &name, NULL)) name = *pl; for (i=0; ; i++) { const struct mod_export *me = mod_table[i]; if (!me) return NULL; if (0 == pl_strcasecmp(&name, me->name)) return me; } return NULL; }
/** * Find a module by name in the list of loaded modules * * @param name Name of module to find * * @return Module if found, NULL if not found */ struct mod *mod_find(const char *name) { struct le *le; struct pl x; if (!name) return NULL; if (re_regex(name, strlen(name), "[/]*[^./]+" MOD_EXT, NULL, &x)) return NULL; for (le = modl.head; le; le = le->next) { struct mod *m = le->data; if (0 == pl_strcasecmp(&x, m->me->name)) return m; } return NULL; }
/** * Find the correct UA from the contact user * * @param cuser Contact username * * @return Matching UA if found, NULL if not found */ struct ua *uag_find(const struct pl *cuser) { struct le *le; for (le = uag.ual.head; le; le = le->next) { struct ua *ua = le->data; if (0 == pl_strcasecmp(cuser, ua->cuser)) return ua; } /* Try also matching by AOR, for better interop */ for (le = uag.ual.head; le; le = le->next) { struct ua *ua = le->data; if (0 == pl_casecmp(cuser, &ua->acc->luri.user)) return ua; } return NULL; }
int subscriber_init(void) { struct le *le; int err = 0; for (le = list_head(contact_list()); le; le = le->next) { struct contact *c = le->data; struct sip_addr *addr = contact_addr(c); struct pl val; if (0 == msg_param_decode(&addr->params, "presence", &val) && 0 == pl_strcasecmp(&val, "p2p")) { err |= presence_alloc(le->data); } } info("Subscribing to %u contacts\n", list_count(&presencel)); return err; }
int stun_uri_decode(struct stun_uri *stun_uri, const char *str) { struct uri uri; struct pl pl_uri; uint16_t port; struct pl transp; int err; if (!stun_uri || !str) return EINVAL; pl_set_str(&pl_uri, str); err = uri_decode(&uri, &pl_uri); if (err) { warning("cannot decode URI (%r)\n", &pl_uri); return err; } if (0 == pl_strcasecmp(&uri.scheme, "stun") || 0 == pl_strcasecmp(&uri.scheme, "stuns")) { stun_uri->scheme = STUN_SCHEME_STUN; } else if (0 == pl_strcasecmp(&uri.scheme, "turn") || 0 == pl_strcasecmp(&uri.scheme, "turns")) { stun_uri->scheme = STUN_SCHEME_TURN; } else { warning("unsupported stun scheme (%r)\n", &uri.scheme); return ENOTSUP; } stun_uri->secure = 's' == tolower(uri.scheme.p[uri.scheme.l-1]); if (uri.port) port = uri.port; else if (stun_uri->secure) port = 5349; else port = 3478; err = sa_set(&stun_uri->addr, &uri.host, port); if (err) { warning("invalid stun address (%r)\n", &uri.host); return err; } if (0 == re_regex(str, strlen(str), "?transport=[a-z]+", &transp)) { if (0 == pl_strcasecmp(&transp, "udp")) stun_uri->proto = IPPROTO_UDP; else if (0 == pl_strcasecmp(&transp, "tcp")) stun_uri->proto = IPPROTO_TCP; else { warning("unsupported stun transport (%r)\n", &transp); return ENOTSUP; } } else { stun_uri->proto = IPPROTO_UDP; } return 0; }
/** * Send a SIP request * * @param reqp Pointer to allocated SIP request object * @param sip SIP Stack * @param stateful Stateful client transaction * @param met SIP Method string * @param metl Length of SIP Method string * @param uri Request URI * @param uril Length of Request URI string * @param route Next hop route URI * @param mb Buffer containing SIP request * @param sendh Send handler * @param resph Response handler * @param arg Handler argument * * @return 0 if success, otherwise errorcode */ int sip_request(struct sip_request **reqp, struct sip *sip, bool stateful, const char *met, int metl, const char *uri, int uril, const struct uri *route, struct mbuf *mb, sip_send_h *sendh, sip_resp_h *resph, void *arg) { struct sip_request *req; struct sa dst; struct pl pl; int err; if (!sip || !met || !uri || !route || !mb) return EINVAL; if (pl_strcasecmp(&route->scheme, "sip")) return ENOSYS; req = mem_zalloc(sizeof(*req), destructor); if (!req) return ENOMEM; list_append(&sip->reql, &req->le, req); err = str_ldup(&req->met, met, metl); if (err) goto out; err = str_ldup(&req->uri, uri, uril); if (err) goto out; if (sip_param_decode(&route->params, "maddr", &pl)) pl = route->host; err = pl_strdup(&req->host, &pl); if (err) goto out; req->stateful = stateful; req->mb = mem_ref(mb); req->sip = sip; req->sendh = sendh; req->resph = resph; req->arg = arg; if (!sip_param_decode(&route->params, "transport", &pl)) { if (!pl_strcasecmp(&pl, "udp")) req->tp = SIP_TRANSP_UDP; else if (!pl_strcasecmp(&pl, "tcp")) req->tp = SIP_TRANSP_TCP; else if (!pl_strcasecmp(&pl, "tls")) req->tp = SIP_TRANSP_TLS; else { err = EPROTONOSUPPORT; goto out; } if (!sip_transp_supported(sip, req->tp, AF_UNSPEC)) { err = EPROTONOSUPPORT; goto out; } req->tp_selected = true; } else { req->tp = SIP_TRANSP_NONE; if (!transp_next(sip, &req->tp)) { err = EPROTONOSUPPORT; goto out; } req->tp_selected = false; } if (!sa_set_str(&dst, req->host, sip_transp_port(req->tp, route->port))) { err = request(req, req->tp, &dst); if (!req->stateful) { mem_deref(req); return err; } } else if (route->port) { req->port = sip_transp_port(req->tp, route->port); err = addr_lookup(req, req->host); } else if (req->tp_selected) { err = srv_lookup(req, req->host); } else { err = dnsc_query(&req->dnsq, sip->dnsc, req->host, DNS_TYPE_NAPTR, DNS_CLASS_IN, true, naptr_handler, req); } out: if (err) mem_deref(req); else if (reqp) { req->reqp = reqp; *reqp = req; } return err; }