// call->master_lock held in W struct media_player *media_player_new(struct call_monologue *ml) { #ifdef WITH_TRANSCODING ilog(LOG_DEBUG, "creating media_player"); uint32_t ssrc = 0; while (ssrc == 0) ssrc = random(); struct ssrc_ctx *ssrc_ctx = get_ssrc_ctx(ssrc, ml->call->ssrc_hash, SSRC_DIR_OUTPUT); struct media_player *mp = obj_alloc0("media_player", sizeof(*mp), __media_player_free); mp->tt_obj.tt = &media_player_thread; mutex_init(&mp->lock); mp->call = obj_get(ml->call); mp->ml = ml; mp->seq = random(); mp->ssrc_out = ssrc_ctx; av_init_packet(&mp->pkt); mp->pkt.data = NULL; mp->pkt.size = 0; return mp; #else return NULL; #endif }
/* unlocks on return */ static int __poller_add_item(struct poller *p, struct poller_item *i, int has_lock) { struct poller_item_int *ip; unsigned int u; struct epoll_event e; if (!p || !i) goto fail_lock; if (i->fd < 0) goto fail_lock; if (!i->readable && !i->writeable) goto fail_lock; if (!i->closed) goto fail_lock; if (!has_lock) mutex_lock(&p->lock); if (i->fd < p->items_size && p->items[i->fd]) goto fail; ZERO(e); e.events = epoll_events(i, NULL); e.data.fd = i->fd; if (epoll_ctl(p->fd, EPOLL_CTL_ADD, i->fd, &e)) abort(); if (i->fd >= p->items_size) { u = p->items_size; p->items_size = i->fd + 1; p->items = realloc(p->items, sizeof(*p->items) * p->items_size); memset(p->items + u, 0, sizeof(*p->items) * (p->items_size - u - 1)); } ip = obj_alloc0("poller_item_int", sizeof(*ip), poller_item_free); memcpy(&ip->item, i, sizeof(*i)); obj_hold_o(ip->item.obj); /* new ref in *ip */ p->items[i->fd] = obj_get(ip); mutex_unlock(&p->lock); if (i->timer) poller_add_timer(p, poller_fd_timer, &ip->obj); obj_put(ip); return 0; fail: mutex_unlock(&p->lock); return -1; fail_lock: if (has_lock) mutex_unlock(&p->lock); return -1; }
// call->master_lock held in W struct send_timer *send_timer_new(struct packet_stream *ps) { ilog(LOG_DEBUG, "creating send_timer"); struct send_timer *st = obj_alloc0("send_timer", sizeof(*st), __send_timer_free); st->tt_obj.tt = &send_timer_thread; mutex_init(&st->lock); st->call = obj_get(ps->call); st->sink = ps; g_queue_init(&st->packets); return st; }
static void control_incoming(int fd, void *p, uintptr_t u) { int nfd; struct control_tcp *c = p; struct control_stream *s; struct poller_item i; struct sockaddr_in sin; socklen_t sinl; next: sinl = sizeof(sin); nfd = accept(fd, (struct sockaddr *) &sin, &sinl); if (nfd == -1) { if (errno == EAGAIN || errno == EWOULDBLOCK) return; goto next; } nonblock(nfd); ilog(LOG_INFO, "New control connection from " DF, DP(sin)); s = obj_alloc0("control_stream", sizeof(*s), control_stream_free); s->fd = nfd; s->control = c; s->poller = c->poller; s->inbuf = streambuf_new(c->poller, nfd); s->outbuf = streambuf_new(c->poller, nfd); memcpy(&s->inaddr, &sin, sizeof(s->inaddr)); mutex_init(&s->lock); s->linked = 1; ZERO(i); i.fd = nfd; i.closed = control_stream_closed; i.readable = control_stream_readable; i.writeable = control_stream_writeable; i.timer = control_stream_timer; i.obj = &s->obj; if (poller_add_item(c->poller, &i)) goto fail; mutex_lock(&c->lock); /* let the list steal our own ref */ c->streams = g_list_prepend(c->streams, s); mutex_unlock(&c->lock); goto next; fail: obj_put(s); goto next; }
static struct ice_agent *__ice_agent_new(struct call_media *media) { struct ice_agent *ag; struct call *call = media->call; ag = obj_alloc0("ice_agent", sizeof(*ag), __ice_agent_free); ag->call = obj_get(call); ag->media = media; mutex_init(&ag->lock); __ice_agent_initialize(ag); return ag; }
struct control_udp *control_udp_new(struct poller *p, endpoint_t *ep, struct callmaster *m) { struct control_udp *c; const char *errptr; int erroff; if (!p || !m) return NULL; c = obj_alloc0("control_udp", sizeof(*c), NULL); c->callmaster = m; c->parse_re = pcre_compile( /* cookie cmd flags callid viabranch:5 */ "^(\\S+)\\s+(?:([ul])(\\S*)\\s+([^;]+)(?:;(\\S+))?\\s+" \ /* addr4 addr6:7 */ "(?:([\\d.]+)|([\\da-f:]+(?::ffff:[\\d.]+)?))" \ /* port fromtag num totag:11 */ "\\s+(\\d+)\\s+(\\S+?);(\\d+)(?:\\s+(\\S+?);\\d+(?:\\s+.*)?)?\r?\n?$" \ /* "d/q" flags callid viabranch fromtag totag:17 */ "|([dq])(\\S*)\\s+([^;\\s]+)(?:;(\\S+))?\\s+(\\S+?)(?:;\\d+)?(?:\\s+(\\S+?)(?:;\\d+)?)?\r?\n?$" \ /* v flags params:20 */ "|(v)(\\S*)(?:\\s+(\\S+))?)", PCRE_DOLLAR_ENDONLY | PCRE_DOTALL | PCRE_CASELESS, &errptr, &erroff, NULL); c->parse_ree = pcre_study(c->parse_re, 0, &errptr); /* cookie cmd flags callid addr port */ c->fallback_re = pcre_compile("^(\\S+)(?:\\s+(\\S)\\S*\\s+\\S+(\\s+\\S+)(\\s+\\S+))?", PCRE_DOLLAR_ENDONLY | PCRE_DOTALL | PCRE_CASELESS, &errptr, &erroff, NULL); if (!c->parse_re || !c->fallback_re) goto fail2; cookie_cache_init(&c->cookie_cache); if (udp_listener_init(&c->udp_listeners[0], p, ep, control_udp_incoming, &c->obj)) goto fail2; if (ipv46_any_convert(ep) && udp_listener_init(&c->udp_listeners[1], p, ep, control_udp_incoming, &c->obj)) goto fail2; return c; fail2: obj_put(c); return NULL; }
static int poller_timer_link(struct poller *p, GSList **lp, void (*f)(void *), struct obj *o) { struct timer_item *i; if (!f) return -1; i = obj_alloc0("timer_item", sizeof(*i), timer_item_free); i->func = f; i->obj_ptr = o ? obj_hold_o(o) : NULL; mutex_lock(&p->timers_add_del_lock); *lp = g_slist_prepend(*lp, i); if (!mutex_trylock(&p->timers_lock)) { poller_timers_mod(p); mutex_unlock(&p->timers_lock); } mutex_unlock(&p->timers_add_del_lock); return 0; }
static int cert_init() { X509 *x509 = NULL; EVP_PKEY *pkey = NULL; BIGNUM *exponent = NULL, *serial_number = NULL; RSA *rsa = NULL; ASN1_INTEGER *asn1_serial_number; X509_NAME *name; struct dtls_cert *new_cert; ilog(LOG_INFO, "Generating new DTLS certificate"); /* objects */ pkey = EVP_PKEY_new(); exponent = BN_new(); rsa = RSA_new(); serial_number = BN_new(); name = X509_NAME_new(); x509 = X509_new(); if (!exponent || !pkey || !rsa || !serial_number || !name || !x509) goto err; /* key */ if (!BN_set_word(exponent, 0x10001)) goto err; if (!RSA_generate_key_ex(rsa, 1024, exponent, NULL)) goto err; if (!EVP_PKEY_assign_RSA(pkey, rsa)) goto err; /* x509 cert */ if (!X509_set_pubkey(x509, pkey)) goto err; /* serial */ if (!BN_pseudo_rand(serial_number, 64, 0, 0)) goto err; asn1_serial_number = X509_get_serialNumber(x509); if (!asn1_serial_number) goto err; if (!BN_to_ASN1_INTEGER(serial_number, asn1_serial_number)) goto err; /* version 1 */ if (!X509_set_version(x509, 0L)) goto err; /* common name */ if (!X509_NAME_add_entry_by_NID(name, NID_commonName, MBSTRING_UTF8, (unsigned char *) "rtpengine", -1, -1, 0)) goto err; if (!X509_set_subject_name(x509, name)) goto err; if (!X509_set_issuer_name(x509, name)) goto err; /* cert lifetime */ if (!X509_gmtime_adj(X509_get_notBefore(x509), -60*60*24)) goto err; if (!X509_gmtime_adj(X509_get_notAfter(x509), CERT_EXPIRY_TIME)) goto err; /* sign it */ if (!X509_sign(x509, pkey, EVP_sha1())) goto err; /* digest */ new_cert = obj_alloc0("dtls_cert", sizeof(*new_cert), cert_free); new_cert->fingerprint.hash_func = &hash_funcs[0]; dtls_fingerprint_hash(&new_cert->fingerprint, x509); new_cert->x509 = x509; new_cert->pkey = pkey; new_cert->expires = time(NULL) + CERT_EXPIRY_TIME; dump_cert(new_cert); /* swap out certs */ rwlock_lock_w(&__dtls_cert_lock); if (__dtls_cert) obj_put(__dtls_cert); __dtls_cert = new_cert; rwlock_unlock_w(&__dtls_cert_lock); /* cleanup */ BN_free(exponent); BN_free(serial_number); X509_NAME_free(name); return 0; err: ilog(LOG_ERROR, "Failed to generate DTLS certificate"); if (pkey) EVP_PKEY_free(pkey); if (exponent) BN_free(exponent); if (rsa) RSA_free(rsa); if (x509) X509_free(x509); if (serial_number) BN_free(serial_number); return -1; }
struct control_tcp *control_tcp_new(struct poller *p, u_int32_t ip, u_int16_t port, struct callmaster *m) { int fd; struct control_tcp *c; struct poller_item i; struct sockaddr_in sin; const char *errptr; int erroff; if (!p) return NULL; if (!m) return NULL; fd = socket(AF_INET, SOCK_STREAM, 0); if (fd == -1) return NULL; nonblock(fd); reuseaddr(fd); ZERO(sin); sin.sin_family = AF_INET; sin.sin_addr.s_addr = ip; sin.sin_port = htons(port); if (bind(fd, (struct sockaddr *) &sin, sizeof(sin))) goto fail; if (listen(fd, 5)) goto fail; c = obj_alloc0("control", sizeof(*c), NULL); c->parse_re = pcre_compile( /* reqtype callid streams ip fromdom fromtype todom totype agent info |reqtype callid info | reqtype */ "^(?:(request|lookup)\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)\\s+info=(\\S*)|(delete)\\s+(\\S+)\\s+info=(\\S*)|(build|version|controls|quit|exit|status))$", PCRE_DOLLAR_ENDONLY | PCRE_DOTALL, &errptr, &erroff, NULL); c->parse_ree = pcre_study(c->parse_re, 0, &errptr); c->fd = fd; c->poller = p; c->callmaster = m; mutex_init(&c->lock); ZERO(i); i.fd = fd; i.closed = control_closed; i.readable = control_incoming; i.obj = &c->obj; if (poller_add_item(p, &i)) goto fail2; obj_put(c); return c; fail2: obj_put(c); fail: close(fd); return NULL; }