func ExampleDecoder() { l, err := net.Listen("tcp", ":564") if err != nil { log.Fatal(err) } rwc, err := l.Accept() if err != nil { log.Fatal(err) } d := styxproto.NewDecoder(rwc) e := styxproto.NewEncoder(rwc) for d.Next() { switch msg := d.Msg().(type) { case styxproto.Tversion: log.Printf("Client wants version %s", msg.Version()) e.Rversion(8192, "9P2000") case styxproto.Tread: e.Rread(msg.Tag(), []byte("data data")) case styxproto.Twrite: log.Printf("Receiving %d bytes from client", msg.Count()) io.Copy(ioutil.Discard, msg) } } }
func newConn(srv *Server, rwc io.ReadWriteCloser) *conn { var msize int64 = styxproto.DefaultMaxSize if srv.MaxSize > 0 { if srv.MaxSize > styxproto.MinBufSize { msize = srv.MaxSize } else { msize = styxproto.MinBufSize } } var enc *styxproto.Encoder var dec *styxproto.Decoder if srv.TraceLog != nil { enc = tracing.Encoder(rwc, func(m styxproto.Msg) { srv.TraceLog.Printf("← %03d %s", m.Tag(), m) }) dec = tracing.Decoder(rwc, func(m styxproto.Msg) { srv.TraceLog.Printf("→ %03d %s", m.Tag(), m) }) } else { enc = styxproto.NewEncoder(rwc) dec = styxproto.NewDecoder(rwc) } return &conn{ Decoder: dec, Encoder: enc, srv: srv, rwc: rwc, cx: context.TODO(), msize: msize, sessionFid: util.NewMap(), pendingReq: util.NewMap(), qidpool: qidpool.New(), } }
func copyMsg(msg styxproto.Msg) styxproto.Msg { var err error rd, wr := io.Pipe() d := styxproto.NewDecoder(rd) go func() { _, err = styxproto.Write(wr, msg) wr.CloseWithError(err) }() for d.Next() { return d.Msg() } panic(fmt.Errorf("failed to copy %T message: %s", msg, d.Err())) }
func messagesFrom(t *testing.T, r io.Reader) chan styxproto.Msg { c := make(chan styxproto.Msg) input := styxproto.NewDecoder(r) go func() { for input.Next() { if b, ok := input.Msg().(styxproto.BadMessage); ok { t.Logf("skipping bad message: %s", b.Err) } else { c <- copyMsg(input.Msg()) } } if input.Err() != nil { t.Error("error reading input: ", input.Err()) } close(c) }() return c }
func chanServer(t *testing.T, handler Handler) (in, out chan styxproto.Msg) { var ln netutil.PipeListener // last for one session srv := Server{ Handler: handler, ErrorLog: testLogger{t}, } go srv.Serve(&ln) conn, err := ln.Dial() if err != nil { panic(err) } // NOTE(droyo) by buffering the channel we allow the server to take // in multiple requests without being blocked on sending their responses. // This is a compromise between keeping the messages in order and having // an infinite buffer depth (such as with goroutine per channel). Good enough // for testing. out = make(chan styxproto.Msg, 1000) in = make(chan styxproto.Msg) go func() { for req := range in { if _, err := styxproto.Write(conn, req); err != nil { t.Error(err) break } } conn.Close() }() go func() { d := styxproto.NewDecoder(conn) for d.Next() { out <- copyMsg(d.Msg()) } close(out) }() return in, out }