Commit Diff


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 {