Skip to content

Commit 939a3c3

Browse files
committed
fix DialogId logic
1 parent 1118210 commit 939a3c3

13 files changed

Lines changed: 114 additions & 104 deletions

File tree

examples/client/main.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use rsipstack::dialog::dialog_layer::DialogLayer;
77
use rsipstack::dialog::invitation::InviteOption;
88
use rsipstack::dialog::server_dialog::ServerInviteDialog;
99
use rsipstack::transaction::endpoint::EndpointInnerRef;
10+
use rsipstack::transaction::key::TransactionRole;
1011
use rsipstack::Result;
1112
use rsipstack::{
1213
dialog::{authenticate::Credential, registration::Registration},
@@ -306,7 +307,7 @@ async fn process_incoming_request(
306307
info!("Received transaction: {:?}", tx.key);
307308

308309
match tx.original.to_header()?.tag()?.as_ref() {
309-
Some(_) => match dialog_layer.match_dialog(&tx.original) {
310+
Some(_) => match dialog_layer.match_dialog(&tx) {
310311
Some(mut d) => {
311312
tokio::spawn(async move {
312313
d.handle(&mut tx).await?;

examples/proxy.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ async fn process_incoming_request(
257257
}
258258
rsip::Method::Ack => {
259259
info!(method = ?tx.original.method, "received out of transaction ack");
260-
let dialog_id = DialogId::try_from(&tx.original)?;
260+
let dialog_id = DialogId::try_from(&tx)?;
261261
if !state_ref.inner.sessions.lock().await.contains(&dialog_id) {
262262
tx.reply(rsip::StatusCode::NotAcceptable).await?;
263263
continue;
@@ -458,7 +458,7 @@ async fn handle_invite(state: AppState, mut tx: Transaction) -> Result<()> {
458458
header_pop!(resp.headers, rsip::Header::Via);
459459
resp.headers.push_front(record_route.clone().into());
460460
if resp.status_code.kind() == rsip::StatusCodeKind::Successful {
461-
let dialog_id = DialogId::try_from(&resp)?;
461+
let dialog_id = DialogId::try_from((&resp, TransactionRole::Client))?;
462462
info!(id = %dialog_id, "add session");
463463
state.inner.sessions.lock().await.insert(dialog_id);
464464
}
@@ -523,7 +523,7 @@ async fn handle_bye(state: AppState, mut tx: Transaction) -> Result<()> {
523523

524524
bye_tx.send().await?;
525525

526-
let dialog_id = DialogId::try_from(&bye_tx.original)?;
526+
let dialog_id = DialogId::try_from(&bye_tx)?;
527527
if state.inner.sessions.lock().await.remove(&dialog_id) {
528528
info!(id = %dialog_id, "removed session");
529529
}
@@ -857,8 +857,8 @@ mod tests {
857857
// Create a test dialog ID
858858
let dialog_id = DialogId {
859859
call_id: "test-call-id".to_string(),
860-
from_tag: "local-tag".to_string(),
861-
to_tag: "remote-tag".to_string(),
860+
local_tag: "local-tag".to_string(),
861+
remote_tag: "remote-tag".to_string(),
862862
};
863863

864864
state.inner.sessions.lock().await.insert(dialog_id.clone());

src/bin/bench_ua.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ async fn run_server(
107107
});
108108
}
109109
rsip::Method::Bye => {
110-
if let Ok(dialog_id) = DialogId::try_from(&tx.original) {
110+
if let Ok(dialog_id) = DialogId::try_from(&tx) {
111111
stats.active_calls.lock().unwrap().remove(&dialog_id);
112112
tx.reply(rsip::StatusCode::OK).await.ok();
113113
dialog_layer.remove_dialog(&dialog_id);

src/dialog/authenticate.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ pub async fn handle_client_authenticate(
197197
let proxy_header = rsip::header_opt!(resp.headers().iter(), Header::ProxyAuthenticate);
198198
let proxy_header = proxy_header.ok_or(crate::Error::DialogError(
199199
"missing proxy/www authenticate".to_string(),
200-
DialogId::try_from(&tx.original)?,
200+
DialogId::try_from(tx)?,
201201
code,
202202
))?;
203203
Header::ProxyAuthenticate(proxy_header.clone())

src/dialog/client_dialog.rs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
use super::dialog::DialogInnerRef;
22
use super::DialogId;
3-
use crate::dialog::{
4-
authenticate::handle_client_authenticate,
5-
dialog::{DialogState, TerminatedReason, TransactionHandle},
6-
subscription::ClientSubscriptionDialog,
7-
};
83
use crate::rsip_ext::RsipResponseExt;
94
use crate::transaction::transaction::Transaction;
105
use crate::Result;
6+
use crate::{
7+
dialog::{
8+
authenticate::handle_client_authenticate,
9+
dialog::{DialogState, TerminatedReason, TransactionHandle},
10+
subscription::ClientSubscriptionDialog,
11+
},
12+
transaction::key::TransactionRole,
13+
};
1114
use rsip::prelude::HasHeaders;
1215
use rsip::{prelude::HeadersExt, Header};
1316
use rsip::{Response, SipMessage, StatusCode};
@@ -702,7 +705,7 @@ impl ClientInviteDialog {
702705
None => {}
703706
}
704707

705-
if let Ok(id) = DialogId::try_from(&resp) {
708+
if let Ok(id) = DialogId::try_from((&resp, TransactionRole::Client)) {
706709
dialog_id = id;
707710
}
708711
match resp.status_code {

src/dialog/dialog.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,14 @@ impl DialogInner {
403403
let from = initial_request.from_header()?.typed()?;
404404
let mut to = initial_request.to_header()?.typed()?;
405405
if !to.params.iter().any(|p| matches!(p, Param::Tag(_))) {
406-
to.params.push(rsip::Param::Tag(id.to_tag.clone().into()));
406+
match role {
407+
TransactionRole::Client => to
408+
.params
409+
.push(rsip::Param::Tag(id.remote_tag.clone().into())),
410+
TransactionRole::Server => to
411+
.params
412+
.push(rsip::Param::Tag(id.local_tag.clone().into())),
413+
}
407414
}
408415

409416
let mut route_set = vec![];
@@ -461,7 +468,7 @@ impl DialogInner {
461468
}
462469

463470
pub fn update_remote_tag(&self, tag: &str) -> Result<()> {
464-
self.id.lock().unwrap().to_tag = tag.to_string();
471+
self.id.lock().unwrap().remote_tag = tag.to_string();
465472
let mut to = self.to.lock().unwrap();
466473
*to = to.clone().with_tag(tag.into());
467474
Ok(())
@@ -795,7 +802,7 @@ impl DialogInner {
795802
&& !to.params.iter().any(|p| matches!(p, Param::Tag(_)))
796803
{
797804
to.params.push(rsip::Param::Tag(
798-
self.id.lock().unwrap().to_tag.clone().into(),
805+
self.id.lock().unwrap().local_tag.clone().into(),
799806
));
800807
}
801808
resp_headers.push(Header::To(to.into()));

src/dialog/dialog_layer.rs

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ use crate::transaction::make_tag;
1010
use crate::transaction::{endpoint::EndpointInnerRef, transaction::Transaction};
1111
use crate::Result;
1212
use rsip::prelude::HeadersExt;
13-
use rsip::Request;
1413
use std::sync::atomic::{AtomicU32, Ordering};
1514
use std::{
1615
collections::HashMap,
@@ -155,8 +154,8 @@ impl DialogLayer {
155154
credential: Option<Credential>,
156155
local_contact: Option<rsip::Uri>,
157156
) -> Result<ServerInviteDialog> {
158-
let mut id = DialogId::try_from(&tx.original)?;
159-
if !id.to_tag.is_empty() {
157+
let mut id = DialogId::try_from(tx)?;
158+
if !id.local_tag.is_empty() {
160159
let dlg = self
161160
.inner
162161
.dialogs
@@ -175,7 +174,7 @@ impl DialogLayer {
175174
}
176175
}
177176
}
178-
id.to_tag = make_tag().to_string(); // generate to tag
177+
id.local_tag = make_tag().to_string(); // generate to tag
179178

180179
let mut local_contact = local_contact;
181180
if local_contact.is_none() {
@@ -216,8 +215,8 @@ impl DialogLayer {
216215
credential: Option<Credential>,
217216
local_contact: Option<rsip::Uri>,
218217
) -> Result<ServerSubscriptionDialog> {
219-
let mut id = DialogId::try_from(&tx.original)?;
220-
if !id.to_tag.is_empty() {
218+
let mut id = DialogId::try_from(tx)?;
219+
if !id.local_tag.is_empty() {
221220
let dlg = self
222221
.inner
223222
.dialogs
@@ -236,7 +235,7 @@ impl DialogLayer {
236235
}
237236
}
238237
}
239-
id.to_tag = make_tag().to_string(); // generate to tag
238+
id.local_tag = make_tag().to_string(); // generate to tag
240239

241240
let mut local_contact = local_contact;
242241
if local_contact.is_none() {
@@ -277,8 +276,8 @@ impl DialogLayer {
277276
credential: Option<Credential>,
278277
local_contact: Option<rsip::Uri>,
279278
) -> Result<ServerPublicationDialog> {
280-
let mut id = DialogId::try_from(&tx.original)?;
281-
if !id.to_tag.is_empty() {
279+
let mut id = DialogId::try_from(tx)?;
280+
if !id.local_tag.is_empty() {
282281
let dlg = self
283282
.inner
284283
.dialogs
@@ -297,7 +296,7 @@ impl DialogLayer {
297296
}
298297
}
299298
}
300-
id.to_tag = make_tag().to_string(); // generate to tag
299+
id.local_tag = make_tag().to_string(); // generate to tag
301300

302301
let mut local_contact = local_contact;
303302
if local_contact.is_none() {
@@ -341,8 +340,8 @@ impl DialogLayer {
341340
) -> Result<ClientPublicationDialog> {
342341
let id = DialogId {
343342
call_id,
344-
from_tag,
345-
to_tag,
343+
local_tag: from_tag,
344+
remote_tag: to_tag,
346345
};
347346

348347
if let Some(Dialog::ClientPublication(dlg)) = self.get_dialog(&id) {
@@ -391,8 +390,8 @@ impl DialogLayer {
391390
) -> Result<ClientSubscriptionDialog> {
392391
let id = DialogId {
393392
call_id,
394-
from_tag,
395-
to_tag,
393+
local_tag: from_tag,
394+
remote_tag: to_tag,
396395
};
397396

398397
if let Some(Dialog::ClientSubscription(dlg)) = self.get_dialog(&id) {
@@ -501,8 +500,8 @@ impl DialogLayer {
501500
.map(|d| d.on_remove());
502501
}
503502

504-
pub fn match_dialog(&self, req: &Request) -> Option<Dialog> {
505-
let id = DialogId::try_from(req).ok()?;
503+
pub fn match_dialog(&self, tx: &Transaction) -> Option<Dialog> {
504+
let id = DialogId::try_from(tx).ok()?;
506505
self.get_dialog(&id)
507506
}
508507

src/dialog/invitation.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -548,7 +548,7 @@ impl DialogLayer {
548548
}
549549
}
550550

551-
let id = DialogId::try_from(&request)?;
551+
let id = DialogId::try_from(&tx)?;
552552
let dlg_inner = DialogInner::new(
553553
TransactionRole::Client,
554554
id.clone(),

src/dialog/mod.rs

Lines changed: 44 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
use crate::{Error, Result};
1+
use crate::{
2+
transaction::{key::TransactionRole, transaction::Transaction},
3+
Error, Result,
4+
};
25
use rsip::{
36
prelude::{HeadersExt, UntypedHeader},
47
Request, Response,
@@ -47,46 +50,17 @@ mod tests;
4750
/// - During early dialog establishment, `to_tag` may be an empty string
4851
/// - Dialog ID remains constant throughout the dialog lifetime
4952
/// - Used for managing and routing SIP messages at the dialog layer
50-
#[derive(Clone, Debug)]
53+
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
5154
pub struct DialogId {
5255
pub call_id: String,
53-
pub from_tag: String,
54-
pub to_tag: String,
55-
}
56-
57-
impl PartialEq for DialogId {
58-
fn eq(&self, other: &DialogId) -> bool {
59-
if self.call_id != other.call_id {
60-
return false;
61-
}
62-
if self.from_tag == other.from_tag && self.to_tag == other.to_tag {
63-
return true;
64-
}
65-
if self.from_tag == other.to_tag && self.to_tag == other.from_tag {
66-
return true;
67-
}
68-
false
69-
}
56+
pub local_tag: String,
57+
pub remote_tag: String,
7058
}
7159

72-
impl Eq for DialogId {}
73-
impl std::hash::Hash for DialogId {
74-
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
75-
self.call_id.hash(state);
76-
if self.from_tag > self.to_tag {
77-
self.from_tag.hash(state);
78-
self.to_tag.hash(state);
79-
} else {
80-
self.to_tag.hash(state);
81-
self.from_tag.hash(state);
82-
}
83-
}
84-
}
85-
86-
impl TryFrom<&Request> for DialogId {
60+
impl TryFrom<(&Request, TransactionRole)> for DialogId {
8761
type Error = crate::Error;
8862

89-
fn try_from(request: &Request) -> Result<Self> {
63+
fn try_from((request, direction): (&Request, TransactionRole)) -> Result<Self> {
9064
let call_id = request.call_id_header()?.value().to_string();
9165

9266
let from_tag = match request.from_header()?.tag()? {
@@ -99,18 +73,25 @@ impl TryFrom<&Request> for DialogId {
9973
None => "".to_string(),
10074
};
10175

102-
Ok(DialogId {
103-
call_id,
104-
from_tag,
105-
to_tag,
106-
})
76+
match direction {
77+
TransactionRole::Client => Ok(DialogId {
78+
call_id,
79+
local_tag: from_tag,
80+
remote_tag: to_tag,
81+
}),
82+
TransactionRole::Server => Ok(DialogId {
83+
call_id,
84+
local_tag: to_tag,
85+
remote_tag: from_tag,
86+
}),
87+
}
10788
}
10889
}
10990

110-
impl TryFrom<&Response> for DialogId {
91+
impl TryFrom<(&Response, TransactionRole)> for DialogId {
11192
type Error = crate::Error;
11293

113-
fn try_from(resp: &Response) -> Result<Self> {
94+
fn try_from((resp, direction): (&Response, TransactionRole)) -> Result<Self> {
11495
let call_id = resp.call_id_header()?.value().to_string();
11596

11697
let from_tag = match resp.from_header()?.tag()? {
@@ -123,24 +104,31 @@ impl TryFrom<&Response> for DialogId {
123104
None => return Err(Error::Error("to tag not found".to_string())),
124105
};
125106

126-
Ok(DialogId {
127-
call_id,
128-
from_tag,
129-
to_tag,
130-
})
107+
match direction {
108+
TransactionRole::Client => Ok(DialogId {
109+
call_id,
110+
local_tag: from_tag,
111+
remote_tag: to_tag,
112+
}),
113+
TransactionRole::Server => Ok(DialogId {
114+
call_id,
115+
local_tag: to_tag,
116+
remote_tag: from_tag,
117+
}),
118+
}
119+
}
120+
}
121+
122+
impl TryFrom<&Transaction> for DialogId {
123+
type Error = crate::Error;
124+
125+
fn try_from(value: &Transaction) -> std::result::Result<Self, Self::Error> {
126+
DialogId::try_from((&value.original, value.role()))
131127
}
132128
}
133129

134130
impl std::fmt::Display for DialogId {
135131
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
136-
if self.from_tag > self.to_tag {
137-
if self.to_tag.is_empty() {
138-
write!(f, "{}-{}", self.call_id, self.from_tag)
139-
} else {
140-
write!(f, "{}-{}-{}", self.call_id, self.from_tag, self.to_tag)
141-
}
142-
} else {
143-
write!(f, "{}-{}-{}", self.call_id, self.to_tag, self.from_tag)
144-
}
132+
write!(f, "{}-{}-{}", self.call_id, self.local_tag, self.remote_tag)
145133
}
146134
}

src/dialog/registration.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -495,7 +495,7 @@ impl Registration {
495495
}
496496
return Err(crate::Error::DialogError(
497497
"registration transaction is already terminated".to_string(),
498-
DialogId::try_from(&tx.original)?,
498+
DialogId::try_from(&tx)?,
499499
StatusCode::BadRequest,
500500
));
501501
}

0 commit comments

Comments
 (0)