diago icon indicating copy to clipboard operation
diago copied to clipboard

disabling ipv6 on host causes segfault

Open k4lipso opened this issue 3 weeks ago • 2 comments

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
}

k4lipso avatar Nov 29 '25 02:11 k4lipso

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?

k4lipso avatar Nov 29 '25 11:11 k4lipso

Hi @k4lipso there is recent changes arround IPV6. I think some bugs are introduced. I will update lib soon.

emiago avatar Nov 29 '25 22:11 emiago