mirror of
https://github.com/yggdrasil-network/yggdrasil-go.git
synced 2025-08-26 21:17:36 +00:00
Compare commits
8 Commits
v0.5.6
...
neil/linkc
Author | SHA1 | Date | |
---|---|---|---|
![]() |
2bc2b77ed9 | ||
![]() |
bfdcf0762f | ||
![]() |
5ea16e63a1 | ||
![]() |
da7ebde828 | ||
![]() |
02d92ff81c | ||
![]() |
04c0acf71b | ||
![]() |
8ecc402d7c | ||
![]() |
c505097be0 |
@@ -247,6 +247,7 @@ func main() {
|
||||
Listen: intf.Listen,
|
||||
Port: intf.Port,
|
||||
Priority: uint8(intf.Priority),
|
||||
Cost: uint8(intf.Cost),
|
||||
Password: intf.Password,
|
||||
})
|
||||
}
|
||||
|
@@ -174,7 +174,7 @@ func run() int {
|
||||
if err := json.Unmarshal(recv.Response, &resp); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
table.SetHeader([]string{"URI", "State", "Dir", "IP Address", "Uptime", "RTT", "RX", "TX", "Pr", "Last Error"})
|
||||
table.SetHeader([]string{"URI", "State", "Dir", "IP Address", "Uptime", "RTT", "RX", "TX", "Pr", "Cost", "Last Error"})
|
||||
for _, peer := range resp.Peers {
|
||||
state, lasterr, dir, rtt := "Up", "-", "Out", "-"
|
||||
if !peer.Up {
|
||||
@@ -200,6 +200,7 @@ func run() int {
|
||||
peer.RXBytes.String(),
|
||||
peer.TXBytes.String(),
|
||||
fmt.Sprintf("%d", peer.Priority),
|
||||
fmt.Sprintf("%d", peer.Cost),
|
||||
lasterr,
|
||||
})
|
||||
}
|
||||
|
@@ -97,6 +97,7 @@ func (m *Yggdrasil) StartJSON(configjson []byte) error {
|
||||
Listen: intf.Listen,
|
||||
Port: intf.Port,
|
||||
Priority: uint8(intf.Priority),
|
||||
Cost: uint8(intf.Cost),
|
||||
Password: intf.Password,
|
||||
})
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
//go:build ios
|
||||
// +build ios
|
||||
//go:build ios || darwin
|
||||
// +build ios darwin
|
||||
|
||||
package mobile
|
||||
|
@@ -1,5 +1,5 @@
|
||||
//go:build !android && !ios
|
||||
// +build !android,!ios
|
||||
//go:build !android && !ios && !darwin
|
||||
// +build !android,!ios,!darwin
|
||||
|
||||
package mobile
|
||||
|
||||
|
27
go.mod
27
go.mod
@@ -2,23 +2,26 @@ module github.com/yggdrasil-network/yggdrasil-go
|
||||
|
||||
go 1.21
|
||||
|
||||
replace github.com/Arceliar/ironwood => github.com/neilalexander/ironwood v0.0.0-20240530214820-2be4c2c0545a
|
||||
|
||||
require (
|
||||
github.com/Arceliar/ironwood v0.0.0-20240529054413-b8e59574e2b2
|
||||
github.com/Arceliar/phony v0.0.0-20220903101357-530938a4b13d
|
||||
github.com/cheggaaa/pb/v3 v3.1.4
|
||||
github.com/cheggaaa/pb/v3 v3.1.5
|
||||
github.com/gologme/log v1.3.0
|
||||
github.com/hashicorp/go-syslog v1.0.0
|
||||
github.com/hjson/hjson-go/v4 v4.4.0
|
||||
github.com/kardianos/minwinsvc v1.0.2
|
||||
github.com/quic-go/quic-go v0.44.0
|
||||
github.com/quic-go/quic-go v0.45.1
|
||||
github.com/vishvananda/netlink v1.1.0
|
||||
golang.org/x/crypto v0.23.0
|
||||
golang.org/x/mobile v0.0.0-20240520174638-fa72addaaa1b
|
||||
golang.org/x/net v0.25.0
|
||||
golang.org/x/sys v0.20.0
|
||||
golang.org/x/text v0.15.0
|
||||
golang.zx2c4.com/wireguard v0.0.0-20230223181233-21636207a675
|
||||
golang.org/x/crypto v0.25.0
|
||||
golang.org/x/mobile v0.0.0-20240716161057-1ad2df20a8b6
|
||||
golang.org/x/net v0.27.0
|
||||
golang.org/x/sys v0.22.0
|
||||
golang.org/x/text v0.16.0
|
||||
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173
|
||||
golang.zx2c4.com/wireguard/windows v0.5.3
|
||||
nhooyr.io/websocket v1.8.11
|
||||
)
|
||||
|
||||
require (
|
||||
@@ -30,10 +33,10 @@ require (
|
||||
github.com/onsi/ginkgo/v2 v2.9.5 // indirect
|
||||
github.com/rivo/uniseg v0.2.0 // indirect
|
||||
go.uber.org/mock v0.4.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 // indirect
|
||||
golang.org/x/mod v0.17.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect
|
||||
golang.org/x/mod v0.19.0 // indirect
|
||||
golang.org/x/sync v0.7.0 // indirect
|
||||
golang.org/x/tools v0.21.0 // indirect
|
||||
golang.org/x/tools v0.23.0 // indirect
|
||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
|
||||
)
|
||||
|
||||
@@ -41,7 +44,7 @@ require (
|
||||
github.com/VividCortex/ewma v1.2.0 // indirect
|
||||
github.com/fatih/color v1.15.0 // indirect
|
||||
github.com/mattn/go-isatty v0.0.19 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.14 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.15 // indirect
|
||||
github.com/olekukonko/tablewriter v0.0.5
|
||||
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f // indirect
|
||||
)
|
||||
|
59
go.sum
59
go.sum
@@ -1,5 +1,3 @@
|
||||
github.com/Arceliar/ironwood v0.0.0-20240529054413-b8e59574e2b2 h1:SBdYBKeXYUUFef5wi2CMhYmXFVGiYaRpTvbki0Bu+JQ=
|
||||
github.com/Arceliar/ironwood v0.0.0-20240529054413-b8e59574e2b2/go.mod h1:6WP4799FX0OuWdENGQAh+0RXp9FLh0y7NZ7tM9cJyXk=
|
||||
github.com/Arceliar/phony v0.0.0-20220903101357-530938a4b13d h1:UK9fsWbWqwIQkMCz1CP+v5pGbsGoWAw6g4AyvMpm1EM=
|
||||
github.com/Arceliar/phony v0.0.0-20220903101357-530938a4b13d/go.mod h1:BCnxhRf47C/dy/e/D2pmB8NkB3dQVIrkD98b220rx5Q=
|
||||
github.com/VividCortex/ewma v1.2.0 h1:f58SaIzcDXrSy3kWaHNvuJgJ3Nmz59Zji6XoJR/q1ow=
|
||||
@@ -9,8 +7,8 @@ github.com/bits-and-blooms/bitset v1.13.0 h1:bAQ9OPNFYbGHV6Nez0tmNI0RiEu7/hxlYJR
|
||||
github.com/bits-and-blooms/bitset v1.13.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
|
||||
github.com/bits-and-blooms/bloom/v3 v3.7.0 h1:VfknkqV4xI+PsaDIsoHueyxVDZrfvMn56jeWUzvzdls=
|
||||
github.com/bits-and-blooms/bloom/v3 v3.7.0/go.mod h1:VKlUSvp0lFIYqxJjzdnSsZEw4iHb1kOL2tfHTgyJBHg=
|
||||
github.com/cheggaaa/pb/v3 v3.1.4 h1:DN8j4TVVdKu3WxVwcRKu0sG00IIU6FewoABZzXbRQeo=
|
||||
github.com/cheggaaa/pb/v3 v3.1.4/go.mod h1:6wVjILNBaXMs8c21qRiaUM8BR82erfgau1DQ4iUXmSA=
|
||||
github.com/cheggaaa/pb/v3 v3.1.5 h1:QuuUzeM2WsAqG2gMqtzaWithDJv0i+i6UlnwSCI4QLk=
|
||||
github.com/cheggaaa/pb/v3 v3.1.5/go.mod h1:CrxkeghYTXi1lQBEI7jSn+3svI3cuc19haAj6jM60XI=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
@@ -27,6 +25,8 @@ github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg
|
||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/gologme/log v1.3.0 h1:l781G4dE+pbigClDSDzSaaYKtiueHCILUa/qSDsmHAo=
|
||||
github.com/gologme/log v1.3.0/go.mod h1:yKT+DvIPdDdDoPtqFrFxheooyVmoqi0BAsw+erN3wA4=
|
||||
github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4=
|
||||
github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE=
|
||||
@@ -44,8 +44,10 @@ github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/
|
||||
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
|
||||
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU=
|
||||
github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
|
||||
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/neilalexander/ironwood v0.0.0-20240530214820-2be4c2c0545a h1:QtmEQn0ahcIFkkt8iXjBlyej984hdFS6Cc2cqTN2CuQ=
|
||||
github.com/neilalexander/ironwood v0.0.0-20240530214820-2be4c2c0545a/go.mod h1:6WP4799FX0OuWdENGQAh+0RXp9FLh0y7NZ7tM9cJyXk=
|
||||
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
|
||||
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
|
||||
github.com/onsi/ginkgo/v2 v2.9.5 h1:+6Hr4uxzP4XIUyAkg61dWBw8lb/gc4/X5luuxN/EC+Q=
|
||||
@@ -54,8 +56,8 @@ github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE=
|
||||
github.com/onsi/gomega v1.27.6/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/quic-go/quic-go v0.44.0 h1:So5wOr7jyO4vzL2sd8/pD9Kesciv91zSk8BoFngItQ0=
|
||||
github.com/quic-go/quic-go v0.44.0/go.mod h1:z4cx/9Ny9UtGITIPzmPTXh1ULfOyWh4qGQlpnPcWmek=
|
||||
github.com/quic-go/quic-go v0.45.1 h1:tPfeYCk+uZHjmDRwHHQmvHRYL2t44ROTujLeFVBmjCA=
|
||||
github.com/quic-go/quic-go v0.45.1/go.mod h1:1dLehS7TIR64+vxGR70GDcatWTOtMX2PUtnKsjbTurI=
|
||||
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
@@ -74,24 +76,25 @@ go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
|
||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 h1:vr/HnozRka3pE4EsMEg1lgkXJkTFJCVUX+S/ZT6wYzM=
|
||||
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc=
|
||||
golang.org/x/mobile v0.0.0-20240520174638-fa72addaaa1b h1:WX7nnnLfCEXg+FmdYZPai2XuP3VqCP1HZVMST0n9DF0=
|
||||
golang.org/x/mobile v0.0.0-20240520174638-fa72addaaa1b/go.mod h1:EiXZlVfUTaAyySFVJb9rsODuiO+WXu8HrUuySb7nYFw=
|
||||
golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30=
|
||||
golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M=
|
||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
|
||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
|
||||
golang.org/x/mobile v0.0.0-20240716161057-1ad2df20a8b6 h1:/VlmIrkuLf2wzPjkZ8imSpckHoW7Y71h66dxbLHSpi8=
|
||||
golang.org/x/mobile v0.0.0-20240716161057-1ad2df20a8b6/go.mod h1:TCsc78+c4cqb8IKEosz2LwJ6YRNkIjMuAYeHYjchGDE=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
|
||||
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8=
|
||||
golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
|
||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||
golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys=
|
||||
golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -110,8 +113,9 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
|
||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
|
||||
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
@@ -124,26 +128,31 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
|
||||
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
|
||||
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
|
||||
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.21.0 h1:qc0xYgIbsSDt9EyWz05J5wfa7LOVW0YTLOXrqdLAWIw=
|
||||
golang.org/x/tools v0.21.0/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
||||
golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg=
|
||||
golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeunTOisW56dUokqW/FOteYJJ/yg=
|
||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI=
|
||||
golang.zx2c4.com/wireguard v0.0.0-20230223181233-21636207a675 h1:/J/RVnr7ng4fWPRH3xa4WtBJ1Jp+Auu4YNLmGiPv5QU=
|
||||
golang.zx2c4.com/wireguard v0.0.0-20230223181233-21636207a675/go.mod h1:whfbyDBt09xhCYQWtO2+3UVjlaq6/9hDZrjg2ZE6SyA=
|
||||
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 h1:/jFs0duh4rdb8uIfPMv78iAJGcPKDeqAFnaLBropIC4=
|
||||
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173/go.mod h1:tkCQ4FQXmpAgYVh++1cq16/dH4QJtmvpRv19DWGAHSA=
|
||||
golang.zx2c4.com/wireguard/windows v0.5.3 h1:On6j2Rpn3OEMXqBq00QEDC7bWSZrPIHKIus8eIuExIE=
|
||||
golang.zx2c4.com/wireguard/windows v0.5.3/go.mod h1:9TEe8TJmtwyQebdFwAkEWOPr3prrtqm+REGFifP60hI=
|
||||
google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
|
||||
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
||||
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gvisor.dev/gvisor v0.0.0-20230927004350-cbd86285d259 h1:TbRPT0HtzFP3Cno1zZo7yPzEEnfu8EjLfl6IU9VfqkQ=
|
||||
gvisor.dev/gvisor v0.0.0-20230927004350-cbd86285d259/go.mod h1:AVgIgHMwK63XvmAzWG9vLQ41YnVHN0du0tEC46fI7yY=
|
||||
nhooyr.io/websocket v1.8.11 h1:f/qXNc2/3DpoSZkHt1DQu6rj4zGC8JmkkLkWss0MgN0=
|
||||
nhooyr.io/websocket v1.8.11/go.mod h1:rN9OFWIUwuxg4fR5tELlYC04bXYowCP9GX47ivo2l+c=
|
||||
|
@@ -12,7 +12,7 @@ type AddPeerRequest struct {
|
||||
|
||||
type AddPeerResponse struct{}
|
||||
|
||||
func (a *AdminSocket) addPeerHandler(req *AddPeerRequest, res *AddPeerResponse) error {
|
||||
func (a *AdminSocket) addPeerHandler(req *AddPeerRequest, _ *AddPeerResponse) error {
|
||||
u, err := url.Parse(req.Uri)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to parse peering URI: %w", err)
|
||||
|
@@ -201,10 +201,6 @@ func (a *AdminSocket) SetupAdminHandlers() {
|
||||
return res, nil
|
||||
},
|
||||
)
|
||||
//_ = a.AddHandler("getNodeInfo", []string{"key"}, t.proto.nodeinfo.nodeInfoAdminHandler)
|
||||
//_ = a.AddHandler("debug_remoteGetSelf", []string{"key"}, t.proto.getSelfHandler)
|
||||
//_ = a.AddHandler("debug_remoteGetPeers", []string{"key"}, t.proto.getPeersHandler)
|
||||
//_ = a.AddHandler("debug_remoteGetDHT", []string{"key"}, t.proto.getDHTHandler)
|
||||
}
|
||||
|
||||
// IsStarted returns true if the module has been started.
|
||||
@@ -269,7 +265,6 @@ func (a *AdminSocket) listen() {
|
||||
case "tcp":
|
||||
a.listener, err = net.Listen("tcp", u.Host)
|
||||
default:
|
||||
// err = errors.New(fmt.Sprint("protocol not supported: ", u.Scheme))
|
||||
a.listener, err = net.Listen("tcp", listenaddr)
|
||||
}
|
||||
} else {
|
||||
@@ -309,23 +304,6 @@ func (a *AdminSocket) handleRequest(conn net.Conn) {
|
||||
|
||||
defer conn.Close()
|
||||
|
||||
/*
|
||||
defer func() {
|
||||
r := recover()
|
||||
if r != nil {
|
||||
fmt.Println("ERROR:", r)
|
||||
a.log.Debugln("Admin socket error:", r)
|
||||
if err := encoder.Encode(&ErrorResponse{
|
||||
Error: "Check your syntax and input types",
|
||||
}); err != nil {
|
||||
fmt.Println("ERROR 2:", err)
|
||||
a.log.Debugln("Admin socket JSON encode error:", err)
|
||||
}
|
||||
conn.Close()
|
||||
}
|
||||
}()
|
||||
*/
|
||||
|
||||
for {
|
||||
var err error
|
||||
var buf json.RawMessage
|
||||
|
@@ -23,7 +23,7 @@ type PathEntry struct {
|
||||
Sequence uint64 `json:"sequence"`
|
||||
}
|
||||
|
||||
func (a *AdminSocket) getPathsHandler(req *GetPathsRequest, res *GetPathsResponse) error {
|
||||
func (a *AdminSocket) getPathsHandler(_ *GetPathsRequest, res *GetPathsResponse) error {
|
||||
paths := a.core.GetPaths()
|
||||
res.Paths = make([]PathEntry, 0, len(paths))
|
||||
for _, p := range paths {
|
||||
|
@@ -24,6 +24,7 @@ type PeerEntry struct {
|
||||
PublicKey string `json:"key"`
|
||||
Port uint64 `json:"port"`
|
||||
Priority uint64 `json:"priority"`
|
||||
Cost uint64 `json:"cost"`
|
||||
RXBytes DataUnit `json:"bytes_recvd,omitempty"`
|
||||
TXBytes DataUnit `json:"bytes_sent,omitempty"`
|
||||
Uptime float64 `json:"uptime,omitempty"`
|
||||
@@ -32,7 +33,7 @@ type PeerEntry struct {
|
||||
LastError string `json:"last_error,omitempty"`
|
||||
}
|
||||
|
||||
func (a *AdminSocket) getPeersHandler(req *GetPeersRequest, res *GetPeersResponse) error {
|
||||
func (a *AdminSocket) getPeersHandler(_ *GetPeersRequest, res *GetPeersResponse) error {
|
||||
peers := a.core.GetPeers()
|
||||
res.Peers = make([]PeerEntry, 0, len(peers))
|
||||
for _, p := range peers {
|
||||
@@ -41,6 +42,7 @@ func (a *AdminSocket) getPeersHandler(req *GetPeersRequest, res *GetPeersRespons
|
||||
Up: p.Up,
|
||||
Inbound: p.Inbound,
|
||||
Priority: uint64(p.Priority), // can't be uint8 thanks to gobind
|
||||
Cost: uint64(p.Cost), // can't be uint8 thanks to gobind
|
||||
URI: p.URI,
|
||||
RXBytes: DataUnit(p.RXBytes),
|
||||
TXBytes: DataUnit(p.TXBytes),
|
||||
|
@@ -17,7 +17,7 @@ type GetSelfResponse struct {
|
||||
Subnet string `json:"subnet"`
|
||||
}
|
||||
|
||||
func (a *AdminSocket) getSelfHandler(req *GetSelfRequest, res *GetSelfResponse) error {
|
||||
func (a *AdminSocket) getSelfHandler(_ *GetSelfRequest, res *GetSelfResponse) error {
|
||||
self := a.core.GetSelf()
|
||||
snet := a.core.Subnet()
|
||||
res.BuildName = version.BuildName()
|
||||
|
@@ -23,7 +23,7 @@ type SessionEntry struct {
|
||||
Uptime float64 `json:"uptime"`
|
||||
}
|
||||
|
||||
func (a *AdminSocket) getSessionsHandler(req *GetSessionsRequest, res *GetSessionsResponse) error {
|
||||
func (a *AdminSocket) getSessionsHandler(_ *GetSessionsRequest, res *GetSessionsResponse) error {
|
||||
sessions := a.core.GetSessions()
|
||||
res.Sessions = make([]SessionEntry, 0, len(sessions))
|
||||
for _, s := range sessions {
|
||||
|
@@ -20,11 +20,9 @@ type TreeEntry struct {
|
||||
PublicKey string `json:"key"`
|
||||
Parent string `json:"parent"`
|
||||
Sequence uint64 `json:"sequence"`
|
||||
//Port uint64 `json:"port"`
|
||||
//Rest uint64 `json:"rest"`
|
||||
}
|
||||
|
||||
func (a *AdminSocket) getTreeHandler(req *GetTreeRequest, res *GetTreeResponse) error {
|
||||
func (a *AdminSocket) getTreeHandler(_ *GetTreeRequest, res *GetTreeResponse) error {
|
||||
tree := a.core.GetTree()
|
||||
res.Tree = make([]TreeEntry, 0, len(tree))
|
||||
for _, d := range tree {
|
||||
@@ -34,8 +32,6 @@ func (a *AdminSocket) getTreeHandler(req *GetTreeRequest, res *GetTreeResponse)
|
||||
PublicKey: hex.EncodeToString(d.Key[:]),
|
||||
Parent: hex.EncodeToString(d.Parent[:]),
|
||||
Sequence: d.Sequence,
|
||||
//Port: d.Port,
|
||||
//Rest: d.Rest,
|
||||
})
|
||||
}
|
||||
sort.SliceStable(res.Tree, func(i, j int) bool {
|
||||
|
@@ -12,7 +12,7 @@ type RemovePeerRequest struct {
|
||||
|
||||
type RemovePeerResponse struct{}
|
||||
|
||||
func (a *AdminSocket) removePeerHandler(req *RemovePeerRequest, res *RemovePeerResponse) error {
|
||||
func (a *AdminSocket) removePeerHandler(req *RemovePeerRequest, _ *RemovePeerResponse) error {
|
||||
u, err := url.Parse(req.Uri)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to parse peering URI: %w", err)
|
||||
|
@@ -62,6 +62,7 @@ type MulticastInterfaceConfig struct {
|
||||
Listen bool
|
||||
Port uint16
|
||||
Priority uint64 // really uint8, but gobind won't export it
|
||||
Cost uint16 // really uint8, but gobind won't export it
|
||||
Password string
|
||||
}
|
||||
|
||||
|
@@ -30,6 +30,7 @@ type PeerInfo struct {
|
||||
Coords []uint64
|
||||
Port uint64
|
||||
Priority uint8
|
||||
Cost uint8
|
||||
RXBytes uint64
|
||||
TXBytes uint64
|
||||
Uptime time.Duration
|
||||
@@ -94,6 +95,7 @@ func (c *Core) GetPeers() []PeerInfo {
|
||||
peerinfo.Port = p.Port
|
||||
peerinfo.Priority = p.Priority
|
||||
peerinfo.Latency = p.Latency
|
||||
peerinfo.Cost = uint8(p.Cost)
|
||||
}
|
||||
peers = append(peers, peerinfo)
|
||||
}
|
||||
|
@@ -7,7 +7,6 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/netip"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -38,6 +37,8 @@ type links struct {
|
||||
unix *linkUNIX // UNIX interface support
|
||||
socks *linkSOCKS // SOCKS interface support
|
||||
quic *linkQUIC // QUIC interface support
|
||||
ws *linkWS // WS interface support
|
||||
wss *linkWSS // WSS interface support
|
||||
// _links can only be modified safely from within the links actor
|
||||
_links map[linkInfo]*link // *link is nil if connection in progress
|
||||
}
|
||||
@@ -69,6 +70,7 @@ type link struct {
|
||||
type linkOptions struct {
|
||||
pinnedEd25519Keys map[keyArray]struct{}
|
||||
priority uint8
|
||||
cost uint8
|
||||
tlsSNI string
|
||||
password []byte
|
||||
maxBackoff time.Duration
|
||||
@@ -98,6 +100,8 @@ func (l *links) init(c *Core) error {
|
||||
l.unix = l.newLinkUNIX()
|
||||
l.socks = l.newLinkSOCKS()
|
||||
l.quic = l.newLinkQUIC()
|
||||
l.ws = l.newLinkWS()
|
||||
l.wss = l.newLinkWSS()
|
||||
l._links = make(map[linkInfo]*link)
|
||||
|
||||
var listeners []ListenAddress
|
||||
@@ -136,6 +140,7 @@ func (e linkError) Error() string { return string(e) }
|
||||
const ErrLinkAlreadyConfigured = linkError("peer is already configured")
|
||||
const ErrLinkNotConfigured = linkError("peer is not configured")
|
||||
const ErrLinkPriorityInvalid = linkError("priority value is invalid")
|
||||
const ErrLinkCostInvalid = linkError("cost value is invalid")
|
||||
const ErrLinkPinnedKeyInvalid = linkError("pinned public key is invalid")
|
||||
const ErrLinkPasswordInvalid = linkError("password is invalid")
|
||||
const ErrLinkUnrecognisedSchema = linkError("link schema unknown")
|
||||
@@ -178,6 +183,14 @@ func (l *links) add(u *url.URL, sintf string, linkType linkType) error {
|
||||
}
|
||||
options.priority = uint8(pi)
|
||||
}
|
||||
if p := u.Query().Get("cost"); p != "" {
|
||||
c, err := strconv.ParseUint(p, 10, 8)
|
||||
if err != nil {
|
||||
retErr = ErrLinkCostInvalid
|
||||
return
|
||||
}
|
||||
options.cost = uint8(c)
|
||||
}
|
||||
if p := u.Query().Get("password"); p != "" {
|
||||
if len(p) > blake2b.Size {
|
||||
retErr = ErrLinkPasswordInvalid
|
||||
@@ -379,7 +392,7 @@ func (l *links) add(u *url.URL, sintf string, linkType linkType) error {
|
||||
return retErr
|
||||
}
|
||||
|
||||
func (l *links) remove(u *url.URL, sintf string, linkType linkType) error {
|
||||
func (l *links) remove(u *url.URL, sintf string, _ linkType) error {
|
||||
var retErr error
|
||||
phony.Block(l, func() {
|
||||
// Generate the link info and see whether we think we already
|
||||
@@ -418,6 +431,10 @@ func (l *links) listen(u *url.URL, sintf string) (*Listener, error) {
|
||||
protocol = l.unix
|
||||
case "quic":
|
||||
protocol = l.quic
|
||||
case "ws":
|
||||
protocol = l.ws
|
||||
case "wss":
|
||||
protocol = l.wss
|
||||
default:
|
||||
cancel()
|
||||
return nil, ErrLinkUnrecognisedSchema
|
||||
@@ -441,6 +458,13 @@ func (l *links) listen(u *url.URL, sintf string) (*Listener, error) {
|
||||
}
|
||||
options.priority = uint8(pi)
|
||||
}
|
||||
if p := u.Query().Get("cost"); p != "" {
|
||||
c, err := strconv.ParseUint(p, 10, 8)
|
||||
if err != nil {
|
||||
return nil, ErrLinkCostInvalid
|
||||
}
|
||||
options.cost = uint8(c)
|
||||
}
|
||||
if p := u.Query().Get("password"); p != "" {
|
||||
if len(p) > blake2b.Size {
|
||||
return nil, ErrLinkPasswordInvalid
|
||||
@@ -546,6 +570,10 @@ func (l *links) connect(ctx context.Context, u *url.URL, info linkInfo, options
|
||||
dialer = l.unix
|
||||
case "quic":
|
||||
dialer = l.quic
|
||||
case "ws":
|
||||
dialer = l.ws
|
||||
case "wss":
|
||||
dialer = l.wss
|
||||
default:
|
||||
return nil, ErrLinkUnrecognisedSchema
|
||||
}
|
||||
@@ -556,6 +584,7 @@ func (l *links) handler(linkType linkType, options linkOptions, conn net.Conn, s
|
||||
meta := version_getBaseMetadata()
|
||||
meta.publicKey = l.core.public
|
||||
meta.priority = options.priority
|
||||
meta.cost = options.cost
|
||||
metaBytes, err := meta.encode(l.core.secret, options.password)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to generate handshake: %w", err)
|
||||
@@ -567,7 +596,7 @@ func (l *links) handler(linkType linkType, options linkOptions, conn net.Conn, s
|
||||
switch {
|
||||
case err != nil:
|
||||
return fmt.Errorf("write handshake: %w", err)
|
||||
case err == nil && n != len(metaBytes):
|
||||
case n != len(metaBytes):
|
||||
return fmt.Errorf("incomplete handshake send")
|
||||
}
|
||||
meta = version_metadata{}
|
||||
@@ -617,17 +646,20 @@ func (l *links) handler(linkType linkType, options linkOptions, conn net.Conn, s
|
||||
remoteAddr := net.IP(address.AddrForKey(meta.publicKey)[:]).String()
|
||||
remoteStr := fmt.Sprintf("%s@%s", remoteAddr, conn.RemoteAddr())
|
||||
localStr := conn.LocalAddr()
|
||||
priority := options.priority
|
||||
cost, priority := options.cost, options.priority
|
||||
if meta.priority > priority {
|
||||
priority = meta.priority
|
||||
}
|
||||
if meta.cost > cost {
|
||||
cost = meta.cost
|
||||
}
|
||||
l.core.log.Infof("Connected %s: %s, source %s",
|
||||
dir, remoteStr, localStr)
|
||||
if success != nil {
|
||||
success()
|
||||
}
|
||||
|
||||
err = l.core.HandleConn(meta.publicKey, conn, priority)
|
||||
err = l.core.HandleConn(meta.publicKey, conn, cost, priority)
|
||||
switch err {
|
||||
case io.EOF, net.ErrClosed, nil:
|
||||
l.core.log.Infof("Disconnected %s: %s, source %s",
|
||||
@@ -641,16 +673,6 @@ func (l *links) handler(linkType linkType, options linkOptions, conn net.Conn, s
|
||||
|
||||
func urlForLinkInfo(u url.URL) url.URL {
|
||||
u.RawQuery = ""
|
||||
if host, _, err := net.SplitHostPort(u.Host); err == nil {
|
||||
if addr, err := netip.ParseAddr(host); err == nil {
|
||||
// For peers that look like multicast peers (i.e.
|
||||
// link-local addresses), we will ignore the port number,
|
||||
// otherwise we might open multiple connections to them.
|
||||
if addr.IsLinkLocalUnicast() {
|
||||
u.Host = fmt.Sprintf("[%s]", addr.String())
|
||||
}
|
||||
}
|
||||
}
|
||||
return u
|
||||
}
|
||||
|
||||
|
@@ -28,6 +28,6 @@ func (t *linkTCP) tcpContext(network, address string, c syscall.RawConn) error {
|
||||
}
|
||||
}
|
||||
|
||||
func (t *linkTCP) getControl(sintf string) func(string, string, syscall.RawConn) error {
|
||||
func (t *linkTCP) getControl(_ string) func(string, string, syscall.RawConn) error {
|
||||
return t.tcpContext
|
||||
}
|
||||
|
123
src/core/link_ws.go
Normal file
123
src/core/link_ws.go
Normal file
@@ -0,0 +1,123 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/Arceliar/phony"
|
||||
"nhooyr.io/websocket"
|
||||
)
|
||||
|
||||
type linkWS struct {
|
||||
phony.Inbox
|
||||
*links
|
||||
}
|
||||
|
||||
type linkWSConn struct {
|
||||
net.Conn
|
||||
}
|
||||
|
||||
type linkWSListener struct {
|
||||
ch chan *linkWSConn
|
||||
ctx context.Context
|
||||
httpServer *http.Server
|
||||
listener net.Listener
|
||||
}
|
||||
|
||||
type wsServer struct {
|
||||
ch chan *linkWSConn
|
||||
ctx context.Context
|
||||
}
|
||||
|
||||
func (l *linkWSListener) Accept() (net.Conn, error) {
|
||||
qs := <-l.ch
|
||||
if qs == nil {
|
||||
return nil, context.Canceled
|
||||
}
|
||||
return qs, nil
|
||||
}
|
||||
|
||||
func (l *linkWSListener) Addr() net.Addr {
|
||||
return l.listener.Addr()
|
||||
}
|
||||
|
||||
func (l *linkWSListener) Close() error {
|
||||
if err := l.httpServer.Shutdown(l.ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return l.listener.Close()
|
||||
}
|
||||
|
||||
func (s *wsServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
if r.URL.Path == "/health" || r.URL.Path == "/healthz" {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
_, _ = w.Write([]byte("OK"))
|
||||
return
|
||||
}
|
||||
|
||||
c, err := websocket.Accept(w, r, &websocket.AcceptOptions{
|
||||
Subprotocols: []string{"ygg-ws"},
|
||||
})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if c.Subprotocol() != "ygg-ws" {
|
||||
c.Close(websocket.StatusPolicyViolation, "client must speak the ygg-ws subprotocol")
|
||||
return
|
||||
}
|
||||
|
||||
s.ch <- &linkWSConn{
|
||||
Conn: websocket.NetConn(s.ctx, c, websocket.MessageBinary),
|
||||
}
|
||||
}
|
||||
|
||||
func (l *links) newLinkWS() *linkWS {
|
||||
lt := &linkWS{
|
||||
links: l,
|
||||
}
|
||||
return lt
|
||||
}
|
||||
|
||||
func (l *linkWS) dial(ctx context.Context, url *url.URL, info linkInfo, options linkOptions) (net.Conn, error) {
|
||||
wsconn, _, err := websocket.Dial(ctx, url.String(), &websocket.DialOptions{
|
||||
Subprotocols: []string{"ygg-ws"},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &linkWSConn{
|
||||
Conn: websocket.NetConn(ctx, wsconn, websocket.MessageBinary),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (l *linkWS) listen(ctx context.Context, url *url.URL, _ string) (net.Listener, error) {
|
||||
nl, err := net.Listen("tcp", url.Host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ch := make(chan *linkWSConn)
|
||||
|
||||
httpServer := &http.Server{
|
||||
Handler: &wsServer{
|
||||
ch: ch,
|
||||
ctx: ctx,
|
||||
},
|
||||
BaseContext: func(_ net.Listener) context.Context { return ctx },
|
||||
ReadTimeout: time.Second * 10,
|
||||
WriteTimeout: time.Second * 10,
|
||||
}
|
||||
|
||||
lwl := &linkWSListener{
|
||||
ch: ch,
|
||||
ctx: ctx,
|
||||
httpServer: httpServer,
|
||||
listener: nl,
|
||||
}
|
||||
go lwl.httpServer.Serve(nl) // nolint:errcheck
|
||||
return lwl, nil
|
||||
}
|
43
src/core/link_wss.go
Normal file
43
src/core/link_wss.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/url"
|
||||
|
||||
"github.com/Arceliar/phony"
|
||||
"nhooyr.io/websocket"
|
||||
)
|
||||
|
||||
type linkWSS struct {
|
||||
phony.Inbox
|
||||
*links
|
||||
}
|
||||
|
||||
type linkWSSConn struct {
|
||||
net.Conn
|
||||
}
|
||||
|
||||
func (l *links) newLinkWSS() *linkWSS {
|
||||
lwss := &linkWSS{
|
||||
links: l,
|
||||
}
|
||||
return lwss
|
||||
}
|
||||
|
||||
func (l *linkWSS) dial(ctx context.Context, url *url.URL, info linkInfo, options linkOptions) (net.Conn, error) {
|
||||
wsconn, _, err := websocket.Dial(ctx, url.String(), &websocket.DialOptions{
|
||||
Subprotocols: []string{"ygg-ws"},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &linkWSSConn{
|
||||
Conn: websocket.NetConn(ctx, wsconn, websocket.MessageBinary),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (l *linkWSS) listen(ctx context.Context, url *url.URL, _ string) (net.Listener, error) {
|
||||
return nil, fmt.Errorf("WSS listener not supported, use WS listener behind reverse proxy instead")
|
||||
}
|
@@ -22,6 +22,7 @@ type version_metadata struct {
|
||||
minorVer uint16
|
||||
publicKey ed25519.PublicKey
|
||||
priority uint8
|
||||
cost uint8
|
||||
}
|
||||
|
||||
const (
|
||||
@@ -36,6 +37,7 @@ const (
|
||||
metaVersionMinor // uint16
|
||||
metaPublicKey // [32]byte
|
||||
metaPriority // uint8
|
||||
metaCost // uint8
|
||||
)
|
||||
|
||||
// Gets a base metadata with no keys set, but with the correct version numbers.
|
||||
@@ -64,9 +66,17 @@ func (m *version_metadata) encode(privateKey ed25519.PrivateKey, password []byte
|
||||
bs = binary.BigEndian.AppendUint16(bs, ed25519.PublicKeySize)
|
||||
bs = append(bs, m.publicKey[:]...)
|
||||
|
||||
bs = binary.BigEndian.AppendUint16(bs, metaPriority)
|
||||
bs = binary.BigEndian.AppendUint16(bs, 1)
|
||||
bs = append(bs, m.priority)
|
||||
if m.priority > 0 {
|
||||
bs = binary.BigEndian.AppendUint16(bs, metaPriority)
|
||||
bs = binary.BigEndian.AppendUint16(bs, 1)
|
||||
bs = append(bs, m.priority)
|
||||
}
|
||||
|
||||
if m.cost > 0 {
|
||||
bs = binary.BigEndian.AppendUint16(bs, metaCost)
|
||||
bs = binary.BigEndian.AppendUint16(bs, 1)
|
||||
bs = append(bs, m.cost)
|
||||
}
|
||||
|
||||
hasher, err := blake2b.New512(password)
|
||||
if err != nil {
|
||||
@@ -126,6 +136,9 @@ func (m *version_metadata) decode(r io.Reader, password []byte) error {
|
||||
|
||||
case metaPriority:
|
||||
m.priority = bs[0]
|
||||
|
||||
case metaCost:
|
||||
m.cost = bs[0]
|
||||
}
|
||||
bs = bs[oplen:]
|
||||
}
|
||||
|
@@ -52,6 +52,9 @@ func TestVersionRoundtrip(t *testing.T) {
|
||||
{majorVer: 258, minorVer: 259},
|
||||
{majorVer: 3, minorVer: 5, priority: 6},
|
||||
{majorVer: 260, minorVer: 261, priority: 7},
|
||||
{majorVer: 258, minorVer: 259, cost: 5},
|
||||
{majorVer: 3, minorVer: 5, priority: 6, cost: 12},
|
||||
{majorVer: 260, minorVer: 261, priority: 7, cost: 1},
|
||||
} {
|
||||
// Generate a random public key for each time, since it is
|
||||
// a required field.
|
||||
|
@@ -11,7 +11,7 @@ type GetMulticastInterfacesResponse struct {
|
||||
Interfaces []string `json:"multicast_interfaces"`
|
||||
}
|
||||
|
||||
func (m *Multicast) getMulticastInterfacesHandler(req *GetMulticastInterfacesRequest, res *GetMulticastInterfacesResponse) error {
|
||||
func (m *Multicast) getMulticastInterfacesHandler(_ *GetMulticastInterfacesRequest, res *GetMulticastInterfacesResponse) error {
|
||||
res.Interfaces = []string{}
|
||||
for _, v := range m.Interfaces() {
|
||||
res.Interfaces = append(res.Interfaces, v.Name)
|
||||
|
@@ -45,6 +45,7 @@ type interfaceInfo struct {
|
||||
listen bool
|
||||
port uint16
|
||||
priority uint8
|
||||
cost uint8
|
||||
password []byte
|
||||
hash []byte
|
||||
}
|
||||
@@ -214,6 +215,7 @@ func (m *Multicast) _getAllowedInterfaces() map[string]*interfaceInfo {
|
||||
listen: ifcfg.Listen,
|
||||
port: ifcfg.Port,
|
||||
priority: ifcfg.Priority,
|
||||
cost: ifcfg.Cost,
|
||||
password: []byte(ifcfg.Password),
|
||||
hash: hasher.Sum(nil),
|
||||
}
|
||||
@@ -314,6 +316,7 @@ func (m *Multicast) _announce() {
|
||||
// No listener was found - let's create one
|
||||
v := &url.Values{}
|
||||
v.Add("priority", fmt.Sprintf("%d", info.priority))
|
||||
v.Add("cost", fmt.Sprintf("%d", info.cost))
|
||||
v.Add("password", string(info.password))
|
||||
u := &url.URL{
|
||||
Scheme: "tls",
|
||||
@@ -428,6 +431,7 @@ func (m *Multicast) listen() {
|
||||
v := &url.Values{}
|
||||
v.Add("key", hex.EncodeToString(adv.PublicKey))
|
||||
v.Add("priority", fmt.Sprintf("%d", info.priority))
|
||||
v.Add("cost", fmt.Sprintf("%d", info.cost))
|
||||
v.Add("password", string(info.password))
|
||||
u := &url.URL{
|
||||
Scheme: "tls",
|
||||
|
@@ -21,6 +21,7 @@ type MulticastInterface struct {
|
||||
Listen bool
|
||||
Port uint16
|
||||
Priority uint8
|
||||
Cost uint8
|
||||
Password string
|
||||
}
|
||||
|
||||
|
@@ -1,42 +1,60 @@
|
||||
package tun
|
||||
|
||||
const TUN_OFFSET_BYTES = 4
|
||||
const TUN_OFFSET_BYTES = 80 // sizeof(virtio_net_hdr)
|
||||
|
||||
func (tun *TunAdapter) read() {
|
||||
var buf [TUN_OFFSET_BYTES + 65535]byte
|
||||
vs := tun.iface.BatchSize()
|
||||
bufs := make([][]byte, vs)
|
||||
sizes := make([]int, vs)
|
||||
for i := range bufs {
|
||||
bufs[i] = make([]byte, TUN_OFFSET_BYTES+65535)
|
||||
}
|
||||
for {
|
||||
n, err := tun.iface.Read(buf[:], TUN_OFFSET_BYTES)
|
||||
if n <= TUN_OFFSET_BYTES || err != nil {
|
||||
n, err := tun.iface.Read(bufs, sizes, TUN_OFFSET_BYTES)
|
||||
if err != nil {
|
||||
tun.log.Errorln("Error reading TUN:", err)
|
||||
ferr := tun.iface.Flush()
|
||||
if ferr != nil {
|
||||
tun.log.Errorln("Unable to flush packets:", ferr)
|
||||
}
|
||||
return
|
||||
}
|
||||
begin := TUN_OFFSET_BYTES
|
||||
end := begin + n
|
||||
bs := buf[begin:end]
|
||||
if _, err := tun.rwc.Write(bs); err != nil {
|
||||
tun.log.Debugln("Unable to send packet:", err)
|
||||
for i, b := range bufs[:n] {
|
||||
if _, err := tun.rwc.Write(b[TUN_OFFSET_BYTES : TUN_OFFSET_BYTES+sizes[i]]); err != nil {
|
||||
tun.log.Debugln("Unable to send packet:", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (tun *TunAdapter) write() {
|
||||
var buf [TUN_OFFSET_BYTES + 65535]byte
|
||||
func (tun *TunAdapter) queue() {
|
||||
for {
|
||||
bs := buf[TUN_OFFSET_BYTES:]
|
||||
n, err := tun.rwc.Read(bs)
|
||||
p := bufPool.Get().([]byte)[:bufPoolSize]
|
||||
n, err := tun.rwc.Read(p)
|
||||
if err != nil {
|
||||
tun.log.Errorln("Exiting TUN writer due to core read error:", err)
|
||||
return
|
||||
}
|
||||
tun.ch <- p[:n]
|
||||
}
|
||||
}
|
||||
|
||||
func (tun *TunAdapter) write() {
|
||||
vs := cap(tun.ch)
|
||||
bufs := make([][]byte, vs)
|
||||
for i := range bufs {
|
||||
bufs[i] = make([]byte, TUN_OFFSET_BYTES+65535)
|
||||
}
|
||||
for {
|
||||
n := len(tun.ch)
|
||||
if n == 0 {
|
||||
n = 1 // Nothing queued up yet, wait for it instead
|
||||
}
|
||||
for i := 0; i < n; i++ {
|
||||
msg := <-tun.ch
|
||||
bufs[i] = append(bufs[i][:TUN_OFFSET_BYTES], msg...)
|
||||
bufPool.Put(msg) // nolint:staticcheck
|
||||
}
|
||||
if !tun.isEnabled {
|
||||
continue // Nothing to do, the tun isn't enabled
|
||||
}
|
||||
bs = buf[:TUN_OFFSET_BYTES+n]
|
||||
if _, err = tun.iface.Write(bs, TUN_OFFSET_BYTES); err != nil {
|
||||
if _, err := tun.iface.Write(bufs[:n], TUN_OFFSET_BYTES); err != nil {
|
||||
tun.Act(nil, func() {
|
||||
if !tun.isOpen {
|
||||
tun.log.Errorln("TUN iface write error:", err)
|
||||
|
@@ -10,9 +10,11 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/Arceliar/phony"
|
||||
"golang.zx2c4.com/wireguard/tun"
|
||||
wgtun "golang.zx2c4.com/wireguard/tun"
|
||||
|
||||
"github.com/yggdrasil-network/yggdrasil-go/src/address"
|
||||
"github.com/yggdrasil-network/yggdrasil-go/src/config"
|
||||
@@ -39,7 +41,7 @@ type TunAdapter struct {
|
||||
addr address.Address
|
||||
subnet address.Subnet
|
||||
mtu uint64
|
||||
iface tun.Device
|
||||
iface wgtun.Device
|
||||
phony.Inbox // Currently only used for _handlePacket from the reader, TODO: all the stuff that currently needs a mutex below
|
||||
isOpen bool
|
||||
isEnabled bool // Used by the writer to drop sessionTraffic if not enabled
|
||||
@@ -48,6 +50,7 @@ type TunAdapter struct {
|
||||
name InterfaceName
|
||||
mtu InterfaceMTU
|
||||
}
|
||||
ch chan []byte
|
||||
}
|
||||
|
||||
// Gets the maximum supported MTU for the platform based on the defaults in
|
||||
@@ -62,6 +65,20 @@ func getSupportedMTU(mtu uint64) uint64 {
|
||||
return mtu
|
||||
}
|
||||
|
||||
func waitForTUNUp(ch <-chan wgtun.Event) bool {
|
||||
t := time.After(time.Second * 5)
|
||||
for {
|
||||
select {
|
||||
case ev := <-ch:
|
||||
if ev == wgtun.EventUp {
|
||||
return true
|
||||
}
|
||||
case <-t:
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Name returns the name of the adapter, e.g. "tun0". On Windows, this may
|
||||
// return a canonical adapter name instead.
|
||||
func (tun *TunAdapter) Name() string {
|
||||
@@ -145,6 +162,8 @@ func (tun *TunAdapter) _start() error {
|
||||
tun.rwc.SetMTU(tun.MTU())
|
||||
tun.isOpen = true
|
||||
tun.isEnabled = true
|
||||
tun.ch = make(chan []byte, tun.iface.BatchSize())
|
||||
go tun.queue()
|
||||
go tun.read()
|
||||
go tun.write()
|
||||
return nil
|
||||
@@ -178,3 +197,12 @@ func (tun *TunAdapter) _stop() error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
const bufPoolSize = TUN_OFFSET_BYTES + 65535
|
||||
|
||||
var bufPool = sync.Pool{
|
||||
New: func() any {
|
||||
b := [bufPoolSize]byte{}
|
||||
return b[:]
|
||||
},
|
||||
}
|
||||
|
@@ -80,6 +80,9 @@ func (tun *TunAdapter) setup(ifname string, addr string, mtu uint64) error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create TUN: %w", err)
|
||||
}
|
||||
if !waitForTUNUp(iface.Events()) {
|
||||
return fmt.Errorf("TUN did not come up in time")
|
||||
}
|
||||
tun.iface = iface
|
||||
if mtu, err := iface.MTU(); err == nil {
|
||||
tun.mtu = getSupportedMTU(uint64(mtu))
|
||||
|
@@ -27,6 +27,9 @@ func (tun *TunAdapter) setup(ifname string, addr string, mtu uint64) error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create TUN: %w", err)
|
||||
}
|
||||
if !waitForTUNUp(iface.Events()) {
|
||||
return fmt.Errorf("TUN did not come up in time")
|
||||
}
|
||||
tun.iface = iface
|
||||
if m, err := iface.MTU(); err == nil {
|
||||
tun.mtu = getSupportedMTU(uint64(m))
|
||||
@@ -55,6 +58,9 @@ func (tun *TunAdapter) setupFD(fd int32, addr string, mtu uint64) error {
|
||||
unix.Close(dfd)
|
||||
return fmt.Errorf("failed to create TUN from FD: %w", err)
|
||||
}
|
||||
if !waitForTUNUp(iface.Events()) {
|
||||
return fmt.Errorf("TUN did not come up in time")
|
||||
}
|
||||
tun.iface = iface
|
||||
if m, err := iface.MTU(); err == nil {
|
||||
tun.mtu = getSupportedMTU(uint64(m))
|
||||
|
@@ -21,6 +21,9 @@ func (tun *TunAdapter) setup(ifname string, addr string, mtu uint64) error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create TUN: %w", err)
|
||||
}
|
||||
if !waitForTUNUp(iface.Events()) {
|
||||
return fmt.Errorf("TUN did not come up in time")
|
||||
}
|
||||
tun.iface = iface
|
||||
if mtu, err := iface.MTU(); err == nil {
|
||||
tun.mtu = getSupportedMTU(uint64(mtu))
|
||||
|
@@ -18,6 +18,9 @@ func (tun *TunAdapter) setup(ifname string, addr string, mtu uint64) error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create TUN: %w", err)
|
||||
}
|
||||
if !waitForTUNUp(iface.Events()) {
|
||||
return fmt.Errorf("TUN did not come up in time")
|
||||
}
|
||||
tun.iface = iface
|
||||
if mtu, err := iface.MTU(); err == nil {
|
||||
tun.mtu = getSupportedMTU(uint64(mtu))
|
||||
|
@@ -34,6 +34,9 @@ func (tun *TunAdapter) setup(ifname string, addr string, mtu uint64) error {
|
||||
if iface, err = wgtun.CreateTUNWithRequestedGUID(ifname, &guid, int(mtu)); err != nil {
|
||||
return err
|
||||
}
|
||||
if !waitForTUNUp(iface.Events()) {
|
||||
return fmt.Errorf("TUN did not come up in time")
|
||||
}
|
||||
tun.iface = iface
|
||||
if addr != "" {
|
||||
if err = tun.setupAddress(addr); err != nil {
|
||||
|
Reference in New Issue
Block a user