Answer SDP Error Kurento NodeJS server with vanilla webRTC client - node.js

I've been developing an application to record a session from the browser using the Kurento Media Server. I've set up the backend using the kurento-client library and used the vanilla WebRTC API on the front end.
The offer is generated at the client side and the answer is returned back from the server.
The issue arises during the setRemoteDescription method at the client side.
I'm getting the error as shown below
Uncaught (in promise) TypeError: Failed to execute 'setRemoteDescription' on 'RTCPeerConnection': The provided value is not of type 'RTCSessionDescriptionInit'.
console logging the received SDP yields me the following value.
v=0
o=- 3858259838 3858259838 IN IP4 0.0.0.0
s=Kurento Media Server
c=IN IP4 0.0.0.0
t=0 0
a=extmap-allow-mixed:
a=msid-semantic: WMS EkyCjRfgsyNQMlKh9vmRFVBIlCgbgNt51tst
a=group:BUNDLE 0 1
m=audio 1 UDP/TLS/RTP/SAVPF 111 0
a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=sendrecv
a=mid:0
a=rtcp:9 IN IP4 0.0.0.0
a=rtpmap:111 opus/48000/2
a=rtpmap:0 PCMU/8000
a=setup:active
a=rtcp-mux
a=fmtp:111 minptime=10;useinbandfec=1
a=ssrc:2441312662 cname:user4258135824#host-a3760c98
a=ice-ufrag:u7MJ
a=ice-pwd:uAgK+b4b5eK2333Z+qQZnP
a=fingerprint:sha-256 BD:6C:C8:40:7C:30:60:30:76:63:CC:28:20:D3:81:5F:EE:5A:6D:B0:C4:AA:09:37:70:8E:13:55:51:81:4B:37
m=video 1 UDP/TLS/RTP/SAVPF 96 127 125 108 124 123 35
a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=sendrecv
a=mid:1
a=rtcp:9 IN IP4 0.0.0.0
a=rtpmap:96 VP8/90000
a=rtpmap:127 H264/90000
a=rtpmap:125 H264/90000
a=rtpmap:108 H264/90000
a=rtpmap:124 H264/90000
a=rtpmap:123 H264/90000
a=rtpmap:35 H264/90000
a=rtcp-fb:96 goog-remb
a=rtcp-fb:96 ccm fir
a=rtcp-fb:96 nack
a=rtcp-fb:96 nack pli
a=rtcp-fb:127 goog-remb
a=rtcp-fb:127 ccm fir
a=rtcp-fb:127 nack
a=rtcp-fb:127 nack pli
a=rtcp-fb:125 goog-remb
a=rtcp-fb:125 ccm fir
a=rtcp-fb:125 nack
a=rtcp-fb:125 nack pli
a=rtcp-fb:108 goog-remb
a=rtcp-fb:108 ccm fir
a=rtcp-fb:108 nack
a=rtcp-fb:108 nack pli
a=rtcp-fb:124 goog-remb
a=rtcp-fb:124 ccm fir
a=rtcp-fb:124 nack
a=rtcp-fb:124 nack pli
a=rtcp-fb:123 goog-remb
a=rtcp-fb:123 ccm fir
a=rtcp-fb:123 nack
a=rtcp-fb:123 nack pli
a=rtcp-fb:35 goog-remb
a=rtcp-fb:35 ccm fir
a=rtcp-fb:35 nack
a=rtcp-fb:35 nack pli
a=setup:active
a=rtcp-mux
a=fmtp:127 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f
a=fmtp:125 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42001f
a=fmtp:108 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f
a=fmtp:124 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42e01f
a=fmtp:123 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=4d001f
a=fmtp:35 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=4d001f
a=ssrc:3201711112 cname:user4258135824#host-a3760c98
a=ice-ufrag:u7MJ
a=ice-pwd:uAgK+b4b5eK2333Z+qQZnP
a=fingerprint:sha-256 BD:6C:C8:40:7C:30:60:30:76:63:CC:28:20:D3:81:5F:EE:5A:6D:B0:C4:AA:09:37:70:8E:13:55:51:81:4B:37
I've provided the code segment below which throws the error.
socket.on("credentials", async({ sdp, ice} ) => {
try {
if(sdp) {
console.log(sdp)
await pc.setRemoteDescription(sdp)
console.log('set')
}
else if(ice) {
await pc.addIceCandidate(ice)
console.log('ice set')
}
}
catch(error) {
console.log(error)
}
})
Is this not the correct format for the answer SDP? Some help to solve this issue is much appreciated.

You have a problem with your terminology. The SDP itself is the string starting with v=....
However, the setRemoteDescription call expects a RTCSessionDescriptionInit argument, i.e. an object with {type, sdp}.
That type (offer or answer typically) should also come from your signaling.

Related

WebRTC ICE Connection Failing with Valid ICE Servers and Candidates

