@ -1,12 +1,11 @@
// Copyright (c) Tailscale Inc & AUTHORS
// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
// SPDX-License-Identifier: BSD-3-Clause
//go:build go1.22
// Package local contains a Go client for the Tailscale LocalAPI.
// Package local contains a Go client for the Tailscale LocalAPI.
package local
package local
import (
import (
"bufio"
"bytes"
"bytes"
"cmp"
"cmp"
"context"
"context"
@ -16,6 +15,7 @@ import (
"errors"
"errors"
"fmt"
"fmt"
"io"
"io"
"iter"
"net"
"net"
"net/http"
"net/http"
"net/http/httptrace"
"net/http/httptrace"
@ -42,6 +42,7 @@ import (
"tailscale.com/types/dnstype"
"tailscale.com/types/dnstype"
"tailscale.com/types/key"
"tailscale.com/types/key"
"tailscale.com/types/tkatype"
"tailscale.com/types/tkatype"
"tailscale.com/util/eventbus"
"tailscale.com/util/syspolicy/setting"
"tailscale.com/util/syspolicy/setting"
)
)
@ -414,24 +415,42 @@ func (lc *Client) TailDaemonLogs(ctx context.Context) (io.Reader, error) {
return res . Body , nil
return res . Body , nil
}
}
// StreamBusEvents returns a stream of the Tailscale bus events as they arrive.
// StreamBusEvents returns an iterator of Tailscale bus events as they arrive.
// Close the context to stop the stream.
// Each pair is a valid event and a nil error, or a zero event a non-nil error.
// Expected response from the server is newline-delimited JSON.
// In case of error, the iterator ends after the pair reporting the error.
// The caller must close the reader when it is finished reading.
// Iteration stops if ctx ends.
func ( lc * Client ) StreamBusEvents ( ctx context . Context ) ( io . ReadCloser , error ) {
func ( lc * Client ) StreamBusEvents ( ctx context . Context ) iter . Seq2 [ eventbus . DebugEvent , error ] {
req , err := http . NewRequestWithContext ( ctx , "GET" ,
return func ( yield func ( eventbus . DebugEvent , error ) bool ) {
"http://" + apitype . LocalAPIHost + "/localapi/v0/debug-bus-events" , nil )
req , err := http . NewRequestWithContext ( ctx , "GET" ,
if err != nil {
"http://" + apitype . LocalAPIHost + "/localapi/v0/debug-bus-events" , nil )
return nil , err
if err != nil {
}
yield ( eventbus . DebugEvent { } , err )
res , err := lc . doLocalRequestNiceError ( req )
return
if err != nil {
}
return nil , err
res , err := lc . doLocalRequestNiceError ( req )
}
if err != nil {
if res . StatusCode != http . StatusOK {
yield ( eventbus . DebugEvent { } , err )
return nil , errors . New ( res . Status )
return
}
if res . StatusCode != http . StatusOK {
yield ( eventbus . DebugEvent { } , errors . New ( res . Status ) )
return
}
defer res . Body . Close ( )
dec := json . NewDecoder ( bufio . NewReader ( res . Body ) )
for {
var evt eventbus . DebugEvent
if err := dec . Decode ( & evt ) ; err == io . EOF {
return
} else if err != nil {
yield ( eventbus . DebugEvent { } , err )
return
}
if ! yield ( evt , nil ) {
return
}
}
}
}
return res . Body , nil
}
}
// Pprof returns a pprof profile of the Tailscale daemon.
// Pprof returns a pprof profile of the Tailscale daemon.