1 40d4a02d 2015-11-03 stephen.d package p9pnew
3 40d4a02d 2015-11-03 stephen.d import (
6 40d4a02d 2015-11-03 stephen.d "golang.org/x/net/context"
9 40d4a02d 2015-11-03 stephen.d type handler interface {
10 40d4a02d 2015-11-03 stephen.d handle(ctx context.Context, req *Fcall) (*Fcall, error)
13 40d4a02d 2015-11-03 stephen.d // dispatcher routes fcalls to a Session.
14 40d4a02d 2015-11-03 stephen.d type dispatcher struct {
15 40d4a02d 2015-11-03 stephen.d session Session
18 40d4a02d 2015-11-03 stephen.d // handle responds to an fcall using the session. An error is only returned if
19 40d4a02d 2015-11-03 stephen.d // the handler cannot proceed. All session errors are returned as Rerror.
20 40d4a02d 2015-11-03 stephen.d func (d *dispatcher) handle(ctx context.Context, req *Fcall) (*Fcall, error) {
21 40d4a02d 2015-11-03 stephen.d var resp *Fcall
22 40d4a02d 2015-11-03 stephen.d switch req.Type {
23 40d4a02d 2015-11-03 stephen.d case Tauth:
24 40d4a02d 2015-11-03 stephen.d reqmsg, ok := req.Message.(MessageTauth)
25 40d4a02d 2015-11-03 stephen.d if !ok {
26 40d4a02d 2015-11-03 stephen.d return nil, fmt.Errorf("incorrect message for type: %v message=%v", req, req.Message)
29 40d4a02d 2015-11-03 stephen.d qid, err := d.session.Auth(ctx, reqmsg.Afid, reqmsg.Uname, reqmsg.Aname)
30 40d4a02d 2015-11-03 stephen.d if err != nil {
31 40d4a02d 2015-11-03 stephen.d return nil, err
34 40d4a02d 2015-11-03 stephen.d resp = newFcall(MessageRauth{Qid: qid})
35 40d4a02d 2015-11-03 stephen.d case Tattach:
36 deb98ab4 2015-11-05 stephen.d reqmsg, ok := req.Message.(MessageTattach)
37 40d4a02d 2015-11-03 stephen.d if !ok {
38 40d4a02d 2015-11-03 stephen.d return nil, fmt.Errorf("bad message: %v message=%#v", req, req.Message)
41 40d4a02d 2015-11-03 stephen.d qid, err := d.session.Attach(ctx, reqmsg.Fid, reqmsg.Afid, reqmsg.Uname, reqmsg.Aname)
42 40d4a02d 2015-11-03 stephen.d if err != nil {
43 40d4a02d 2015-11-03 stephen.d return nil, err
46 40d4a02d 2015-11-03 stephen.d resp = newFcall(MessageRattach{
47 40d4a02d 2015-11-03 stephen.d Qid: qid,
49 40d4a02d 2015-11-03 stephen.d case Twalk:
50 deb98ab4 2015-11-05 stephen.d reqmsg, ok := req.Message.(MessageTwalk)
51 40d4a02d 2015-11-03 stephen.d if !ok {
52 40d4a02d 2015-11-03 stephen.d return nil, fmt.Errorf("bad message: %v message=%#v", req, req.Message)
55 40d4a02d 2015-11-03 stephen.d // TODO(stevvooe): This is one of the places where we need to manage
56 40d4a02d 2015-11-03 stephen.d // fid allocation lifecycle. We need to reserve the fid, then, if this
57 40d4a02d 2015-11-03 stephen.d // call succeeds, we should alloc the fid for future uses. Also need
58 40d4a02d 2015-11-03 stephen.d // to interact correctly with concurrent clunk and the flush of this
59 40d4a02d 2015-11-03 stephen.d // walk message.
60 40d4a02d 2015-11-03 stephen.d qids, err := d.session.Walk(ctx, reqmsg.Fid, reqmsg.Newfid, reqmsg.Wnames...)
61 40d4a02d 2015-11-03 stephen.d if err != nil {
62 40d4a02d 2015-11-03 stephen.d return nil, err
65 deb98ab4 2015-11-05 stephen.d resp = newFcall(MessageRwalk{
66 40d4a02d 2015-11-03 stephen.d Qids: qids,
68 40d4a02d 2015-11-03 stephen.d case Topen:
69 deb98ab4 2015-11-05 stephen.d reqmsg, ok := req.Message.(MessageTopen)
70 40d4a02d 2015-11-03 stephen.d if !ok {
71 40d4a02d 2015-11-03 stephen.d return nil, fmt.Errorf("bad message: %v message=%v", req, req.Message)
74 40d4a02d 2015-11-03 stephen.d qid, iounit, err := d.session.Open(ctx, reqmsg.Fid, reqmsg.Mode)
75 40d4a02d 2015-11-03 stephen.d if err != nil {
76 40d4a02d 2015-11-03 stephen.d return nil, err
79 deb98ab4 2015-11-05 stephen.d resp = newFcall(MessageRopen{
80 40d4a02d 2015-11-03 stephen.d Qid: qid,
81 40d4a02d 2015-11-03 stephen.d IOUnit: iounit,
83 40d4a02d 2015-11-03 stephen.d case Tcreate:
84 deb98ab4 2015-11-05 stephen.d reqmsg, ok := req.Message.(MessageTcreate)
85 40d4a02d 2015-11-03 stephen.d if !ok {
86 40d4a02d 2015-11-03 stephen.d return nil, fmt.Errorf("bad message: %v message=%v", req, req.Message)
89 deb98ab4 2015-11-05 stephen.d qid, iounit, err := d.session.Create(ctx, reqmsg.Fid, reqmsg.Name, reqmsg.Perm, reqmsg.Mode)
90 40d4a02d 2015-11-03 stephen.d if err != nil {
91 40d4a02d 2015-11-03 stephen.d return nil, err
94 40d4a02d 2015-11-03 stephen.d resp = newFcall(&MessageRcreate{
95 40d4a02d 2015-11-03 stephen.d Qid: qid,
96 40d4a02d 2015-11-03 stephen.d IOUnit: iounit,
99 40d4a02d 2015-11-03 stephen.d case Tread:
100 deb98ab4 2015-11-05 stephen.d reqmsg, ok := req.Message.(MessageTread)
101 40d4a02d 2015-11-03 stephen.d if !ok {
102 40d4a02d 2015-11-03 stephen.d return nil, fmt.Errorf("bad message: %v message=%v", req, req.Message)
105 40d4a02d 2015-11-03 stephen.d p := make([]byte, int(reqmsg.Count))
106 40d4a02d 2015-11-03 stephen.d n, err := d.session.Read(ctx, reqmsg.Fid, p, int64(reqmsg.Offset))
107 40d4a02d 2015-11-03 stephen.d if err != nil {
108 40d4a02d 2015-11-03 stephen.d return nil, err
111 40d4a02d 2015-11-03 stephen.d resp = newFcall(&MessageRread{
112 40d4a02d 2015-11-03 stephen.d Data: p[:n],
114 40d4a02d 2015-11-03 stephen.d case Twrite:
115 deb98ab4 2015-11-05 stephen.d reqmsg, ok := req.Message.(MessageTwrite)
116 40d4a02d 2015-11-03 stephen.d if !ok {
117 40d4a02d 2015-11-03 stephen.d return nil, fmt.Errorf("bad message: %v message=%v", req, req.Message)
120 40d4a02d 2015-11-03 stephen.d n, err := d.session.Write(ctx, reqmsg.Fid, reqmsg.Data, int64(reqmsg.Offset))
121 40d4a02d 2015-11-03 stephen.d if err != nil {
122 40d4a02d 2015-11-03 stephen.d return nil, err
125 40d4a02d 2015-11-03 stephen.d resp = newFcall(&MessageRwrite{
126 40d4a02d 2015-11-03 stephen.d Count: uint32(n),
128 40d4a02d 2015-11-03 stephen.d case Tclunk:
129 deb98ab4 2015-11-05 stephen.d reqmsg, ok := req.Message.(MessageTclunk)
130 40d4a02d 2015-11-03 stephen.d if !ok {
131 40d4a02d 2015-11-03 stephen.d return nil, fmt.Errorf("bad message: %v message=%v", req, req.Message)
134 40d4a02d 2015-11-03 stephen.d // TODO(stevvooe): Manage the clunking of file descriptors based on
135 40d4a02d 2015-11-03 stephen.d // walk and attach call progression.
136 40d4a02d 2015-11-03 stephen.d if err := d.session.Clunk(ctx, reqmsg.Fid); err != nil {
137 40d4a02d 2015-11-03 stephen.d return nil, err
140 deb98ab4 2015-11-05 stephen.d resp = newFcall(MessageRclunk{})
141 40d4a02d 2015-11-03 stephen.d case Tremove:
142 deb98ab4 2015-11-05 stephen.d reqmsg, ok := req.Message.(MessageTremove)
143 40d4a02d 2015-11-03 stephen.d if !ok {
144 40d4a02d 2015-11-03 stephen.d return nil, fmt.Errorf("bad message: %v message=%v", req, req.Message)
147 40d4a02d 2015-11-03 stephen.d if err := d.session.Remove(ctx, reqmsg.Fid); err != nil {
148 40d4a02d 2015-11-03 stephen.d return nil, err
151 40d4a02d 2015-11-03 stephen.d resp = newFcall(&MessageRremove{})
152 40d4a02d 2015-11-03 stephen.d case Tstat:
153 deb98ab4 2015-11-05 stephen.d reqmsg, ok := req.Message.(MessageTstat)
154 40d4a02d 2015-11-03 stephen.d if !ok {
155 40d4a02d 2015-11-03 stephen.d return nil, fmt.Errorf("bad message: %v message=%v", req, req.Message)
158 40d4a02d 2015-11-03 stephen.d dir, err := d.session.Stat(ctx, reqmsg.Fid)
159 40d4a02d 2015-11-03 stephen.d if err != nil {
160 40d4a02d 2015-11-03 stephen.d return nil, err
163 deb98ab4 2015-11-05 stephen.d resp = newFcall(MessageRstat{
164 40d4a02d 2015-11-03 stephen.d Stat: dir,
166 40d4a02d 2015-11-03 stephen.d case Twstat:
167 40d4a02d 2015-11-03 stephen.d panic("not implemented")
168 40d4a02d 2015-11-03 stephen.d default:
169 40d4a02d 2015-11-03 stephen.d return nil, ErrUnknownMsg
172 40d4a02d 2015-11-03 stephen.d return resp, nil