MCPcopy Index your code
hub / github.com/tailscale/tailscale / forwardTCP

Method forwardTCP

wgengine/netstack/netstack.go:1703–1816  ·  view source on GitHub ↗
(getClient func(...tcpip.SettableSocketOption) *gonet.TCPConn, clientRemoteIP netip.Addr, wq *waiter.Queue, dialAddr netip.AddrPort, isLocal bool)

Source from the content-addressed store, hash-verified

1701}
1702
1703func (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

Callers 1

acceptTCPMethod · 0.95

Calls 10

UnmapFunction · 0.92
StringMethod · 0.65
CloseMethod · 0.65
LocalAddrMethod · 0.65
ErrorfMethod · 0.65
CloseWriteMethod · 0.65
CloseReadMethod · 0.65
logfMethod · 0.45

Tested by

no test coverage detected