Browse code

sbc: added R-URI host patching with resolved fqdn.

Raphael Coeffic authored on 19/06/2013 10:54:57
Showing 10 changed files
... ...
@@ -555,6 +555,7 @@ bool SBCCallProfile::operator==(const SBCCallProfile& rhs) const {
555 555
     aleg_force_outbound_proxy == rhs.aleg_force_outbound_proxy &&
556 556
     next_hop == rhs.next_hop &&
557 557
     next_hop_1st_req == rhs.next_hop_1st_req &&
558
+    patch_ruri_next_hop == rhs.patch_ruri_next_hop &&
558 559
     aleg_next_hop == rhs.aleg_next_hop &&
559 560
     headerfilter == rhs.headerfilter &&
560 561
     //headerfilter_list == rhs.headerfilter_list &&
... ...
@@ -882,6 +883,9 @@ int SBCCallProfile::apply_b_routing(ParamReplacerCtx& ctx,
882 883
     dlg.setNextHop1stReq(next_hop_1st_req);
883 884
   }
884 885
 
886
+  DBG("patch_ruri_next_hop = %i",patch_ruri_next_hop);
887
+  dlg.setPatchRURINextHop(patch_ruri_next_hop);
888
+
885 889
   if (!outbound_proxy.empty()) {
886 890
     string op = ctx.replaceParameters(outbound_proxy, "outbound_proxy", req);
887 891
     dlg.outbound_proxy = op;
... ...
@@ -114,6 +114,7 @@ struct SBCCallProfile
114 114
 
115 115
   string next_hop;
116 116
   bool next_hop_1st_req;
117
+  bool patch_ruri_next_hop;
117 118
 
118 119
   string aleg_next_hop;
119 120
 
... ...
@@ -29,6 +29,7 @@ AmBasicSipDialog::AmBasicSipDialog(AmBasicSipEventHandler* h)
29 29
     force_outbound_proxy(AmConfig::ForceOutboundProxy),
30 30
     next_hop(AmConfig::NextHop),
31 31
     next_hop_1st_req(AmConfig::NextHop1stReq),
32
+    patch_ruri_next_hop(),
32 33
     outbound_interface(-1),
33 34
     nat_handling(false),
34 35
     usages(0)
... ...
@@ -635,7 +636,10 @@ int AmBasicSipDialog::sendRequest(const string& method,
635 636
   int res = SipCtrlInterface::send(req, local_tag,
636 637
 				   remote_tag.empty() || !next_hop_1st_req ?
637 638
 				   next_hop : "",
638
-				   outbound_interface, logger);
639
+				   outbound_interface,
640
+				   !patch_ruri_next_hop || !remote_tag.empty() ? 0
641
+				   : SEND_REQUEST_FLAG_NEXT_HOP_RURI,
642
+				   logger);
639 643
   if(res) {
640 644
     ERROR("Could not send request: method=%s; call-id=%s; cseq=%i\n",
641 645
 	  req.method.c_str(),req.callid.c_str(),req.cseq);
... ...
@@ -110,6 +110,7 @@ protected:
110 110
 
111 111
   string next_hop;
112 112
   bool next_hop_1st_req;
113
+  bool patch_ruri_next_hop;
113 114
 
114 115
   int outbound_interface;
115 116
 
... ...
@@ -278,6 +279,10 @@ public:
278 279
   virtual void setNextHop1stReq(bool nh_1st_req)
279 280
   { next_hop_1st_req = nh_1st_req; }
280 281
 
282
+  bool getPatchRURINextHop() const { return patch_ruri_next_hop; }
283
+  virtual void setPatchRURINextHop(bool patch_nh)
284
+  { patch_ruri_next_hop = patch_nh; }
285
+
281 286
   /**
282 287
    * Compute the Contact-HF for the next request
283 288
    */
... ...
@@ -777,7 +777,7 @@ int AmSipDialog::send_200_ack(unsigned int inv_cseq,
777 777
   int res = SipCtrlInterface::send(req, local_tag,
778 778
 				   remote_tag.empty() || !next_hop_1st_req ? 
779 779
 				   next_hop : "",
780
-				   outbound_interface, logger);
780
+				   outbound_interface, 0, logger);
781 781
   if (res)
782 782
     return res;
783 783
 
... ...
@@ -166,8 +166,8 @@ int _SipCtrlInterface::cancel(trans_ticket* tt, const string& hdrs)
166 166
 }
167 167
 
168 168
 int _SipCtrlInterface::send(AmSipRequest &req, const string& dialog_id,
169
-			   const string& next_hop, int out_interface,
170
-			   msg_logger* logger)
169
+			    const string& next_hop, int out_interface,
170
+			    unsigned int flags, msg_logger* logger)
171 171
 {
172 172
     if(req.method == "CANCEL")
173 173
 	return cancel(&req.tt, req.hdrs);
... ...
@@ -261,7 +261,8 @@ int _SipCtrlInterface::send(AmSipRequest &req, const string& dialog_id,
261 261
     int res = trans_layer::instance()->send_request(msg,&req.tt,
262 262
 						    stl2cstr(dialog_id),
263 263
 						    stl2cstr(next_hop),
264
-						    out_interface,logger);
264
+						    out_interface,
265
+						    flags,logger);
265 266
     delete msg;
266 267
 
267 268
     return res;
... ...
@@ -91,7 +91,7 @@ public:
91 91
      */
92 92
     static int send(AmSipRequest &req, const string& dialog_id,
93 93
 		    const string& next_hop = "", int outbound_interface = -1,
94
-		    msg_logger* logger = NULL);
94
+		    unsigned int flags = 0, msg_logger* logger = NULL);
95 95
 
96 96
     /**
97 97
      * Sends a SIP reply. 
... ...
@@ -142,6 +142,9 @@ class sip_trans
142 142
     sockaddr_storage retr_addr;
143 143
     trsp_socket*     retr_socket;
144 144
 
145
+    /** flags used by send_request() */
146
+    unsigned int flags;
147
+
145 148
     /** message logging */
146 149
     msg_logger* logger;
147 150
 
... ...
@@ -874,10 +874,124 @@ void _trans_layer::timeout(trans_bucket* bucket, sip_trans* t)
874 874
     ua->handle_sip_reply(dialog_id,&msg);
875 875
 }
