Browse code

sip: use sip_target_set instead of a fake DNS handle for multiple destinations

This allows, among other things, to keep the transport set in the next-hop list and remove the use of fake DNS records.

Raphael Coeffic authored on 10/11/2013 12:59:42
Showing 6 changed files
... ...
@@ -95,7 +95,8 @@ int dns_ip_entry::next_ip(dns_handle* h, sockaddr_storage* sa)
95 95
     }
96 96
     
97 97
     int& index = h->ip_n;
98
-    if(index >= (int)ip_vec.size()) return -1;
98
+    if((index < 0) || (index >= (int)ip_vec.size()))
99
+	return -1;
99 100
     
100 101
     //copy address
101 102
     ((ip_entry*)ip_vec[index++])->to_sa(sa);
... ...
@@ -176,8 +177,6 @@ public:
176 177
     int next_ip(dns_handle* h, sockaddr_storage* sa)
177 178
     {
178 179
 	int& index = h->srv_n;
179
-	if(index >= (int)ip_vec.size()) return -1;
180
-	
181 180
 	if(h->srv_e != this){
182 181
 	    if(h->srv_e) dec_ref(h->srv_e);
183 182
 	    h->srv_e = this;
... ...
@@ -195,6 +194,10 @@ public:
195 194
 	    }
196 195
 	    return h->ip_e->next_ip(h,sa);
197 196
 	}
197
+
198
+	if((index < 0) ||
199
+	   (index >= (int)ip_vec.size()))
200
+	    return -1;
198 201
 	
199 202
 	// reset IP record
200 203
 	if(h->ip_e){
... ...
@@ -132,8 +132,7 @@ struct sip_msg
132 132
     trsp_socket*       local_socket;
133 133
 
134 134
     sockaddr_storage   remote_ip;
135
-    dns_handle         h_dns;
136
-    
135
+
137 136
     sip_msg();
138 137
     sip_msg(const char* msg_buf, int msg_len);
139 138
     ~sip_msg();
... ...
@@ -35,6 +35,7 @@
35 35
 #include "trans_layer.h"
36 36
 #include "transport.h"
37 37
 #include "msg_logger.h"
38
+#include "ip_util.h"
38 39
 
39 40
 #include "log.h"
40 41
 
... ...
@@ -65,8 +66,22 @@ inline trans_timer** fetch_timer(unsigned int timer_type, trans_timer** base)
65 66
     return NULL;
66 67
 }
67 68
 
69
+void sip_target_set::debug()
70
+{
71
+    DBG("target list:");
72
+
73
+    for(list<sip_target>::iterator it = dest_list.begin();
74
+	it != dest_list.end(); it++) {
75
+
76
+	DBG("\t%s:%u/%s to target list",
77
+	    am_inet_ntop(&it->ss).c_str(),
78
+	    am_get_port(&it->ss),it->trsp);
79
+    }
80
+}
81
+
68 82
 sip_trans::sip_trans()
69 83
     : msg(NULL),
84
+      targets(NULL),
70 85
       retr_buf(NULL),
71 86
       retr_socket(NULL),
72 87
       retr_len(0),
... ...
@@ -80,6 +95,7 @@ sip_trans::~sip_trans()
80 95
 {
81 96
     reset_all_timers();
82 97
     delete msg;
98
+    delete targets;
83 99
     delete [] retr_buf;
84 100
     if(retr_socket){
85 101
 	dec_ref(retr_socket);
... ...
@@ -35,6 +35,9 @@
35 35
 
36 36
 #include <sys/socket.h>
37 37
 
38
+#include <list>
39
+using std::list;
40
+
38 41
 struct sip_msg;
39 42
 class trsp_socket;
40 43
 class msg_logger;
... ...
@@ -114,7 +117,7 @@ struct sip_target
114 117
 
115 118
     const sip_target& operator = (const sip_target& target) {
116 119
 	memcpy(&ss,&target.ss,sizeof(sockaddr_storage));
117
-	memcpy(trsp,target.trsp,SIP_TRSP_SIZE_MAX);
120
+	memcpy(trsp,target.trsp,SIP_TRSP_SIZE_MAX+1);
118 121
 	return target;
119 122
     }
120 123
 
... ...
@@ -153,6 +156,8 @@ struct sip_target_set
153 156
 	return has_next();
154 157
     }
155 158
 
159
+    void debug();
160
+
156 161
 private:
157 162
     sip_target_set(const sip_target_set&) {}
158 163
 };
