lib9p

Go 9P library.
Log | Files | Refs | LICENSE

commit 7643de5da53a48e8235ef62d63d5c7f0007537bb
parent d00ed1bef534f12831fa61cfface30544097d550
Author: Matsuda Kenji <info@mtkn.jp>
Date:   Wed, 27 Dec 2023 15:29:46 +0900

change Server.Auth function

Diffstat:
Mauth_test.go | 59++++++++++++++++++++++++++++++-----------------------------
Mserver.go | 18++++++++++--------
Mserver2_test.go | 65++++++++++++++++++++++++++++-------------------------------------
3 files changed, 68 insertions(+), 74 deletions(-)

diff --git a/auth_test.go b/auth_test.go @@ -9,9 +9,6 @@ import ( "git.mtkn.jp/lib9p/testfs" ) -// TODO: this test sometimes fails. -// err: unknown fid, or err: not authenticated. -// maybe there is some race condition or something. func TestAuth(t *testing.T) { conn := testfs.SetupConn() defer conn.Close() @@ -23,33 +20,29 @@ func TestAuth(t *testing.T) { asr.Close() asw.Close() }() - conn.S.Auth = func(ctx context.Context, respc chan<- *lib9p.Req) chan<- *lib9p.Req { - authc := make(chan *lib9p.Req) - go func() { - for { - select { - case <-ctx.Done(): + conn.S.Auth = func(ctx context.Context, authc <-chan *lib9p.Req, respc chan<- *lib9p.Req) { + for { + select { + case <-ctx.Done(): + return + case r, ok := <-authc: + if !ok { return - case r, ok := <-authc: - if !ok { - return - } - ifcall := r.Ifcall.(*lib9p.TAuth) - aqid := lib9p.Qid{Type: lib9p.QTAUTH, Vers: 0, Path: ^uint64(0)} - r.Afid.File = &lib9p.AuthFile{ - Qid: aqid, - Uname: ifcall.Uname, - Aname: ifcall.Aname, - W: acw, - R: acr, - } - runAuth(ctx, t, r.Afid.File.(*lib9p.AuthFile), asr, asw) - r.Ofcall = &lib9p.RAuth{Tag: ifcall.Tag, Aqid: aqid} - respc <- r } + ifcall := r.Ifcall.(*lib9p.TAuth) + aqid := lib9p.Qid{Type: lib9p.QTAUTH, Vers: 0, Path: ^uint64(0)} + r.Afid.File = &lib9p.AuthFile{ + Qid: aqid, + Uname: ifcall.Uname, + Aname: ifcall.Aname, + W: acw, + R: acr, + } + runAuth(ctx, t, r.Afid.File.(*lib9p.AuthFile), asr, asw) + r.Ofcall = &lib9p.RAuth{Tag: ifcall.Tag, Aqid: aqid} + respc <- r } - }() - return authc + } } ctx := context.Background() _, _, err := conn.C.Version(ctx, lib9p.NOTAG, 8*1024, "9P2000") @@ -111,12 +104,20 @@ func runAuth(ctx context.Context, t *testing.T, afile *lib9p.AuthFile, r io.Read } case 1: // accepted afile.AuthOK = true - go func() { for { r.Read(buf) } }() + go func() { + for { + r.Read(buf) + } + }() for { w.Write([]byte("ok")) } case 2: // unknown user - go func() { for { r.Read(buf) } }() + go func() { + for { + r.Read(buf) + } + }() for { w.Write([]byte("unknown user")) } diff --git a/server.go b/server.go @@ -64,15 +64,16 @@ type Server struct { respChan chan *Req - // Auth function is passed an auth request when a TAuth message arrives. - // It should run a goroutine listeneing to the channel which the function - // returns and send processed *Req through the channel specified by the - // second argument. + // Auth function is passed an auth request via authc when a TAuth message + // arrives. It is called as a separate goroutine and should listen to + // authc and send processed *Req through respc. + // Don't close these channels. // If authentication is desired, the Auth goroutine should // set Req.Afid.File to an *AuthFile and Req.Ofcall.Qid, and prepare to - // authenticate via the Read()/Write() calls to Req.Afid.File + // authenticate via the Read()/Write() calls to Req.Afid.File. + // Auth goroutine should return when ctx is canceled. // If this is nil, no authentication is performed. - Auth func(context.Context, chan<- *Req) chan<- *Req + Auth func(ctx context.Context, authc <-chan *Req, respc chan<- *Req) } // NewServer creates a Server and runs listener and speaker goroutines. @@ -235,9 +236,10 @@ func sVersion(ctx context.Context, s *Server, c <-chan *Req) { // sAuth serves Tauth message. func sAuth(ctx context.Context, s *Server, c <-chan *Req) { - var authc chan<- *Req + var authc chan *Req if s.Auth != nil { - authc = s.Auth(ctx, s.respChan) + authc = make(chan *Req) + go s.Auth(ctx, authc, s.respChan) defer close(authc) } for { diff --git a/server2_test.go b/server2_test.go @@ -144,15 +144,15 @@ func TestGetReq(t *testing.T) { } func TestSVersion(t *testing.T) { - tests := []struct{ + tests := []struct { input *Req - want *Req + want *Req }{ {&Req{Ifcall: &TVersion{Msize: 1024, Version: "9P2000"}}, &Req{Ofcall: &RVersion{Msize: 1024, Version: "9P2000"}}}, {&Req{Ifcall: &TVersion{Msize: 564, Version: "9P2000"}}, &Req{Ofcall: &RVersion{Msize: 564, Version: "9P2000"}}}, - {&Req{Ifcall: &TVersion{Msize: 8*1024, Version: "9P2000"}}, + {&Req{Ifcall: &TVersion{Msize: 8 * 1024, Version: "9P2000"}}, &Req{Ofcall: &RVersion{Msize: 1024, Version: "9P2000"}}}, {&Req{Ifcall: &TVersion{Msize: 1024, Version: "unko"}}, &Req{Ofcall: &RVersion{Msize: 1024, Version: "unknown"}}}, @@ -183,55 +183,47 @@ func TestSVersion(t *testing.T) { } func TestSAuth(t *testing.T) { - tests := []struct{ - input *Req - want *Req - authFunc func(context.Context, chan<- *Req) chan<- *Req + tests := []struct { + input *Req + want *Req + authFunc func(context.Context, <-chan *Req, chan<- *Req) }{ {&Req{Ifcall: &TAuth{Afid: NOFID, Uname: "kenji", Aname: ""}}, &Req{Ofcall: &RError{Ename: errors.New("authentication not required")}}, nil}, {&Req{Ifcall: &TAuth{Afid: NOFID, Uname: "kenji", Aname: ""}}, &Req{Ofcall: &RError{Ename: errors.New("NOFID can't be used for afid")}}, - func(ctx context.Context, respc chan<- *Req) chan<- *Req { - authc := make(chan *Req) - go func() { - for { - select { - case r, ok := <-authc: - if !ok { - return - } - respc <- r - case <-ctx.Done(): + func(ctx context.Context, authc <-chan *Req, respc chan<- *Req) { + for { + select { + case r, ok := <-authc: + if !ok { return } + respc <- r + case <-ctx.Done(): + return } - }() - return authc + } }}, {&Req{Ifcall: &TAuth{Afid: 0, Uname: "kenji", Aname: ""}}, &Req{Ofcall: &RAuth{Tag: 0, Aqid: Qid{0, 1, 2}}}, - func(ctx context.Context, respc chan<- *Req) chan<- *Req { - authc := make(chan *Req) - go func() { - for { - select { - case r, ok := <-authc: - if !ok { - return - } - r.Ofcall = &RAuth{Tag: 0, Aqid: Qid{0, 1, 2}} - respc <- r - case <-ctx.Done(): + func(ctx context.Context, authc <-chan *Req, respc chan<- *Req) { + for { + select { + case r, ok := <-authc: + if !ok { return } + r.Ofcall = &RAuth{Tag: 0, Aqid: Qid{0, 1, 2}} + respc <- r + case <-ctx.Done(): + return } - }() - return authc + } }}, } for _, test := range tests { - func () { + func() { tc := make(chan *Req) rc := make(chan *Req) defer close(tc) @@ -264,4 +256,4 @@ func TestSAuth(t *testing.T) { } }() } -} -\ No newline at end of file +}