876 876
 
877
+static int patch_ruri_with_remote_ip(string& n_uri, sip_msg* msg)
878
+{
879
+    // TODO:
880
+    // - parse R-URI
881
+    // - replace host/port
882
+    // - generate new R-URI
883
+    cstring old_ruri = msg->u.request->ruri_str;
884
+    struct sip_uri parsed_uri;
885
+    if(parse_uri(&parsed_uri, old_ruri.s, old_ruri.len) < 0) {
886
+ 	ERROR("could not parse local R-URI ('%.*s')",old_ruri.len,old_ruri.s);
887
+ 	return -1;
888
+    }
889
+ 	
890
+    // copy from the beginning until URI-host
891
+    n_uri = string(old_ruri.s, parsed_uri.host.s - old_ruri.s);
892
+ 
893
+    // append new host and port
894
+    n_uri += get_addr_str(&msg->remote_ip);
895
+    unsigned short new_port = am_get_port(&msg->remote_ip);
896
+    if(new_port != 5060) {
897
+ 	n_uri += ":" + int2str(new_port);
898
+    }
899
+ 	
900
+    if(parsed_uri.port_str.len) {
901
+ 	// copy from end of port-string until the end of old R-URI
902
+ 	n_uri += string(parsed_uri.port_str.s + parsed_uri.port_str.len,
903
+ 			old_ruri.s + old_ruri.len
904
+ 			- (parsed_uri.port_str.s 
905
+ 			   + parsed_uri.port_str.len));
906
+    }
907
+    else {
908
+ 	// copy from end of host-string until the end of old R-URI
909
+ 	n_uri += string(parsed_uri.host.s + parsed_uri.host.len,
910
+ 			old_ruri.s + old_ruri.len
911
+ 			- (parsed_uri.host.s 
912
+ 			   + parsed_uri.host.len));
913
+    }
914
+ 
915
+    msg->u.request->ruri_str = stl2cstr(n_uri);
916
+ 
917
+    return 0;
918
+}
919
+ 
920
+static int generate_and_parse_new_msg(sip_msg* msg, sip_msg*& p_msg)
921
+{
922
+    int request_len = request_line_len(msg->u.request->method_str,
923
+ 				       msg->u.request->ruri_str);
924
+ 
925
+    char branch_buf[BRANCH_BUF_LEN];
926
+    compute_branch(branch_buf,msg->callid->value,msg->cseq->value);
927
+    cstring branch(branch_buf,BRANCH_BUF_LEN);
928
+     
929
+    string via(msg->local_socket->get_ip());
930
+    if(msg->local_socket->get_port() != 5060)
931
+ 	via += ":" + int2str(msg->local_socket->get_port());
932
+ 
933
+    // add 'rport' parameter defaultwise? yes, for now
934
+    request_len += via_len(stl2cstr(via),branch,true);
935
+ 
936
+    request_len += copy_hdrs_len(msg->hdrs);
937
+     
938
+    string content_len = int2str(msg->body.len);
939
+     
940
+    request_len += content_length_len(stl2cstr(content_len));
941
+    request_len += 2/* CRLF end-of-headers*/;
942
+     
943
+    if(msg->body.len){
944
+ 	request_len += msg->body.len;
945
+    }
946
+     
947
+    // Allocate new message
948
+    p_msg = new sip_msg();
949
+    p_msg->buf = new char[request_len+1];
950
+    p_msg->len = request_len;
951
+    p_msg->h_dns = msg->h_dns;
952
+ 
953
+    // generate it
954
+    char* c = p_msg->buf;
955
+    request_line_wr(&c,msg->u.request->method_str,
956
+ 		    msg->u.request->ruri_str);
957
+ 
958
+    via_wr(&c,stl2cstr(via),branch,true);
959
+    copy_hdrs_wr(&c,msg->hdrs);
960
+ 
961
+    content_length_wr(&c,stl2cstr(content_len));
962
+ 
963
+    *c++ = CR;
964
+    *c++ = LF;
965
+ 
966
+    if(msg->body.len){
967
+ 	memcpy(c,msg->body.s,msg->body.len);
968
+ 
969
+ 	c += msg->body.len;
970
+    }
971
+    *c++ = '\0';
972
+ 
973
+    // and parse it
974
+    char* err_msg=0;
975
+    if(parse_sip_msg(p_msg,err_msg)){
976
+ 	ERROR("Parser failed on generated request\n");
977
+ 	ERROR("Message was: <%.*s>\n",p_msg->len,p_msg->buf);
978
+ 	delete p_msg;
979
+ 	p_msg = NULL;
980
+ 	return MALFORMED_SIP_MSG;
981
+    }
982
+ 
983
+    // copy msg->remote_ip
984
+    memcpy(&p_msg->remote_ip,&msg->remote_ip,sizeof(sockaddr_storage));
985
+    p_msg->local_socket = msg->local_socket;
986
+    inc_ref(p_msg->local_socket);
987
+ 
988
+    return 0;
989
+}
990
+ 
877 991
 int _trans_layer::send_request(sip_msg* msg, trans_ticket* tt, 
878 992
 			       const cstring& dialog_id,
879 993
 			       const cstring& _next_hop, 
880
-			       int out_interface,
994
+			       int out_interface, unsigned int flags,
881 995
 			       msg_logger* logger)
