commit - e6bcde663b39a93941cfd4188a6378e2ac5b92b2
commit + 97423e8b7909c86abde24bd416798b1172759758
blob - 5993872f445220c17408dabd657bcfd53470ba28
blob + 49f36bf99fe75ae3bdfb40e35d93b4c68c440fac
--- client.go
+++ client.go
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)
}
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
"io"
"log"
"reflect"
+ "strings"
"time"
)
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)
}
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
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
}
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
}
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 {
case Tauth:
case Rauth:
+
case Tattach:
return &MessageTattach{}, nil
case Rattach:
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:
case Tclunk:
return &MessageTclunk{}, nil
case Rclunk:
- return nil, nil // no response body
+ return &MessageRclunk{}, nil // no response body
case Tremove:
case Rremove:
Oldtag Tag
}
+type MessageRflush struct{}
+
type MessageTattach struct {
Fid Fid
Afid Fid
Fid Fid
}
+type MessageRclunk struct{}
+
type MessageTremove struct {
Fid Fid
}
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 }
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
"fmt"
"log"
"net"
- "time"
"golang.org/x/net/context"
)
}
tags[fcall.Tag] = fcall
- resp, err := s.handle(fcall)
+ resp, err := s.handle(s.ctx, fcall)
if err != nil {
log.Println("server:", err)
continue
// 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:
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
"fmt"
"log"
"net"
- "os"
"time"
"golang.org/x/net/context"
}
func (t *transport) send(ctx context.Context, fcall *Fcall) (*Fcall, error) {
-
req := newFcallRequest(ctx, fcall)
log.Println("dispatch", fcall)
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
}
}
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 {