(getClient func(...tcpip.SettableSocketOption) *gonet.TCPConn, clientRemoteIP netip.Addr, wq *waiter.Queue, dialAddr netip.AddrPort, isLocal bool)
| 1701 | } |
| 1702 | |
| 1703 | func (ns *Impl) forwardTCP(getClient func(...tcpip.SettableSocketOption) *gonet.TCPConn, clientRemoteIP netip.Addr, wq *waiter.Queue, dialAddr netip.AddrPort, isLocal bool) (handled bool) { |
| 1704 | dialAddrStr := dialAddr.String() |
| 1705 | if debugNetstack() { |
| 1706 | ns.logf("[v2] netstack: forwarding incoming connection to %s", dialAddrStr) |
| 1707 | } |
| 1708 | |
| 1709 | ctx, cancel := context.WithCancel(context.Background()) |
| 1710 | defer cancel() |
| 1711 | |
| 1712 | waitEntry, notifyCh := waiter.NewChannelEntry(waiter.EventHUp) // TODO(bradfitz): right EventMask? |
| 1713 | wq.EventRegister(&waitEntry) |
| 1714 | defer wq.EventUnregister(&waitEntry) |
| 1715 | done := make(chan bool) |
| 1716 | // netstack doesn't close the notification channel automatically if there was no |
| 1717 | // hup signal, so we close done after we're done to not leak the goroutine below. |
| 1718 | defer close(done) |
| 1719 | go func() { |
| 1720 | select { |
| 1721 | case <-notifyCh: |
| 1722 | if debugNetstack() { |
| 1723 | ns.logf("[v2] netstack: forwardTCP notifyCh fired; canceling context for %s", dialAddrStr) |
| 1724 | } |
| 1725 | case <-done: |
| 1726 | } |
| 1727 | cancel() |
| 1728 | }() |
| 1729 | |
| 1730 | // Attempt to dial the outbound connection before we accept the inbound one. |
| 1731 | var dialFunc netx.DialFunc |
| 1732 | if ns.forwardDialFunc != nil { |
| 1733 | dialFunc = ns.forwardDialFunc |
| 1734 | } else { |
| 1735 | var stdDialer net.Dialer |
| 1736 | dialFunc = stdDialer.DialContext |
| 1737 | } |
| 1738 | |
| 1739 | // TODO: this is racy, dialing before we register our local address. See |
| 1740 | // https://github.com/tailscale/tailscale/issues/1616. |
| 1741 | backend, err := dialFunc(ctx, "tcp", dialAddrStr) |
| 1742 | if err != nil { |
| 1743 | ns.logf("netstack: could not connect to local backend server at %s: %v", dialAddr.String(), err) |
| 1744 | return |
| 1745 | } |
| 1746 | defer backend.Close() |
| 1747 | |
| 1748 | backendLocalAddr := backend.LocalAddr().(*net.TCPAddr) |
| 1749 | backendLocalIPPort := netaddr.Unmap(backendLocalAddr.AddrPort()) |
| 1750 | if isLocal { |
| 1751 | if err := ns.pm.RegisterIPPortIdentity("tcp", backendLocalIPPort, clientRemoteIP); err != nil { |
| 1752 | ns.logf("netstack: could not register TCP mapping %s: %v", backendLocalIPPort, err) |
| 1753 | return |
| 1754 | } |
| 1755 | defer ns.pm.UnregisterIPPortIdentity("tcp", backendLocalIPPort) |
| 1756 | } |
| 1757 | |
| 1758 | // If we get here, either the getClient call below will succeed and |
| 1759 | // return something we can Close, or it will fail and will properly |
| 1760 | // respond to the client with a RST. Either way, the caller no longer |
no test coverage detected