static int sangoma_create_rtp(void *usr_priv, sngtc_codec_request_leg_t *codec_reg_leg, sngtc_codec_reply_leg_t* codec_reply_leg, void **rtp_fd) { switch_rtp_t *rtp_session = NULL; switch_port_t rtp_port; char codec_ip[255]; char local_ip[255]; switch_rtp_flag_t flags = 0; int iana = 0; const char *err = NULL; struct sangoma_transcoding_session *sess = usr_priv; struct in_addr local_ip_addr = { 0 }; local_ip_addr.s_addr = htonl(codec_reply_leg->host_ip); switch_inet_ntop(AF_INET, &local_ip_addr, local_ip, sizeof(local_ip)); /* request a port */ if (!(rtp_port = switch_rtp_request_port(local_ip))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to allocate RTP port for IP %s\n", local_ip); return -1; } switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Allocated port %d for IP %s\n", rtp_port, local_ip); codec_reg_leg->host_udp_port = rtp_port; sngtc_codec_ipv4_hex_to_str(codec_reply_leg->codec_ip, codec_ip); iana = codec_id_to_iana(codec_reg_leg->codec_id); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Creating RTP session for host (%s/%d) vocallo(%s/%d) Iana=%d ms=%d idx=%lu\n", local_ip, rtp_port, codec_ip, codec_reply_leg->codec_udp_port, iana, codec_reg_leg->ms*1000, sess->sessid); /* create the RTP socket, dont use the session pool since the session may go away while the RTP socket should linger around * until sangoma_transcode decides to kill it (possibly because the same RTP session is used for a different call) */ rtp_session = switch_rtp_new(local_ip, rtp_port, codec_ip, codec_reply_leg->codec_udp_port, iana, sess->impl->samples_per_packet, codec_reg_leg->ms*1000, /* microseconds per packet */ flags, NULL, &err, g_pool); if (!rtp_session) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to create switch rtp session: %s\n", err); return -1; } *rtp_fd = rtp_session; return 0; }
static int sangoma_create_rtp_port(void *usr_priv, uint32_t host_ip, uint32_t *p_rtp_port, void **rtp_fd) { struct in_addr local_ip_addr = { 0 }; char local_ip[255]; switch_port_t rtp_port; local_ip_addr.s_addr = htonl(host_ip); switch_inet_ntop(AF_INET, &local_ip_addr, local_ip, sizeof(local_ip)); /* request a port */ if (!(rtp_port = switch_rtp_request_port(local_ip))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to allocate RTP port for IP %s\n", local_ip); return -1; } switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "New allocated port %d for IP %s/%d.%d.%d.%d\n", rtp_port, local_ip, SNGTC_NIPV4(host_ip)); *p_rtp_port = rtp_port; *rtp_fd = (void *)(long)rtp_port; return 0; }
static int sangoma_parse_config(void) { switch_xml_t cfg, settings, param, vocallos, xml, vocallo; struct in_addr vocallo_base_ip; char ipbuff[50]; char netbuff[50]; int host_ipaddr = 0; int host_netmaskaddr = 0; int vidx = 0; int baseudp = 0; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Reading sangoma codec configuration\n"); if (!(xml = switch_xml_open_cfg(SANGOMA_TRANSCODE_CONFIG, &cfg, NULL))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to open sangoma codec configuration %s\n", SANGOMA_TRANSCODE_CONFIG); return -1; } memset(&g_init_cfg, 0, sizeof(g_init_cfg)); if ((settings = switch_xml_child(cfg, "settings"))) { /* nothing here yet */ for (param = switch_xml_child(settings, "param"); param; param = param->next) { char *var = (char *)switch_xml_attr_soft(param, "name"); char *val = (char *)switch_xml_attr_soft(param, "value"); /* this parameter overrides the default list of codecs to load */ if (!strcasecmp(var, "register")) { strncpy(g_codec_register_list, val, sizeof(g_codec_register_list)-1); g_codec_register_list[sizeof(g_codec_register_list)-1] = 0; } else if (!strcasecmp(var, "noregister")) { strncpy(g_codec_noregister_list, val, sizeof(g_codec_noregister_list)-1); g_codec_noregister_list[sizeof(g_codec_noregister_list)-1] = 0; } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Ignored unknown Sangoma codec setting %s\n", var); } } } if ((vocallos = switch_xml_child(cfg, "vocallos"))) { for (vocallo = switch_xml_child(vocallos, "vocallo"); vocallo; vocallo = vocallo->next) { const char *name = switch_xml_attr(vocallo, "name"); if (!name) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Sangoma vocallo found with no name= attribute, ignoring!\n"); continue; } if (load_nic_network_information(name, &g_init_cfg.host_nic_vocallo_cfg[vidx])) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Ignoring vocallo %s, failed to retrieve its network configuration\n", name); continue; } switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Configuring vocallo %s\n", name); g_init_cfg.host_nic_vocallo_cfg[vidx].vocallo_base_udp_port = SANGOMA_DEFAULT_UDP_PORT; g_init_cfg.host_nic_vocallo_cfg[vidx].silence_suppression = 0; for (param = switch_xml_child(vocallo, "param"); param; param = param->next) { char *var = (char *)switch_xml_attr_soft(param, "name"); char *val = (char *)switch_xml_attr_soft(param, "value"); /* starting UDP port to be used by the vocallo modules */ if (!strcasecmp(var, "baseudp")) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Found Sangoma codec base udp port %s\n", val); baseudp = atoi(val); if (baseudp < SANGOMA_MIN_UDP_PORT || baseudp > SANGOMA_MAX_UDP_PORT) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid Sangoma codec base udp port %s, using default %d\n", val, SANGOMA_DEFAULT_UDP_PORT); break; } g_init_cfg.host_nic_vocallo_cfg[vidx].vocallo_base_udp_port = baseudp; } else if (!strcasecmp(var, "vocalloaddr")) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Found Sangoma codec vocallo addr %s\n", val); if (switch_inet_pton(AF_INET, val, &vocallo_base_ip) <= 0) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid Sangoma codec vocallo addr %s\n", val); break; } g_init_cfg.host_nic_vocallo_cfg[vidx].vocallo_ip = ntohl(vocallo_base_ip.s_addr); } else if (!strcasecmp(var, "silence")) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Found Sangoma codec silence setting %s\n", val); g_init_cfg.host_nic_vocallo_cfg[vidx].silence_suppression = switch_true(val) ? 1 : 0; } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Ignored unknown Sangoma vocallo setting %s\n", var); } } if (!g_init_cfg.host_nic_vocallo_cfg[vidx].vocallo_ip) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Ignoring vocallo %s, no valid address was configured\n", name); continue; } host_ipaddr = htonl(g_init_cfg.host_nic_vocallo_cfg[vidx].host_ip); host_netmaskaddr = htonl(g_init_cfg.host_nic_vocallo_cfg[vidx].host_ip_netmask); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Configured Sangoma transcoding interface %s, IP address %s, netmask %s\n", name, switch_inet_ntop(AF_INET, &host_ipaddr, ipbuff, sizeof(ipbuff)), switch_inet_ntop(AF_INET, &host_netmaskaddr, netbuff, sizeof(netbuff))); strncpy(g_vocallo_names[vidx], name, sizeof(g_vocallo_names[vidx])-1); g_vocallo_names[vidx][sizeof(g_vocallo_names[vidx])-1] = 0; vidx++; } } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No <vocallos> section found in configuration file %s\n", SANGOMA_TRANSCODE_CONFIG); } switch_xml_free(xml); if (!vidx) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No vocallos were configured, make sure there is at least one <vocallo> in %s.\n", SANGOMA_TRANSCODE_CONFIG); } g_init_cfg.host_nic_vocallo_sz = vidx; return 0; }