From 129d9e397a418dd47a54e465579a8288f202d083 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Thu, 5 Aug 2021 10:32:13 -0700 Subject: [PATCH] net/portmapper: add sketch of a TestIGD for portmapper testing Signed-off-by: Brad Fitzpatrick --- net/portmapper/igd_test.go | 78 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 net/portmapper/igd_test.go diff --git a/net/portmapper/igd_test.go b/net/portmapper/igd_test.go new file mode 100644 index 000000000..bdda9d9d3 --- /dev/null +++ b/net/portmapper/igd_test.go @@ -0,0 +1,78 @@ +// Copyright (c) 2021 Tailscale Inc & AUTHORS All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package portmapper + +import ( + "net" + "net/http" + "net/http/httptest" +) + +// TestIGD is an IGD (Intenet Gateway Device) for testing. It supports fake +// implementations of NAT-PMP, PCP, and/or UPnP to test clients against. +type TestIGD struct { + upnpConn net.PacketConn // for UPnP discovery + pxpConn net.PacketConn // for NAT-PMP and/or PCP + ts *httptest.Server + + doPMP bool + doPCP bool + doUPnP bool // TODO: more options for 3 flavors of UPnP services +} + +func NewTestIGD() (*TestIGD, error) { + d := &TestIGD{ + doPMP: true, + doPCP: true, + doUPnP: true, + } + var err error + if d.upnpConn, err = net.ListenPacket("udp", "127.0.0.1:1900"); err != nil { + return nil, err + } + if d.pxpConn, err = net.ListenPacket("udp", "127.0.0.1:5351"); err != nil { + return nil, err + } + d.ts = httptest.NewServer(http.HandlerFunc(d.serveUPnPHTTP)) + go d.serveUPnPDiscovery() + go d.servePxP() + return d, nil +} + +func (d *TestIGD) Close() error { + d.ts.Close() + d.upnpConn.Close() + d.pxpConn.Close() + return nil +} + +func (d *TestIGD) serveUPnPHTTP(w http.ResponseWriter, r *http.Request) { + http.NotFound(w, r) // TODO +} + +func (d *TestIGD) serveUPnPDiscovery() { + buf := make([]byte, 1500) + for { + n, addr, err := d.upnpConn.ReadFrom(buf) + if err != nil { + return + } + pkt := buf[:n] + _, _ = pkt, addr // TODO + } +} + +// servePxP serves NAT-PMP and PCP, which share a port number. +func (d *TestIGD) servePxP() { + buf := make([]byte, 1500) + for { + n, addr, err := d.pxpConn.ReadFrom(buf) + if err != nil { + return + } + pkt := buf[:n] + _, _ = pkt, addr // TODO + } +}