From 872db73eeb6bb41d78440d8a1b92b917a64e3932 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 18 Dec 2007 19:12:45 +0000 Subject: [PATCH] update sofia git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@6874 d0543943-73ff-0310-b7d9-9358b9ac24b2 --- conf/sip_profiles/default.xml | 9 + .../libsofia-sip-ua/tport/tport_type_sctp.c | 2 +- src/mod/endpoints/mod_sofia/mod_sofia.h | 31 +++- src/mod/endpoints/mod_sofia/sofia.c | 111 ++++++++++-- src/mod/endpoints/mod_sofia/sofia_glue.c | 161 ++++++++++++++++-- 5 files changed, 274 insertions(+), 40 deletions(-) diff --git a/conf/sip_profiles/default.xml b/conf/sip_profiles/default.xml index cbdab21c42..7a822398e7 100644 --- a/conf/sip_profiles/default.xml +++ b/conf/sip_profiles/default.xml @@ -42,6 +42,15 @@ + + + + + + + + + diff --git a/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_sctp.c b/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_sctp.c index 5c8f6bdeaa..8c43529355 100644 --- a/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_sctp.c +++ b/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_sctp.c @@ -242,7 +242,7 @@ int tport_recv_sctp(tport_t *self) return 0; /* End of stream */ } - tport_recv_bytes(self, n, n); + tport_recv_bytes(self, N, N); veclen = tport_recv_iovec(self, &self->tp_msg, iovec, N, 0); if (veclen < 0) diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h index 015b040ba0..868db83c5c 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.h +++ b/src/mod/endpoints/mod_sofia/mod_sofia.h @@ -71,6 +71,7 @@ typedef struct private_object private_object_t; #define SOFIA_SIP_HEADER_PREFIX "sip_h_" #define SOFIA_SIP_HEADER_PREFIX_T "~sip_h_" #define SOFIA_DEFAULT_PORT "5060" +#define SOFIA_DEFAULT_TLS_PORT "5061" #include #include @@ -113,7 +114,8 @@ typedef enum { PFLAG_RESPAWN = (1 << 9), PFLAG_GREEDY = (1 << 10), PFLAG_MULTIREG = (1 << 11), - PFLAG_SUPRESS_CNG = (1 << 12) + PFLAG_SUPRESS_CNG = (1 << 12), + PFLAG_TLS = (1 << 13) } PFLAGS; typedef enum { @@ -220,13 +222,18 @@ struct sofia_profile { char *username; char *url; char *bindurl; + char *tls_url; + char *tls_bindurl; char *sipdomain; char *timer_name; char *hold_music; char *bind_params; + char *tls_bind_params; + char *tls_cert_dir; char *reg_domain; char *user_agent; int sip_port; + int tls_sip_port; char *codec_string; int running; int dtmf_duration; @@ -369,6 +376,14 @@ typedef enum { AUTH_STALE, } auth_res_t; +typedef enum { + SOFIA_TRANSPORT_UNKNOWN = 0, + SOFIA_TRANSPORT_UDP, + SOFIA_TRANSPORT_TCP, + SOFIA_TRANSPORT_TCP_TLS, + SOFIA_TRANSPORT_SCTP, +} sofia_transport_t; + #define sofia_test_pflag(obj, flag) ((obj)->pflags & flag) #define sofia_set_pflag(obj, flag) (obj)->pflags |= (flag) #define sofia_set_pflag_locked(obj, flag) assert(obj->flag_mutex != NULL);\ @@ -469,7 +484,7 @@ char *sofia_glue_get_url_from_contact(char *buf, uint8_t to_dup); void sofia_presence_set_hash_key(char *hash_key, int32_t len, sip_t const *sip); void sofia_glue_sql_close(sofia_profile_t *profile); int sofia_glue_init_sql(sofia_profile_t *profile); -char *sofia_overcome_sip_uri_weakness(switch_core_session_t *session, const char *uri, const char *transport, switch_bool_t uri_only); +char *sofia_overcome_sip_uri_weakness(switch_core_session_t *session, const char *uri, const sofia_transport_t transport, switch_bool_t uri_only); switch_bool_t sofia_glue_execute_sql_callback(sofia_profile_t *profile, switch_bool_t master, switch_mutex_t *mutex, @@ -521,4 +536,14 @@ void sofia_reg_release_gateway__(const char *file, const char *func, int line, s \ if(_session) break; \ } while(!_session) - + + +/* + * Transport handling helper functions + */ +sofia_transport_t sofia_glue_via2transport(const sip_via_t *via); +sofia_transport_t sofia_glue_url2transport(const url_t *url); + +const char *sofia_glue_transport2str(const sofia_transport_t tp); + +int sofia_glue_transport_has_tls(const sofia_transport_t tp); diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 0c760f6547..0e90a0e98b 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -385,9 +385,14 @@ void *SWITCH_THREAD_FUNC sofia_profile_thread_run(switch_thread_t *thread, void } profile->nua = nua_create(profile->s_root, /* Event loop */ - sofia_event_callback, /* Callback for processing events */ - profile, /* Additional data to pass to callback */ - NUTAG_URL(profile->bindurl), NTATAG_UDP_MTU(65536), TAG_IF(tportlog,TPTAG_LOG(1)), TAG_END()); /* Last tag should always finish the sequence */ + sofia_event_callback, /* Callback for processing events */ + profile, /* Additional data to pass to callback */ + NUTAG_URL(profile->bindurl), + TAG_IF(sofia_test_pflag(profile, PFLAG_TLS), NUTAG_SIPS_URL(profile->tls_bindurl)), + TAG_IF(sofia_test_pflag(profile, PFLAG_TLS), NUTAG_CERTIFICATE_DIR(profile->tls_cert_dir)), + NTATAG_UDP_MTU(65536), + TAG_IF(tportlog, TPTAG_LOG(1)), + TAG_END()); /* Last tag should always finish the sequence */ if (!profile->nua) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Creating SIP UA for profile: %s\n", profile->name); @@ -451,11 +456,18 @@ void *SWITCH_THREAD_FUNC sofia_profile_thread_run(switch_thread_t *thread, void gateway_loops = GATEWAY_SECONDS; if (switch_event_create(&s_event, SWITCH_EVENT_PUBLISH) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "service", "_sip._udp,_sip._tcp,_sip._sctp"); + switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "service", "_sip._udp,_sip._tcp,_sip._sctp%s", + (sofia_test_pflag(profile, PFLAG_TLS)) ? ",_sips._tcp" : "")); + switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "port", "%d", profile->sip_port); switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "module_name", "%s", "mod_sofia"); switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "profile_name", "%s", profile->name); switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "profile_uri", "%s", profile->url); + + if (sofia_test_pflag(profile, PFLAG_TLS)) { + switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "tls_port", "%d", profile->tls_sip_port); + switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "profile_tls_uri", "%s", profile->tls_url); + } switch_event_fire(&s_event); } @@ -498,11 +510,18 @@ void *SWITCH_THREAD_FUNC sofia_profile_thread_run(switch_thread_t *thread, void switch_mutex_unlock(profile->ireg_mutex); if (switch_event_create(&s_event, SWITCH_EVENT_UNPUBLISH) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "service", "_sip._udp,_sip._tcp,_sip._sctp"); + switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "service", "_sip._udp,_sip._tcp,_sip._sctp%s", + (sofia_test_pflag(profile, PFLAG_TLS)) ? ",_sips._tcp" : ""); + switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "port", "%d", profile->sip_port); switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "module_name", "%s", "mod_sofia"); switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "profile_name", "%s", profile->name); switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "profile_uri", "%s", profile->url); + + if (sofia_test_pflag(profile, PFLAG_TLS)) { + switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "tls_port", "%d", profile->tls_sip_port); + switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "profile_tls_uri", "%s", profile->tls_url); + } switch_event_fire(&s_event); } @@ -1013,7 +1032,21 @@ switch_status_t config_sofia(int reload, char *profile_name) } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Duration out of bounds!\n"); } - } + + /* + * handle TLS params #1 + */ + } else if (!strcasecmp(var, "tls")) { + if (switch_true(val)) { + sofia_set_pflag(profile, PFLAG_TLS); + } + } else if (!strcasecmp(var, "tls-bind-params")) { + profile->tls_bind_params = switch_core_strdup(profile->pool, val); + } else if (!strcasecmp(var, "tls-sip-port")) { + profile->tls_sip_port = atoi(val); + } else if (!strcasecmp(var, "tls-cert-dir")) { + profile->tls_cert_dir = switch_core_strdup(profile->pool, val); + } } if (!profile->cng_pt) { @@ -1070,13 +1103,38 @@ switch_status_t config_sofia(int reload, char *profile_name) profile->bindurl = switch_core_sprintf(profile->pool, "%s;%s", bindurl, profile->bind_params); } + /* + * handle TLS params #2 + */ + if (sofia_test_pflag(profile, PFLAG_TLS)) { + if (!profile->tls_sip_port) { + profile->tls_sip_port = atoi(SOFIA_DEFAULT_TLS_PORT); + } + + if (profile->extsipip) { + profile->tls_url = switch_core_sprintf(profile->pool, "sip:mod_sofia@%s:%d", profile->extsipip, profile->tls_sip_port); + profile->tls_bindurl = switch_core_sprintf(profile->pool, "sips:mod_sofia@%s:%d;maddr=%s", profile->extsipip, profile->tls_sip_port, profile->sipip); + } else { + profile->tls_url = switch_core_sprintf(profile->pool, "sip:mod_sofia@%s:%d", profile->sipip, profile->tls_sip_port); + profile->tls_bindurl = switch_core_sprintf(profile->pool, "sips:mod_sofia@%s:%d", profile->sipip, profile->tls_sip_port); + } + + if (profile->tls_bind_params) { + char *url = profile->tls_bindurl; + profile->tls_bindurl = switch_core_sprintf(profile->pool, "%s;%s", url, profile->tls_bind_params); + } + + if (!profile->tls_cert_dir) { + profile->tls_cert_dir = switch_core_sprintf(profile->pool, "%s/ssl", SWITCH_GLOBAL_dirs.conf_dir); + } + } } if (profile) { switch_xml_t aliases_tag, alias_tag; if ((gateways_tag = switch_xml_child(xprofile, "registrations"))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, - "The syntax has been discontinued, please see the new syntax in the default configuration examples\n"); + "The syntax has been discontinued, please see the new syntax in the default configuration examples\n"); } else if ((gateways_tag = switch_xml_child(xprofile, "gateways"))) { parse_gateways(profile, gateways_tag); } @@ -2083,12 +2141,25 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_ } if (sip->sip_to && sip->sip_to->a_url) { - const char *val; - char *transport = (my_addrinfo->ai_socktype == SOCK_STREAM) ? "tcp" : "udp"; - + const char *host, *user; + int port; + sofia_transport_t transport = sofia_glue_url2transport(sip->sip_contact->m_url); + url_set_chanvars(session, sip->sip_to->a_url, sip_to); - if ((val = switch_channel_get_variable(channel, "sip_to_uri"))) { - tech_pvt->to_uri = switch_core_session_sprintf(session, "sip:%s;transport=%s", val, transport); + if (switch_channel_get_variable(channel, "sip_to_uri")) { + + host = switch_channel_get_variable(channel, "sip_to_host"); + user = switch_channel_get_variable(channel, "sip_to_user"); + + if (sip->sip_contact->m_url->url_port) { + port = atoi(sip->sip_contact->m_url->url_port); + } else { + port = sofia_glue_transport_has_tls(transport) ? profile->tls_sip_port : profile->sip_port; + } + + tech_pvt->to_uri = switch_core_session_sprintf(session, "sip:%s@%s:%d;transport=%s", + user, host, port, sofia_glue_transport2str(transport)); + if (profile->ndlb & PFLAG_NDLB_TO_IN_200_CONTACT) { if (strchr(tech_pvt->to_uri, '>')) { tech_pvt->reply_contact = tech_pvt->to_uri; @@ -2096,17 +2167,21 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_ tech_pvt->reply_contact = switch_core_session_sprintf(session, "<%s>", tech_pvt->to_uri); } } else { - if (strchr(profile->url, '>')) { - tech_pvt->reply_contact = switch_core_session_sprintf(session, "%s;transport=%s", profile->url, transport); + const char *url = (sofia_glue_transport_has_tls(transport)) ? profile->tls_url : profile->url; + + if (strchr(url, '>')) { + tech_pvt->reply_contact = switch_core_session_sprintf(session, "%s;transport=%s", url, sofia_glue_transport2str(transport)); } else { - tech_pvt->reply_contact = switch_core_session_sprintf(session, "<%s;transport=%s>", profile->url, transport); + tech_pvt->reply_contact = switch_core_session_sprintf(session, "<%s;transport=%s>", url, sofia_glue_transport2str(transport)); } } } else { - if (strchr(profile->url, '>')) { - tech_pvt->reply_contact = switch_core_session_sprintf(session, "%s;transport=%s", profile->url, transport); + const char *url = (sofia_glue_transport_has_tls(transport)) ? profile->tls_url : profile->url; + + if (strchr(url, '>')) { + tech_pvt->reply_contact = switch_core_session_sprintf(session, "%s;transport=%s", url, sofia_glue_transport2str(transport)); } else { - tech_pvt->reply_contact = switch_core_session_sprintf(session, "<%s;transport=%s>", profile->url, transport); + tech_pvt->reply_contact = switch_core_session_sprintf(session, "<%s;transport=%s>", url, sofia_glue_transport2str(transport)); } } } diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index 0449527b3b..69c81335d8 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -453,20 +453,139 @@ switch_status_t sofia_glue_tech_choose_video_port(private_object_t *tech_pvt) return SWITCH_STATUS_SUCCESS; } -char *sofia_overcome_sip_uri_weakness(switch_core_session_t *session, const char *uri, const char *transport, switch_bool_t uri_only) +static sofia_transport_t sofia_glue_str2transport(const char *str) +{ + if (!strcasecmp(str, "udp")) { + return SOFIA_TRANSPORT_UDP; + } + else if (!strcasecmp(str, "tcp")) { + return SOFIA_TRANSPORT_TCP; + } + else if (!strcasecmp(str, "sctp")) { + return SOFIA_TRANSPORT_SCTP; + } + else if (!strcasecmp(str, "tls")) { + return SOFIA_TRANSPORT_TCP_TLS; + } + + return SOFIA_TRANSPORT_UNKNOWN; +} + +sofia_transport_t sofia_glue_url2transport(const url_t *url) +{ + char *ptr = NULL; + int tls = 0; + + if(!url) + return SOFIA_TRANSPORT_UNKNOWN; + + if (url->url_scheme && !strcasecmp(url->url_scheme, "sips")) { + tls++; + } + + ptr = (char *)url->url_params; + while(ptr) { + + if (!strncasecmp(ptr, "transport=", 10)) { + ptr += 10; + + if (!strncasecmp(ptr, "udp", 3)) { + return SOFIA_TRANSPORT_UDP; + } + else if (!strncasecmp(ptr, "tcp", 3)) { + return SOFIA_TRANSPORT_TCP; + } + else if (!strncasecmp(ptr, "tls", 3)) { + return SOFIA_TRANSPORT_TCP_TLS; + } + else if (!strncasecmp(ptr, "sctp", 4)) { + return SOFIA_TRANSPORT_SCTP; + } + break; + } + + if ((ptr = strchr(ptr, ';'))) + ptr++; + } + + return (tls) ? SOFIA_TRANSPORT_TCP_TLS : SOFIA_TRANSPORT_UDP; +} + +sofia_transport_t sofia_glue_via2transport(const sip_via_t *via) +{ + char *ptr = NULL; + int tls = 0; + + if (!via || !via->v_protocol) + return SOFIA_TRANSPORT_UNKNOWN; + + if (!strncasecmp(via->v_protocol, "sips", 4)) { + tls++; + } + + if ((ptr = strrchr(via->v_protocol, '/'))) { + ptr++; + + if (!strncasecmp(ptr, "udp", 3)) { + return SOFIA_TRANSPORT_UDP; + } + else if(!strncasecmp(ptr, "tcp", 3)) { + return SOFIA_TRANSPORT_TCP; + } + else if(!strncasecmp(ptr, "tls", 3)) { + return SOFIA_TRANSPORT_TCP_TLS; + } + else if(!strncasecmp(ptr, "sctp", 4)) { + return SOFIA_TRANSPORT_SCTP; + } + } + + return SOFIA_TRANSPORT_UNKNOWN; +} + +const char *sofia_glue_transport2str(const sofia_transport_t tp) +{ + switch(tp) { + case SOFIA_TRANSPORT_TCP: + return "tcp"; + + case SOFIA_TRANSPORT_TCP_TLS: + return "tls"; + + case SOFIA_TRANSPORT_SCTP: + return "sctp"; + + default: + return "udp"; + } +} + +int sofia_glue_transport_has_tls(const sofia_transport_t tp) +{ + switch(tp) { + case SOFIA_TRANSPORT_TCP_TLS: + return 1; + + default: + return 0; + } +} + +char *sofia_overcome_sip_uri_weakness(switch_core_session_t *session, const char *uri, const sofia_transport_t transport, switch_bool_t uri_only) { char *stripped = switch_core_session_strdup(session, uri); char *new_uri = NULL; stripped = sofia_glue_get_url_from_contact(stripped, 0); - if (transport && strcasecmp(transport, "udp")) { + if (transport && transport != SOFIA_TRANSPORT_UDP) { + if (switch_stristr("port=", stripped)) { new_uri = switch_core_session_sprintf(session, "%s%s%s", uri_only ? "" : "<", stripped, uri_only ? "" : ">"); } else { if (strchr(stripped, ';')) { - new_uri = switch_core_session_sprintf(session, "%s%s&transport=%s%s", uri_only ? "" : "<", stripped, transport, uri_only ? "" : ">"); + new_uri = switch_core_session_sprintf(session, "%s%s&transport=%s%s", uri_only ? "" : "<", stripped, sofia_glue_transport2str(transport), uri_only ? "" : ">"); } else { - new_uri = switch_core_session_sprintf(session, "%s%s;transport=%s%s", uri_only ? "" : "<", stripped, transport, uri_only ? "" : ">"); + new_uri = switch_core_session_sprintf(session, "%s%s;transport=%s%s", uri_only ? "" : "<", stripped, sofia_glue_transport2str(transport), uri_only ? "" : ">"); } } } else { @@ -543,8 +662,9 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session) if (!tech_pvt->nh) { char *d_url = NULL, *url = NULL; sofia_private_t *sofia_private; + sofia_transport_t transport = SOFIA_TRANSPORT_UDP; char *invite_contact = NULL, *to_str, *use_from_str, *from_str, *url_str; - const char *transport = "udp", *t_var; + const char *t_var; char *rpid_domain = "cluecon.com", *p; const char *priv = "off"; const char *screen = "no"; @@ -553,7 +673,7 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "URL Error! [%s]\n", tech_pvt->dest); return SWITCH_STATUS_FALSE; } - + if ((d_url = sofia_glue_get_url_from_contact(tech_pvt->dest, 1))) { url = d_url; } else { @@ -562,16 +682,12 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session) url_str = url; - if (switch_strlen_zero(tech_pvt->invite_contact)) { - tech_pvt->invite_contact = tech_pvt->profile->url; - } - if (!switch_strlen_zero(tech_pvt->gateway_from_str)) { use_from_str = tech_pvt->gateway_from_str; } else { use_from_str = tech_pvt->from_str; } - + rpid_domain = switch_core_session_strdup(session, use_from_str); sofia_glue_get_url_from_contact(rpid_domain, 0); if ((rpid_domain = strchr(rpid_domain, '@'))) { @@ -586,21 +702,30 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session) } if (switch_stristr("port=tcp", url)) { - transport = "tcp"; + transport = SOFIA_TRANSPORT_TCP; } else { if ((t_var = switch_channel_get_variable(channel, "sip_transport"))) { - if (!strcasecmp(t_var, "tcp") || !strcasecmp(t_var, "udp")) { - transport = t_var; + sofia_transport_t t_val; + + if ((t_val = sofia_glue_str2transport(t_var)) != SOFIA_TRANSPORT_UNKNOWN) { + transport = t_val; } } } + if (switch_strlen_zero(tech_pvt->invite_contact)) { + if (sofia_glue_transport_has_tls(transport)) + tech_pvt->invite_contact = tech_pvt->profile->tls_url; + else + tech_pvt->invite_contact = tech_pvt->profile->url; + } + url_str = sofia_overcome_sip_uri_weakness(session, url, transport, SWITCH_TRUE); invite_contact = sofia_overcome_sip_uri_weakness(session, tech_pvt->invite_contact, transport, SWITCH_FALSE); - from_str = sofia_overcome_sip_uri_weakness(session, use_from_str, NULL, SWITCH_FALSE); - to_str = sofia_overcome_sip_uri_weakness(session, tech_pvt->dest_to, NULL, SWITCH_FALSE); - - /* + from_str = sofia_overcome_sip_uri_weakness(session, use_from_str, 0, SWITCH_FALSE); + to_str = sofia_overcome_sip_uri_weakness(session, tech_pvt->dest_to, 0, SWITCH_FALSE); + + /* Does the "genius" who wanted SIP to be "text-based" so it was "easier to read" even use it now, or did he just suggest it to make our lives miserable? */