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
}