diff options
Diffstat (limited to 'src/sip/sip.c')
-rw-r--r-- | src/sip/sip.c | 64 |
1 files changed, 54 insertions, 10 deletions
diff --git a/src/sip/sip.c b/src/sip/sip.c index ff6ea31..0988213 100644 --- a/src/sip/sip.c +++ b/src/sip/sip.c @@ -30,6 +30,7 @@ #include <sofia-sip/sip_header.h> #include <sofia-sip/stun_tag.h> #include <sofia-sip/su_md5.h> +#include <sofia-sip/msg_addr.h> #include "sip.h" #ifndef SOFIA_SIP_GCC_4_8_PATCH_APLLIED @@ -167,6 +168,23 @@ static const char *sdp_replace_contact(const char *input, const char *address) return sdp; } +void rtp_peer_nat(sip_endpoint_t *sip_ep, char **sdp_p) +{ + if (sip_ep->remote_nat_rtp && sip_ep->remote_peer[0]) { + /* replace peer by remote contact, note that port in peer is ignored */ + char peer[256], *p; + strcpy(peer, sip_ep->remote_contact_peer); + p = strchr(peer, ':'); + if (*p) + *p = '\0'; + const char *s = sdp_replace_contact(*sdp_p, peer); + free(*sdp_p); + *sdp_p = malloc(strlen(s) + 1); + memcpy(*sdp_p, s, strlen(s)); + (*sdp_p)[strlen(s)] = '\0'; + } +} + /* authenticate (remote) */ static int authenticate(sip_endpoint_t *sip_ep, nua_handle_t *nh, sip_t const *sip) { @@ -510,8 +528,10 @@ static void setup_req(call_t *call, osmo_cc_msg_t *msg) // contact is set above /* append port of local peer */ p = osmo_cc_port_of_address(call->sip_ep->local_peer); - if (p) + if (p) { + strcat(contact, ":"); strcat(contact, p); + } PDEBUG(DSIP, DEBUG_DEBUG, " -> Contact = %s\n", contact); } @@ -879,13 +899,28 @@ static void ep_i_register(sip_endpoint_t *sip_ep, int status, nua_t *nua, nua_ha if (sip->sip_contact->m_url->url_user) strcpy(contact_user, sip->sip_contact->m_url->url_user); - if (sip->sip_contact->m_url->url_host) { - // FIXME: unstable/might not work with IPv6 - strcpy(contact_peer, sip->sip_contact->m_url->url_host); - if (sip->sip_contact->m_url->url_port && sip->sip_contact->m_url->url_port[0]) { - strcat(contact_peer, ":"); - strcat(contact_peer, sip->sip_contact->m_url->url_port); + if (sip_ep->remote_nat_sip) { + su_addrinfo_t *addrinfo = msg_addrinfo(data->e_msg); + getnameinfo(addrinfo->ai_addr, (socklen_t)addrinfo->ai_addrlen, contact_peer, sizeof(contact_peer), NULL, 0, NI_NUMERICHOST); + switch (addrinfo->ai_addr->sa_family) { + case AF_INET: + sprintf(strchr(contact_peer, '\0'), ":%d", ntohs(((struct sockaddr_in *) addrinfo->ai_addr)->sin_port)); + break; + case AF_INET6: + sprintf(strchr(contact_peer, '\0'), ":%d", ntohs(((struct sockaddr_in6 *) addrinfo->ai_addr)->sin6_port)); + break; } + PDEBUG(DSIP, DEBUG_DEBUG, " -> contact %s@%s (given by UDP source)\n", contact_user, contact_peer); + } else { + if (sip->sip_contact->m_url->url_host) { + // FIXME: unstable/might not work with IPv6 + strcpy(contact_peer, sip->sip_contact->m_url->url_host); + if (sip->sip_contact->m_url->url_port && sip->sip_contact->m_url->url_port[0]) { + strcat(contact_peer, ":"); + strcat(contact_peer, sip->sip_contact->m_url->url_port); + } + } + PDEBUG(DSIP, DEBUG_DEBUG, " -> contact %s@%s (given by remote)\n", contact_user, contact_peer); } if (!sip_ep->local_register) { @@ -899,8 +934,6 @@ static void ep_i_register(sip_endpoint_t *sip_ep, int status, nua_t *nua, nua_ha return; } - PDEBUG(DSIP, DEBUG_DEBUG, " -> contact %s@%s\n", contact_user, contact_peer); - if (sip_ep->authenticate_local && sip_ep->auth_realm[0]) { authorization = sip->sip_authorization; status = check_authorization(authorization, "REGISTER", sip_ep->auth_user, sip_ep->auth_password, sip_ep->auth_realm, sip_ep->register_nonce, &auth_text); @@ -1079,6 +1112,7 @@ static void call_i_invite(call_t *call, nua_handle_t *nh, sip_t const *sip) call->sdp_request = malloc(sip->sip_payload->pl_len + 1); memcpy(call->sdp_request, sip->sip_payload->pl_data, sip->sip_payload->pl_len); call->sdp_request[sip->sip_payload->pl_len] = '\0'; + rtp_peer_nat(call->sip_ep, &call->sdp_request); } else { PDEBUG(DSIP, DEBUG_DEBUG, " -> No SDP in message\n"); new_state(call, SIP_STATE_IN_INVITE); @@ -1183,6 +1217,7 @@ static void call_r_invite(call_t *call, int status, char const *phrase, nua_hand call->sdp_response = malloc(sip->sip_payload->pl_len + 1); memcpy(call->sdp_response, sip->sip_payload->pl_data, sip->sip_payload->pl_len); call->sdp_response[sip->sip_payload->pl_len] = '\0'; + rtp_peer_nat(call->sip_ep, &call->sdp_response); osmo_cc_debug_sdp(call->sdp_response); } else if (!call->sdp_response && status >= 200 && status <= 299) { PDEBUG(DSIP, DEBUG_DEBUG, " -> No SDP in message\n"); @@ -1580,6 +1615,12 @@ static void sip_message(nua_event_t event, int status, char const *phrase, nua_t case nua_i_terminated: PDEBUG(DSIP, DEBUG_DEBUG, "terminated received\n"); break; + case nua_i_prack: + PDEBUG(DSIP, DEBUG_DEBUG, "prack indication received\n"); + break; + case nua_r_prack: + PDEBUG(DSIP, DEBUG_DEBUG, "prack response received\n"); + break; default: PDEBUG(DSIP, DEBUG_DEBUG, "Event %d not handled\n", event); } @@ -1671,7 +1712,7 @@ static void register_option_timeout(struct timer *timer) TAG_END()); } -sip_endpoint_t *sip_endpoint_create(const char *user_agent, int send_no_ringing_after_progress, int receive_no_ringing_after_progress, const char *name, const char *local_user, const char *local_peer, const char *remote_user, const char *remote_peer, const char *asserted_id, int local_register, int remote_register, const char *register_user, const char *register_peer, int authenticate_local, int authenticate_remote, const char *auth_user, const char *auth_password, const char *auth_realm, const char *public_ip, const char *stun_server, int register_interval, int options_interval, int stun_interval, int expires) +sip_endpoint_t *sip_endpoint_create(const char *user_agent, int send_no_ringing_after_progress, int receive_no_ringing_after_progress, const char *name, const char *local_user, const char *local_peer, const char *remote_user, const char *remote_peer, const char *asserted_id, int local_register, int remote_register, int remote_nat_sip, int remote_nat_rtp, const char *register_user, const char *register_peer, int authenticate_local, int authenticate_remote, const char *auth_user, const char *auth_password, const char *auth_realm, const char *public_ip, const char *stun_server, int register_interval, int options_interval, int stun_interval, int expires) { sip_endpoint_t *sip_ep; char local[256]; @@ -1696,6 +1737,8 @@ sip_endpoint_t *sip_endpoint_create(const char *user_agent, int send_no_ringing_ sip_ep->local_register = local_register; sip_ep->remote_register = remote_register; + sip_ep->remote_nat_sip = remote_nat_sip; + sip_ep->remote_nat_rtp = remote_nat_rtp; sip_ep->register_user = register_user; sip_ep->register_peer = register_peer; @@ -1753,6 +1796,7 @@ sip_endpoint_t *sip_endpoint_create(const char *user_agent, int send_no_ringing_ NUTAG_AUTOANSWER(0), TAG_IF(expires, NUTAG_SESSION_TIMER(expires)), // wozu das? NUTAG_ALLOW("INFO"), + NUTAG_ALLOW("PRACK"), TAG_NULL()); if (sip_ep->remote_register) |