static str *call_update_lookup_udp(char **out, struct callmaster *m, enum call_opmode opmode) { struct call *c; struct call_monologue *monologue; GQueue q = G_QUEUE_INIT; struct stream_params sp; str *ret, callid, viabranch, fromtag, totag = STR_NULL; int i; str_init(&callid, out[RE_UDP_UL_CALLID]); str_init(&viabranch, out[RE_UDP_UL_VIABRANCH]); str_init(&fromtag, out[RE_UDP_UL_FROMTAG]); if (opmode == OP_ANSWER) str_init(&totag, out[RE_UDP_UL_TOTAG]); c = call_get_opmode(&callid, m, opmode); if (!c) { ilog(LOG_WARNING, "["STR_FORMAT"] Got UDP LOOKUP for unknown call-id", STR_FMT(&callid)); return str_sprintf("%s 0 0.0.0.0\n", out[RE_UDP_COOKIE]); } monologue = call_get_mono_dialogue(c, &fromtag, &totag); if (!monologue) goto ml_fail; if (addr_parse_udp(&sp, out)) goto addr_fail; g_queue_push_tail(&q, &sp); i = monologue_offer_answer(monologue, &q, NULL); g_queue_clear(&q); if (i) goto unlock_fail; ret = streams_print(&monologue->active_dialogue->medias, sp.index, sp.index, out[RE_UDP_COOKIE], SAF_UDP); rwlock_unlock_w(&c->master_lock); redis_update(c, m->conf.redis); ilog(LOG_INFO, "Returning to SIP proxy: "STR_FORMAT"", STR_FMT(ret)); goto out; ml_fail: ilog(LOG_ERR, "Invalid dialogue association"); goto unlock_fail; addr_fail: ilog(LOG_ERR, "Failed to parse a media stream: %s/%s:%s", out[RE_UDP_UL_ADDR4], out[RE_UDP_UL_ADDR6], out[RE_UDP_UL_PORT]); goto unlock_fail; unlock_fail: rwlock_unlock_w(&c->master_lock); ret = str_sprintf("%s E8\n", out[RE_UDP_COOKIE]); out: obj_put(c); return ret; }
static str *call_request_lookup_tcp(char **out, struct callmaster *m, enum call_opmode opmode) { struct call *c; struct call_monologue *monologue; GQueue s = G_QUEUE_INIT; str *ret = NULL, callid, fromtag, totag = STR_NULL; GHashTable *infohash; str_init(&callid, out[RE_TCP_RL_CALLID]); infohash = g_hash_table_new_full(g_str_hash, g_str_equal, free, free); c = call_get_opmode(&callid, m, opmode); if (!c) { ilog(LOG_WARNING, "["STR_FORMAT"] Got LOOKUP for unknown call-id", STR_FMT(&callid)); goto out; } info_parse(out[RE_TCP_RL_INFO], infohash, m); streams_parse(out[RE_TCP_RL_STREAMS], m, &s); str_init(&fromtag, g_hash_table_lookup(infohash, "fromtag")); if (!fromtag.s) { ilog(LOG_WARNING, "No from-tag in message"); goto out2; } str_init(&totag, g_hash_table_lookup(infohash, "totag")); if (opmode == OP_ANSWER) { if (!totag.s) { ilog(LOG_WARNING, "No to-tag in message"); goto out2; } str_swap(&fromtag, &totag); } monologue = call_get_mono_dialogue(c, &fromtag, &totag, NULL); if (!monologue) { ilog(LOG_WARNING, "Invalid dialogue association"); goto out2; } if (monologue_offer_answer(monologue, &s, NULL)) goto out2; ret = streams_print(&monologue->active_dialogue->medias, 1, s.length, NULL, SAF_TCP); out2: rwlock_unlock_w(&c->master_lock); streams_free(&s); if (m->conf.redis_write) { redis_update(c, m->conf.redis_write, ANY_REDIS_ROLE); } else if (m->conf.redis) { redis_update(c, m->conf.redis, MASTER_REDIS_ROLE); } ilog(LOG_INFO, "Returning to SIP proxy: "STR_FORMAT"", STR_FMT0(ret)); obj_put(c); out: g_hash_table_destroy(infohash); return ret; }
str *call_query_udp(char **out, struct callmaster *m) { struct call *c; str *ret, callid, fromtag, totag; struct call_stats stats; __C_DBG("got query for callid '%s'", out[RE_UDP_DQ_CALLID]); str_init(&callid, out[RE_UDP_DQ_CALLID]); str_init(&fromtag, out[RE_UDP_DQ_FROMTAG]); str_init(&totag, out[RE_UDP_DQ_TOTAG]); c = call_get_opmode(&callid, m, OP_OTHER); if (!c) { ilog(LOG_INFO, "["STR_FORMAT"] Call-ID to query not found", STR_FMT(&callid)); goto err; } ng_call_stats(c, &fromtag, &totag, NULL, &stats); rwlock_unlock_w(&c->master_lock); ret = str_sprintf("%s %lld "UINT64F" "UINT64F" "UINT64F" "UINT64F"\n", out[RE_UDP_COOKIE], (long long int) m->conf.silent_timeout - (poller_now - stats.last_packet), stats.totals[0].packets, stats.totals[1].packets, stats.totals[2].packets, stats.totals[3].packets); goto out; err: if (c) rwlock_unlock_w(&c->master_lock); ret = str_sprintf("%s E8\n", out[RE_UDP_COOKIE]); goto out; out: if (c) obj_put(c); return ret; }
const char *call_query_ng(bencode_item_t *input, struct callmaster *m, bencode_item_t *output) { str callid, fromtag, totag; struct call *call; if (!bencode_dictionary_get_str(input, "call-id", &callid)) return "No call-id in message"; call = call_get_opmode(&callid, m, OP_OTHER); if (!call) return "Unknown call-id"; bencode_dictionary_get_str(input, "from-tag", &fromtag); bencode_dictionary_get_str(input, "to-tag", &totag); bencode_dictionary_add_string(output, "result", "ok"); ng_call_stats(call, &fromtag, &totag, output, NULL); rwlock_unlock_w(&call->master_lock); obj_put(call); return NULL; }
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; }
static const char *call_offer_answer_ng(bencode_item_t *input, struct callmaster *m, bencode_item_t *output, enum call_opmode opmode) { str sdp, fromtag, totag = STR_NULL, callid; char *errstr; GQueue parsed = G_QUEUE_INIT; GQueue streams = G_QUEUE_INIT; struct call *call; struct call_monologue *monologue; int ret; struct sdp_ng_flags flags; struct sdp_chopper *chopper; if (!bencode_dictionary_get_str(input, "sdp", &sdp)) return "No SDP body in message"; if (!bencode_dictionary_get_str(input, "call-id", &callid)) return "No call-id in message"; if (!bencode_dictionary_get_str(input, "from-tag", &fromtag)) return "No from-tag in message"; if (opmode == OP_ANSWER) { if (!bencode_dictionary_get_str(input, "to-tag", &totag)) return "No to-tag in message"; } //bencode_dictionary_get_str(input, "via-branch", &viabranch); if (sdp_parse(&sdp, &parsed)) return "Failed to parse SDP"; call_ng_process_flags(&flags, input); flags.opmode = opmode; errstr = "Incomplete SDP specification"; if (sdp_streams(&parsed, &streams, &flags)) goto out; call = call_get_opmode(&callid, m, opmode); errstr = "Unknown call-id"; if (!call) goto out; /* At least the random ICE strings are contained within the call struct, so we * need to hold a ref until we're done sending the reply */ call_bencode_hold_ref(call, output); monologue = call_get_mono_dialogue(call, &fromtag, &totag); errstr = "Invalid dialogue association"; if (!monologue) { rwlock_unlock_w(&call->master_lock); obj_put(call); goto out; } chopper = sdp_chopper_new(&sdp); bencode_buffer_destroy_add(output->buffer, (free_func_t) sdp_chopper_destroy, chopper); ret = monologue_offer_answer(monologue, &streams, &flags); if (!ret) ret = sdp_replace(chopper, &parsed, monologue->active_dialogue, &flags); rwlock_unlock_w(&call->master_lock); redis_update(call, m->conf.redis); obj_put(call); errstr = "Error rewriting SDP"; if (ret) goto out; bencode_dictionary_add_iovec(output, "sdp", &g_array_index(chopper->iov, struct iovec, 0), chopper->iov_num, chopper->str_len); bencode_dictionary_add_string(output, "result", "ok"); errstr = NULL; out: sdp_free(&parsed); streams_free(&streams); return errstr; }