Blame


1 40d4a02d 2015-11-03 stephen.d package p9pnew
2 40d4a02d 2015-11-03 stephen.d
3 40d4a02d 2015-11-03 stephen.d import (
4 40d4a02d 2015-11-03 stephen.d "fmt"
5 40d4a02d 2015-11-03 stephen.d
6 40d4a02d 2015-11-03 stephen.d "golang.org/x/net/context"
7 40d4a02d 2015-11-03 stephen.d )
8 40d4a02d 2015-11-03 stephen.d
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)
11 40d4a02d 2015-11-03 stephen.d }
12 40d4a02d 2015-11-03 stephen.d
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
16 40d4a02d 2015-11-03 stephen.d }
17 40d4a02d 2015-11-03 stephen.d
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)
27 40d4a02d 2015-11-03 stephen.d }
28 40d4a02d 2015-11-03 stephen.d
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
32 40d4a02d 2015-11-03 stephen.d }
33 40d4a02d 2015-11-03 stephen.d
34 40d4a02d 2015-11-03 stephen.d resp = newFcall(MessageRauth{Qid: qid})
35 40d4a02d 2015-11-03 stephen.d case Tattach:
36 40d4a02d 2015-11-03 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)
39 40d4a02d 2015-11-03 stephen.d }
40 40d4a02d 2015-11-03 stephen.d
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
44 40d4a02d 2015-11-03 stephen.d }
45 40d4a02d 2015-11-03 stephen.d
46 40d4a02d 2015-11-03 stephen.d resp = newFcall(MessageRattach{
47 40d4a02d 2015-11-03 stephen.d Qid: qid,
48 40d4a02d 2015-11-03 stephen.d })
49 40d4a02d 2015-11-03 stephen.d case Twalk:
50 40d4a02d 2015-11-03 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)
53 40d4a02d 2015-11-03 stephen.d }
54 40d4a02d 2015-11-03 stephen.d
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
63 40d4a02d 2015-11-03 stephen.d }
64 40d4a02d 2015-11-03 stephen.d
65 40d4a02d 2015-11-03 stephen.d resp = newFcall(&MessageRwalk{
66 40d4a02d 2015-11-03 stephen.d Qids: qids,
67 40d4a02d 2015-11-03 stephen.d })
68 40d4a02d 2015-11-03 stephen.d case Topen:
69 40d4a02d 2015-11-03 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)
72 40d4a02d 2015-11-03 stephen.d }
73 40d4a02d 2015-11-03 stephen.d
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
77 40d4a02d 2015-11-03 stephen.d }
78 40d4a02d 2015-11-03 stephen.d
79 40d4a02d 2015-11-03 stephen.d resp = newFcall(&MessageRopen{
80 40d4a02d 2015-11-03 stephen.d Qid: qid,
81 40d4a02d 2015-11-03 stephen.d IOUnit: iounit,
82 40d4a02d 2015-11-03 stephen.d })
83 40d4a02d 2015-11-03 stephen.d case Tcreate:
84 40d4a02d 2015-11-03 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)
87 40d4a02d 2015-11-03 stephen.d }
88 40d4a02d 2015-11-03 stephen.d
89 40d4a02d 2015-11-03 stephen.d qid, iounit, err := d.session.Create(ctx, reqmsg.Fid, reqmsg.Name, reqmsg.Perm, uint32(reqmsg.Mode))
90 40d4a02d 2015-11-03 stephen.d if err != nil {
91 40d4a02d 2015-11-03 stephen.d return nil, err
92 40d4a02d 2015-11-03 stephen.d }
93 40d4a02d 2015-11-03 stephen.d
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,
97 40d4a02d 2015-11-03 stephen.d })
98 40d4a02d 2015-11-03 stephen.d
99 40d4a02d 2015-11-03 stephen.d case Tread:
100 40d4a02d 2015-11-03 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)
103 40d4a02d 2015-11-03 stephen.d }
104 40d4a02d 2015-11-03 stephen.d
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
109 40d4a02d 2015-11-03 stephen.d }
110 40d4a02d 2015-11-03 stephen.d
111 40d4a02d 2015-11-03 stephen.d resp = newFcall(&MessageRread{
112 40d4a02d 2015-11-03 stephen.d Data: p[:n],
113 40d4a02d 2015-11-03 stephen.d })
114 40d4a02d 2015-11-03 stephen.d case Twrite:
115 40d4a02d 2015-11-03 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)
118 40d4a02d 2015-11-03 stephen.d }
119 40d4a02d 2015-11-03 stephen.d
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
123 40d4a02d 2015-11-03 stephen.d }
124 40d4a02d 2015-11-03 stephen.d
125 40d4a02d 2015-11-03 stephen.d resp = newFcall(&MessageRwrite{
126 40d4a02d 2015-11-03 stephen.d Count: uint32(n),
127 40d4a02d 2015-11-03 stephen.d })
128 40d4a02d 2015-11-03 stephen.d case Tclunk:
129 40d4a02d 2015-11-03 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)
132 40d4a02d 2015-11-03 stephen.d }
133 40d4a02d 2015-11-03 stephen.d
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
138 40d4a02d 2015-11-03 stephen.d }
139 40d4a02d 2015-11-03 stephen.d
140 40d4a02d 2015-11-03 stephen.d resp = newFcall(&MessageRclunk{})
141 40d4a02d 2015-11-03 stephen.d case Tremove:
142 40d4a02d 2015-11-03 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)
145 40d4a02d 2015-11-03 stephen.d }
146 40d4a02d 2015-11-03 stephen.d
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
149 40d4a02d 2015-11-03 stephen.d }
150 40d4a02d 2015-11-03 stephen.d
151 40d4a02d 2015-11-03 stephen.d resp = newFcall(&MessageRremove{})
152 40d4a02d 2015-11-03 stephen.d case Tstat:
153 40d4a02d 2015-11-03 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)
156 40d4a02d 2015-11-03 stephen.d }
157 40d4a02d 2015-11-03 stephen.d
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
161 40d4a02d 2015-11-03 stephen.d }
162 40d4a02d 2015-11-03 stephen.d
163 40d4a02d 2015-11-03 stephen.d resp = newFcall(&MessageRstat{
164 40d4a02d 2015-11-03 stephen.d Stat: dir,
165 40d4a02d 2015-11-03 stephen.d })
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
170 40d4a02d 2015-11-03 stephen.d }
171 40d4a02d 2015-11-03 stephen.d
172 40d4a02d 2015-11-03 stephen.d return resp, nil
173 40d4a02d 2015-11-03 stephen.d }