commit 97423e8b7909c86abde24bd416798b1172759758 from: Stephen J Day date: Thu Oct 29 03:32:31 2015 UTC fs/p9p/new: ls and cat command now fully working Signed-off-by: Stephen J Day commit - e6bcde663b39a93941cfd4188a6378e2ac5b92b2 commit + 97423e8b7909c86abde24bd416798b1172759758 blob - 5993872f445220c17408dabd657bcfd53470ba28 blob + 49f36bf99fe75ae3bdfb40e35d93b4c68c440fac --- client.go +++ client.go @@ -145,7 +145,7 @@ func (c *client) Write(ctx context.Context, fid Fid, p return 0, err } - mrr, ok := resp.Message.(MessageRwrite) + mrr, ok := resp.Message.(*MessageRwrite) if !ok { return 0, fmt.Errorf("invalid rpc response for write message: %v", resp) } @@ -164,7 +164,7 @@ func (c *client) Open(ctx context.Context, fid Fid, mo return Qid{}, 0, err } - respmsg, ok := resp.Message.(MessageRopen) + respmsg, ok := resp.Message.(*MessageRopen) if !ok { return Qid{}, 0, fmt.Errorf("invalid rpc response for open message: %v", resp) } blob - 529dbcad3e754a2d6af8c32544adc0bfbc3d0c39 blob + 200e30422567e89a0b07142ec27544ad2d5364dc --- encoding.go +++ encoding.go @@ -6,6 +6,7 @@ import ( "io" "log" "reflect" + "strings" "time" ) @@ -318,7 +319,6 @@ func fields9p(v interface{}) ([]interface{}, error) { rv := reflect.Indirect(reflect.ValueOf(v)) if rv.Kind() != reflect.Struct { - panic("asdf") return nil, fmt.Errorf("cannot extract fields from non-struct: %v", rv) } @@ -345,15 +345,24 @@ func fields9p(v interface{}) ([]interface{}, error) { return elements, nil } -func pretty9p(w io.Writer, v interface{}) error { - switch v := v.(type) { - case *Fcall: - pretty9p(w, *v) - case Fcall: - fmt.Fprintf(w, "uint32(%v) %v(%v) ", size9p(v), v.Type, v.Tag) - pretty9p(w, v.Message) - fmt.Fprintln(w) +func string9p(v interface{}) string { + if v == nil { + return "nil" } - return nil + rv := reflect.Indirect(reflect.ValueOf(v)) + + if rv.Kind() != reflect.Struct { + panic("not a struct") + } + + var s string + + for i := 0; i < rv.NumField(); i++ { + f := rv.Field(i) + + s += fmt.Sprintf(" %v=%v", strings.ToLower(rv.Type().Field(i).Name), f) + } + + return s } blob - 76b8a9ae3ccc5c4a86aa70d2b232a1155dbd2f8f blob + 6e11cca7e4518ea4c56ec3c5b7877dce8cd47fb6 --- encoding_test.go +++ encoding_test.go @@ -67,7 +67,7 @@ func TestEncodeDecode(t *testing.T) { Message: &MessageTwalk{ Fid: 1010, Newfid: 1011, - Wname: []string{"a", "b", "c"}, + Wnames: []string{"a", "b", "c"}, }, }, marshaled: []byte{ blob - 6a21069e2335562348947f852752d1a70734bc25 blob + 6a1212e5299bf975367e1754ded62b3be8a88130 --- errors.go +++ errors.go @@ -41,7 +41,7 @@ type error9p struct { } func new9pError(s string) error { - return &error9p{Name: s} + return error9p{Name: s} } func (e error9p) Error() string { blob - 05d7d2c1a99ab94e8695ccc4740dedfda8d0371f blob + 9e03f7e1d58923ae84789c8cf90fab13bc7c9b6e --- fcall.go +++ fcall.go @@ -114,7 +114,7 @@ func newFcall(msg Message) *Fcall { } func (fc *Fcall) String() string { - return fmt.Sprintf("%8d %v(%v) %v", size9p(fc), fc.Type, fc.Tag, fc.Message) + return fmt.Sprintf("%8d %v(%v) %v", size9p(fc), fc.Type, fc.Tag, string9p(fc.Message)) } type Message interface { @@ -135,6 +135,7 @@ func newMessage(typ FcallType) (Message, error) { case Tauth: case Rauth: + case Tattach: return &MessageTattach{}, nil case Rattach: @@ -144,7 +145,7 @@ func newMessage(typ FcallType) (Message, error) { case Tflush: return &MessageTflush{}, nil case Rflush: - return nil, nil // No message body for this response. + return &MessageRflush{}, nil // No message body for this response. case Twalk: return &MessageTwalk{}, nil case Rwalk: @@ -168,7 +169,7 @@ func newMessage(typ FcallType) (Message, error) { case Tclunk: return &MessageTclunk{}, nil case Rclunk: - return nil, nil // no response body + return &MessageRclunk{}, nil // no response body case Tremove: case Rremove: @@ -216,6 +217,8 @@ type MessageTflush struct { Oldtag Tag } +type MessageRflush struct{} + type MessageTattach struct { Fid Fid Afid Fid @@ -283,6 +286,8 @@ type MessageTclunk struct { Fid Fid } +type MessageRclunk struct{} + type MessageTremove struct { Fid Fid } @@ -306,6 +311,7 @@ func (MessageTauth) Type() FcallType { return Tauth func (MessageRauth) Type() FcallType { return Rauth } func (MessageRerror) Type() FcallType { return Rerror } func (MessageTflush) Type() FcallType { return Tflush } +func (MessageRflush) Type() FcallType { return Rflush } func (MessageTattach) Type() FcallType { return Tattach } func (MessageRattach) Type() FcallType { return Rattach } func (MessageTwalk) Type() FcallType { return Twalk } @@ -319,6 +325,7 @@ func (MessageRread) Type() FcallType { return Rread func (MessageTwrite) Type() FcallType { return Twrite } func (MessageRwrite) Type() FcallType { return Rwrite } func (MessageTclunk) Type() FcallType { return Tclunk } +func (MessageRclunk) Type() FcallType { return Rclunk } func (MessageTremove) Type() FcallType { return Tremove } func (MessageTstat) Type() FcallType { return Tstat } func (MessageRstat) Type() FcallType { return Rstat } blob - dce6821112555e7c268f22d5c2cbaa952dd1e991 blob + db1076f7a47a1f6a1475b98a52947c464adaccc5 --- server.go +++ server.go @@ -5,7 +5,6 @@ import ( "fmt" "log" "net" - "time" "golang.org/x/net/context" ) @@ -74,7 +73,7 @@ func (s *server) run() { } tags[fcall.Tag] = fcall - resp, err := s.handle(fcall) + resp, err := s.handle(s.ctx, fcall) if err != nil { log.Println("server:", err) continue @@ -91,11 +90,7 @@ func (s *server) run() { // handle responds to an fcall using the session. An error is only returned if // the handler cannot proceed. All session errors are returned as Rerror. -func (s *server) handle(req *Fcall) (*Fcall, error) { - const timeout = 30 * time.Second // TODO(stevvooe): Allow this to be configured. - ctx, cancel := context.WithTimeout(s.ctx, timeout) - defer cancel() - +func (s *server) handle(ctx context.Context, req *Fcall) (*Fcall, error) { var resp *Fcall switch req.Type { case Tattach: @@ -135,9 +130,53 @@ func (s *server) handle(req *Fcall) (*Fcall, error) { resp = newFcall(&MessageRwalk{ Qids: qids, }) + case Topen: + reqmsg, ok := req.Message.(*MessageTopen) + if !ok { + return nil, fmt.Errorf("bad message: %v message=%v", req, req.Message) + } + + qid, msize, err := s.session.Open(ctx, reqmsg.Fid, reqmsg.Mode) + if err != nil { + return nil, err + } + + resp = newFcall(&MessageRopen{ + Qid: qid, + Msize: msize, + }) + case Tread: + reqmsg, ok := req.Message.(*MessageTread) + if !ok { + return nil, fmt.Errorf("bad message: %v message=%v", req, req.Message) + } + + p := make([]byte, int(reqmsg.Count)) + n, err := s.session.Read(ctx, reqmsg.Fid, p, int64(reqmsg.Offset)) + if err != nil { + return nil, err + } + + resp = newFcall(&MessageRread{ + Data: p[:n], + }) + case Tclunk: + reqmsg, ok := req.Message.(*MessageTclunk) + if !ok { + return nil, fmt.Errorf("bad message: %v message=%v", req, req.Message) + } + + // TODO(stevvooe): Manage the clunking of file descriptors based on + // walk and attach call progression. + if err := s.session.Clunk(ctx, reqmsg.Fid); err != nil { + return nil, err + } + + resp = newFcall(&MessageRclunk{}) } if resp == nil { + log.Println("unknown message type:", req.Type) resp = newFcall(&MessageRerror{ Ename: "unknown message type", }) blob - 82c3b4b965eb8eeaaa15ad008456f41a203c091c blob + 7c956dd15cc2364349bdac627b8a8af380784de7 --- transport.go +++ transport.go @@ -5,7 +5,6 @@ import ( "fmt" "log" "net" - "os" "time" "golang.org/x/net/context" @@ -58,7 +57,6 @@ func newFcallRequest(ctx context.Context, fcall *Fcall } func (t *transport) send(ctx context.Context, fcall *Fcall) (*Fcall, error) { - req := newFcallRequest(ctx, fcall) log.Println("dispatch", fcall) @@ -79,6 +77,16 @@ func (t *transport) send(ctx context.Context, fcall *F case <-ctx.Done(): return nil, ctx.Err() case resp := <-req.response: + if resp.Type == Rerror { + // pack the error into something useful + respmesg, ok := resp.Message.(*MessageRerror) + if !ok { + return nil, fmt.Errorf("invalid error response: %v", resp) + } + + return nil, new9pError(respmesg.Ename) + } + return resp, nil } } @@ -153,7 +161,6 @@ func (t *transport) handle() { req.fcall.Tag = tags outstanding[req.fcall.Tag] = req - pretty9p(os.Stdout, req.fcall) // use deadline to set write deadline for this request. deadline, ok := req.ctx.Deadline() if !ok {