openvibers/openvibe.link Commits
Use Link audience and URLs for Connect shares (#137)
Changes
@@@ -5,8 +5,8 @@"wave": "T15","plan": "Plan track T15 (Bot complete) and ADR-043 (Bot: devices, pairing, control and safety); the computer plugin and the job worker serve OpenVibe.Actor and the Codes job runner (tracks T14/T17)","kind": "client",-- "version": "0.45.0",-- "release": "v0.45.0: sell a local model on the Exchange (`openvibe-node exchange serve`, #120); AI plugin 0.4.0, machine pools over llama.cpp RPC behind a private link, isolated with bubblewrap where Ubuntu restricts user namespaces (#121); Memory M5, `memory export` and `memory import` of the portable memory file (#122); `skills sync`, the skills and rules chosen in the Codes hub written into each coding tool's own folders (#123).",++ "version": "0.47.0",++ "release": "v0.47.0: `openvibe-node share` asks for the openvibe.link audience and prints share addresses on openvibe.link (`<label>--<user>.openvibe.link`; the openvibe.website address keeps working, #137); Link answers HO12 camera and location requests on the phone (#138).","runtime": "go 1.24 (one static binary per platform); plugins in Python 3; an ESP32 Arduino library","database": "none","deployed": false,@@@ -36,12 +36,12 @@ const shareUsage = `usage:openvibe-link share list the shares the service keeps upopenvibe-link share remove <PORT|KEY|ID|ADDRESS> stop keeping one up--Make a share at https://connect.openvibe.website. On its page, pick this computer under "Or serve it from one of your++Make a share at https://connect.openvibe.website; its address is https://<label>--<you>.openvibe.link. On its page, pick this computer under "Or serve it from one of yourcomputers" to serve it with --share and no key (the computer must be added on openvibe.bot/machines). Without --port,the Node serves the port the share's page names now, and keeps that one. The Node only ever connects to localhost onthe share's port; every visitor signs in with OpenVibe first.`--// connectNodeToken buys this machine's node token for OpenVibe Connect (audience openvibe.website). A machine++// connectNodeToken buys this machine's node token for OpenVibe Connect (audience openvibe.link). A machine// removed on OpenVibe stops its shares (connect.ErrStopped) instead of trying forever.func connectNodeToken(creds *credentials.Credentials) func(context.Context) (string, error) {ts := link.NewTokenSourceFor(creds, nil, "openvibe-node/"+version, link.ConnectAudience)@@@ -83,10 +83,10 @@ func TestSharesText(t *testing.T) {t.Fatalf("no shares: %q", got)}got := sharesText([]connect.Status{-- {ID: "shr_01K9ZZZZZZZZZZZZZZZZZZZZZZ", Port: 8790, Host: "bot--alex.openvibe.website", URL: "https://bot--alex.openvibe.website", Connected: true, Requests: 3},++ {ID: "shr_01K9ZZZZZZZZZZZZZZZZZZZZZZ", Port: 8790, Host: "bot--alex.openvibe.link", URL: "https://bot--alex.openvibe.link", Connected: true, Requests: 3},{Port: 9001, LastError: "dial: connection refused"},})-- for _, want := range []string{"Shares: 2 kept up", "localhost:8790", "https://bot--alex.openvibe.website", "connected, 3 requests", "localhost:9001", "not connected", "dial: connection refused"} {++ for _, want := range []string{"Shares: 2 kept up", "localhost:8790", "https://bot--alex.openvibe.link", "connected, 3 requests", "localhost:9001", "not connected", "dial: connection refused"} {if !strings.Contains(got, want) {t.Fatalf("status is missing %q:\n%s", want, got)}@@@ -1,5 +1,5 @@// Package connect keeps OpenVibe Connect shares up from the Node: each share is one port on this machine served at--// https://<label>--<user>.openvibe.website behind OpenVibe sign-in (OpenVibe.Connect, ADR-057, Website Connect v0).++// https://<label>--<user>.openvibe.link behind OpenVibe sign-in (OpenVibe.Connect, ADR-057, Website Connect v0).//// The Node opens one outgoing WebSocket per share to wss://connect.openvibe.website/tunnel and speaks ovconnect-ws/1,// the same protocol as the one-file client (OpenVibe.Connect public/ov-connect.js):@@@ -80,7 +80,7 @@ type Options struct {MinWait time.Duration // reconnect backoff floor (default 1 s)MaxWait time.Duration // reconnect backoff ceiling (default 30 s)-- // NodeToken buys this computer's node token for openvibe.website, for shares it serves by id (node.go). An error++ // NodeToken buys this computer's node token for openvibe.link, for shares it serves by id (node.go). An error// wrapping ErrStopped (the machine was removed on OpenVibe) stops the share; any other is tried again.NodeToken func(ctx context.Context) (string, error)HTTPClient *http.Client // Connect's API, for tunnel tokens (default: 20 s timeout)@@@ -67,7 +67,7 @@ func newFakeServer(t *testing.T, refuse int) *fakeServer {_ = ws.Close()return}-- _ = ws.WriteMessage(websocket.TextMessage, []byte(`{"t":"ready","v":1,"share":{"id":"shr_1","host":"agents--alex.openvibe.website","url":"https://agents--alex.openvibe.website","mode":"owner"}}`))++ _ = ws.WriteMessage(websocket.TextMessage, []byte(`{"t":"ready","v":1,"share":{"id":"shr_1","host":"agents--alex.openvibe.link","url":"https://agents--alex.openvibe.link","mode":"owner"}}`))c := &serverConn{ws: ws, frames: map[uint32]chan frame{}}f.conns <- cfor {@@@ -237,7 +237,7 @@ func TestHelloAndHTTP(t *testing.T) {if hello["t"] != "hello" || hello["v"].(float64) != 1 || hello["port"].(float64) != float64(port) || !strings.HasPrefix(hello["key"].(string), "ovc_") {t.Fatalf("hello %v", hello)}-- if r := <-ready; r.Host != "agents--alex.openvibe.website" {++ if r := <-ready; r.Host != "agents--alex.openvibe.link" {t.Fatalf("ready %v", r)}@@@ -16,12 +16,12 @@ func TestLiveSharesForStatus(t *testing.T) {if got := LiveShares(); len(got) != 1 || got[0].Port != 8790 || got[0].Connected {t.Fatalf("marked: %+v", got)}-- liveReady(s, Ready{Host: "agents--alex.openvibe.website", URL: "https://agents--alex.openvibe.website"})++ liveReady(s, Ready{Host: "agents--alex.openvibe.link", URL: "https://agents--alex.openvibe.link"})liveRequest(s)liveRequest(s)got := LiveShares()-- if len(got) != 1 || !got[0].Connected || got[0].Host != "agents--alex.openvibe.website" ||-- got[0].URL != "https://agents--alex.openvibe.website" || got[0].Requests != 2 || got[0].LastError != "" {++ if len(got) != 1 || !got[0].Connected || got[0].Host != "agents--alex.openvibe.link" ||++ got[0].URL != "https://agents--alex.openvibe.link" || got[0].Requests != 2 || got[0].LastError != "" {t.Fatalf("ready: %+v", got)}if got[0].ID != s.ID {@@@ -2,7 +2,7 @@ package connect// A share served by this computer itself, as OpenVibe Node (CON-4, ADR-057 decision 4). The share's owner picks the// computer on the share's page; there is no connect key. Before every connection the Node buys its node token (subject--// node:nod_…, audience openvibe.website) and asks Connect for a tunnel token for that one share:++// node:nod_…, audience openvibe.link) and asks Connect for a tunnel token for that one share://// POST https://connect.openvibe.website/api/v1/node/shares/<shr_…>/tunnel-token Authorization: Bearer <node token>// → {"tunnel_token":"ovt_…","expires_in":60,"share":{"id","host","url","local_port","mode"}}@@@ -39,7 +39,7 @@ func newNodeServer(t *testing.T) *nodeServer {n.mu.Lock()n.bearers = append(n.bearers, r.Header.Get("Authorization"))n.mu.Unlock()-- _ = json.NewEncoder(w).Encode(map[string]any{"shares": []map[string]any{{"id": testShareID, "host": "portal--alex.openvibe.website", "url": "https://portal--alex.openvibe.website", "local_port": n.pagePort, "mode": "owner"}}})++ _ = json.NewEncoder(w).Encode(map[string]any{"shares": []map[string]any{{"id": testShareID, "host": "portal--alex.openvibe.link", "url": "https://portal--alex.openvibe.link", "local_port": n.pagePort, "mode": "owner"}}})})mux.HandleFunc("/api/v1/node/shares/"+testShareID+"/tunnel-token", func(w http.ResponseWriter, r *http.Request) {n.mu.Lock()@@@ -71,7 +71,7 @@ func newNodeServer(t *testing.T) *nodeServer {var hello map[string]any_ = json.Unmarshal(data, &hello)n.hellos <- hello-- _ = ws.WriteMessage(websocket.TextMessage, []byte(`{"t":"ready","v":1,"node":true,"share":{"id":"`+testShareID+`","host":"portal--alex.openvibe.website","url":"https://portal--alex.openvibe.website","mode":"owner","local_port":8790}}`))++ _ = ws.WriteMessage(websocket.TextMessage, []byte(`{"t":"ready","v":1,"node":true,"share":{"id":"`+testShareID+`","host":"portal--alex.openvibe.link","url":"https://portal--alex.openvibe.link","mode":"owner","local_port":8790}}`))for {_, data, err := ws.ReadMessage()if err != nil {@@@ -123,7 +123,7 @@ func TestAShareServedByThisComputer(t *testing.T) {if _, has := hello["key"]; has {t.Fatal("no key in a computer's hello")}-- if r := <-ready; r.Host != "portal--alex.openvibe.website" {++ if r := <-ready; r.Host != "portal--alex.openvibe.link" {t.Fatalf("ready %v", r)}// It keeps the tunnel with fresh node tokens.nnew file mode 100644@@@ -0,0 +1,30 @@++package link++++import (++ "context"++ "net/http"++ "net/http/httptest"++ "testing"++)++++func TestConnectTokenRequestsLinkAudience(t *testing.T) {++ _, _, creds := networkPair(t)++ var audience string++ server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {++ if err := r.ParseForm(); err != nil {++ t.Error(err)++ }++ audience = r.Form.Get("audience")++ w.Header().Set("Content-Type", "application/json")++ _, _ = w.Write([]byte(`{"access_token":"test-node-token","token_type":"Bearer","expires_in":300}`))++ }))++ defer server.Close()++ creds.Network = server.URL++ source := NewTokenSourceFor(creds, server.Client(), "test", ConnectAudience)++ if _, err := source.Token(context.Background()); err != nil {++ t.Fatal(err)++ }++ if audience != "openvibe.link" {++ t.Fatalf("requested audience = %q, want openvibe.link", audience)++ }++}@@@ -156,7 +156,7 @@ func NewTokenSource(c *credentials.Credentials, client *http.Client, userAgent s// ConnectAudience is OpenVibe Connect's: any person's machine may buy a node token for it, whichever service paired// the machine (Network, CON-4), to serve the shares bound to it.--const ConnectAudience = "openvibe.website"++const ConnectAudience = "openvibe.link"// NewTokenSourceFor returns a token source for another audience the machine may speak to (ConnectAudience).func NewTokenSourceFor(c *credentials.Credentials, client *http.Client, userAgent, audience string) *TokenSource {
@@ -5,8 +5,8 @@
@@ -5,8 +5,8 @@
"wave": "T15",
"wave": "T15",
"plan": "Plan track T15 (Bot complete) and ADR-043 (Bot: devices, pairing, control and safety); the computer plugin and the job worker serve OpenVibe.Actor and the Codes job runner (tracks T14/T17)",
"plan": "Plan track T15 (Bot complete) and ADR-043 (Bot: devices, pairing, control and safety); the computer plugin and the job worker serve OpenVibe.Actor and the Codes job runner (tracks T14/T17)",
"kind": "client",
"kind": "client",
- "version": "0.45.0",
- "release": "v0.45.0: sell a local model on the Exchange (`openvibe-node exchange serve`, #120); AI plugin 0.4.0, machine pools over llama.cpp RPC behind a private link, isolated with bubblewrap where Ubuntu restricts user namespaces (#121); Memory M5, `memory export` and `memory import` of the portable memory file (#122); `skills sync`, the skills and rules chosen in the Codes hub written into each coding tool's own folders (#123).",
+ "version": "0.47.0",
+ "release": "v0.47.0: `openvibe-node share` asks for the openvibe.link audience and prints share addresses on openvibe.link (`<label>--<user>.openvibe.link`; the openvibe.website address keeps working, #137); Link answers HO12 camera and location requests on the phone (#138).",
"runtime": "go 1.24 (one static binary per platform); plugins in Python 3; an ESP32 Arduino library",
"runtime": "go 1.24 (one static binary per platform); plugins in Python 3; an ESP32 Arduino library",
"database": "none",
"database": "none",
"deployed": false,
"deployed": false,
@@ -36,12 +36,12 @@ const shareUsage = `usage:
@@ -36,12 +36,12 @@ const shareUsage = `usage:
openvibe-link share list the shares the service keeps up
openvibe-link share list the shares the service keeps up
openvibe-link share remove <PORT|KEY|ID|ADDRESS> stop keeping one up
openvibe-link share remove <PORT|KEY|ID|ADDRESS> stop keeping one up
-Make a share at https://connect.openvibe.website. On its page, pick this computer under "Or serve it from one of your
+Make a share at https://connect.openvibe.website; its address is https://<label>--<you>.openvibe.link. On its page, pick this computer under "Or serve it from one of your
computers" to serve it with --share and no key (the computer must be added on openvibe.bot/machines). Without --port,
computers" to serve it with --share and no key (the computer must be added on openvibe.bot/machines). Without --port,
the Node serves the port the share's page names now, and keeps that one. The Node only ever connects to localhost on
the Node serves the port the share's page names now, and keeps that one. The Node only ever connects to localhost on
the share's port; every visitor signs in with OpenVibe first.`
the share's port; every visitor signs in with OpenVibe first.`
-// connectNodeToken buys this machine's node token for OpenVibe Connect (audience openvibe.website). A machine
+// connectNodeToken buys this machine's node token for OpenVibe Connect (audience openvibe.link). A machine
// removed on OpenVibe stops its shares (connect.ErrStopped) instead of trying forever.
// removed on OpenVibe stops its shares (connect.ErrStopped) instead of trying forever.
func connectNodeToken(creds *credentials.Credentials) func(context.Context) (string, error) {
func connectNodeToken(creds *credentials.Credentials) func(context.Context) (string, error) {
ts := link.NewTokenSourceFor(creds, nil, "openvibe-node/"+version, link.ConnectAudience)
ts := link.NewTokenSourceFor(creds, nil, "openvibe-node/"+version, link.ConnectAudience)
@@ -83,10 +83,10 @@ func TestSharesText(t *testing.T) {
@@ -83,10 +83,10 @@ func TestSharesText(t *testing.T) {
t.Fatalf("no shares: %q", got)
t.Fatalf("no shares: %q", got)
}
}
got := sharesText([]connect.Status{
got := sharesText([]connect.Status{
- {ID: "shr_01K9ZZZZZZZZZZZZZZZZZZZZZZ", Port: 8790, Host: "bot--alex.openvibe.website", URL: "https://bot--alex.openvibe.website", Connected: true, Requests: 3},
+ {ID: "shr_01K9ZZZZZZZZZZZZZZZZZZZZZZ", Port: 8790, Host: "bot--alex.openvibe.link", URL: "https://bot--alex.openvibe.link", Connected: true, Requests: 3},
{Port: 9001, LastError: "dial: connection refused"},
{Port: 9001, LastError: "dial: connection refused"},
})
})
- for _, want := range []string{"Shares: 2 kept up", "localhost:8790", "https://bot--alex.openvibe.website", "connected, 3 requests", "localhost:9001", "not connected", "dial: connection refused"} {
+ for _, want := range []string{"Shares: 2 kept up", "localhost:8790", "https://bot--alex.openvibe.link", "connected, 3 requests", "localhost:9001", "not connected", "dial: connection refused"} {
if !strings.Contains(got, want) {
if !strings.Contains(got, want) {
t.Fatalf("status is missing %q:\n%s", want, got)
t.Fatalf("status is missing %q:\n%s", want, got)
}
}
@@ -1,5 +1,5 @@
@@ -1,5 +1,5 @@
// Package connect keeps OpenVibe Connect shares up from the Node: each share is one port on this machine served at
// Package connect keeps OpenVibe Connect shares up from the Node: each share is one port on this machine served at
-// https://<label>--<user>.openvibe.website behind OpenVibe sign-in (OpenVibe.Connect, ADR-057, Website Connect v0).
+// https://<label>--<user>.openvibe.link behind OpenVibe sign-in (OpenVibe.Connect, ADR-057, Website Connect v0).
//
//
// The Node opens one outgoing WebSocket per share to wss://connect.openvibe.website/tunnel and speaks ovconnect-ws/1,
// The Node opens one outgoing WebSocket per share to wss://connect.openvibe.website/tunnel and speaks ovconnect-ws/1,
// the same protocol as the one-file client (OpenVibe.Connect public/ov-connect.js):
// the same protocol as the one-file client (OpenVibe.Connect public/ov-connect.js):
@@ -80,7 +80,7 @@ type Options struct {
@@ -80,7 +80,7 @@ type Options struct {
MinWait time.Duration // reconnect backoff floor (default 1 s)
MinWait time.Duration // reconnect backoff floor (default 1 s)
MaxWait time.Duration // reconnect backoff ceiling (default 30 s)
MaxWait time.Duration // reconnect backoff ceiling (default 30 s)
- // NodeToken buys this computer's node token for openvibe.website, for shares it serves by id (node.go). An error
+ // NodeToken buys this computer's node token for openvibe.link, for shares it serves by id (node.go). An error
// wrapping ErrStopped (the machine was removed on OpenVibe) stops the share; any other is tried again.
// wrapping ErrStopped (the machine was removed on OpenVibe) stops the share; any other is tried again.
NodeToken func(ctx context.Context) (string, error)
NodeToken func(ctx context.Context) (string, error)
HTTPClient *http.Client // Connect's API, for tunnel tokens (default: 20 s timeout)
HTTPClient *http.Client // Connect's API, for tunnel tokens (default: 20 s timeout)
@@ -67,7 +67,7 @@ func newFakeServer(t *testing.T, refuse int) *fakeServer {
@@ -67,7 +67,7 @@ func newFakeServer(t *testing.T, refuse int) *fakeServer {
_ = ws.Close()
_ = ws.Close()
return
return
}
}
- _ = ws.WriteMessage(websocket.TextMessage, []byte(`{"t":"ready","v":1,"share":{"id":"shr_1","host":"agents--alex.openvibe.website","url":"https://agents--alex.openvibe.website","mode":"owner"}}`))
+ _ = ws.WriteMessage(websocket.TextMessage, []byte(`{"t":"ready","v":1,"share":{"id":"shr_1","host":"agents--alex.openvibe.link","url":"https://agents--alex.openvibe.link","mode":"owner"}}`))
c := &serverConn{ws: ws, frames: map[uint32]chan frame{}}
c := &serverConn{ws: ws, frames: map[uint32]chan frame{}}
f.conns <- c
f.conns <- c
for {
for {
@@ -237,7 +237,7 @@ func TestHelloAndHTTP(t *testing.T) {
@@ -237,7 +237,7 @@ func TestHelloAndHTTP(t *testing.T) {
if hello["t"] != "hello" || hello["v"].(float64) != 1 || hello["port"].(float64) != float64(port) || !strings.HasPrefix(hello["key"].(string), "ovc_") {
if hello["t"] != "hello" || hello["v"].(float64) != 1 || hello["port"].(float64) != float64(port) || !strings.HasPrefix(hello["key"].(string), "ovc_") {
t.Fatalf("hello %v", hello)
t.Fatalf("hello %v", hello)
}
}
- if r := <-ready; r.Host != "agents--alex.openvibe.website" {
+ if r := <-ready; r.Host != "agents--alex.openvibe.link" {
t.Fatalf("ready %v", r)
t.Fatalf("ready %v", r)
}
}
@@ -16,12 +16,12 @@ func TestLiveSharesForStatus(t *testing.T) {
@@ -16,12 +16,12 @@ func TestLiveSharesForStatus(t *testing.T) {
if got := LiveShares(); len(got) != 1 || got[0].Port != 8790 || got[0].Connected {
if got := LiveShares(); len(got) != 1 || got[0].Port != 8790 || got[0].Connected {
t.Fatalf("marked: %+v", got)
t.Fatalf("marked: %+v", got)
}
}
- liveReady(s, Ready{Host: "agents--alex.openvibe.website", URL: "https://agents--alex.openvibe.website"})
+ liveReady(s, Ready{Host: "agents--alex.openvibe.link", URL: "https://agents--alex.openvibe.link"})
liveRequest(s)
liveRequest(s)
liveRequest(s)
liveRequest(s)
got := LiveShares()
got := LiveShares()
- if len(got) != 1 || !got[0].Connected || got[0].Host != "agents--alex.openvibe.website" ||
- got[0].URL != "https://agents--alex.openvibe.website" || got[0].Requests != 2 || got[0].LastError != "" {
+ if len(got) != 1 || !got[0].Connected || got[0].Host != "agents--alex.openvibe.link" ||
+ got[0].URL != "https://agents--alex.openvibe.link" || got[0].Requests != 2 || got[0].LastError != "" {
t.Fatalf("ready: %+v", got)
t.Fatalf("ready: %+v", got)
}
}
if got[0].ID != s.ID {
if got[0].ID != s.ID {
@@ -2,7 +2,7 @@ package connect
@@ -2,7 +2,7 @@ package connect
// A share served by this computer itself, as OpenVibe Node (CON-4, ADR-057 decision 4). The share's owner picks the
// A share served by this computer itself, as OpenVibe Node (CON-4, ADR-057 decision 4). The share's owner picks the
// computer on the share's page; there is no connect key. Before every connection the Node buys its node token (subject
// computer on the share's page; there is no connect key. Before every connection the Node buys its node token (subject
-// node:nod_…, audience openvibe.website) and asks Connect for a tunnel token for that one share:
+// node:nod_…, audience openvibe.link) and asks Connect for a tunnel token for that one share:
//
//
// POST https://connect.openvibe.website/api/v1/node/shares/<shr_…>/tunnel-token Authorization: Bearer <node token>
// POST https://connect.openvibe.website/api/v1/node/shares/<shr_…>/tunnel-token Authorization: Bearer <node token>
// → {"tunnel_token":"ovt_…","expires_in":60,"share":{"id","host","url","local_port","mode"}}
// → {"tunnel_token":"ovt_…","expires_in":60,"share":{"id","host","url","local_port","mode"}}
@@ -39,7 +39,7 @@ func newNodeServer(t *testing.T) *nodeServer {
@@ -39,7 +39,7 @@ func newNodeServer(t *testing.T) *nodeServer {
n.mu.Lock()
n.mu.Lock()
n.bearers = append(n.bearers, r.Header.Get("Authorization"))
n.bearers = append(n.bearers, r.Header.Get("Authorization"))
n.mu.Unlock()
n.mu.Unlock()
- _ = json.NewEncoder(w).Encode(map[string]any{"shares": []map[string]any{{"id": testShareID, "host": "portal--alex.openvibe.website", "url": "https://portal--alex.openvibe.website", "local_port": n.pagePort, "mode": "owner"}}})
+ _ = json.NewEncoder(w).Encode(map[string]any{"shares": []map[string]any{{"id": testShareID, "host": "portal--alex.openvibe.link", "url": "https://portal--alex.openvibe.link", "local_port": n.pagePort, "mode": "owner"}}})
})
})
mux.HandleFunc("/api/v1/node/shares/"+testShareID+"/tunnel-token", func(w http.ResponseWriter, r *http.Request) {
mux.HandleFunc("/api/v1/node/shares/"+testShareID+"/tunnel-token", func(w http.ResponseWriter, r *http.Request) {
n.mu.Lock()
n.mu.Lock()
@@ -71,7 +71,7 @@ func newNodeServer(t *testing.T) *nodeServer {
@@ -71,7 +71,7 @@ func newNodeServer(t *testing.T) *nodeServer {
var hello map[string]any
var hello map[string]any
_ = json.Unmarshal(data, &hello)
_ = json.Unmarshal(data, &hello)
n.hellos <- hello
n.hellos <- hello
- _ = ws.WriteMessage(websocket.TextMessage, []byte(`{"t":"ready","v":1,"node":true,"share":{"id":"`+testShareID+`","host":"portal--alex.openvibe.website","url":"https://portal--alex.openvibe.website","mode":"owner","local_port":8790}}`))
+ _ = ws.WriteMessage(websocket.TextMessage, []byte(`{"t":"ready","v":1,"node":true,"share":{"id":"`+testShareID+`","host":"portal--alex.openvibe.link","url":"https://portal--alex.openvibe.link","mode":"owner","local_port":8790}}`))
for {
for {
_, data, err := ws.ReadMessage()
_, data, err := ws.ReadMessage()
if err != nil {
if err != nil {
@@ -123,7 +123,7 @@ func TestAShareServedByThisComputer(t *testing.T) {
@@ -123,7 +123,7 @@ func TestAShareServedByThisComputer(t *testing.T) {
if _, has := hello["key"]; has {
if _, has := hello["key"]; has {
t.Fatal("no key in a computer's hello")
t.Fatal("no key in a computer's hello")
}
}
- if r := <-ready; r.Host != "portal--alex.openvibe.website" {
+ if r := <-ready; r.Host != "portal--alex.openvibe.link" {
t.Fatalf("ready %v", r)
t.Fatalf("ready %v", r)
}
}
// It keeps the tunnel with fresh node tokens.
// It keeps the tunnel with fresh node tokens.
new file mode 100644
new file mode 100644
@@ -0,0 +1,30 @@
@@ -0,0 +1,30 @@
+package link
+
+import (
+ "context"
+ "net/http"
+ "net/http/httptest"
+ "testing"
+)
+
+func TestConnectTokenRequestsLinkAudience(t *testing.T) {
+ _, _, creds := networkPair(t)
+ var audience string
+ server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ if err := r.ParseForm(); err != nil {
+ t.Error(err)
+ }
+ audience = r.Form.Get("audience")
+ w.Header().Set("Content-Type", "application/json")
+ _, _ = w.Write([]byte(`{"access_token":"test-node-token","token_type":"Bearer","expires_in":300}`))
+ }))
+ defer server.Close()
+ creds.Network = server.URL
+ source := NewTokenSourceFor(creds, server.Client(), "test", ConnectAudience)
+ if _, err := source.Token(context.Background()); err != nil {
+ t.Fatal(err)
+ }
+ if audience != "openvibe.link" {
+ t.Fatalf("requested audience = %q, want openvibe.link", audience)
+ }
+}
@@ -156,7 +156,7 @@ func NewTokenSource(c *credentials.Credentials, client *http.Client, userAgent s
@@ -156,7 +156,7 @@ func NewTokenSource(c *credentials.Credentials, client *http.Client, userAgent s
// ConnectAudience is OpenVibe Connect's: any person's machine may buy a node token for it, whichever service paired
// ConnectAudience is OpenVibe Connect's: any person's machine may buy a node token for it, whichever service paired
// the machine (Network, CON-4), to serve the shares bound to it.
// the machine (Network, CON-4), to serve the shares bound to it.
-const ConnectAudience = "openvibe.website"
+const ConnectAudience = "openvibe.link"
// NewTokenSourceFor returns a token source for another audience the machine may speak to (ConnectAudience).
// NewTokenSourceFor returns a token source for another audience the machine may speak to (ConnectAudience).
func NewTokenSourceFor(c *credentials.Credentials, client *http.Client, userAgent, audience string) *TokenSource {
func NewTokenSourceFor(c *credentials.Credentials, client *http.Client, userAgent, audience string) *TokenSource {