Skip to content

Commit

Permalink
Output server details as json (#37)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
marwan-at-work authored and tylersmalley committed Jun 21, 2023
1 parent 277a5ba commit 9e507b9
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 10 deletions.
12 changes: 6 additions & 6 deletions src/tailscale/cli.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import * as cp from 'child_process';
import * as vscode from 'vscode';
import fetch from 'node-fetch';
import { getNonce } from '../get-nonce';
import * as WebSocket from 'ws';
import type { ServeParams, ServeConfig, ServeStatus } from '../types';
import type { ServeParams, ServeStatus, TSRelayDetails } from '../types';
import { Logger } from '../logger';
import * as path from 'node:path';
import { LogLevel } from 'vscode';
Expand All @@ -26,14 +25,13 @@ interface vscodeModule {

export class Tailscale {
private _vscode: vscodeModule;
private nonce: string;
private nonce?: string;
public url?: string;
public authkey?: string;
private childProcess?: cp.ChildProcess;

constructor(vscode: vscodeModule) {
this._vscode = vscode;
this.nonce = getNonce();
}

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

if (this.childProcess.stdout) {
this.childProcess.stdout.on('data', (data: Buffer) => {
this.url = data.toString().trim();
const details = JSON.parse(data.toString().trim()) as TSRelayDetails;
this.url = details.address;
this.nonce = details.nonce;
this.authkey = Buffer.from(`${this.nonce}:`).toString('base64');
Logger.info(`url: ${this.url}`, LOG_COMPONENT);

Expand Down
5 changes: 5 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,3 +152,8 @@ export interface NewPortNotification {
message: string;
port: number;
}

export interface TSRelayDetails {
address: string;
nonce: string;
}
25 changes: 21 additions & 4 deletions tsrelay/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"fmt"
"io"
"log"
"math/rand"
"net"
"net/http"
"net/url"
Expand Down Expand Up @@ -74,12 +75,14 @@ func run() error {
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)
defer cancel()

if *nonce == "" {
return errors.New("missing nonce as first argument")
}
return runHTTPServer(ctx, lggr, *port, *nonce)
}

type serverDetails struct {
Address string `json:"address,omitempty"`
Nonce string `json:"nonce,omitempty"`
}

func runHTTPServer(ctx context.Context, lggr *logger, port int, nonce string) error {
l, err := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", port))
if err != nil {
Expand All @@ -89,7 +92,12 @@ func runHTTPServer(ctx context.Context, lggr *logger, port int, nonce string) er
if err != nil {
return fmt.Errorf("error parsing addr %q: %w", l.Addr().String(), err)
}
fmt.Fprintf(os.Stdout, "http://127.0.0.1:%s\n", u.Port())
sd := serverDetails{Address: fmt.Sprintf("http://127.0.0.1:%s", u.Port())}
if nonce == "" {
nonce = getNonce()
sd.Nonce = nonce // only print it out if not set by flag
}
json.NewEncoder(os.Stdout).Encode(sd)
s := &http.Server{
Handler: &httpHandler{
lc: tailscale.LocalClient{
Expand All @@ -105,6 +113,15 @@ func runHTTPServer(ctx context.Context, lggr *logger, port int, nonce string) er
return serveTLS(ctx, l, s, time.Second)
}

func getNonce() string {
const possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
var b strings.Builder
for i := 0; i < 32; i++ {
b.WriteByte(possible[rand.Intn(len(possible))])
}
return b.String()
}

type httpHandler struct {
sync.Mutex
nonce string
Expand Down

0 comments on commit 9e507b9

Please sign in to comment.