Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions dialog_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -402,19 +402,25 @@ func (s *DialogClientSession) WriteAck(ctx context.Context, ack *sip.Request) er
// request is passed to the transport layer directly for transmission,
// rather than a client transaction. This is because the UAC core
// handles retransmissions of the ACK, not the transaction layer.
retransmissionAck := ack.Clone() // We need to clone for RACE safety
s.buildReq(ack)
if err := s.requestValidate(s.UA.Client, ack); err != nil {
return err
}
// Snapshot the fully routed ACK once; Clone pins the current destination.
// Replay fresh copies without rebuilding dialog headers to avoid races and header accumulation.
ackTemplate := ack.Clone()
s.inviteTx.OnRetransmission(func(r *sip.Response) {
// Detect retransmission
if r.StatusCode != 200 {
return
}

if err := s.WriteRequest(retransmissionAck); err != nil {
if err := s.UA.Client.WriteRequest(ackTemplate.Clone(), s.requestValidate); err != nil {

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is point of second Clone? After this request is serilaized

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The second clone gives each retransmission its own request. Before serialization, ClientRequestConnection writes req.raddr and can update the Via host/port.

Retransmission callbacks can overlap because passUpRetransmission releases fsmMu before calling the hook. Reusing ackTemplate would let those writes race with another callback’s transport setup or serialization. The first clone isolates the template from the initial send; the second keeps the template immutable across retransmissions.

This is a defensive strategy to handle the case where UA receives retransmitted ACKs in quick succession, that is addressed to a different endpoint and it needs to forward it to the next destination.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

then problem is overlapping, if I see, but I could only right now think more complex solution.

s.endWithCause(fmt.Errorf("ACK retransmission failed: %w", err))
}
})

if err := s.WriteRequest(ack); err != nil {
if err := s.UA.Client.WriteRequest(ack, s.requestValidate); err != nil {
// Make sure we close our error
// s.Close()
return err
Expand Down
Loading