lib9p

Go 9P library.
Log | Files | Refs

commit 11053d7793b1f0299e8fbc104ef1d02d176bc0eb
parent 7d78089531ea3268e91a69014d9f72c7e3f616d0
Author: Matsuda Kenji <info@mtkn.jp>
Date:   Mon,  2 Oct 2023 11:27:33 +0900

change Client.Version

Diffstat:
Mclient.go | 76++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------
Mclient_test.go | 14++++++++------
2 files changed, 60 insertions(+), 30 deletions(-)

diff --git a/client.go b/client.go @@ -80,47 +80,75 @@ func (c *Client) runSpeaker(ctx context.Context, w io.Writer) (chan<- Msg, <-cha return mc, ec } -func transact(ctx context.Context, w io.Writer, r io.Reader, tmsg Msg) (<-chan Msg, error) { - if err := send(tmsg, w); err != nil { - return nil, fmt.Errorf("send: %v", err) - } - mc := make(chan Msg) +func transact(ctx context.Context, w io.Writer, r io.Reader, tmsg Msg) (<-chan Msg, <-chan error) { + err := send(tmsg, w) + rmsgc := make(chan Msg, 1) + errc := make(chan error, 1) go func() { - defer close(mc) - rmc := make(chan Msg) - var err error + defer close(rmsgc) + defer close(errc) + if err != nil { + errc <- err + return + } + + rmsgc1 := make(chan Msg, 1) + errc1 := make(chan error, 1) + // TODO: cancel recv() with ctx.Done() go func() { - defer close(rmc) - var rmsg Msg - rmsg, err = recv(r) + defer close(rmsgc1) + defer close(errc1) + rmsg, err := recv(r) if err != nil { + errc1 <- err return } - rmc <- rmsg + rmsgc1 <- rmsg }() select { - case rmsg := <-rmc: - mc <- rmsg + case rmsg := <-rmsgc1: + rmsgc <- rmsg + case err := <-errc1: + errc <- err case <-ctx.Done(): - return + errc <- fmt.Errorf("wait rmsg: %w", ctx.Err()) } }() - return mc, nil + return rmsgc, errc } -func (c *Client) Version(mSize uint32, version string) (<-chan *RVersion, error) { +func (c *Client) Version(ctx context.Context, mSize uint32, version string) (<-chan *RVersion, <-chan error) { tmsg := &TVersion{ tag: ^uint16(0), mSize: mSize, version: version, } - rmsgc, err := transact(context.TODO(), c.writer, c.reader, tmsg) - if err != nil { - return nil, err - } - rversionc := make(chan *RVersion) + rmsgc, errc := transact(ctx, c.writer, c.reader, tmsg) + rmsgc1 := make(chan *RVersion, 1) + errc1 := make(chan error, 1) go func() { - rversionc<- (<-rmsgc).(*RVersion) + defer close(rmsgc1) + defer close(errc1) + select { + case rmsg := <-rmsgc: + switch rmsg := rmsg.(type) { + case *RVersion: + rmsgc1<- rmsg + case *RError: + errc1<- rmsg.ename + default: + panic(fmt.Errorf("invalid R message: %v", rmsg)) + } + case err := <- errc: + errc1 <- err + case <- ctx.Done(): + errc1 <- fmt.Errorf("wait transact: %w", ctx.Err()) + } }() - return rversionc, nil + return rmsgc1, errc1 +} + +func (c *Client) Auth(ctx context.Context, afid uint32, uname, aname string) (<-chan *RAuth, <-chan error) { +// tmsg := &TAuth{afid: afid, uname: uname} + return nil, nil } \ No newline at end of file diff --git a/client_test.go b/client_test.go @@ -1,6 +1,7 @@ package lib9p import ( + "context" "io" "reflect" "testing" @@ -26,19 +27,20 @@ func TestServerVersion(t *testing.T) { } for _, test := range tests { - t.Logf("%v\n", test) cr, sw := io.Pipe() sr, cw := io.Pipe() server := NewServer(fsys, mSize, sr, sw) client := NewClient(mSize, "kenji", cr, cw) go server.Serve() - rvc, err := client.Version(test.mSize, test.version) - if err != nil { - t.Fatal(err) - } + rvc, ec := client.Version(context.TODO(), test.mSize, test.version) - got := <-rvc + var got *RVersion + select { + case got = <-rvc: + case err := <-ec: + t.Error(err) + } if !reflect.DeepEqual(got, test.want) { t.Errorf("%s: want %v, get %v\n", test.name, test.want, got) }