-
Notifications
You must be signed in to change notification settings - Fork 23
Description
When you have multiple listeners and/or TCP listeners, ysipchan
needs to pick a connection to use to send out SIP messages. For voice call setup, it uses the oconnection_id
parameter for that, but for SIP MESSAGEs, it seems to pick connection_id
, which is the incoming connection, not the outgoing one.
Modifying the msg.execute
YATE message to set connection_id
to the correct connection as well as setting ip_transport
to the correct value for the outgoing connection, makes the SIP MESSAGE go out to the correct target.
It would seem that voice call setup, for example the call.execute
YATE message, picks the outgoing connection from oconnection_id
but that SIP MESSAGE messaging picks the outgoing connection from connection_id
instead, and that the latter is wrong.
I believe the fix would be to make msg.execute
in ysipchan
work the same way as call.execute
in this respect, and pick oconnection_id
(and ignore the value set for ip_transport
, which refers to the incoming connection).
Workaround
(I happen to use sqlite
as the database, so that is the dialect used here)
Store the user's transport_ip
value on register (as well as oconnection_id
, which was already there to support multiple listeners in the first place):
register.conf
:
[user.register]
query=UPDATE users SET oconnection_id='${oconnection_id}',oconnection_transport='${ip_transport}',location='${data}',expires=datetime('now', '${expires} seconds') WHERE username='${username}'
[call.route]
query=SELECT location,oconnection_id,oconnection_transport,(CASE WHEN location IS NULL THEN 'offline' ELSE NULL END) AS error FROM users WHERE username='${called}'
result=location
and then patch msg.execute
to overwrite connection_id
and ip_transport
with the values for the outgoing connection:
regexroute.conf
:
[extra]
msg.execute=90
[msg.execute]
.*=return;connection_id=${oconnection_id};ip_transport=${oconnection_transport}
Details
All the details
When using multiple listeners:
ysipchan.conf
:
[general]
ipv6_support=yes
type=udp
ipv6=yes
udp_force_bind=no
useragent=YATE
generate=enable
[listener udp4]
type=udp
ipv6=no
udp_force_bind=no
[listener tcp6]
type=tcp
ipv6=yes
[listener tcp4]
type=tcp
ipv6=no
ysipchan
needs to have a way to select which connection it is going to send an outgoing SIP message on. I have this configured as follows:
register.conf
:
[user.register]
query=UPDATE users SET oconnection_id='${oconnection_id}',location='${data}',expires=datetime('now', '${expires} seconds') WHERE username='${username}'
[call.route]
query=SELECT location,oconnection_id,(CASE WHEN location IS NULL THEN 'offline' ELSE NULL END) AS error FROM users WHERE username='${called}'
result=location
I store oconnection_id
on user.register
and retrieve it on call.route
. When a call is routed to a user connected on the tcp6
listener while originating from the udp4
listener, we see something like this (partly redacted for privacy):
2025-07-07_11:21:34.626092 Returned true 'call.execute' delay=0.001462
param['address'] = '10.222.7.<calling user address>:5060'
param['ip_host'] = '10.222.7.<calling user address>'
param['ip_port'] = '5060'
param['ip_transport'] = 'UDP'
param['address'] = '10.222.7.<calling user address>:5060'
param['connection_id'] = 'udp4'
param['connection_reliable'] = 'false'
param['oconnection_id'] = 'tcp:[2a10:3781:1696:<YATE address>]:5060-[2a10:3781:1696:<called user address>]:46726'
param['callto'] = 'sip/sip:101@[2a10:3781:1696:<called user address>]:46726;transport=Tcp;line=jru96hpi'
2025-07-07_11:21:34.628858 <sip:INFO> 'tcp:[2a10:3781:1696:<YATE address>]:5060-[2a10:3781:1696:<called user address>]:46726' sending 881 bytes 'INVITE sip:101@[2a10:3781:1696:<called user address>]:46726;transport=Tcp;line=jru96hpi' 0x7fd544020580 [0x7fd55c001020]
(Somehow, this YATE message has the address
parameter twice; I only notice this as I'm editing the parameter list here. Weird!)
However, if we enable SIP MESSAGEs:
ysipchan.conf
:
[message]
enable=yes
then we can't send a message to that TCP user; it picks the incoming connection (here udp4
) for the outgoing message, which of course fails:
2025-07-07_12:01:08.944308 Returned true 'msg.execute' delay=0.003161
param['connection_id'] = 'udp4'
param['connection_reliable'] = 'false'
param['ip_host'] = '10.0.2.<sender address>'
param['ip_port'] = '58745'
param['ip_transport'] = 'UDP'
param['address'] = '10.0.2.<sender address>:58745'
param['oconnection_id'] = 'tcp:[2a10:3781:1696:<YATE address>]:5060-[2a10:3781:1696:<recipient address>]:46726'
param['callto'] = 'sip/sip:101@[2a10:3781:1696:<recipient address>]:46726;transport=Tcp;line=jru96hpi'
2025-07-07_12:01:08.946437 <sip:INFO> 'udp:0.0.0.0:5060' sending 683 bytes 'MESSAGE sip:101@[2a10:3781:1696:<recipient address>]:46726;transport=Tcp;line=jru96hpi' 0x7fd544077b70 to [2a10:3781:1696:<recipient address>]:46726 [0x56099b5bf7e0]
2025-07-07_12:01:08.946506 <sip:WARN> Transport(udp4) Socket send error: Address family not supported by protocol (97) [0x56099b5bf7e0]
2025-07-07_12:01:08.946516 <sipengine:INFO> SIPTransaction send failed state=Trying: clearing [0x7fd544066400]
With the workaround above, overwriting connection_id
and ip_transport
(other fields don't matter), we get the correct result:
2025-07-07_12:08:47.015993 Returned true 'msg.execute' delay=0.001831
param['connection_id'] = 'tcp:[2a10:3781:1696:<YATE address>]:5060-[2a10:3781:1696:<recipient address>]:40503'
param['connection_reliable'] = 'false'
param['ip_host'] = '10.0.2.<sender address>'
param['ip_port'] = '56361'
param['ip_transport'] = 'TCP'
param['address'] = '10.0.2.<sender address>:56361'
param['oconnection_id'] = 'tcp:[2a10:3781:1696:<YATE address>]:5060-[2a10:3781:1696:<recipient address>]:40503'
param['oconnection_transport'] = 'TCP'
param['callto'] = 'sip/sip:101@[2a10:3781:1696:<recipient address>]:40503;transport=Tcp;line=jru96hpi'
2025-07-07_12:08:47.023039 <sip:INFO> 'tcp:[2a10:3781:1696:<YATE address>]:5060-[2a10:3781:1696:<recipient address>]:40503' sending 687 bytes 'MESSAGE sip:101@[2a10:3781:1696:<recipient address>]:40503;transport=Tcp;line=jru96hpi' 0x7f8958076030 [0x7f8978001020]
Since only connection_id
and ip_transport
seem to matter, the other fields still refer to the sender, which makes for a bit of an odd read of those parameters together.
(I use the word message in three different senses; unfortunate, but it's difficult to avoid. Sometimes I mean just any command flow occuring over SIP, sometimes I mean the SIP MESSAGE method, and sometimes I mean the things happening in the message passing system inside YATE. I think it's clear when I mean what.)
Environment
CPU: x86-64
OS: Debian bookworm/stable
YATE: Compiled from master
, slightly behind at 25a425e