diff --git a/core/AmRtpStream.cpp b/core/AmRtpStream.cpp index a68f1ce5..70596344 100644 --- a/core/AmRtpStream.cpp +++ b/core/AmRtpStream.cpp @@ -335,6 +335,11 @@ int AmRtpStream::getRPort() return r_port; } +string AmRtpStream::getRHost() +{ + return r_host; +} + void AmRtpStream::setRAddr(const string& addr, unsigned short port) { DBG("RTP remote address set to %s:%u\n",addr.c_str(),port); diff --git a/core/AmRtpStream.h b/core/AmRtpStream.h index 34a3b712..9e7aaf9f 100644 --- a/core/AmRtpStream.h +++ b/core/AmRtpStream.h @@ -179,7 +179,16 @@ public: * @return remote RTP port. */ int getRPort(); + + /** + * Gets remote host IP. + * @return remote host IP. + */ + string getRHost(); + /** + * Set remote IP & port. + */ void setRAddr(const string& addr, unsigned short port); /** Symmetric RTP: passive mode ? */ diff --git a/core/AmSession.cpp b/core/AmSession.cpp index 057c7c7f..6c8ab749 100644 --- a/core/AmSession.cpp +++ b/core/AmSession.cpp @@ -198,12 +198,14 @@ int AmSession::getRPort() return rtp_str.getRPort(); } -void AmSession::negotiate(const AmSipRequest& request) +void AmSession::negotiate(const string& sdp_body, + bool force_symmetric_rtp, + string& sdp_reply) { string r_host = ""; int r_port = 0; - sdp.setBody(request.body.c_str()); + sdp.setBody(sdp_body.c_str()); if(sdp.parse()) throw AmSession::Exception(400,"session description parsing failed"); @@ -240,46 +242,22 @@ void AmSession::negotiate(const AmSipRequest& request) DBG("remote party doesn't support telephone events\n"); } - string str_msg_flags = getHeader(request.hdrs,"P-MsgFlags"); - unsigned int msg_flags = 0; - if(reverse_hex2int(str_msg_flags,msg_flags)){ - ERROR("while parsing 'P-MsgFlags' header\n"); - msg_flags = 0; - } - DBG("msg_flags=%u\n",msg_flags); - bool passive_mode = false; - if( sdp.remote_active - || (msg_flags & FL_FORCE_ACTIVE) ) { + if( sdp.remote_active || force_symmetric_rtp) { DBG("The other UA is NATed: switched to passive mode.\n"); - DBG("remote_active = %i; msg_flags = %i\n", - sdp.remote_active,msg_flags); + DBG("remote_active = %i; force_symmetric_rtp = %i\n", + sdp.remote_active,force_symmetric_rtp); + passive_mode = true; } - - //TODO: if dialog started - if(first_negotiation) - onBeforeCallAccept(request); - - lockAudio(); - rtp_str.setLocalIP(AmConfig::LocalIP); - unlockAudio(); - - string sdp_body; - sdp.genResponse(AmConfig::LocalIP,rtp_str.getLocalPort(),sdp_body); - if( dlg.reply(request,200,"OK", - "application/sdp",sdp_body//, getReplyHeaders(request) - ) != 0 ) - throw AmSession::Exception(500,"could not send response."); + sdp.genResponse(AmConfig::LocalIP,rtp_str.getLocalPort(),sdp_reply); lockAudio(); + rtp_str.setLocalIP(AmConfig::LocalIP); rtp_str.setPassiveMode(passive_mode); rtp_str.setRAddr(r_host, r_port); unlockAudio(); - - DBG("Sending Rtp data to %s/%i\n",r_host.c_str(),r_port); - first_negotiation = false; } void AmSession::run() @@ -476,7 +454,18 @@ void AmSession::onSipRequest(const AmSipRequest& req) DBG("onSipRequest: method = %s\n",req.method.c_str()); if(req.method == "INVITE"){ - acceptAudio(req); + onInvite(req); + + if(detached.get()){ + + onSessionStart(req); + + if(input || output) + AmSessionScheduler::instance()->addSession(this, callgroup); + else { + ERROR("missing audio input and/or ouput.\n"); + } + } } else if( req.method == "BYE" ){ @@ -486,7 +475,10 @@ void AmSession::onSipRequest(const AmSipRequest& req) else if( req.method == "CANCEL" ){ dlg.reply(req,200,"OK"); + onCancel(); + } else if( req.method == "INFO" ){ + if ((strip_header_params(getHeader(req.hdrs, "Content-Type")) =="application/dtmf-relay")|| (strip_header_params(getHeader(req.hdrs, "c")) @@ -504,35 +496,50 @@ void AmSession::onSipReply(const AmSipReply& reply) dlg.updateStatus(reply); } +void AmSession::onInvite(const AmSipRequest& req) +{ + string sdp_reply; + if(acceptAudio(req,sdp_reply)!=0) + return; + + if(dlg.reply(req,200,"OK", + "application/sdp",sdp_reply) != 0){ + + //throw AmSession::Exception(500,"error while sending response"); + setStopped(); + } +} + void AmSession::onBye(const AmSipRequest& req) { setStopped(); } -int AmSession::acceptAudio(const AmSipRequest& req) +int AmSession::acceptAudio(const AmSipRequest& req, + string& sdp_reply) { try { try { // handle codec and send reply - negotiate(req); + string str_msg_flags = getHeader(req.hdrs,"P-MsgFlags"); + unsigned int msg_flags = 0; + if(reverse_hex2int(str_msg_flags,msg_flags)){ + ERROR("while parsing 'P-MsgFlags' header\n"); + msg_flags = 0; + } + + negotiate( req.body, + msg_flags & FL_FORCE_ACTIVE, + sdp_reply); // enable RTP stream lockAudio(); rtp_str.init(&payload); unlockAudio(); - if(detached.get()){ - - onSessionStart(req); - - if(input || output) - AmSessionScheduler::instance()->addSession(this, callgroup); - else { - ERROR("missing audio input and/or ouput.\n"); - return -1; - } - } - + DBG("Sending Rtp data to %s/%i\n", + rtp_str.getRHost().c_str(),rtp_str.getRPort()); + return 0; } catch(const AmSession::Exception& e){ throw e; } @@ -586,4 +593,3 @@ void AmSession::sendReinvite() dlg.reinvite("", "application/sdp", sdp_body); } - diff --git a/core/AmSession.h b/core/AmSession.h index 9d35769f..e1feed42 100644 --- a/core/AmSession.h +++ b/core/AmSession.h @@ -182,7 +182,8 @@ public: * Accept the INVITE proposal * thus setting up audio stream */ - int acceptAudio(const AmSipRequest& req); + int acceptAudio(const AmSipRequest& req, + string& sdp_reply); /** * Lock and unlock audio input & output @@ -233,7 +234,9 @@ public: int getRPort(); /** handle SDP negotiation: only for INVITEs & re-INVITEs */ - virtual void negotiate(const AmSipRequest& request); + virtual void negotiate(const string& sdp_body, + bool force_symmetric_rtp, + string& sdp_reply); void sendUpdate(); void sendReinvite(); @@ -282,13 +285,24 @@ public: virtual void onStart(){} /** - * onBeforeCallAccept will be called on incoming - * request before the call gets definitely established. - * - * Throw AmSession::Exception if you want to - * signal any error. + * onInvite will be called if an INVITE or re-INVITE + * has been received for the session. + */ + virtual void onInvite(const AmSipRequest& req); + + /** + * onCancel will be called if a CANCEL for a running + * dialog has been received. At this point, the CANCEL + * transaction has been replied with 200. + * + * A normal plug-in does not have to do anything special, + * as normal dialogs are immediatly replied with 200 + * or error code. + * + * Note: You are still responsible for responding the + * initial transaction. */ - virtual void onBeforeCallAccept(const AmSipRequest& req){} + virtual void onCancel(){} /** * onSessionStart will be called after call setup. diff --git a/core/AmSessionContainer.cpp b/core/AmSessionContainer.cpp index 18569f03..8735a805 100644 --- a/core/AmSessionContainer.cpp +++ b/core/AmSessionContainer.cpp @@ -142,7 +142,7 @@ AmSession* AmSessionContainer::getSession(const string& callid, const string& re return NULL; } - return getSession(it->first); + return getSession(it->second); } AmSession* AmSessionContainer::getSession(const string& local_tag) @@ -209,8 +209,8 @@ bool AmSessionContainer::postEvent(const string& callid, const string& remote_tag, AmEvent* event) { - DBG("postEvent: callid = %s; remote_tag = %s\n", - callid.c_str(),remote_tag.c_str()); +// DBG("postEvent: callid = %s; remote_tag = %s\n", +// callid.c_str(),remote_tag.c_str()); as_mut.lock(); AmSession* s = getSession(callid,remote_tag); @@ -228,7 +228,7 @@ bool AmSessionContainer::postEvent(const string& callid, bool AmSessionContainer::postEvent(const string& local_tag, AmEvent* event) { - DBG("postEvent: local_tag = %s\n",local_tag.c_str()); +// DBG("postEvent: local_tag = %s\n",local_tag.c_str()); as_mut.lock(); AmSession* s = getSession(local_tag); @@ -239,7 +239,7 @@ bool AmSessionContainer::postEvent(const string& local_tag, return false; } - DBG("posting...\n"); +// DBG("posting...\n"); s->postEvent(event); return true; }