disabling ipv6 on host causes segfault
Iam running the register example with added playback of an audio file. I use an external registrar to get calls through a public phone number. Register works, ringing works. When the file should be played i get an error:
2025/11/29 02:52:36 ERROR Failed to play error="write udp [XXXXXXXXXXXIPV6]:34985->XXXXXIPV4:21870: sendto: network is unreachable" (i replaced ip addresses with X).
Here a write from my local ipv6 address to a public ipv4 is failing with network unreachable. I tried to force using ipv4 by setting Transport "udp4", sadly with no effect.
tu := diago.NewDiago(ua, diago.WithTransport(
diago.Transport{
Transport: "udp4",
BindHost: "localhost",
BindPort: 15060,
},
))
With this, still an ipv6 address is logged. So i disabled ipv6 complelty on my host using sudo sysctl -w net.ipv6.conf.all.disable_ipv6=0.
This leads to the following segfault when trying to playback:
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0xc8 pc=0x696a90]
goroutine 29 [running]:
github.com/emiago/diago/media.CodecAudioFromSession(...)
/home/kalipso/proggn/diago/media/codec.go:53
github.com/emiago/diago.(*DialogMedia).audioWriterProps.WithAudioWriterMediaProps.func1(...)
/home/kalipso/proggn/diago/dialog_media.go:353
github.com/emiago/diago.(*DialogMedia).audioWriterProps(0xc0001ce0e8, 0xc00023b680)
/home/kalipso/proggn/diago/dialog_media.go:407 +0xb0
github.com/emiago/diago.(*DialogMedia).PlaybackCreate(0xc0001ce0e8)
/home/kalipso/proggn/diago/dialog_media.go:441 +0x8d
main.Playback(0xc0001ce0e0)
/home/kalipso/proggn/diago/examples/register/main.go:106 +0x185
main.start.func1.1(0xc0001ce0e0)
/home/kalipso/proggn/diago/examples/register/main.go:87 +0x132
github.com/emiago/diago.NewDiago.func4(0xc000142180, {0x26ed010, 0xc0001c81e0})
/home/kalipso/proggn/diago/diago.go:297 +0x6ee
github.com/emiago/diago.NewDiago.NewDiago.func2.func14(0xc000142180, {0x26ed010?, 0xc0001c81e0?})
/home/kalipso/proggn/diago/diago.go:225 +0x47
github.com/emiago/sipgo.(*Server).handleRequest(0xc000236080, 0xc000142180, 0xc0001c81e0)
/home/kalipso/go/pkg/mod/github.com/emiago/[email protected]/server.go:264 +0xb7
github.com/emiago/sipgo/sip.(*TransactionLayer).serverTxRequest(0xc0002283f0, 0xc000142180, {0xc000178240, 0x33})
/home/kalipso/go/pkg/mod/github.com/emiago/[email protected]/sip/transaction_layer.go:155 +0x1bd
github.com/emiago/sipgo/sip.(*TransactionLayer).handleRequest(0xc0002283f0, 0xc000142180)
/home/kalipso/go/pkg/mod/github.com/emiago/[email protected]/sip/transaction_layer.go:129 +0x219
github.com/emiago/sipgo/sip.(*TransactionLayer).handleRequestBackground(0xc0002283f0, 0xc000142180)
/home/kalipso/go/pkg/mod/github.com/emiago/[email protected]/sip/transaction_layer.go:89 +0x2f
created by github.com/emiago/sipgo/sip.(*TransactionLayer).handleMessage in goroutine 37
/home/kalipso/go/pkg/mod/github.com/emiago/[email protected]/sip/transaction_layer.go:80 +0x107
exit status 2
Sourcecode:
package main
import (
"context"
"flag"
"fmt"
"log/slog"
"os"
"os/signal"
"time"
"github.com/emiago/diago"
"github.com/emiago/diago/examples"
"github.com/emiago/diago/testdata"
"github.com/emiago/sipgo"
"github.com/emiago/sipgo/sip"
)
// Run app:
// go run . sip:[email protected]
func main() {
fUsername := flag.String("username", "", "Digest username")
fPassword := flag.String("password", "", "Digest password")
flag.Usage = func() {
fmt.Fprintf(os.Stderr, "Usage: %s -username <username> -password <pass> sip:[email protected]\n", os.Args[0])
flag.PrintDefaults()
}
flag.Parse()
// Setup signaling
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)
defer cancel()
examples.SetupLogger()
recipientUri := flag.Arg(0)
if recipientUri == "" {
flag.Usage()
return
}
err := start(ctx, recipientUri, diago.RegisterOptions{
Username: *fUsername,
Password: *fPassword,
ProxyHost: "some_public_ip:5060",
})
if err != nil {
slog.Error("PBX finished with error", "error", err)
}
}
func start(ctx context.Context, recipientURI string, regOpts diago.RegisterOptions) error {
recipient := sip.Uri{}
if err := sip.ParseUri(recipientURI, &recipient); err != nil {
return fmt.Errorf("failed to parse register uri: %w", err)
}
// Setup our main transaction user
useragent := regOpts.Username
if useragent == "" {
useragent = "change-me"
}
ua, _ := sipgo.NewUA(
sipgo.WithUserAgent(useragent),
sipgo.WithUserAgentHostname("localhost"),
)
defer ua.Close()
tu := diago.NewDiago(ua, diago.WithTransport(
diago.Transport{
Transport: "udp",
BindHost: "localhost",
BindPort: 15060,
},
))
// Start listening incoming calls
go func() {
tu.Serve(ctx, func(inDialog *diago.DialogServerSession) {
slog.Info("New dialog request", "id", inDialog.ID)
defer slog.Info("Dialog finished", "id", inDialog.ID)
if err := Playback(inDialog); err != nil {
slog.Error("Failed to play", "error", err)
}
})
}()
// Do register or fail on error
return tu.Register(ctx, recipient, regOpts)
}
func Playback(inDialog *diago.DialogServerSession) error {
inDialog.Trying() // Progress -> 100 Trying
inDialog.Ringing() // Ringing -> 180 Response
time.Sleep(time.Second * 3)
inDialog.Answer() // Answer -> 200 Response
playfile, _ := testdata.OpenFile("test.wav")
slog.Info("Playing a file", "file", "test.wav")
pb, err := inDialog.PlaybackCreate()
if err != nil {
return err
}
_, err = pb.Play(playfile, "audio/wav")
return err
}
I got the Playback working setting diago.Transport.BindHost to my local Ipv4 within the 192.168.1.0/24 range instead of localhost, as well as the sipgo.WithUserAgentHostname.
Now iam wondering a bit what are the correct values that i should specify here?
With 0.0.0.0 Register Fails, with 127.0.0.1 it fails too, with localhost it works but play fails due to using ipv6 addresses, with my local ipv4 address it works. I feel like it should work with all these values consistently, or am i wrong about this?
Hi @k4lipso there is recent changes arround IPV6. I think some bugs are introduced. I will update lib soon.