882 996
 {
883 997
     // Request-URI
... ...
@@ -980,70 +1094,16 @@ int _trans_layer::send_request(sip_msg* msg, trans_ticket* tt,
980 1094
 	DBG("send_request to R-URI <%.*s>",msg->u.request->ruri_str.len,msg->u.request->ruri_str.s);
981 1095
     }
982 1096
 
983
-    int request_len = request_line_len(msg->u.request->method_str,
984
-				       msg->u.request->ruri_str);
985
-
986
-    char branch_buf[BRANCH_BUF_LEN];
987
-    compute_branch(branch_buf,msg->callid->value,msg->cseq->value);
988
-    cstring branch(branch_buf,BRANCH_BUF_LEN);
989
-    
990
-    string via(msg->local_socket->get_ip());
991
-    if(msg->local_socket->get_port() != 5060)
992
-	via += ":" + int2str(msg->local_socket->get_port());
993
-
994
-    // add 'rport' parameter defaultwise? yes, for now
995
-    request_len += via_len(stl2cstr(via),branch,true);
996
-
997
-    request_len += copy_hdrs_len(msg->hdrs);
998
-
999
-    string content_len = int2str(msg->body.len);
1000
-
1001
-    request_len += content_length_len(stl2cstr(content_len));
1002
-    request_len += 2/* CRLF end-of-headers*/;
1003
-
1004
-    if(msg->body.len){
1005
-	request_len += msg->body.len;
1097
+    string ruri; // buffer needs to be @ function scope
1098
+    if((flags & SEND_REQUEST_FLAG_NEXT_HOP_RURI) &&
1099
+       (patch_ruri_with_remote_ip(ruri,msg) < 0)) {
1100
+ 	return -1;
1006 1101
     }
1007 1102
 
1008
-    // Allocate new message
1009
-    sip_msg* p_msg = new sip_msg();
1010
-    p_msg->buf = new char[request_len+1];
1011
-    p_msg->len = request_len;
1012
-    p_msg->h_dns = msg->h_dns;
1013
-
1014
-    // generate it
1015
-    char* c = p_msg->buf;
1016
-    request_line_wr(&c,msg->u.request->method_str,
1017
-		    msg->u.request->ruri_str);
1018
-
1019
-    via_wr(&c,stl2cstr(via),branch,true);
1020
-    copy_hdrs_wr(&c,msg->hdrs);
1021
-
1022
-    content_length_wr(&c,stl2cstr(content_len));
1023
-
1024
-    *c++ = CR;
1025
-    *c++ = LF;
1026
-
1027
-    if(msg->body.len){
1028
-	memcpy(c,msg->body.s,msg->body.len);
1029
-
1030
-	c += msg->body.len;
1031
-    }
1032
-    *c++ = '\0';
1033
-
1034
-    // and parse it
1035
-    char* err_msg=0;
1036
-    if(parse_sip_msg(p_msg,err_msg)){
1037
-	ERROR("Parser failed on generated request\n");
1038
-	ERROR("Message was: <%.*s>\n",p_msg->len,p_msg->buf);
1039
-	delete p_msg;
1040
-	return MALFORMED_SIP_MSG;
1041
-    }
1042
-
1043
-    // copy msg->remote_ip
1044
-    memcpy(&p_msg->remote_ip,&msg->remote_ip,sizeof(sockaddr_storage));
1045
-    p_msg->local_socket = msg->local_socket;
1046
-    inc_ref(p_msg->local_socket);
1103
+    // generate new msg and parse it
1104
+    sip_msg* p_msg=NULL;
1105
+    int err = generate_and_parse_new_msg(msg,p_msg);
1106
+    if(err != 0) { return err; }
1047 1107
 
1048 1108
     DBG("Sending to %s:%i <%.*s...>\n",
1049 1109
 	get_addr_str(&p_msg->remote_ip).c_str(),
... ...
@@ -1073,6 +1133,10 @@ int _trans_layer::send_request(sip_msg* msg, trans_ticket* tt,
1073 1133
 	    return send_err;
1074 1134
 	}
1075 1135
 
1136
+	// TODO:
1137
+	// - save flags in transaction
1138
+	tt->_t->flags = flags;
1139
+
1076 1140
 	DBG("logger = %p\n",logger);
1077 1141
 
1078 1142
 	if(logger) {
... ...
@@ -1081,15 +1145,19 @@ int _trans_layer::send_request(sip_msg* msg, trans_ticket* tt,
1081 1145
 
1082 1146
 	    cstring method_str = msg->u.request->method_str;
1083 1147
 	    char* msg_buffer=NULL;
1148
+	    unsigned int msg_len=0;
1149
+
1084 1150
 	    if(method == sip_request::ACK) {
1085 1151
 		// in case of ACK, p_msg gets deleted in update_uac_request
1086 1152
 		msg_buffer = tt->_t->retr_buf;
1153
+		msg_len = tt->_t->retr_len;
1087 1154
 	    }
1088 1155
 	    else {
1089 1156
 		msg_buffer = p_msg->buf;
1157
+		msg_len = p_msg->len;
1090 1158
 	    }
1091 1159
 
1092
-	    logger->log(msg_buffer,request_len,
1160
+	    logger->log(msg_buffer,msg_len,
1093 1161
 			&src_ip,&msg->remote_ip,
1094 1162
 			method_str);
1095 1163
 
... ...
@@ -2160,7 +2228,18 @@ int _trans_layer::try_next_ip(trans_bucket* bucket, sip_trans* tr)
2160 2228
     // create new branch tag
2161 2229
     compute_branch((char*)(tr->msg->via_p1->branch.s+MAGIC_BRANCH_LEN),
2162 2230
 		   tr->msg->callid->value,tr->msg->cseq->value);
2163
-    
2231
+
2232
+    if(tr->flags & SEND_REQUEST_FLAG_NEXT_HOP_RURI) {
2233
+	string   n_uri;
2234
+	sip_msg* p_msg=NULL;
2235
+	if(!patch_ruri_with_remote_ip(n_uri, tr->msg) &&
2236
+	   !generate_and_parse_new_msg(tr->msg,p_msg)) {
2237
+
2238
+	    delete tr->msg;
2239
+	    tr->msg = p_msg;
2240
+	}		
2241
+    }
2242
+
2164 2243
     // and re-send
2165 2244
     tr->msg->send();
2166 2245
     
... ...
@@ -53,6 +53,9 @@ class sip_ua;
53 53
 //draft msg logging
54 54
 class msg_logger;
55 55
 
56
+// replace the RURI-host with next-hop IP / port
57
+#define SEND_REQUEST_FLAG_NEXT_HOP_RURI 1
58
+
56 59
 /** 
57 60
  * The transaction layer object.
58 61
  * Uses the singleton pattern.
... ...
@@ -106,7 +109,7 @@ public:
106 109
      */
107 110
     int send_request(sip_msg* msg, trans_ticket* tt, const cstring& dialog_id,
108 111
 		     const cstring& _next_hop, int out_interface = -1,
109
-		     msg_logger* logger=NULL);
112
+		     unsigned int flags=0, msg_logger* logger=NULL);
110 113
 
111 114
     /**
112 115
      * Cancels a request.