Skip to content

Commit f690ea4

Browse files
Output server details as json (#37)
This PR changes the address url stdout to be in json format and lets tsrelay come up with its own once by default. This way, we can add more details that a client such as vscode might need to extract out of tsrelay at server startup.
1 parent 07be1c5 commit f690ea4

File tree

3 files changed

+32
-10
lines changed

3 files changed

+32
-10
lines changed

src/tailscale/cli.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
import * as cp from 'child_process';
22
import * as vscode from 'vscode';
33
import fetch from 'node-fetch';
4-
import { getNonce } from '../get-nonce';
54
import * as WebSocket from 'ws';
6-
import type { ServeParams, ServeConfig, ServeStatus } from '../types';
5+
import type { ServeParams, ServeStatus, TSRelayDetails } from '../types';
76
import { Logger } from '../logger';
87
import * as path from 'node:path';
98
import { LogLevel } from 'vscode';
@@ -26,14 +25,13 @@ interface vscodeModule {
2625

2726
export class Tailscale {
2827
private _vscode: vscodeModule;
29-
private nonce: string;
28+
private nonce?: string;
3029
public url?: string;
3130
public authkey?: string;
3231
private childProcess?: cp.ChildProcess;
3332

3433
constructor(vscode: vscodeModule) {
3534
this._vscode = vscode;
36-
this.nonce = getNonce();
3735
}
3836

3937
static async withInit(vscode: vscodeModule): Promise<Tailscale> {
@@ -58,7 +56,7 @@ export class Tailscale {
5856
__dirname,
5957
`../bin/vscode-tailscale_${platform}_${arch}/vscode-tailscale`
6058
);
61-
let args = [`-nonce=${this.nonce}`];
59+
let args = [];
6260
if (this._vscode.env.logLevel === LogLevel.Debug) {
6361
args.push('-v');
6462
}
@@ -82,7 +80,9 @@ export class Tailscale {
8280

8381
if (this.childProcess.stdout) {
8482
this.childProcess.stdout.on('data', (data: Buffer) => {
85-
this.url = data.toString().trim();
83+
const details = JSON.parse(data.toString().trim()) as TSRelayDetails;
84+
this.url = details.address;
85+
this.nonce = details.nonce;
8686
this.authkey = Buffer.from(`${this.nonce}:`).toString('base64');
8787
Logger.info(`url: ${this.url}`, LOG_COMPONENT);
8888

src/types.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,3 +152,8 @@ export interface NewPortNotification {
152152
message: string;
153153
port: number;
154154
}
155+
156+
export interface TSRelayDetails {
157+
address: string;
158+
nonce: string;
159+
}

tsrelay/main.go

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"fmt"
99
"io"
1010
"log"
11+
"math/rand"
1112
"net"
1213
"net/http"
1314
"net/url"
@@ -74,12 +75,14 @@ func run() error {
7475
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)
7576
defer cancel()
7677

77-
if *nonce == "" {
78-
return errors.New("missing nonce as first argument")
79-
}
8078
return runHTTPServer(ctx, lggr, *port, *nonce)
8179
}
8280

81+
type serverDetails struct {
82+
Address string `json:"address,omitempty"`
83+
Nonce string `json:"nonce,omitempty"`
84+
}
85+
8386
func runHTTPServer(ctx context.Context, lggr *logger, port int, nonce string) error {
8487
l, err := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", port))
8588
if err != nil {
@@ -89,7 +92,12 @@ func runHTTPServer(ctx context.Context, lggr *logger, port int, nonce string) er
8992
if err != nil {
9093
return fmt.Errorf("error parsing addr %q: %w", l.Addr().String(), err)
9194
}
92-
fmt.Fprintf(os.Stdout, "http://127.0.0.1:%s\n", u.Port())
95+
sd := serverDetails{Address: fmt.Sprintf("http://127.0.0.1:%s", u.Port())}
96+
if nonce == "" {
97+
nonce = getNonce()
98+
sd.Nonce = nonce // only print it out if not set by flag
99+
}
100+
json.NewEncoder(os.Stdout).Encode(sd)
93101
s := &http.Server{
94102
Handler: &httpHandler{
95103
lc: tailscale.LocalClient{
@@ -105,6 +113,15 @@ func runHTTPServer(ctx context.Context, lggr *logger, port int, nonce string) er
105113
return serveTLS(ctx, l, s, time.Second)
106114
}
107115

116+
func getNonce() string {
117+
const possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
118+
var b strings.Builder
119+
for i := 0; i < 32; i++ {
120+
b.WriteByte(possible[rand.Intn(len(possible))])
121+
}
122+
return b.String()
123+
}
124+
108125
type httpHandler struct {
109126
sync.Mutex
110127
nonce string

0 commit comments

Comments
 (0)