... ...
@@ -186,6 +191,9 @@ class sip_trans
186 191
     /** Dialog-ID used for UAC transactions */
187 192
     cstring dialog_id;
188 193
 
194
+    /** Destination list for requests */
195
+    sip_target_set* targets;
196
+    
189 197
     /**
190 198
      * Retransmission buffer
191 199
      *  - UAC transaction: ACK
... ...
@@ -791,14 +791,16 @@ int _trans_layer::set_next_hop(sip_msg* msg,
791 791
 }
792 792
 
793 793
 
794
-int _trans_layer::set_destination_ip(sip_msg* msg, cstring* next_hop,
795
-				     unsigned short next_port)
794
+int _trans_layer::set_destination_ip(const cstring* next_hop,
795
+				     unsigned short next_port,
796
+				     sockaddr_storage* remote_ip,
797
+				     dns_handle* h_dns)
796 798
 {
797 799
 
798 800
     string nh = c2stlstr(*next_hop);
799 801
 
800 802
     DBG("checking whether '%s' is IP address...\n", nh.c_str());
801
-    if (am_inet_pton(nh.c_str(), &(msg->remote_ip)) != 1) {
803
+    if (am_inet_pton(nh.c_str(), remote_ip) != 1) {
802 804
 
803 805
 	// nh does NOT contain a valid IP address
804 806
     
... ...
@@ -810,11 +812,12 @@ int _trans_layer::set_destination_ip(sip_msg* msg, cstring* next_hop,
810 812
 	    } else {
811 813
 		string srv_name = "_sip._udp." + nh;
812 814
 
813
-		DBG("no port specified, looking up SRV '%s'...\n", srv_name.c_str());
815
+		DBG("no port specified, looking up SRV '%s'...\n",
816
+		    srv_name.c_str());
814 817
 
815 818
 		if(!resolver::instance()->resolve_name(srv_name.c_str(),
816
-						       &(msg->h_dns),
817
-						       &(msg->remote_ip),IPv4)){
819
+						       h_dns,remote_ip,
820
+						       IPv4)){
818 821
 		    return 0;
819 822
 		}
820 823
 
... ...
@@ -822,27 +825,62 @@ int _trans_layer::set_destination_ip(sip_msg* msg, cstring* next_hop,
822 825
 	    }
823 826
 	}
824 827
 
825
-	memset(&(msg->remote_ip),0,sizeof(sockaddr_storage));
828
+	memset(remote_ip,0,sizeof(sockaddr_storage));
826 829
 	int err = resolver::instance()->resolve_name(nh.c_str(),
827
-						     &(msg->h_dns),
828
-						     &(msg->remote_ip),IPv4);
830
+						     h_dns,remote_ip,
831
+						     IPv4);
829 832
 	if(err < 0){
830 833
 	    ERROR("Unresolvable Request URI domain\n");
831 834
 	    return -478;
832 835
 	}
833 836
     }
834 837
 
835
-    if(!am_get_port(&msg->remote_ip)) {
838
+    if(!am_get_port(remote_ip)) {
836 839
 	if(!next_port) next_port = 5060;
837
-	am_set_port(&msg->remote_ip,next_port);
840
+	am_set_port(remote_ip,next_port);
838 841
     }
839 842
 
840 843
     DBG("set destination to %s:%u\n",
841
-	nh.c_str(), am_get_port(&msg->remote_ip));
844
+	nh.c_str(), am_get_port(remote_ip));
842 845
     
843 846
     return 0;
844 847
 }
845 848
 
849
+int _trans_layer::resolve_targets(const list<sip_destination>& dest_list,
850
+				  sip_target_set* targets)
851
+{
852
+    for(list<sip_destination>::const_iterator it = dest_list.begin();
853
+	it != dest_list.end(); it++) {
854
+	
855
+	sip_target t;
856
+	dns_handle h_dns;
857
+
858
+	DBG("sip_destination: %.*s:%u/%.*s",
859
+	    it->host.len,it->host.s,
860
+	    it->port,
861
+	    it->trsp.len,it->trsp.s);
862
+
863
+	if(set_destination_ip(&it->host,it->port,&t.ss,&h_dns) != 0) {
864
+	    ERROR("Unresolvable destination");
865
+	    return -478;
866
+	}
867
+	if(it->trsp.len && (it->trsp.len <= SIP_TRSP_SIZE_MAX)) {
868
+	    memcpy(t.trsp,it->trsp.s,it->trsp.len);
869
+	    t.trsp[it->trsp.len] = '\0';
870
+	}
871
+	else {
872
+	    t.trsp[0] = '\0';
873
+	}
874
+
875
+	do {
876
+	    targets->dest_list.push_back(t);
877
+
878
+	} while(h_dns.next_ip(&t.ss) == 0);
879
+    }
880
+
881
+    return 0;
882
+}
883
+
846 884
 static void set_err_reply_from_req(sip_msg* err, sip_msg* req,
847 885
 				   int code, const char* reason)
848 886
 {
... ...
@@ -1048,7 +1086,7 @@ static int generate_and_parse_new_msg(sip_msg* msg, sip_msg*& p_msg)
1048 1086
     p_msg = new sip_msg();
1049 1087
     p_msg->buf = new char[request_len+1];
1050 1088
     p_msg->len = request_len;
1051
-    p_msg->h_dns = msg->h_dns;
1089
+    //p_msg->h_dns = msg->h_dns;
1052 1090
  
1053 1091
     // generate it
1054 1092
     char* c = p_msg->buf;
... ...
@@ -1109,88 +1147,89 @@ int _trans_layer::send_request(sip_msg* msg, trans_ticket* tt,
1109 1147
     assert(msg);
1110 1148
     assert(tt);
1111 1149
 
1112
-    cstring next_hop;
1113
-    unsigned short next_port=0;
1114
-    cstring next_trsp;
1150
+    // cstring next_hop;
1151
+    // unsigned short next_port=0;
1152
+    // cstring next_trsp;
1115 1153
 
1116 1154
     int res=0;
1155
+    list<sip_destination> dest_list;
1117 1156
     if (_next_hop.len) {
1118 1157
 
1119
-	list<sip_destination> dest_list;
1120 1158
 	res = parse_next_hop(_next_hop,dest_list);
1121
-	if(res) {
1159
+	if(res || dest_list.empty()) {
1122 1160
 	    DBG("parse_next_hop %.*s failed (%i)\n",_next_hop.len, _next_hop.s, res);
1123 1161
 	    return res;
1124 1162
 	}
1125 1163
 
1126
-	if(dest_list.size() == 1) {
1127
-	    const sip_destination& dest = dest_list.front();
1128
-	    next_hop = dest.host;
1129
-	    next_port = dest.port;
1130
-	    next_trsp = dest.trsp;
1131
-	    DBG("single next-hop: <%.*s:%u/%.*s>",
1132
-		next_hop.len,next_hop.s,next_port,
1133
-		next_trsp.len,next_trsp.s);
1134
-	}
1135
-	else if(dest_list.size() > 1) {
1136
-	    dns_ip_entry* e = new dns_ip_entry();
1137
-	    if(e->fill_ip_list(dest_list) < 0) {
1138
-		delete e;
1139
-		return -1;
1140
-	    }
1141
-
1142
-	    inc_ref(e);
1143
-	    //TODO: avoid to loose the transport from the next-hop-list
1144
-	    e->next_ip(&msg->h_dns,&msg->remote_ip);
1145
-	    DBG("destination set to <%s>\n",
1146
-		get_addr_str(&msg->remote_ip).c_str());
1147
-	}
1164
+	// if(dest_list.size() == 1) {
1165
+	//     const sip_destination& dest = dest_list.front();
1166
+	//     next_hop = dest.host;
1167
+	//     next_port = dest.port;
1168
+	//     next_trsp = dest.trsp;
1169
+	//     DBG("single next-hop: <%.*s:%u/%.*s>",
1170
+	// 	next_hop.len,next_hop.s,next_port,
1171
+	// 	next_trsp.len,next_trsp.s);
1172
+	// }
1173
+	// else if(dest_list.size() > 1) {
1174
+	//     dns_ip_entry* e = new dns_ip_entry();
1175
+	//     if(e->fill_ip_list(dest_list) < 0) {
1176
+	// 	delete e;
1177
+	// 	return -1;
1178
+	//     }
1179
+	//     inc_ref(e);
1180
+	//     //TODO: avoid to loose the transport from the next-hop-list
1181
+	//     e->next_ip(&msg->h_dns,&msg->remote_ip);
1182
+	//     DBG("destination set to <%s>\n",
1183
+	// 	get_addr_str(&msg->remote_ip).c_str());
1184
+	// }
1148 1185
     }
1149 1186
     else {
1150
-	if(set_next_hop(msg,&next_hop,&next_port,&next_trsp) < 0){
1187
+	sip_destination dest;
1188
+	if(set_next_hop(msg,&dest.host,&dest.port,&dest.trsp) < 0){
1151 1189
 	    DBG("set_next_hop failed\n");
1152 1190
 	    return -1;
1153 1191
 	}
1192
+	dest_list.push_back(dest);
1154 1193
     }
1155 1194
 
1156 1195
     string uri_buffer; // must have the same scope as 'msg'
1157 1196
     prepare_strict_routing(msg,uri_buffer);
1158 1197
 
1159
-    if(next_hop.len) {
1160
-	res = set_destination_ip(msg,&next_hop,next_port);
1161
-	if(res < 0){
1162
-	    DBG("set_destination_ip failed\n");
1163
-	    return res;
1164
-	}
1198
+    auto_ptr<sip_target_set> targets(new sip_target_set());
1199
+    res = resolve_targets(dest_list,targets.get());
1200
+    if(res < 0){
1201
+	DBG("resolve_targets failed\n");
1202
+	return res;
1165 1203
     }
1166 1204
 
1167
-    if(!(flags & TR_FLAG_DISABLE_BL) &&
1168
-       tr_blacklist::instance()->exist(&msg->remote_ip)) {
1205
+    targets->debug();
1169 1206
 
1170
-	sockaddr_storage sa;
1171
-	do {
1172
-	    memset(&sa,0,sizeof(sockaddr_storage));
1173
-
1174
-	    // get the next ip
1175
-	    if(msg->h_dns.next_ip(&sa) < 0){
1176
-		DBG("next_ip(): no more destinations! reply 500");
1177
-		sip_msg err;
1178
-		set_err_reply_from_req(&err,msg,500,
1179
-				       "All destinations blacklisted");
1180
-		ua->handle_sip_reply(c2stlstr(dialog_id),&err);
1181
-		return 0;
1182
-	    }
1183
-    
1184
-	    //If a SRV record is involved, the port number
1185
-	    // should have been set by h_dns.next_ip(...).
1186
-	    if(!am_get_port(&sa)){
1187
-		//Else, we copy the old port number
1188
-		am_set_port(&sa,am_get_port(&msg->remote_ip));
1189
-	    }
1190
-	} while(tr_blacklist::instance()->exist(&sa));
1191
-	
1192
-	memcpy(&msg->remote_ip,&sa,sizeof(sockaddr_storage));
1193
-    }
1207
+    cstring next_trsp;
1208
+    targets->reset_iterator();
1209
+    do {
1210
+	if(!targets->has_next()) {
1211
+	    DBG("next_ip(): no more destinations! reply 500");
1212
+	    sip_msg err;
1213
+	    set_err_reply_from_req(&err,msg,500,
1214
+				   "No destination available");
1215
+	    ua->handle_sip_reply(c2stlstr(dialog_id),&err);
1216
+	    return 0;
1217
+	}
1218
+
1219
+	targets->copy_next(&msg->remote_ip,&next_trsp);
1220
+	targets->next();
1221
+
1222
+	//TODO: take care of port manipulation in SRV case
1223
+	//      and the likes
1224
+	//
1225
+	// //If a SRV record is involved, the port number
1226
+	// // should have been set by h_dns.next_ip(...).
1227
+	// if(!am_get_port(&sa)){
1228
+	//     //Else, we copy the old port number
1229
+	//     am_set_port(&sa,am_get_port(&msg->remote_ip));
1230
+	// }
1231
+    } while(!(flags & TR_FLAG_DISABLE_BL) &&
1232
+	    tr_blacklist::instance()->exist(&msg->remote_ip));
1194 1233
 
1195 1234
     if((out_interface < 0) 
1196 1235
        || ((unsigned int)out_interface >= transports.size())) {
... ...
@@ -1279,9 +1318,14 @@ int _trans_layer::send_request(sip_msg* msg, trans_ticket* tt,
1279 1318
 	    return send_err;
1280 1319
 	}
1281 1320
 
1282
-	// TODO:
1283
-	// - save flags in transaction
1321
+	// save flags & target set in transaction
1284 1322
 	tt->_t->flags = flags;
1323
+	tt->_t->targets = targets.release();
1324
+
1325
+	if(tt->_t->targets->has_next()){
1326
+	    tt->_t->reset_timer(STIMER_M,M_TIMER,
1327
+				tt->_bucket->get_id());
1328
+	}
1285 1329
 
1286 1330
 	DBG("logger = %p\n",logger);
1287 1331
 
... ...
@@ -1987,10 +2031,6 @@ int _trans_layer::update_uac_request(trans_bucket* bucket, sip_trans*& t, sip_ms
1987 2031
 	break;
1988 2032
     }
1989 2033
 
1990
-    if(!msg->h_dns.eoip()){
1991
-	t->reset_timer(STIMER_M,M_TIMER,bucket->get_id());
1992
-    }
1993
-
1994 2034
     return 0;
1995 2035
 }
1996 2036
 
... ...
@@ -2463,25 +2503,38 @@ int _trans_layer::try_next_ip(trans_bucket* bucket, sip_trans* tr,
2463 2503
 			      bool use_new_trans)
2464 2504
 {
2465 2505
     tr->clear_timer(STIMER_M);
2506
+
2507
+    cstring next_trsp;
2466 2508
     sockaddr_storage sa;
2509
+
2467 2510
     do {
2468 2511
 	memset(&sa,0,sizeof(sockaddr_storage));
2469 2512
     
2470 2513
 	// get the next ip
2471
-	if(tr->msg->h_dns.next_ip(&sa) < 0){
2514
+	if(!tr->targets->has_next()){
2472 2515
 	    DBG("no more destinations!");
2473 2516
 	    return -1;
2474 2517
 	}
2475
-    
2476
-	//If a SRV record is involved, the port number
2477
-	// should have been set by h_dns.next_ip(...).
2478
-	if(!am_get_port(&sa)){
2479
-	    //Else, we copy the old port number
2480
-	    am_set_port(&sa,am_get_port(&tr->msg->remote_ip));
2481
-	}
2518
+
2519
+	tr->targets->copy_next(&sa,&next_trsp);
2520
+	tr->targets->next();
2521
+
2522
+	//TODO: take care of port manipulation in SRV case
2523
+	//      and the likes
2524
+	//
2525
+	// //If a SRV record is involved, the port number
2526
+	// // should have been set by h_dns.next_ip(...).
2527
+	// if(!am_get_port(&sa)){
2528
+	//     //Else, we copy the old port number
2529
+	//     am_set_port(&sa,am_get_port(&tr->msg->remote_ip));
2530
+	// }
2482 2531
     } while(!(tr->flags & TR_FLAG_DISABLE_BL) &&
2483 2532
 	    tr_blacklist::instance()->exist(&sa));
2484 2533
 
2534
+    //TODO: support transport changes
2535
+    // -> potentially find another socket
2536
+    //    if next_trsp is different from the 
2537
+    //    current socket's transport
2485 2538
 
2486 2539
     if(use_new_trans) {
2487 2540
 	string   n_uri;
... ...
@@ -2526,6 +2579,10 @@ int _trans_layer::try_next_ip(trans_bucket* bucket, sip_trans* tr,
2526 2579
 	tr->clear_timer(STIMER_A);
2527 2580
 	tr->state = TS_ABANDONED;
2528 2581
 
2582
+	// take over target set
2583
+	n_tr->targets = tr->targets;
2584
+	tr->targets = NULL;
2585
+
2529 2586
 	// restore old R-URI
2530 2587
 	tr->msg->u.request->ruri_str = old_uri;
2531 2588
 
... ...
@@ -2538,8 +2595,7 @@ int _trans_layer::try_next_ip(trans_bucket* bucket, sip_trans* tr,
2538 2595
 	    tr->reset_timer(t_bf,t_bf->type);
2539 2596
 	}
2540 2597
 
2541
-	bucket->append(tr);
2542
-	
2598
+	bucket->append(tr);	
2543 2599
     }
2544 2600
     else {
2545 2601
 	// copy the new address back
... ...
@@ -2598,7 +2654,7 @@ int _trans_layer::try_next_ip(trans_bucket* bucket, sip_trans* tr,
2598 2654
 	}
2599 2655
     }
2600 2656
     
2601
-    if(!tr->msg->h_dns.eoip())
2657
+    if(tr->targets->has_next())
2602 2658
 	tr->reset_timer(STIMER_M,M_TIMER,bucket->get_id());
2603 2659
 
2604 2660
     return 0;
... ...
@@ -33,6 +33,8 @@
33 33
 #include "singleton.h"
34 34
 #include "atomic_types.h"
35 35
 
36
+#include "parse_next_hop.h"
37
+
36 38
 #include <list>
37 39
 using std::list;
38 40
 
... ...
@@ -47,9 +49,11 @@ using std::map;
47 49
 
48 50
 struct sip_msg;
49 51
 struct sip_uri;
50
-class sip_trans;
52
+class  sip_trans;
51 53
 struct sip_header;
52 54
 struct sockaddr_storage;
55
+struct dns_handle;
56
+struct sip_target_set;
53 57
 
54 58
 class trans_ticket;
55 59
 class trans_bucket;
... ...
@@ -247,15 +251,22 @@ protected:
247 251
      * Fills the address structure passed and modifies 
248 252
      * R-URI and Route headers as needed.
249 253
      */
250
-    int set_next_hop(sip_msg* msg,
251
-		     cstring* next_hop,
252
-		     unsigned short* next_port,
253
-		     cstring* next_trsp);
254
+    int set_next_hop(sip_msg* msg, cstring* next_hop,
255
+		     unsigned short* next_port, cstring* next_trsp);
256
+
257
+    /**
258
+     * Transforms all elements of a destination list into
259
+     * a target set, thus resolving all DNS names and
260
+     * converting IPs into a sockaddr_storage.
261
+     */
262
+    int resolve_targets(const list<sip_destination>& dest_list,
263
+			sip_target_set* targets);
254 264
 
255 265
     /**
256 266
      * Fills msg->remote_ip according to next_hop and next_port.
257 267
      */
258
-    int set_destination_ip(sip_msg* msg, cstring* next_hop, unsigned short next_port);    
268
+    int set_destination_ip(const cstring* next_hop, unsigned short next_port,
269
+			   sockaddr_storage* remote_ip, dns_handle* h_dns);
259 270
 
260 271
     sip_trans* copy_uac_trans(sip_trans* tr);
261 272