commit 7464c340f8010cecdeafff2b5aa1fe44d5233f57
parent 0020dcd0a0e379bad363ac2aee9a8535fdde00f5
Author: Matsuda Kenji <info@mtkn.jp>
Date: Mon, 17 Jul 2023 15:25:08 +0900
add fidpool and sAttach
Diffstat:
| M | cmd/disk.go | | | 10 | +++++----- |
| M | fcall.go | | | 32 | +++++++++++++++++++++++++------- |
| M | fid.go | | | 59 | ++++++++++++++++++++++++++++++++++++++++++++++++----------- |
| M | server.go | | | 59 | +++++++++++++++++++++++++++++++++++++++++++++++------------ |
4 files changed, 125 insertions(+), 35 deletions(-)
diff --git a/cmd/disk.go b/cmd/disk.go
@@ -36,17 +36,17 @@ func main() {
log.Printf("accept connection: %v", err)
continue
}
- disk := os.DirFS(os.Args[1])
+ disk := os.DirFS(flag.Arg(0))
go handle(conn, disk)
}
}
func handle(conn net.Conn, disk fs.FS) {
srv := &lib9p.Srv{
- disk,
- 8 * 1024,
- conn,
- conn,
+ FS: disk,
+ MSize: 8 * 1024,
+ Reader: conn,
+ Writer: conn,
}
lib9p.Serve(srv)
diff --git a/fcall.go b/fcall.go
@@ -76,6 +76,12 @@ type Msg interface {
String() string
}
+type Req struct {
+ srv *Srv
+ ifcall Msg
+ ofcall Msg
+}
+
// bufMsg is Msg with just an array of bytes.
type bufMsg []byte
@@ -130,7 +136,7 @@ type TAuth []byte
func (msg TAuth) Size() uint32 { return gbit32(msg[0:4]) }
func (msg TAuth) Type() MsgType { return MsgType(msg[4]) }
func (msg TAuth) Tag() uint16 { return gbit16(msg[5:7]) }
-func (msg TAuth) AFid() Fid { return Fid(msg[7:11]) }
+func (msg TAuth) AFid() uint32 { return gbit32(msg[7:11]) }
func (msg TAuth) UName() string {
size := gbit16(msg[11:13])
return string(msg[13 : 13+size])
@@ -142,8 +148,12 @@ func (msg TAuth) AName() string {
}
func (msg TAuth) conv2M() []byte { return []byte(msg)[:msg.Size()] }
func (msg TAuth) String() string {
- return fmt.Sprintf("Tauth tag %d afid %v uname %s aname %s",
- msg.Tag(), msg.AFid(), msg.UName(), msg.AName())
+ afid := int64(msg.AFid())
+ if afid == int64(NOFID) {
+ afid = -1
+ }
+ return fmt.Sprintf("Tauth tag %d afid %d uname %s aname %s",
+ msg.Tag(), afid, msg.UName(), msg.AName())
}
type RAuth []byte
@@ -163,8 +173,8 @@ type TAttach []byte
func (msg TAttach) Size() uint32 { return gbit32(msg[0:4]) }
func (msg TAttach) Type() MsgType { return MsgType(msg[4]) }
func (msg TAttach) Tag() uint16 { return gbit16(msg[5:7]) }
-func (msg TAttach) Fid() Fid { return Fid(msg[7:11]) }
-func (msg TAttach) AFid() Fid { return Fid(msg[11:15]) }
+func (msg TAttach) Fid() uint32 { return gbit32(msg[7:11]) }
+func (msg TAttach) AFid() uint32 { return gbit32(msg[11:15]) }
func (msg TAttach) UName() string {
usize := gbit16(msg[15:17])
return string(msg[17 : 17+usize])
@@ -176,8 +186,16 @@ func (msg TAttach) AName() string {
}
func (msg TAttach) conv2M() []byte { return []byte(msg)[:msg.Size()] }
func (msg TAttach) String() string {
- return fmt.Sprintf("Tattach tag %d fid %v afid %v uname %s aname %s",
- msg.Tag(), msg.Fid(), msg.AFid(), msg.UName(), msg.AName())
+ fid := int64(msg.Fid())
+ if fid == int64(NOFID) {
+ fid = -1
+ }
+ afid := int64(msg.AFid())
+ if afid == int64(NOFID) {
+ afid = -1
+ }
+ return fmt.Sprintf("Tattach tag %d fid %d afid %d uname %s aname %s",
+ msg.Tag(), fid, afid, msg.UName(), msg.AName())
}
type RAttach []byte
diff --git a/fid.go b/fid.go
@@ -2,6 +2,7 @@ package lib9p
import (
"fmt"
+ "io/fs"
)
// QidType represents the type of Qid. the 'QT' prefix may be redundant.
@@ -18,22 +19,29 @@ const (
QTFILE = 0x00 /* type bits for plain file */
)
-type Req struct {
- srv *Srv
- ifcall Msg
- ofcall Msg
+type Fid struct {
+ Fid uint32
+ OMode int32 /* -1 = not open */
+ File fs.File
+ Uid string
+ Qid Qid
}
-type Fid []byte
-
const NOFID = ^uint32(0)
-func (f Fid) String() string {
- fn := int64(gbit32(f))
- if uint32(fn) == NOFID {
- fn = -1
+func newFid(fid uint32) *Fid {
+ f := new(Fid)
+ f.Fid = fid
+ f.OMode = -1
+ return f
+}
+
+func (f *Fid) String() string {
+ fid := int64(f.Fid)
+ if uint32(fid) == NOFID {
+ fid = -1
}
- return fmt.Sprintf("%d", fn)
+ return fmt.Sprintf("%d", fid)
}
type Qid []byte
@@ -66,3 +74,32 @@ func (q Qid) typeStr() string {
}
return s
}
+
+type FidPool struct {
+ m map[uint32]*Fid
+}
+
+func allocFidPool() *FidPool {
+ f := new(FidPool)
+ f.m = make(map[uint32]*Fid)
+ return f
+}
+
+func (pool *FidPool) lookupFid(fid uint32) *Fid {
+ return pool.m[fid]
+}
+
+func (pool *FidPool) allocFid(fid uint32) (*Fid, error) {
+ if _, ok := pool.m[fid]; ok {
+ return nil, fmt.Errorf("fid already in use.")
+ }
+ f := newFid(fid)
+ pool.m[fid] = f
+ return f, nil
+}
+
+func (pool *FidPool) removeFid(fid uint32) *Fid {
+ f := pool.lookupFid(fid)
+ delete(pool.m, fid)
+ return f
+}
diff --git a/server.go b/server.go
@@ -16,18 +16,20 @@ func Chatty() {
}
type Srv struct {
- FS fs.FS
- MSize uint32
- io.Reader
- io.Writer
+ FS fs.FS
+ MSize uint32
+ fPool *FidPool
+ Reader io.Reader
+ Writer io.Writer
}
func getReq(s *Srv) (*Req, error) {
var r Req
+ r.srv = s
- buf, err := read9PMsg(s)
+ buf, err := read9PMsg(s.Reader)
if err != nil {
- return nil, fmt.Errorf("read message: %v", err)
+ return &r, fmt.Errorf("read message: %v", err)
}
switch t := bufMsg(buf).Type(); t {
@@ -35,7 +37,7 @@ func getReq(s *Srv) (*Req, error) {
if chatty9P {
fmt.Fprintf(os.Stderr, "<-- %v\n", bufMsg(buf))
}
- return nil, fmt.Errorf("unknown message type %d", t)
+ return &r, fmt.Errorf("unknown message type %d", t)
case Tversion:
r.ifcall = TVersion(buf)
case Tattach:
@@ -43,7 +45,6 @@ func getReq(s *Srv) (*Req, error) {
case Tauth:
r.ifcall = TAuth(buf)
}
- r.srv = s
if chatty9P {
fmt.Fprintf(os.Stderr, "<-- %v\n", r.ifcall)
}
@@ -98,6 +99,40 @@ func rAuth(r *Req, err error) {
}
func sAttach(s *Srv, r *Req) {
+ ifcall, ok := r.ifcall.(TAttach)
+ if !ok {
+ panic("not TAttach")
+ }
+ if s.fPool == nil {
+ s.fPool = allocFidPool()
+ }
+ fid, err := s.fPool.allocFid(ifcall.Fid())
+ if err != nil {
+ respond(r, fmt.Errorf("duplicate fid"))
+ return
+ }
+
+ fid.File, err = s.FS.Open(".") // TODO: use aname
+ if err != nil {
+ respond(r, fmt.Errorf("unable to open file tree"))
+ return
+ }
+
+ fid.Uid = ifcall.UName()
+
+ qid := Qid(make([]byte, 13))
+ qid.SetType(QTDIR)
+ qid.SetVers(0)
+ qid.SetPath(0)
+ fid.Qid = qid
+
+ ofcall := RAttach(make([]byte, 4+1+2+13))
+ ofcall.SetSize(uint32(len(ofcall)))
+ ofcall.SetType(Rattach)
+ ofcall.SetTag(ifcall.Tag())
+ ofcall.SetQid(qid)
+ r.ofcall = ofcall
+
respond(r, nil)
}
@@ -118,7 +153,8 @@ func Serve(s *Srv) {
r, err := getReq(s)
if err != nil {
log.Printf("get req: %v\n", err)
- break
+ respond(r, fmt.Errorf("internal error"))
+ continue
}
switch r.ifcall.(type) {
default:
@@ -142,7 +178,7 @@ func respond(r *Req, err error) {
}
rError(r, err)
} else {
- rError(r, fmt.Errorf("unknown message type: %s", r.ofcall.Type()))
+ rError(r, fmt.Errorf("unknown message type: %d", r.ofcall.Type()))
}
case RVersion:
rVersion(r, err)
@@ -155,6 +191,5 @@ func respond(r *Req, err error) {
if chatty9P {
fmt.Fprintf(os.Stderr, "--> %s\n", r.ofcall)
}
- r.srv.Write(r.ofcall.conv2M())
-
+ r.srv.Writer.Write(r.ofcall.conv2M())
}