mirror of
https://github.com/simon-ding/polaris.git
synced 2026-02-06 23:21:00 +08:00
WIP: stun proxy
This commit is contained in:
25
go.mod
25
go.mod
@@ -10,7 +10,7 @@ require (
|
||||
github.com/mattn/go-sqlite3 v1.14.22 // indirect
|
||||
github.com/robfig/cron v1.2.0
|
||||
go.uber.org/zap v1.27.0
|
||||
golang.org/x/net v0.39.0
|
||||
golang.org/x/net v0.40.0
|
||||
)
|
||||
|
||||
require (
|
||||
@@ -21,6 +21,8 @@ require (
|
||||
github.com/gocolly/colly v1.2.0
|
||||
github.com/ncruces/go-sqlite3 v0.18.4
|
||||
github.com/nikoksr/notify v1.0.0
|
||||
github.com/openai/openai-go v0.1.0-beta.10
|
||||
github.com/pion/stun/v3 v3.0.0
|
||||
github.com/stretchr/testify v1.9.0
|
||||
golift.io/starr v1.0.0
|
||||
)
|
||||
@@ -55,7 +57,6 @@ require (
|
||||
github.com/bits-and-blooms/bitset v1.2.2 // indirect
|
||||
github.com/blinkbean/dingtalk v1.1.3 // indirect
|
||||
github.com/bradfitz/iter v0.0.0-20191230175014-e8f45d346db8 // indirect
|
||||
github.com/buger/jsonparser v1.1.1 // indirect
|
||||
github.com/cespare/xxhash v1.1.0 // indirect
|
||||
github.com/dustin/go-humanize v1.0.0 // indirect
|
||||
github.com/edsrzf/mmap-go v1.1.0 // indirect
|
||||
@@ -73,19 +74,17 @@ require (
|
||||
github.com/gregdel/pushover v1.3.1 // indirect
|
||||
github.com/huandu/xstrings v1.3.2 // indirect
|
||||
github.com/kennygrant/sanitize v1.2.4 // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/minio/sha256-simd v1.0.0 // indirect
|
||||
github.com/mr-tron/base58 v1.2.0 // indirect
|
||||
github.com/mschoch/smat v0.2.0 // indirect
|
||||
github.com/multiformats/go-multihash v0.2.3 // indirect
|
||||
github.com/multiformats/go-varint v0.0.6 // indirect
|
||||
github.com/ncruces/julianday v1.0.0 // indirect
|
||||
github.com/openai/openai-go v0.1.0-beta.10 // indirect
|
||||
github.com/pion/datachannel v1.5.9 // indirect
|
||||
github.com/pion/dtls/v3 v3.0.3 // indirect
|
||||
github.com/pion/ice/v4 v4.0.2 // indirect
|
||||
github.com/pion/interceptor v0.1.37 // indirect
|
||||
github.com/pion/logging v0.2.2 // indirect
|
||||
github.com/pion/logging v0.2.3 // indirect
|
||||
github.com/pion/mdns/v2 v2.0.7 // indirect
|
||||
github.com/pion/randutil v0.1.0 // indirect
|
||||
github.com/pion/rtcp v1.2.14 // indirect
|
||||
@@ -93,7 +92,6 @@ require (
|
||||
github.com/pion/sctp v1.8.33 // indirect
|
||||
github.com/pion/sdp/v3 v3.0.9 // indirect
|
||||
github.com/pion/srtp/v3 v3.0.4 // indirect
|
||||
github.com/pion/stun/v3 v3.0.0 // indirect
|
||||
github.com/pion/transport/v3 v3.0.7 // indirect
|
||||
github.com/pion/turn/v4 v4.0.0 // indirect
|
||||
github.com/pion/webrtc/v4 v4.0.0 // indirect
|
||||
@@ -112,15 +110,13 @@ require (
|
||||
github.com/tidwall/match v1.1.1 // indirect
|
||||
github.com/tidwall/pretty v1.2.1 // indirect
|
||||
github.com/tidwall/sjson v1.2.5 // indirect
|
||||
github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect
|
||||
github.com/wlynxg/anet v0.0.3 // indirect
|
||||
github.com/wlynxg/anet v0.0.5 // indirect
|
||||
go.etcd.io/bbolt v1.3.6 // indirect
|
||||
go.opentelemetry.io/otel v1.28.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.28.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.28.0 // indirect
|
||||
golang.org/x/sync v0.13.0 // indirect
|
||||
golang.org/x/sync v0.14.0 // indirect
|
||||
golang.org/x/time v0.5.0 // indirect
|
||||
golang.org/x/tools v0.32.0 // indirect
|
||||
google.golang.org/appengine v1.6.8 // indirect
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
@@ -148,7 +144,7 @@ require (
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/go-playground/validator/v10 v10.20.0 // indirect
|
||||
github.com/goccy/go-json v0.10.2 // indirect
|
||||
github.com/goccy/go-json v0.10.2
|
||||
github.com/google/go-cmp v0.6.0 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||
@@ -174,11 +170,11 @@ require (
|
||||
github.com/ugorji/go/codec v1.2.12 // indirect
|
||||
github.com/zclconf/go-cty v1.8.0 // indirect
|
||||
golang.org/x/arch v0.8.0 // indirect
|
||||
golang.org/x/crypto v0.37.0
|
||||
golang.org/x/crypto v0.38.0
|
||||
golang.org/x/exp v0.0.0-20240823005443-9b4947da3948
|
||||
golang.org/x/mod v0.24.0 // indirect
|
||||
golang.org/x/sys v0.32.0
|
||||
golang.org/x/text v0.24.0 // indirect
|
||||
golang.org/x/sys v0.33.0
|
||||
golang.org/x/text v0.25.0 // indirect
|
||||
google.golang.org/protobuf v1.36.5 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
@@ -188,7 +184,6 @@ require (
|
||||
github.com/cyruzin/golang-tmdb v1.6.3
|
||||
github.com/gin-gonic/gin v1.10.0
|
||||
github.com/hekmon/transmissionrpc/v3 v3.0.0
|
||||
github.com/invopop/jsonschema v0.13.0
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
|
||||
49
go.sum
49
go.sum
@@ -120,8 +120,6 @@ github.com/bradfitz/iter v0.0.0-20140124041915-454541ec3da2/go.mod h1:PyRFw1Lt2w
|
||||
github.com/bradfitz/iter v0.0.0-20190303215204-33e6a9893b0c/go.mod h1:PyRFw1Lt2wKX4ZVSQ2mk+PeDa1rxyObEDlApuIsUKuo=
|
||||
github.com/bradfitz/iter v0.0.0-20191230175014-e8f45d346db8 h1:GKTyiRCL6zVf5wWaqKnf+7Qs6GbEPfd4iMOitWzXJx8=
|
||||
github.com/bradfitz/iter v0.0.0-20191230175014-e8f45d346db8/go.mod h1:spo1JLcs67NmW1aVLEgtA8Yy1elc+X8y5SRW1sFW4Og=
|
||||
github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs=
|
||||
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
|
||||
github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0=
|
||||
github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4=
|
||||
github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM=
|
||||
@@ -280,13 +278,8 @@ github.com/huandu/xstrings v1.3.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq
|
||||
github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
|
||||
github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw=
|
||||
github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/invopop/jsonschema v0.13.0 h1:KvpoAJWEjR3uD9Kbm2HWJmqsEaHt8lBUpd0qHcIi21E=
|
||||
github.com/invopop/jsonschema v0.13.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0=
|
||||
github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible h1:jdpOPRN1zP63Td1hDQbZW73xKmzDvZHzVdNYxhnTMDA=
|
||||
github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible/go.mod h1:1c7szIrayyPPB/987hsnvNzLushdWf4o/79s3P08L8A=
|
||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
@@ -320,12 +313,8 @@ github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
||||
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
||||
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
|
||||
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
|
||||
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
|
||||
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
@@ -360,8 +349,6 @@ github.com/ncruces/julianday v1.0.0 h1:fH0OKwa7NWvniGQtxdJRxAgkBMolni2BjDHaWTxqt
|
||||
github.com/ncruces/julianday v1.0.0/go.mod h1:Dusn2KvZrrovOMJuOt0TNXL6tB7U2E8kvza5fFc9G7g=
|
||||
github.com/nikoksr/notify v1.0.0 h1:qe9/6FRsWdxBgQgWcpvQ0sv8LRGJZDpRB4TkL2uNdO8=
|
||||
github.com/nikoksr/notify v1.0.0/go.mod h1:hPaaDt30d6LAA7/5nb0e48Bp/MctDfycCSs8VEgN29I=
|
||||
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 v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
@@ -380,8 +367,8 @@ github.com/pion/ice/v4 v4.0.2 h1:1JhBRX8iQLi0+TfcavTjPjI6GO41MFn4CeTBX+Y9h5s=
|
||||
github.com/pion/ice/v4 v4.0.2/go.mod h1:DCdqyzgtsDNYN6/3U8044j3U7qsJ9KFJC92VnOWHvXg=
|
||||
github.com/pion/interceptor v0.1.37 h1:aRA8Zpab/wE7/c0O3fh1PqY0AJI3fCSEM5lRWJVorwI=
|
||||
github.com/pion/interceptor v0.1.37/go.mod h1:JzxbJ4umVTlZAf+/utHzNesY8tmRkM2lVmkS82TTj8Y=
|
||||
github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY=
|
||||
github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms=
|
||||
github.com/pion/logging v0.2.3 h1:gHuf0zpoh1GW67Nr6Gj4cv5Z9ZscU7g/EaoC/Ke/igI=
|
||||
github.com/pion/logging v0.2.3/go.mod h1:z8YfknkquMe1csOrxK5kc+5/ZPAzMxbKLX5aXpbpC90=
|
||||
github.com/pion/mdns/v2 v2.0.7 h1:c9kM8ewCgjslaAmicYMFQIde2H9/lrZpjBkN8VwoVtM=
|
||||
github.com/pion/mdns/v2 v2.0.7/go.mod h1:vAdSYNAT0Jy3Ru0zl2YiW3Rm/fJCwIeM0nToenfOJKA=
|
||||
github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA=
|
||||
@@ -468,8 +455,6 @@ github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
|
||||
github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY=
|
||||
github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0=
|
||||
github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
|
||||
github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
|
||||
github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI=
|
||||
@@ -522,10 +507,8 @@ github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+
|
||||
github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI=
|
||||
github.com/willf/bitset v1.1.9/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
|
||||
github.com/willf/bitset v1.1.10/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
|
||||
github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc=
|
||||
github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw=
|
||||
github.com/wlynxg/anet v0.0.3 h1:PvR53psxFXstc12jelG6f1Lv4MWqE0tI76/hHGjh9rg=
|
||||
github.com/wlynxg/anet v0.0.3/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA=
|
||||
github.com/wlynxg/anet v0.0.5 h1:J3VJGi1gvo0JwZ/P1/Yc/8p63SoW98B5dHkYDmpgvvU=
|
||||
github.com/wlynxg/anet v0.0.5/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA=
|
||||
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/zclconf/go-cty v1.8.0 h1:s4AvqaeQzJIu3ndv4gVIhplVD0krU+bgrcLSVUnaWuA=
|
||||
@@ -559,8 +542,8 @@ golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
||||
golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
|
||||
golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
|
||||
golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
|
||||
golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20220428152302-39d4317da171/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE=
|
||||
golang.org/x/exp v0.0.0-20240823005443-9b4947da3948 h1:kx6Ds3MlpiUHKj7syVnbp57++8WpuKPcR5yjLBjvLEA=
|
||||
@@ -601,8 +584,8 @@ golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
|
||||
golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY=
|
||||
golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E=
|
||||
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
|
||||
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -618,8 +601,8 @@ golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610=
|
||||
golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
|
||||
golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@@ -647,8 +630,8 @@ golang.org/x/sys v0.13.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/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
|
||||
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
||||
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
|
||||
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=
|
||||
@@ -672,8 +655,8 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||
golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
|
||||
golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
|
||||
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
|
||||
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
|
||||
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-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
@@ -688,10 +671,6 @@ 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.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
||||
golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24=
|
||||
golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ=
|
||||
golang.org/x/tools v0.32.0 h1:Q7N1vhpkQv7ybVzLFtTjvQya2ewbwNDZzUgfXGqtMWU=
|
||||
golang.org/x/tools v0.32.0/go.mod h1:ZxrU41P/wAbZD8EDa6dDCa6XfpkhJ7HFMjHJXfBDu8s=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io"
|
||||
"log"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"net/http/cookiejar"
|
||||
@@ -93,6 +94,28 @@ func (client *Client) get(endpoint string, opts map[string]string) (*http.Respon
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (cleint *Client) postJson(endpoint string, body any) (*http.Response, error) {
|
||||
var buff bytes.Buffer
|
||||
buff.WriteString("json=")
|
||||
d, err := json.Marshal(body)
|
||||
if err!= nil {
|
||||
return nil, err
|
||||
}
|
||||
buff.Write(d)
|
||||
log.Println(buff.String())
|
||||
req, err := http.NewRequest("POST", cleint.URL+endpoint, &buff)
|
||||
if err!= nil {
|
||||
return nil, err
|
||||
}
|
||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
req.Header.Set("User-Agent", "go-qbittorrent v0.1")
|
||||
resp, err := cleint.http.Do(req)
|
||||
if err!= nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// post will perform a POST request with no content-type specified
|
||||
func (client *Client) post(endpoint string, opts map[string]string) (*http.Response, error) {
|
||||
// add optional parameters that the user wants
|
||||
@@ -315,8 +338,9 @@ func (client *Client) Preferences() (prefs Preferences, err error) {
|
||||
}
|
||||
|
||||
// SetPreferences of the qbittorrent client
|
||||
func (client *Client) SetPreferences() (prefsSet bool, err error) {
|
||||
resp, err := client.post("api/v2/app/setPreferences", nil)
|
||||
func (client *Client) SetPreferences(m map[string]any) (prefsSet bool, err error) {
|
||||
|
||||
resp, err := client.postJson("api/v2/app/setPreferences", m)
|
||||
return (resp.Status == "200 OK"), err
|
||||
}
|
||||
|
||||
|
||||
31
pkg/nat/cmd/main.go
Normal file
31
pkg/nat/cmd/main.go
Normal file
@@ -0,0 +1,31 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"net"
|
||||
"polaris/log"
|
||||
"polaris/pkg/nat"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// This is a placeholder for the main function.
|
||||
// The actual implementation will depend on the specific requirements of the application.
|
||||
src, err := net.Listen("tcp", ":8080")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
for {
|
||||
conn, err := src.Accept()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
log.Infof("new connection: %+v", conn)
|
||||
dest, err := net.Dial("tcp", "10.0.0.8:8080")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
go nat.ReverseProxy(conn, dest)
|
||||
}
|
||||
select {}
|
||||
}
|
||||
67
pkg/nat/reverse_proxy.go
Normal file
67
pkg/nat/reverse_proxy.go
Normal file
@@ -0,0 +1,67 @@
|
||||
package nat
|
||||
|
||||
import (
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
)
|
||||
|
||||
func ReverseProxy(sourceConn net.Conn, targetConn net.Conn) {
|
||||
serverClosed := make(chan struct{}, 1)
|
||||
clientClosed := make(chan struct{}, 1)
|
||||
|
||||
go broker(sourceConn, targetConn, clientClosed)
|
||||
go broker(targetConn, sourceConn, serverClosed)
|
||||
|
||||
// wait for one half of the proxy to exit, then trigger a shutdown of the
|
||||
// other half by calling CloseRead(). This will break the read loop in the
|
||||
// broker and allow us to fully close the connection cleanly without a
|
||||
// "use of closed network connection" error.
|
||||
var waitFor chan struct{}
|
||||
select {
|
||||
case <-clientClosed:
|
||||
// the client closed first and any more packets from the server aren't
|
||||
// useful, so we can optionally SetLinger(0) here to recycle the port
|
||||
// faster.
|
||||
waitFor = serverClosed
|
||||
case <-serverClosed:
|
||||
waitFor = clientClosed
|
||||
}
|
||||
|
||||
// Wait for the other connection to close.
|
||||
// This "waitFor" pattern isn't required, but gives us a way to track the
|
||||
// connection and ensure all copies terminate correctly; we can trigger
|
||||
// stats on entry and deferred exit of this function.
|
||||
<-waitFor
|
||||
}
|
||||
|
||||
func pipe(src net.Conn, dest net.Conn) {
|
||||
errChan := make(chan error, 1)
|
||||
go func() {
|
||||
_, err := io.Copy(src, dest)
|
||||
errChan <- err
|
||||
}()
|
||||
go func() {
|
||||
_, err := io.Copy(dest, src)
|
||||
errChan <- err
|
||||
}()
|
||||
<-errChan
|
||||
}
|
||||
|
||||
// This does the actual data transfer.
|
||||
// The broker only closes the Read side.
|
||||
func broker(dst, src net.Conn, srcClosed chan struct{}) {
|
||||
// We can handle errors in a finer-grained manner by inlining io.Copy (it's
|
||||
// simple, and we drop the ReaderFrom or WriterTo checks for
|
||||
// net.Conn->net.Conn transfers, which aren't needed). This would also let
|
||||
// us adjust buffersize.
|
||||
_, err := io.Copy(dst, src)
|
||||
|
||||
if err != nil {
|
||||
log.Printf("Copy error: %s", err)
|
||||
}
|
||||
if err := src.Close(); err != nil {
|
||||
log.Printf("Close error: %s", err)
|
||||
}
|
||||
srcClosed <- struct{}{}
|
||||
}
|
||||
169
pkg/nat/stun.go
Normal file
169
pkg/nat/stun.go
Normal file
@@ -0,0 +1,169 @@
|
||||
package nat
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"polaris/log"
|
||||
|
||||
"github.com/pion/stun/v3"
|
||||
)
|
||||
|
||||
func getNatIpAndPort() (*stun.XORMappedAddress, error) {
|
||||
|
||||
var xorAddr stun.XORMappedAddress
|
||||
|
||||
for _, server := range getStunServers() {
|
||||
log.Infof("try to connect to stun server: %s", server)
|
||||
u, err := stun.ParseURI("stun:" + server)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
// Creating a "connection" to STUN server.
|
||||
c, err := stun.DialURI(u, &stun.DialConfig{})
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
// Building binding request with random transaction id.
|
||||
message := stun.MustBuild(stun.TransactionID, stun.BindingRequest)
|
||||
// Sending request to STUN server, waiting for response message.
|
||||
var err1 error
|
||||
if err := c.Do(message, func(res stun.Event) {
|
||||
if res.Error != nil {
|
||||
err1 = res.Error
|
||||
return
|
||||
}
|
||||
log.Infof("stun server %s response: %v", server, res.Message.String())
|
||||
// Decoding XOR-MAPPED-ADDRESS attribute from message.
|
||||
|
||||
if err := xorAddr.GetFrom(res.Message); err != nil {
|
||||
err1 = err
|
||||
return
|
||||
}
|
||||
fmt.Println("your IP is", xorAddr.IP)
|
||||
fmt.Println("your port is", xorAddr.Port)
|
||||
}); err != nil {
|
||||
log.Warnf("stun server %s error: %v", server, err)
|
||||
continue
|
||||
}
|
||||
if err1 != nil {
|
||||
log.Warnf("stun server %s error: %v", server, err1)
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
return &xorAddr, nil
|
||||
}
|
||||
|
||||
func getStunServers() []string {
|
||||
var servers []string
|
||||
for _, line := range strings.Split(strings.TrimSpace(stunServers1), "\n") {
|
||||
line = strings.TrimSpace(line)
|
||||
if line == "" {
|
||||
continue
|
||||
}
|
||||
servers = append(servers, line)
|
||||
}
|
||||
return servers
|
||||
}
|
||||
|
||||
// https://github.com/heiher/natmap/issues/18
|
||||
const stunServers1 = `
|
||||
stun.miwifi.com:3478
|
||||
stun.chat.bilibili.com:3478
|
||||
stun.cloudflare.com:3478
|
||||
turn.cloudflare.com:3478
|
||||
fwa.lifesizecloud.com:3478
|
||||
`
|
||||
|
||||
// https://github.com/pradt2/always-online-stun
|
||||
const stunServers = `
|
||||
stun.miwifi.com:3478
|
||||
stun.ukh.de:3478
|
||||
stun.kanojo.de:3478
|
||||
stun.m-online.net:3478
|
||||
stun.nextcloud.com:3478
|
||||
stun.voztovoice.org:3478
|
||||
stun.oncloud7.ch:3478
|
||||
stun.antisip.com:3478
|
||||
stun.bitburger.de:3478
|
||||
stun.acronis.com:3478
|
||||
stun.signalwire.com:3478
|
||||
stun.sonetel.net:3478
|
||||
stun.poetamatusel.org:3478
|
||||
stun.avigora.fr:3478
|
||||
stun.diallog.com:3478
|
||||
stun.nanocosmos.de:3478
|
||||
stun.romaaeterna.nl:3478
|
||||
stun.heeds.eu:3478
|
||||
stun.freeswitch.org:3478
|
||||
stun.engineeredarts.co.uk:3478
|
||||
stun.root-1.de:3478
|
||||
stun.healthtap.com:3478
|
||||
stun.allflac.com:3478
|
||||
stun.vavadating.com:3478
|
||||
stun.godatenow.com:3478
|
||||
stun.mixvoip.com:3478
|
||||
stun.sip.us:3478
|
||||
stun.sipthor.net:3478
|
||||
stun.stochastix.de:3478
|
||||
stun.kaseya.com:3478
|
||||
stun.files.fm:3478
|
||||
stun.meetwife.com:3478
|
||||
stun.myspeciality.com:3478
|
||||
stun.3wayint.com:3478
|
||||
stun.voip.blackberry.com:3478
|
||||
stun.axialys.net:3478
|
||||
stun.bridesbay.com:3478
|
||||
stun.threema.ch:3478
|
||||
stun.siptrunk.com:3478
|
||||
stun.ncic.com:3478
|
||||
stun.1cbit.ru:3478
|
||||
stun.ttmath.org:3478
|
||||
stun.yesdates.com:3478
|
||||
stun.sonetel.com:3478
|
||||
stun.peethultra.be:3478
|
||||
stun.pure-ip.com:3478
|
||||
stun.business-isp.nl:3478
|
||||
stun.ringostat.com:3478
|
||||
stun.imp.ch:3478
|
||||
stun.cope.es:3478
|
||||
stun.baltmannsweiler.de:3478
|
||||
stun.lovense.com:3478
|
||||
stun.frozenmountain.com:3478
|
||||
stun.linuxtrent.it:3478
|
||||
stun.thinkrosystem.com:3478
|
||||
stun.3deluxe.de:3478
|
||||
stun.skydrone.aero:3478
|
||||
stun.ru-brides.com:3478
|
||||
stun.streamnow.ch:3478
|
||||
stun.atagverwarming.nl:3478
|
||||
stun.ipfire.org:3478
|
||||
stun.fmo.de:3478
|
||||
stun.moonlight-stream.org:3478
|
||||
stun.f.haeder.net:3478
|
||||
stun.nextcloud.com:443
|
||||
stun.finsterwalder.com:3478
|
||||
stun.voipia.net:3478
|
||||
stun.zepter.ru:3478
|
||||
stun.sipnet.net:3478
|
||||
stun.hot-chilli.net:3478
|
||||
stun.zentauron.de:3478
|
||||
stun.geesthacht.de:3478
|
||||
stun.annatel.net:3478
|
||||
stun.flashdance.cx:3478
|
||||
stun.voipgate.com:3478
|
||||
stun.genymotion.com:3478
|
||||
stun.graftlab.com:3478
|
||||
stun.fitauto.ru:3478
|
||||
stun.telnyx.com:3478
|
||||
stun.verbo.be:3478
|
||||
stun.dcalling.de:3478
|
||||
stun.lleida.net:3478
|
||||
stun.romancecompass.com:3478
|
||||
stun.siplogin.de:3478
|
||||
stun.bethesda.net:3478
|
||||
stun.alpirsbacher.de:3478
|
||||
stun.uabrides.com:3478
|
||||
stun.technosens.fr:3478
|
||||
stun.radiojar.com:3478
|
||||
`
|
||||
14
pkg/nat/stun_test.go
Normal file
14
pkg/nat/stun_test.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package nat
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestStun1(t *testing.T) {
|
||||
// s,err := getNatIpAndPort()
|
||||
// if err != nil {
|
||||
// t.Logf("get nat ip and port error: %v", err)
|
||||
// t.Fail()
|
||||
// }
|
||||
|
||||
//NatTraversal()
|
||||
t.Logf("nat ip: ")
|
||||
}
|
||||
197
pkg/nat/traversal.go
Normal file
197
pkg/nat/traversal.go
Normal file
@@ -0,0 +1,197 @@
|
||||
package nat
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/pion/stun/v3"
|
||||
)
|
||||
|
||||
const (
|
||||
udp = "udp4"
|
||||
pingMsg = "ping"
|
||||
pongMsg = "pong"
|
||||
timeoutMillis = 500
|
||||
)
|
||||
|
||||
type natTraversal struct {
|
||||
peerAddr *net.UDPAddr
|
||||
cancel chan struct{}
|
||||
port <-chan int
|
||||
}
|
||||
|
||||
func (s *natTraversal) Port() int {
|
||||
return <-s.port
|
||||
}
|
||||
|
||||
func (s *natTraversal) Cancel() {
|
||||
s.cancel <- struct{}{}
|
||||
}
|
||||
|
||||
func NatTraversal(targetAddr string) (*natTraversal, error) { //nolint:gocognit,cyclop
|
||||
|
||||
srvAddr, err := net.ResolveUDPAddr(udp, getStunServers()[0])
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to resolve server addr: %s", err)
|
||||
}
|
||||
|
||||
conn, err := net.ListenUDP(udp, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("listen: %w", err)
|
||||
}
|
||||
|
||||
log.Printf("Listening on %s", conn.LocalAddr())
|
||||
|
||||
peerAddr, err := net.ResolveUDPAddr(udp, targetAddr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("resolve peeraddr: %w", err)
|
||||
}
|
||||
err = sendBindingRequest(conn, srvAddr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("send binding request: %w", err)
|
||||
}
|
||||
nt := &natTraversal{
|
||||
peerAddr: peerAddr,
|
||||
cancel: make(chan struct{}),
|
||||
port: make(chan int),
|
||||
}
|
||||
go func() {
|
||||
err := doTraversal(conn, peerAddr, nt.cancel)
|
||||
if err != nil {
|
||||
log.Println("nat traversal error:", err)
|
||||
}
|
||||
}()
|
||||
return nt, nil
|
||||
|
||||
}
|
||||
|
||||
func doTraversal(conn *net.UDPConn, peerAddr *net.UDPAddr, quit <-chan struct{}) error {
|
||||
defer func() {
|
||||
_ = conn.Close()
|
||||
}()
|
||||
|
||||
var publicAddr stun.XORMappedAddress
|
||||
|
||||
messageChan := listen(conn)
|
||||
//var peerAddrChan <-chan string
|
||||
|
||||
keepalive := time.Tick(timeoutMillis * time.Millisecond)
|
||||
keepaliveMsg := pingMsg
|
||||
|
||||
gotPong := false
|
||||
sentPong := false
|
||||
|
||||
for {
|
||||
select {
|
||||
case message, ok := <-messageChan:
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
switch {
|
||||
case string(message) == pingMsg:
|
||||
keepaliveMsg = pongMsg
|
||||
|
||||
case string(message) == pongMsg:
|
||||
if !gotPong {
|
||||
log.Println("Received pong message.")
|
||||
}
|
||||
|
||||
// One client may skip sending ping if it receives
|
||||
// a ping message before knowning the peer address.
|
||||
keepaliveMsg = pongMsg
|
||||
|
||||
gotPong = true
|
||||
|
||||
case stun.IsMessage(message):
|
||||
m := new(stun.Message)
|
||||
m.Raw = message
|
||||
decErr := m.Decode()
|
||||
if decErr != nil {
|
||||
log.Println("decode:", decErr)
|
||||
|
||||
break
|
||||
}
|
||||
var xorAddr stun.XORMappedAddress
|
||||
if getErr := xorAddr.GetFrom(m); getErr != nil {
|
||||
log.Println("getFrom:", getErr)
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
if publicAddr.String() != xorAddr.String() {
|
||||
log.Printf("My public address: %s\n", xorAddr)
|
||||
publicAddr = xorAddr
|
||||
|
||||
//peerAddrChan = getPeerAddr()
|
||||
}
|
||||
|
||||
default:
|
||||
send(message, conn, peerAddr)
|
||||
}
|
||||
|
||||
case <-keepalive:
|
||||
// Keep NAT binding alive using STUN server or the peer once it's known
|
||||
err := sendStr(keepaliveMsg, conn, peerAddr)
|
||||
if keepaliveMsg == pongMsg {
|
||||
sentPong = true
|
||||
}
|
||||
_ = sentPong
|
||||
|
||||
if err != nil {
|
||||
log.Panicln("keepalive:", err)
|
||||
}
|
||||
|
||||
case <-quit:
|
||||
_ = conn.Close()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func listen(conn *net.UDPConn) <-chan []byte {
|
||||
messages := make(chan []byte)
|
||||
go func() {
|
||||
for {
|
||||
buf := make([]byte, 10240)
|
||||
|
||||
n, _, err := conn.ReadFromUDP(buf)
|
||||
if err != nil {
|
||||
close(messages)
|
||||
|
||||
return
|
||||
}
|
||||
buf = buf[:n]
|
||||
|
||||
messages <- buf
|
||||
}
|
||||
}()
|
||||
|
||||
return messages
|
||||
}
|
||||
|
||||
func sendBindingRequest(conn *net.UDPConn, addr *net.UDPAddr) error {
|
||||
m := stun.MustBuild(stun.TransactionID, stun.BindingRequest)
|
||||
|
||||
err := send(m.Raw, conn, addr)
|
||||
if err != nil {
|
||||
return fmt.Errorf("binding: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func send(msg []byte, conn *net.UDPConn, addr *net.UDPAddr) error {
|
||||
_, err := conn.WriteToUDP(msg, addr)
|
||||
if err != nil {
|
||||
return fmt.Errorf("send: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func sendStr(msg string, conn *net.UDPConn, addr *net.UDPAddr) error {
|
||||
return send([]byte(msg), conn, addr)
|
||||
}
|
||||
@@ -61,6 +61,23 @@ func (c *Client) GetAll() ([]pkg.Torrent, error) {
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (c *Client) GetListenPort() (int, error) {
|
||||
pref, err := c.c.Preferences()
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "get preferences")
|
||||
}
|
||||
|
||||
return pref.ListenPort, nil
|
||||
}
|
||||
|
||||
func (c *Client) SetListenPort(port int) error {
|
||||
ok, err := c.c.SetPreferences(map[string]any{"listen_port": port})
|
||||
if !ok || err != nil {
|
||||
return errors.Wrap(err, "set preferences")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) Download(link, hash, dir string) (pkg.Torrent, error) {
|
||||
err := c.c.DownloadLinks([]string{link}, qbt.DownloadOptions{Savepath: &dir, Category: &c.category})
|
||||
if err != nil {
|
||||
|
||||
@@ -11,10 +11,17 @@ func Test1(t *testing.T) {
|
||||
log.Errorf("new client error: %v", err)
|
||||
t.Fail()
|
||||
}
|
||||
all, err := c.GetAll()
|
||||
for _, t := range all {
|
||||
name, _ := t.Name()
|
||||
log.Infof("torrent: %+v", name)
|
||||
log.Infof("new client success: %v", c)
|
||||
port, err := c.GetListenPort()
|
||||
if err != nil {
|
||||
log.Errorf("get listen port error: %v", err)
|
||||
t.Fail()
|
||||
} else {
|
||||
log.Infof("listen port: %d", port)
|
||||
err := c.SetListenPort(port + 1)
|
||||
if err!= nil {
|
||||
log.Errorf("set listen port error: %v", err)
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user