mirror of
https://git.mills.io/saltyim/saltyim.git
synced 2024-06-16 03:48:24 +00:00
![James Mills](/assets/img/avatar_default.png)
beeep was cuasing the PWA to crash on iPhone with: ``` [Error] Did not parse stylesheet at 'https://salty.mills.io/web/css/micons.woff2' because non CSS MIME types are not allowed in strict mode. [Log] registering app service worker (app.js, line 12) [Error] Failed to load resource: the server responded with a status of 404 () (material-components-web.min.css.map, line 0) [Log] 2022/04/01 08:13:09 connect() (wasm_exec.js, line 22) [Log] 2022/04/01 08:13:09 creating new client (wasm_exec.js, line 22) [Log] time="2022-04-01T08:13:09+10:00" level=debug msg="Looking up SRV record for _salty._tcp.mills.io" (wasm_exec.js, line 22) [Log] time="2022-04-01T08:13:09+10:00" level=debug msg="Using DNSOverHTTPResolver, looking up SRV _salty._tcp.mills.io" (wasm_exec.js, line 22) [Log] time="2022-04-01T08:13:09+10:00" level=debug msg="Discovered salty services salty.mills.io" (wasm_exec.js, line 22) [Log] time="2022-04-01T08:13:09+10:00" level=debug msg="map[Accept-Encoding:[br, gzip, deflate] Accept-Ranges:[bytes] Access-Control-Allow-Headers:[*] Access-Control-Allow-Origin:[*] Access-Control-Expose-Headers:[*] Content-Length:[151] Content-Type:[application/json] Date:[Thu, 31 Mar 2022 22:10:02 GMT] Last-Modified:[Mon, 21 Mar 2022 23:59:42 GMT] Vary:[Accept-Encoding, Cookie] X-Salty-Accept-Encoding:[br, gzip, deflate]]" (wasm_exec.js, line 22) [Log] time="2022-04-01T08:13:09+10:00" level=debug msg="Discovered endpoint: https://salty.mills.io/inbox/01FYQEP8FS9XBDYZV9ZNRY4ENS" (wasm_exec.js, line 22) [Log] time="2022-04-01T08:13:09+10:00" level=debug msg="Discovered capability: accept-encoding: br, gzip, deflate" (wasm_exec.js, line 22) [Log] time="2022-04-01T08:13:09+10:00" level=debug msg="Using identity []byte with public key kex1ekt5cru4vs42wnaxppkjn5pexmt2w6uxx9z2mz0fqeuc80e0g9gsggs8ah" (wasm_exec.js, line 22) [Log] time="2022-04-01T08:13:09+10:00" level=debug msg="Salty Addr is prologic@mills.io" (wasm_exec.js, line 22) [Log] time="2022-04-01T08:13:09+10:00" level=debug msg="Endpoint is https://salty.mills.io/inbox/01FYQEP8FS9XBDYZV9ZNRY4ENS" (wasm_exec.js, line 22) [Log] time="2022-04-01T08:13:09+10:00" level=debug msg="Looking up SRV record for _salty._tcp.mills.io" (wasm_exec.js, line 22) [Log] time="2022-04-01T08:13:09+10:00" level=debug msg="Using DNSOverHTTPResolver, looking up SRV _salty._tcp.mills.io" (wasm_exec.js, line 22) [Log] time="2022-04-01T08:13:09+10:00" level=debug msg="Connected to https://salty.mills.io/inbox/01FYQEP8FS9XBDYZV9ZNRY4ENS" (wasm_exec.js, line 22) [Log] fatal error: panic while printing panic value (wasm_exec.js, line 22) [Log] (wasm_exec.js, line 22) [Log] goroutine 17 [running]: (wasm_exec.js, line 22) [Log] runtime.throw({0x19ad82, 0x20}) (wasm_exec.js, line 22) [Log] /usr/local/go/src/runtime/panic.go:992 +0x7 fp=0x1079620 sp=0x10795f8 pc=0x12600007 (wasm_exec.js, line 22) [Log] runtime.preprintpanics.func1() (wasm_exec.js, line 22) [Log] /usr/local/go/src/runtime/panic.go:529 +0x5 fp=0x1079640 sp=0x1079620 pc=0x12550005 (wasm_exec.js, line 22) [Log] runtime.deferCallSave(0x1079718, 0x1db388) (wasm_exec.js, line 22) [Log] /usr/local/go/src/runtime/panic.go:750 +0xe fp=0x1079658 sp=0x1079640 pc=0x125c000e (wasm_exec.js, line 22) [Log] runtime.runOpenDeferFrame(0x12a0ea0, 0x103fb30) (wasm_exec.js, line 22) [Log] /usr/local/go/src/runtime/panic.go:723 +0x33 fp=0x10796a0 sp=0x1079658 pc=0x125b0033 (wasm_exec.js, line 22) [Log] panic({0xcc2e0, 0x12bb800}) (wasm_exec.js, line 22) [Log] /usr/local/go/src/runtime/panic.go:838 +0x29 fp=0x1079758 sp=0x10796a0 pc=0x125d0029 (wasm_exec.js, line 22) [Log] runtime.panicwrap() (wasm_exec.js, line 22) [Log] /usr/local/go/src/runtime/error.go:328 +0x1c fp=0x1079890 sp=0x1079758 pc=0x1090001c (wasm_exec.js, line 22) [Log] syscall/js.(*Error).Error(0x0) (wasm_exec.js, line 22) [Log] <autogenerated>:1 +0x5 fp=0x10798b8 sp=0x1079890 pc=0x178d0005 (wasm_exec.js, line 22) [Log] runtime.preprintpanics(0x1079988) (wasm_exec.js, line 22) [Log] /usr/local/go/src/runtime/panic.go:535 +0xa fp=0x1079910 sp=0x10798b8 pc=0x1256000a (wasm_exec.js, line 22) [Log] panic({0x15d200, 0x0}) (wasm_exec.js, line 22) [Log] /usr/local/go/src/runtime/panic.go:939 +0x53 fp=0x10799c8 sp=0x1079910 pc=0x125d0053 (wasm_exec.js, line 22) [Log] github.com/gen2brain/beeep.Notify.func1() (wasm_exec.js, line 22) [Log] /home/mattman/go/pkg/mod/github.com/prologic/beeep@v0.0.0-20220331052839-35525ae5ee34/notify_js.go:25 +0xb fp=0x10799f0 sp=0x10799c8 pc=0x42c5000b (wasm_exec.js, line 22) [Log] runtime.deferCallSave(0x1079ac8, 0x1079c10) (wasm_exec.js, line 22) [Log] /usr/local/go/src/runtime/panic.go:750 +0xe fp=0x1079a08 sp=0x10799f0 pc=0x125c000e (wasm_exec.js, line 22) [Log] runtime.runOpenDeferFrame(0x12a0ea0, 0x103fae0) (wasm_exec.js, line 22) [Log] /usr/local/go/src/runtime/panic.go:723 +0x33 fp=0x1079a50 sp=0x1079a08 pc=0x125b0033 (wasm_exec.js, line 22) [Log] panic({0xbc2a0, 0x1294ca8}) (wasm_exec.js, line 22) [Log] /usr/local/go/src/runtime/panic.go:838 +0x29 fp=0x1079b08 sp=0x1079a50 pc=0x125d0029 (wasm_exec.js, line 22) [Log] syscall/js.Value.Get({{}, 0x0, 0x0}, {0x18d181, 0xa}) (wasm_exec.js, line 22) [Log] /usr/local/go/src/syscall/js/js.go:288 +0xc fp=0x1079b48 sp=0x1079b08 pc=0x174e000c (wasm_exec.js, line 22) [Log] github.com/gen2brain/beeep.Notify({0x18bd62, 0x8}, {0x1976d0, 0x1c}, {0x0, 0x0}) (wasm_exec.js, line 22) [Log] /home/mattman/go/pkg/mod/github.com/prologic/beeep@v0.0.0-20220331052839-35525ae5ee34/notify_js.go:35 +0x8 fp=0x1079c78 sp=0x1079b48 pc=0x42c30008 (wasm_exec.js, line 22) [Log] github.com/gen2brain/beeep.Alert({0x18bd62, 0x8}, {0x1976d0, 0x1c}, {0x0, 0x0}) (wasm_exec.js, line 22) [Log] /home/mattman/go/pkg/mod/github.com/prologic/beeep@v0.0.0-20220331052839-35525ae5ee34/alert_js.go:8 +0x2 fp=0x1079cc0 sp=0x1079c78 pc=0x42bf0002 (wasm_exec.js, line 22) [Log] go.mills.io/saltyim.(*Client).processMessage(0x1296940, 0x1297640, {0x0, 0x0}, {0x0, 0x0}, {0x0, 0x0}) (wasm_exec.js, line 22) [Log] /home/mattman/golang/saltyim/client.go:147 +0x2 fp=0x1079e30 sp=0x1079cc0 pc=0x4f610002 (wasm_exec.js, line 22) [Log] go.mills.io/saltyim.(*Client).Read(0x1296940, {0x0, 0x0}, {0x0, 0x0}, {0x0, 0x0}) (wasm_exec.js, line 22) [Log] /home/mattman/golang/saltyim/client.go:314 +0x17 fp=0x1079ec0 sp=0x1079e30 pc=0x4f6a0017 (wasm_exec.js, line 22) [Log] go.mills.io/saltyim.(*Client).Drain.func1() (wasm_exec.js, line 22) [Log] /home/mattman/golang/saltyim/client.go:261 +0x5 fp=0x1079fe0 sp=0x1079ec0 pc=0x4f690005 (wasm_exec.js, line 22) [Log] runtime.goexit() (wasm_exec.js, line 22) [Log] /usr/local/go/src/runtime/asm_wasm.s:401 +0x1 fp=0x1079fe8 sp=0x1079fe0 pc=0x14480001 (wasm_exec.js, line 22) [Log] created by go.mills.io/saltyim.(*Client).Drain (wasm_exec.js, line 22) [Log] /home/mattman/golang/saltyim/client.go:259 +0x15 (wasm_exec.js, line 22) [Log] (wasm_exec.js, line 22) [Log] goroutine 1 [chan receive]: (wasm_exec.js, line 22) [Log] github.com/likexian/doh-go.(*DoH).fastECSQuery(0x103f9f0, {0x288ed0, 0x12af080}, {0x128dc80, 0x2, 0x2}, {0x107ccf0, 0x14}, {0x189fb6, 0x3}, ...) (wasm_exec.js, line 22) [Log] /home/mattman/go/pkg/mod/github.com/likexian/doh-go@v0.6.4/doh.go:225 +0x1a (wasm_exec.js, line 22) [Log] github.com/likexian/doh-go.(*DoH).ECSQuery(0x103f9f0, {0x288ed0, 0x12af080}, {0x107ccf0, 0x14}, {0x189fb6, 0x3}, {0x0, 0x0}) (wasm_exec.js, line 22) [Log] /home/mattman/go/pkg/mod/github.com/likexian/doh-go@v0.6.4/doh.go:181 +0xc (wasm_exec.js, line 22) [Log] github.com/likexian/doh-go.(*DoH).Query(...) (wasm_exec.js, line 22) [Log] /home/mattman/go/pkg/mod/github.com/likexian/doh-go@v0.6.4/doh.go:158 (wasm_exec.js, line 22) [Log] go.mills.io/saltyim.(*DNSOverHTTPResolver).LookupSRV(0xc09878, {0x18a96c, 0x5}, {0x18a0e5, 0x3}, {0x107cc51, 0x8}) (wasm_exec.js, line 22) [Log] /home/mattman/golang/saltyim/resolv.go:62 +0x13 (wasm_exec.js, line 22) [Log] go.mills.io/saltyim.(*Addr).Refresh(0x12aec00) (wasm_exec.js, line 22) [Log] /home/mattman/golang/saltyim/lookup.go:179 +0xd (wasm_exec.js, line 22) [Log] go.mills.io/saltyim.LookupAddr({0x107cc48, 0x11}) (wasm_exec.js, line 22) [Log] /home/mattman/golang/saltyim/lookup.go:246 +0x4 (wasm_exec.js, line 22) [Log] go.mills.io/saltyim.(*ProxyLookup).LookupAddr(0x12a3360, {0x107cc48, 0x11}) (wasm_exec.js, line 22) [Log] /home/mattman/golang/saltyim/lookup.go:271 +0x3 (wasm_exec.js, line 22) [Log] go.mills.io/saltyim.(*Client).getAddr(0x1296940, {0x107cc48, 0x11}) (wasm_exec.js, line 22) [Log] /home/mattman/golang/saltyim/client.go:124 +0x8 (wasm_exec.js, line 22) [Log] go.mills.io/saltyim.(*Client).Lookup(...) (wasm_exec.js, line 22) [Log] /home/mattman/golang/saltyim/client.go:345 (wasm_exec.js, line 22) [Log] go.mills.io/saltyim/internal/pwa/components.(*ChatMessage).Render(0x10b4c00) (wasm_exec.js, line 22) [Log] /home/mattman/golang/saltyim/internal/pwa/components/chatmessage.go:27 +0x13 (wasm_exec.js, line 22) [Log] github.com/maxence-charriere/go-app/v9/pkg/app.(*Compo).render(0x10b4c00) (wasm_exec.js, line 22) [Log] /home/mattman/go/pkg/mod/github.com/maxence-charriere/go-app/v9@v9.4.1/pkg/app/component.go:442 +0x6 (wasm_exec.js, line 22) [Log] github.com/maxence-charriere/go-app/v9/pkg/app.(*Compo).mount(0x10b4c00, {0x28cd38, 0x107fc20}) (wasm_exec.js, line 22) [Log] /home/mattman/go/pkg/mod/github.com/maxence-charriere/go-app/v9@v9.4.1/pkg/app/component.go:293 +0x22 (wasm_exec.js, line 22) [Log] github.com/maxence-charriere/go-app/v9/pkg/app.mount({0x28cd38, 0x107fc20}, {0x28e000, 0x10b4c00}) (wasm_exec.js, line 22) [Log] /home/mattman/go/pkg/mod/github.com/maxence-charriere/go-app/v9@v9.4.1/pkg/app/node.go:188 +0x5 (wasm_exec.js, line 22) [Log] github.com/maxence-charriere/go-app/v9/pkg/app.(*elem).replaceChildAt(0x128f220, 0x0, {0x28e000, 0x10b4c00}) (wasm_exec.js, line 22) [Log] /home/mattman/go/pkg/mod/github.com/maxence-charriere/go-app/v9@v9.4.1/pkg/app/element.go:238 +0x8 (wasm_exec.js, line 22) [Log] github.com/maxence-charriere/go-app/v9/pkg/app.(*elem).update(0x128f220, {0x28d300, 0x12bda40}) (wasm_exec.js, line 22) [Log] /home/mattman/go/pkg/mod/github.com/maxence-charriere/go-app/v9@v9.4.1/pkg/app/element.go:172 +0x3f (wasm_exec.js, line 22) [Log] github.com/maxence-charriere/go-app/v9/pkg/app.update({0x28d300, 0x128f220}, {0x28d300, 0x12bda40}) (wasm_exec.js, line 22) [Log] /home/mattman/go/pkg/mod/github.com/maxence-charriere/go-app/v9@v9.4.1/pkg/app/node.go:199 +0x8 (wasm_exec.js, line 22) [Log] github.com/maxence-charriere/go-app/v9/pkg/app.(*Compo).updateRoot(0x10b4880) (wasm_exec.js, line 22) [Log] /home/mattman/go/pkg/mod/github.com/maxence-charriere/go-app/v9@v9.4.1/pkg/app/component.go:386 +0x5 (wasm_exec.js, line 22) [Log] github.com/maxence-charriere/go-app/v9/pkg/app.(*engine).updateComponents(0x107fc20) (wasm_exec.js, line 22) [Log] /home/mattman/go/pkg/mod/github.com/maxence-charriere/go-app/v9@v9.4.1/pkg/app/engine.go:419 +0x18 (wasm_exec.js, line 22) [Log] github.com/maxence-charriere/go-app/v9/pkg/app.(*engine).start.func1() (wasm_exec.js, line 22) [Log] /home/mattman/go/pkg/mod/github.com/maxence-charriere/go-app/v9@v9.4.1/pkg/app/engine.go:347 +0x1c (wasm_exec.js, line 22) [Log] sync.(*Once).doSlow(0x107fc8c, 0x1271d18) (wasm_exec.js, line 22) [Log] /usr/local/go/src/sync/once.go:68 +0x9 (wasm_exec.js, line 22) [Log] sync.(*Once).Do(0x107fc8c, 0x1271d18) (wasm_exec.js, line 22) [Log] /usr/local/go/src/sync/once.go:59 +0x6 (wasm_exec.js, line 22) [Log] github.com/maxence-charriere/go-app/v9/pkg/app.(*engine).start(0x107fc20, {0x288e98, 0x101e040}) (wasm_exec.js, line 22) [Log] /home/mattman/go/pkg/mod/github.com/maxence-charriere/go-app/v9@v9.4.1/pkg/app/engine.go:323 +0x4 (wasm_exec.js, line 22) [Log] github.com/maxence-charriere/go-app/v9/pkg/app.RunWhenOnBrowser() (wasm_exec.js, line 22) [Log] /home/mattman/go/pkg/mod/github.com/maxence-charriere/go-app/v9@v9.4.1/pkg/app/app.go:152 +0x86 (wasm_exec.js, line 22) [Log] main.main() (wasm_exec.js, line 22) [Log] /home/mattman/golang/saltyim/internal/pwa/main.go:18 +0x2 (wasm_exec.js, line 22) [Log] (wasm_exec.js, line 22) [Log] goroutine 9 [select]: (wasm_exec.js, line 22) [Log] github.com/likexian/gokit/xcache/memory.(*Objects).gc(0x1260b80) (wasm_exec.js, line 22) [Log] /home/mattman/go/pkg/mod/github.com/likexian/gokit@v0.25.6/xcache/memory/memory.go:244 +0xc (wasm_exec.js, line 22) [Log] created by github.com/likexian/gokit/xcache/memory.New (wasm_exec.js, line 22) [Log] /home/mattman/go/pkg/mod/github.com/likexian/gokit@v0.25.6/xcache/memory/memory.go:76 +0x12 (wasm_exec.js, line 22) [Log] (wasm_exec.js, line 22) [Log] goroutine 15 [chan receive]: (wasm_exec.js, line 22) [Log] go.mills.io/saltyim/internal/pwa/components.(*SaltyChat).connect.func1() (wasm_exec.js, line 22) [Log] /home/mattman/golang/saltyim/internal/pwa/components/saltychat.go:116 +0xd (wasm_exec.js, line 22) [Log] github.com/maxence-charriere/go-app/v9/pkg/app.(*engine).Async.func1() (wasm_exec.js, line 22) [Log] /home/mattman/go/pkg/mod/github.com/maxence-charriere/go-app/v9@v9.4.1/pkg/app/engine.go:124 +0x4 (wasm_exec.js, line 22) [Log] created by github.com/maxence-charriere/go-app/v9/pkg/app.(*engine).Async (wasm_exec.js, line 22) [Log] /home/mattman/go/pkg/mod/github.com/maxence-charriere/go-app/v9@v9.4.1/pkg/app/engine.go:123 +0xb (wasm_exec.js, line 22) [Log] (wasm_exec.js, line 22) [Log] goroutine 20 [select]: (wasm_exec.js, line 22) [Log] github.com/likexian/doh-go.Use.func1() (wasm_exec.js, line 22) [Log] /home/mattman/go/pkg/mod/github.com/likexian/doh-go@v0.6.4/doh.go:122 +0xa (wasm_exec.js, line 22) [Log] created by github.com/likexian/doh-go.Use (wasm_exec.js, line 22) [Log] /home/mattman/go/pkg/mod/github.com/likexian/doh-go@v0.6.4/doh.go:119 +0x14 (wasm_exec.js, line 22) [Log] (wasm_exec.js, line 22) [Log] goroutine 14 [waiting]: (wasm_exec.js, line 22) [Log] runtime.gopark(0x0, 0x0, 0x0, 0x0, 0x1) (wasm_exec.js, line 22) [Log] /usr/local/go/src/runtime/proc.go:361 +0x27 (wasm_exec.js, line 22) [Log] runtime.handleEvent() (wasm_exec.js, line 22) [Log] /usr/local/go/src/runtime/lock_js.go:249 +0x1b (wasm_exec.js, line 22) [Log] runtime.goexit() (wasm_exec.js, line 22) [Log] /usr/local/go/src/runtime/asm_wasm.s:401 +0x1 (wasm_exec.js, line 22) [Log] (wasm_exec.js, line 22) [Log] goroutine 18 [select]: (wasm_exec.js, line 22) [Log] go.mills.io/saltyim.(*Client).Drain.func2() (wasm_exec.js, line 22) [Log] /home/mattman/golang/saltyim/client.go:284 +0x9 (wasm_exec.js, line 22) [Log] created by go.mills.io/saltyim.(*Client).Drain (wasm_exec.js, line 22) [Log] /home/mattman/golang/saltyim/client.go:281 +0x2c (wasm_exec.js, line 22) [Log] (wasm_exec.js, line 22) [Log] goroutine 19 [select]: (wasm_exec.js, line 22) [Log] nhooyr.io/websocket.dial({0x288e98, 0x101e040}, {0x1085740, 0x35}, 0x0) (wasm_exec.js, line 22) [Log] /home/mattman/go/pkg/mod/nhooyr.io/websocket@v1.8.7/ws_js.go:278 +0x1e (wasm_exec.js, line 22) [Log] nhooyr.io/websocket.Dial({0x288e98, 0x101e040}, {0x1085740, 0x35}, 0x0) (wasm_exec.js, line 22) [Log] /home/mattman/go/pkg/mod/nhooyr.io/websocket@v1.8.7/ws_js.go:247 +0x2 (wasm_exec.js, line 22) [Log] git.mills.io/prologic/msgbus/client.(*Subscriber).connect(0x12aed80) (wasm_exec.js, line 22) [Log] /home/mattman/go/pkg/mod/git.mills.io/prologic/msgbus@v0.1.13-0.20220329220338-7181b6df1bd6/client/client.go:212 +0x12 (wasm_exec.js, line 22) [Log] created by git.mills.io/prologic/msgbus/client.(*Subscriber).Start (wasm_exec.js, line 22) [Log] /home/mattman/go/pkg/mod/git.mills.io/prologic/msgbus@v0.1.13-0.20220329220338-7181b6df1bd6/client/client.go:247 +0x7 (wasm_exec.js, line 22) [Log] (wasm_exec.js, line 22) [Log] goroutine 21 [select]: (wasm_exec.js, line 22) [Log] net/http.(*Transport).RoundTrip(0x1282dc0, 0x10b0d00) (wasm_exec.js, line 22) [Log] /usr/local/go/src/net/http/roundtrip_js.go:193 +0x8e (wasm_exec.js, line 22) [Log] net/http.send(0x10b0d00, {0x2857b8, 0x1282dc0}, {0x0, 0x0, 0x0}) (wasm_exec.js, line 22) [Log] /usr/local/go/src/net/http/client.go:252 +0x88 (wasm_exec.js, line 22) [Log] net/http.(*Client).send(0x12c0ba0, 0x10b0d00, {0x0, 0x0, 0x0}) (wasm_exec.js, line 22) [Log] /usr/local/go/src/net/http/client.go:176 +0x11 (wasm_exec.js, line 22) [Log] net/http.(*Client).do(0x12c0ba0, 0x10b0d00) (wasm_exec.js, line 22) [Log] /usr/local/go/src/net/http/client.go:725 +0xc5 (wasm_exec.js, line 22) [Log] net/http.(*Client).Do(...) (wasm_exec.js, line 22) [Log] /usr/local/go/src/net/http/client.go:593 (wasm_exec.js, line 22) [Log] github.com/likexian/gokit/xhttp.(*Request).Do(0x10b4e00, {0x288e60, 0x12975c0}, {0x189f62, 0x3}, {0x19dac6, 0x24}, {0x1047eb0, 0x2, 0x2}) (wasm_exec.js, line 22) [Log] /home/mattman/go/pkg/mod/github.com/likexian/gokit@v0.25.6/xhttp/xhttp.go:685 +0x1d5 (wasm_exec.js, line 22) [Log] github.com/likexian/gokit/xhttp.(*Request).Get(...) (wasm_exec.js, line 22) [Log] /home/mattman/go/pkg/mod/github.com/likexian/gokit@v0.25.6/xhttp/xhttp.go:285 (wasm_exec.js, line 22) [Log] github.com/likexian/doh-go/provider/cloudflare.(*Provider).ECSQuery(0x12ad728, {0x288e60, 0x12975c0}, {0x107ccf0, 0x14}, {0x189fb6, 0x3}, {0x0, 0x0}) (wasm_exec.js, line 22) [Log] /home/mattman/go/pkg/mod/github.com/likexian/doh-go@v0.6.4/provider/cloudflare/cloudflare.go:110 +0x30 (wasm_exec.js, line 22) [Log] github.com/likexian/doh-go.(*DoH).fastECSQuery.func1(0x0, {0x2881f8, 0x12ad728}) (wasm_exec.js, line 22) [Log] /home/mattman/go/pkg/mod/github.com/likexian/doh-go@v0.6.4/doh.go:201 +0x4 (wasm_exec.js, line 22) [Log] created by github.com/likexian/doh-go.(*DoH).fastECSQuery (wasm_exec.js, line 22) [Log] /home/mattman/go/pkg/mod/github.com/likexian/doh-go@v0.6.4/doh.go:200 +0x5e (wasm_exec.js, line 22) [Log] (wasm_exec.js, line 22) [Log] goroutine 23 [chan receive (nil chan)]: (wasm_exec.js, line 22) [Log] go.mills.io/saltyim.(*Client).Subscribe.func1() (wasm_exec.js, line 22) [Log] /home/mattman/golang/saltyim/client.go:333 +0x5 (wasm_exec.js, line 22) [Log] created by go.mills.io/saltyim.(*Client).Subscribe (wasm_exec.js, line 22) [Log] /home/mattman/golang/saltyim/client.go:332 +0x26 (wasm_exec.js, line 22) [Warning] exit code: – 2 (wasm_exec.js, line 101) [Error] Error: Go program has already exited _resume (wasm_exec.js:536) (anonymous function) (wasm_exec.js:549) [Error] Unhandled Promise Rejection: Error: Go program has already exited _resume (wasm_exec.js:536) (anonymous function) (wasm_exec.js:549) promiseReactionJob ``` Which I have no fucking clue what's going on there :/ Co-authored-by: James Mills <prologic@shortcircuit.net.au> Reviewed-on: https://git.mills.io/saltyim/saltyim/pulls/112 Reviewed-by: xuu <xuu@noreply@mills.io> Co-authored-by: James Mills <james@mills.io> Co-committed-by: James Mills <james@mills.io>
392 lines
9.5 KiB
Go
392 lines
9.5 KiB
Go
package saltyim
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"crypto/sha256"
|
|
"errors"
|
|
"fmt"
|
|
"net/url"
|
|
"os"
|
|
"path"
|
|
"strings"
|
|
"time"
|
|
|
|
"git.mills.io/prologic/msgbus"
|
|
msgbus_client "git.mills.io/prologic/msgbus/client"
|
|
"github.com/avast/retry-go"
|
|
"github.com/keys-pub/keys"
|
|
log "github.com/sirupsen/logrus"
|
|
|
|
"go.mills.io/salty"
|
|
"go.mills.io/saltyim/internal/exec"
|
|
)
|
|
|
|
const (
|
|
DefaultEnvPath = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
|
ServiceUser = "salty"
|
|
)
|
|
|
|
var (
|
|
ErrNoMessages = errors.New("error: no messages found")
|
|
ErrClientNotConnected = errors.New("error: client not connected")
|
|
)
|
|
|
|
type addrCache map[string]*Addr
|
|
|
|
type Message struct {
|
|
Text string
|
|
Key *keys.EdX25519PublicKey
|
|
}
|
|
|
|
// TODO: Support shell quoting and escapes?
|
|
func parseExtraEnvs(extraenvs string) map[string]string {
|
|
env := make(map[string]string)
|
|
for _, extraenv := range strings.Split(extraenvs, " ") {
|
|
tokens := strings.SplitN(extraenv, "=", 2)
|
|
switch len(tokens) {
|
|
case 1:
|
|
env[tokens[0]] = ""
|
|
case 2:
|
|
env[tokens[0]] = tokens[1]
|
|
}
|
|
}
|
|
return env
|
|
}
|
|
|
|
// PackMessage formts an outoing message in the Message Format
|
|
// <timestamp>\t(<sender>) <message>
|
|
func PackMessage(me *Addr, msg string) []byte {
|
|
return []byte(
|
|
fmt.Sprint(
|
|
time.Now().UTC().Format(time.RFC3339), "\t",
|
|
me.Formatted(), "\t",
|
|
strings.TrimSpace(msg), "\n",
|
|
),
|
|
)
|
|
}
|
|
|
|
// Client is a Salty IM client that handles talking to a Salty IM Broker
|
|
// and Sedngina and Receiving messages to/from Salty IM Users.
|
|
type Client struct {
|
|
me *Addr
|
|
id *Identity
|
|
key *keys.EdX25519Key
|
|
cache addrCache
|
|
|
|
lookup Lookuper
|
|
send Sender
|
|
}
|
|
|
|
// NewClient reeturns a new Salty IM client for sending and receiving
|
|
// encrypted messages to other Salty IM users as well as decrypting
|
|
// and displaying messages of the user's own inbox.
|
|
func NewClient(me *Addr, options ...IdentityOption) (*Client, error) {
|
|
id, err := GetIdentity(options...)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("error opening identity %s: %w", id.Source(), err)
|
|
}
|
|
if me == nil || me.IsZero() {
|
|
me = id.addr
|
|
}
|
|
|
|
if me == nil || me.IsZero() {
|
|
return nil, fmt.Errorf("unable to find your user addressn in %s", id.Source())
|
|
}
|
|
|
|
if err := me.Refresh(); err != nil {
|
|
log.WithError(err).Warn("error looking up user endpoint")
|
|
}
|
|
|
|
log.Debugf("Using identity %s with public key %s", id.Source(), id.key)
|
|
log.Debugf("Salty Addr is %s", me)
|
|
log.Debugf("Endpoint is %s", me.Endpoint())
|
|
|
|
return &Client{
|
|
me: me,
|
|
id: id,
|
|
key: id.key,
|
|
|
|
cache: make(addrCache),
|
|
|
|
lookup: &DirectLookup{},
|
|
send: &DirectSend{},
|
|
}, nil
|
|
}
|
|
|
|
func (cli *Client) getAddr(user string) (*Addr, error) {
|
|
addr, ok := cli.cache[user]
|
|
if ok {
|
|
return addr, nil
|
|
}
|
|
|
|
addr, err := cli.lookup.LookupAddr(user)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("error: failed to lookup user %s: %w", user, err)
|
|
}
|
|
|
|
cli.cache[user] = addr
|
|
|
|
return addr, nil
|
|
}
|
|
|
|
func (cli *Client) processMessage(msg *msgbus.Message, extraenvs, prehook, posthook string) (Message, error) {
|
|
var data []byte
|
|
|
|
defer func() {
|
|
if posthook != "" {
|
|
out, err := exec.RunCmd(exec.DefaultRunCmdTimeout, cli.Env(extraenvs), posthook, bytes.NewBuffer(data))
|
|
if err != nil {
|
|
log.WithError(err).Debugf("error running post-hook %s", posthook)
|
|
}
|
|
log.Debugf("post-hook: %q", out)
|
|
}
|
|
}()
|
|
|
|
if prehook != "" {
|
|
out, err := exec.RunCmd(exec.DefaultRunCmdTimeout, cli.Env(extraenvs), prehook, bytes.NewBuffer(msg.Payload))
|
|
if err != nil {
|
|
log.WithError(err).Debugf("error running pre-hook %s", prehook)
|
|
}
|
|
log.Debugf("pre-hook: %q", out)
|
|
}
|
|
|
|
unencrypted, senderKey, err := salty.Decrypt(cli.key, msg.Payload)
|
|
if err != nil {
|
|
return Message{}, fmt.Errorf("error decrypting message: %w", err)
|
|
}
|
|
data = unencrypted[:]
|
|
|
|
return Message{Text: string(data), Key: senderKey}, nil
|
|
}
|
|
|
|
func (cli *Client) messageHandler(extraenvs, prehook, posthook string, msgs chan Message) msgbus.HandlerFunc {
|
|
return func(msg *msgbus.Message) error {
|
|
message, err := cli.processMessage(msg, extraenvs, prehook, posthook)
|
|
if err != nil {
|
|
return fmt.Errorf("error processing message: %w", err)
|
|
}
|
|
|
|
msgs <- message
|
|
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func (cli *Client) Me() *Addr { return cli.me }
|
|
func (cli *Client) Key() *keys.EdX25519PublicKey { return cli.key.PublicKey() }
|
|
|
|
func (cli *Client) Env(extraenvs string) []string {
|
|
Path := DefaultEnvPath
|
|
GoPath := os.Getenv("GOPATH")
|
|
if GoPath != "" {
|
|
Path = fmt.Sprintf("%s/bin:%s", GoPath, Path)
|
|
}
|
|
|
|
env := []string{
|
|
fmt.Sprintf("PATH=%s", Path),
|
|
fmt.Sprintf("PWD=%s", os.Getenv("PWD")),
|
|
fmt.Sprintf("HOME=%s", os.Getenv("HOME")),
|
|
|
|
fmt.Sprintf("SALTY_USER=%s", cli.me.String()),
|
|
fmt.Sprintf("SALTY_IDENTITY=%s", cli.id.Source()),
|
|
}
|
|
|
|
for key, val := range parseExtraEnvs(extraenvs) {
|
|
log.Debugf("key: %q", key)
|
|
log.Debugf("val: %q", val)
|
|
val = os.ExpandEnv(val)
|
|
if val == "" {
|
|
val = os.Getenv(key)
|
|
}
|
|
if val != "" {
|
|
env = append(env, fmt.Sprintf("%s=%s", key, val))
|
|
}
|
|
}
|
|
|
|
log.Debugf("env: #%v", env)
|
|
|
|
return env
|
|
}
|
|
|
|
func (cli *Client) Outbox() *url.URL {
|
|
ep := cli.me.Endpoint()
|
|
ep.Path = path.Join(
|
|
path.Dir(ep.Path),
|
|
fmt.Sprintf("%x", sha256.Sum256(cli.me.key.Private())),
|
|
)
|
|
return ep
|
|
}
|
|
|
|
func (cli *Client) OutboxAddr() *Addr {
|
|
return &Addr{
|
|
endpoint: cli.Outbox(),
|
|
key: cli.me.key,
|
|
}
|
|
}
|
|
|
|
func (cli *Client) String() string {
|
|
b := &bytes.Buffer{}
|
|
fmt.Fprintln(b, "Me: ", cli.me)
|
|
fmt.Fprintln(b, "Endpoint: ", cli.me.Endpoint())
|
|
fmt.Fprintln(b, "Outbox: ", cli.Outbox())
|
|
fmt.Fprintln(b, "Key: ", cli.key)
|
|
return b.String()
|
|
}
|
|
|
|
// SetLookup sets the internal lookup interface to use (Lookuper) for looking
|
|
// up Salty Addresses. By default the DirectLookup implementation is used.
|
|
func (cli *Client) SetLookup(lookup Lookuper) {
|
|
cli.lookup = lookup
|
|
}
|
|
|
|
// SetSend sets the internal send interface to use (Sender) for sending
|
|
// messages to endpoints. By default the DirectSend implementation is used.
|
|
func (cli *Client) SetSend(send Sender) {
|
|
cli.send = send
|
|
}
|
|
|
|
// Drain drains this user's inbox by simulteneiously reading until empty anda
|
|
// subscribing to the inbox for new messages.
|
|
func (cli *Client) Drain(ctx context.Context, extraenvs, prehook, posthook string) chan Message {
|
|
msgs := make(chan Message)
|
|
|
|
go func() {
|
|
for {
|
|
msg, err := cli.Read(extraenvs, prehook, posthook)
|
|
if err != nil {
|
|
log.Debugf("err: #%v", err)
|
|
switch err {
|
|
case ErrNoMessages:
|
|
log.Debug("no more messages, existing readloop...")
|
|
return
|
|
case ErrClientNotConnected:
|
|
log.Debug("client not connected, existing readloop...")
|
|
return
|
|
default:
|
|
log.WithError(err).Warn("error reading inbox")
|
|
}
|
|
} else {
|
|
msgs <- msg
|
|
}
|
|
time.Sleep(time.Millisecond * 100)
|
|
}
|
|
}()
|
|
|
|
go func() {
|
|
msgCh := cli.Subscribe(ctx, extraenvs, prehook, posthook)
|
|
for {
|
|
select {
|
|
case msg := <-msgCh:
|
|
msgs <- msg
|
|
case <-ctx.Done():
|
|
close(msgs)
|
|
return
|
|
}
|
|
}
|
|
}()
|
|
|
|
return msgs
|
|
}
|
|
|
|
// Read reads a single message from this user's inbox
|
|
func (cli *Client) Read(extraenvs, prehook, posthook string) (Message, error) {
|
|
if cli.me.Endpoint() == nil {
|
|
return Message{}, ErrClientNotConnected
|
|
}
|
|
|
|
uri, inbox := SplitInbox(cli.me.Endpoint().String())
|
|
bus := msgbus_client.NewClient(uri, nil)
|
|
|
|
msg, err := bus.Pull(inbox)
|
|
if err != nil {
|
|
return Message{}, fmt.Errorf("error reading inbox: %w", err)
|
|
}
|
|
if msg == nil {
|
|
return Message{}, ErrNoMessages
|
|
}
|
|
|
|
return cli.processMessage(msg, extraenvs, prehook, posthook)
|
|
}
|
|
|
|
// Subscribe subscribers to this user's inbox for new messages
|
|
func (cli *Client) Subscribe(ctx context.Context, extraenvs, prehook, posthook string) chan Message {
|
|
if cli.me.Endpoint() == nil {
|
|
return nil
|
|
}
|
|
|
|
uri, inbox := SplitInbox(cli.me.Endpoint().String())
|
|
bus := msgbus_client.NewClient(uri, nil)
|
|
|
|
msgs := make(chan Message)
|
|
s := bus.Subscribe(inbox, cli.messageHandler(extraenvs, prehook, posthook, msgs))
|
|
s.Start()
|
|
|
|
log.Debugf("Connected to %s/%s", uri, inbox)
|
|
|
|
go func() {
|
|
<-ctx.Done()
|
|
s.Stop()
|
|
close(msgs)
|
|
}()
|
|
|
|
return msgs
|
|
}
|
|
|
|
// Lookup performs a lookup for a user's address and config
|
|
// If the user has an address already cached, the cached addr
|
|
// is returned, otherwise a full lookup is done.
|
|
func (cli *Client) Lookup(user string) (*Addr, error) {
|
|
return cli.getAddr(user)
|
|
}
|
|
|
|
// Send sends an encrypted message to the specified user
|
|
func (cli *Client) Send(user, msg string) error {
|
|
addr, err := cli.getAddr(user)
|
|
if err != nil {
|
|
return fmt.Errorf("error looking up user %s: %w", user, err)
|
|
}
|
|
|
|
err = cli.SendToAddr(addr, msg)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return cli.SendToAddr(cli.OutboxAddr(), msg)
|
|
}
|
|
|
|
func (cli *Client) SendToAddr(addr *Addr, msg string) error {
|
|
b, err := salty.Encrypt(cli.key, PackMessage(cli.me, msg), []string{addr.key.ID().String()})
|
|
if err != nil {
|
|
return fmt.Errorf("error encrypting message to %s: %w", addr, err)
|
|
}
|
|
|
|
if err := cli.send.Send(cli.key, addr.Endpoint().String(), string(b), addr.Cap()); err != nil {
|
|
return fmt.Errorf("error sending message to %s: %w", addr, err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Register sends a registration request to the service user of a Salty Broker
|
|
func (cli *Client) Register() error {
|
|
svc, err := cli.lookup.LookupAddr(fmt.Sprintf("%s@%s", ServiceUser, cli.Me().Domain))
|
|
if err != nil {
|
|
return fmt.Errorf("error looking up service user on %s: %w", cli.Me().Domain, err)
|
|
}
|
|
|
|
if err := cli.SendToAddr(svc, "REGISTER"); err != nil {
|
|
return fmt.Errorf("error sending REGISTER to %s: %w", svc, err)
|
|
}
|
|
|
|
if err := retry.Do(
|
|
func() error {
|
|
return cli.Me().Refresh()
|
|
},
|
|
); err != nil {
|
|
return fmt.Errorf("error registrating account: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|