From b24f51ef5b985d1c1ea39d040bb78db2f80a2fe6 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Thu, 22 Apr 2010 14:27:20 +0000 Subject: [PATCH] - simplified some code in the SIP stack - introduced outbound_proxy+force_outbound_proxy at the SIP dialog level (AmSipDialog) - outbound_proxy+force_outbound_proxy is configurable in the sems.conf git-svn-id: http://svn.berlios.de/svnroot/repos/sems/trunk@1818 8eb893ce-cfd4-0310-b710-fb5ebe64c474 --- apps/conference/Conference.cpp | 6 +- core/AmConfig.cpp | 6 ++ core/AmConfig.h | 2 + core/AmSipDialog.cpp | 123 +++++++++------------------------ core/AmSipDialog.h | 22 ++---- core/AmSipMsg.h | 1 - core/SipCtrlInterface.cpp | 67 ++---------------- core/SipCtrlInterface.h | 10 ++- core/sip/parse_header.cpp | 2 - core/sip/trans_layer.cpp | 24 +++++-- core/sip/trans_layer.h | 20 +++--- 11 files changed, 85 insertions(+), 198 deletions(-) diff --git a/apps/conference/Conference.cpp b/apps/conference/Conference.cpp index 1e778ebe..f95fe93e 100644 --- a/apps/conference/Conference.cpp +++ b/apps/conference/Conference.cpp @@ -839,14 +839,12 @@ void ConferenceDialog::onSipRequest(const AmSipRequest& req) // get route set and next hop string iptel_app_param = getHeader(req.hdrs, PARAM_HDR); if (iptel_app_param.length()) { - dlg.setRoute(get_header_keyvalue(iptel_app_param,"Transfer-RR")); - //dlg.next_hop = get_header_keyvalue(iptel_app_param,"Transfer-NH"); + dlg.route = get_header_keyvalue(iptel_app_param,"Transfer-RR"); } else { INFO("Use of P-Transfer-RR/P-Transfer-NH is deprecated. " "Use '%s: Transfer-RR=;Transfer-NH=' instead.\n",PARAM_HDR); - dlg.setRoute(getHeader(req.hdrs,"P-Transfer-RR")); - //dlg.next_hop = getHeader(req.hdrs,"P-Transfer-NH"); + dlg.route = getHeader(req.hdrs,"P-Transfer-RR"); } DBG("ConferenceDialog::onSipRequest: local_party = %s\n",dlg.local_party.c_str()); diff --git a/core/AmConfig.cpp b/core/AmConfig.cpp index 4ad08788..7ab74d67 100644 --- a/core/AmConfig.cpp +++ b/core/AmConfig.cpp @@ -57,6 +57,7 @@ int AmConfig::SIPServerThreads = NUM_SIP_SERVERS; int AmConfig::LocalSIPPort = 5060; string AmConfig::LocalSIPIP = ""; string AmConfig::OutboundProxy = ""; +bool AmConfig::ForceOutboundProxy = false; string AmConfig::Signature = ""; bool AmConfig::SingleCodecInOK = false; unsigned int AmConfig::DeadRtpTime = DEAD_RTP_TIME; @@ -218,6 +219,11 @@ int AmConfig::readConfiguration() // outbound_proxy OutboundProxy = cfg.getParameter("outbound_proxy"); + + // force_outbound_proxy + if(cfg.hasParameter("force_outbound_proxy")) { + ForceOutboundProxy = (cfg.getParameter("force_outbound_proxy") == "yes"); + } // plugin_path PlugInPath = cfg.getParameter("plugin_path"); diff --git a/core/AmConfig.h b/core/AmConfig.h index 87aef3e4..411a25ff 100644 --- a/core/AmConfig.h +++ b/core/AmConfig.h @@ -87,6 +87,8 @@ struct AmConfig static int LocalSIPPort; /** Outbound Proxy (optional, outgoing calls only) */ static string OutboundProxy; + /** force Outbound Proxy to be used for in dialog requests */ + static bool ForceOutboundProxy; /** Server/User-Agent header (optional) */ static string Signature; /** If 200 OK reply should be limited to preferred codec only */ diff --git a/core/AmSipDialog.cpp b/core/AmSipDialog.cpp index ac8a34cf..a26e7cab 100644 --- a/core/AmSipDialog.cpp +++ b/core/AmSipDialog.cpp @@ -41,7 +41,9 @@ const char* AmSipDialog::status2str[4] = { AmSipDialog::AmSipDialog(AmSipDialogEventHandler* h) - : status(Disconnected),cseq(10),hdl(h), serKeyLen(0) + : status(Disconnected),cseq(10),hdl(h), + outbound_proxy(AmConfig::OutboundProxy), + force_outbound_proxy(AmConfig::ForceOutboundProxy) { } @@ -69,8 +71,7 @@ AmSipDialog::~AmSipDialog() void AmSipDialog::updateStatus(const AmSipRequest& req) { - if (req.method == "ACK") { - // || (req.method == "CANCEL") + if ((req.method == "ACK") || (req.method == "CANCEL")) { return; } @@ -102,9 +103,7 @@ void AmSipDialog::updateStatus(const AmSipRequest& req) local_uri = req.r_uri; remote_party = req.from; local_party = req.to; - - setRoute(req.route); - //next_hop = req.next_hop; + route = req.route; } } @@ -145,8 +144,6 @@ int AmSipDialog::updateStatusReply(const AmSipRequest& req, unsigned int code) DBG("reply: transaction found!\n"); AmSipTransaction& t = t_it->second; - - //t->reply_code = code; switch(status){ case Disconnected: @@ -202,24 +199,21 @@ void AmSipDialog::updateStatus(const AmSipReply& reply, bool do_200_ack) AmSipTransaction& t = t_it->second; // rfc3261 12.1 - // && method==INVITE // Dialog established only by 101-199 or 2xx // responses to INVITE - if ((reply.code >= 101) && (reply.code < 300) && - (remote_tag.empty() && !reply.remote_tag.empty())) - remote_tag = reply.remote_tag; - if ((reply.code >= 200) && (reply.code < 300) && - (status != Connected && !reply.remote_tag.empty())) + if ( (reply.code > 100) + && (reply.code < 300) + && !reply.remote_tag.empty() + && (remote_tag.empty() || + ((status < Connected) && (reply.code >= 200))) ) { + remote_tag = reply.remote_tag; + } // allow route overwritting - if(status < Connected) { - - if(!reply.route.empty()) - setRoute(reply.route); - - //next_hop = reply.next_hop; + if ((status < Connected) && !reply.route.empty()) { + route = reply.route; } if (reply.next_request_uri.length()) @@ -491,7 +485,7 @@ int AmSipDialog::transfer(const string& target) string hdrs = ""; AmSipDialog tmp_d(*this); - tmp_d.setRoute(""); + tmp_d.route = ""; tmp_d.contact_uri = SIP_HDR_COLSP(SIP_HDR_CONTACT) "<" + tmp_d.remote_uri + ">" CRLF; tmp_d.remote_uri = target; @@ -499,14 +493,7 @@ int AmSipDialog::transfer(const string& target) string r_set; if(!route.empty()){ - vector::iterator it = route.begin(); - r_set ="Transfer-RR=\"" + *it; - - for(it++; it != route.end(); it++) - r_set += "," + *it; - - r_set += "\""; - hdrs = PARAM_HDR ": " + r_set; + hdrs = PARAM_HDR ": " "Transfer-RR=\"" + route + "\""; } int ret = tmp_d.sendRequest("REFER","","",hdrs); @@ -527,22 +514,12 @@ int AmSipDialog::transfer(const string& target) int AmSipDialog::cancel() { - - for(TransMap::reverse_iterator t = uac_trans.rbegin(); t != uac_trans.rend(); t++) { if(t->second.method == "INVITE"){ - - AmSipRequest req; - - req.method = "CANCEL"; - req.callid = callid; - req.cseq = t->second.cseq; - - req.tt = t->second.tt; - - return SipCtrlInterface::send(req) ? 0 : -1; + + return SipCtrlInterface::cancel(&t->second.tt); } } @@ -566,7 +543,6 @@ int AmSipDialog::sendRequest(const string& method, req.method = method; req.r_uri = remote_uri; - //req.next_hop = next_hop; req.from = SIP_HDR_COLSP(SIP_HDR_FROM) + local_party; if(!local_tag.empty()) @@ -590,13 +566,22 @@ int AmSipDialog::sendRequest(const string& method, if (AmConfig::Signature.length()) req.hdrs += SIP_HDR_COLSP(SIP_HDR_USER_AGENT) + AmConfig::Signature + CRLF; - req.hdrs += SIP_HDR_COLSP(SIP_HDR_MAX_FORWARDS) /*TODO: configurable?!*/MAX_FORWARDS CRLF; + req.hdrs += SIP_HDR_COLSP(SIP_HDR_MAX_FORWARDS) /*TODO: configurable?!*/ MAX_FORWARDS CRLF; } - if(!route.empty()) - req.route = getRoute(); - + if(!route.empty()) { + + req.route = "Route: "; + if(force_outbound_proxy){ + req.route += "<" + outbound_proxy + ";lr>, "; + } + req.route += route + CRLF; + } + else if (remote_tag.empty() && !outbound_proxy.empty()) { + req.route = "Route: <" + outbound_proxy + ";lr>" CRLF; + } + if(!body.empty()) { req.content_type = content_type; req.body = body; @@ -613,17 +598,6 @@ int AmSipDialog::sendRequest(const string& method, return 0; } - -// bool AmSipDialog::match_cancel(const AmSipRequest& cancel_req) -// { -// TransMap::iterator t = uas_trans.find(cancel_req.cseq); - -// if((t != uas_trans.end()) && (t->second.method == "INVITE")) -// return true; - -// return false; -// } - string AmSipDialog::get_uac_trans_method(unsigned int cseq) { TransMap::iterator t = uac_trans.find(cseq); @@ -634,39 +608,6 @@ string AmSipDialog::get_uac_trans_method(unsigned int cseq) return ""; } -string AmSipDialog::getRoute() -{ - string r_set(""); - for(vector::iterator it = route.begin(); - it != route.end(); it++) { - r_set += SIP_HDR_COLSP(SIP_HDR_ROUTE) + *it + CRLF; - } - - return r_set; -} - -void AmSipDialog::setRoute(const string& n_route) -{ - string m_route = n_route; - if(!m_route.empty() && (m_route.find("Route: ")!=string::npos)) - m_route = m_route.substr(7/*sizeof("Route: ")*/); - - route.clear(); - while(!m_route.empty()){ - - string::size_type comma_pos; - - comma_pos = m_route.find(','); - //route += "Route: " + m_route.substr(0,comma_pos) + "\r\n"; - route.push_back(m_route.substr(0,comma_pos)); - - if(comma_pos != string::npos) - m_route = m_route.substr(comma_pos+1); - else - m_route = ""; - } -} - int AmSipDialog::drop() { status = Disconnected; @@ -722,7 +663,7 @@ int AmSipDialog::send_200_ack(const AmSipTransaction& t, } if(!route.empty()) - req.route = getRoute(); + req.route = route; //getRoute(); if(!body.empty()) { req.content_type = content_type; diff --git a/core/AmSipDialog.h b/core/AmSipDialog.h index ae7855ee..c427d1f9 100644 --- a/core/AmSipDialog.h +++ b/core/AmSipDialog.h @@ -100,7 +100,6 @@ class AmSipDialog TransMap uac_trans; AmSipDialogEventHandler* hdl; - std::vector route; // record routing int updateStatusReply(const AmSipRequest& req, unsigned int code); @@ -133,15 +132,11 @@ class AmSipDialog string remote_party; // To/From string local_party; // To/From - string getRoute(); // record routing - void setRoute(const string& n_route); + string route; + string outbound_proxy; + bool force_outbound_proxy; - //string next_hop; // next_hop for t_uac_dlg - - int cseq; // CSeq for next request - - char serKey[MAX_SER_KEY_LEN]; // opaque string returned by SER, when staring a T - unsigned int serKeyLen; + int cseq; // Local CSeq for next request AmSipDialog(AmSipDialogEventHandler* h=0); ~AmSipDialog(); @@ -152,10 +147,11 @@ class AmSipDialog void updateStatus(const AmSipRequest& req); void updateStatus(const AmSipReply& reply, bool do_200_ack=true); + /** update Status from locally originated request (e.g. INVITE) */ void updateStatusFromLocalRequest(const AmSipRequest& req); - int reply(const AmSipRequest& req, // Ser's transaction key + int reply(const AmSipRequest& req, unsigned int code, const string& reason, const string& content_type = "", @@ -189,12 +185,6 @@ class AmSipDialog int transfer(const string& target); int drop(); - /** - * @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 */ diff --git a/core/AmSipMsg.h b/core/AmSipMsg.h index 7da36ce8..35a582e1 100644 --- a/core/AmSipMsg.h +++ b/core/AmSipMsg.h @@ -11,7 +11,6 @@ class _AmSipMsgInDlg { public: string method; - //string next_hop; // URI string route; string contact; diff --git a/core/SipCtrlInterface.cpp b/core/SipCtrlInterface.cpp index 7fffc50e..afcac551 100644 --- a/core/SipCtrlInterface.cpp +++ b/core/SipCtrlInterface.cpp @@ -127,16 +127,15 @@ SipCtrlInterface::SipCtrlInterface() trans_layer::instance()->register_ua(this); } -int SipCtrlInterface::cancel(AmSipRequest& req) +int SipCtrlInterface::cancel(trans_ticket* tt) { - return trans_layer::instance()->cancel(&req.tt); + return trans_layer::instance()->cancel(tt); } - int SipCtrlInterface::send(AmSipRequest &req) { if(req.method == "CANCEL") - return cancel(req); + return cancel(&req.tt); sip_msg* msg = new sip_msg(); @@ -152,7 +151,6 @@ int SipCtrlInterface::send(AmSipRequest &req) // CSeq // Contact // Max-Forwards - char* c = (char*)req.from.c_str(); int err = parse_headers(msg,&c); @@ -175,7 +173,6 @@ int SipCtrlInterface::send(AmSipRequest &req) msg->callid = new sip_header(0,"Call-ID",stl2cstr(req.callid)); msg->hdrs.push_back(msg->callid); - if(!req.contact.empty()){ c = (char*)req.contact.c_str(); @@ -189,9 +186,8 @@ int SipCtrlInterface::send(AmSipRequest &req) if(!req.route.empty()){ - char *c = (char*)req.route.c_str(); - - err = parse_headers(msg,&c); + c = (char*)req.route.c_str(); + err = parse_headers(msg,&c); if(err){ ERROR("Route headers parsing failed\n"); @@ -199,27 +195,11 @@ int SipCtrlInterface::send(AmSipRequest &req) delete msg; return -1; } - - // - // parse_headers() appends our route headers - // to msg->hdrs and msg->route. But we want - // only msg->route(), so we just remove the - // route headers at the end of msg->hdrs. - // - for(sip_header* h_rr = msg->hdrs.back(); - !msg->hdrs.empty(); h_rr = msg->hdrs.back()) { - - if(h_rr->type != sip_header::H_ROUTE){ - break; - } - - msg->hdrs.pop_back(); - } } if(!req.hdrs.empty()) { - char *c = (char*)req.hdrs.c_str(); + c = (char*)req.hdrs.c_str(); err = parse_headers(msg,&c); @@ -244,41 +224,6 @@ int SipCtrlInterface::send(AmSipRequest &req) } } - string next_hop; - unsigned int next_port_i = 0; - -// if(!req.next_hop.empty()){ -// string next_port; -// sip_uri parsed_uri; -// if (parse_uri(&parsed_uri, (char *)req.next_hop.c_str(), -// req.next_hop.length()) < 0) { -// ERROR("invalid next hop URI '%s'\n", req.next_hop.c_str()); -// ERROR("Using default outbound proxy"); -// next_hop = SipCtrlInterface::outbound_host; -// next_port_i = SipCtrlInterface::outbound_port; -// } else { -// next_hop = c2stlstr(parsed_uri.host); -// if (parsed_uri.port) { -// next_port_i= parsed_uri.port; } -// next_hop += *(c++); -// } -// } -// else - if(!SipCtrlInterface::outbound_host.empty()){ - next_hop = SipCtrlInterface::outbound_host; - next_port_i = SipCtrlInterface::outbound_port; - } - - cstring c_next_hop = stl2cstr(next_hop); - if(trans_layer::instance()->set_next_hop(msg->route,msg->u.request->ruri_str, - c_next_hop,(unsigned short)next_port_i, - &msg->remote_ip) < 0){ - - DBG("set_next_hop failed\n"); - delete msg; - return -1; - } - int res = trans_layer::instance()->send_request(msg,&req.tt); delete msg; diff --git a/core/SipCtrlInterface.h b/core/SipCtrlInterface.h index 8280107a..1cec2c1f 100644 --- a/core/SipCtrlInterface.h +++ b/core/SipCtrlInterface.h @@ -38,17 +38,16 @@ using std::list; class AmSipRequest; class AmSipReply; -class trans_layer; -class trans_bucket; struct sip_msg; struct sip_header; +class trans_ticket; + class SipCtrlInterface: public sip_ua { void prepare_routes_uac(const list& routes, string& route_field); void prepare_routes_uas(const list& routes, string& route_field); - static int cancel(AmSipRequest& req); friend class udp_trsp; @@ -68,10 +67,9 @@ public: void run(const string& bind_addr, unsigned short bind_port); - /** - * From AmCtrlInterface - */ static int send(AmSipRequest &req); + static int cancel(trans_ticket* tt); + static int send(const AmSipReply &rep); /** diff --git a/core/sip/parse_header.cpp b/core/sip/parse_header.cpp index 3844fa4f..b81191b6 100644 --- a/core/sip/parse_header.cpp +++ b/core/sip/parse_header.cpp @@ -282,8 +282,6 @@ int parse_headers(sip_msg* msg, char** c) int saved_st = 0; char* begin = *c; - //bool cr = false; - auto_ptr hdr(new sip_header()); for(;**c;(*c)++){ diff --git a/core/sip/trans_layer.cpp b/core/sip/trans_layer.cpp index 6750ce0a..2f0d25eb 100644 --- a/core/sip/trans_layer.cpp +++ b/core/sip/trans_layer.cpp @@ -539,7 +539,7 @@ int trans_layer::send_sl_reply(sip_msg* req, int reply_code, // int trans_layer::set_next_hop(list& route_hdrs, cstring& r_uri, cstring& next_hop, - unsigned short next_port, + unsigned short& next_port, sockaddr_storage* remote_ip) { int err=0; @@ -648,7 +648,7 @@ int trans_layer::set_next_hop(list& route_hdrs, case RR_PARAMS: // remove current route header from message DBG("delete (fr=0x%p)\n",fr); - delete fr; // route_hdrs.front(); + delete fr; route_hdrs.pop_front(); DBG("route_hdrs.length() = %i\n",(int)route_hdrs.size()); break; @@ -669,7 +669,8 @@ int trans_layer::set_next_hop(list& route_hdrs, } } - else if (next_hop.len == 0) { + else { + sip_uri parsed_r_uri; err = parse_uri(&parsed_r_uri,r_uri.s,r_uri.len); if(err < 0){ @@ -730,17 +731,26 @@ int trans_layer::send_request(sip_msg* msg, trans_ticket* tt) // Contact // Supported / Require // Content-Length / Content-Type - + assert(transport); assert(msg); assert(tt); + cstring next_hop; + unsigned short next_port = 0; + tt->_bucket = 0; tt->_t = 0; - // assume that msg->route headers are not in msg->hdrs - msg->hdrs.insert(msg->hdrs.begin(),msg->route.begin(),msg->route.end()); + if(trans_layer::instance()->set_next_hop(msg->route,msg->u.request->ruri_str, + next_hop,next_port, + &msg->remote_ip) < 0){ + DBG("set_next_hop failed\n"); + delete msg; + return -1; + } + int request_len = request_line_len(msg->u.request->method_str, msg->u.request->ruri_str); @@ -1036,7 +1046,7 @@ void trans_layer::received_msg(sip_msg* msg) } else { DBG("Found retransmission\n"); - retransmit(t); + retransmit(t); // retransmit reply } } else { diff --git a/core/sip/trans_layer.h b/core/sip/trans_layer.h index 20970b80..dbf2aac7 100644 --- a/core/sip/trans_layer.h +++ b/core/sip/trans_layer.h @@ -97,12 +97,12 @@ class trans_layer int update_uas_reply(trans_bucket* bucket, sip_trans* t, int reply_code); /** - * Retransmits reply / non-200 ACK (if possible). + * Retransmits the content of the retry buffer (replies or non-200 ACK). */ void retransmit(sip_trans* t); /** - * Retransmits a message (mostly the first UAC request). + * Retransmits a message (UAC requests). */ void retransmit(sip_msg* msg); @@ -120,6 +120,14 @@ class trans_layer int send_sl_reply(sip_msg* req, int reply_code, const cstring& reason, const cstring& hdrs, const cstring& body); + + /** + * Fills the address structure passed and modifies + * R-URI and Route headers as needed. + */ + int set_next_hop(list& route_hdrs, cstring& r_uri, + cstring& next_hop, unsigned short& next_port, + sockaddr_storage* remote_ip); /** * Transaction timeout @@ -179,14 +187,6 @@ class trans_layer */ void received_msg(sip_msg* msg); - /** - * Fills the address structure passed and modifies - * R-URI and Route headers as needed. - */ - int set_next_hop(list& route_hdrs, cstring& r_uri, - cstring& next_hop, unsigned short next_port, - sockaddr_storage* remote_ip); - /** * This is called by the transaction timer callback. * At this place, the bucket is already locked, so