diff --git a/core/AmSession.cpp b/core/AmSession.cpp index 1362efd9..73182358 100644 --- a/core/AmSession.cpp +++ b/core/AmSession.cpp @@ -434,8 +434,6 @@ void AmSession::process(AmEvent* ev) setStopped(); return; } - - //AmDialogState::process(ev); } @@ -464,7 +462,7 @@ void AmSession::onSipRequest(const AmSipRequest& req) CALL_EVENT_H(onSipRequest,req); dlg.updateStatus(req); - + DBG("onSipRequest: method = %s\n",req.method.c_str()); if(req.method == "INVITE"){ @@ -507,6 +505,23 @@ void AmSession::onSipReply(const AmSipReply& reply) { CALL_EVENT_H(onSipReply,reply); + if (dlg.get_uac_trans_method(reply.cseq) == "INVITE") { + if ((reply.code == 200) || (reply.code == 183)) { + DBG("Got 200 or 183 reply to INVITE.\n"); + string sdp_reply; + if(acceptAudio(reply.body,reply.hdrs,&sdp_reply)!=0) { + DBG("acceptAudio failed.\n"); + return; + } + + if(detached.get() && !getStopped()){ + onSessionStart(reply); + + if(input || output) + AmSessionScheduler::instance()->addSession(this, callgroup); + } + } + } dlg.updateStatus(reply); } @@ -608,3 +623,9 @@ void AmSession::sendReinvite() dlg.reinvite("", "application/sdp", sdp_body); } +void AmSession::sendInvite() +{ + string sdp_body; + sdp.genRequest(AmConfig::LocalIP,rtp_str.getLocalPort(),sdp_body); + dlg.invite("", "application/sdp", sdp_body); +} diff --git a/core/AmSession.h b/core/AmSession.h index 098f6c2e..d0e19e92 100644 --- a/core/AmSession.h +++ b/core/AmSession.h @@ -242,6 +242,7 @@ public: void sendUpdate(); void sendReinvite(); + void sendInvite(); /** * Destroy the session. @@ -315,11 +316,22 @@ public: * signal any error. * * Warning: - * The session ends with this method. * Sems will NOT send any BYE on his own. */ virtual void onSessionStart(const AmSipRequest& req){} + /** + * onSessionStart method for calls originating + * from SEMS. + * + * Throw AmSession::Exception if you want to + * signal any error. + * + * Warning: + * Sems will NOT send any BYE on his own. + */ + virtual void onSessionStart(const AmSipReply& reply){} + /** * @see AmDialogState */ diff --git a/core/AmSessionContainer.cpp b/core/AmSessionContainer.cpp index f92b6a4d..aa1db8d0 100644 --- a/core/AmSessionContainer.cpp +++ b/core/AmSessionContainer.cpp @@ -158,6 +158,38 @@ AmSession* AmSessionContainer::getSession(const string& local_tag) return it->second; } +AmSession* AmSessionContainer::startSessionUAC(AmSipRequest& req) { + AmSession* session = NULL; + as_mut.lock(); + try { + if((session = createSession(req)) != 0){ + session->dlg.updateStatusFromLocalRequest(req); // sets local tag as well + session->setCallgroup(req.from_tag); + + session->sendInvite(); + session->start(); + + addSession_unsafe(req.callid,req.from_tag,req.from_tag,session); + // session does not get its own INVITE + // session->postEvent(new AmSipRequestEvent(req)); + } + } + catch(const AmSession::Exception& e){ + ERROR("%i %s\n",e.code,e.reason.c_str()); + AmSipDialog::reply_error(req,e.code,e.reason); + } + catch(const string& err){ + ERROR("startSession: %s\n",err.c_str()); + AmSipDialog::reply_error(req,500,err); + } + catch(...){ + ERROR("unexpected exception\n"); + AmSipDialog::reply_error(req,500,"unexpected exception"); + } + as_mut.unlock(); + return session; +} + void AmSessionContainer::startSessionUAS(AmSipRequest& req) { as_mut.lock(); diff --git a/core/AmSessionContainer.h b/core/AmSessionContainer.h index ce20ef56..da38990e 100644 --- a/core/AmSessionContainer.h +++ b/core/AmSessionContainer.h @@ -133,12 +133,16 @@ class AmSessionContainer : public AmThread /** * Constructs a new session and adds it to the active session container. - * @param hash_str Call-ID + remote-tag - * @param sess_key local-tag * @param req client's request */ void startSessionUAS(AmSipRequest& req); + /** + * Constructs a new session and adds it to the active session container. + * @param req client's request + */ + AmSession* startSessionUAC(AmSipRequest& req); + /** * Detroys a session. */ diff --git a/core/AmSipDialog.cpp b/core/AmSipDialog.cpp index 8fd9d6d7..596f4a2f 100644 --- a/core/AmSipDialog.cpp +++ b/core/AmSipDialog.cpp @@ -50,6 +50,31 @@ void AmSipDialog::updateStatus(const AmSipRequest& req) } } +/** + * + * update dialog status from UAC Request that we send (e.g. INVITE) + */ +void AmSipDialog::updateStatusFromLocalRequest(const AmSipRequest& req) +{ + remote_uri = req.r_uri; + if(callid.empty()){ + DBG("dialog callid is empty, updating from UACRequest\n"); + callid = req.callid; + local_tag = req.from_tag; + user = req.user; + domain = req.domain; + local_uri = req.from_uri; + remote_party = req.to; + local_party = req.from; + +// sip_ip = AmConfig::req.dstip; +// sip_port = req.port; + +// setRoute(req.route); + next_hop = req.next_hop; + } +} + int AmSipDialog::updateStatusReply(const AmSipRequest& req, unsigned int code) { TransMap::iterator t_it = uas_trans.find(req.cseq); @@ -362,6 +387,28 @@ int AmSipDialog::reinvite(const string& hdrs, } } +int AmSipDialog::invite(const string& hdrs, + const string& content_type, + const string& body) +{ + switch(status){ + case Disconnected: { + int res = sendRequest("INVITE", content_type, body, hdrs); + status = Pending; + return res; + }; break; + + case Disconnecting: + case Connected: + case Pending: + default: + DBG("invite(): we are already connected." + "(status=%i). do nothing!\n",status); + + return 0; + } +} + int AmSipDialog::update(const string& hdrs) { switch(status){ @@ -521,6 +568,16 @@ bool AmSipDialog::match_cancel(const AmSipRequest& cancel_req) return false; } +string AmSipDialog::get_uac_trans_method(unsigned int cseq) +{ + TransMap::iterator t = uac_trans.find(cseq); + + if (t != uac_trans.end()) + return t->second.method; + + return ""; +} + string AmSipDialog::getRoute() { string r_set(""); diff --git a/core/AmSipDialog.h b/core/AmSipDialog.h index e42d05c1..4529e26d 100644 --- a/core/AmSipDialog.h +++ b/core/AmSipDialog.h @@ -112,6 +112,8 @@ public: void updateStatus(const AmSipRequest& req); void updateStatus(const AmSipReply& reply); + /** update Status from locally originated request (e.g. INVITE) */ + void updateStatusFromLocalRequest(const AmSipRequest& req); int reply(const AmSipRequest& req, // Ser's transaction key unsigned int code, @@ -131,13 +133,20 @@ public: int reinvite(const string& hdrs, const string& content_type, const string& body); - + int invite(const string& hdrs, + const string& content_type, + const string& body); /** * @return true if a transaction could be found that * matches the CANCEL's one. */ bool match_cancel(const AmSipRequest& cancel_req); + /** + * @return the method of the corresponding uac request + */ + string get_uac_trans_method(unsigned int cseq); + static int reply_error(const AmSipRequest& req, unsigned int code, const string& reason,