diff --git a/core/AmConfig.cpp b/core/AmConfig.cpp index 5d7a3bfe..a308e4d1 100644 --- a/core/AmConfig.cpp +++ b/core/AmConfig.cpp @@ -47,6 +47,7 @@ string AmConfig::ExcludePlugins = ""; string AmConfig::ExcludePayloads = ""; int AmConfig::DaemonMode = DEFAULT_DAEMON_MODE; string AmConfig::LocalIP = ""; +string AmConfig::PublicIP = ""; string AmConfig::PrefixSep = PREFIX_SEPARATOR; int AmConfig::RtpLowPort = RTP_LOWPORT; int AmConfig::RtpHighPort = RTP_HIGHPORT; @@ -146,6 +147,8 @@ int AmConfig::setDeadRtpTime(const string& drt) int AmConfig::readConfiguration() { + DBG("Reading configuration..."); + AmConfigReader cfg; if(cfg.loadFile(ConfigurationFile.c_str())){ @@ -180,6 +183,15 @@ int AmConfig::readConfiguration() if(cfg.hasParameter("sip_ip")) LocalSIPIP = cfg.getParameter("sip_ip"); + if(cfg.hasParameter("public_ip")){ + string p_ip = cfg.getParameter("public_ip"); + DBG("Setting public_ip parameter to %s.\n", p_ip.c_str()); + PublicIP = p_ip; + } + else { + DBG("Config file has no public_ip parameter."); + } + // outbound_proxy OutboundProxy = cfg.getParameter("outbound_proxy"); diff --git a/core/AmConfig.h b/core/AmConfig.h index 5a919ecd..2dd51718 100644 --- a/core/AmConfig.h +++ b/core/AmConfig.h @@ -62,8 +62,14 @@ struct AmConfig //static unsigned int MaxRecordTime; /** run the programm in daemon mode? */ static int DaemonMode; + /** local IP for SDP media advertising */ static string LocalIP; + + /** public IP for SDP media advertising; we actually + * bind to local IP, but advertise public IP. */ + static string PublicIP; + /** Separator character for uri application prefix (ex: voicemail+jiri@iptel.org) */ static string PrefixSep; /** Lowest local RTP port */ diff --git a/core/AmSession.cpp b/core/AmSession.cpp index ce15fb88..494ea5ff 100644 --- a/core/AmSession.cpp +++ b/core/AmSession.cpp @@ -322,7 +322,7 @@ void AmSession::negotiate(const string& sdp_body, if( sdp.remote_active || force_symmetric_rtp) { DBG("The other UA is NATed: switched to passive mode.\n"); DBG("remote_active = %i; force_symmetric_rtp = %i\n", - sdp.remote_active,force_symmetric_rtp); + sdp.remote_active, force_symmetric_rtp); passive_mode = true; } @@ -339,7 +339,7 @@ void AmSession::negotiate(const string& sdp_body, unlockAudio(); if(sdp_reply) - sdp.genResponse(AmConfig::LocalIP,rtp_str.getLocalPort(),*sdp_reply, AmConfig::SingleCodecInOK); + sdp.genResponse(advertisedIP(), rtp_str.getLocalPort(), *sdp_reply, AmConfig::SingleCodecInOK); } void AmSession::run() @@ -784,7 +784,7 @@ void AmSession::sendReinvite(bool updateSDP, const string& headers) if (updateSDP) { rtp_str.setLocalIP(AmConfig::LocalIP); string sdp_body; - sdp.genResponse(AmConfig::LocalIP,rtp_str.getLocalPort(),sdp_body); + sdp.genResponse(advertisedIP(), rtp_str.getLocalPort(), sdp_body); dlg.reinvite(headers, "application/sdp", sdp_body); } else { dlg.reinvite(headers, "", ""); @@ -793,12 +793,13 @@ void AmSession::sendReinvite(bool updateSDP, const string& headers) int AmSession::sendInvite(const string& headers) { - // set local IP first, so that IP is set when - // getLocalPort/setLocalPort may bind + // Set local IP first, so that IP is set when + // getLocalPort/setLocalPort may bind. rtp_str.setLocalIP(AmConfig::LocalIP); - // generate SDP + + // Generate SDP. string sdp_body; - sdp.genRequest(AmConfig::LocalIP,rtp_str.getLocalPort(),sdp_body); + sdp.genRequest(advertisedIP(), rtp_str.getLocalPort(), sdp_body); return dlg.invite(headers, "application/sdp", sdp_body); } @@ -811,3 +812,15 @@ void AmSession::setOnHold(bool hold) sendReinvite(); unlockAudio(); } + +// Utility for basic NAT handling: allow the config file to specify the IP +// address to use in SDP bodies and Contact header. +// TODO: Contact header! :) +string AmSession::advertisedIP() +{ + string set_ip = AmConfig::PublicIP; // "public_ip" parameter. (NEW) + DBG("AmConfig::PublicIP is %s.", set_ip.c_str()); + if (set_ip.empty()) + return AmConfig::LocalIP; // "listen" parameter. + return set_ip; +} diff --git a/core/AmSession.h b/core/AmSession.h index 64d01884..167096df 100644 --- a/core/AmSession.h +++ b/core/AmSession.h @@ -457,6 +457,9 @@ public: const string& body, string& hdrs, int flags); + + // The IP address to put as c= in SDP bodies and to use for Contact:. + string advertisedIP(); }; #endif diff --git a/core/etc/sems.conf.sample b/core/etc/sems.conf.sample index 2209a8e4..c0a19c4e 100644 --- a/core/etc/sems.conf.sample +++ b/core/etc/sems.conf.sample @@ -162,13 +162,27 @@ media_processor_threads=1 # registrations. # It defaults to the value of 'listen' (see above). # -# Example : +# Example: # sip_ip=10.0.0.34 # # default: # #sip_ip=10.0.0.34 +# optional parameter: public_ip= +# +# - when running SEMS behind certain simple NAT configurations, +# you can use this parameter to inform SEMS of its public IP +# address. If this parameter is set, SEMS will write this value +# into SDP bodies. +# If this parameter is not set, the local IP address is used. +# N.B., there is no support for port translation; the local +# RTP port is used in either case. +# +# Example: +# public_sip=75.101.219.48 +# + # optional parameter: sip_port= # # - this informs SEMS about the port where its SIP stack is diff --git a/core/sems.cpp b/core/sems.cpp index e5610a0c..e3d5b384 100644 --- a/core/sems.cpp +++ b/core/sems.cpp @@ -253,6 +253,7 @@ int main(int argc, char* argv[]) " plug-in path: %s\n" " daemon mode: %i\n" " local SIP IP: %s\n" + " public media IP: %s\n" " local SIP port: %i\n" " local media IP: %s\n" " application: %s\n" @@ -261,6 +262,7 @@ int main(int argc, char* argv[]) AmConfig::PlugInPath.c_str(), AmConfig::DaemonMode, AmConfig::LocalSIPIP.c_str(), + AmConfig::PublicIP.c_str(), AmConfig::LocalSIPPort, AmConfig::LocalIP.c_str(), AmConfig::Application.empty()?