func (ct *codecTransport) Dial(addr net.Addr) (codec.CarrierConn, error) { c, err := net.Dial("tcp", addr.String()) if err != nil { return nil, err } return newCodecConn(trace.NewFrame("hmac", "dial"), c.(*net.TCPConn), ct.key) }
func TestCodec(t *testing.T) { f := trace.NewFrame() sx := sandbox.NewUnreliableTransport(f.Refine("sandbox"), 5, 0, time.Second/3, time.Second/3) hx := chain.NewTransport(f.Refine("chain"), sx) fx := faithful.NewTransport(f.Refine("faithful"), hx) cx := codec.NewTransport(fx, codec.GobCodec{}) bx := NewTransport(f.Refine("session"), cx) // Sync ya, yb := make(chan int), make(chan int) // Accepter go func() { as := bx.Listen(sandbox.Addr("@")).AcceptSession() for i := 0; i < testN; i++ { go testAcceptConn(t, as, ya, yb) } }() // Dialer ds := bx.DialSession(sandbox.Addr("@"), nil) go func() { for i := 0; i < testN; i++ { go testDialConn(t, ds, ya, yb) } }() for i := 0; i < testN; i++ { <-yb } }
func TestBuffer(t *testing.T) { bfr := NewBuffer(trace.NewFrame("TestBuffer"), 2) bfr.Write(testSeqNo(0)) bfr.Write(testSeqNo(1)) bfr.Remove(1) bfr.Write(testSeqNo(2)) bfr.Seek(SeqNo(1)) // Read 1 chunk, seqno, err := bfr.Read() if err != nil { t.Fatalf("read (%s) or bad seqno", err) } if chunk != testSeqNo(1) || seqno != SeqNo(1) { t.Fatalf("chunk=%d seqno=%d; expecting %d", chunk, seqno, 1) } // Read 2 chunk, seqno, err = bfr.Read() if err != nil { t.Fatalf("read (%s)", err) } if chunk != testSeqNo(2) || seqno != SeqNo(2) { t.Fatalf("chunk=%d seqno=%d; expecting %d", chunk, seqno, 2) } bfr.Remove(2) bfr.Close() if _, _, err := bfr.Read(); err != io.EOF { t.Fatalf("u (%s)", err) } }
func TestConnOverTCP(t *testing.T) { frame := trace.NewFrame() x := tcp.Transport ready := make(chan int, 2) sent, recv := make(map[byte]struct{}), make(map[byte]struct{}) // Accepter endpoint go func() { l := NewListener(frame.Refine("listener"), x, tcp.Addr(":17222")) ready <- 1 // SYNC: Notify that listener is accepting testGreedyRead(t, l.Accept(), recv) ready <- 1 }() // Dialer endpoint <-ready // SYNC: Wait for listener to start accepting d := NewDialer(frame.Refine("dialer"), x) conn := d.Dial(tcp.Addr("localhost:17222")) testGreedyWrite(t, conn, sent) <-ready // SYNC: Wait for accepter goroutine to complete // Make sure all marked writes have been received if !reflect.DeepEqual(sent, recv) { t.Errorf("expected %#v, got %#v", sent, recv) failNow() } }
func (l listener) Accept() (net.Conn, error) { c, err := l.Listener.Accept() if err != nil { return nil, err } return &conn{trace.NewFrame("tcp", "acpt"), c}, nil }
func TestHalfConn(t *testing.T) { ready := make(chan int) f := trace.NewFrame("TestHalfConn") p, q := NewPipe(f.Refine("@r"), f.Refine("@w"), Addr("@r"), Addr("@w")) // Read goroutine go func() { defer func() { close(ready) }() b, err := ioutil.ReadAll(q) if err != nil { log.Printf("read all (%s)", err) t.Fatalf("read all (%s)", err) } if len(b) != N { t.Fatalf("bad length") } for i := 0; i < N; i++ { if b[i] != byte(i) { t.Fatalf("unexpected byte @%d", i) } } }() // Write logic for i := 0; i < N; i++ { if n, err := p.Write([]byte{byte(i)}); err != nil || n != 1 { t.Fatalf("write %d (%v)", n, err) } } if err := p.Close(); err != nil { t.Fatalf("close (%s)", err) } <-ready }
func (l codecListener) Accept() codec.CarrierConn { c, err := l.Listener.Accept() if err != nil { log.Printf("error accepting tcp connection: %v", err) return nil } return newCodecConn(trace.NewFrame("tcp", "acpt"), c.(*net.TCPConn)) }
func NewStructOverTCP() *blend.Transport { f := trace.NewFrame("tele") // Carrier x2 := tcp.CodecTransport // Codec x3 := codec.NewTransport(x2, codec.GobCodec{}) // Blend return blend.NewTransport(f.Refine("blend"), x3) }
func NewStructOverTCPWithHMAC(key []byte) *blend.Transport { f := trace.NewFrame("tele") // Carrier x2 := hmac.NewTransport(key) // Codec x3 := codec.NewTransport(x2, codec.GobCodec{}) // Blend return blend.NewTransport(f.Refine("blend"), x3) }
func TestReliable(t *testing.T) { sandbox := NewReliableTransport(trace.NewFrame("TestReliable")) ready := make(chan int) go func() { l, err := sandbox.Listen(Addr("x")) if err != nil { t.Fatalf("listen (%s)", err) } for i := 0; i < N; i++ { ready <- 1 //println("receiver", i) conn, err := l.Accept() if err != nil { t.Fatalf("accept (%s)", err) } r := make([]byte, 3) if _, err := conn.Read(r); err != nil { t.Fatalf("read (%s)", err) } if !reflect.DeepEqual([]byte{0, 1, 2}, r) { t.Fatalf("unexpected read") } var w []byte = []byte{0, 1, 2} if _, err := conn.Write(w); err != nil { t.Fatalf("write (%s)", err) } if err := conn.Close(); err != nil { t.Fatalf("close (%s)", err) } } ready <- 1 }() for i := 0; i < N; i++ { <-ready //println("sender", i) conn, err := sandbox.Dial(Addr("x")) if err != nil { t.Fatalf("dial (%s)", err) } var w []byte = []byte{0, 1, 2} if _, err := conn.Write(w); err != nil { t.Fatalf("write (%s)", err) } r := make([]byte, 3) if _, err := conn.Read(r); err != nil { t.Fatalf("read (%s)", err) } if err := conn.Close(); err != nil { t.Fatalf("close (%s)", err) } } <-ready }
func TestCodec(t *testing.T) { // Transport f := trace.NewFrame() // Carrier sx := sandbox.NewRandomUnreliableTransport(f.Refine("sandbox"), 3, 3, time.Second/4, time.Second/4) // Chain hx := chain.NewTransport(f.Refine("chain"), sx) // Faithful fx := faithful.NewTransport(f.Refine("faithful"), hx) // Codec cx := NewTransport(fx, GobCodec{}) // Sync y := make(chan int) // Accepter go func() { l := cx.Listen(sandbox.Addr("@")) for i := 0; i < testN; i++ { y <- 1 conn := l.Accept() msg := &testMsg{} if err := conn.Read(msg); err != nil { t.Fatalf("read (%s)", err) failNow() } if msg.Carry != i { t.Fatalf("check") failNow() } f.Printf("READ %d/%d CLOSING", i+1, testN) conn.Close() f.Printf("READ %d/%d √", i+1, testN) } y <- 1 }() // Dialer for i := 0; i < testN; i++ { <-y conn := cx.Dial(sandbox.Addr("@")) if err := conn.Write(&testMsg{i}); err != nil { t.Fatalf("write (%s)", err) failNow() } f.Printf("WRITE %d/%d CLOSING", i+1, testN) if err := conn.Close(); err != nil { t.Fatalf("close (%s)", err) failNow() } f.Printf("WRITE %d/%d √", i+1, testN) } <-y }
func NewServer(inAddr, outAddr string) (*Server, error) { t := tele.NewStructOverTCP() l := t.Listen(tcp.Addr(outAddr)) if outAddr == "" { outAddr = l.Addr().String() fmt.Println(outAddr) } srv := &Server{frame: trace.NewFrame("tele", "server"), tele: t, inAddr: inAddr, outAddr: outAddr} srv.frame.Bind(srv) go srv.loop(l) return srv, nil }
func NewStructOverTCP() *blend.Transport { f := trace.NewFrame("tele") // Carrier x0 := tcp.Transport // Chain x1 := chain.NewTransport(f.Refine("chain"), x0) // Faithful x2 := faithful.NewTransport(f.Refine("faithful"), x1) // Codec x3 := codec.NewTransport(x2, codec.GobCodec{}) // Blend return blend.NewTransport(f.Refine("blend"), x3) }
func (l *codecListener) Accept() codec.CarrierConn { for { c, err := l.Listener.Accept() if err != nil { log.Printf("error accepting tcp connection: %v", err) return nil } cc, err := newCodecConn(trace.NewFrame("hmac", "acpt"), c.(*net.TCPConn), l.key) if err != nil { continue } return cc } }
func (transport) Dial(addr net.Addr) (net.Conn, error) { c, err := net.Dial("tcp", addr.String()) if err != nil { operr, ok := err.(*net.OpError) if !ok { return nil, err } if operr.Temporary() { return nil, err } return nil, chain.ErrRIP } return &conn{trace.NewFrame("tcp", "dial"), c}, nil }
func TestUnreliable(t *testing.T) { f := trace.NewFrame("TestDropTail") q, p := NewSievePipe(f.Refine("@r"), f.Refine("@w"), Addr("@r"), Addr("@w"), N, N, 0, 0) // Read goroutine ready := make(chan int) go func() { defer func() { close(ready) }() b, err := ioutil.ReadAll(q) // We get io.ErrUnexpectedEOF because the closing eof{} is not transmitted properly if err != io.ErrUnexpectedEOF { t.Fatalf("read all (%s)", err) } if len(b) != N { t.Fatalf("bad length") } for i := 0; i < N; i++ { if b[i] != byte(i) { t.Fatalf("unexpected byte @%d", i) } } }() // The following writes go through for i := 0; i < N; i++ { if n, err := p.Write([]byte{byte(i)}); err != nil || n != 1 { t.Fatalf("write %d (%v)", n, err) } } // The following writes are all dropped silently for i := 0; i+1 < N; i++ { if n, err := p.Write([]byte{byte(i)}); err != nil || n != 1 { t.Fatalf("write %d (%v)", n, err) } } // The last write is dropped quietly and also returns the unexpected EOF /* if n, err := p.Write([]byte{N - 1}); err != io.ErrUnexpectedEOF || n != 1 { t.Fatalf("write expects error (%v), got (%v); expects len %d, got %d", io.ErrUnexpectedEOF, err, 1, n) } */ if err := p.Close(); err != nil { t.Fatalf("close (%s)", err) } <-ready }
func testConn(t *testing.T, mode testMode) { f := trace.NewFrame("testConn") f.Bind(&f) fsx := f.Refine("sandbox") fsx.Bind(&fsx) var x *sandbox.Transport if mode.Random { x = sandbox.NewRandomUnreliableTransport(fsx, mode.NOK, mode.NDrop, exp, exp) } else { x = sandbox.NewUnreliableTransport(fsx, mode.NOK, mode.NDrop, exp, exp) } ready := make(chan int, 3) // Accept side go func() { ax := NewTransport(f.Refine("faithful:a"), chain.NewTransport(f.Refine("chain:a"), x)) l := ax.Listen(sandbox.Addr("@")) ready <- 1 c := l.Accept() switch mode.Kind { case testDWAR: testRead(f, t, c, ready) case testDRAW: testWrite(f, t, c, ready) } }() // Dial side dx := NewTransport(f.Refine("faithful:d"), chain.NewTransport(f.Refine("chain:d"), x)) <-ready c := dx.Dial(sandbox.Addr("@")) setabrt(func() { dbg := c.Debug().(*sandbox.DebugInfo) dbg.Out.Abort() }) switch mode.Kind { case testDWAR: testWrite(f, t, c, ready) case testDRAW: testRead(f, t, c, ready) } _, _ = <-ready, <-ready // One from testRead and one from testWrite }
func testConn(t *testing.T, mode connMode) { // Transport frame := trace.NewFrame() var x Carrier if mode.Random { x = sandbox.NewRandomUnreliableTransport(frame.Refine("sandbox"), mode.NOK, mode.NDrop, 0, 0) } else { x = sandbox.NewUnreliableTransport(frame.Refine("sandbox"), mode.NOK, mode.NDrop, 0, 0) } // Signalling ready := make(chan int, 2) feedfwd := make(chan byte, mode.NWrite()+1) // Accepter endpoint go func() { defer func() { ready <- 1 // SYNC: Notify that accepter-side logic is done }() l := NewListener(frame.Refine("chain", "listener"), x, sandbox.Addr("")) ready <- 1 // SYNC: Notify that listener is accepting switch mode.Kind { case testDWAR: testRead(t, l.Accept(), feedfwd) case testDRAW: testWrite(t, l.Accept(), mode, feedfwd) default: panic("u") } }() // Dialer endpoint <-ready // SYNC: Wait for listener to start accepting d := NewDialer(frame.Refine("chain", "dialer"), x) conn := d.Dial(sandbox.Addr("")) switch mode.Kind { case testDWAR: testWrite(t, conn, mode, feedfwd) case testDRAW: testRead(t, conn, feedfwd) default: panic("u") } <-ready // SYNC: Wait for accepter goroutine to complete }
func TestClosure(t *testing.T) { const testK = 1 f := trace.NewFrame() sx := tcp.Transport hx := chain.NewTransport(f.Refine("chain"), sx) fx := faithful.NewTransport(f.Refine("faithful"), hx) cx := codec.NewTransport(fx, codec.GobCodec{}) bx := NewTransport(f.Refine("session"), cx) // Sync ya, yb := make(chan int), make(chan int) a, _ := net.ResolveTCPAddr("tcp", "127.0.0.1:40090") // Accepter go func() { as := bx.Listen(a).AcceptSession() for i := 0; i < testK; i++ { go testAcceptConn(t, as, ya, yb) } }() // Dialer ds := bx.DialSession(a, nil) go func() { for i := 0; i < testK; i++ { go testDialConn(t, ds, ya, yb) } }() for i := 0; i < testK; i++ { <-yb } ds.Close() println("hold a minute...") time.Sleep(time.Minute) println("now check that the test process has no open tcp connections...") time.Sleep(time.Minute) println("great.") }
func NewClient(inAddr, outAddr string) { cli := &Client{frame: trace.NewFrame("tele", "client"), outAddr: outAddr} cli.frame.Bind(cli) // Make teleport transport t := tele.NewStructOverTCP() // Listen on input TCP address l, err := net.Listen("tcp", inAddr) if err != nil { cli.frame.Printf("listen on teleport address %s (%s)", inAddr, err) os.Exit(1) } if inAddr == "" { inAddr = l.Addr().String() fmt.Println(inAddr) } cli.tele, cli.inAddr = t, inAddr go cli.loop(l) return }
// Authors: // 2013 Petar Maymounkov <*****@*****.**> // Package tcp implements a carrier transport over TCP. package tcp import ( "net" "strings" "github.com/gocircuit/circuit/kit/tele/chain" "github.com/gocircuit/circuit/kit/tele/trace" ) // Transport is a chain.Carrier over TCP. var Transport = transport{trace.NewFrame("tcp")} type transport struct { trace.Frame } func (transport) Listen(addr net.Addr) (net.Listener, error) { t := addr.String() if strings.Index(t, ":") < 0 { t = t + ":0" } l, err := net.Listen("tcp", t) if err != nil { return nil, err } return listener{l}, nil
// Package tcp implements carrier transports over TCP. package tcp import ( "bufio" "encoding/binary" "log" "net" "strings" "github.com/gocircuit/circuit/kit/tele/codec" "github.com/gocircuit/circuit/kit/tele/trace" ) // CodecTransport is a codec.Carrier over TCP. var CodecTransport = codecTransport{trace.NewFrame("tcp")} type codecTransport struct { trace.Frame } func (codecTransport) Listen(addr net.Addr) codec.CarrierListener { t := addr.String() if strings.Index(t, ":") < 0 { t = t + ":0" } l, err := net.Listen("tcp", t) if err != nil { return nil } return codecListener{l}
func NewTransport(key []byte) codec.CarrierTransport { return &codecTransport{ Frame: trace.NewFrame("hmac"), key: key, } }
func Proxy(legacy net.Conn, tele *blend.Conn) { p := &proxy{frame: trace.NewFrame("proxy"), legacy: legacy, tele: tele} p.frame.Bind(p) go p.legacy2tele() go p.tele2legacy() }