|
reSIProcate/repro
9694
|
00001 #ifdef HAVE_CONFIG_H 00002 #include "config.h" 00003 #endif 00004 00005 #include "repro/RRDecorator.hxx" 00006 00007 #include "repro/Proxy.hxx" 00008 00009 #include "resip/stack/ExtensionParameter.hxx" 00010 #include "resip/stack/Helper.hxx" 00011 #include "resip/stack/InteropHelper.hxx" 00012 #include "resip/stack/SipMessage.hxx" 00013 #include "resip/stack/Tuple.hxx" 00014 #include "resip/stack/Transport.hxx" 00015 00016 #include "rutil/Logger.hxx" 00017 00018 #define RESIPROCATE_SUBSYSTEM resip::Subsystem::REPRO 00019 00020 using resip::ExtensionParameter; 00021 using resip::NameAddr; 00022 using resip::UDP; 00023 using resip::h_RecordRoutes; 00024 using resip::h_Paths; 00025 using resip::h_RequestLine; 00026 using resip::h_Routes; 00027 using resip::p_comp; 00028 00029 namespace repro 00030 { 00031 RRDecorator::RRDecorator(const Proxy& proxy, 00032 const resip::Transport* receivedTransport, 00033 bool alreadySingleRecordRouted, 00034 bool hasInboundFlowToken, 00035 bool forceRecordRouteEnabled, 00036 bool doPath, 00037 bool isOriginalSenderBehindNAT) : 00038 mProxy(proxy), 00039 mAddedRecordRoute(0), 00040 mAlreadySingleRecordRouted(alreadySingleRecordRouted), 00041 mHasInboundFlowToken(hasInboundFlowToken), 00042 mForceRecordRouteEnabled(forceRecordRouteEnabled), 00043 mDoPath(doPath), 00044 mIsOriginalSenderBehindNAT(isOriginalSenderBehindNAT), 00045 mReceivedTransport(receivedTransport) 00046 {} 00047 00048 RRDecorator::~RRDecorator() 00049 {} 00050 00051 void 00052 RRDecorator::decorateMessage(resip::SipMessage& request, 00053 const resip::Tuple &source, 00054 const resip::Tuple &destination, 00055 const resip::Data& sigcompId) 00056 { 00057 DebugLog(<<"Proxy::decorateMessage called."); 00058 resip::NameAddr rt; 00059 00060 if(isTransportSwitch(source)) 00061 { 00062 if(mAlreadySingleRecordRouted) 00063 { 00064 singleRecordRoute(request, source, destination, sigcompId); 00065 } 00066 else 00067 { 00068 doubleRecordRoute(request, source, destination, sigcompId); 00069 } 00070 } 00071 else 00072 { 00073 // We might still want to record-route in this case; if we need an 00074 // outbound flow token or we've already added an inbound flow token 00075 if(outboundFlowTokenNeeded(request, source, destination, sigcompId) || 00076 mHasInboundFlowToken) // or we have an inbound flow 00077 { 00078 assert(mAlreadySingleRecordRouted); 00079 singleRecordRoute(request, source, destination, sigcompId); 00080 } 00081 } 00082 00083 static ExtensionParameter p_drr("drr"); 00084 resip::NameAddrs* routes=0; 00085 if(mDoPath) 00086 { 00087 routes=&(request.header(resip::h_Paths)); 00088 } 00089 else 00090 { 00091 routes=&(request.header(resip::h_RecordRoutes)); 00092 } 00093 00094 if(routes->size() > 1 && 00095 mAddedRecordRoute && 00096 routes->front().uri().exists(p_drr)) 00097 { 00098 // .bwc. It is possible that we have duplicate Record-Routes at this 00099 // point, if we have done a transport switch but both transports use the 00100 // same FQDN. 00101 resip::NameAddrs::iterator second = ++(routes->begin()); 00102 if(*second == routes->front()) 00103 { 00104 // Duplicated record-routes; pare down to a single one. 00105 routes->pop_front(); 00106 --mAddedRecordRoute; 00107 routes->front().uri().remove(p_drr); 00108 } 00109 } 00110 } 00111 00112 void 00113 RRDecorator::singleRecordRoute(resip::SipMessage& request, 00114 const resip::Tuple &source, 00115 const resip::Tuple &destination, 00116 const resip::Data& sigcompId) 00117 { 00118 resip::NameAddr rt; 00119 // .bwc. outboundFlowTokenNeeded means that we are assuming that whoever is 00120 // just downstream will remain in the call-path throughout the dialog. 00121 if(outboundFlowTokenNeeded(request, source, destination, sigcompId)) 00122 { 00123 if(destination.getType()==resip::TLS || 00124 destination.getType()==resip::DTLS) 00125 { 00126 rt = mProxy.getRecordRoute(destination.transport); 00127 rt.uri().scheme()="sips"; 00128 } 00129 else 00130 { 00131 // .bwc. It is safe to put ip+port+proto here, since we have an 00132 // existing flow to the next hop. 00133 rt.uri().host()=resip::Tuple::inet_ntop(source); 00134 rt.uri().port()=source.getPort(); 00135 rt.uri().param(resip::p_transport)=resip::Tuple::toDataLower(source.getType()); 00136 } 00137 // .bwc. If our target has an outbound flow to us, we need to put a flow 00138 // token in a Record-Route. 00139 resip::Helper::massageRoute(request,rt); 00140 resip::Data binaryFlowToken; 00141 resip::Tuple::writeBinaryToken(destination,binaryFlowToken, Proxy::FlowTokenSalt); 00142 00143 rt.uri().user()=binaryFlowToken.base64encode(); 00144 } 00145 else 00146 { 00147 // No need for a flow-token; just use an ordinary record-route. 00148 rt = mProxy.getRecordRoute(destination.transport); 00149 resip::Helper::massageRoute(request,rt); 00150 } 00151 00152 #ifdef USE_SIGCOMP 00153 if(mProxy.compressionEnabled() && !sigcompId.empty()) 00154 { 00155 rt.uri().param(p_comp)="sigcomp"; 00156 } 00157 #endif 00158 00159 static ExtensionParameter p_drr("drr"); 00160 rt.uri().param(p_drr); 00161 00162 resip::NameAddrs* routes=0; 00163 if(mDoPath) 00164 { 00165 routes=&(request.header(resip::h_Paths)); 00166 InfoLog(<< "Adding outbound Path: " << rt); 00167 } 00168 else 00169 { 00170 routes=&(request.header(resip::h_RecordRoutes)); 00171 InfoLog(<< "Adding outbound Record-Route: " << rt); 00172 } 00173 00174 routes->front().uri().param(p_drr); 00175 routes->push_front(rt); 00176 ++mAddedRecordRoute; 00177 } 00178 00179 void 00180 RRDecorator::doubleRecordRoute(resip::SipMessage& request, 00181 const resip::Tuple &source, 00182 const resip::Tuple &destination, 00183 const resip::Data& sigcompId) 00184 { 00185 // We only use this on transport switch when we have not yet Record-Routed. 00186 // If we needed a flow-token in the inbound Record-Route, it would have been 00187 // added already. 00188 resip::NameAddr rt(mProxy.getRecordRoute(mReceivedTransport)); 00189 resip::Helper::massageRoute(request,rt); 00190 if(mDoPath) 00191 { 00192 request.header(h_Paths).push_front(rt); 00193 } 00194 else 00195 { 00196 request.header(h_RecordRoutes).push_front(rt); 00197 } 00198 ++mAddedRecordRoute; 00199 singleRecordRoute(request, source, destination, sigcompId); 00200 } 00201 00202 bool 00203 RRDecorator::isTransportSwitch(const resip::Tuple& sendingFrom) 00204 { 00205 if(mForceRecordRouteEnabled) 00206 { 00207 // If we are forcing record routes to be added, then DRR on any transport switch 00208 return mReceivedTransport != sendingFrom.transport; 00209 } 00210 else 00211 { 00212 // If record routing is not forced then only DRR if we are switching transport types or 00213 // protocol versions, since the interfaces themselves may all be equally reachable 00214 // !slg! - could make this behavior more configurable 00215 return sendingFrom.getType() != mReceivedTransport->getTuple().getType() || 00216 sendingFrom.ipVersion() != mReceivedTransport->getTuple().ipVersion(); 00217 } 00218 } 00219 00220 bool 00221 RRDecorator::outboundFlowTokenNeeded(resip::SipMessage &msg, 00222 const resip::Tuple &source, 00223 const resip::Tuple &destination, 00224 const resip::Data& sigcompId) 00225 { 00226 return (destination.onlyUseExistingConnection // destination is an outbound target 00227 || resip::InteropHelper::getRRTokenHackEnabled() // or the token is enabled 00228 || mIsOriginalSenderBehindNAT // or the nat detection hack is enabled 00229 || !sigcompId.empty()); // or we are routing to a SigComp transport 00230 // ?slg? For Sigcomp are we guaranteed to always have 00231 // single RR at this point? If not, then strangeness 00232 // will happen when singleRecordRoute adds a ;drr param 00233 } 00234 00235 void 00236 RRDecorator::rollbackMessage(resip::SipMessage& request) 00237 { 00238 resip::NameAddrs* routes=0; 00239 if(mDoPath) 00240 { 00241 routes=&(request.header(resip::h_Paths)); 00242 } 00243 else 00244 { 00245 routes=&(request.header(resip::h_RecordRoutes)); 00246 } 00247 00248 while(mAddedRecordRoute--) 00249 { 00250 assert(!routes->empty()); 00251 routes->pop_front(); 00252 } 00253 00254 if(mAlreadySingleRecordRouted) 00255 { 00256 // Make sure we remove the drr param if it is there. 00257 static ExtensionParameter p_drr("drr"); 00258 routes->front().uri().remove(p_drr); 00259 } 00260 } 00261 00262 resip::MessageDecorator* 00263 RRDecorator::clone() const 00264 { 00265 return new RRDecorator(*this); 00266 } 00267 00268 } // of namespace repro
1.7.5.1