This is a continuation of my previous question here.
I started using the webrtc crate in this library to create a WebRTC connection, but I'm having issues with the ICE connection failing. I checked the STUN and TURN servers being used with this site and they all work correctly.
Here is my current code:
async fn new(...) {
let webrtcredux = Arc::new(AsyncMutex::new(WebRtcRedux::default()));
webrtcredux.lock().await.set_tokio_runtime(Handle::current());
let servers = ice.urls.into_iter().map(|url| {
if url.starts_with("turn") {
RTCIceServer {
urls: vec![url],
username: ice.username.clone(),
credential: ice.credential.clone(),
.. RTCIceServer::default()
}
} else {
RTCIceServer {
urls: vec![url],
.. RTCIceServer::default()
}
}
}).collect::<Vec<_>>();
debug!("Using ICE servers: {:#?}", servers);
webrtcredux.lock().await.add_ice_servers(servers);
// More gstreamer setup code...
}
async fn start(...) {
self.pipeline.set_state(gst::State::Playing)?;
let encoder = self.encoder_type;
let arc_from_ws = Arc::new(AsyncMutex::new(from_ws_rx));
self.webrtcredux.lock().await.on_peer_connection_state_change(Box::new(|state| {
debug!("[WebRTC] Peer connection state changed to: {}", state);
Box::pin(async {})
})).await.expect("Failed to set on peer connection state change");
self.webrtcredux.lock().await.on_ice_connection_state_change(Box::new(|state| {
debug!("[WebRTC] ICE connection state changed to: {}", state);
Box::pin(async {})
})).await.expect("Failed to set on ice connection state change");
// let redux_arc = self.webrtcredux.clone();
// let candidates = Arc::new(AsyncMutex::new(Vec::new()));
// let candidates_arc = candidates.clone();
self.webrtcredux.lock().await.on_ice_candidate(Box::new(move |candidate| {
// let redux_arc = redux_arc.clone()
// let candidates = candidates_arc.clone();
Box::pin(async move {
if let Some(candidate) = candidate {
debug!("ICE Candidate: {:#?}", candidate.to_json().await.unwrap());
// candidates.lock().await.push(candidate.to_json().await.unwrap());
}
// redux_arc.lock().await.add_ice_candidate(candidate.unwrap().to_json().await.unwrap()).await.unwrap();
})
})).await.expect("Failed ice candidate");
let redux_arc = self.webrtcredux.clone();
self.webrtcredux.lock().await.on_negotiation_needed(Box::new(move || {
let redux_arc = redux_arc.clone();
info!("[WebRTC] Negotiation needed");
Box::pin(async move {
// Waits for all tracks to be added to create full SDP
redux_arc.lock().await.wait_for_all_tracks().await;
let offer = redux_arc.lock().await.create_offer(Some(RTCOfferOptions {
voice_activity_detection: true,
ice_restart: false,
})).await.expect("Failed to create offer");
// offer.props.insert(4, SdpProp::Attribute {
// key: "ice-options".to_string(),
// value: Some("trickle".to_string())
// });
// offer.props.insert(5, SdpProp::Attribute {
// key: "extmap-allow-mixed".to_string(),
// value: None
// });
// offer.props.insert(6, SdpProp::Attribute {
// key: "msid-semantic".to_string(),
// value: Some(" WMS".to_string())
// });
trace!("[WebRTC] Generated local SDP: {}", offer.to_string());
redux_arc.lock().await.set_local_description(&offer, RTCSdpType::Offer).await.expect("Failed to set local description");
info!("[WebRTC] Local description set");
})
})).await.expect("Failed to set on negotiation needed");
let redux_arc = self.webrtcredux.clone();
self.webrtcredux.lock().await.on_ice_gathering_state_change(Box::new(move |state| {
debug!("[WebRTC] ICE gathering state changed to: {}", state);
let redux_arc = redux_arc.clone();
let to_ws_tx = to_ws_tx.clone();
let from_ws_rx = arc_from_ws.clone();
if state != RTCIceGathererState::Complete {
return Box::pin(async {});
}
Box::pin(async move {
let local = redux_arc.lock().await.local_description().await.unwrap().unwrap();
let video_media: &SdpProp = local.props.iter().find(|v| match *v {
SdpProp::Media { r#type, .. } => {
*r#type == MediaType::Video
},
_ => false
}).unwrap();
let (video_ssrc, video_payload_type, rtx_payload_type) = if let SdpProp::Media { props, .. } = video_media {
let mut ssrc = 0u32;
let mut video_payload = 0u8;
let mut rtx_payload = 0u8;
for prop in props {
match prop {
MediaProp::Attribute { key, value } => {
match key {
v if *v == "rtpmap".to_string() => {
match value {
Some(val) => {
let num = val.clone().split(' ').collect::<Vec<_>>()[0].parse::<u8>().unwrap();
if val.ends_with(&format!("{}/90000", encoder.type_string())) && video_payload == 0 {
video_payload = num;
} else if val.ends_with("rtx/90000") && rtx_payload == 0 {
rtx_payload = num;
}
},
None => unreachable!()
}
},
v if *v == "ssrc".to_string() => {
ssrc = match value {
Some(val) => val.clone().split(' ').collect::<Vec<_>>()[0].parse::<u32>().unwrap(),
None => unreachable!(),
};
},
_ => continue
}
},
_ => continue
}
}
(ssrc, video_payload, rtx_payload)
} else { unreachable!() };
let audio_media: &SdpProp = local.props.iter().find(|v| match *v {
SdpProp::Media { r#type, .. } => {
*r#type == MediaType::Audio
},
_ => false
}).unwrap();
let audio_ssrc = if let SdpProp::Media { props, .. } = audio_media {
props.into_iter().find_map(|p| match p {
MediaProp::Attribute {key, value} => {
if key != "ssrc" {
return None;
}
let val = match value {
Some(val) => val.clone(),
None => unreachable!(),
};
Some(val.split(' ').collect::<Vec<_>>()[0].parse::<u32>().unwrap())
},
_ => None
}).unwrap()
} else { unreachable!() };
trace!("[WebRTC] Updated local SDP: {}", local.to_string());
to_ws_tx.send(ToWs {
ssrcs: StreamSSRCs {
audio: audio_ssrc,
video: video_ssrc,
rtx: 0
},
local_sdp: local.to_string(),
video_payload_type,
rtx_payload_type,
}).await.unwrap();
let from_ws = from_ws_rx.lock().await.recv().await.unwrap();
match SDP::from_str(&from_ws.remote_sdp).unwrap().props.pop().unwrap() {
SdpProp::Media { ports, props, .. } => {
let mut main_ip = None;
let mut fingerprint = None;
let mut ufrag = None;
let mut pwd = None;
let mut candidate = None;
for prop in props {
let current = prop.clone();
match prop {
MediaProp::Connection { address, .. } => main_ip = Some(address),
MediaProp::Attribute { key, value: _ } => {
match &key[..] {
"candidate" => candidate = Some(current),
"fingerprint" => fingerprint = Some(current),
"ice-ufrag" => ufrag = Some(current),
"ice-pwd" => pwd = Some(current),
_ => continue
}
}
_ => continue
}
}
let connection = MediaProp::Connection {
net_type: NetworkType::Internet,
address_type: AddressType::IPv4,
address: main_ip.unwrap(),
ttl: Some(127),
num_addresses: Some(1),
suffix: None,
};
let base_media_props = vec![
connection,
// candidate.unwrap(),
fingerprint.unwrap(),
ufrag.unwrap(),
pwd.unwrap(),
MediaProp::Attribute {
key: "rtcp-mux".to_string(),
value: None
},
MediaProp::Attribute {
key: "rtcp".to_string(),
value: Some(ports[0].to_string())
},
MediaProp::Attribute {
key: "setup".to_string(),
value: Some("passive".to_string())
},
MediaProp::Attribute {
key: "inactive".to_string(),
value: None
}
];
let mut video_vec_attrs = ["ccm fir", "nack", "nack pli", "goog-remb", "transport-cc"].into_iter().map(|val| {
MediaProp::Attribute {
key: "rtcp-fb".to_string(),
value: Some(format!("{} {}", video_payload_type, val))
}
}).collect::<Vec<_>>();
video_vec_attrs.append(&mut [
"2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time",
"3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01",
"14 urn:ietf:params:rtp-hdrext:toffset",
"13 urn:3gpp:video-orientation",
"5 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay"
].into_iter().map(|ext| {
MediaProp::Attribute {
key: "extmap".to_string(),
value: Some(ext.to_string())
}
}).collect::<Vec<_>>());
video_vec_attrs.append(&mut vec![
MediaProp::Attribute {
key: "fmtp".to_string(),
value: Some(format!("{} x-google-max-bitrate=2500;level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f", video_payload_type))
},
MediaProp::Attribute {
key: "fmtp".to_string(),
value: Some(format!("{} apt={}", rtx_payload_type, video_payload_type))
},
MediaProp::Attribute {
key: "mid".to_string(),
value: Some(0.to_string())
},
MediaProp::Attribute {
key: "rtpmap".to_string(),
value: Some(format!("{} {}/90000", video_payload_type, encoder.type_string()))
},
MediaProp::Attribute {
key: "rtpmap".to_string(),
value: Some(format!("{} rtx/90000", rtx_payload_type))
},
candidate.unwrap(),
MediaProp::Attribute {
key: "end-of-candidates".to_string(),
value: None
}
]);
let video_media = SdpProp::Media {
r#type: MediaType::Video,
ports: ports.clone(),
protocol: format!("UDP/TLS/RTP/SAVPF {} {}", video_payload_type, rtx_payload_type),
format: "".to_string(),
props: base_media_props.clone().into_iter().chain(video_vec_attrs.into_iter()).collect::<Vec<_>>()
};
let mut audio_vec_attrs = [
"1 urn:ietf:params:rtp-hdrext:ssrc-audio-level",
"3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01"
].into_iter().map(|ext| {
MediaProp::Attribute {
key: "extmap".to_string(),
value: Some(ext.to_string())
}
}).collect::<Vec<_>>();
audio_vec_attrs.append(&mut vec![
MediaProp::Attribute {
key: "fmtp".to_string(),
value: Some("111 minptime=10;useinbandfec=1;usedtx=1".to_string())
},
MediaProp::Attribute {
key: "maxptime".to_string(),
value: Some(60.to_string())
},
MediaProp::Attribute {
key: "rtpmap".to_string(),
value: Some("111 opus/90000".to_string())
},
MediaProp::Attribute {
key: "rtcp-fb".to_string(),
value: Some("111 transport-cc".to_string())
},
MediaProp::Attribute {
key: "mid".to_string(),
value: Some(1.to_string())
}
]);
let audio_media = SdpProp::Media {
r#type: MediaType::Audio,
ports,
protocol: "UDP/TLS/RTP/SAVPF 111".to_string(),
format: "".to_string(),
props: base_media_props.clone().into_iter().chain(audio_vec_attrs.into_iter()).collect::<Vec<_>>()
};
// Generate answer
let answer = SDP { props: vec![
SdpProp::Version(0),
SdpProp::Origin {
username: "-".to_string(),
session_id: "1420070400000".to_string(),
session_version: 0,
net_type: NetworkType::Internet,
address_type: AddressType::IPv4,
address: "127.0.0.1".to_string()
},
SdpProp::SessionName("-".to_string()),
SdpProp::Timing {
start: 0,
stop: 0
},
SdpProp::Attribute {
key: "msid-semantic".to_string(),
value: Some(" WMS *".to_string())
},
SdpProp::Attribute {
key: "group".to_string(),
value: Some("BUNDLE 0 1".to_string())
},
video_media,
audio_media
]};
trace!("[WebRTC] Generated remote SDP: {}", answer.to_string());
redux_arc.lock().await.set_remote_description(&answer, RTCSdpType::Answer).await.expect("Failed to set remote description");
info!("[WebRTC] Remote description set");
}
_ => unreachable!()
}
})
})).await.expect("Failed to set on ice gathering change");
Ok(StateChangeSuccess::Success)
}
Local SDP after ICE gathering completes:
v=0
o=- 3006164469565782471 253007078 IN IP4 0.0.0.0
s=-
t=0 0
a=fingerprint:sha-256 F5:34:75:08:3E:AB:99:1E:5F:79:BF:6D:14:EC:D6:C2:F6:20:74:D6:D3:1D:78:48:58:B6:1E:2B:32:F3:D9:64
a=group:BUNDLE 0 1
m=video 9 UDP/TLS/RTP/SAVPF 96 97 98 99 100 101 102 121 127 120 125 107 108 109 123 118 116
c=IN IP4 0.0.0.0
a=setup:actpass
a=mid:0
a=ice-ufrag:cWRCBPTiuOohkLsf
a=ice-pwd:mHMqXcRexKOkbHKAZlvxjgvLFtdHiZAL
a=rtcp-mux
a=rtcp-rsize
a=rtpmap:96 VP8/90000
a=rtcp-fb:96 goog-remb
a=rtcp-fb:96 ccm fir
a=rtcp-fb:96 nack
a=rtcp-fb:96 nack pli
a=rtcp-fb:96 nack
a=rtcp-fb:96 nack pli
a=rtcp-fb:96 transport-cc
a=rtpmap:97 rtx/90000
a=fmtp:97 apt=96
a=rtcp-fb:97 nack
a=rtcp-fb:97 nack pli
a=rtcp-fb:97 transport-cc
a=rtpmap:98 VP9/90000
a=fmtp:98 profile-id=0
a=rtcp-fb:98 goog-remb
a=rtcp-fb:98 ccm fir
a=rtcp-fb:98 nack
a=rtcp-fb:98 nack pli
a=rtcp-fb:98 nack
a=rtcp-fb:98 nack pli
a=rtcp-fb:98 transport-cc
a=rtpmap:99 rtx/90000
a=fmtp:99 apt=98
a=rtcp-fb:99 nack
a=rtcp-fb:99 nack pli
a=rtcp-fb:99 transport-cc
a=rtpmap:100 VP9/90000
a=fmtp:100 profile-id=1
a=rtcp-fb:100 goog-remb
a=rtcp-fb:100 ccm fir
a=rtcp-fb:100 nack
a=rtcp-fb:100 nack pli
a=rtcp-fb:100 nack
a=rtcp-fb:100 nack pli
a=rtcp-fb:100 transport-cc
a=rtpmap:101 rtx/90000
a=fmtp:101 apt=100
a=rtcp-fb:101 nack
a=rtcp-fb:101 nack pli
a=rtcp-fb:101 transport-cc
a=rtpmap:102 H264/90000
a=fmtp:102 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f
a=rtcp-fb:102 goog-remb
a=rtcp-fb:102 ccm fir
a=rtcp-fb:102 nack
a=rtcp-fb:102 nack pli
a=rtcp-fb:102 nack
a=rtcp-fb:102 nack pli
a=rtcp-fb:102 transport-cc
a=rtpmap:121 rtx/90000
a=fmtp:121 apt=102
a=rtcp-fb:121 nack
a=rtcp-fb:121 nack pli
a=rtcp-fb:121 transport-cc
a=rtpmap:127 H264/90000
a=fmtp:127 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42001f
a=rtcp-fb:127 goog-remb
a=rtcp-fb:127 ccm fir
a=rtcp-fb:127 nack
a=rtcp-fb:127 nack pli
a=rtcp-fb:127 nack
a=rtcp-fb:127 nack pli
a=rtcp-fb:127 transport-cc
a=rtpmap:120 rtx/90000
a=fmtp:120 apt=127
a=rtcp-fb:120 nack
a=rtcp-fb:120 nack pli
a=rtcp-fb:120 transport-cc
a=rtpmap:125 H264/90000
a=fmtp:125 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f
a=rtcp-fb:125 goog-remb
a=rtcp-fb:125 ccm fir
a=rtcp-fb:125 nack
a=rtcp-fb:125 nack pli
a=rtcp-fb:125 nack
a=rtcp-fb:125 nack pli
a=rtcp-fb:125 transport-cc
a=rtpmap:107 rtx/90000
a=fmtp:107 apt=125
a=rtcp-fb:107 nack
a=rtcp-fb:107 nack pli
a=rtcp-fb:107 transport-cc
a=rtpmap:108 H264/90000
a=fmtp:108 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42e01f
a=rtcp-fb:108 goog-remb
a=rtcp-fb:108 ccm fir
a=rtcp-fb:108 nack
a=rtcp-fb:108 nack pli
a=rtcp-fb:108 nack
a=rtcp-fb:108 nack pli
a=rtcp-fb:108 transport-cc
a=rtpmap:109 rtx/90000
a=fmtp:109 apt=108
a=rtcp-fb:109 nack
a=rtcp-fb:109 nack pli
a=rtcp-fb:109 transport-cc
a=rtpmap:123 H264/90000
a=fmtp:123 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=640032
a=rtcp-fb:123 goog-remb
a=rtcp-fb:123 ccm fir
a=rtcp-fb:123 nack
a=rtcp-fb:123 nack pli
a=rtcp-fb:123 nack
a=rtcp-fb:123 nack pli
a=rtcp-fb:123 transport-cc
a=rtpmap:118 rtx/90000
a=fmtp:118 apt=123
a=rtcp-fb:118 nack
a=rtcp-fb:118 nack pli
a=rtcp-fb:118 transport-cc
a=rtpmap:116 ulpfec/90000
a=rtcp-fb:116 nack
a=rtcp-fb:116 nack pli
a=rtcp-fb:116 transport-cc
a=extmap:1 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
a=ssrc:3980097584 cname:video_0
a=ssrc:3980097584 msid:video_0 video
a=ssrc:3980097584 mslabel:video_0
a=ssrc:3980097584 label:video
a=msid:video_0 video
a=sendrecv
a=candidate:167090039 1 udp 2130706431 :: 48818 typ host
a=candidate:167090039 2 udp 2130706431 :: 48818 typ host
a=candidate:2938512866 1 udp 2130706431 192.168.1.100 47953 typ host
a=candidate:2938512866 2 udp 2130706431 192.168.1.100 47953 typ host
a=candidate:2414835526 1 udp 1694498815 72.196.215.130 35989 typ srflx raddr 0.0.0.0 rport 35989
a=candidate:2414835526 2 udp 1694498815 72.196.215.130 35989 typ srflx raddr 0.0.0.0 rport 35989
a=candidate:2414835526 1 udp 1694498815 72.196.215.130 37580 typ srflx raddr 0.0.0.0 rport 37580
a=candidate:2414835526 2 udp 1694498815 72.196.215.130 37580 typ srflx raddr 0.0.0.0 rport 37580
a=candidate:2414835526 1 udp 1694498815 72.196.215.130 59238 typ srflx raddr 0.0.0.0 rport 59238
a=candidate:2414835526 2 udp 1694498815 72.196.215.130 59238 typ srflx raddr 0.0.0.0 rport 59238
a=candidate:2414835526 1 udp 1694498815 72.196.215.130 53377 typ srflx raddr 0.0.0.0 rport 53377
a=candidate:2414835526 2 udp 1694498815 72.196.215.130 53377 typ srflx raddr 0.0.0.0 rport 53377
a=candidate:1022905401 1 udp 16777215 34.203.251.215 29290 typ relay raddr 0.0.0.0 rport 38594
a=candidate:1022905401 2 udp 16777215 34.203.251.215 29290 typ relay raddr 0.0.0.0 rport 38594
a=end-of-candidates
m=audio 9 UDP/TLS/RTP/SAVPF 111 9 0 8
c=IN IP4 0.0.0.0
a=setup:actpass
a=mid:1
a=ice-ufrag:cWRCBPTiuOohkLsf
a=ice-pwd:mHMqXcRexKOkbHKAZlvxjgvLFtdHiZAL
a=rtcp-mux
a=rtcp-rsize
a=rtpmap:111 opus/48000/2
a=fmtp:111 minptime=10;useinbandfec=1
a=rtcp-fb:111 transport-cc
a=rtpmap:9 G722/8000
a=rtcp-fb:9 transport-cc
a=rtpmap:0 PCMU/8000
a=rtcp-fb:0 transport-cc
a=rtpmap:8 PCMA/8000
a=rtcp-fb:8 transport-cc
a=extmap:1 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
a=ssrc:597106938 cname:audio_0
a=ssrc:597106938 msid:audio_0 audio
a=ssrc:597106938 mslabel:audio_0
a=ssrc:597106938 label:audio
a=msid:audio_0 audio
a=sendrecv
Generated remote SDP:
v=0
o=- 1420070400000 0 IN IP4 127.0.0.1
s=-
t=0 0
a=msid-semantic: WMS *
a=group:BUNDLE 0 1
m=video 50016 UDP/TLS/RTP/SAVPF 98 97
c=IN IP4 66.22.231.190/127/1
a=fingerprint:sha-256 4A:79:94:16:44:3F:BD:05:41:5A:C7:20:F3:12:54:70:00:73:5D:33:00:2D:2C:80:9B:39:E1:9F:2D:A7:49:87
a=ice-ufrag:PkLE
a=ice-pwd:o9QGn2N6YizFOM/UNojYai
a=rtcp-mux
a=rtcp:50016
a=setup:passive
a=inactive
a=rtcp-fb:98 ccm fir
a=rtcp-fb:98 nack
a=rtcp-fb:98 nack pli
a=rtcp-fb:98 goog-remb
a=rtcp-fb:98 transport-cc
a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
a=extmap:14 urn:ietf:params:rtp-hdrext:toffset
a=extmap:13 urn:3gpp:video-orientation
a=extmap:5 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay
a=fmtp:98 x-google-max-bitrate=2500;level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f
a=fmtp:97 apt=98
a=mid:0
a=rtpmap:98 VP9/90000
a=rtpmap:97 rtx/90000
a=candidate:1 1 UDP 4261412862 66.22.231.190 50016 typ host
a=end-of-candidates
m=audio 50016 UDP/TLS/RTP/SAVPF 111
c=IN IP4 66.22.231.190/127/1
a=fingerprint:sha-256 4A:79:94:16:44:3F:BD:05:41:5A:C7:20:F3:12:54:70:00:73:5D:33:00:2D:2C:80:9B:39:E1:9F:2D:A7:49:87
a=ice-ufrag:PkLE
a=ice-pwd:o9QGn2N6YizFOM/UNojYai
a=rtcp-mux
a=rtcp:50016
a=setup:passive
a=inactive
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
a=fmtp:111 minptime=10;useinbandfec=1;usedtx=1
a=maxptime:60
a=rtpmap:111 opus/90000
a=rtcp-fb:111 transport-cc
a=mid:1
After setting the remote answer SDP the ICE connection state changes to "checking", but after about 20 seconds it changes to "failing" and kills the connection. Is there something wrong I'm doing in terms of the SDPs or my code?
Edit: I got logging working, here is the connection log:
https://pastebin.com/vNvd3Af6
Edit 2: I'm not receiving any inbound traffic from the STUN servers. Other programs using the same ICE servers work fine, so what could I be doing wrong outside of basic network configuration?
Edit 3: Here is a working ICE connection capture and here is the one I'm currently dealing with.
Edit 4: I ran netstat to see what ports my code is listening on, and there are some differences. I cut out all other programs.
Here is the working ICE connection:
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 192.168.1.100:41383 0.0.0.0:* LISTEN 37973/target/debug/
tcp 0 0 192.168.1.100:51469 0.0.0.0:* LISTEN 37973/target/debug/
tcp6 0 0 fe80::60d2:bcaa:a:40899 :::* LISTEN 37973/target/debug/
udp 0 0 192.168.1.100:44897 0.0.0.0:* 37973/target/debug/
udp 0 0 239.255.255.250:1900 0.0.0.0:* 37973/target/debug/
udp 0 0 192.168.1.100:1900 0.0.0.0:* 37973/target/debug/
udp 0 0 239.255.255.250:1900 0.0.0.0:* 37973/target/debug/
udp 0 0 127.0.0.1:1900 0.0.0.0:* 37973/target/debug/
udp 0 0 127.0.0.1:37386 0.0.0.0:* 37973/target/debug/
udp 0 0 192.168.1.100:59877 0.0.0.0:* 37973/target/debug/
udp6 0 0 fe80::60d2:bcaa:a:56003 :::* 37973/target/debug/
Here is the non-working connection:
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
udp 0 0 0.0.0.0:50651 0.0.0.0:* 37186/target/debug/
udp 0 0 0.0.0.0:51996 0.0.0.0:* 37186/target/debug/
udp 0 0 0.0.0.0:35776 0.0.0.0:* 37186/target/debug/
udp 0 0 0.0.0.0:53036 0.0.0.0:* 37186/target/debug/
udp 0 0 224.0.0.251:5353 0.0.0.0:* 37186/target/debug/
udp 0 0 0.0.0.0:40115 0.0.0.0:* 37186/target/debug/
udp 0 0 192.168.1.100:40707 0.0.0.0:* 37186/target/debug/
udp6 0 0 :::37965 :::* 37186/target/debug/
The server I was communicating with only accepted LF line endings, while I was sending CRLF in my new implementation. Changing it to LF fixed the issue.

