... | ... |
@@ -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()); |
... | ... |
@@ -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 |
}; |
... | ... |
@@ -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. |