func NewStream(w io.Writer, r io.Reader) *stream { s := &stream{ Reader: r, Writer: w, toDeliver: make(chan *transportObject), } s.proc = process.WithTeardown(s.teardown) s.proc.Go(s.transport) return s }
func newConn(ln, rn *peernet, l *link) *conn { c := &conn{net: ln, link: l} c.local = ln.peer c.remote = rn.peer c.localAddr = ln.ps.Addrs(ln.peer)[0] c.remoteAddr = rn.ps.Addrs(rn.peer)[0] c.localPrivKey = ln.ps.PrivKey(ln.peer) c.remotePubKey = rn.ps.PubKey(rn.peer) c.proc = process.WithTeardown(c.teardown) return c }
// NewMapping attemps to construct a mapping on protocol and internal port // It will also periodically renew the mapping until the returned Mapping // -- or its parent NAT -- is Closed. // // May not succeed, and mappings may change over time; // NAT devices may not respect our port requests, and even lie. // Clients should not store the mapped results, but rather always // poll our object for the latest mappings. func (nat *NAT) NewMapping(maddr ma.Multiaddr) (Mapping, error) { if nat == nil { return nil, fmt.Errorf("no nat available") } network, addr, err := manet.DialArgs(maddr) if err != nil { return nil, fmt.Errorf("DialArgs failed on addr:", maddr.String()) } switch network { case "tcp", "tcp4", "tcp6": network = "tcp" case "udp", "udp4", "udp6": network = "udp" default: return nil, fmt.Errorf("transport not supported by NAT: %s", network) } intports := strings.Split(addr, ":")[1] intport, err := strconv.Atoi(intports) if err != nil { return nil, err } m := &mapping{ nat: nat, proto: network, intport: intport, intaddr: maddr, } m.proc = goprocess.WithTeardown(func() error { nat.rmMapping(m) return nil }) nat.addMapping(m) m.proc.AddChild(periodic.Every(MappingDuration/3, func(worker goprocess.Process) { nat.establishMapping(m) })) // do it once synchronously, so first mapping is done right away, and before exiting, // allowing users -- in the optimistic case -- to use results right after. nat.establishMapping(m) return m, nil }
// New constructs and sets up a new *BasicHost with given Network func New(net inet.Network, opts ...interface{}) *BasicHost { h := &BasicHost{ network: net, mux: msmux.NewMultistreamMuxer(), bwc: metrics.NewBandwidthCounter(), } h.proc = goprocess.WithTeardown(func() error { if h.natmgr != nil { h.natmgr.Close() } return h.Network().Close() }) // setup host services h.ids = identify.NewIDService(h) muxh := h.Mux().Handle handle := func(s inet.Stream) { muxh(s) } h.relay = relay.NewRelayService(h, handle) for _, o := range opts { switch o := o.(type) { case Option: switch o { case NATPortMap: h.natmgr = newNatManager(h) } case metrics.Reporter: h.bwc = o } } net.SetConnHandler(h.newConnHandler) net.SetStreamHandler(h.newStreamHandler) return h }
func newNatManager(host *BasicHost) *natManager { nmgr := &natManager{ host: host, ready: make(chan struct{}), proc: goprocess.WithParent(host.proc), } // teardown nmgr.proc = goprocess.WithTeardown(func() error { // on closing, unregister from network notifications. host.Network().StopNotify((*nmgrNetNotifiee)(nmgr)) return nil }) // host is our parent. close when host closes. host.proc.AddChild(nmgr.proc) // discover the nat. nmgr.discoverNAT() return nmgr }
// WithContextAndTeardown is a helper function to set teardown at initiation // of WithContext func WithContextAndTeardown(ctx context.Context, tf goprocess.TeardownFunc) goprocess.Process { p := goprocess.WithTeardown(tf) CloseAfterContext(p, ctx) return p }