Merge pull request #7436 from akram/fix_port_forward_listens_ipv_and_ipv4

Port forward now listens on IPv4 and IPv6 localhost address
This commit is contained in:
Derek Carr 2015-05-12 10:27:56 -04:00
commit 3e4713787a
2 changed files with 23 additions and 22 deletions

View File

@ -183,17 +183,26 @@ func (pf *PortForwarder) forward() error {
return nil return nil
} }
// listenOnPort delegates listener creation and waits for new connections // listenOnPort delegates tcp4 and tcp6 listener creation and waits for connections on both of these addresses.
// in the background. // If both listener creation fail, an error is raised.
func (pf *PortForwarder) listenOnPort(port *ForwardedPort) error { func (pf *PortForwarder) listenOnPort(port *ForwardedPort) error {
listener, err := pf.getListener("tcp", "localhost", port) errTcp4 := pf.listenOnPortAndAddress(port, "tcp4", "127.0.0.1")
errTcp6 := pf.listenOnPortAndAddress(port, "tcp6", "[::1]")
if errTcp4 != nil && errTcp6 != nil {
return fmt.Errorf("All listeners failed to create with the following errors: %s, %s", errTcp4, errTcp6)
}
return nil
}
// listenOnPortAndAddress delegates listener creation and waits for new connections
// in the background f
func (pf *PortForwarder) listenOnPortAndAddress(port *ForwardedPort, protocol string, address string) error {
listener, err := pf.getListener(protocol, address, port)
if err != nil { if err != nil {
return err return err
} }
pf.listeners = append(pf.listeners, listener) pf.listeners = append(pf.listeners, listener)
go pf.waitForConnection(listener, *port) go pf.waitForConnection(listener, *port)
return nil return nil
} }
@ -213,7 +222,7 @@ func (pf *PortForwarder) getListener(protocol string, hostname string, port *For
return nil, fmt.Errorf("Error parsing local port: %s from %s (%s)", err, listenerAddress, host) return nil, fmt.Errorf("Error parsing local port: %s from %s (%s)", err, listenerAddress, host)
} }
port.Local = uint16(localPortUInt) port.Local = uint16(localPortUInt)
glog.Infof("Forwarding from %d -> %d", localPortUInt, port.Remote) glog.Infof("Forwarding from %s:%d -> %d", hostname, localPortUInt, port.Remote)
return listener, nil return listener, nil
} }

View File

@ -209,7 +209,7 @@ func (s *fakeUpgradeStream) Headers() http.Header {
return http.Header{} return http.Header{}
} }
type TestCase struct { type GetListenerTestCase struct {
Hostname string Hostname string
Protocol string Protocol string
ShouldRaiseError bool ShouldRaiseError bool
@ -218,7 +218,7 @@ type TestCase struct {
func TestGetListener(t *testing.T) { func TestGetListener(t *testing.T) {
var pf PortForwarder var pf PortForwarder
testCases := []TestCase{ testCases := []GetListenerTestCase{
{ {
Hostname: "localhost", Hostname: "localhost",
Protocol: "tcp4", Protocol: "tcp4",
@ -247,20 +247,12 @@ func TestGetListener(t *testing.T) {
Protocol: "tcp6", Protocol: "tcp6",
ShouldRaiseError: true, ShouldRaiseError: true,
}, },
} {
// IPv6 address must be put into brackets. This test reveals this.
// On some linux systems, ::1 does not resolve to localhost but to localhost6 or Hostname: "::1",
// ip6-localhost. To make the test case portable, we need to do a reverse lookup on ::1 and
// trying to bind a port with the name.
names, err := net.LookupAddr("::1")
if err == nil && len(names) > 0 {
ipv6TestCase := TestCase{
Hostname: names[0],
Protocol: "tcp6", Protocol: "tcp6",
ShouldRaiseError: false, ShouldRaiseError: true,
ExpectedListenerAddress: "::1", },
}
testCases = append(testCases, ipv6TestCase)
} }
for i, testCase := range testCases { for i, testCase := range testCases {