func NewTransport(frame trace.Frame, sub *codec.Transport) *Transport { t := &Transport{ frame: frame, sub: sub, Dialer: NewDialer(frame.Refine("dialer"), sub), } frame.Bind(t) return t }
// NewSievePipe returns the two net.Conn endpoints of a new bi-directional drop tail pipe. func NewSievePipe(f0, f1 trace.Frame, a0, a1 net.Addr, nok, ndrop int, expa, expb time.Duration) (p, q net.Conn) { a, b := NewHalfConn(f0), NewHalfConn(f1) ax, bx, xa, xb := newChan(), newChan(), newChan(), newChan() axk, bxk := newBackChan(), newBackChan() a.RecvFrom(xa, a1) b.RecvFrom(xb, a0) a.SendTo(ax, axk, a0) b.SendTo(bx, bxk, a1) ab, ba := StartSieve(f0.Refine("sieve"), f1.Refine("sieve"), ax, bx, xa, xb, axk, bxk, nok, ndrop, expa, expb) a.in, a.out = ba, ab b.in, b.out = ab, ba return a, b }
func NewConn(frame trace.Frame, under *chain.Conn) *Conn { // Only 1 needed in readLoop; get 3 just to be safe rch := make(chan interface{}, 3) // Capacity 1 (below) unblocks writeSync, invoked in readLoop right after a connection stitch // stitch is received, racing with a user write waiting on waitForLink. // In particular, if execUserWrite is waiting on waitForLink, it would prevent readLoop from // moving on to adopt the new connection. sch := make(chan *control, 1) // Abort channel ach := make(chan struct{}) // User-facing Conn c := &Conn{ frame: frame, sub: under, rch: rch, ach: ach, bfr: NewBuffer(frame.Refine("buffer"), MemoryCap), } c.frame.Bind(c) // readConn rc := &readConn{ frame: frame.Refine("R∞"), sub: c.sub, rch: rch, sch: sch, ach: ach, bfr: c.bfr, } rc.frame.Bind(rc) go rc.loop() // writeConn wc := &writeConn{ frame: frame.Refine("W∞"), sub: c.sub, bfr: c.bfr, sch: sch, } wc.frame.Bind(wc) go wc.loop() return c }