Browse code

Merge remote-tracking branch 'frafos/tcp-trsp' into 1.6-dev-ccdsm

* frafos/tcp-trsp: (55 commits)
sip: b/f: fix segfault in try_next_ip()
sip: fns: solved some memory management issues
sip: b/f: fix case-sensitivity issue for transport parameter
sip: b/f: added Content-Length-HF to non-200 ACK
sip: b/f: return immediately from parse_headers() if the input string is empty
sbc: b/f: correct fix for nat_handling flag support
Revert "b/f:core:dlg: reevaluate nat_handling flag after onSipRequest/onInvite"
sip: initialise sip_destination correctly
sip: b/f: avoid checking header type more than once in parse_headers()
b/f:core:dlg: reevaluate nat_handling flag after onSipRequest/onInvite
sip: c/f: fixed copy-paste error
sip: insert into blacklist only if default_bl_ttl != 0
sip: try next target on TCP immediate errors
sip: moved resolve_targets() to resolver
sip: moved sip_target_set to resolver
sip: patch temporary Contact-HFs instead of the given ones
core: fixed small issue when sending BYE on 2xx w/o to-tag
sip: tcp: small fixes to avoid libevent errors
core: set transport when updating next-hop
sip: tcp: hash only the sin[6]_addr to compute the tcp worker thread
...

Conflicts:
core/sip/resolver.cpp
core/sip/resolver.h
core/sip/sip_parser.h
core/sip/trans_layer.cpp
core/sip/trans_layer.h

Stefan Sayer authored on 20/01/2014 10:01:13
Showing 21 changed files
... ...
@@ -7,6 +7,8 @@
7 7
 #include "DSMStateDiagramCollection.h"
8 8
 #include "../apps/jsonrpc/JsonRPCEvents.h" // todo!
9 9
 #include "AmSipSubscription.h"
10
+#include "AmSessionContainer.h"
11
+#include "ampi/MonitoringAPI.h"
10 12
 
11 13
 SystemDSM::SystemDSM(const DSMScriptConfig& config,
12 14
 		     const string& startDiagName,
... ...
@@ -416,9 +416,6 @@ int RegisterDialog::initUAC(const AmSipRequest& req, const SBCCallProfile& cp)
416 416
   
417 417
   fixUacContactHosts(req,cp);
418 418
 
419
-  // patch initial CSeq to fix re-REGISTER with transparent-id enabled
420
-  cseq = req.cseq;
421
-
422 419
   return 0;
423 420
 }
424 421
 
... ...
@@ -831,7 +831,7 @@ void SBCCallLeg::onInvite(const AmSipRequest& req)
831 831
   }
832 832
   else if(call_profile.reg_caching) {
833 833
     // REG-Cache lookup
834
-    uac_req.r_uri = call_profile.retarget(req.user,*dlg);
834
+    uac_req.r_uri = call_profile.retarget(req.user);
835 835
   }
836 836
 
837 837
   ruri = call_profile.ruri.empty() ? uac_req.r_uri : call_profile.ruri;
... ...
@@ -1244,6 +1244,33 @@ void SBCCallProfile::fix_reg_contact(ParamReplacerCtx& ctx,
1244 1244
   }
1245 1245
 }
1246 1246
 
1247
+string SBCCallProfile::retarget(const string& alias)
1248
+{
1249
+    // REG-Cache lookup
1250
+    AliasEntry alias_entry;
1251
+    if(!RegisterCache::instance()->findAliasEntry(alias, alias_entry)) {
1252
+      throw AmSession::Exception(404,"User not found");
1253
+    }
1254
+    string new_r_uri = alias_entry.contact_uri;
1255
+    DBG("setting from registration cache: r_uri='%s'\n",new_r_uri.c_str());
1256
+
1257
+    // fix NAT
1258
+    string nh = alias_entry.source_ip;
1259
+    if(alias_entry.source_port != 5060)
1260
+      nh += ":" + int2str(alias_entry.source_port);
1261
+
1262
+    DBG("setting from registration cache: next_hop='%s'\n", nh.c_str());
1263
+    next_hop = nh;
1264
+
1265
+    // sticky interface
1266
+    DBG("setting from registration cache: outbound_interface='%s'\n",
1267
+	AmConfig::SIP_Ifs[alias_entry.local_if].name.c_str());
1268
+    outbound_interface = AmConfig::SIP_Ifs[alias_entry.local_if].name;
1269
+    outbound_interface_value = alias_entry.local_if;
1270
+
1271
+    return new_r_uri;
1272
+}
1273
+
1247 1274
 string SBCCallProfile::retarget(const string& alias, AmBasicSipDialog& dlg) const
1248 1275
 {
1249 1276
     // REG-Cache lookup
... ...
@@ -399,10 +399,18 @@ struct SBCCallProfile
399 399
   /**
400 400
    * Reg-cache lookup:
401 401
    * - searches for alias in the reg-cache.
402
-   * - sets next-hop & outbound_interface
402
+   * - sets next-hop & outbound_interface on the given dialog
403 403
    * @return retargeted R-URI
404 404
    */
405 405
   string retarget(const string& alias, AmBasicSipDialog& dlg) const;
406
+
407
+  /**
408
+   * Reg-cache lookup:
409
+   * - searches for alias in the reg-cache.
410
+   * - sets next-hop & outbound_interface in this profile
411
+   * @return retargeted R-URI
412
+   */
413
+  string retarget(const string& alias);
406 414
 };
407 415
 
408 416
 #endif // _SBCCallProfile_h