pygatt connects but unable to subscribe vs. bleak connects and able to subscribe: why isn't bleak replicable with pygatt?

I am trying to subscribe to single characteristic on a BLE device. Using bleak I am able to connect to the device and then write / subscribe to characteristics. With virtually identical code using pygatt, I can connect to the same device using my BLED112 dongle, but am not able to write/subscribe to that same characteristic.
bleak test program:
import sys
import os
import asyncio
import aioconsole
from bleak import BleakClient
ADDRESS = '28686572-5A71-435E-952A-6F4292F5B04A'
#ADDRESS = '00:55:DA:B7:98:9C'
CHARACTERISTIC_UUID = '273e0003-4c4d-454d-96be-f03bac821358'
if len(sys.argv) == 3:
ADDRESS = sys.argv[1]
CHARACTERISTIC_UUID = sys.argv[2]
def notification_handler(sender, data):
"""Simple notification handler which prints the data received."""
print("{0}: {1}".format(sender, data))
async def run(address):
async with BleakClient(address) as client:
await client.connect()
print("Is connected")
# start notifications on control characteristic
await client.start_notify('273e0001-4c4d-454d-96be-f03bac821358', notification_handler)
# write to control handle, set preset to 21
await client.write_gatt_char('273e0001-4c4d-454d-96be-f03bac821358', bytearray([0x04, 0x70, 0x32, 0x31, 0x0a]), False)
# write to control handle get device info
await client.write_gatt_char('273e0001-4c4d-454d-96be-f03bac821358', bytearray([0x03, 0x76, 0x31, 0x0a]), False)
# write to control handle for resume
await client.write_gatt_char('273e0001-4c4d-454d-96be-f03bac821358', bytearray([0x02, 0x64, 0x0a]), False)
# start notifications on TP9
await client.start_notify('273e0003-4c4d-454d-96be-f03bac821358', notification_handler)
# wait for input
await aioconsole.ainput('Running: Press a key to quit')
await client.stop_notify('273e0003-4c4d-454d-96be-f03bac821358')
if __name__ == "__main__":
os.environ["PYTHONASYNCIODEBUG"] = str(1)
loop = asyncio.get_event_loop()
loop.run_until_complete(run(ADDRESS))
Output:
$ python3 bleaktest.py
Is connected
13: bytearray(b'\x08{"rc":0}\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
13: bytearray(b'\x10{"ap":"headset",\x00\x00\x00')
13: bytearray(b'\x13"sp":"Blackcomb_rev')
13: bytearray(b'\x03B",":"Blackcomb_rev')
13: bytearray(b'\x10"tp":"consumer",rev')
13: bytearray(b'\x0c"hw":"10.6",er",rev')
13: bytearray(b'\x07"bn":2,0.6",er",rev')
13: bytearray(b'\x0e"fw":"1.0.21",",rev')
13: bytearray(b'\r"bl":"1.0.0",,",rev')
13: bytearray(b'\x07"pv":1,.0.0",,",rev')
13: bytearray(b'\x07"rc":0}.0.0",,",rev')
Running: Press a key to quit
13: bytearray(b'\x08{"rc":0}0.0",,",rev')
31: bytearray(b'\x00\x00\x80\x08\x00z\xa8\xdfL#\x00\xa8!\xb6p\xa0\x00hA\x92')
31: bytearray(b'\x00\x01\x9d0\x00]q\x86\xb5\xb0\x00+\xaf\x96\xf3#\x1a\x00\t\x88')
31: bytearray(b'\x00\x02\x1bh\x04\x00\x06\x14\x18\t\xe8\x00\x05&\x13\xdc%\x00\x01\x97')
...
31: bytearray(b'\x00\x19_\xf1\x85\x9e\xc0\x00GP\xe9\xcb#\x00\t\x9c\xaf\x11\x15\xe4')
...
As you can see from the output, the writes are successful because of the response handles. And the subscriptions are clearly functional given the responses from both the control characteristic and the secondary characteristic.
pygatt test program:
import pygatt
import time
from binascii import hexlify
from pygatt.backends.backend import BLEAddressType
def handle_data(handle, data):
"""
handle -- integer, characteristic read handle the data was received on
raw_value -- bytearray, the data returned in the notification
"""
print(hexlify(data))
#adapter = pygatt.GATTToolBackend('hci0') linux backend
adapter = pygatt.BGAPIBackend()
try:
adapter.start()
device = adapter.connect('00:55:DA:B7:98:9C', address_type = BLEAddressType.public)
print("Is connected")
# start notifications on control characteristic
device.subscribe('273e0001-4c4d-454d-96be-f03bac821358', callback = handle_data, wait_for_response = True)
# write to control handle, set preset to 21
device.char_write('273e0001-4c4d-454d-96be-f03bac821358', bytearray([0x04, 0x70, 0x32, 0x31, 0x0a]), wait_for_response = True)
# write to control handle get device info
device.char_write('273e0001-4c4d-454d-96be-f03bac821358', bytearray([0x03, 0x76, 0x31, 0x0a]), wait_for_response = True)
# write to control handle for resume
device.char_write('273e0001-4c4d-454d-96be-f03bac821358', bytearray([0x02, 0x64, 0x0a]), wait_for_response = True)
time.sleep(5)
# subscribe to eeg characteristic
device.subscribe('273e0003-4c4d-454d-96be-f03bac821358', callback = handle_data, indication = False, wait_for_response = True)
time.sleep(5)
finally:
print("Adapter stopped")
adapter.stop()
Output:
$ python3 pygatttest.py
Is connected
Adapter stopped
The pygatt program is able to connect to the device (I can see the indicator light change states from flashing to solid), but subscription fails. I don't know if char_write is working because I don't receive a return notification. Am in the process of trying the logging module to figure out more per the comments below.
Updated output with logging enabled:
$ python3 pygatttest.py
INFO:pygatt.backends.bgapi.bgapi:Initialized new BGAPI backend
INFO:pygatt.backends.bgapi.bgapi:Auto-detecting serial port for BLED112
DEBUG:pygatt.backends.bgapi.util:Found 4 serial USB devices
DEBUG:pygatt.backends.bgapi.util:Checking serial USB device: /dev/cu.Bluetooth-Incoming-Port - n/a
DEBUG:pygatt.backends.bgapi.util:Checking serial USB device: /dev/cu.usbmodem11 - Low Energy Dongle - CDC data
DEBUG:pygatt.backends.bgapi.util:USB device: Low Energy Dongle - CDC data VID=0x2458 PID=0x0001 on /dev/cu.usbmodem11
INFO:pygatt.backends.bgapi.bgapi:Found BLED112 on serial port /dev/cu.usbmodem11
INFO:pygatt.backends.bgapi.bgapi:Resetting and reconnecting to device for a clean environment
DEBUG:pygatt.backends.bgapi.bgapi:Opening connection to serial port (attempt 1)
INFO:pygatt.backends.bgapi.bgapi:Auto-detecting serial port for BLED112
DEBUG:pygatt.backends.bgapi.util:Found 4 serial USB devices
DEBUG:pygatt.backends.bgapi.util:Checking serial USB device: /dev/cu.Bluetooth-Incoming-Port - n/a
DEBUG:pygatt.backends.bgapi.util:Checking serial USB device: /dev/cu.usbmodem11 - Low Energy Dongle - CDC data
DEBUG:pygatt.backends.bgapi.util:USB device: Low Energy Dongle - CDC data VID=0x2458 PID=0x0001 on /dev/cu.usbmodem11
INFO:pygatt.backends.bgapi.bgapi:Found BLED112 on serial port /dev/cu.usbmodem11
DEBUG:pygatt.backends.bgapi.bgapi:Opening connection to serial port (attempt 1)
INFO:pygatt.backends.bgapi.bgapi:Auto-detecting serial port for BLED112
DEBUG:pygatt.backends.bgapi.util:Found 3 serial USB devices
DEBUG:pygatt.backends.bgapi.util:Checking serial USB device: /dev/cu.Bluetooth-Incoming-Port - n/a
DEBUG:pygatt.backends.bgapi.bgapi:Failed to open serial port
Traceback (most recent call last):
File ".../pygatt/backends/bgapi/bgapi.py", line 171, in _open_serial_port
serial_port = self._serial_port or self._detect_device_port()
File ".../pygatt/backends/bgapi/bgapi.py", line 147, in _detect_device_port
raise BGAPIError("Unable to auto-detect BLED112 serial port")
pygatt.backends.bgapi.exceptions.BGAPIError: Unable to auto-detect BLED112 serial port
DEBUG:pygatt.backends.bgapi.bgapi:Opening connection to serial port (attempt 2)
INFO:pygatt.backends.bgapi.bgapi:Auto-detecting serial port for BLED112
DEBUG:pygatt.backends.bgapi.util:Found 3 serial USB devices
DEBUG:pygatt.backends.bgapi.util:Checking serial USB device: /dev/cu.Bluetooth-Incoming-Port - n/a
...
DEBUG:pygatt.backends.bgapi.bgapi:Failed to open serial port
Traceback (most recent call last):
File ".../pygatt/backends/bgapi/bgapi.py", line 171, in _open_serial_port
serial_port = self._serial_port or self._detect_device_port()
File ".../pygatt/backends/bgapi/bgapi.py", line 147, in _detect_device_port
raise BGAPIError("Unable to auto-detect BLED112 serial port")
pygatt.backends.bgapi.exceptions.BGAPIError: Unable to auto-detect BLED112 serial port
DEBUG:pygatt.backends.bgapi.bgapi:Opening connection to serial port (attempt 3)
INFO:pygatt.backends.bgapi.bgapi:Auto-detecting serial port for BLED112
DEBUG:pygatt.backends.bgapi.util:Found 4 serial USB devices
DEBUG:pygatt.backends.bgapi.util:Checking serial USB device: /dev/cu.Bluetooth-Incoming-Port - n/a
...
DEBUG:pygatt.backends.bgapi.util:Checking serial USB device: /dev/cu.usbmodem11 - Low Energy Dongle - CDC data
DEBUG:pygatt.backends.bgapi.util:USB device: Low Energy Dongle - CDC data VID=0x2458 PID=0x0001 on /dev/cu.usbmodem11
INFO:pygatt.backends.bgapi.bgapi:Found BLED112 on serial port /dev/cu.usbmodem11
INFO:pygatt.backends.bgapi.bgapi:Running receiver
INFO:pygatt.backends.bgapi.bgapi:Disabling advertising
DEBUG:pygatt.backends.bgapi.bgapi:Expecting a response of one of [<ResponsePacketType.gap_set_mode: 58>] within 1.000000s
DEBUG:pygatt.backends.bgapi.bgapi:Received a ResponsePacketType.gap_set_mode packet: Success
DEBUG:pygatt.backends.bgapi.bgapi:Expecting a response of one of [<ResponsePacketType.sm_set_bondable_mode: 51>] within 1.000000s
DEBUG:pygatt.backends.bgapi.bgapi:Received a ResponsePacketType.sm_set_bondable_mode packet: Success
DEBUG:pygatt.backends.bgapi.bgapi:Stopping any outstanding GAP procedure
DEBUG:pygatt.backends.bgapi.bgapi:Expecting a response of one of [<ResponsePacketType.gap_end_procedure: 61>] within 1.000000s
DEBUG:pygatt.backends.bgapi.bgapi:Received a ResponsePacketType.gap_end_procedure packet: Device in wrong state
INFO:pygatt.backends.bgapi.bgapi:Connecting to device at address 00:55:DA:B7:98:9C (timeout 5s)
DEBUG:pygatt.backends.bgapi.bgapi:Expecting a response of one of [<ResponsePacketType.sm_set_bondable_mode: 51>] within 1.000000s
DEBUG:pygatt.backends.bgapi.bgapi:Received a ResponsePacketType.sm_set_bondable_mode packet: Success
DEBUG:pygatt.backends.bgapi.bgapi:Expecting a response of one of [<ResponsePacketType.gap_connect_direct: 60>] within 1.000000s
DEBUG:pygatt.backends.bgapi.bgapi:Received a ResponsePacketType.gap_connect_direct packet: Success
DEBUG:pygatt.backends.bgapi.bgapi:Expecting a response of one of [<EventPacketType.connection_status: 11>] within 5.000000s
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.connection_status packet: Success
INFO:pygatt.backends.bgapi.bgapi:Connection status: handle=0x0, flags=5, address=0xb'9c98b7da5500', connection interval=75.000000ms, timeout=1000, latency=0 intervals, bonding=0xff
INFO:pygatt.backends.bgapi.bgapi:Connected to 00:55:DA:B7:98:9C
Is connected
DEBUG:pygatt.device:Looking up handle for characteristic 273e0001-4c4d-454d-96be-f03bac821358
INFO:pygatt.backends.bgapi.bgapi:Fetching characteristics for connection 0
DEBUG:pygatt.backends.bgapi.bgapi:Expecting a response of one of [<ResponsePacketType.attclient_find_information: 41>] within 1.000000s
DEBUG:pygatt.backends.bgapi.bgapi:Received a ResponsePacketType.attclient_find_information packet: Success
DEBUG:pygatt.backends.bgapi.bgapi:Expecting a response of one of [<EventPacketType.attclient_procedure_completed: 17>] within 30.000000s
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
INFO:pygatt.backends.bgapi.bgapi:Found approved characteristic 00002a05-0000-1000-8000-00805f9b34fb
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
INFO:pygatt.backends.bgapi.bgapi:Found approved characteristic 00002a00-0000-1000-8000-00805f9b34fb
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
INFO:pygatt.backends.bgapi.bgapi:Found approved characteristic 00002a01-0000-1000-8000-00805f9b34fb
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
INFO:pygatt.backends.bgapi.bgapi:Found approved characteristic 00002a04-0000-1000-8000-00805f9b34fb
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
INFO:pygatt.backends.bgapi.bgapi:Found custom characteristic 273e0001-4c4d-454d-96be-f03bac821358
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
INFO:pygatt.backends.bgapi.bgapi:Found custom characteristic 273e0008-4c4d-454d-96be-f03bac821358
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
INFO:pygatt.backends.bgapi.bgapi:Found custom characteristic 273e0009-4c4d-454d-96be-f03bac821358
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
INFO:pygatt.backends.bgapi.bgapi:Found custom characteristic 273e000a-4c4d-454d-96be-f03bac821358
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
INFO:pygatt.backends.bgapi.bgapi:Found custom characteristic 273e000b-4c4d-454d-96be-f03bac821358
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
INFO:pygatt.backends.bgapi.bgapi:Found custom characteristic 273e0002-4c4d-454d-96be-f03bac821358
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
INFO:pygatt.backends.bgapi.bgapi:Found custom characteristic 273e0003-4c4d-454d-96be-f03bac821358
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
INFO:pygatt.backends.bgapi.bgapi:Found custom characteristic 273e0004-4c4d-454d-96be-f03bac821358
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
INFO:pygatt.backends.bgapi.bgapi:Found custom characteristic 273e0005-4c4d-454d-96be-f03bac821358
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
INFO:pygatt.backends.bgapi.bgapi:Found custom characteristic 273e0006-4c4d-454d-96be-f03bac821358
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
INFO:pygatt.backends.bgapi.bgapi:Found custom characteristic 273e0007-4c4d-454d-96be-f03bac821358
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
INFO:pygatt.backends.bgapi.bgapi:Found custom characteristic 273e000c-4c4d-454d-96be-f03bac821358
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
cDEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
INFO:pygatt.backends.bgapi.bgapi:Found custom characteristic 273e000d-4c4d-454d-96be-f03bac821358
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
INFO:pygatt.backends.bgapi.bgapi:Found custom characteristic 273e000e-4c4d-454d-96be-f03bac821358
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
INFO:pygatt.backends.bgapi.bgapi:Found custom characteristic 273e000f-4c4d-454d-96be-f03bac821358
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
INFO:pygatt.backends.bgapi.bgapi:Found custom characteristic 273e0010-4c4d-454d-96be-f03bac821358
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
INFO:pygatt.backends.bgapi.bgapi:Found custom characteristic 273e0011-4c4d-454d-96be-f03bac821358
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_find_information_found packet: Success
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_procedure_completed packet: Success
INFO:pygatt.backends.bgapi.bgapi:Characteristic 0x00002a05-0000-1000-8000-00805f9b34fb is handle 0x3
INFO:pygatt.backends.bgapi.bgapi:Characteristic descriptor 0x00002902-0000-1000-8000-00805f9b34fb is handle 0x4
INFO:pygatt.backends.bgapi.bgapi:Characteristic 0x00002a00-0000-1000-8000-00805f9b34fb is handle 0x7
INFO:pygatt.backends.bgapi.bgapi:Characteristic 0x00002a01-0000-1000-8000-00805f9b34fb is handle 0x9
INFO:pygatt.backends.bgapi.bgapi:Characteristic 0x00002a04-0000-1000-8000-00805f9b34fb is handle 0xb
INFO:pygatt.backends.bgapi.bgapi:Characteristic 0x273e0001-4c4d-454d-96be-f03bac821358 is handle 0xe
INFO:pygatt.backends.bgapi.bgapi:Characteristic descriptor 0x00002902-0000-1000-8000-00805f9b34fb is handle 0xf
INFO:pygatt.backends.bgapi.bgapi:Characteristic 0x273e0008-4c4d-454d-96be-f03bac821358 is handle 0x11
INFO:pygatt.backends.bgapi.bgapi:Characteristic descriptor 0x00002902-0000-1000-8000-00805f9b34fb is handle 0x12
INFO:pygatt.backends.bgapi.bgapi:Characteristic 0x273e0009-4c4d-454d-96be-f03bac821358 is handle 0x14
INFO:pygatt.backends.bgapi.bgapi:Characteristic descriptor 0x00002902-0000-1000-8000-00805f9b34fb is handle 0x15
INFO:pygatt.backends.bgapi.bgapi:Characteristic 0x273e000a-4c4d-454d-96be-f03bac821358 is handle 0x17
INFO:pygatt.backends.bgapi.bgapi:Characteristic descriptor 0x00002902-0000-1000-8000-00805f9b34fb is handle 0x18
INFO:pygatt.backends.bgapi.bgapi:Characteristic 0x273e000b-4c4d-454d-96be-f03bac821358 is handle 0x1a
INFO:pygatt.backends.bgapi.bgapi:Characteristic descriptor 0x00002902-0000-1000-8000-00805f9b34fb is handle 0x1b
INFO:pygatt.backends.bgapi.bgapi:Characteristic 0x273e0002-4c4d-454d-96be-f03bac821358 is handle 0x1d
INFO:pygatt.backends.bgapi.bgapi:Characteristic descriptor 0x00002902-0000-1000-8000-00805f9b34fb is handle 0x1e
INFO:pygatt.backends.bgapi.bgapi:Characteristic 0x273e0003-4c4d-454d-96be-f03bac821358 is handle 0x20
INFO:pygatt.backends.bgapi.bgapi:Characteristic descriptor 0x00002902-0000-1000-8000-00805f9b34fb is handle 0x21
INFO:pygatt.backends.bgapi.bgapi:Characteristic 0x273e0004-4c4d-454d-96be-f03bac821358 is handle 0x23
INFO:pygatt.backends.bgapi.bgapi:Characteristic descriptor 0x00002902-0000-1000-8000-00805f9b34fb is handle 0x24
INFO:pygatt.backends.bgapi.bgapi:Characteristic 0x273e0005-4c4d-454d-96be-f03bac821358 is handle 0x26
INFO:pygatt.backends.bgapi.bgapi:Characteristic descriptor 0x00002902-0000-1000-8000-00805f9b34fb is handle 0x27
INFO:pygatt.backends.bgapi.bgapi:Characteristic 0x273e0006-4c4d-454d-96be-f03bac821358 is handle 0x29
INFO:pygatt.backends.bgapi.bgapi:Characteristic descriptor 0x00002902-0000-1000-8000-00805f9b34fb is handle 0x2a
INFO:pygatt.backends.bgapi.bgapi:Characteristic 0x273e0007-4c4d-454d-96be-f03bac821358 is handle 0x2c
INFO:pygatt.backends.bgapi.bgapi:Characteristic descriptor 0x00002902-0000-1000-8000-00805f9b34fb is handle 0x2d
INFO:pygatt.backends.bgapi.bgapi:Characteristic 0x273e000c-4c4d-454d-96be-f03bac821358 is handle 0x2f
INFO:pygatt.backends.bgapi.bgapi:Characteristic descriptor 0x00002902-0000-1000-8000-00805f9b34fb is handle 0x30
INFO:pygatt.backends.bgapi.bgapi:Characteristic 0x273e000d-4c4d-454d-96be-f03bac821358 is handle 0x32
INFO:pygatt.backends.bgapi.bgapi:Characteristic descriptor 0x00002902-0000-1000-8000-00805f9b34fb is handle 0x33
INFO:pygatt.backends.bgapi.bgapi:Characteristic 0x273e000e-4c4d-454d-96be-f03bac821358 is handle 0x35
INFO:pygatt.backends.bgapi.bgapi:Characteristic descriptor 0x00002902-0000-1000-8000-00805f9b34fb is handle 0x36
INFO:pygatt.backends.bgapi.bgapi:Characteristic 0x273e000f-4c4d-454d-96be-f03bac821358 is handle 0x38
INFO:pygatt.backends.bgapi.bgapi:Characteristic descriptor 0x00002902-0000-1000-8000-00805f9b34fb is handle 0x39
INFO:pygatt.backends.bgapi.bgapi:Characteristic 0x273e0010-4c4d-454d-96be-f03bac821358 is handle 0x3b
INFO:pygatt.backends.bgapi.bgapi:Characteristic descriptor 0x00002902-0000-1000-8000-00805f9b34fb is handle 0x3c
INFO:pygatt.backends.bgapi.bgapi:Characteristic 0x273e0011-4c4d-454d-96be-f03bac821358 is handle 0x3e
INFO:pygatt.backends.bgapi.bgapi:Characteristic descriptor 0x00002902-0000-1000-8000-00805f9b34fb is handle 0x3f
DEBUG:pygatt.device:Found <Characteristic uuid=273e0001-4c4d-454d-96be-f03bac821358 handle=14>
DEBUG:pygatt.backends.bgapi.bgapi:Expecting a response of one of [<ResponsePacketType.attclient_attribute_write: 43>] within 1.000000s
DEBUG:pygatt.backends.bgapi.bgapi:Received a ResponsePacketType.attclient_attribute_write packet: Success
DEBUG:pygatt.backends.bgapi.bgapi:Expecting a response of one of [<EventPacketType.attclient_procedure_completed: 17>] within 30.000000s
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_procedure_completed packet: Success
INFO:pygatt.device:Subscribed to uuid=273e0001-4c4d-454d-96be-f03bac821358
DEBUG:pygatt.device:Looking up handle for characteristic 273e0001-4c4d-454d-96be-f03bac821358
DEBUG:pygatt.device:Found <Characteristic uuid=273e0001-4c4d-454d-96be-f03bac821358 handle=14>
DEBUG:pygatt.backends.bgapi.bgapi:Expecting a response of one of [<ResponsePacketType.attclient_attribute_write: 43>] within 1.000000s
DEBUG:pygatt.backends.bgapi.bgapi:Received a ResponsePacketType.attclient_attribute_write packet: Success
DEBUG:pygatt.backends.bgapi.bgapi:Expecting a response of one of [<EventPacketType.attclient_procedure_completed: 17>] within 30.000000s
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_procedure_completed packet: Write not permitted
DEBUG:pygatt.device:Looking up handle for characteristic 273e0001-4c4d-454d-96be-f03bac821358
DEBUG:pygatt.device:Found <Characteristic uuid=273e0001-4c4d-454d-96be-f03bac821358 handle=14>
DEBUG:pygatt.backends.bgapi.bgapi:Expecting a response of one of [<ResponsePacketType.attclient_attribute_write: 43>] within 1.000000s
DEBUG:pygatt.backends.bgapi.bgapi:Received a ResponsePacketType.attclient_attribute_write packet: Success
DEBUG:pygatt.backends.bgapi.bgapi:Expecting a response of one of [<EventPacketType.attclient_procedure_completed: 17>] within 30.000000s
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_procedure_completed packet: Write not permitted
DEBUG:pygatt.device:Looking up handle for characteristic 273e0001-4c4d-454d-96be-f03bac821358
DEBUG:pygatt.device:Found <Characteristic uuid=273e0001-4c4d-454d-96be-f03bac821358 handle=14>
DEBUG:pygatt.backends.bgapi.bgapi:Expecting a response of one of [<ResponsePacketType.attclient_attribute_write: 43>] within 1.000000s
DEBUG:pygatt.backends.bgapi.bgapi:Received a ResponsePacketType.attclient_attribute_write packet: Success
DEBUG:pygatt.backends.bgapi.bgapi:Expecting a response of one of [<EventPacketType.attclient_procedure_completed: 17>] within 30.000000s
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.attclient_procedure_completed packet: Write not permitted
DEBUG:pygatt.device:Looking up handle for characteristic 273e0003-4c4d-454d-96be-f03bac821358
DEBUG:pygatt.device:Found <Characteristic uuid=273e0003-4c4d-454d-96be-f03bac821358 handle=32>
DEBUG:pygatt.backends.bgapi.bgapi:Expecting a response of one of [<ResponsePacketType.attclient_attribute_write: 43>] within 1.000000s
DEBUG:pygatt.backends.bgapi.bgapi:Received a EventPacketType.connection_disconnected packet: Success
DEBUG:pygatt.backends.bgapi.bgapi:Received a ResponsePacketType.attclient_attribute_write packet: Not connected
DEBUG:pygatt.backends.bgapi.bgapi:Expecting a response of one of [<EventPacketType.attclient_procedure_completed: 17>] within 30.000000s
Adapter stopped
INFO:pygatt.backends.bgapi.bgapi:Stopping
INFO:pygatt.backends.bgapi.bgapi:Stopping receiver
I'm not sure if I'm interpreting this information correctly, but it seems as if the subscription is working and that I'm receiving information but the callback is not being fired?
I tried the solution here: pygatt: Unable to execute device.subscribe() by adding the time.sleep() lines to my code, but the output did not change.
How can I translate my bleak program to pygatt and subscribe successfully using pygatt?

Routing to an error channel if fault is thrown in outbound gateway in DSL

I have the following Spring Integration JAva DSL code:
return flow -> flow.channel(INPUT_CHANNEL)
.transform(customMapper, "mapFrom")
.enrichHeaders(polarisPreCompSoapActionHeader())
.route("headers.key",
subflowMapping -> subflowMapping
.subFlowMapping("value1", subflow -> subflow
.handle(webserviceOutboundGateway,
e -> e.advice(skipAdvice()))
)
)
.channel(OUTPUT_CHANNEL);
#Bean
public Advice skipAdvice() {
ExpressionEvaluatingRequestHandlerAdvice advice = new ExpressionEvaluatingRequestHandlerAdvice();
advice.setFailureChannel(errorChannel());
return advice;
}
The webserviceOutboundGateway is created as a bean of MarshallingWebServiceOutboundGateway.
What I am trying to achieve is to route the error message to the error channel when a SOAP fault arrives. I thought that I can add an advice to the handler and this advice should be an ExpressionEvaluatingRequestHandlerAdvice where I can set the failure channel. So whenever an error is thrown in the outbound gateway then the error message will be forwarded to the error channel.
Then problem is that now the gateway throw an exception and the flow stops
2020-05-20 22:21:48,161 INFO com.acme.Timing Thread=qtp14486859-12 MDC=16d7cc4c-c9da-449b-8bfa-504e6d81185d REQUEST COMPLETE : time[39]ms message[ProcessTran] endpoint[http://localhost:8081/system-integration-service/service]
2020-05-20 22:21:48,161 DEBUG org.springframework.integration.transformer.ContentEnricher$Gateway Thread=qtp14486859-12 MDC=16d7cc4c-c9da-449b-8bfa-504e6d81185d failure occurred in gateway sendAndReceive: error occurred in message handler [webserviceOutboundGateway]; nested exception is org.springframework.ws.client.WebServiceTransportException: Not Found [404]
2020-05-20 22:21:48,162 DEBUG org.springframework.integration.gateway.GatewayProxyFactoryBean$MethodInvocationGateway Thread=qtp14486859-12 MDC=16d7cc4c-c9da-449b-8bfa-504e6d81185d failure occurred in gateway sendAndReceive: error occurred in message handler [webserviceOutboundGateway]; nested exception is org.springframework.ws.client.WebServiceTransportException: Not Found [404]
2020-05-20 22:21:48,167 ERROR com.acme.webservice.OrchestrationServiceEndpoint Thread=qtp14486859-12 MDC=16d7cc4c-c9da-449b-8bfa-504e6d81185d Error
org.springframework.ws.client.WebServiceTransportException: Not Found [404]
at org.springframework.ws.client.core.WebServiceTemplate.handleError(WebServiceTemplate.java:699)
at org.springframework.ws.client.core.WebServiceTemplate.doSendAndReceive(WebServiceTemplate.java:609)
at org.springframework.ws.client.core.WebServiceTemplate.sendAndReceive(WebServiceTemplate.java:555)
at org.springframework.integration.ws.MarshallingWebServiceOutboundGateway.doHandle(MarshallingWebServiceOutboundGateway.java:87)
at com.acme.webservice.MarshallingWebServiceOutboundGateway.doHandle(MarshallingWebServiceOutboundGateway.java:60)
at org.springframework.integration.ws.AbstractWebServiceOutboundGateway.handleRequestMessage(AbstractWebServiceOutboundGateway.java:188)
at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:109)
at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:127)
at org.springframework.integration.dispatcher.AbstractDispatcher.tryOptimizedDispatch(AbstractDispatcher.java:116)
at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:148)
at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:121)
at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:89)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:425)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:375)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:183)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:162)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:47)
at org.springframework.messaging.core.AbstractMessageSendingTemplate.send(AbstractMessageSendingTemplate.java:108)
at org.springframework.integration.router.AbstractMessageRouter.handleMessageInternal(AbstractMessageRouter.java:194)
at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:127)
at org.springframework.integration.dispatcher.AbstractDispatcher.tryOptimizedDispatch(AbstractDispatcher.java:116)
at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:148)
at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:121)
at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:89)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:425)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:375)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:183)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:162)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:47)
at org.springframework.messaging.core.AbstractMessageSendingTemplate.send(AbstractMessageSendingTemplate.java:108)
at org.springframework.integration.handler.AbstractMessageProducingHandler.sendOutput(AbstractMessageProducingHandler.java:360)
at org.springframework.integration.handler.AbstractMessageProducingHandler.produceOutput(AbstractMessageProducingHandler.java:271)
at org.springframework.integration.handler.AbstractMessageProducingHandler.sendOutputs(AbstractMessageProducingHandler.java:188)
at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:115)
at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:127)
at org.springframework.integration.dispatcher.AbstractDispatcher.tryOptimizedDispatch(AbstractDispatcher.java:116)
at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:148)
at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:121)
at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:89)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:425)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:375)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:183)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:162)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:47)
Any advice / help would be highly appreciated!
Thanks,
V.
UPDATE1
I set the trapExecution to false, added the advice to the gateway directly and I had to use setOnFailureExpressionString otherwise the flow was hanging. So how it looks now as follows:
#Bean
#Autowired
public MarshallingWebServiceOutboundGateway webserviceOutboundGateway(...) {
MarshallingWebServiceOutboundGateway gateway = new ...;
gateway.setAdviceChain(Arrays.asList(skipAdvice()));
return gateway;
}
#Autowired
#Qualifier("skipCallChannel")
private MessageChannel skipCallChannel;
#Bean
public Advice skipAdvice() {
ExpressionEvaluatingRequestHandlerAdvice advice = new ExpressionEvaluatingRequestHandlerAdvice();
advice.setFailureChannel(endChannel);
advice.setOnFailureExpressionString("payload + ' was bad, with reason: ' + #exception");
advice.setTrapException(true);
return advice;
}
and I get the following error:
2020-05-21 14:45:13,921 DEBUG org.springframework.integration.handler.BridgeHandler Thread=qtp14486859-19 MDC=16d7cc4c-c9da-449b-8bfa-504e6d81185d org.springframework.integration.handler.BridgeHandler#cdf55 received message: ErrorMessage [payload=org.springframework.integration.handler.advice.ExpressionEvaluatingRequestHandlerAdvice$MessageHandlingExpressionEvaluatingAdviceException: Handler Failed; nested exception is org.springframework.ws.client.WebServiceTransportException: Not Found [404], failedMessage=GenericMessage [payload=uk.co.acme._2009._03.ProcessTran#1759824, headers={replyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel#1ddbf77, errorChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel#1ddbf77, header.cqs.model=com.acme.model.FlowModel#cc006f, ws_soapAction=http://www.acme.co.uk/XRTEService/2009/03/ProcessTran, id=59e305ee-1672-d5ba-db4b-672198f25ab8, timestamp=1590068713891}], headers={id=14aeb6ed-77af-52bf-6b53-72bc0a4bb5c1, timestamp=1590068713921}]
2020-05-21 14:45:13,922 DEBUG org.springframework.integration.transformer.ContentEnricher$Gateway Thread=qtp14486859-19 MDC=16d7cc4c-c9da-449b-8bfa-504e6d81185d failure occurred in gateway sendAndReceive: Dispatcher failed to deliver Message; nested exception is org.springframework.messaging.core.DestinationResolutionException: no output-channel or replyChannel header available
2020-05-21 14:45:13,922 DEBUG org.springframework.integration.gateway.GatewayProxyFactoryBean$MethodInvocationGateway Thread=qtp14486859-19 MDC=16d7cc4c-c9da-449b-8bfa-504e6d81185d failure occurred in gateway sendAndReceive: Dispatcher failed to deliver Message; nested exception is org.springframework.messaging.core.DestinationResolutionException: no output-channel or replyChannel header available
2020-05-21 14:45:13,927 ERROR com.acme.webservice.OrchestrationServiceEndpoint Thread=qtp14486859-19 MDC=16d7cc4c-c9da-449b-8bfa-504e6d81185d Error
org.springframework.messaging.MessagingException: Dispatcher failed to deliver Message; nested exception is org.springframework.messaging.core.DestinationResolutionException: no output-channel or replyChannel header available
at org.springframework.integration.dispatcher.AbstractDispatcher.wrapExceptionIfNecessary(AbstractDispatcher.java:133)
at org.springframework.integration.dispatcher.AbstractDispatcher.tryOptimizedDispatch(AbstractDispatcher.java:120)
at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:148)
at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:121)
at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:89)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:425)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:375)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:183)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:162)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:47)
at org.springframework.messaging.core.AbstractMessageSendingTemplate.send(AbstractMessageSendingTemplate.java:108)
at org.springframework.integration.handler.advice.ExpressionEvaluatingRequestHandlerAdvice.evaluateFailureExpression(ExpressionEvaluatingRequestHandlerAdvice.java:271)
at org.springframework.integration.handler.advice.ExpressionEvaluatingRequestHandlerAdvice.doInvoke(ExpressionEvaluatingRequestHandlerAdvice.java:221)
at org.springframework.integration.handler.advice.AbstractRequestHandlerAdvice.invoke(AbstractRequestHandlerAdvice.java:70)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
at com.sun.proxy.$Proxy190.handleRequestMessage(Unknown Source)
at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.doInvokeAdvisedRequestHandler(AbstractReplyProducingMessageHandler.java:127)
at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:112)
at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:127)
at org.springframework.integration.dispatcher.AbstractDispatcher.tryOptimizedDispatch(AbstractDispatcher.java:116)
at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:148)
at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:121)
at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:89)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:425)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:375)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:183)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:162)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:47)
at org.springframework.messaging.core.AbstractMessageSendingTemplate.send(AbstractMessageSendingTemplate.java:108)
at org.springframework.integration.router.AbstractMessageRouter.handleMessageInternal(AbstractMessageRouter.java:194)
at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:127)
at org.springframework.integration.dispatcher.AbstractDispatcher.tryOptimizedDispatch(AbstractDispatcher.java:116)
at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:148)
at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:121)
at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:89)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:425)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:375)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:183)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:162)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:47)
at org.springframework.messaging.core.AbstractMessageSendingTemplate.send(AbstractMessageSendingTemplate.java:108)
I presume I have to add channel for successful execution but I don't want to do that as it is already defined in the flow where the handler is (see .channel(OUTPUT_CHANNEL)). Can I set only the fault channel in the advice?
Thanks!
UPDATE2
I did what Gary recommended (i.e. added an error channel to the upstream flow) and the error message is delivered now to the error channel. However now I have another problem which vaguely relates to my original problem. So now I have the following exception:
2020-05-22 10:10:48,023 ERROR com.acme.webservice.OrchestrationServiceEndpoint Thread=qtp14486859-13 MDC=16d7cc4c-c9da-449b-8bfa-504e6d81185d Error
org.springframework.messaging.MessagingException: failure occurred in error-handling flow; nested exception is org.springframework.messaging.MessageDeliveryException: Dispatcher has no subscribers for channel 'enrich.acmeRequest.output'.; nested exception is org.springframework.integration.MessageDispatchingException: Dispatcher has no subscribers, failedMessage=GenericMessage [payload=uk.co.acme.payload.request._2017._06.Message#4a5e6c, headers={replyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel#19d4520, errorChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel#19d4520, ws_soapAction=http://www.acme.co.uk/XRTEService/ProcessTran, id=902bd270-89d8-62e9-b00f-b69399241bd1, timestamp=1590138648017}], ...}]
at org.springframework.integration.gateway.MessagingGatewaySupport.doSendAndReceive(MessagingGatewaySupport.java:489)
at org.springframework.integration.gateway.MessagingGatewaySupport.sendAndReceiveMessage(MessagingGatewaySupport.java:426)
at org.springframework.integration.transformer.ContentEnricher$Gateway.sendAndReceiveMessage(ContentEnricher.java:481)
at org.springframework.integration.transformer.ContentEnricher.handleRequestMessage(ContentEnricher.java:383)
at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:109)
at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:127)
at org.springframework.integration.dispatcher.AbstractDispatcher.tryOptimizedDispatch(AbstractDispatcher.java:116)
at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:148)
at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:121)
at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:89)
In the main flow I have the following:
return flow -> flow.channel(ORCH_REQUEST_INPUT)
.<HomeRequest, HomeModel>transform(requestToModelTransformer)
...
//
.enrich(this::acmePreCompRequestEnricher)
.enrich(this::acmePreCompEnricher)
.handle(this.acmePreCompResponseValidator())
//
.enrich(this::mlRequestEnricher)
.enrich(this::mlEnricher)
//
.enrich(this::acmeRequestEnricher)
.enrich(this::acmeEnricher)
...
The SOAP fault is thrown in acmePreCompEnricher where the outbound gateway is used. The error channel is set to skip.ml.input then I have to following flow which handles the fault:
return flow -> flow.channel("skip.ml.input")
.transform(ErrorMessage.class, (ErrorMessage m) -> {
Message originalMessage = ((MessageHandlingException)m.getPayload()).getFailedMessage();
return MessageBuilder.withPayload(originalMessage.getHeaders().get(HEADER_CQS_MODEL, HomeQuoteModel.class))
.copyHeaders(originalMessage.getHeaders())
.build();
})
.channel("enrich.acmeRequest.output");
The enrich.acmeRequest.output channel is the reply channel of acmeRequestEnricher. My intention is if there is no error then execute all the tasks in the flow but if there is a SOAP fault in acmePreCompEnricher then skip the mlRequestEnricher and mlEnricher and go straight to acmeRequestEnricher.
I presume the problem is that in the faul scenario the SI cannot see what subscribed to the channel of acmeRequestEnricher...? What can I do in this case?
See this method on the ExpressionEvaluatingRequestHandlerAdvice:
/**
* If true, any exception will be caught and null returned.
* Default false.
* #param trapException true to trap Exceptions.
*/
public void setTrapException(boolean trapException) {
So, set it to true to avoid exception rethrowing.
See more in Docs, too: https://docs.spring.io/spring-integration/docs/5.3.0.RELEASE/reference/html/messaging-endpoints.html#expression-advice
UPPDATE
Since everything works but advice, it looks like a bug in the obsolete Java DSL project. Please, consider to inject your skipAdvice into the webserviceOutboundGateway directly. It has a respective setter:
/**
* Configure a list of {#link Advice}s to proxy a {#link #handleRequestMessage(Message)} method.
* #param adviceChain the list of {#link Advice}s to use.
*/
public void setAdviceChain(List<Advice> adviceChain) {
UPDATE2
OK. Looks like you need to send a reply back, after processing that SOAP error.
So, you probably don't need that failureChannel configuration. The expression you have so far should be enough to trap an exception and send some plain string back to the gateway on top as a reply.
As Gary Russell recommended in one of his comments I set an error channel in the upstream flow (see UPDATE2).

RTSP1.0/ 404 Stream Not Found

I wanna get stream from camera:
DESCRIBE rtsp://192.168.1.200:554/ RTSP/1.0
CSeq: 1
Accept: application/sdpAuthorization: Basic YWRtaW46YWRtaW4=
RTSP/1.0 200 OK
CSeq: 1
Date: Wed, Feb 16 2011 10:17:47 GMT
Content-Base: rtsp://192.168.1.200:554/
Content-Type: application/sdp
Content-Length: 358
v=0
o=RTSP 1297842675200000 1 IN IP4 192.168.1.200
s=RTSP Server
t=0 0
a=range:npt=0-
a=control:*
m=video 0 RTP/AVP 96
c=IN IP4 0.0.0.0
a=rtpmap:96 MP4V-ES/90000
a=framerate:20
a=fmtp:96 profile-level-id=1;config=000001B001000001B50900000100000001200086C4004F0C14103C518F
a=control:track1
m=audio 0 RTP/AVP 0
c=IN IP4 0.0.0.0
a=control:track2
SETUP rtsp://192.168.1.200:554/trackID=1 RTSP/1.0
CSeq: 2
Transport: RTP/AVP/TCP;unicast;interleaved=0-1
Authorization: Basic YWRtaW46YWRtaW4=
**RTSP/1.0 404 Stream Not Found**
CSeq: 2
Date: Wed, Feb 16 2011 10:17:48 GMT
If use the VLC it can work but why do i get the 404?
In the SDP a=control:track1 and a=control:track2, whereas in the RTSP setup request you are using trackID=1. VLC is probably then doing this correctly?

SIP Callee does not get notification that call ended

I have deleted my previous question and post this updated:
I have a an issue with my SIP UAC, once I received a ringing from the B2BUA on both the caller and callee, and the caller hangs up the call while the call is ringing (I send cancel request and receive "request terminated" on the caller side), the callee does not get any notification that the call has been terminated by the caller.
But when the callee declines the call, the caller gets a busy here.
Here is the Callee side:
/----------------------- MEDIA SESSION ------------------------/
--- Multimedia-Session: Composed Audio ---
1. Media Session: "Audio" enabled=true
States:
[Disconnected]
Capturers: (1 in total)
Stream 1: audio device - DirectSoundCapture
Formats:
[PCMU/8000]
Connection Details:
My address: 10.0.0.2:52044
Participants: (1 in total)
Address 1: HostAddress:17364
/-------------------- END OF MEDIA SESSION --------------------/
/------------------------- BEGINNING --------------------------/
-------------------------------- Request: Test 2-->Me: INVITE#102 --------------------------------
INVITE sip:430#Host SIP/2.0
Via: SIP/2.0/UDP HostAddress:5060;branch=z9hG4bK1fd06834;rport=5060;received=HostAddress
From: "Test 2" <sip:410#HostAddress>;tag=as2b22eddf
To: <sip:430#Host>
Contact: <sip:410#HostAddress>
Call-ID: 35e0e8655b20ad886f137a0c0e563809#HostAddress
CSeq: 102 INVITE
User-Agent: Freeswitch 1.2.3
Max-Forwards: 70
Date: Sun, 11 Jul 2010 02:44:43 GMT
Allow: INVITE,ACK,CANCEL,OPTIONS,BYE,REFER,SUBSCRIBE,NOTIFY,INFO
Supported: replaces
Content-Type: application/sdp
Content-Length: 264
v=0
o=root 27669 27669 IN IP4 HostAddress
s=session
c=IN IP4 HostAddress
t=0 0
m=audio 17364 RTP/AVP 0 8 101
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-16
a=silenceSupp:off - - - -
a=ptime:20
a=sendrecv
------------------------ Response: Me ==> Test 2: INVITE#102: 180 Ringing ------------------------
SIP/2.0 180 Ringing
Via: SIP/2.0/UDP HostAddress:5060;branch=z9hG4bK1fd06834;rport=5060;received=HostAddress
From: "Test 2" <sip:410#HostAddress>;tag=as2b22eddf
To: <sip:430#Host>;tag=e125be76
Call-ID: 35e0e8655b20ad886f137a0c0e563809#HostAddress
CSeq: 102 INVITE
Content-Length: 0
------------------------ Response: Me ==> Test 2: INVITE#102: 603 Decline ------------------------
SIP/2.0 603 Decline
Via: SIP/2.0/UDP HostAddress:5060;branch=z9hG4bK1fd06834;rport=5060;received=HostAddress
From: "Test 2" <sip:410#HostAddress>;tag=as2b22eddf
To: <sip:430#Host>;tag=e125be76
Call-ID: 35e0e8655b20ad886f137a0c0e563809#HostAddress
CSeq: 102 INVITE
Content-Length: 0
/---------------------------- END -----------------------------/
I must decline at the callee end, because if I don't respond to the request, the callee account get stuck in a loop and then the client returns busy forever, and requests does not reach that client, or at least until the account is deleted.
And there is another thing, the B2BUA does not send anything back to the decline response, shouldn't I get an ACK from the server?
And here is the Caller side:
/----------------------- MEDIA SESSION ------------------------/
--- Multimedia-Session: Audio ---
1. Media Session: "Audio" enabled=true
States:
[Disconnected]
Capturers: (1 in total)
Stream 1: audio device - DirectSoundCapture
Formats:
[PCMU/8000]
[GSM/8000]
[G723/8000]
[DVI4/8000]
[MPA/-1]
[DVI4/11025]
[DVI4/22050]
Connection Details:
My address:
Participants: (0 in total)
/-------------------- END OF MEDIA SESSION --------------------/
/------------------------- BEGINNING --------------------------/
-------------------------- Request: Client 410-->Client 430: INVITE#81 --------------------------
INVITE sip:430#host SIP/2.0
Subject: Session Name: Nu-Art Software
Via: SIP/2.0/UDP host:5060;branch=z9hG4bK4dd6bdf707a85fb5a73faec9ff648f703236
Contact: "Client 410" <sip:410#host>
From: "Client 410" <sip:410#host>;tag=8f7b94cb
To: "Client 430" <sip:430#host>
Organization: Future Earth
Max-Forwards: 32
CSeq: 81 INVITE
Call-ID: 97ee019923d6a6d11a9476d71880e289#10.0.0.1
Allow: INVITE,ACK,CANCEL,BYE,OPTIONS
Expires: 60
Content-Type: application/sdp
Content-Length: 324
v=0
o=Client 410 699719 699719 IN IP4 MyAddress
s=Audio
i=Made by: Nu-Art Software 07-2010
c=IN IP4 MyAddress
t=0 0
m=audio 2871 RTP/AVP 0 3 4 5 14 16 17
a=rtpmap:0 PCMU/8000
a=rtpmap:3 GSM/8000
a=rtpmap:4 G723/8000
a=rtpmap:5 DVI4/8000
a=rtpmap:14 MPA/-1
a=rtpmap:16 DVI4/11025
a=rtpmap:17 DVI4/22050
------- Response: Client 430 ==> Client 410: INVITE#81: 407 Proxy Authentication Required -------
SIP/2.0 407 Proxy Authentication Required
Via: SIP/2.0/UDP host:5060;branch=z9hG4bK4dd6bdf707a85fb5a73faec9ff648f703236;received=MyAddress
From: "Client 410" <sip:410#host>;tag=8f7b94cb
To: "Client 430" <sip:430#host>;tag=as78e28f4d
Call-ID: 97ee019923d6a6d11a9476d71880e289#10.0.0.1
CSeq: 81 INVITE
User-Agent: Freeswitch 1.2.3
Allow: INVITE,ACK,CANCEL,OPTIONS,BYE,REFER,SUBSCRIBE,NOTIFY,INFO
Supported: replaces
Proxy-Authenticate: Digest algorithm=MD5,realm="asterisk",nonce="574b3d49"
Content-Length: 0
---------------------------- Request: Client 410-->Client 430: ACK#81 ----------------------------
ACK sip:430#host SIP/2.0
Via: SIP/2.0/UDP host:5060;branch=z9hG4bK4dd6bdf707a85fb5a73faec9ff648f703236
From: "Client 410" <sip:410#host>;tag=8f7b94cb
To: "Client 430" <sip:430#host>
Max-Forwards: 32
CSeq: 81 ACK
Call-ID: 97ee019923d6a6d11a9476d71880e289#10.0.0.1
Content-Length: 0
-------------------------- Request: Client 410-->Client 430: INVITE#82 --------------------------
INVITE sip:430#host SIP/2.0
Subject: Session Name: Nu-Art Software
Via: SIP/2.0/UDP host:5060;branch=z9hG4bK34c52041066f24c6ac4499af25a948b63236
Contact: "Client 410" <sip:410#host>
From: "Client 410" <sip:410#host>;tag=8f7b94cb
To: "Client 430" <sip:430#host>;tag=as78e28f4d
Organization: Future Earth
Max-Forwards: 32
CSeq: 82 INVITE
Call-ID: 97ee019923d6a6d11a9476d71880e289#10.0.0.1
Allow: INVITE,ACK,CANCEL,BYE,OPTIONS
Expires: 60
Content-Type: application/sdp
Proxy-Authorization: Digest username="410",nonce="574b3d49",realm="asterisk",uri="sip:410#host",algorithm=MD5,response="e674e15de7b6dd05c7fe6da6c155befd"
Content-Length: 324
v=0
o=Client 410 699719 699719 IN IP4 MyAddress
s=Audio
i=Made by: Nu-Art Software 07-2010
c=IN IP4 MyAddress
t=0 0
m=audio 2871 RTP/AVP 0 3 4 5 14 16 17
a=rtpmap:0 PCMU/8000
a=rtpmap:3 GSM/8000
a=rtpmap:4 G723/8000
a=rtpmap:5 DVI4/8000
a=rtpmap:14 MPA/-1
a=rtpmap:16 DVI4/11025
a=rtpmap:17 DVI4/22050
------------------- Response: Client 430 ==> Client 410: INVITE#82: 100 Trying -------------------
SIP/2.0 100 Trying
Via: SIP/2.0/UDP host:5060;branch=z9hG4bK34c52041066f24c6ac4499af25a948b63236;received=MyAddress
From: "Client 410" <sip:410#host>;tag=8f7b94cb
To: "Client 430" <sip:430#host>;tag=as78e28f4d
Call-ID: 97ee019923d6a6d11a9476d71880e289#10.0.0.1
CSeq: 82 INVITE
User-Agent: Freeswitch 1.2.3
Allow: INVITE,ACK,CANCEL,OPTIONS,BYE,REFER,SUBSCRIBE,NOTIFY,INFO
Supported: replaces
Contact: <sip:430#HostAddress>
Content-Length: 0
------------------ Response: Client 430 ==> Client 410: INVITE#82: 180 Ringing ------------------
SIP/2.0 180 Ringing
Via: SIP/2.0/UDP host:5060;branch=z9hG4bK34c52041066f24c6ac4499af25a948b63236;received=MyAddress
From: "Client 410" <sip:410#host>;tag=8f7b94cb
To: "Client 430" <sip:430#host>;tag=as78e28f4d
Call-ID: 97ee019923d6a6d11a9476d71880e289#10.0.0.1
CSeq: 82 INVITE
User-Agent: Freeswitch 1.2.3
Allow: INVITE,ACK,CANCEL,OPTIONS,BYE,REFER,SUBSCRIBE,NOTIFY,INFO
Supported: replaces
Contact: <sip:430#HostAddress>
Content-Length: 0
-------------------------- Request: Client 410-->Client 430: CANCEL#82 --------------------------
CANCEL sip:430#host SIP/2.0
Call-ID: 97ee019923d6a6d11a9476d71880e289#10.0.0.1
To: "Client 430" <sip:430#host>;tag=as78e28f4d
CSeq: 82 CANCEL
From: "Client 410" <sip:410#host>;tag=8f7b94cb
Via: SIP/2.0/UDP host:5060;branch=z9hG4bK34c52041066f24c6ac4499af25a948b63236
Max-Forwards: 32
Content-Length: 0
--------------------- Response: Client 430 ==> Client 410: CANCEL#82: 200 OK ---------------------
SIP/2.0 200 OK
Via: SIP/2.0/UDP host:5060;branch=z9hG4bK34c52041066f24c6ac4499af25a948b63236;received=MyAddress
From: "Client 410" <sip:410#host>;tag=8f7b94cb
To: "Client 430" <sip:430#host>;tag=as78e28f4d
Call-ID: 97ee019923d6a6d11a9476d71880e289#10.0.0.1
CSeq: 82 CANCEL
User-Agent: Freeswitch 1.2.3
Allow: INVITE,ACK,CANCEL,OPTIONS,BYE,REFER,SUBSCRIBE,NOTIFY,INFO
Supported: replaces
Content-Length: 0
------------- Response: Client 430 ==> Client 410: INVITE#82: 487 Request Terminated -------------
SIP/2.0 487 Request Terminated
Via: SIP/2.0/UDP host:5060;branch=z9hG4bK34c52041066f24c6ac4499af25a948b63236;received=MyAddress
From: "Client 410" <sip:410#host>;tag=8f7b94cb
To: "Client 430" <sip:430#host>;tag=as78e28f4d
Call-ID: 97ee019923d6a6d11a9476d71880e289#10.0.0.1
CSeq: 82 INVITE
User-Agent: Freeswitch 1.2.3
Allow: INVITE,ACK,CANCEL,OPTIONS,BYE,REFER,SUBSCRIBE,NOTIFY,INFO
Supported: replaces
Content-Length: 0
---------------------------- Request: Client 410-->Client 430: ACK#82 ----------------------------
ACK sip:430#host SIP/2.0
Via: SIP/2.0/UDP host:5060;branch=z9hG4bK34c52041066f24c6ac4499af25a948b63236
From: "Client 410" <sip:410#host>;tag=8f7b94cb
To: "Client 430" <sip:430#host>
Max-Forwards: 32
CSeq: 82 ACK
Call-ID: 97ee019923d6a6d11a9476d71880e289#10.0.0.1
Content-Length: 0
/---------------------------- END -----------------------------/
Frank, I tried to pay attention to your details, perhaps I missed something, since the other side still does not receives notification on an early hang up.
Any idea why?
Thanks in advance,
Adam.
1) 6xx is unusual; normally rejecting a call is done with a 4xx (usually "Busy Here")
2) The lack of cancel to the destination is a bug in the sip server. (Ok, they're not required to send a CANCEL if you cancel, but they really should.)

Resources