Skip to content

proto_tls: report real ports when the write is queued on async connect - #4226

Open
hafkensite wants to merge 1 commit into
OpenSIPS:3.6from
hafkensite:fix/tls-async-trace-ports
Open

proto_tls: report real ports when the write is queued on async connect#4226
hafkensite wants to merge 1 commit into
OpenSIPS:3.6from
hafkensite:fix/tls-async-trace-ports

Conversation

@hafkensite

Copy link
Copy Markdown
Contributor

Summary

When tls_async is enabled, the first SIP request sent over a newly opened outbound TLS connection is traced (tracer/proto_hep) with the wrong to_port — and the wrong correlation id — because proto_tls_send() does not update last_outgoing_tcp_id / send_sock->last_real_ports on the path where the write is only queued onto a pending connect.

Details

This is a bug fix, and the scenario is a narrow one: it needs tls_async enabled (the default) and a message that triggers a brand-new outbound TLS connection.

socket_info->last_real_ports is per-listener state that each transport module refreshes on every send, so that the tracer can report the real IP-level ports instead of the SIP-level ones (introduced in d6a663f). modules/tracer/tracer.c reads it when filling in the trace:

(unsigned long)(send_sock && send_sock->last_real_ports->remote?
    send_sock->last_real_ports->remote:su_getport(to)),

proto_tls_send() only refreshes it just before returning from send_it. If no connection exists yet and tls_async is on, tcp_async_connect() / tls_async_connect() may not complete inline; the buffer is then attached with tcp_async_add_chunk() and the function returns via con_release, which never touches those fields.

The result is that the trace for that first message carries the ports — and the last_outgoing_tcp_id correlation id — left behind by whatever was last sent from the same listener, i.e. an unrelated peer. Because the connection exists from that point on, every subsequent message on it goes through send_it and is traced correctly. That is what makes it look odd in practice: only the initial INVITE of a call is wrong, the rest of the dialog is fine.

net/proto_tcp/proto_tcp.c already sets both fields on each of its async paths (in the n==0 branch after tcp_async_connect(), and in the S_CONN_CONNECTING branch); proto_tls was simply never given the same treatment. proto_ws, proto_wss and proto_msrp have no async-connect path and are not affected.

Solution

Set last_outgoing_tcp_id and send_sock->last_real_ports at the con_release label, mirroring what send_it and proto_tcp do.

con_release is also reached when tls_async_connect() fails, where the assignment is harmless: the values are the real ports of the connection just attempted, and no trace is produced for a message that was never queued. send_sock cannot be NULL on this path — tcp_con_get_profile(to, &send_sock->su, ...) earlier in the same branch would already have dereferenced it.

Compatibility

No functional change outside tracing, no config or API change, nothing to migrate.

Submitted against 3.6 as the oldest supported branch; master has the identical gap (same three goto con_release sites) and needs the same change.

proto_tls_send() only updated last_outgoing_tcp_id and
send_sock->last_real_ports on the send_it path. When tls_async is
enabled and no connection exists yet, the first message is attached as a
write chunk to the pending connection and the function returns via
con_release, leaving both stale from a previous send on that listener.

The tracer module reads them when building the trace, so the very first
request over a new outbound TLS connection (typically the INVITE) is
logged with the ports and connection id of an unrelated peer. Every
later message on that connection goes through send_it and is correct.

proto_tcp already does this on both of its async paths.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@razvancrainea razvancrainea self-assigned this Sep 1, 2026
@bogdan-iancu

Copy link
Copy Markdown
Member

Hi @hafkensite , good catch here. Nevertheless, for code clarity, I would suggest adding the settings in the async block (as the settings of the ports are strictly related to the async op), somewhere here for example, instead of having them in the "release" section - this is something more generic (as intention), not 100% related to async stuff

@bogdan-iancu bogdan-iancu self-assigned this Sep 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants