Browse code

core/sbc: added application support for Max-Forwards

- reply w/ 400 if Max-Forwards is not parseable or out of range.
- reply w/ 483 if Max-Forwards==0 and request should be forwarded.
- automatically add Max-Forwards HF if no value specified for sent requests.

Raphael Coeffic authored on 06/09/2013 08:58:54 • Václav Kubart committed on 16/10/2013 09:19:53
Showing 7 changed files
... ...
@@ -395,6 +395,11 @@ void SBCFactory::onOoDRequest(const AmSipRequest& req)
395 395
     }
396 396
     return;
397 397
   }
398
+
399
+  if(req.max_forwards == 0) {
400
+    AmSipDialog::reply_error(req, 483, SIP_REPLY_TOO_MANY_HOPS);
401
+    return;
402
+  }
398 403
   
399 404
   call_profile.fix_append_hdrs(ctx, req);
400 405
 
... ...
@@ -169,10 +169,18 @@ void AmB2BSession::onB2BEvent(B2BEvent* ev)
169 169
 
170 170
       if(req_ev->forward){
171 171
 
172
+	// Check Max-Forwards first
173
+	if(req_ev->req.max_forwards == 0) {
174
+	  relayError(req_ev->req.method,req_ev->req.cseq,
175
+		     true,483,SIP_REPLY_TOO_MANY_HOPS);
176
+	  return;
177
+	}
178
+
172 179
 	if (req_ev->req.method == SIP_METH_INVITE &&
173 180
 	    dlg->getUACInvTransPending()) {
174 181
 	  // don't relay INVITE if INV trans pending
175
-          relayError(req_ev->req.method, req_ev->req.cseq, true, 491, SIP_REPLY_PENDING);
182
+          relayError(req_ev->req.method, req_ev->req.cseq,
183
+		     true, 491, SIP_REPLY_PENDING);
176 184
 	  return;
177 185
 	}
178 186
 
... ...
@@ -646,9 +646,6 @@ int AmBasicSipDialog::sendRequest(const string& method,
646 646
     // add Signature
647 647
     if (AmConfig::Signature.length())
648 648
       req.hdrs += SIP_HDR_COLSP(SIP_HDR_USER_AGENT) + AmConfig::Signature + CRLF;
649
-    
650
-    req.hdrs += SIP_HDR_COLSP(SIP_HDR_MAX_FORWARDS) + 
651
-      int2str(AmConfig::MaxForwards) + CRLF;
652 649
   }
653 650
 
654 651
   int res = SipCtrlInterface::send(req, local_tag,
... ...
@@ -747,8 +747,10 @@ int AmSipDialog::send_200_ack(unsigned int inv_cseq,
747 747
   // acceptable, the UAC core MUST generate a valid answer in the ACK and
748 748
   // then send a BYE immediately."
749 749
 
750
-  if (uac_trans.find(inv_cseq) == uac_trans.end()) {
751
-    ERROR("trying to ACK a non-existing transaction (cseq=%i;local_tag=%s)\n",inv_cseq,local_tag.c_str());
750
+  TransMap::iterator inv_it = uac_trans.find(inv_cseq);
751
+  if (inv_it == uac_trans.end()) {
752
+    ERROR("trying to ACK a non-existing transaction (cseq=%i;local_tag=%s)\n",
753
+	  inv_cseq,local_tag.c_str());
752 754
     return -1;
753 755
   }
754 756
 
... ...
@@ -773,6 +775,8 @@ int AmSipDialog::send_200_ack(unsigned int inv_cseq,
773 775
     
774 776
   req.route = getRoute();
775 777
 
778
+  req.max_forwards = inv_it->second.max_forwards;
779
+
776 780
   if(body != NULL)
777 781
     req.body = *body;
778 782
 
... ...
@@ -783,9 +787,6 @@ int AmSipDialog::send_200_ack(unsigned int inv_cseq,
783 787
     // add Signature
784 788
     if (AmConfig::Signature.length())
785 789
       req.hdrs += SIP_HDR_COLSP(SIP_HDR_USER_AGENT) + AmConfig::Signature + CRLF;
786
-    
787
-    req.hdrs += SIP_HDR_COLSP(SIP_HDR_MAX_FORWARDS) 
788
-      + int2str(AmConfig::MaxForwards) + CRLF;
789 790
   }
790 791
 
791 792
   int res = SipCtrlInterface::send(req, local_tag,
... ...
@@ -7,6 +7,12 @@
7 7
 #include "sip/sip_parser.h"
8 8
 #include "sip/msg_logger.h"
9 9
 
10
+AmSipRequest::AmSipRequest() 
11
+  : _AmSipMsgInDlg(), 
12
+    max_forwards(-1) 
13
+{
14
+}
15
+
10 16
 string getHeader(const string& hdrs,const string& hdr_name, bool single)
11 17
 {
12 18
   size_t pos1; 
... ...
@@ -96,9 +96,11 @@ class AmSipRequest : public _AmSipMsgInDlg
96 96
   string via_branch;
97 97
   bool   first_hop;
98 98
 
99
+  int max_forwards;
100
+
99 101
   unsigned short local_if;
100 102
 
101
-  AmSipRequest() : _AmSipMsgInDlg() { }
103
+  AmSipRequest();
102 104
   ~AmSipRequest() { }
103 105
   
104 106
   string print() const;
... ...
@@ -236,6 +236,13 @@ int _SipCtrlInterface::send(AmSipRequest &req, const string& dialog_id,
236 236
 	}
237 237
     }
238 238
 
239
+    if(req.max_forwards < 0) {
240
+	req.max_forwards = AmConfig::MaxForwards;
241
+    }
242
+
243
+    string mf = int2str(req.max_forwards);
244
+    msg->hdrs.push_back(new sip_header(0,SIP_HDR_MAX_FORWARDS,stl2cstr(mf)));
245
+
239 246
     if(!req.hdrs.empty()) {
240 247
 	
241 248
  	c = (char*)req.hdrs.c_str();
... ...
@@ -534,6 +541,15 @@ inline bool _SipCtrlInterface::sip_msg2am_request(const sip_msg *msg,
534 541
 	    req.vias += c2stlstr((*it)->name) + ": " 
535 542
 		+ c2stlstr((*it)->value) + CRLF;
536 543
 	    break;
544
+	case sip_header::H_MAX_FORWARDS:
545
+	    if(!str2int(c2stlstr((*it)->value),req.max_forwards) ||
546
+	       (req.max_forwards < 0) ||
547
+	       (req.max_forwards > 255)) {
548
+		trans_layer::instance()->
549
+		    send_sf_error_reply(&tt, msg, 400, "Incorrect Max-Forwards");
550
+		return false;
551
+	    }
552
+	    break;
537 553
 	}
538 554
     }
539 555