summaryrefslogtreecommitdiffstats
path: root/src/sip/sip.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/sip/sip.c')
-rw-r--r--src/sip/sip.c64
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)