Browse code

sip: allow for alternative dialog-id when posting event for received replies

Raphael Coeffic authored on 16/10/2012 10:51:04
Showing 9 changed files
... ...
@@ -40,11 +40,12 @@ AmSipDispatcher* AmSipDispatcher::instance()
40 40
   return _instance ? _instance : ((_instance = new AmSipDispatcher()));
41 41
 }
42 42
 
43
-void AmSipDispatcher::handleSipMsg(AmSipReply &reply)
43
+void AmSipDispatcher::handleSipMsg(const string& dialog_id, AmSipReply &reply)
44 44
 {
45
+  const string& id = dialog_id.empty() ? reply.local_tag : dialog_id;
45 46
   AmSipReplyEvent* ev = new AmSipReplyEvent(reply);
46 47
 
47
-  if(!AmEventDispatcher::instance()->post(reply.from_tag,ev)){
48
+  if(!AmEventDispatcher::instance()->post(id,ev)){
48 49
     if ((reply.code >= 100) && (reply.code < 300)) {
49 50
       if (AmConfig::UnhandledReplyLoglevel >= 0) {
50 51
 	_LOG(AmConfig::UnhandledReplyLoglevel,
... ...
@@ -68,21 +69,25 @@ void AmSipDispatcher::handleSipMsg(AmSipRequest &req)
68 69
   if(!local_tag.empty()) {
69 70
     AmSipRequestEvent* ev = new AmSipRequestEvent(req);
70 71
 
71
-      if(!ev_disp->post(local_tag,ev)) {
72
-
73
-	  delete ev;
74
-	  if(req.method != SIP_METH_ACK) {
75
-	    AmSipDialog::reply_error(req,481,
76
-				     "Call leg/Transaction does not exist");
77
-	  }
78
-	  else {
79
-	    DBG("received ACK for non-existing dialog "
80
-		"(callid=%s;remote_tag=%s;local_tag=%s)\n",
81
-		callid.c_str(),remote_tag.c_str(),local_tag.c_str());
82
-	  }
83
-      }
72
+    if(ev_disp->post(local_tag,ev))
73
+      return;
84 74
 
75
+    // Contact-user may contain internal dialog ID
76
+    if(!req.user.empty() && ev_disp->post(req.user,ev))
85 77
       return;
78
+
79
+    delete ev;
80
+    if(req.method != SIP_METH_ACK) {
81
+      AmSipDialog::reply_error(req,481,
82
+			       "Call leg/Transaction does not exist");
83
+    }
84
+    else {
85
+      DBG("received ACK for non-existing dialog "
86
+	  "(callid=%s;remote_tag=%s;local_tag=%s)\n",
87
+	  callid.c_str(),remote_tag.c_str(),local_tag.c_str());
88
+    }
89
+
90
+    return;
86 91
   }
87 92
 
88 93
   DBG("method: `%s' [%zd].\n", req.method.c_str(), req.method.length());
... ...
@@ -36,7 +36,7 @@ class AmSipDispatcher
36 36
 
37 37
   public:
38 38
     void handleSipMsg(AmSipRequest &);
39
-    void handleSipMsg(AmSipReply &);
39
+    void handleSipMsg(const string& dialog_id, AmSipReply &);
40 40
 
41 41
     static AmSipDispatcher* instance();
42 42
 };
... ...
@@ -127,9 +127,8 @@ int SipCtrlInterface::cancel(trans_ticket* tt)
127 127
     return trans_layer::instance()->cancel(tt);
128 128
 }
129 129
 
130
-int SipCtrlInterface::send(AmSipRequest &req,
131
-			   const string& next_hop,
132
-			   int out_interface)
130
+int SipCtrlInterface::send(AmSipRequest &req, const string& dialog_id,
131
+			   const string& next_hop, int out_interface)
133 132
 {
134 133
     if(req.method == "CANCEL")
135 134
 	return cancel(&req.tt);
... ...
@@ -221,6 +220,7 @@ int SipCtrlInterface::send(AmSipRequest &req,
221 220
     }
222 221
 
223 222
     int res = trans_layer::instance()->send_request(msg,&req.tt,
223
+						    stl2cstr(dialog_id),
224 224
 						    stl2cstr(next_hop),
225 225
 						    out_interface);
226 226
     delete msg;
... ...
@@ -596,7 +596,7 @@ void SipCtrlInterface::handle_sip_request(const trans_ticket& tt, sip_msg* msg)
596 596
 	req.callid.c_str(), req.to_tag.c_str(), req.method.c_str());
597 597
 }
598 598
 
599
-void SipCtrlInterface::handle_sip_reply(sip_msg* msg)
599
+void SipCtrlInterface::handle_sip_reply(const string& dialog_id, sip_msg* msg)
600 600
 {
601 601
     assert(msg->from && msg->from->p);
602 602
     assert(msg->to && msg->to->p);
... ...
@@ -617,7 +617,7 @@ void SipCtrlInterface::handle_sip_reply(sip_msg* msg)
617 617
     DBG("hdrs = <%s>\n",reply.hdrs.c_str());
618 618
     DBG("body-ct = <%s>\n",reply.body.getCTStr().c_str());
619 619
 
620
-    AmSipDispatcher::instance()->handleSipMsg(reply);
620
+    AmSipDispatcher::instance()->handleSipMsg(dialog_id, reply);
621 621
 
622 622
     DBG("^^ M [%s|%s] ru SIP reply %u %s handled ^^\n",
623 623
 	reply.callid.c_str(), reply.from_tag.c_str(),
... ...
@@ -89,9 +89,8 @@ public:
89 89
      * @param req The request to send. If the request creates a transaction, 
90 90
      *            its ticket is written into req.tt.
91 91
      */
92
-    static int send(AmSipRequest &req,
93
-		    const string& next_hop = "",
94
-		    int outbound_interface = -1);
92
+    static int send(AmSipRequest &req, const string& dialog_id,
93
+		    const string& next_hop = "", int outbound_interface = -1);
95 94
 
96 95
     /**
97 96
      * Sends a SIP reply. 
... ...
@@ -112,7 +111,7 @@ public:
112 111
      * From sip_ua
113 112
      */
114 113
     void handle_sip_request(const trans_ticket& tt, sip_msg* msg);
115
-    void handle_sip_reply(sip_msg* msg);
114
+    void handle_sip_reply(const string& dialog_id, sip_msg* msg);
116 115
     void handle_reply_timeout(AmSipTimeoutEvent::EvType evt,
117 116
         sip_trans *tr, trans_bucket *buk=0);
118 117
 };
... ...
@@ -81,6 +81,9 @@ sip_trans::~sip_trans()
81 81
     if((type == TT_UAC) && to_tag.s){
82 82
 	delete [] to_tag.s;
83 83
     }
84
+    if(dialog_id.s) {
85
+	delete [] dialog_id.s;
86
+    }
84 87
 }
85 88
 
86 89
 /**
... ...
@@ -124,6 +124,9 @@ class sip_trans
124 124
     /** used by UAS only; keeps RSeq of last sent reliable 1xx */
125 125
     unsigned int last_rseq;
126 126
 
127
+    /** Dialog-ID used for UAC transactions */
128
+    cstring dialog_id;
129
+
127 130
     /**
128 131
      * Retransmission buffer
129 132
      *  - UAC transaction: ACK
... ...
@@ -41,7 +41,7 @@ public:
41 41
     virtual ~sip_ua() {}
42 42
 
43 43
     virtual void handle_sip_request(const trans_ticket& tt, sip_msg* msg)=0;
44
-    virtual void handle_sip_reply(sip_msg* msg)=0;
44
+  virtual void handle_sip_reply(const string& dialog_id, sip_msg* msg)=0;
45 45
 
46 46
     //virtual void handle_request_timeout(const sip_msg *msg)=0;
47 47
     virtual void handle_reply_timeout(AmSipTimeoutEvent::EvType evt,
... ...
@@ -814,14 +814,16 @@ void _trans_layer::timeout(trans_bucket* bucket, sip_trans* t)
814 814
 
815 815
     translate_hdr(&msg,msg.callid, req,req->callid);
816 816
 
817
+    string dialog_id(t->dialog_id.s,t->dialog_id.len);
817 818
     bucket->remove(t);
818 819
     bucket->unlock();
819 820
 
820
-    ua->handle_sip_reply(&msg);
821
+    ua->handle_sip_reply(dialog_id,&msg);
821 822
 }
822 823
 
823
-int _trans_layer::send_request(sip_msg* msg, trans_ticket* tt,
824
-			       const cstring& _next_hop,
824
+int _trans_layer::send_request(sip_msg* msg, trans_ticket* tt, 
825
+			       const cstring& dialog_id,
826
+			       const cstring& _next_hop, 
825 827
 			       int out_interface)
826 828
 {
827 829
     // Request-URI
... ...
@@ -999,6 +1001,11 @@ int _trans_layer::send_request(sip_msg* msg, trans_ticket* tt,
999 1001
 	    DBG("Could not update UAC state for request\n");
1000 1002
 	    delete p_msg;
1001 1003
 	}
1004
+	else if(dialog_id.len && !(tt->_t->dialog_id.len)) {
1005
+	    tt->_t->dialog_id.s = new char[dialog_id.len];
1006
+	    tt->_t->dialog_id.len = dialog_id.len;
1007
+	    memcpy((void*)tt->_t->dialog_id.s,dialog_id.s,dialog_id.len);
1008
+	}
1002 1009
     }
1003 1010
 
1004 1011
     tt->_bucket->unlock();
... ...
@@ -1296,8 +1303,9 @@ void _trans_layer::received_msg(sip_msg* msg)
1296 1303
 		break;
1297 1304
 	    }
1298 1305
 	    if (res) {
1306
+		string dialog_id(t->dialog_id.s, t->dialog_id.len);
1299 1307
 		bucket->unlock();
1300
-		ua->handle_sip_reply(msg);
1308
+		ua->handle_sip_reply(dialog_id, msg);
1301 1309
 		DROP_MSG;
1302 1310
 		//return; - part of DROP_MSG
1303 1311
 	    }
... ...
@@ -101,9 +101,8 @@ public:
101 101
      * @param [in]  msg Pre-built message.
102 102
      * @param [out] tt transaction ticket (needed for replies & CANCEL)
103 103
      */
104
-    int send_request(sip_msg* msg, trans_ticket* tt,
105
-		     const cstring& _next_hop,
106
-		     int out_interface = -1);
104
+    int send_request(sip_msg* msg, trans_ticket* tt, const cstring& dialog_id,
105
+		     const cstring& _next_hop, int out_interface = -1);
107 106
 
108 107
     /**
109 108
      * Cancels a request.