4
4
"context"
5
5
"encoding/binary"
6
6
"encoding/json"
7
+ "fmt"
8
+ "io"
7
9
"net"
8
10
"net/http"
9
11
"net/netip"
@@ -176,6 +178,19 @@ func (c *AgentConn) statisticsClient() *http.Client {
176
178
// request, and this triggers goleak in tests
177
179
DisableKeepAlives : true ,
178
180
DialContext : func (ctx context.Context , network , addr string ) (net.Conn , error ) {
181
+ if network != "tcp" {
182
+ return nil , xerrors .Errorf ("network must be tcp" )
183
+ }
184
+ host , port , err := net .SplitHostPort (addr )
185
+ if err != nil {
186
+ return nil , xerrors .Errorf ("split host port %q: %w" , addr , err )
187
+ }
188
+ // Verify that host is TailnetIP and port is
189
+ // TailnetStatisticsPort.
190
+ if host != TailnetIP .String () || port != strconv .Itoa (TailnetStatisticsPort ) {
191
+ return nil , xerrors .Errorf ("request %q does not appear to be for statistics server" , addr )
192
+ }
193
+
179
194
conn , err := c .DialContextTCP (context .Background (), netip .AddrPortFrom (TailnetIP , uint16 (TailnetStatisticsPort )))
180
195
if err != nil {
181
196
return nil , xerrors .Errorf ("dial statistics: %w" , err )
@@ -187,6 +202,18 @@ func (c *AgentConn) statisticsClient() *http.Client {
187
202
}
188
203
}
189
204
205
+ func (c * AgentConn ) doStatisticsRequest (ctx context.Context , method , path string , body io.Reader ) (* http.Response , error ) {
206
+ host := net .JoinHostPort (TailnetIP .String (), strconv .Itoa (TailnetStatisticsPort ))
207
+ url := fmt .Sprintf ("http://%s%s" , host , path )
208
+
209
+ req , err := http .NewRequestWithContext (ctx , method , url , body )
210
+ if err != nil {
211
+ return nil , xerrors .Errorf ("new statistics server request to %q: %w" , url , err )
212
+ }
213
+
214
+ return c .statisticsClient ().Do (req )
215
+ }
216
+
190
217
type ListeningPortsResponse struct {
191
218
// If there are no ports in the list, nothing should be displayed in the UI.
192
219
// There must not be a "no ports available" message or anything similar, as
@@ -208,11 +235,7 @@ type ListeningPort struct {
208
235
}
209
236
210
237
func (c * AgentConn ) ListeningPorts (ctx context.Context ) (ListeningPortsResponse , error ) {
211
- req , err := http .NewRequestWithContext (ctx , http .MethodGet , "http://agent-stats/api/v0/listening-ports" , nil )
212
- if err != nil {
213
- return ListeningPortsResponse {}, xerrors .Errorf ("new request: %w" , err )
214
- }
215
- res , err := c .statisticsClient ().Do (req )
238
+ res , err := c .doStatisticsRequest (ctx , http .MethodGet , "/api/v0/listening-ports" , nil )
216
239
if err != nil {
217
240
return ListeningPortsResponse {}, xerrors .Errorf ("do request: %w" , err )
218
241
}
0 commit comments