Browse code

sip: kill UAC transactions on cancel() even if no reply has been received yet.

In case no reply has been received yet, the stack would have only flagged the desire to cancel the transaction, but not stopped the UAC transaction, thus causing unneeded retransmissions.

Raphael Coeffic authored on 17/12/2013 15:27:46
Showing 5 changed files
... ...
@@ -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
 }
... ...
@@ -372,10 +372,6 @@ bool AmSipDialog::onRxReplyStatus(const AmSipReply& reply,
372 372
 	setStatus(Disconnected);
373 373
 	setRemoteTag(reply.to_tag);
374 374
       }
375
-      else if(cancel_pending){
376
-	cancel_pending = false;
377
-	bye();
378
-      }
379 375
       break;
380 376
 
381 377
     case Early:
... ...
@@ -712,12 +708,8 @@ int AmSipDialog::cancel()
712 708
 	t != uac_trans.rend(); t++) {
713 709
 	
714 710
 	if(t->second.method == SIP_METH_INVITE){
715
-	  
716
-	  if(getStatus() == Trying){
717
-	    cancel_pending=true;
718
-	    return 0;
719
-	  }
720
-	  else if(getStatus() != Cancelling){
711
+
712
+	  if(getStatus() != Cancelling){
721 713
 	    setStatus(Cancelling);
722 714
 	    return SipCtrlInterface::cancel(&t->second.tt, local_tag,
723 715
 					    t->first, t->second.hdrs);
... ...
@@ -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
 
... ...
@@ -103,28 +99,6 @@ protected:
103 99
 
104 100
   void uasTimeout(AmSipTimeoutEvent* to_ev);
105 101
 
106
-  /** @return 0 on success (deprecated) */
107
-  // int reply(const AmSipRequest& req,
108
-  // 	    unsigned int  code, 
109
-  // 	    const string& reason,
110
-  // 	    const AmMimeBody* body = NULL,
111
-  // 	    const string& hdrs = "",
112
-  // 	    int flags = 0);
113
-
114
-  /** @return 0 on success */
115
-  // int reply(const AmSipTransaction& t,
116
-  // 	    unsigned int  code, 
117
-  // 	    const string& reason,
118
-  // 	    const AmMimeBody* body = NULL,
119
-  // 	    const string& hdrs = "",
120
-  // 	    int flags = 0);
121
-
122
-  /** @return 0 on success */
123
-  // int sendRequest(const string& method, 
124
-  // 		  const AmMimeBody* body = NULL,
125
-  // 		  const string& hdrs = "",
126
-  // 		  int flags = 0);
127
-
128 102
   /** @return 0 on success */
129 103
   int send_200_ack(unsigned int inv_cseq,
130 104
 		   const AmMimeBody* body = NULL,
... ...
@@ -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;
... ...
@@ -138,6 +138,8 @@ struct sip_msg
138 138
     sip_msg(const char* msg_buf, int msg_len);
139 139
     ~sip_msg();
140 140
 
141
+    void copy_msg_buf(const char* msg_buf, int msg_len);
142
+
141 143
     int send();
142 144
 
143 145
     /**
... ...
@@ -834,14 +834,14 @@ int _trans_layer::set_destination_ip(sip_msg* msg, cstring* next_hop,
834 834
 }
835 835
 
836 836
 static void translate_string(sip_msg* dst_msg, cstring& dst,
837
-			     sip_msg* src_msg, cstring& src)
837
+			     const sip_msg* src_msg, const cstring& src)
838 838
 {
839 839
     dst.s = (char*)src.s + (dst_msg->buf - src_msg->buf);
840 840
     dst.len = src.len;
841 841
 }
842 842
 
843 843
 static void translate_hdr(sip_msg* dst_msg, sip_header*& dst, 
844
-			  sip_msg* src_msg, sip_header* src)
844
+			  const sip_msg* src_msg, const sip_header* src)
845 845
 {
846 846
     dst = new sip_header();
847 847
     dst_msg->hdrs.push_back(dst);
... ...
@@ -851,37 +851,43 @@ static void translate_hdr(sip_msg* dst_msg, sip_header*& dst,
851 851
     dst->p = NULL;
852 852
 }
853 853
 
854
-void _trans_layer::timeout(trans_bucket* bucket, sip_trans* t)
854
+static void gen_error_reply_from_req(sip_msg& reply, const sip_msg* req,
855
+				     int code, const char* reason)
855 856
 {
856
-    t->reset_all_timers();
857
-    t->state = TS_TERMINATED;
857
+    reply.copy_msg_buf(req->buf,req->len);
858 858
 
859
-    // send 408 to 'ua'
860
-    sip_msg* req = t->msg;
861
-    sip_msg  msg(req->buf,req->len);
859
+    reply.type = SIP_REPLY;
860
+    reply.u.reply = new sip_reply();
862 861
 
863
-    msg.type = SIP_REPLY;
864
-    msg.u.reply = new sip_reply();
862
+    reply.u.reply->code = code;
863
+    reply.u.reply->reason = cstring(reason);
865 864
 
866
-    msg.u.reply->code = 408;
867
-    msg.u.reply->reason = cstring("Timeout");
865
+    translate_hdr(&reply,reply.from, req,req->from);
866
+    reply.from->p = new sip_from_to();
867
+    parse_from_to((sip_from_to*)reply.from->p,
868
+		  reply.from->value.s,reply.from->value.len);
868 869
 
869
-    translate_hdr(&msg,msg.from, req,req->from);
870
-    msg.from->p = new sip_from_to();
871
-    parse_from_to((sip_from_to*)msg.from->p,
872
-		  msg.from->value.s,msg.from->value.len);
870
+    translate_hdr(&reply,reply.to, req,req->to);
871
+    reply.to->p = new sip_from_to();
872
+    parse_from_to((sip_from_to*)reply.to->p,
873
+		  reply.to->value.s,reply.to->value.len);
873 874
 
874
-    translate_hdr(&msg,msg.to, req,req->to);
875
-    msg.to->p = new sip_from_to();
876
-    parse_from_to((sip_from_to*)msg.to->p,
877
-		  msg.to->value.s,msg.to->value.len);
875
+    translate_hdr(&reply,reply.cseq, req,req->cseq);
876
+    reply.cseq->p = new sip_cseq();
877
+    parse_cseq((sip_cseq*)reply.cseq->p,
878
+	       reply.cseq->value.s,reply.cseq->value.len);
878 879
 
879
-    translate_hdr(&msg,msg.cseq, req,req->cseq);
880
-    msg.cseq->p = new sip_cseq();
881
-    parse_cseq((sip_cseq*)msg.cseq->p,
882
-	       msg.cseq->value.s,msg.cseq->value.len);
880
+    translate_hdr(&reply,reply.callid, req,req->callid);
881
+}
883 882
 
884
-    translate_hdr(&msg,msg.callid, req,req->callid);
883
+void _trans_layer::timeout(trans_bucket* bucket, sip_trans* t)
884
+{
885
+    t->reset_all_timers();
886
+    t->state = TS_TERMINATED;
887
+
888
+    // send 408 to 'ua'
889
+    sip_msg reply;
890
+    gen_error_reply_from_req(reply,t->msg,408,"Timeout");
885 891
 
886 892
     string dialog_id(t->dialog_id.s,t->dialog_id.len);
887 893
 
... ...
@@ -894,7 +900,7 @@ void _trans_layer::timeout(trans_bucket* bucket, sip_trans* t)
894 900
     }
895 901
     bucket->unlock();
896 902
 
897
-    ua->handle_sip_reply(dialog_id,&msg);
903
+    ua->handle_sip_reply(dialog_id,&reply);
898 904
 }
899 905
 
900 906
 static int patch_ruri_with_remote_ip(string& n_uri, sip_msg* msg)
... ...
@@ -1290,10 +1296,21 @@ int _trans_layer::cancel(trans_ticket* tt, const cstring& dialog_id,
1290 1296
     }
1291 1297
     
1292 1298
     switch(t->state){
1293
-    case TS_CALLING:
1299
+    case TS_CALLING: {
1300
+	// Abandon canceled transaction
1301
+	t->clear_timer(STIMER_A);
1302
+	t->clear_timer(STIMER_M);
1303
+	t->flags |= TR_FLAG_DISABLE_BL;
1304
+	t->state = TS_ABANDONED;
1305
+
1306
+	// Answer request internally to terminate the dialog...
1307
+	sip_msg reply;
1308
+	gen_error_reply_from_req(reply, t->msg, 487, "Request Terminated");
1309
+	string dlg_id(t->dialog_id.s, t->dialog_id.len);
1294 1310
 	bucket->unlock();
1295
-	ERROR("Trying to cancel a request while in TS_CALLING state.\n");
1296
-	return -1;
1311
+	ua->handle_sip_reply(dlg_id, &reply);
1312
+	return 0;
1313
+    }
1297 1314
 
1298 1315
     case TS_COMPLETED:
1299 1316
 	bucket->unlock();
... ...
@@ -1645,9 +1662,9 @@ int _trans_layer::update_uac_reply(trans_bucket* bucket, sip_trans* t, sip_msg*
1645 1662
 
1646 1663
 	case TS_ABANDONED:
1647 1664
 	    // disable blacklisting: remote UA did reply
1648
-	    INFO("disable blacklisting: remote UA (%s/%i) did reply",
1649
-		 am_inet_ntop(&msg->remote_ip).c_str(),
1650
-		 am_get_port(&msg->remote_ip));
1665
+	    DBG("disable blacklisting: remote UA (%s/%i) did reply",
1666
+		am_inet_ntop(&msg->remote_ip).c_str(),
1667
+		am_get_port(&msg->remote_ip));
1651 1668
 	    t->flags |= TR_FLAG_DISABLE_BL;
1652 1669
 	    bucket->unlock();
1653 1670
 	    {
... ...
@@ -1663,9 +1680,9 @@ int _trans_layer::update_uac_reply(trans_bucket* bucket, sip_trans* t, sip_msg*
1663 1680
 
1664 1681
 	case TS_TERMINATED:
1665 1682
 	    // disable blacklisting: remote UA did reply
1666
-	    INFO("disable blacklisting: remote UA (%s/%i) did reply",
1667
-		 am_inet_ntop(&msg->remote_ip).c_str(),
1668
-		 am_get_port(&msg->remote_ip));
1683
+	    DBG("disable blacklisting: remote UA (%s/%i) did reply",
1684
+		am_inet_ntop(&msg->remote_ip).c_str(),
1685
+		am_get_port(&msg->remote_ip));
1669 1686
 	    t->flags |= TR_FLAG_DISABLE_BL;
1670 1687
 	    goto end;
1671 1688
 
... ...
@@ -1718,9 +1735,9 @@ int _trans_layer::update_uac_reply(trans_bucket* bucket, sip_trans* t, sip_msg*
1718 1735
 	    case TS_ABANDONED:
1719 1736
 	    case TS_TERMINATED:
1720 1737
 		// disable blacklisting: remote UA did reply
1721
-		INFO("disable blacklisting: remote UA (%s/%i) did reply",
1722
-		     am_inet_ntop(&msg->remote_ip).c_str(),
1723
-		     am_get_port(&msg->remote_ip));
1738
+		DBG("disable blacklisting: remote UA (%s/%i) did reply",
1739
+		    am_inet_ntop(&msg->remote_ip).c_str(),
1740
+		    am_get_port(&msg->remote_ip));
1724 1741
 
1725 1742
 		t->flags |= TR_FLAG_DISABLE_BL;
1726 1743
 		// fall through trap
... ...
@@ -1794,9 +1811,9 @@ int _trans_layer::update_uac_reply(trans_bucket* bucket, sip_trans* t, sip_msg*
1794 1811
 	    case TS_ABANDONED:
1795 1812
 	    case TS_TERMINATED:
1796 1813
 		//TODO: send ACK+BYE
1797
-		INFO("disable blacklisting: remote UA (%s/%i) did reply",
1798
-		     am_inet_ntop(&msg->remote_ip).c_str(),
1799
-		     am_get_port(&msg->remote_ip));
1814
+		DBG("disable blacklisting: remote UA (%s/%i) did reply",
1815
+		    am_inet_ntop(&msg->remote_ip).c_str(),
1816
+		    am_get_port(&msg->remote_ip));
1800 1817
 		t->flags |= TR_FLAG_DISABLE_BL;
1801 1818
 		goto end;
1802 1819