... ...
@@ -363,6 +363,7 @@ int SimpleRelayDialog::initUAC(const AmSipRequest& req,
363 363
 
364 364
   if(cp.transparent_dlg_id){
365 365
     setExtLocalTag(req.from_tag);
366
+    cseq = req.cseq;
366 367
   }
367 368
   else if(n_req.callid == req.callid)
368 369
     n_req.callid = AmSession::getNewId();
... ...
@@ -64,7 +64,7 @@ AmSipDialog::AmSipDialog(AmSipDialogEventHandler* h)
64 64
   : AmBasicSipDialog(h),oa(this),rel100(this,h),
65 65
     offeranswer_enabled(true),
66 66
     early_session_started(false),session_started(false),
67
-    pending_invites(0),cancel_pending(false),
67
+    pending_invites(0),
68 68
     sdp_local(), sdp_remote()
69 69
 {
70 70
 }
... ...
@@ -373,10 +373,6 @@ bool AmSipDialog::onRxReplyStatus(const AmSipReply& reply,
373 373
 	setStatus(Disconnected);
374 374
 	setRemoteTag(reply.to_tag);
375 375
       }
376
-      else if(cancel_pending){
377
-	cancel_pending = false;
378
-	bye();
379
-      }
380 376
       break;
381 377
 
382 378
     case Early:
... ...
@@ -717,14 +713,11 @@ int AmSipDialog::cancel()
717 713
 	t != uac_trans.rend(); t++) {
718 714
 	
719 715
 	if(t->second.method == SIP_METH_INVITE){
720
-	  
721
-	  if(getStatus() == Trying){
722
-	    cancel_pending=true;
723
-	    return 0;
724
-	  }
725
-	  else if(getStatus() != Cancelling){
716
+
717
+	  if(getStatus() != Cancelling){
726 718
 	    setStatus(Cancelling);
727
-	    return SipCtrlInterface::cancel(&t->second.tt,t->second.hdrs);
719
+	    return SipCtrlInterface::cancel(&t->second.tt, local_tag,
720
+					    t->first, t->second.hdrs);
728 721
 	  }
729 722
 	  else {
730 723
 	    ERROR("INVITE transaction has already been cancelled\n");
... ...
@@ -46,10 +46,6 @@ protected:
46 46
   // Number of open UAS INVITE transactions
47 47
   unsigned int pending_invites;
48 48
 
49
-  // In case a CANCEL should have been sent
50
-  // while in 'Trying' state
51
-  bool         cancel_pending;
52
-
53 49
   AmSdp   sdp_local;
54 50
   AmSdp   sdp_remote;
55 51
 
... ...
@@ -105,28 +101,6 @@ protected:
105 101
 
106 102
   void uasTimeout(AmSipTimeoutEvent* to_ev);
107 103
 
108
-  /** @return 0 on success (deprecated) */
109
-  // int reply(const AmSipRequest& req,
110
-  // 	    unsigned int  code, 
111
-  // 	    const string& reason,
112
-  // 	    const AmMimeBody* body = NULL,
113
-  // 	    const string& hdrs = "",
114
-  // 	    int flags = 0);
115
-
116
-  /** @return 0 on success */
117
-  // int reply(const AmSipTransaction& t,
118
-  // 	    unsigned int  code, 
119
-  // 	    const string& reason,
120
-  // 	    const AmMimeBody* body = NULL,
121
-  // 	    const string& hdrs = "",
122
-  // 	    int flags = 0);
123
-
124
-  /** @return 0 on success */
125
-  // int sendRequest(const string& method, 
126
-  // 		  const AmMimeBody* body = NULL,
127
-  // 		  const string& hdrs = "",
128
-  // 		  int flags = 0);
129
-
130 104
   /** @return 0 on success */
131 105
   int send_200_ack(unsigned int inv_cseq,
132 106
 		   const AmMimeBody* body = NULL,
... ...
@@ -259,9 +259,11 @@ _SipCtrlInterface::_SipCtrlInterface()
259 259
     trans_layer::instance()->register_ua(this);
260 260
 }
261 261
 
262
-int _SipCtrlInterface::cancel(trans_ticket* tt, const string& hdrs)
262
+int _SipCtrlInterface::cancel(trans_ticket* tt, const string& dialog_id,
263
+			      unsigned int inv_cseq, const string& hdrs)
263 264
 {
264
-    return trans_layer::instance()->cancel(tt,stl2cstr(hdrs));
265
+    return trans_layer::instance()->cancel(tt,stl2cstr(dialog_id),
266
+					   inv_cseq,stl2cstr(hdrs));
265 267
 }
266 268
 
267 269
 int _SipCtrlInterface::send(AmSipRequest &req, const string& dialog_id,
... ...
@@ -269,7 +271,7 @@ int _SipCtrlInterface::send(AmSipRequest &req, const string& dialog_id,
269 271
 			    unsigned int flags, msg_logger* logger)
270 272
 {
271 273
     if(req.method == "CANCEL")
272
-	return cancel(&req.tt, req.hdrs);
274
+	return cancel(&req.tt, dialog_id, req.cseq, req.hdrs);
273 275
 
274 276
     sip_msg* msg = new sip_msg();
275 277
     
... ...
@@ -122,7 +122,8 @@ public:
122 122
      *
123 123
      * @param tt transaction ticket of the request to cancel.
124 124
      */
125
-    static int cancel(trans_ticket* tt, const string& hdrs);
125
+    static int cancel(trans_ticket* tt, const string& dialog_id,
126
+		      unsigned int inv_cseq, const string& hdrs);
126 127
 
127 128
     /**
128 129
      * From sip_ua
... ...
@@ -166,10 +166,16 @@ inline int lower_cmp(const char* l, const char* r, int len)
166 166
     const char* end = l+len;
167 167
 
168 168
     while(l!=end){
169
-	if( LOWER_B(*l) != LOWER_B(*r) ){
169
+	if( LOWER_B(*l) == LOWER_B(*r) ){
170
+	    l++; r++;
171
+	    continue;
172
+	}
173
+	else if(LOWER_B(*l) < LOWER_B(*r)) {
174
+	    return -1;
175
+	}
176
+	else {
170 177
 	    return 1;
171 178
 	}
172
-	l++; r++;
173 179
     }
174 180
 
175 181
     return 0;
... ...
@@ -177,10 +183,12 @@ inline int lower_cmp(const char* l, const char* r, int len)
177 183
 
178 184
 inline int lower_cmp_n(const char* l, int llen, const char* r, int rlen)
179 185
 {
180
-    if(llen != rlen)
181
-	return 1;
186
+    if(llen == rlen)
187
+	return lower_cmp(l,r,rlen);
188
+    else if(llen < rlen)
189
+	return -1;
182 190
 
183
-    return lower_cmp(l,r,rlen);
191
+    return 1;
184 192
 }
185 193
 
186 194
 inline int lower_cmp_n(const cstring& l, const cstring& r)
... ...
@@ -11,23 +11,21 @@ int dns_skip_name(u_char** p, u_char* end);
11 11
 int dns_expand_name(u_char** ptr, u_char* begin, u_char* end, 
12 12
 		    u_char* buf, unsigned int len);
13 13
 
14
-inline unsigned short dns_get_16(u_char* p)
14
+
15
+const char* dns_rr_type_str(dns_rr_type t)
15 16
 {
16
-  unsigned short res = *(p++);
17
-  res <<= 8;
18
-  res |= *p;
19
-  
20
-  return res;
17
+  switch(t) {
18
+  case dns_r_a:     return "A";
19
+  case dns_r_ns:    return "NS";
20
+  case dns_r_cname: return "CNAME";
21
+  case dns_r_aaaa:  return "AAAA";
22
+  case dns_r_srv:   return "SRV";
23
+  case dns_r_naptr: return "NAPTR";
24
+  default:          return "UNKNOWN";
25
+  };
21 26
 }
22 27
 
23
-inline unsigned int dns_get_32(u_char* p)
24
-{
25
-  unsigned int res = dns_get_16(p);
26
-  res <<= 16;
27
-  res |= dns_get_16(p+2);
28 28
 
29
-  return res;
30
-}
31 29
 
32 30
 int dns_msg_parse(u_char* msg, int len, dns_parse_fct fct, void* data)
33 31
 {
... ...
@@ -2,6 +2,8 @@
2 2
 #define _parse_dns_h_
3 3
 
4 4
 #include <arpa/nameser.h>
5
+#include <arpa/inet.h>
6
+#include <stdint.h>
5 7
 
6 8
 enum dns_section_type {
7 9
 
... ...
@@ -18,9 +20,12 @@ enum dns_rr_type {
18 20
   dns_r_ns    = 2,
19 21
   dns_r_cname = 5,
20 22
   dns_r_aaaa  = 28,
21
-  dns_r_srv   = 33
23
+  dns_r_srv   = 33,
24
+  dns_r_naptr = 35
22 25
 };
23 26
 
27
+const char* dns_rr_type_str(dns_rr_type t);
28
+
24 29
 struct dns_record
25 30
 {
26 31
   char           name[NS_MAXDNAME];
... ...
@@ -40,4 +45,14 @@ int dns_msg_parse(u_char* msg, int len, dns_parse_fct fct, void* data);
40 45
 int dns_expand_name(u_char** ptr, u_char* begin, u_char* end, 
41 46
 		    u_char* buf, unsigned int len);
42 47
 
48
+inline uint16_t dns_get_16(const u_char* p)
49
+{
50
+  return ntohs(*(uint16_t*)p);
51
+}
52
+
53
+inline uint32_t dns_get_32(const u_char* p)
54
+{
55
+  return ntohl(*(uint32_t*)p);
56
+}
57
+
43 58
 #endif
... ...
@@ -35,6 +35,9 @@
35 35
 #include "ip_util.h"
36 36
 #include "trans_layer.h"
37 37
 #include "tr_blacklist.h"
38
+#include "wheeltimer.h"
39
+
40
+#include "AmUtils.h"
38 41
 
39 42
 #include <sys/socket.h> 
40 43
 #include <netdb.h>
... ...
@@ -45,9 +48,11 @@
45 48
 #include <arpa/nameser.h> 
46 49
 
47 50
 #include <list>
51
+#include <utility>
48 52
 #include <algorithm>
49 53
 
50 54
 using std::pair;
55
+using std::make_pair;
51 56
 using std::list;
52 57
 
53 58
 #include "log.h"
... ...
@@ -58,26 +63,12 @@ using std::list;
58 63
 // (the limit is the # bits in dns_handle::srv_used)
59 64
 #define MAX_SRV_RR (sizeof(unsigned int)*8)
60 65
 
61
-/* The SEMS_GET16 macro and the sems_get16 function were copied from glibc 2.7
62
- * (include/arpa/nameser.h (NS_GET16) and resolv/ns_netint.c (ns_get16)) to
63
- *  avoid using private glibc functions.
64
- */
65
-
66
-# define SEMS_GET16(s, cp)              \
67
-  do {                                  \
68
-    uint16_t *t_cp = (uint16_t *) (cp); \
69
-    (s) = ntohs (*t_cp);                \
70
-    (cp) += NS_INT16SZ;                 \
71
-} while (0)
72
-
73
-u_int
74
-sems_get16(const u_char *src)
75
-{
76
-       u_int dst;
66
+/* in seconds */
67
+#define DNS_CACHE_CYCLE 10L
77 68
 
78
-       SEMS_GET16(dst, src);
79
-       return (dst);
80
-}
69
+/* in us */
70
+#define DNS_CACHE_SINGLE_CYCLE \
71
+  ((DNS_CACHE_CYCLE*1000000L)/DNS_CACHE_SIZE)
81 72
 
82 73
 struct srv_entry
83 74
     : public dns_base_entry
... ...
@@ -87,6 +78,8 @@ struct srv_entry
87 78
 
88 79
     unsigned short port;
89 80
     string       target;
81
+
82
+    virtual string to_str();
90 83
 };
91 84
 
92 85
 int dns_ip_entry::next_ip(dns_handle* h, sockaddr_storage* sa)
... ...
@@ -94,6 +87,7 @@ int dns_ip_entry::next_ip(dns_handle* h, sockaddr_storage* sa)
94 87
     if(h->ip_e != this){
95 88
 	if(h->ip_e) dec_ref(h->ip_e);
96 89
 	h->ip_e = this;
90
+	inc_ref(this);
97 91
 	h->ip_n = 0;
98 92
     }
99 93
     
... ...
@@ -183,6 +177,7 @@ public:
183 177
 	if(h->srv_e != this){
184 178
 	    if(h->srv_e) dec_ref(h->srv_e);
185 179
 	    h->srv_e = this;
180
+	    inc_ref(this);
186 181
 	    h->srv_n = 0;
187 182
 	    h->srv_used = 0;
188 183
 	}
... ...
@@ -298,6 +293,7 @@ dns_entry::dns_entry()
298 293
 
299 294
 dns_entry::~dns_entry()
300 295
 {
296
+    DBG("dns_entry::~dns_entry(): %s",to_str().c_str());
301 297
     for(vector<dns_base_entry*>::iterator it = ip_vec.begin();
302 298
 	it != ip_vec.end(); ++it) {
303 299
 
... ...
@@ -305,14 +301,16 @@ dns_entry::~dns_entry()
305 301
     }
306 302
 }
307 303
 
308
-dns_entry* dns_entry::make_entry(ns_type t)
304
+dns_entry* dns_entry::make_entry(dns_rr_type t)
309 305
 {
310 306
     switch(t){
311
-    case ns_t_srv:
307
+    case dns_r_srv:
312 308
 	return new dns_srv_entry();
313
-    case ns_t_a:
314
-    //case ns_t_aaaa:
309
+    case dns_r_a:
310
+    //case dns_r_aaaa:
315 311
 	return new dns_ip_entry();
312
+    case dns_r_naptr:
313
+	return new dns_naptr_entry();
316 314
     default:
317 315
 	return NULL;
318 316
     }
... ...
@@ -330,6 +328,22 @@ void dns_entry::add_rr(dns_record* rr, u_char* begin, u_char* end, long now)
330 328
     ip_vec.push_back(e);
331 329
 }
332 330
 
331
+string dns_entry::to_str()
332
+{
333
+    string res;
334
+
335
+    for(vector<dns_base_entry*>::iterator it = ip_vec.begin();
336
+	it != ip_vec.end(); it++) {
337
+	
338
+	if(it != ip_vec.begin())
339
+	    res += ", ";
340
+
341
+	res += (*it)->to_str();
342
+    }
343
+
344
+    return "[" + res + "]";
345
+}
346
+
333 347
 dns_bucket::dns_bucket(unsigned long id) 
334 348
   : dns_bucket_base(id) 
335 349
 {
... ...
@@ -383,9 +397,8 @@ dns_entry* dns_bucket::find(const string& name)
383 397
 
384 398
     dns_entry* e = it->second;
385 399
 
386
-    timeval now;
387
-    gettimeofday(&now,NULL);
388
-    if(now.tv_sec >= e->expire){
400
+    u_int64_t now = wheeltimer::instance()->unix_clock.get();
401
+    if(now >= e->expire){
389 402
 	elmts.erase(it);
390 403
 	dec_ref(e);
391 404
 	unlock();
... ...
@@ -435,6 +448,22 @@ void ip_entry::to_sa(sockaddr_storage* sa)
435 448
     }
436 449
 }
437 450
 
451
+string ip_entry::to_str()
452
+{
453
+    if(type == IPv4) {
454
+	u_char* cp = (u_char*)&addr;
455
+	return int2str(cp[0]) + 
456
+	    "." + int2str(cp[1]) + 
457
+	    "." + int2str(cp[2]) + 
458
+	    "." + int2str(cp[3]);
459
+    }
460
+    else {
461
+	// not supported yet...
462
+	return "[IPv6]";
463
+    }
464
+}
465
+
466
+
438 467
 void ip_port_entry::to_sa(sockaddr_storage* sa)
439 468
 {
440 469
     switch(type){
... ...
@@ -462,6 +491,11 @@ void ip_port_entry::to_sa(sockaddr_storage* sa)
462 491
     }
463 492
 }
464 493
 
494
+string ip_port_entry::to_str()
495
+{
496
+    return ip_entry::to_str() + ":" + int2str(port);
497
+}
498
+
465 499
 dns_base_entry* dns_ip_entry::get_rr(dns_record* rr, u_char* begin, u_char* end)
466 500
 {
467 501
     if(rr->type != dns_r_a)
... ...
@@ -504,39 +538,63 @@ dns_base_entry* dns_srv_entry::get_rr(dns_record* rr, u_char* begin, u_char* end
504 538
     DBG("SRV:\tTTL=%i\t%s\tP=<%i> W=<%i> P=<%i> T=<%s>\n",
505 539
     	ns_rr_ttl(*rr),
506 540
     	ns_rr_name(*rr),
507
-    	sems_get16(rdata),
508
-    	sems_get16(rdata+2),
509
-    	sems_get16(rdata+4),
541
+    	dns_get_16(rdata),
542
+    	dns_get_16(rdata+2),
543
+    	dns_get_16(rdata+4),
510 544
     	name_buf);
511 545
     
512 546
     srv_entry* srv_r = new srv_entry();
513
-    srv_r->p = sems_get16(rdata);
514
-    srv_r->w = sems_get16(rdata+2);
515
-    srv_r->port = sems_get16(rdata+4);
547
+    srv_r->p = dns_get_16(rdata);
548
+    srv_r->w = dns_get_16(rdata+2);
549
+    srv_r->port = dns_get_16(rdata+4);
516 550
     srv_r->target = (const char*)name_buf;
517 551
 
518 552
     return srv_r;
519 553
 }
520 554
 
521
-struct dns_entry_h
555
+string srv_entry::to_str()
556
+{
557
+    return target + ":" + int2str(port)
558
+	+ "/" + int2str(p)
559
+	+ "/" + int2str(w);
560
+};
561
+
562
+struct dns_search_h
522 563
 {
523
-    dns_entry* e;
524
-    long     now;
564
+    dns_entry_map entry_map;
565
+    uint64_t      now;
566
+
567
+    dns_search_h() {
568
+	now = wheeltimer::instance()->unix_clock.get();
569
+    }
525 570
 };
526 571
 
527 572
 int rr_to_dns_entry(dns_record* rr, dns_section_type t,
528 573
 		    u_char* begin, u_char* end, void* data)
529 574
 {
530
-    dns_entry* dns_e = ((dns_entry_h*)data)->e;
531
-    long     now = ((dns_entry_h*)data)->now;
575
+    // only answer and additional sections
576
+    if(t != dns_s_an && t != dns_s_ar)
577
+	return 0;
532 578
 
533
-    if(t == dns_s_an)
534
-	dns_e->add_rr(rr,begin,end,now);
579
+    dns_search_h* h = (dns_search_h*)data;
580
+    string name = ns_rr_name(*rr);
535 581
 
536
-    // TODO: parse the additional section as well.
537
-    //       there might be some A/AAAA records related to
538
-    //       the SRV targets.
539
-    
582
+    dns_entry* dns_e = NULL;
583
+    dns_entry_map::iterator it = h->entry_map.find(name);
584
+
585
+    if(it == h->entry_map.end()) {
586
+	dns_e = dns_entry::make_entry((dns_rr_type)rr->type);
587
+	if(!dns_e) {
588
+	    // unsupported record type
589
+	    return 0;
590
+	}
591
+	h->entry_map.insert(name,dns_e);
592
+    }
593
+    else {
594
+	dns_e = it->second;
595
+    }
596
+
597
+    dns_e->add_rr(rr,begin,end,h->now);
540 598
     return 0;
541 599
 }
542 600
 
... ...
@@ -594,6 +652,79 @@ const dns_handle& dns_handle::operator = (const dns_handle& rh)
594 652
     return *this;
595 653
 }
596 654
 
655
+static bool naptr_less(const dns_base_entry* le, const dns_base_entry* re)
656
+{
657
+    const naptr_record* l_naptr = (const naptr_record*)le;
658
+    const naptr_record* r_naptr = (const naptr_record*)re;
659
+
660
+    if(l_naptr->order != r_naptr->order)
661
+	return l_naptr->order < r_naptr->order;
662
+    else
663
+	return l_naptr->pref < r_naptr->pref;
664
+}
665
+
666
+void dns_naptr_entry::init()
667
+{
668
+    stable_sort(ip_vec.begin(),ip_vec.end(),naptr_less);
669
+}
670
+
671
+dns_base_entry* dns_naptr_entry::get_rr(dns_record* rr, u_char* begin, u_char* end)
672
+{
673
+    enum NAPTR_FieldIndex {
674
+	NAPTR_Flags       = 0,
675
+	NAPTR_Services    = 1,
676
+	NAPTR_Regexp      = 2,
677
+	NAPTR_Replacement = 3,
678
+	NAPTR_Fields
679
+    };
680
+
681
+    if(rr->type != dns_r_naptr)
682
+	return NULL;
683
+
684
+    const u_char * rdata = ns_rr_rdata(*rr);
685
+
686
+    unsigned short order = dns_get_16(rdata);
687
+    rdata += 2;
688
+
689
+    unsigned short pref = dns_get_16(rdata);
690
+    rdata += 2;
691
+
692
+    cstring fields[NAPTR_Fields];
693
+
694
+    for(int i=0; i < NAPTR_Fields; i++) {
695
+
696
+	if(rdata > end) {
697
+	    ERROR("corrupted NAPTR record!!\n");
698
+	    return NULL;
699
+	}
700
+
701
+	fields[i].len = *(rdata++);
702
+	fields[i].s = (const char*)rdata;
703
+
704
+	rdata += fields[i].len;
705
+    }
706
+
707
+    printf("ENUM: TTL=%i P=<%i> W=<%i>"
708
+	   " FL=<%.*s> S=<%.*s>"
709
+	   " REG=<%.*s> REPL=<%.*s>\n",
710
+	   ns_rr_ttl(*rr),
711
+	   order, pref,
712
+	   fields[NAPTR_Flags].len,       fields[NAPTR_Flags].s,
713
+	   fields[NAPTR_Services].len,    fields[NAPTR_Services].s,
714
+	   fields[NAPTR_Regexp].len,      fields[NAPTR_Regexp].s,
715
+	   fields[NAPTR_Replacement].len, fields[NAPTR_Replacement].s);
716
+
717
+    naptr_record* naptr_r = new naptr_record();
718
+    naptr_r->order = order;
719
+    naptr_r->pref  = pref;
720
+    naptr_r->flags = c2stlstr(fields[NAPTR_Flags]);
721
+    naptr_r->services = c2stlstr(fields[NAPTR_Services]);
722
+    naptr_r->regexp = c2stlstr(fields[NAPTR_Regexp]);
723
+    naptr_r->replace = c2stlstr(fields[NAPTR_Replacement]);
724
+
725
+    return naptr_r;
726
+}
727
+
597 728
 sip_target::sip_target() {}
598 729
 
599 730
 sip_target::sip_target(const sip_target& target)
... ...
@@ -671,6 +802,45 @@ void sip_target_set::debug()
671 802
     }
672 803
 }
673 804
 
805
+dns_entry_map::dns_entry_map()
806
+    : map<string,dns_entry*>()
807
+{
808
+}
809
+
810
+dns_entry_map::~dns_entry_map()
811
+{
812
+    for(iterator it = begin(); it != end(); ++it) {
813
+	dec_ref(it->second);
814
+    }
815
+}
816
+
817
+std::pair<dns_entry_map::iterator, bool>
818
+dns_entry_map::insert(const dns_entry_map::value_type& x)
819
+{
820
+    return dns_entry_map_base::insert(x);
821
+}
822
+
823
+bool dns_entry_map::insert(const string& key, dns_entry* e)
824
+{
825
+    std::pair<iterator, bool> res =
826
+    	insert(make_pair<const key_type&,mapped_type>(key,e));
827
+
828
+    if(res.second) {
829
+	inc_ref(e);
830
+	return true;
831
+    }
832
+
833
+    return false;
834
+}
835
+
836
+dns_entry* dns_entry_map::fetch(const key_type& key)
837
+{
838
+    iterator it = find(key);
839
+    if(it != end())
840
+	return it->second;
841
+    return NULL;
842
+}
843
+
674 844
 bool _resolver::disable_srv = false;
675 845
 
676 846
 _resolver::_resolver()
... ...
@@ -684,47 +854,40 @@ _resolver::~_resolver()
684 854
     
685 855
 }
686 856
 
687
-int _resolver::query_dns(const char* name, dns_entry** e, long now)
857
+int _resolver::query_dns(const char* name, dns_entry_map& entry_map, dns_rr_type t)
688 858
 {
689 859
     u_char dns_res[NS_PACKETSZ];
690 860
 
691 861
     if(!name) return -1;
692 862
 
693
-    ns_type t = (name[0] == '_') ? ns_t_srv : ns_t_a;
694
-    
695
-    //TODO: add AAAA record support
696
-    int dns_res_len = res_search(name,ns_c_in,t,dns_res,NS_PACKETSZ);
863
+    DBG("Querying '%s' (%s)...",name,dns_rr_type_str(t));
864
+
865
+    int dns_res_len = res_search(name,ns_c_in,(ns_type)t,
866
+				 dns_res,NS_PACKETSZ);
697 867
     if(dns_res_len < 0){
698 868
 	dns_error(h_errno,name);
699 869
 	return -1;
700 870
     }
701 871
 
702
-    *e = dns_entry::make_entry(t);
703
-
704 872
     /*
705 873
      * Initialize a handle to this response.  The handle will
706 874
      * be used later to extract information from the response.
707 875
      */
708
-    dns_entry_h dns_h = { *e, now };
709
-    if (dns_msg_parse(dns_res, dns_res_len, rr_to_dns_entry, &dns_h) < 0) {
876
+    dns_search_h h;
877
+    if (dns_msg_parse(dns_res, dns_res_len, rr_to_dns_entry, &h) < 0) {
710 878
 	DBG("Could not parse DNS reply");
711 879
 	return -1;
712 880
     }
713
-    
714
-    *e = dns_h.e;
715
-    if(!*e) {
716
-	DBG("no dns_entry created");
717
-	return -1;
718
-    }
719 881
 
720
-    if((*e)->ip_vec.empty()){
721
-    	delete *e;
722
-    	*e = NULL;
723
-    	return -1;
724
-    }
882
+    for(dns_entry_map::iterator it = h.entry_map.begin();
883
+	it != h.entry_map.end(); it++) {
725 884
 
726
-    (*e)->init();
727
-    inc_ref(*e);
885
+	dns_entry* e = it->second;
886
+	if(!e || e->ip_vec.empty()) continue;
887
+
888
+	e->init();
889
+	entry_map.insert(it->first,e);
890
+    }
728 891
 
729 892
     return 0;
730 893
 }
... ...
@@ -732,7 +895,8 @@ int _resolver::query_dns(const char* name, dns_entry** e, long now)
732 895
 int _resolver::resolve_name(const char* name,
733 896
 			    dns_handle* h,
734 897
 			    sockaddr_storage* sa,
735
-			    const address_type types)
898
+			    const address_type types,
899
+			    dns_rr_type t)
736 900
 {
737 901
     int ret;
738 902
 
... ...
@@ -742,12 +906,16 @@ int _resolver::resolve_name(const char* name,
742 906
 	return h->next_ip(sa);
743 907
     }
744 908
 
745
-    // first try to detect if 'name' is already an IP address
746
-    ret = am_inet_pton(name,sa);
747
-    if(ret == 1) {
748
-	h->ip_n = -1; // flag end of IP list
749
-	h->srv_n = -1;
750
-	return 0; // 'name' is an IP address
909
+    if(t != dns_r_srv &&
910
+       t != dns_r_naptr) {
911
+
912
+	// first try to detect if 'name' is already an IP address
913
+	ret = am_inet_pton(name,sa);
914
+	if(ret == 1) {
915
+	    h->ip_n = -1; // flag end of IP list
916
+	    h->srv_n = -1;
917
+	    return 0; // 'name' is an IP address
918
+	}
751 919
     }
752 920
     
753 921
     // name is NOT an IP address -> try a cache look up
... ...
@@ -757,30 +925,38 @@ int _resolver::resolve_name(const char* name,
757 925
     // first attempt to get a valid IP
758 926
     // (from the cache)
759 927
     if(e){
760
-	return e->next_ip(h,sa);
928
+	int ret = e->next_ip(h,sa);
929
+	dec_ref(e);
930
+	return ret;
761 931
     }
762 932
 
763
-    timeval tv_now;
764
-    gettimeofday(&tv_now,NULL);
765
-
766 933
     // no valid IP, query the DNS
767
-    if(query_dns(name,&e,tv_now.tv_sec) < 0) {
934
+    dns_entry_map entry_map;
935
+    if(query_dns(name,entry_map,t) < 0) {
768 936
 	return -1;
769 937
     }
770 938
 
771
-    if(e) {
939
+    for(dns_entry_map::iterator it = entry_map.begin();
940
+	it != entry_map.end(); it++) {
941
+
942
+	if(!it->second) continue;
772 943
 
773
-	// if ttl != 0
774
-	if(e->expire != tv_now.tv_sec){
775
-	    // cache the new record
776
-	    b->insert(name,e);
944
+	b = cache.get_bucket(hashlittle(it->first.c_str(),
945
+					it->first.length(),0));
946
+	// cache the new record
947
+	if(b->insert(it->first,it->second)) {
948
+	    // cache insert successful
949
+	    DBG("new DNS cache entry: '%s' -> %s",
950
+		it->first.c_str(), it->second->to_str().c_str());
777 951
 	}
778
-    
952
+    }
953
+
954
+    e = entry_map.fetch(name);
955
+    if(e) {
779 956
 	// now we should have a valid IP
780 957
 	return e->next_ip(h,sa);
781 958
     }
782 959
 
783
-    // should not happen...
784 960
     return -1;
785 961
 }
786 962
 
... ...
@@ -856,7 +1032,7 @@ int _resolver::set_destination_ip(const cstring& next_hop,
856 1032
 
857 1033
 		if(!resolver::instance()->resolve_name(srv_name.c_str(),
858 1034
 						       h_dns,remote_ip,
859
-						       IPv4)){
1035
+						       IPv4,dns_r_srv)){
860 1036
 		    return 0;
861 1037
 		}
862 1038
 
... ...
@@ -926,42 +1102,47 @@ int _resolver::resolve_targets(const list<sip_destination>& dest_list,
926 1102
 
927 1103
 void _resolver::run()
928 1104
 {
929
-    for(;;) {
930
-	sleep(10);
1105
+    struct timespec tick,rem;
1106
+    tick.tv_sec  = (DNS_CACHE_SINGLE_CYCLE/1000000L);
1107
+    tick.tv_nsec = (DNS_CACHE_SINGLE_CYCLE - (tick.tv_sec)*1000000L) * 1000L;
931 1108
 
932
-	timeval tv_now;
933
-	gettimeofday(&tv_now,NULL);
1109
+    unsigned long i = 0;
1110
+    for(;;) {
1111
+	nanosleep(&tick,&rem);
934 1112
 
935
-	//DBG("starting DNS cache garbage collection");
936
-	for(unsigned long i=0; i<cache.get_size(); i++){
1113
+	u_int64_t now = wheeltimer::instance()->unix_clock.get();
1114
+	dns_bucket* bucket = cache.get_bucket(i);
937 1115
 
938
-	    dns_bucket* bucket = cache.get_bucket(i);
939
-	    bucket->lock();
1116
+	bucket->lock();
940 1117
 	    
941
-	    for(dns_bucket::value_map::iterator it = bucket->elmts.begin();
942
-		it != bucket->elmts.end(); ++it){
1118
+	for(dns_bucket::value_map::iterator it = bucket->elmts.begin();
1119
+	    it != bucket->elmts.end(); ++it){
943 1120
 
944
-		dns_entry* dns_e = (dns_entry*)it->second;
945
-		if(tv_now.tv_sec >= it->second->expire){
1121
+	    dns_entry* dns_e = (dns_entry*)it->second;
1122
+	    if(now >= it->second->expire){
946 1123
 
947
-		    dns_bucket::value_map::iterator tmp_it = it;
948
-		    bool end_of_bucket = (++it == bucket->elmts.end());
1124
+		dns_bucket::value_map::iterator tmp_it = it;
1125
+		bool end_of_bucket = (++it == bucket->elmts.end());
949 1126
 
950
-		    DBG("DNS record expired (%p)",dns_e);
951
-		    bucket->elmts.erase(tmp_it);
952
-		    dec_ref(dns_e);
1127
+		DBG("DNS record expired (%p)",dns_e);
1128
+		bucket->elmts.erase(tmp_it);
1129
+		dec_ref(dns_e);
953 1130
 
954
-		    if(end_of_bucket) break;
955
-		}
956
-		else {
957
-		    //DBG("######### record %p expires in %li seconds ##########",dns_e,it->second->expire-tv_now.tv_sec);
958
-		}
1131
+		if(end_of_bucket) break;
1132
+	    }
1133
+	    else {
1134
+		//DBG("######### record %p expires in %li seconds ##########",
1135
+		//    dns_e,it->second->expire-tv_now.tv_sec);
959 1136
 	    }
960
-	    bucket->unlock();
961 1137
 	}
1138
+
1139
+	bucket->unlock();
1140
+
1141
+	if(++i >= cache.get_size()) i = 0;
962 1142
     }
963 1143
 }
964 1144
 
1145
+
965 1146
 /** EMACS **
966 1147
  * Local variables:
967 1148
  * mode: c++
... ...
@@ -37,8 +37,10 @@
37 37
 
38 38
 #include <string>
39 39
 #include <vector>
40
+#include <map>
40 41
 using std::string;
41 42
 using std::vector;
43
+using std::map;
42 44
 
43 45
 #include <netinet/in.h>
44 46
 
... ...
@@ -61,13 +63,14 @@ struct dns_handle;
61 63
 
62 64
 struct dns_base_entry
63 65
 {
64
-    long int expire;
66
+    u_int64_t expire;
65 67
 
66 68
     dns_base_entry()
67 69
 	:expire(0)
68 70
     {}
69 71
 
70 72
     virtual ~dns_base_entry() {}
73
+    virtual string to_str() = 0;
71 74
 };
72 75
 
73 76
 class dns_entry
... ...
@@ -79,13 +82,15 @@ class dns_entry
79 82
 public:
80 83
     vector<dns_base_entry*> ip_vec;
81 84
 
82
-    static dns_entry* make_entry(ns_type t);
85
+    static dns_entry* make_entry(dns_rr_type t);
83 86
 
84 87
     dns_entry();
85 88
     virtual ~dns_entry();
86 89
     virtual void init()=0;
87 90
     virtual void add_rr(dns_record* rr, u_char* begin, u_char* end, long now);
88 91
     virtual int next_ip(dns_handle* h, sockaddr_storage* sa)=0;
92
+
93
+    virtual string to_str();
89 94
 };
90 95
 
91 96
 typedef ht_map_bucket<string,dns_entry> dns_bucket_base;
... ...
@@ -114,6 +119,7 @@ struct ip_entry
114 119
     };
115 120
 
116 121
     virtual void to_sa(sockaddr_storage* sa);
122
+    virtual string to_str();
117 123
 };
118 124
 
119 125
 struct ip_port_entry
... ...
@@ -122,6 +128,7 @@ struct ip_port_entry
122 128
     unsigned short port;
123 129
 
124 130
     virtual void to_sa(sockaddr_storage* sa);
131
+    virtual string to_str();
125 132
 };
126 133
 
127 134
 class dns_ip_entry
... ...
@@ -168,6 +175,36 @@ private:
168 175
     int            ip_n;
169 176
 };
170 177
 
178
+struct naptr_record
179
+    : public dns_base_entry
180
+{
181
+    unsigned short order;
182
+    unsigned short pref;
183
+
184
+    string flags;
185
+    string services;
186
+    string regexp;
187
+    string replace;
188
+
189
+    virtual string to_str() 
190
+    { return string(); }
191
+};
192
+
193
+class dns_naptr_entry
194
+    : public dns_entry
195
+{
196
+public:
197
+    dns_naptr_entry()
198
+	: dns_entry()
199
+    {}
200
+
201
+    void init();
202
+    dns_base_entry* get_rr(dns_record* rr, u_char* begin, u_char* end);
203
+
204
+    // not needed
205
+    int next_ip(dns_handle* h, sockaddr_storage* sa) { return -1; }
206
+};
207
+
171 208
 #define SIP_TRSP_SIZE_MAX 4
172 209
 
173 210
 struct sip_target
... ...
@@ -201,6 +238,24 @@ private:
201 238
     sip_target_set(const sip_target_set&) {}
202 239
 };
203 240
 
241
+typedef map<string,dns_entry*> dns_entry_map_base;
242
+
243
+class dns_entry_map
244
+     : public dns_entry_map_base
245
+{
246
+public:
247
+    dns_entry_map();
248
+    ~dns_entry_map();
249
+
250
+    bool insert(const key_type& key, mapped_type e);
251
+    dns_entry* fetch(const key_type& key);
252
+
253
+private:
254
+    // forbid some inherited methods
255
+    mapped_type& operator[](const key_type& k);
256
+    std::pair<iterator, bool> insert(const value_type& x);
257
+};
258
+
204 259
 class _resolver
205 260
     : AmThread
206 261
 {
... ...
@@ -211,12 +266,15 @@ public:
211 266
     int resolve_name(const char* name, 
212 267
 		     dns_handle* h,
213 268
 		     sockaddr_storage* sa,
214
-		     const address_type types);
269
+		     const address_type types,
270
+		     dns_rr_type t = dns_r_a);
215 271
 
216 272
     int str2ip(const char* name,
217 273
 	       sockaddr_storage* sa,
218 274
 	       const address_type types);
219 275
 
276
+    int query_dns(const char* name, dns_entry_map& entry_map, dns_rr_type t);
277
+
220 278
     /**
221 279
      * Transforms all elements of a destination list into
222 280
      * a target set, thus resolving all DNS names and
... ...
@@ -229,10 +287,6 @@ protected:
229 287
     _resolver();
230 288
     ~_resolver();
231 289
 
232
-    int query_dns(const char* name,
233
-		  dns_entry** e,
234
-		  long now);
235
-
236 290
     int set_destination_ip(const cstring& next_hop,
237 291
 			   unsigned short next_port,
238 292
 			   const cstring& next_trsp,
... ...
@@ -63,10 +63,7 @@ sip_msg::sip_msg(const char* msg_buf, int msg_len)
63 63
     u.request = 0;
64 64
     u.reply   = 0;
65 65
 
66
-    buf = new char[msg_len+1];
67
-    memcpy(buf,msg_buf,msg_len);
68
-    buf[msg_len] = '\0';
69
-    len = msg_len;
66
+    copy_msg_buf(msg_buf,msg_len);
70 67
 
71 68
     memset(&local_ip,0,sizeof(sockaddr_storage));
72 69
     memset(&remote_ip,0,sizeof(sockaddr_storage));
... ...
@@ -121,6 +118,14 @@ sip_msg::~sip_msg()
121 118
 	dec_ref(local_socket);
122 119
 }
123 120
 
121
+void sip_msg::copy_msg_buf(const char* msg_buf, int msg_len)
122
+{
123
+    buf = new char[msg_len+1];
124
+    memcpy(buf,msg_buf,msg_len);
125
+    buf[msg_len] = '\0';
126
+    len = msg_len;
127
+}
128
+
124 129
 void sip_msg::release()
125 130
 {
126 131
     buf = NULL;
... ...
@@ -141,6 +141,8 @@ struct sip_msg
141 141
     sip_msg(const char* msg_buf, int msg_len);
142 142
     ~sip_msg();
143 143
 
144
+    void copy_msg_buf(const char* msg_buf, int msg_len);
145
+
144 146
     int send(unsigned flags);
145 147
 
146 148
     /**
... ...
@@ -69,6 +69,12 @@
69 69
 bool _trans_layer::accept_fr_without_totag = false;
70 70
 unsigned int _trans_layer::default_bl_ttl = DEFAULT_BL_TTL;
71 71
 
72
+bool _trans_layer::less_case_i::operator () (const string& lhs, const string& rhs)
73
+{
74
+    return lower_cmp_n(lhs.c_str(),lhs.length(),
75
+		       rhs.c_str(),rhs.length()) < 0;
76
+}
77
+
72 78
 _trans_layer::_trans_layer()
73 79
     : ua(NULL),
74 80
       transports()
... ...
@@ -126,9 +132,19 @@ int _trans_layer::set_trsp_socket(sip_msg* msg, const cstring& next_trsp,
126 132
     prot_collection::iterator prot_sock_it =
127 133
 	transports[out_interface].find(c2stlstr(next_trsp));
128 134
 
129
-    // if we couldn't find anything, take whatever is there...
130 135
     if(prot_sock_it == transports[out_interface].end()) {
131
-	prot_sock_it = transports[out_interface].begin();
136
+
137
+	DBG("could not find transport '%.*s' in outbound interface %i",
138
+	    next_trsp.len,next_trsp.s,out_interface);
139
+
140
+	prot_sock_it = transports[out_interface].find("udp");
141
+	
142
+	// if we couldn't find anything, take whatever is there...
143
+	if(prot_sock_it == transports[out_interface].end()) {
144
+	    DBG("could not find transport 'udp' in outbound interface %i",
145
+		out_interface);
146
+	    prot_sock_it = transports[out_interface].begin();
147
+	}
132 148
     }
133 149
 
134 150
     if(msg->local_socket) dec_ref(msg->local_socket);
... ...
@@ -981,14 +997,14 @@ void _trans_layer::transport_error(sip_msg* msg)
981 997
 }
982 998
 
983 999
 static void translate_string(sip_msg* dst_msg, cstring& dst,
984
-			     sip_msg* src_msg, cstring& src)
1000
+			     const sip_msg* src_msg, const cstring& src)
985 1001
 {
986 1002
     dst.s = (char*)src.s + (dst_msg->buf - src_msg->buf);
987 1003
     dst.len = src.len;
988 1004
 }
989 1005
 
990 1006
 static void translate_hdr(sip_msg* dst_msg, sip_header*& dst, 
991
-			  sip_msg* src_msg, sip_header* src)
1007
+			  const sip_msg* src_msg, const sip_header* src)
992 1008
 {
993 1009
     dst = new sip_header();
994 1010
     dst_msg->hdrs.push_back(dst);
... ...
@@ -998,37 +1014,43 @@ static void translate_hdr(sip_msg* dst_msg, sip_header*& dst,
998 1014
     dst->p = NULL;
999 1015
 }
1000 1016
 
1001
-void _trans_layer::timeout(trans_bucket* bucket, sip_trans* t)
1017
+static void gen_error_reply_from_req(sip_msg& reply, const sip_msg* req,
1018
+				     int code, const char* reason)
1002 1019
 {
1003
-    t->reset_all_timers();
1004
-    t->state = TS_TERMINATED;
1020
+    reply.copy_msg_buf(req->buf,req->len);
1005 1021
 
1006
-    // send 408 to 'ua'
1007
-    sip_msg* req = t->msg;
1008
-    sip_msg  msg(req->buf,req->len);
1022
+    reply.type = SIP_REPLY;
1023
+    reply.u.reply = new sip_reply();
1024
+
1025
+    reply.u.reply->code = code;
1026
+    reply.u.reply->reason = cstring(reason);
1009 1027
 
1010
-    msg.type = SIP_REPLY;
1011
-    msg.u.reply = new sip_reply();
1028
+    translate_hdr(&reply,reply.from, req,req->from);
1029
+    reply.from->p = new sip_from_to();
1030
+    parse_from_to((sip_from_to*)reply.from->p,
1031
+		  reply.from->value.s,reply.from->value.len);
1012 1032
 
1013
-    msg.u.reply->code = 408;
1014
-    msg.u.reply->reason = cstring("Timeout");
1033
+    translate_hdr(&reply,reply.to, req,req->to);
1034
+    reply.to->p = new sip_from_to();
1035
+    parse_from_to((sip_from_to*)reply.to->p,
1036
+		  reply.to->value.s,reply.to->value.len);
1015 1037
 
1016
-    translate_hdr(&msg,msg.from, req,req->from);
1017
-    msg.from->p = new sip_from_to();
1018
-    parse_from_to((sip_from_to*)msg.from->p,
1019
-		  msg.from->value.s,msg.from->value.len);
1038
+    translate_hdr(&reply,reply.cseq, req,req->cseq);
1039
+    reply.cseq->p = new sip_cseq();
1040
+    parse_cseq((sip_cseq*)reply.cseq->p,
1041
+	       reply.cseq->value.s,reply.cseq->value.len);
1020 1042
 
1021
-    translate_hdr(&msg,msg.to, req,req->to);
1022
-    msg.to->p = new sip_from_to();
1023
-    parse_from_to((sip_from_to*)msg.to->p,
1024
-		  msg.to->value.s,msg.to->value.len);
1043
+    translate_hdr(&reply,reply.callid, req,req->callid);
1044
+}
1025 1045
 
1026
-    translate_hdr(&msg,msg.cseq, req,req->cseq);
1027
-    msg.cseq->p = new sip_cseq();
1028
-    parse_cseq((sip_cseq*)msg.cseq->p,
1029
-	       msg.cseq->value.s,msg.cseq->value.len);
1046
+void _trans_layer::timeout(trans_bucket* bucket, sip_trans* t)
1047
+{
1048
+    t->reset_all_timers();
1049
+    t->state = TS_TERMINATED;
1030 1050
 
1031
-    translate_hdr(&msg,msg.callid, req,req->callid);
1051
+    // send 408 to 'ua'
1052
+    sip_msg reply;
1053
+    gen_error_reply_from_req(reply,t->msg,408,"Timeout");
1032 1054
 
1033 1055
     string dialog_id(t->dialog_id.s,t->dialog_id.len);
1034 1056
 
... ...
@@ -1041,7 +1063,7 @@ void _trans_layer::timeout(trans_bucket* bucket, sip_trans* t)
1041 1063
     }
1042 1064
     bucket->unlock();
1043 1065
 
1044
-    ua->handle_sip_reply(dialog_id,&msg);
1066
+    ua->handle_sip_reply(dialog_id,&reply);
1045 1067
 }
1046 1068
 
1047 1069
 static int patch_ruri_with_remote_ip(string& n_uri, sip_msg* msg)
... ...
@@ -1364,7 +1386,8 @@ int _trans_layer::send_request(sip_msg* msg, trans_ticket* tt,
1364 1386
     return err;
1365 1387
 }
1366 1388
 
1367
-int _trans_layer::cancel(trans_ticket* tt, const cstring& hdrs)
1389
+int _trans_layer::cancel(trans_ticket* tt, const cstring& dialog_id,
1390
+			 unsigned int inv_cseq, const cstring& hdrs)
1368 1391
 {
1369 1392
     assert(tt);
1370 1393
     assert(tt->_bucket && tt->_t);
... ...
@@ -1373,7 +1396,14 @@ int _trans_layer::cancel(trans_ticket* tt, const cstring& hdrs)
1373 1396
     sip_trans*    t = tt->_t;
1374 1397
 
1375 1398
     bucket->lock();
1376
-    if(!bucket->exist(t)){
1399
+    if(!bucket->exist(t) || (t->state == TS_ABANDONED)){
1400
+	if(dialog_id.len)
1401
+	    t = bucket->find_uac_trans(dialog_id,inv_cseq);
1402
+	else
1403
+	    t = NULL;
1404
+    }
1405
+
1406
+    if(!t){
1377 1407
 	DBG("No transaction to cancel: wrong key or finally replied\n");
1378 1408
 	bucket->unlock();
1379 1409
 	return 0;
... ...
@@ -1390,10 +1420,21 @@ int _trans_layer::cancel(trans_ticket* tt, const cstring& hdrs)
1390 1420
     }
1391 1421
     
1392 1422
     switch(t->state){
1393
-    case TS_CALLING:
1423
+    case TS_CALLING: {
1424
+	// Abandon canceled transaction
1425
+	t->clear_timer(STIMER_A);
1426
+	t->clear_timer(STIMER_M);
1427
+	t->flags |= TR_FLAG_DISABLE_BL;
1428
+	t->state = TS_ABANDONED;
1429
+
1430
+	// Answer request internally to terminate the dialog...
1431
+	sip_msg reply;
1432
+	gen_error_reply_from_req(reply, t->msg, 487, "Request Terminated");
1433
+	string dlg_id(t->dialog_id.s, t->dialog_id.len);
1394 1434
 	bucket->unlock();
1395
-	ERROR("Trying to cancel a request while in TS_CALLING state.\n");
1396
-	return -1;
1435
+	ua->handle_sip_reply(dlg_id, &reply);
1436
+	return 0;
1437
+    }
1397 1438
 
1398 1439
     case TS_COMPLETED:
1399 1440
 	bucket->unlock();
... ...
@@ -1747,15 +1788,15 @@ int _trans_layer::update_uac_reply(trans_bucket* bucket, sip_trans* t, sip_msg*
1747 1788
 
1748 1789
 	case TS_ABANDONED:
1749 1790
 	    // disable blacklisting: remote UA did reply
1750
-	    INFO("disable blacklisting: remote UA (%s/%i) did reply",
1751
-		 am_inet_ntop(&msg->remote_ip).c_str(),
1752
-		 am_get_port(&msg->remote_ip));
1791
+	    DBG("disable blacklisting: remote UA (%s/%i) did reply",
1792
+		am_inet_ntop(&msg->remote_ip).c_str(),
1793
+		am_get_port(&msg->remote_ip));
1753 1794
 	    t->flags |= TR_FLAG_DISABLE_BL;
1754 1795
 	    bucket->unlock();
1755 1796
 	    {
1756 1797
 		// send CANCEL
1757 1798
 		trans_ticket tt(t,bucket);
1758
-		cancel(&tt,cstring());
1799
+		cancel(&tt,cstring(),0,cstring());
1759 1800
 	    
1760 1801
 		// Now remove the transaction
1761 1802
 		bucket->lock();
... ...
@@ -1765,9 +1806,9 @@ int _trans_layer::update_uac_reply(trans_bucket* bucket, sip_trans* t, sip_msg*
1765 1806
 
1766 1807
 	case TS_TERMINATED:
1767 1808
 	    // disable blacklisting: remote UA did reply
1768
-	    INFO("disable blacklisting: remote UA (%s/%i) did reply",
1769
-		 am_inet_ntop(&msg->remote_ip).c_str(),
1770
-		 am_get_port(&msg->remote_ip));
1809
+	    DBG("disable blacklisting: remote UA (%s/%i) did reply",
1810
+		am_inet_ntop(&msg->remote_ip).c_str(),
1811
+		am_get_port(&msg->remote_ip));
1771 1812
 	    t->flags |= TR_FLAG_DISABLE_BL;
1772 1813
 	    goto end;
1773 1814
 
... ...
@@ -1821,10 +1862,17 @@ int _trans_layer::update_uac_reply(trans_bucket* bucket, sip_trans* t, sip_msg*
1821 1862
 		
1822 1863
 	    case TS_ABANDONED:
1823 1864
 	    case TS_TERMINATED:
1865
+		// local reply: do not send an ACK in this case
1866
+		if(!msg->local_socket) {
1867
+		    t->reset_all_timers();
1868
+		    bucket->remove(t);
1869
+		    goto end;
1870
+		}
1871
+
1824 1872
 		// disable blacklisting: remote UA did reply
1825
-		INFO("disable blacklisting: remote UA (%s/%i) did reply",
1826
-		     am_inet_ntop(&msg->remote_ip).c_str(),
1827
-		     am_get_port(&msg->remote_ip));
1873
+		DBG("disable blacklisting: remote UA (%s/%i) did reply",
1874
+		    am_inet_ntop(&msg->remote_ip).c_str(),
1875
+		    am_get_port(&msg->remote_ip));
1828 1876
 
1829 1877
 		t->flags |= TR_FLAG_DISABLE_BL;
1830 1878
 		// fall through trap
... ...
@@ -1898,9 +1946,9 @@ int _trans_layer::update_uac_reply(trans_bucket* bucket, sip_trans* t, sip_msg*
1898 1946
 	    case TS_ABANDONED:
1899 1947
 	    case TS_TERMINATED:
1900 1948
 		//TODO: send ACK+BYE
1901
-		INFO("disable blacklisting: remote UA (%s/%i) did reply",
1902
-		     am_inet_ntop(&msg->remote_ip).c_str(),
1903
-		     am_get_port(&msg->remote_ip));
1949
+		DBG("disable blacklisting: remote UA (%s/%i) did reply",
1950
+		    am_inet_ntop(&msg->remote_ip).c_str(),
1951
+		    am_get_port(&msg->remote_ip));
1904 1952
 		t->flags |= TR_FLAG_DISABLE_BL;
1905 1953
 		goto end;
1906 1954
 
... ...
@@ -1955,6 +2003,15 @@ int _trans_layer::update_uac_reply(trans_bucket* bucket, sip_trans* t, sip_msg*
1955 2003
 	    
1956 2004
 	case TS_ABANDONED:
1957 2005
 	case TS_TERMINATED:
2006
+	    //local reply
2007
+	    if(!msg->local_socket) {
2008
+		if(reply_code == 500 || reply_code == 503) {
2009
+		    // no more replies will come...
2010
+		    bucket->remove(t);
2011
+		}
2012
+		goto end;
2013
+	    }
2014
+
1958 2015
 	    INFO("disable blacklisting: remote UA (%s/%i) did reply",
1959 2016
 		 am_inet_ntop(&msg->remote_ip).c_str(),
1960 2017
 		 am_get_port(&msg->remote_ip));
... ...
@@ -1972,7 +2029,8 @@ int _trans_layer::update_uac_reply(trans_bucket* bucket, sip_trans* t, sip_msg*
1972 2029
     return 0;
1973 2030
 }
1974 2031
 
1975
-int _trans_layer::update_uac_request(trans_bucket* bucket, sip_trans*& t, sip_msg* msg)
2032
+int _trans_layer::update_uac_request(trans_bucket* bucket, sip_trans*& t,
2033
+				     sip_msg* msg)
1976 2034
 {
1977 2035
     if(msg->u.request->method != sip_request::ACK){
1978 2036
 	t = bucket->add_trans(msg,TT_UAC);
... ...
@@ -2178,10 +2236,14 @@ void _trans_layer::send_non_200_ack(sip_msg* reply, sip_trans* t)
2178 2236
 	+ copy_hdr_len(inv->callid);
2179 2237
     
2180 2238
     ack_len += cseq_len(get_cseq(inv)->num_str,method);
2181
-    ack_len += 2/* EoH CRLF */;
2182 2239
 
2183 2240
     if(!inv->route.empty())
2184 2241
  	ack_len += copy_hdrs_len(inv->route);
2242
+
2243
+    cstring content_len("0");
2244
+    ack_len += content_length_len(content_len);
2245
+
2246
+    ack_len += 2/* EoH CRLF */;
2185 2247
     
2186 2248
     char* ack_buf = new char [ack_len];
2187 2249
     char* c = ack_buf;
... ...
@@ -2190,14 +2252,16 @@ void _trans_layer::send_non_200_ack(sip_msg* reply, sip_trans* t)
2190 2252
     
2191 2253
     copy_hdr_wr(&c,inv->via1);
2192 2254
 
2193
-    if(!inv->route.empty())
2194
-	 copy_hdrs_wr(&c,inv->route);
2195
-
2196 2255
     copy_hdr_wr(&c,inv->from);
2197 2256
     copy_hdr_wr(&c,reply->to);
2198 2257
     copy_hdr_wr(&c,inv->callid);
2199 2258
     
2200 2259
     cseq_wr(&c,get_cseq(inv)->num_str,method);
2260
+
2261
+    if(!inv->route.empty())
2262
+	 copy_hdrs_wr(&c,inv->route);
2263
+
2264
+    content_length_wr(&c,content_len);
2201 2265
     
2202 2266
     *c++ = CR;
2203 2267
     *c++ = LF;
... ...
@@ -2278,13 +2342,12 @@ void _trans_layer::timer_expired(trans_timer* t, trans_bucket* bucket,
2278 2342
 	tr->clear_timer(STIMER_C);
2279 2343
 	//if(tr->state != TS_PROCEEDING)
2280 2344
 	//  break; // shouldn't happen
2281
-
2282 2345
 	bucket->unlock();
2283 2346
 
2284 2347
 	{
2285 2348
 	    // send CANCEL
2286 2349
 	    trans_ticket tt(tr,bucket);
2287
-	    cancel(&tt,cstring());
2350
+	    cancel(&tt,cstring(),0,cstring());
2288 2351
 	    
2289 2352
 	    // Now remove the transaction
2290