27#include <netinet/tcp.h>
29#define TCP_KEEPIDLE TCP_KEEPALIVE
32#define TCP_KEEPINTVL 0x101
35#define TCP_KEEPCNT 0x102
50#define MAX_POINTER_STRING 33
53#define DEFAULT_STATE_BUCKETS 53
102 const char *right_key = arg;
107 right_key = object_right->
id;
110 cmp = strcmp(object_left->
id, right_key);
152 const char *right_key = arg;
157 right_key = object_right->
id;
160 cmp = strcmp(object_left->
id, right_key);
230 if (!transport_state) {
234 if (!transport_state->
flow) {
242 pjsip_transport_dec_ref(transport_state->
transport);
246 pjsip_transport_add_ref(transport_state->
transport);
265 if (!transport_state) {
269 if (!transport_state->
flow) {
294 if (!transport_state) {
299 if (!transport_state->
flow) {
326 if (tdata->msg->type != PJSIP_REQUEST_MSG ||
327 (pjsip_method_cmp(&tdata->msg->line.req.method, &pjsip_invite_method) &&
328 pjsip_method_cmp(&tdata->msg->line.req.method, &pjsip_cancel_method) &&
329 pjsip_method_cmp(&tdata->msg->line.req.method, &pjsip_options_method))) {
334 if (!transport_state) {
338 if (!transport_state->
flow) {
370 service_routes =
ast_calloc(1,
sizeof(*service_routes));
371 if (!service_routes) {
377 return service_routes;
382 if (!service_routes) {
392 int tos_as_dscp = transport->
tos >> 2;
394 if (transport->
tos) {
395 qos->flags |= PJ_QOS_PARAM_HAS_DSCP;
396 qos->dscp_val = tos_as_dscp;
398 if (transport->
cos) {
399 qos->flags |= PJ_QOS_PARAM_HAS_SO_PRIO;
400 qos->so_prio = transport->
cos;
443 pjsip_transport_shutdown(transport_state->
transport);
569 pjsip_tls_setting_default(&new_state->
tls);
570#ifdef HAVE_PJSIP_TLS_TRANSPORT_PROTO
572 new_state->
tls.proto = 0;
590 transport->external_address_refresher =
transport->state->external_signaling_address_refresher;
591 memcpy(&
transport->external_address, &
transport->state->external_signaling_address,
sizeof(
transport->external_signaling_address));
594#ifdef HAVE_PJSIP_TLS_TRANSPORT_RESTART
595static int file_stat_cmp(
const struct stat *old_stat,
const struct stat *new_stat)
597 return old_stat->st_size != new_stat->st_size
598 || old_stat->st_mtime != new_stat->st_mtime
599#if defined(HAVE_STRUCT_STAT_ST_MTIM)
600 || old_stat->st_mtim.tv_nsec != new_stat->st_mtim.tv_nsec
601#elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
602 || old_stat->st_mtimensec != new_stat->st_mtimensec
603#elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC)
604 || old_stat->st_mtimespec.tv_nsec != new_stat->st_mtimespec.tv_nsec
612 if (
a->type !=
b->type) {
616 if (pj_sockaddr_cmp(&
a->host, &
b->host)) {
620 if ((
a->localnet ||
b->localnet)
621 && ((!
a->localnet != !
b->localnet)
628 if (
ast_sockaddr_cmp(&
a->external_signaling_address, &
b->external_signaling_address)) {
636 if (
a->tls.method !=
b->tls.method
637 ||
a->tls.ciphers_num !=
b->tls.ciphers_num
638#ifdef HAVE_PJSIP_TLS_TRANSPORT_PROTO
639 ||
a->tls.proto !=
b->tls.proto
641 ||
a->tls.verify_client !=
b->tls.verify_client
642 ||
a->tls.verify_server !=
b->tls.verify_server
643 ||
a->tls.require_client_cert !=
b->tls.require_client_cert) {
647 if (memcmp(
a->ciphers,
b->ciphers,
sizeof(pj_ssl_cipher) * fmax(
a->tls.ciphers_num,
b->tls.ciphers_num))) {
651#ifdef HAVE_PJSIP_TLS_TRANSPORT_RESTART
652 if (file_stat_cmp(&
a->cert_file_stat, &
b->cert_file_stat) || file_stat_cmp(&
a->privkey_file_stat, &
b->privkey_file_stat)) {
676 pj_status_t res = -1;
679#define BIND_DELAY_US 100000
694 ast_log(
LOG_ERROR,
"Transport '%s' failed to allocate memory\n", transport_id);
699 ast_log(
LOG_WARNING,
"The async_operations setting on transport '%s' has been set to '%d'. The setting can no longer be set and is always 1.\n",
709 transport->
state = perm_state->state;
717 memcpy(&temp_state->state->host, &perm_state->state->host,
sizeof(temp_state->state->host));
718 memcpy(&temp_state->state->tls, &perm_state->state->tls,
sizeof(temp_state->state->tls));
719 memcpy(&temp_state->state->ciphers, &perm_state->state->ciphers,
sizeof(temp_state->state->ciphers));
724 if (temp_state->state->host.addr.sa_family != PJ_AF_INET && temp_state->state->host.addr.sa_family != PJ_AF_INET6) {
725 ast_log(
LOG_ERROR,
"Transport '%s' could not be started as binding not specified\n", transport_id);
730 if (!pj_sockaddr_get_port(&temp_state->state->host)) {
731 pj_sockaddr_set_port(&temp_state->state->host, (transport->
type ==
AST_TRANSPORT_TLS) ? 5061 : 5060);
737 if (temp_state->state->host.addr.sa_family == pj_AF_INET()) {
738 temp_state->state->external_signaling_address.ss.ss_family = AF_INET;
739 }
else if (temp_state->state->host.addr.sa_family == pj_AF_INET6()) {
740 temp_state->state->external_signaling_address.ss.ss_family = AF_INET6;
742 ast_log(
LOG_ERROR,
"Unknown address family for transport '%s', could not get external signaling address\n",
748 ast_log(
LOG_ERROR,
"Could not create dnsmgr for external signaling address on '%s'\n", transport_id);
754 if (temp_state->state->host.addr.sa_family == pj_AF_INET()) {
755 temp_state->state->external_media_address.ss.ss_family = AF_INET;
756 }
else if (temp_state->state->host.addr.sa_family == pj_AF_INET6()) {
757 temp_state->state->external_media_address.ss.ss_family = AF_INET6;
759 ast_log(
LOG_ERROR,
"Unknown address family for transport '%s', could not get external media address\n",
765 ast_log(
LOG_ERROR,
"Could not create dnsmgr for external media address on '%s'\n", transport_id);
770 if (transport->
flow) {
773 ast_debug(1,
"Ignoring any bind configuration on transport '%s' as it is a child of another\n",
775 pj_sockaddr_parse(pj_AF_UNSPEC(), 0, pj_cstr(&
address,
"0.0.0.0"), &temp_state->state->host);
777 temp_state->state->flow = 1;
781#ifdef HAVE_PJSIP_TLS_TRANSPORT_RESTART
782 ast_log(
LOG_NOTICE,
"Transport '%s' is not fully reloadable, not reloading: protocol, bind, TLS (everything but certificate and private key if filename is unchanged), TCP, ToS, or CoS options.\n", transport_id);
785 if (strcmp(perm_state->transport->cert_file, temp_state->transport->cert_file) ||
786 strcmp(perm_state->transport->privkey_file, temp_state->transport->privkey_file)) {
787 ast_log(
LOG_ERROR,
"Unable to restart TLS transport '%s' as certificate or private key filename has changed\n",
789 }
else if (file_stat_cmp(&perm_state->state->cert_file_stat, &temp_state->state->cert_file_stat) ||
790 file_stat_cmp(&perm_state->state->privkey_file_stat, &temp_state->state->privkey_file_stat)) {
791 if (pjsip_tls_transport_restart(perm_state->state->factory, &perm_state->state->host,
NULL) != PJ_SUCCESS) {
794 sprintf(perm_state->state->factory->info,
"%s", transport_id);
799 ast_log(
LOG_NOTICE,
"Transport '%s' is not fully reloadable, not reloading: protocol, bind, TLS, TCP, ToS, or CoS options.\n", transport_id);
801 temp_state->state->transport = perm_state->state->transport;
802 perm_state->state->transport =
NULL;
803 temp_state->state->factory = perm_state->state->factory;
804 perm_state->state->factory =
NULL;
809 for (i = 0; i <
BIND_TRIES && res != PJ_SUCCESS; i++) {
810 if (perm_state && perm_state->state && perm_state->state->transport) {
811 pjsip_udp_transport_pause(perm_state->state->transport,
812 PJSIP_UDP_TRANSPORT_DESTROY_SOCKET);
816 if (temp_state->state->host.addr.sa_family == pj_AF_INET()) {
819 &temp_state->state->transport);
820 }
else if (temp_state->state->host.addr.sa_family == pj_AF_INET6()) {
823 &temp_state->state->transport);
827 if (res == PJ_SUCCESS) {
828 temp_state->state->transport->info = pj_pool_alloc(temp_state->state->transport->pool,
831 sprintf(temp_state->state->transport->info,
"%s:%s",
AST_SIP_X_AST_TXP, transport_id);
833 if (transport->
tos || transport->
cos) {
835 pj_qos_params qos_params;
836 sock = pjsip_udp_transport_get_socket(temp_state->state->transport);
837 pj_sock_get_qos_params(sock, &qos_params);
838 set_qos(transport, &qos_params);
839 pj_sock_set_qos_params(sock, &qos_params);
843 pjsip_tcp_transport_cfg cfg;
844 static int option = 1;
845 int sockopt_count = 0;
847 pjsip_tcp_transport_cfg_default(&cfg, temp_state->state->host.addr.sa_family);
848 cfg.bind_addr = temp_state->state->host;
850 set_qos(transport, &cfg.qos_params);
853 cfg.sockopt_params.options[sockopt_count].level = pj_SOL_TCP();
854 cfg.sockopt_params.options[sockopt_count].optname = pj_TCP_NODELAY();
855 cfg.sockopt_params.options[sockopt_count].optval = &option;
856 cfg.sockopt_params.options[sockopt_count].optlen =
sizeof(option);
860#if defined(PJ_MAX_SOCKOPT_PARAMS) && PJ_MAX_SOCKOPT_PARAMS >= 5
861 ast_log(
LOG_DEBUG,
"TCP Keepalive enabled for transport '%s'. Idle Time: %d, Interval: %d, Count: %d\n",
864 cfg.sockopt_params.options[sockopt_count].level = pj_SOL_SOCKET();
865 cfg.sockopt_params.options[sockopt_count].optname = SO_KEEPALIVE;
866 cfg.sockopt_params.options[sockopt_count].optval = &option;
867 cfg.sockopt_params.options[sockopt_count].optlen =
sizeof(option);
870 cfg.sockopt_params.options[sockopt_count].level = pj_SOL_TCP();
871 cfg.sockopt_params.options[sockopt_count].optname = TCP_KEEPIDLE;
876 cfg.sockopt_params.options[sockopt_count].level = pj_SOL_TCP();
877 cfg.sockopt_params.options[sockopt_count].optname = TCP_KEEPINTVL;
882 cfg.sockopt_params.options[sockopt_count].level = pj_SOL_TCP();
883 cfg.sockopt_params.options[sockopt_count].optname = TCP_KEEPCNT;
888 ast_log(
LOG_WARNING,
"TCP keepalive settings for '%s' not set due to PJSIP built without support for setting all options. Consider using bundled PJSIP.\n",
893 cfg.sockopt_params.cnt = sockopt_count;
895 for (i = 0; i <
BIND_TRIES && res != PJ_SUCCESS; i++) {
896 if (perm_state && perm_state->state && perm_state->state->factory
897 && perm_state->state->factory->destroy) {
898 perm_state->state->factory->destroy(perm_state->state->factory);
903 &temp_state->state->factory);
906#if defined(PJ_HAS_SSL_SOCK) && PJ_HAS_SSL_SOCK != 0
907 static int option = 1;
908 int sockopt_count = 0;
911 ast_log(
LOG_ERROR,
"Transport: %s: When protocol=tls and pjproject version < 2.5.0, async_operations can't be > 1\n",
916 temp_state->state->tls.password = pj_str((
char*)transport->
password);
920 temp_state->state->tls.sockopt_params.options[sockopt_count].level = pj_SOL_TCP();
921 temp_state->state->tls.sockopt_params.options[sockopt_count].optname = pj_TCP_NODELAY();
922 temp_state->state->tls.sockopt_params.options[sockopt_count].optval = &option;
923 temp_state->state->tls.sockopt_params.options[sockopt_count].optlen =
sizeof(option);
927#if defined(PJ_MAX_SOCKOPT_PARAMS) && PJ_MAX_SOCKOPT_PARAMS >= 5
928 ast_log(
LOG_DEBUG,
"TCP Keepalive enabled for transport '%s'. Idle Time: %d, Interval: %d, Count: %d\n",
931 temp_state->state->tls.sockopt_params.options[sockopt_count].level = pj_SOL_SOCKET();
932 temp_state->state->tls.sockopt_params.options[sockopt_count].optname = SO_KEEPALIVE;
933 temp_state->state->tls.sockopt_params.options[sockopt_count].optval = &option;
934 temp_state->state->tls.sockopt_params.options[sockopt_count].optlen =
sizeof(option);
937 temp_state->state->tls.sockopt_params.options[sockopt_count].level = pj_SOL_TCP();
938 temp_state->state->tls.sockopt_params.options[sockopt_count].optname = TCP_KEEPIDLE;
940 temp_state->state->tls.sockopt_params.options[sockopt_count].optlen =
sizeof(transport->
tcp_keepalive_idle_time);
943 temp_state->state->tls.sockopt_params.options[sockopt_count].level = pj_SOL_TCP();
944 temp_state->state->tls.sockopt_params.options[sockopt_count].optname = TCP_KEEPINTVL;
949 temp_state->state->tls.sockopt_params.options[sockopt_count].level = pj_SOL_TCP();
950 temp_state->state->tls.sockopt_params.options[sockopt_count].optname = TCP_KEEPCNT;
955 ast_log(
LOG_WARNING,
"TCP keepalive settings for '%s' not set due to PJSIP built without support for setting all options. Consider using bundled PJSIP.\n",
960 temp_state->state->tls.sockopt_params.cnt = sockopt_count;
962 for (i = 0; i <
BIND_TRIES && res != PJ_SUCCESS; i++) {
963 if (perm_state && perm_state->state && perm_state->state->factory
964 && perm_state->state->factory->destroy) {
965 perm_state->state->factory->destroy(perm_state->state->factory);
971 &temp_state->state->factory);
974 if (res == PJ_SUCCESS) {
979 temp_state->state->factory->info = pj_pool_alloc(
985 sprintf(temp_state->state->factory->info,
"%s", transport_id);
988 ast_log(
LOG_ERROR,
"Transport: %s: PJSIP has not been compiled with TLS transport support, ensure OpenSSL development packages are installed\n",
993 if (transport->
cos || transport->
tos) {
997 ast_log(
LOG_WARNING,
"TLS certificate values ignored for websocket transport as they are configured in http.conf\n");
1002 if (res != PJ_SUCCESS) {
1003 char msg[PJ_ERR_MSG_SIZE];
1005 pj_strerror(res, msg,
sizeof(msg));
1046 ast_log(
LOG_ERROR,
"Transport: %s: %s %s is either missing or not readable\n",
1052 if (!strcasecmp(
var->name,
"ca_list_file")) {
1053 state->tls.ca_list_file = pj_str((
char*)
var->value);
1055 }
else if (!strcasecmp(
var->name,
"ca_list_path")) {
1056#ifdef HAVE_PJ_SSL_CERT_LOAD_FROM_FILES2
1057 state->tls.ca_list_path = pj_str((
char *)
var->value);
1060 ast_log(
LOG_WARNING,
"Asterisk has been built against a version of pjproject that does not "
1061 "support the 'ca_list_path' option. Please upgrade to version 2.4 or later.\n");
1063 }
else if (!strcasecmp(
var->name,
"cert_file")) {
1064 state->tls.cert_file = pj_str((
char *)
var->value);
1066#ifdef HAVE_PJSIP_TLS_TRANSPORT_RESTART
1067 if (stat(
var->value, &
state->cert_file_stat)) {
1068 ast_log(
LOG_ERROR,
"Failed to stat certificate file '%s' for transport '%s' due to '%s'\n",
1075 }
else if (!strcasecmp(
var->name,
"priv_key_file")) {
1076 state->tls.privkey_file = pj_str((
char *)
var->value);
1078#ifdef HAVE_PJSIP_TLS_TRANSPORT_RESTART
1079 if (stat(
var->value, &
state->privkey_file_stat)) {
1080 ast_log(
LOG_ERROR,
"Failed to stat private key file '%s' for transport '%s' due to '%s'\n",
1138 if (!strcasecmp(
var->value,
"flow")) {
1139 transport->
flow = 1;
1141 if (!strcasecmp(
var->value,
"udp")) {
1143 }
else if (!strcasecmp(
var->value,
"tcp")) {
1145 }
else if (!strcasecmp(
var->value,
"tls")) {
1147 }
else if (!strcasecmp(
var->value,
"ws")) {
1149 }
else if (!strcasecmp(
var->value,
"wss")) {
1155 transport->
flow = 0;
1175 if (transport->
flow) {
1196 rc = pj_sockaddr_parse(pj_AF_UNSPEC(), 0, pj_cstr(&
buf,
var->value), &
state->host);
1197 if (rc != PJ_SUCCESS) {
1200 return rc != PJ_SUCCESS ? -1 : 0;
1232 if (!strcasecmp(
var->name,
"verify_server")) {
1234 }
else if (!strcasecmp(
var->name,
"verify_client")) {
1236 }
else if (!strcasecmp(
var->name,
"require_client_cert")) {
1237 state->tls.require_client_cert =
ast_true(
var->value) ? PJ_TRUE : PJ_FALSE;
1238 }
else if (!strcasecmp(
var->name,
"allow_wildcard_certs")) {
1315 state->tls.method = PJSIP_SSL_DEFAULT_METHOD;
1316 }
else if (!strcasecmp(
var->value,
"unspecified")) {
1317 state->tls.method = PJSIP_SSL_UNSPECIFIED_METHOD;
1318 }
else if (!strcasecmp(
var->value,
"tlsv1")) {
1319 state->tls.method = PJSIP_TLSV1_METHOD;
1320#ifdef HAVE_PJSIP_TLS_1_1
1321 }
else if (!strcasecmp(
var->value,
"tlsv1_1")) {
1322 state->tls.method = PJSIP_TLSV1_1_METHOD;
1324#ifdef HAVE_PJSIP_TLS_1_2
1325 }
else if (!strcasecmp(
var->value,
"tlsv1_2")) {
1326 state->tls.method = PJSIP_TLSV1_2_METHOD;
1328#ifdef HAVE_PJSIP_TLS_1_3
1329 }
else if (!strcasecmp(
var->value,
"tlsv1_3")) {
1330 state->tls.method = PJSIP_TLSV1_3_METHOD;
1332 }
else if (!strcasecmp(
var->value,
"sslv2")) {
1333 state->tls.method = PJSIP_SSLV2_METHOD;
1334 }
else if (!strcasecmp(
var->value,
"sslv3")) {
1335 state->tls.method = PJSIP_SSLV3_METHOD;
1336 }
else if (!strcasecmp(
var->value,
"sslv23")) {
1337 state->tls.method = PJSIP_SSLV23_METHOD;
1347 [PJSIP_SSL_UNSPECIFIED_METHOD] =
"unspecified",
1348 [PJSIP_TLSV1_METHOD] =
"tlsv1",
1349#ifdef HAVE_PJSIP_TLS_1_1
1350 [PJSIP_TLSV1_1_METHOD] =
"tlsv1_1",
1352#ifdef HAVE_PJSIP_TLS_1_2
1353 [PJSIP_TLSV1_2_METHOD] =
"tlsv1_2",
1355#ifdef HAVE_PJSIP_TLS_1_3
1356 [PJSIP_TLSV1_3_METHOD] =
"tlsv1_3",
1358 [PJSIP_SSLV2_METHOD] =
"sslv2",
1359 [PJSIP_SSLV3_METHOD] =
"sslv3",
1360 [PJSIP_SSLV23_METHOD] =
"sslv23",
1379#if defined(PJ_HAS_SSL_SOCK) && PJ_HAS_SSL_SOCK != 0
1381static pj_ssl_cipher cipher_name_to_id(
const char *
name)
1383 pj_ssl_cipher
ciphers[PJ_SSL_SOCK_MAX_CIPHERS];
1384 unsigned int cipher_num = PJ_ARRAY_SIZE(
ciphers);
1387 if (pj_ssl_cipher_get_availables(
ciphers, &cipher_num)) {
1391 for (pos = 0; pos < cipher_num; ++pos) {
1392 const char *pos_name = pj_ssl_cipher_name(
ciphers[pos]);
1393 if (pos_name && !strcmp(pos_name,
name)) {
1402#if defined(PJ_HAS_SSL_SOCK) && PJ_HAS_SSL_SOCK != 0
1415 pj_ssl_cipher cipher;
1418 cipher = cipher_name_to_id(
name);
1421 if (!strnicmp(
name,
"0x", 2)) {
1422 pj_str_t cipher_st = pj_str((
char *)
name + 2);
1423 cipher = pj_strtoul2(&cipher_st,
NULL, 16);
1425 cipher = atoi(
name);
1429 if (pj_ssl_cipher_is_supported(cipher)) {
1430 for (idx =
state->tls.ciphers_num; idx--;) {
1431 if (
state->ciphers[idx] == cipher) {
1436 state->ciphers[
state->tls.ciphers_num++] = cipher;
1445#if defined(PJ_HAS_SSL_SOCK) && PJ_HAS_SSL_SOCK != 0
1469 res |= transport_cipher_add(
state,
name);
1475 return res ? -1 : 0;
1479#if defined(PJ_HAS_SSL_SOCK) && PJ_HAS_SSL_SOCK != 0
1480static void cipher_to_str(
char **
buf,
const pj_ssl_cipher *
ciphers,
unsigned int cipher_num)
1491 for (idx = 0; idx < cipher_num; ++idx) {
1493 if (idx < cipher_num - 1) {
1503#if defined(PJ_HAS_SSL_SOCK) && PJ_HAS_SSL_SOCK != 0
1504static int transport_tls_cipher_to_str(
const void *obj,
const intptr_t *
args,
char **
buf)
1514 return *
buf ? 0 : -1;
1518#if defined(PJ_HAS_SSL_SOCK) && PJ_HAS_SSL_SOCK != 0
1521 pj_ssl_cipher
ciphers[PJ_SSL_SOCK_MAX_CIPHERS];
1522 unsigned int cipher_num = PJ_ARRAY_SIZE(
ciphers);
1527 e->
command =
"pjsip list ciphers";
1528 e->
usage =
"Usage: pjsip list ciphers\n"
1529 " List available OpenSSL cipher names.\n";
1535 if (pj_ssl_cipher_get_availables(
ciphers, &cipher_num) || !cipher_num) {
1544 ast_cli(
a->fd,
"No available ciphers\n");
1599 for (ha =
state->localnet; ha; ha = ha->
next) {
1633 "interpret 'tos' value '%s'\n",
1643 "transport '%s' - 'tos' value '%s' uses bits that are "
1644 "discarded when converted to DSCP. Using equivalent %u instead.\n",
1714 "%*s: <TransportId........> <Type> <cos> <tos> <BindAddress%*.*s>\n",
1724 char hoststr[PJ_INET6_ADDRSTRLEN];
1733 pj_sockaddr_print(&
state->host, hoststr,
sizeof(hoststr), 3);
1735 ast_str_append(&context->output_buffer, 0,
"%*s: %-21s %6s %5u %5u %s\n",
1739 transport->
cos, transport->
tos, hoststr);
1741 if (context->show_details
1742 || (context->show_details_only_level_0 && context->indent_level == 0)) {
1751#if defined(PJ_HAS_SSL_SOCK) && PJ_HAS_SSL_SOCK != 0
1752 AST_CLI_DEFINE(handle_pjsip_list_ciphers,
"List available OpenSSL cipher names"),
1755 .
command =
"pjsip list transports",
1756 .
usage =
"Usage: pjsip list transports [ like <pattern> ]\n"
1757 " List the configured PJSIP Transports\n"
1758 " Optional regular expression pattern is used to filter the list.\n"),
1760 .
command =
"pjsip show transports",
1761 .
usage =
"Usage: pjsip show transports [ like <pattern> ]\n"
1762 " Show the configured PJSIP Transport\n"
1763 " Optional regular expression pattern is used to filter the list.\n"),
1765 .
command =
"pjsip show transport",
1766 .
usage =
"Usage: pjsip show transport <id>\n"
1767 " Show the configured PJSIP Transport\n"),
1790 if (trans_state->
flow) {
1793 pjsip_transport_dec_ref(trans_state->
transport);
1870#if defined(PJ_HAS_SSL_SOCK) && PJ_HAS_SSL_SOCK != 0
Access Control of various sorts.
void ast_free_ha(struct ast_ha *ha)
Free a list of HAs.
int ast_str2tos(const char *value, unsigned int *tos)
Convert a string to the appropriate TOS value.
void ast_ha_join(const struct ast_ha *ha, struct ast_str **buf)
Convert HAs to a comma separated string value.
struct ast_ha * ast_append_ha(const char *sense, const char *stuff, struct ast_ha *path, int *error)
Add a new rule to a list of HAs.
void ast_cli_unregister_multiple(void)
char * strsep(char **str, const char *delims)
Asterisk main include file. File version handling, generic pbx functions.
#define ast_strdup(str)
A wrapper for strdup()
#define ast_strdupa(s)
duplicate a string in memory from the stack
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
#define ast_calloc(num, len)
A wrapper for calloc()
int ao2_container_dup(struct ao2_container *dest, struct ao2_container *src, enum search_flags flags)
Copy all object references in the src container into the dest container.
#define ao2_link(container, obj)
Add an object to a container.
@ AO2_ALLOC_OPT_LOCK_NOLOCK
@ AO2_ALLOC_OPT_LOCK_MUTEX
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container,...
#define ao2_unlink_flags(container, obj, flags)
Remove an object from a container.
int() ao2_callback_fn(void *obj, void *arg, int flags)
Type of a generic callback function.
#define ao2_link_flags(container, obj, flags)
Add an object to a container.
#define ao2_find(container, arg, flags)
#define ao2_replace(dst, src)
Replace one object reference with another cleaning up the original.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
@ OBJ_SEARCH_PARTIAL_KEY
The arg parameter is a partial search key similar to OBJ_SEARCH_KEY.
@ OBJ_SEARCH_OBJECT
The arg parameter is an object of the same type.
@ OBJ_NOLOCK
Assume that the ao2_container is already locked.
@ OBJ_SEARCH_MASK
Search option field mask.
@ OBJ_SEARCH_KEY
The arg parameter is a search key, but is not an object.
#define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn)
Allocate and initialize a list container.
#define ao2_alloc(data_size, destructor_fn)
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Allocate and initialize a hash container with the desired number of buckets.
static struct ast_sorcery * sorcery
static struct ast_channel * callback(struct ast_channelstorage_instance *driver, ao2_callback_data_fn *cb_fn, void *arg, void *data, int ao2_flags, int rdlock)
#define AST_CLI_DEFINE(fn, txt,...)
void ast_cli(int fd, const char *fmt,...)
#define ast_cli_register_multiple(e, len)
Register multiple commands.
#define STRFLDSET(type,...)
Convert a struct and a list of stringfield fields to an argument list of field offsets.
#define FLDSET(type,...)
Convert a struct and list of fields to an argument list of field offsets.
@ OPT_UINT_T
Type for default option handler for unsigned integers.
@ OPT_BOOL_T
Type for default option handler for bools (ast_true/ast_false)
@ OPT_INT_T
Type for default option handler for signed integers.
@ OPT_STRINGFIELD_T
Type for default option handler for stringfields.
static struct ast_sip_transport_state * find_temporary_state(struct ast_sip_transport *transport)
static int require_client_cert_to_str(const void *obj, const intptr_t *args, char **buf)
static int transport_state_init(const struct aco_option *opt, struct ast_variable *var, void *obj)
Custom handler for type just makes sure the state is created.
int ast_sip_initialize_sorcery_transport(void)
Initialize sorcery with transport support.
static struct ast_cli_entry cli_commands[]
static int verify_server_to_str(const void *obj, const intptr_t *args, char **buf)
static int transport_tls_method_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
Custom handler for TLS method setting.
int ast_sip_transport_state_set_transport(const char *transport_name, pjsip_transport *transport)
Sets the PJSIP transport on a child transport.
static int format_ami_endpoint_transport(const struct ast_sip_endpoint *endpoint, struct ast_sip_ami *ami)
static int transport_state_hash(const void *obj, const int flags)
hashing function for state objects
static int cli_print_header(void *obj, void *arg, int flags)
struct ao2_container * ast_sip_get_transport_states(void)
Retrieves all transport states.
static int destroy_sip_transport_state(void *data)
static int transport_state_cmp(void *obj, void *arg, int flags)
comparator function for state objects
static int transport_bind_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
Custom handler for turning a string bind into a pj_sockaddr.
static int tls_method_to_str(const void *obj, const intptr_t *args, char **buf)
static void sip_transport_state_destroy(void *obj)
Destructor for ast_sip_transport state information.
static int transport_protocol_to_str(const void *obj, const intptr_t *args, char **buf)
static void sip_transport_destroy(void *obj)
Destructor for transport.
#define DEFAULT_STATE_BUCKETS
Default number of state container buckets.
static int internal_state_hash(const void *obj, const int flags)
hashing function for state objects
static int verify_client_to_str(const void *obj, const intptr_t *args, char **buf)
static void localnet_to_vl_append(struct ast_variable **head, struct ast_ha *ha)
static int allow_wildcard_certs_to_str(const void *obj, const intptr_t *args, char **buf)
static int cert_file_to_str(const void *obj, const intptr_t *args, char **buf)
static int transport_tls_bool_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
Custom handler for TLS boolean settings.
void ast_sip_message_apply_transport(const char *transport_name, pjsip_tx_data *tdata)
Apply the configuration for a transport to an outgoing message.
static int transport_bind_to_str(const void *obj, const intptr_t *args, char **buf)
static struct ast_sip_transport_state * find_state_by_transport(const struct ast_sip_transport *transport)
static struct ast_sip_transport_state * find_or_create_temporary_state(struct ast_sip_transport *transport)
static int internal_state_cmp(void *obj, void *arg, int flags)
comparator function for state objects
void ast_sip_service_route_vector_destroy(struct ast_sip_service_route_vector *service_routes)
Destroy a vector of service routes.
static int localnet_to_str(const void *obj, const intptr_t *args, char **buf)
static int privkey_file_to_str(const void *obj, const intptr_t *args, char **buf)
static int sip_transport_to_ami(const struct ast_sip_transport *transport, struct ast_str **buf)
static int cli_iterate(void *container, ao2_callback_fn callback, void *args)
static void copy_state_to_transport(struct ast_sip_transport *transport)
static struct internal_state * internal_state_alloc(struct ast_sip_transport *transport)
static int transport_localnet_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
Custom handler for localnet setting.
static void * cli_retrieve_by_id(const char *id)
static struct internal_state * find_internal_state_by_transport(const struct ast_sip_transport *transport)
static int populate_transport_states(void *obj, void *arg, int flags)
static void temp_state_store_cleanup(void *data)
static void set_qos(struct ast_sip_transport *transport, pj_qos_params *qos)
struct ast_sip_service_route_vector * ast_sip_service_route_vector_alloc(void)
Allocate a vector of service routes.
static int tos_to_str(const void *obj, const intptr_t *args, char **buf)
static struct ao2_container * cli_get_container(const char *regex)
static int transport_apply(const struct ast_sorcery *sorcery, void *obj)
Apply handler for transports.
static int cli_print_body(void *obj, void *arg, int flags)
struct ast_sip_transport_state * ast_sip_get_transport_state(const char *transport_id)
Retrieve transport state.
static int localnet_to_vl(const void *obj, struct ast_variable **fields)
static int transport_tls_file_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
Custom handler for TLS method setting.
int ast_sip_destroy_sorcery_transport(void)
static const char * transport_types[]
struct ast_sip_endpoint_formatter endpoint_transport_formatter
static int transport_tos_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
Custom handler for TOS setting.
static int ca_list_file_to_str(const void *obj, const intptr_t *args, char **buf)
static struct ast_sip_cli_formatter_entry * cli_formatter
static void * sip_transport_alloc(const char *name)
Allocator for transport.
static int remove_temporary_state(void)
static void internal_state_destroy(void *obj)
Destructor for ast_sip_transport state information.
static int ca_list_path_to_str(const void *obj, const intptr_t *args, char **buf)
int ast_sip_transport_state_set_preferred_identity(const char *transport_name, const char *identity)
Sets the P-Preferred-Identity on a child transport.
static const char * tls_method_map[]
static int has_state_changed(struct ast_sip_transport_state *a, struct ast_sip_transport_state *b)
static int transport_protocol_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
Custom handler for turning a string protocol into an enum.
int ast_sip_transport_state_set_service_routes(const char *transport_name, struct ast_sip_service_route_vector *service_routes)
Sets the service routes on a child transport.
static struct ao2_container * transport_states
static void states_cleanup(void *states)
void ast_dnsmgr_release(struct ast_dnsmgr_entry *entry)
Free a DNS manager entry.
int ast_dnsmgr_lookup(const char *name, struct ast_sockaddr *result, struct ast_dnsmgr_entry **dnsmgr, const char *service)
Allocate and initialize a DNS manager entry.
static int regex(struct ast_channel *chan, const char *cmd, char *parse, char *buf, size_t len)
void astman_send_error_va(struct mansession *s, const struct message *m, const char *fmt,...)
Send error in manager transaction (with va_args support)
void astman_append(struct mansession *s, const char *fmt,...)
#define ast_sip_push_task_wait_servant(serializer, sip_task, task_data)
Support for WebSocket connections within the Asterisk HTTP server and client WebSocket connections to...
#define AST_DEFAULT_WEBSOCKET_WRITE_TIMEOUT_STR
Default websocket write timeout, in ms (as a string)
#define ast_variable_new(name, value, filename)
#define ast_variable_list_append(head, new_var)
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Support for logging to various files, console and syslog Configuration in file logger....
#define ast_debug(level,...)
Log a DEBUG message.
int ast_sockaddr_cmp(const struct ast_sockaddr *a, const struct ast_sockaddr *b)
Compares two ast_sockaddr structures.
static char * ast_sockaddr_stringify_addr(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() to return an address only.
struct ao2_container * container
#define AST_SIP_X_AST_TXP
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
#define SIP_TLS_MAX_CIPHERS
Maximum number of ciphers supported for a TLS transport.
void ast_sip_register_endpoint_formatter(struct ast_sip_endpoint_formatter *obj)
Register an endpoint formatter.
void ast_sip_unregister_endpoint_formatter(struct ast_sip_endpoint_formatter *obj)
Unregister an endpoint formatter.
int ast_sip_sorcery_object_to_ami(const void *obj, struct ast_str **buf)
Converts a sorcery object to a string of object properties.
struct ast_str * ast_sip_create_ami_event(const char *event, struct ast_sip_ami *ami)
Creates a string to store AMI event data in.
int ast_sip_add_header(pjsip_tx_data *tdata, const char *name, const char *value)
Add a header to an outbound SIP message.
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
#define AST_SIP_X_AST_TXP_LEN
int ast_sip_unregister_cli_formatter(struct ast_sip_cli_formatter_entry *formatter)
Unregisters a CLI formatter.
#define CLI_HEADER_FILLER
int ast_sip_cli_print_sorcery_objectset(void *obj, void *arg, int flags)
Prints a sorcery object's ast_variable list.
char * ast_sip_cli_traverse_objects(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
#define CLI_INDENT_TO_SPACES(x)
int ast_sip_register_cli_formatter(struct ast_sip_cli_formatter_entry *formatter)
Registers a CLI formatter.
Sorcery Data Access Layer API.
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
@ AST_RETRIEVE_FLAG_MULTIPLE
Return all matching objects.
@ AST_RETRIEVE_FLAG_ALL
Perform no matching, return all objects.
void ast_sorcery_object_set_has_dynamic_contents(const void *object)
Set the dynamic contents flag on a sorcery object.
int ast_sorcery_diff(const struct ast_sorcery *sorcery, const void *original, const void *modified, struct ast_variable **changes)
Create a changeset of two objects.
void * ast_sorcery_retrieve_by_id(const struct ast_sorcery *sorcery, const char *type, const char *id)
Retrieve an object using its unique identifier.
#define ast_sorcery_object_register(sorcery, type, alloc, transform, apply)
Register an object type.
struct ao2_container * ast_sorcery_retrieve_by_regex(const struct ast_sorcery *sorcery, const char *type, const char *regex)
Retrieve multiple objects using a regular expression on their id.
#define ast_sorcery_object_field_register_custom(sorcery, type, name, default_val, config_handler, sorcery_handler, multiple_handler, flags,...)
Register a field within an object with custom handlers.
void * ast_sorcery_generic_alloc(size_t size, ao2_destructor_fn destructor)
Allocate a generic sorcery capable object.
int ast_sorcery_object_id_compare(void *obj, void *arg, int flags)
ao2 object comparator based on sorcery id.
#define ast_sorcery_object_field_register(sorcery, type, name, default_val, opt_type, flags,...)
Register a field within an object.
int ast_sorcery_object_id_sort(const void *obj, const void *arg, int flags)
ao2 object sorter based on sorcery id.
#define MAX_OBJECT_FIELD
Maximum length of an object field name.
#define ast_sorcery_apply_default(sorcery, type, name, data)
void * ast_sorcery_retrieve_by_fields(const struct ast_sorcery *sorcery, const char *type, unsigned int flags, struct ast_variable *fields)
Retrieve an object or multiple objects using specific fields.
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
static force_inline int attribute_pure ast_str_hash(const char *str)
Compute a hash value on a string.
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
static force_inline int attribute_pure ast_strlen_zero(const char *s)
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
#define AST_YESNO(x)
return Yes or No depending on the argument.
char *attribute_pure ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
descriptor for a cli entry.
internal representation of ACL entries In principle user applications would have no need for this,...
struct ast_sockaddr netmask
CLI Formatter Context passed to all formatters.
CLI Formatter Registry Entry.
int(* iterate)(void *container, ao2_callback_fn callback, void *args)
ao2_callback_fn * print_header
void *(* retrieve_by_id)(const char *id)
const char *(* get_id)(const void *obj)
ao2_callback_fn * print_body
struct ao2_container *(* get_container)(const char *regex)
An entity with which Asterisk communicates.
const ast_string_field transport
Structure for SIP transport information.
struct ast_dnsmgr_entry * external_media_address_refresher
struct ast_sip_service_route_vector * service_routes
char * preferred_identity
struct pjsip_transport * transport
Transport itself.
struct ast_dnsmgr_entry * external_signaling_address_refresher
pj_ssl_cipher ciphers[SIP_TLS_MAX_CIPHERS]
const ast_string_field privkey_file
const ast_string_field ca_list_path
const ast_string_field cert_file
const ast_string_field password
int tcp_keepalive_probe_count
const ast_string_field external_signaling_address
const ast_string_field ca_list_file
struct ast_sip_transport_state * state
unsigned int async_operations
pj_ssl_cipher ciphers[SIP_TLS_MAX_CIPHERS]
const ast_string_field external_media_address
int tcp_keepalive_interval_time
int tcp_keepalive_idle_time
Full structure for sorcery.
Support for dynamic strings.
Structure for variables, used for configurations and for channel variables.
struct ast_sip_transport_state * state
Transport state information.
struct ast_sip_transport * transport
Transport configuration object.
#define AST_THREADSTORAGE_CUSTOM(a, b, c)
Define a thread storage variable, with custom initialization and cleanup.
void * ast_threadstorage_get(struct ast_threadstorage *ts, size_t init_size)
Retrieve thread storage.
int error(const char *format,...)
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
int ast_file_is_readable(const char *filename)
Test that a file exists and is readable by the effective user.
int ast_compare_versions(const char *version1, const char *version2)
Compare 2 major.minor.patch.extra version strings.
#define ARRAY_IN_BOUNDS(v, a)
Checks to see if value is within the bounds of the given array.
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
#define AST_VECTOR_CALLBACK_VOID(vec, callback,...)
Execute a callback on every element in a vector disregarding callback return.
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.