lib9p

Go 9P library.
Log | Files | Refs

commit 17a641b963ac6b11c897f1d84621cfee74b602ed
parent 27938facf38b31090b0292c7495e811e3d9cde1a
Author: Matsuda Kenji <info@mtkn.jp>
Date:   Wed,  4 Oct 2023 11:09:56 +0900

mv chatty option into server struct

Diffstat:
Mclient.go | 82++++++++++++++++++++++++++++++++++++++++++++-----------------------------------
Mclient_test.go | 32++++++++++++++++++++++----------
Mcmd/disk.go | 6+++---
Mcmd/iofs.go | 6+++---
Mcmd/numfs.go | 6+++---
Mserver.go | 17+++++++----------
6 files changed, 84 insertions(+), 65 deletions(-)

diff --git a/client.go b/client.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "io" + "log" "sync" ) @@ -14,7 +15,6 @@ type Client struct { fPool *FidPool rPool *clientReqPool tmsgc chan<- Msg - terrc <-chan error rerrc <-chan error } @@ -26,7 +26,7 @@ func NewClient(mSize uint32, uname string, r io.Reader, w io.Writer) *Client { fPool: allocFidPool(), rPool: newClientReqPool(), } - c.tmsgc, c.terrc = c.runSpeaker(context.TODO(), w) + c.tmsgc = c.runSpeaker(context.TODO(), w) c.rerrc = c.runListener(context.TODO(), r) return c } @@ -77,27 +77,29 @@ func (c *Client) runListener(ctx context.Context, r io.Reader) <-chan error { return ec } -func (c *Client) runSpeaker(ctx context.Context, w io.Writer) (chan<- Msg, <-chan error) { +func (c *Client) runSpeaker(ctx context.Context, w io.Writer) chan<- Msg { mc := make(chan Msg) - ec := make(chan error) go func() { defer close(mc) - defer close(ec) for { select { case <-ctx.Done(): return case msg := <-mc: if err := send(msg, w); err != nil { - ec <- err + req, ok := c.rPool.lookup(msg.Tag()) + if !ok { + log.Printf("speaker: req not found. err: %v", err) + } + req.errc <- err } } } }() - return mc, ec + return mc } -// tag of tmsg is managed by this function. +// tag of tmsg is managed by the library. func (c *Client) transact(ctx context.Context, tmsg Msg) (<-chan Msg, <-chan error) { req, err := c.rPool.add(tmsg) if err != nil { @@ -115,39 +117,47 @@ func (c *Client) transact(ctx context.Context, tmsg Msg) (<-chan Msg, <-chan err return req.rmsgc, req.errc } -func (c *Client) Version(ctx context.Context, mSize uint32, version string) (<-chan *RVersion, <-chan error) { +func (c *Client) Version(ctx context.Context, mSize uint32, version string) (*RVersion, error) { tmsg := &TVersion{ - mSize: mSize, + mSize: mSize, version: version, } rmsgc, errc := c.transact(ctx, tmsg) - rmsgc1 := make(chan *RVersion, 1) - errc1 := make(chan error, 1) - go func() { - 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()) + select { + case rmsg := <-rmsgc: + switch rmsg := rmsg.(type) { + case *RVersion: + return rmsg, nil + case *RError: + return nil, rmsg.ename + default: + return nil, fmt.Errorf("invalid R message: %v", rmsg) } - }() - return rmsgc1, errc1 + case err := <-errc: + return nil, err + case <-ctx.Done(): + return nil, fmt.Errorf("wait transaction: %w", ctx.Err()) + } } -/* -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 + + +func (c *Client) Auth(ctx context.Context, afid uint32, uname, aname string) (*RAuth, error) { + tmsg := &TAuth{afid: afid, uname: uname} + rmsgc, errc := c.transact(ctx, tmsg) + select { + case rmsg := <-rmsgc: + switch rmsg := rmsg.(type) { + case *RAuth: + return rmsg, nil + case *RError: + return nil, rmsg.ename + default: + return nil, fmt.Errorf("invalid R message: %v", rmsg) + } + case err := <-errc: + return nil, err + case <-ctx.Done(): + return nil, fmt.Errorf("wait transaction: %w", ctx.Err()) + } } -*/ diff --git a/client_test.go b/client_test.go @@ -7,7 +7,24 @@ import ( "testing" ) -func TestServerVersion(t *testing.T) { +func TestTransaction(t *testing.T) { + const ( + mSize = 8192 + noTag = ^uint16(0) + ) + cr, sw := io.Pipe() + sr, cw := io.Pipe() + + server := NewServer(fsys, mSize, sr, sw) + Chatty() + client := NewClient(mSize, "kenji", cr, cw) + bg := context.Background() + go server.Serve() + + client.Version(bg, mSize, "9P2000") +} + +func TestClientVersion(t *testing.T) { const ( mSize = 8192 noTag = ^uint16(0) @@ -33,15 +50,10 @@ func TestServerVersion(t *testing.T) { server := NewServer(fsys, mSize, sr, sw) client := NewClient(mSize, "kenji", cr, cw) go server.Serve() - rvc, ec := client.Version(context.TODO(), test.mSize, test.version) - - var got *RVersion - select { - case got = <-rvc: - case err := <-ec: - t.Error(err) - } - if !reflect.DeepEqual(got, test.want) { + got, err := client.Version(context.TODO(), test.mSize, test.version) + if err != nil { + t.Errorf("%s: %v", test.name, err) + } else if !reflect.DeepEqual(got, test.want) { t.Errorf("%s: want %v, get %v\n", test.name, test.want, got) } } diff --git a/cmd/disk.go b/cmd/disk.go @@ -16,9 +16,6 @@ var dFlag = flag.Bool("D", false, "Prints chatty message to the stderr.") func main() { flag.Parse() - if *dFlag { - lib9p.Chatty() - } if flag.NArg() != 1 { fmt.Fprintf(os.Stderr, "usage: %s [-D] <root>\n", os.Args[0]) @@ -46,5 +43,8 @@ func main() { func handle(conn net.Conn, disk *diskfs.FS) { srv := lib9p.NewServer(disk, 8*1024, conn, conn) + if *dFlag { + srv.Chatty() + } srv.Serve() } diff --git a/cmd/iofs.go b/cmd/iofs.go @@ -16,9 +16,6 @@ var dFlag = flag.Bool("D", false, "Prints chatty message to the stderr.") func main() { flag.Parse() - if *dFlag { - lib9p.Chatty() - } if flag.NArg() != 1 { fmt.Fprintf(os.Stderr, "usage: %s [-D] <root>\n", os.Args[0]) @@ -44,5 +41,8 @@ func main() { func handle(conn net.Conn, disk *iofs.FS) { srv := lib9p.NewServer(disk, 8*1024, conn, conn) + if *dFlag { + srv.Chatty() + } srv.Serve() } diff --git a/cmd/numfs.go b/cmd/numfs.go @@ -149,9 +149,6 @@ var dFlag = flag.Bool("D", false, "Prints chatty message to the stderr.") func main() { flag.Parse() - if *dFlag { - lib9p.Chatty() - } if flag.NArg() != 0 { fmt.Fprintf(os.Stderr, "usage: %s [-D]\n", os.Args[0]) @@ -176,5 +173,8 @@ func main() { func handle(conn net.Conn, fs *numFS) { srv := lib9p.NewServer(fs, 8*1024, conn, conn) + if *dFlag { + srv.Chatty() + } srv.Serve() } diff --git a/server.go b/server.go @@ -10,12 +10,6 @@ import ( "sync" ) -var chatty9P = false - -func Chatty() { - chatty9P = true -} - var ( ErrBotch = fmt.Errorf("bocchi") ErrPerm = fmt.Errorf("permission denied") @@ -33,6 +27,7 @@ func setError(r *Req, err error) { } type Server struct { + chatty9P bool fs FS msize uint32 mSizeLock *sync.Mutex @@ -60,6 +55,8 @@ func NewServer(fsys FS, mSize uint32, r io.Reader, w io.Writer) *Server { return s } +func (s *Server) Chatty() { s.chatty9P = true } + func (s *Server) mSize() uint32 { s.mSizeLock.Lock() defer s.mSizeLock.Unlock() @@ -121,7 +118,7 @@ func getReq(r io.Reader, s *Server) (*Req, error) { log.Printf("unmarshal: %v", err) req.ifcall = bufMsg(buf) } - if chatty9P { + if s.chatty9P { fmt.Fprintf(os.Stderr, "<-- %v\n", req.ifcall) } return req, ErrDupTag @@ -132,14 +129,14 @@ func getReq(r io.Reader, s *Server) (*Req, error) { req.ifcall, err = unmarshal(buf) if err != nil { log.Printf("unmarshal: %v", err) - if chatty9P { + if s.chatty9P { fmt.Fprintf(os.Stderr, "<-- %v\n", bufMsg(buf)) } req.ifcall = bufMsg(buf) return req, err } - if chatty9P { + if s.chatty9P { fmt.Fprintf(os.Stderr, "<-- %v\n", req.ifcall) } return req, nil @@ -875,7 +872,7 @@ func respond(r *Req, err error) { log.Fatalf("speak: %v", err) }() - if chatty9P { + if r.srv.chatty9P { fmt.Fprintf(os.Stderr, "--> %s\n", r.ofcall) } }