Skip to content

Commit 50b6d31

Browse files
committed
fix: broadcast_event unique sequence prevents CC event dedup; resolved_agent_id bypasses WebRTC contact
1 parent 832cb9a commit 50b6d31

3 files changed

Lines changed: 37 additions & 25 deletions

File tree

src/addons/cc

Submodule cc updated from 3a0aba4 to f2225f7

src/proxy/proxy_call/sip_session.rs

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2248,23 +2248,11 @@ impl SipSession {
22482248
}
22492249
}
22502250
}
2251-
let connected_callee = self
2252-
.meta
2253-
.routed_callee
2254-
.clone()
2255-
.or_else(|| self.meta.connected_callee.clone());
2256-
info!(
2257-
session_id = %self.context.session_id,
2258-
routed_callee = ?self.meta.routed_callee,
2259-
connected_callee = ?self.meta.connected_callee,
2260-
resolved = ?connected_callee,
2261-
"session_hook_ctx: connected_callee resolution"
2262-
);
22632251
crate::proxy::proxy_call::session_hooks::CallSessionContext {
22642252
session_id: self.context.session_id.clone(),
22652253
caller: self.context.original_caller.clone(),
22662254
callee: self.context.original_callee.clone(),
2267-
connected_callee,
2255+
connected_callee: self.meta.connected_callee.clone(),
22682256
queue_name: self.meta.queue_name.clone(),
22692257
direction: self.context.dialplan.direction.to_string(),
22702258
started_at: Some(self.context.created_at.clone()),
@@ -4407,17 +4395,32 @@ impl SipSession {
44074395
// of building a bare Location that defaults to RTP.
44084396
for agent_uri in agent_uris {
44094397
if let Ok(uri) = rsipstack::sip::Uri::try_from(agent_uri.clone()) {
4398+
// Write the original agent AOR to session extensions
4399+
// so that CC hooks can identify the agent regardless
4400+
// of what routed_callee/connected_callee end up being.
4401+
{
4402+
use std::collections::HashMap;
4403+
let mut ext = self.extensions.write();
4404+
let user_part = uri.auth.as_ref()
4405+
.map(|a| a.user.clone())
4406+
.unwrap_or_default();
4407+
if !user_part.is_empty() {
4408+
if let Some(map) = ext.get_mut::<HashMap<String, String>>() {
4409+
map.entry("resolved_agent_id".to_string())
4410+
.or_insert(user_part.clone());
4411+
} else {
4412+
let mut map = HashMap::new();
4413+
map.insert("resolved_agent_id".to_string(), user_part);
4414+
ext.insert(map);
4415+
}
4416+
}
4417+
}
4418+
44104419
// Query the SIP registrar for this agent's live contact.
44114420
let registered_locations =
44124421
self.server.locator.lookup(&uri).await.unwrap_or_default();
44134422

4414-
if let Some(mut reg_loc) = registered_locations.into_iter().next() {
4415-
// Preserve the original AOR (e.g.
4416-
// "sip:1001@localhost") so that
4417-
// routed_callee carries the agent's
4418-
// extension, not the registrar contact
4419-
// (which may be a random WebRTC ID).
4420-
reg_loc.aor = uri.clone();
4423+
if let Some(reg_loc) = registered_locations.into_iter().next() {
44214424
expanded.push(reg_loc);
44224425
} else {
44234426
// Agent not currently registered.
@@ -4531,9 +4534,6 @@ impl SipSession {
45314534
self.build_target_invite_option(target, None).await?;
45324535

45334536
self.meta.routed_caller = Some(invite_option.caller.to_string());
4534-
// Store the original target AOR (e.g. "sip:test001@localhost"), NOT
4535-
// the resolved contact URI (e.g. WebRTC contact "sip:abc123@...;transport=WS").
4536-
// This is used by session hooks to resolve agent identity.
45374537
self.meta.routed_callee = Some(target.aor.to_string());
45384538

45394539
if let Some(home_proxy) = target.home_proxy.as_ref() {

src/rwi/gateway.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -535,10 +535,22 @@ impl RwiGateway {
535535
/// Call-scoped events (with `call_id`) carry it in the envelope so webhook
536536
/// consumers can correlate. Truly global events (agent_state_changed, etc.)
537537
/// have `call_id = None` and the envelope field is empty.
538+
///
539+
/// Each broadcast event gets a unique sequence number from a monotonic
540+
/// counter so the webhook dedup logic doesn't drop consecutive CC events
541+
/// (cc_ringing, cc_answered, call.ended) that share the same call_id.
538542
pub fn broadcast_event(&self, event: &RwiEvent) {
543+
// Use a unique sequence so webhook dedup doesn't drop consecutive
544+
// CC events with the same call_id.
545+
let seq = {
546+
let mut cache_state = self.event_cache.lock();
547+
let s = cache_state.next_sequence;
548+
cache_state.next_sequence += 1;
549+
s
550+
};
539551
if let Some(tx) = &self.webhook_tx {
540552
let entry = EventCacheEntry {
541-
sequence: 0,
553+
sequence: seq,
542554
cached_at: chrono::Utc::now(),
543555
call_id: event.call_id.clone().unwrap_or_default(),
544556
event: event.clone(),

0 commit comments

Comments
 (0)