Skip to content
Merged
Show file tree
Hide file tree
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
2 changes: 1 addition & 1 deletion .config/cspell/cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"enableGlobDot": true,
"useGitignore": true,
"gitignoreRoot": ".",
"ignorePaths": ["LICENSE", "*.sum", "go.mod", "local.env"],
"ignorePaths": ["LICENSE", "*.sum", "go.mod", "local.env", ".local/", "patch/"],
"words": [
"autorelay",
"briandowns",
Expand Down
5 changes: 1 addition & 4 deletions .config/git/ignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,5 @@ _*
local.env

node_modules/
go.work.sum
bin/
logs/
coverage/
go.*work.sum
!**/testdata/**/.*
2 changes: 1 addition & 1 deletion docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ FROM ${TARGETOS}-${TARGETARCH}-${TARGETVARIANT}base

ARG TARGETPLATFORM

COPY bin/docker/${TARGETPLATFORM} /
COPY .local/bin/docker/${TARGETPLATFORM} /

WORKDIR /data

Expand Down
2 changes: 1 addition & 1 deletion docker/Dockerfile.dockerignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
*
!bin/docker/
!.local/bin/docker/
9 changes: 9 additions & 0 deletions go.vendored.work
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
go 1.25.0

use (
./p2pcp
./project
./test
)

replace github.com/libp2p/go-libp2p => ./.local/vendor/github.com/libp2p/go-libp2p
2 changes: 1 addition & 1 deletion p2pcp/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ require (
go.uber.org/zap v1.27.0 // indirect
go.yaml.in/yaml/v2 v2.4.3 // indirect
go.yaml.in/yaml/v3 v3.0.4 // indirect
golang.org/x/exp v0.0.0-20251017212417-90e834f514db // indirect
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 // indirect
golang.org/x/mod v0.29.0 // indirect
golang.org/x/net v0.46.0 // indirect
golang.org/x/sync v0.17.0 // indirect
Expand Down
4 changes: 2 additions & 2 deletions p2pcp/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -425,8 +425,8 @@ golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1m
golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04=
golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20251017212417-90e834f514db h1:by6IehL4BH5k3e3SJmcoNbOobMey2SLpAF79iPOEBvw=
golang.org/x/exp v0.0.0-20251017212417-90e834f514db/go.mod h1:j/pmGrbnkbPtQfxEe5D0VQhZC6qKbfKifgD0oM7sR70=
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 h1:mgKeJMpvi0yx/sU5GsxQ7p6s2wtOnGAHZWCHUM4KGzY=
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546/go.mod h1:j/pmGrbnkbPtQfxEe5D0VQhZC6qKbfKifgD0oM7sR70=
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
Expand Down
19 changes: 7 additions & 12 deletions p2pcp/internal/interrupt/interrupt.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,13 @@ func RegisterInterruptHandler(ctx context.Context, handler func()) {
signal.Notify(sigChan, os.Interrupt)
go func() {
count := 0
for {
select {
case <-ctx.Done():
return
case <-sigChan:
count++
if count == 1 {
fmt.Println("\nCanceling...")
go handler()
} else {
os.Exit(1)
}
for range sigChan {
count++
if count == 1 {
fmt.Println("\nCanceling...")
go handler()
} else {
os.Exit(1)
}
}
}()
Expand Down
1 change: 1 addition & 0 deletions p2pcp/internal/node/mdns.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ func (notifee *mdnsNotifee) HandlePeerFound(addrInfo peer.AddrInfo) {
slog.Debug("mdns: found new peer.", "peer", addrInfo.ID)
err := notifee.host.Connect(notifee.ctx, addrInfo)
if err == nil {
slog.Debug("mdns: connected to new peer.", "peer", addrInfo.ID)
notifee.host.ConnManager().Protect(addrInfo.ID, "mdns")
}
}
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"update": "go run project update"
},
"dependencies": {
"cspell": "^9.2.1",
"cspell": "^9.2.2",
"prettier": "^3.6.2",
"prettier-plugin-packagejson": "^2.5.19",
"prettier-plugin-toml": "^2.0.6"
Expand Down
187 changes: 187 additions & 0 deletions patch/mdns.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
--- /go/pkg/mod/github.com/libp2p/[email protected]/p2p/discovery/mdns/mdns.go 2025-10-25 10:14:40.301293929 +0000
+++ /workspaces/p2pcp/.local/temp/mdns.go 2025-10-27 11:28:53.210687076 +0000
@@ -5,6 +5,7 @@
"errors"
"io"
"math/rand"
+ "net"
"strings"
"sync"

@@ -45,7 +46,10 @@
ctxCancel context.CancelFunc

resolverWG sync.WaitGroup
- server *zeroconf.Server
+
+ // Per-interface servers map, keyed by interface IP address
+ servers map[string]*zeroconf.Server
+ serversMux sync.RWMutex

notifee Notifee
}
@@ -59,6 +63,7 @@
serviceName: serviceName,
peerName: randomString(32 + rand.Intn(32)), // generate a random string between 32 and 63 characters long
notifee: notifee,
+ servers: make(map[string]*zeroconf.Server),
}
s.ctx, s.ctxCancel = context.WithCancel(context.Background())
return s
@@ -74,39 +79,40 @@

func (s *mdnsService) Close() error {
s.ctxCancel()
- if s.server != nil {
- s.server.Shutdown()
+
+ s.serversMux.Lock()
+ for _, server := range s.servers {
+ if server != nil {
+ server.Shutdown()
+ }
}
+ s.servers = make(map[string]*zeroconf.Server)
+ s.serversMux.Unlock()
+
s.resolverWG.Wait()
return nil
}

-// We don't really care about the IP addresses, but the spec (and various routers / firewalls) require us
-// to send A and AAAA records.
-func (s *mdnsService) getIPs(addrs []ma.Multiaddr) ([]string, error) {
- var ip4, ip6 string
+func groupAddressesByIP(addrs []ma.Multiaddr) map[string][]ma.Multiaddr {
+ addrsByInterface := make(map[string][]ma.Multiaddr)
+
for _, addr := range addrs {
+ var ip string
first, _ := ma.SplitFirst(addr)
if first == nil {
continue
}
- if ip4 == "" && first.Protocol().Code == ma.P_IP4 {
- ip4 = first.Value()
- } else if ip6 == "" && first.Protocol().Code == ma.P_IP6 {
- ip6 = first.Value()
+ switch first.Protocol().Code {
+ case ma.P_IP4, ma.P_IP6:
+ ip = first.Value()
+ default:
+ continue
}
+
+ addrsByInterface[ip] = append(addrsByInterface[ip], addr)
}
- ips := make([]string, 0, 2)
- if ip4 != "" {
- ips = append(ips, ip4)
- }
- if ip6 != "" {
- ips = append(ips, ip6)
- }
- if len(ips) == 0 {
- return nil, errors.New("didn't find any IP addresses")
- }
- return ips, nil
+
+ return addrsByInterface
}

func (s *mdnsService) startServer() error {
@@ -121,32 +127,73 @@
if err != nil {
return err
}
- var txts []string
- for _, addr := range addrs {
- if manet.IsThinWaist(addr) { // don't announce circuit addresses
- txts = append(txts, dnsaddrPrefix+addr.String())
- }
- }
-
- ips, err := s.getIPs(addrs)
+ interfaces, err := net.Interfaces()
if err != nil {
return err
}

- server, err := zeroconf.RegisterProxy(
- s.peerName,
- s.serviceName,
- mdnsDomain,
- 4001, // we have to pass in a port number here, but libp2p only uses the TXT records
- s.peerName,
- ips,
- txts,
- nil,
- )
- if err != nil {
- return err
+ addrsByIP := groupAddressesByIP(addrs)
+
+ s.serversMux.Lock()
+ defer s.serversMux.Unlock()
+ for _, iface := range interfaces {
+ if iface.Flags&(net.FlagUp|net.FlagMulticast) != (net.FlagUp | net.FlagMulticast) {
+ continue
+ }
+
+ var multiAddrs []ma.Multiaddr
+ var ips []string
+ ifaceAddrs, err := iface.Addrs()
+ if err != nil {
+ log.Debug("failed to get interface addresses", "err", err)
+ continue
+ }
+ for _, addr := range ifaceAddrs {
+ if ipNet, ok := addr.(*net.IPNet); ok {
+ ip := ipNet.IP.String()
+ if ifaceMultiAddrs, ok := addrsByIP[ip]; ok {
+ multiAddrs = append(multiAddrs, ifaceMultiAddrs...)
+ ips = append(ips, ip)
+ }
+ }
+ }
+
+ // Build TXT records for this interface
+ var txts []string
+ for _, addr := range multiAddrs {
+ if manet.IsThinWaist(addr) { // don't announce circuit addresses
+ txts = append(txts, dnsaddrPrefix+addr.String())
+ }
+ }
+
+ if len(txts) == 0 {
+ log.Warn("No valid multiaddrs to announce on interface", "interface", iface.Name)
+ continue
+ }
+
+ // Register server for this specific interface
+ server, err := zeroconf.RegisterProxy(
+ s.peerName,
+ s.serviceName,
+ mdnsDomain,
+ 4001, // we have to pass in a port number here, but libp2p only uses the TXT records
+ s.peerName,
+ ips,
+ txts,
+ []net.Interface{iface}, // Bind to specific interface
+ )
+ if err != nil {
+ log.Warn("Failed to register mDNS for interface", "interface", iface.Name, "error", err)
+ continue
+ }
+
+ s.servers[iface.Name] = server
+ }
+
+ if len(s.servers) == 0 {
+ return errors.New("failed to register mDNS on any interface")
}
- s.server = server
+
return nil
}

6 changes: 5 additions & 1 deletion project/cmd/build/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@ import (
"github.com/spf13/cobra"
)

var vendoredGoWorkPath = filepath.Join(workspace.GetProjectPath(), "go.vendored.work")

func Run() {
os.Setenv("CGO_ENABLED", "0")
projectPath := workspace.GetProjectPath()
binPath := filepath.Join(projectPath, "bin")
binPath := filepath.Join(projectPath, ".local/bin")

// Output binaries for the main module.
for _, module := range workspace.GetModules() {
Expand All @@ -21,6 +23,8 @@ func Run() {
if moduleName == project.Name {
output = filepath.Join(binPath, moduleName)
}
restore := workspace.SetEnv("GOWORK", vendoredGoWorkPath)
defer restore()
workspace.Run("go", "build", "-o", output, module)
}
}
Expand Down
8 changes: 5 additions & 3 deletions project/cmd/build/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,15 @@ var platformEnvs = map[string]platformEnv{
}

func GetBinariesPath() string {
return filepath.Join(workspace.GetProjectPath(), "bin/docker")
return filepath.Join(workspace.GetProjectPath(), ".local/bin/docker")
}

func BuildBinaries() {
slog.Info("Building multi-arch binaries...")
restore := workspace.SetEnv("CGO_ENABLED", "0")
defer restore()
restoreCgo := workspace.SetEnv("CGO_ENABLED", "0")
defer restoreCgo()
restoreGoWork := workspace.SetEnv("GOWORK", vendoredGoWorkPath)
defer restoreGoWork()

projectPath := workspace.GetProjectPath()
binariesPath := GetBinariesPath()
Expand Down
4 changes: 2 additions & 2 deletions project/cmd/build/release.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
)

func GetReleaseArtifactsPath() string {
return filepath.Join(workspace.GetProjectPath(), "bin/release")
return filepath.Join(workspace.GetProjectPath(), ".local/bin/release")
}

func PackBinaries() {
Expand All @@ -24,7 +24,7 @@ func PackBinaries() {
for platform := range platformEnvs {
go func() {
defer wg.Done()
outputName := strings.Join([]string{project.Name, project.Version, strings.Replace(platform, "/", "_", -1)}, "_")
outputName := strings.Join([]string{project.Name, project.Version, strings.ReplaceAll(platform, "/", "_")}, "_")

binaryPath := filepath.Join(binariesPath, platform, project.Name)
if strings.HasPrefix(platform, "windows") {
Expand Down
2 changes: 1 addition & 1 deletion project/cmd/codecov/codecov.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ var CodecovCommand = &cobra.Command{
Use: "codecov",
Run: func(cmd *cobra.Command, args []string) {
projectPath := workspace.GetProjectPath()
coverageFile := filepath.Join(projectPath, "coverage/coverage.txt")
coverageFile := filepath.Join(projectPath, ".local/coverage/coverage.txt")
commitHash := workspace.GitCommitHash()
workspace.Run("codecovcli", "--verbose", "upload-process",
"--commit-sha", commitHash,
Expand Down
4 changes: 4 additions & 0 deletions project/cmd/restore/restore.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ var RestoreCmd = &cobra.Command{
Run: func(cmd *cobra.Command, args []string) {
workspace.Run("uv", "python", "install", "--preview", "--default", pythonVersion)
workspace.Run("uv", "tool", "install", "--reinstall", fmt.Sprintf("codecov-cli@%s", codecovVersion))

for _, module := range workspace.GetModules() {
workspace.RunWithChdir(module, "go", "mod", "download")
}
Expand All @@ -37,5 +38,8 @@ var RestoreCmd = &cobra.Command{
"--bootstrap",
"--driver-opt", "network=host")
}

vendor()
applyPatches()
},
}
Loading