Blame


1 8a7ec697 2015-10-26 adrien package p9pnew
2 8a7ec697 2015-10-26 adrien
3 8a7ec697 2015-10-26 adrien import (
4 8a7ec697 2015-10-26 adrien "fmt"
5 8a7ec697 2015-10-26 adrien "log"
6 8a7ec697 2015-10-26 adrien
7 8a7ec697 2015-10-26 adrien "golang.org/x/net/context"
8 8a7ec697 2015-10-26 adrien
9 8a7ec697 2015-10-26 adrien "net"
10 8a7ec697 2015-10-26 adrien )
11 8a7ec697 2015-10-26 adrien
12 8a7ec697 2015-10-26 adrien type client struct {
13 fb37ce2a 2015-10-30 stephen.d version string
14 fb37ce2a 2015-10-30 stephen.d msize uint32
15 e6bcde66 2015-10-29 stephen.d ctx context.Context
16 e6bcde66 2015-10-29 stephen.d transport roundTripper
17 8a7ec697 2015-10-26 adrien }
18 8a7ec697 2015-10-26 adrien
19 5f1e8105 2015-10-28 stephen.d // NewSession returns a session using the connection. The Context ctx provides
20 5f1e8105 2015-10-28 stephen.d // a context for out of bad messages, such as flushes, that may be sent by the
21 5f1e8105 2015-10-28 stephen.d // session. The session can effectively shutdown with this context.
22 5f1e8105 2015-10-28 stephen.d func NewSession(ctx context.Context, conn net.Conn) (Session, error) {
23 fb37ce2a 2015-10-30 stephen.d const msize = 64 << 10
24 fb37ce2a 2015-10-30 stephen.d const vers = "9P2000"
25 fb37ce2a 2015-10-30 stephen.d
26 fb37ce2a 2015-10-30 stephen.d ch := newChannel(conn, codec9p{}, msize) // sets msize, effectively.
27 fb37ce2a 2015-10-30 stephen.d
28 fb37ce2a 2015-10-30 stephen.d // negotiate the protocol version
29 3bf22e58 2015-11-04 stephen.d _, err := clientnegotiate(ctx, ch, vers)
30 fb37ce2a 2015-10-30 stephen.d if err != nil {
31 fb37ce2a 2015-10-30 stephen.d return nil, err
32 fb37ce2a 2015-10-30 stephen.d }
33 fb37ce2a 2015-10-30 stephen.d
34 8a7ec697 2015-10-26 adrien return &client{
35 fb37ce2a 2015-10-30 stephen.d version: vers,
36 fb37ce2a 2015-10-30 stephen.d msize: msize,
37 e6bcde66 2015-10-29 stephen.d ctx: ctx,
38 fb37ce2a 2015-10-30 stephen.d transport: newTransport(ctx, ch),
39 499f8c59 2015-10-27 stephen.d }, nil
40 8a7ec697 2015-10-26 adrien }
41 8a7ec697 2015-10-26 adrien
42 8a7ec697 2015-10-26 adrien var _ Session = &client{}
43 8a7ec697 2015-10-26 adrien
44 fb37ce2a 2015-10-30 stephen.d func (c *client) Version() (uint32, string) {
45 fb37ce2a 2015-10-30 stephen.d return c.msize, c.version
46 fb37ce2a 2015-10-30 stephen.d }
47 fb37ce2a 2015-10-30 stephen.d
48 8a7ec697 2015-10-26 adrien func (c *client) Auth(ctx context.Context, afid Fid, uname, aname string) (Qid, error) {
49 8a7ec697 2015-10-26 adrien panic("not implemented")
50 8a7ec697 2015-10-26 adrien }
51 8a7ec697 2015-10-26 adrien
52 8a7ec697 2015-10-26 adrien func (c *client) Attach(ctx context.Context, fid, afid Fid, uname, aname string) (Qid, error) {
53 e6bcde66 2015-10-29 stephen.d log.Println("client attach", fid, aname)
54 5f1e8105 2015-10-28 stephen.d fcall := &Fcall{
55 5f1e8105 2015-10-28 stephen.d Type: Tattach,
56 5f1e8105 2015-10-28 stephen.d Message: &MessageTattach{
57 5f1e8105 2015-10-28 stephen.d Fid: fid,
58 5f1e8105 2015-10-28 stephen.d Afid: afid,
59 5f1e8105 2015-10-28 stephen.d Uname: uname,
60 5f1e8105 2015-10-28 stephen.d Aname: aname,
61 5f1e8105 2015-10-28 stephen.d },
62 5f1e8105 2015-10-28 stephen.d }
63 5f1e8105 2015-10-28 stephen.d
64 e6bcde66 2015-10-29 stephen.d resp, err := c.transport.send(ctx, fcall)
65 5f1e8105 2015-10-28 stephen.d if err != nil {
66 5f1e8105 2015-10-28 stephen.d return Qid{}, err
67 5f1e8105 2015-10-28 stephen.d }
68 5f1e8105 2015-10-28 stephen.d
69 5f1e8105 2015-10-28 stephen.d mrr, ok := resp.Message.(*MessageRattach)
70 5f1e8105 2015-10-28 stephen.d if !ok {
71 5f1e8105 2015-10-28 stephen.d return Qid{}, fmt.Errorf("invalid rpc response for attach message: %v", resp)
72 5f1e8105 2015-10-28 stephen.d }
73 5f1e8105 2015-10-28 stephen.d
74 5f1e8105 2015-10-28 stephen.d return mrr.Qid, nil
75 8a7ec697 2015-10-26 adrien }
76 8a7ec697 2015-10-26 adrien
77 8a7ec697 2015-10-26 adrien func (c *client) Clunk(ctx context.Context, fid Fid) error {
78 e6bcde66 2015-10-29 stephen.d fcall := newFcall(&MessageTclunk{
79 e6bcde66 2015-10-29 stephen.d Fid: fid,
80 e6bcde66 2015-10-29 stephen.d })
81 e6bcde66 2015-10-29 stephen.d
82 e6bcde66 2015-10-29 stephen.d resp, err := c.transport.send(ctx, fcall)
83 e6bcde66 2015-10-29 stephen.d if err != nil {
84 e6bcde66 2015-10-29 stephen.d return err
85 e6bcde66 2015-10-29 stephen.d }
86 e6bcde66 2015-10-29 stephen.d
87 e6bcde66 2015-10-29 stephen.d if resp.Type != Rclunk {
88 e6bcde66 2015-10-29 stephen.d return fmt.Errorf("incorrect response type: %v", resp)
89 e6bcde66 2015-10-29 stephen.d }
90 e6bcde66 2015-10-29 stephen.d
91 e6bcde66 2015-10-29 stephen.d return nil
92 8a7ec697 2015-10-26 adrien }
93 8a7ec697 2015-10-26 adrien
94 8a7ec697 2015-10-26 adrien func (c *client) Remove(ctx context.Context, fid Fid) error {
95 8a7ec697 2015-10-26 adrien panic("not implemented")
96 8a7ec697 2015-10-26 adrien }
97 8a7ec697 2015-10-26 adrien
98 8a7ec697 2015-10-26 adrien func (c *client) Walk(ctx context.Context, fid Fid, newfid Fid, names ...string) ([]Qid, error) {
99 5f1e8105 2015-10-28 stephen.d if len(names) > 16 {
100 e6bcde66 2015-10-29 stephen.d return nil, fmt.Errorf("too many elements in wname")
101 5f1e8105 2015-10-28 stephen.d }
102 5f1e8105 2015-10-28 stephen.d
103 5f1e8105 2015-10-28 stephen.d fcall := &Fcall{
104 5f1e8105 2015-10-28 stephen.d Type: Twalk,
105 5f1e8105 2015-10-28 stephen.d Message: &MessageTwalk{
106 5f1e8105 2015-10-28 stephen.d Fid: fid,
107 5f1e8105 2015-10-28 stephen.d Newfid: newfid,
108 e6bcde66 2015-10-29 stephen.d Wnames: names,
109 5f1e8105 2015-10-28 stephen.d },
110 5f1e8105 2015-10-28 stephen.d }
111 5f1e8105 2015-10-28 stephen.d
112 e6bcde66 2015-10-29 stephen.d resp, err := c.transport.send(ctx, fcall)
113 5f1e8105 2015-10-28 stephen.d if err != nil {
114 5f1e8105 2015-10-28 stephen.d return nil, err
115 5f1e8105 2015-10-28 stephen.d }
116 5f1e8105 2015-10-28 stephen.d
117 5f1e8105 2015-10-28 stephen.d mrr, ok := resp.Message.(*MessageRwalk)
118 5f1e8105 2015-10-28 stephen.d if !ok {
119 5f1e8105 2015-10-28 stephen.d return nil, fmt.Errorf("invalid rpc response for walk message: %v", resp)
120 5f1e8105 2015-10-28 stephen.d }
121 5f1e8105 2015-10-28 stephen.d
122 5f1e8105 2015-10-28 stephen.d return mrr.Qids, nil
123 8a7ec697 2015-10-26 adrien }
124 8a7ec697 2015-10-26 adrien
125 8a7ec697 2015-10-26 adrien func (c *client) Read(ctx context.Context, fid Fid, p []byte, offset int64) (n int, err error) {
126 5f1e8105 2015-10-28 stephen.d // TODO(stevvooe): Split up reads into multiple messages based on iounit.
127 5f1e8105 2015-10-28 stephen.d // For now, we just support full blast. I mean, why not?
128 5f1e8105 2015-10-28 stephen.d fcall := &Fcall{
129 5f1e8105 2015-10-28 stephen.d Type: Tread,
130 5f1e8105 2015-10-28 stephen.d Message: &MessageTread{
131 5f1e8105 2015-10-28 stephen.d Fid: fid,
132 5f1e8105 2015-10-28 stephen.d Offset: uint64(offset),
133 5f1e8105 2015-10-28 stephen.d Count: uint32(len(p)),
134 5f1e8105 2015-10-28 stephen.d },
135 5f1e8105 2015-10-28 stephen.d }
136 5f1e8105 2015-10-28 stephen.d
137 e6bcde66 2015-10-29 stephen.d resp, err := c.transport.send(ctx, fcall)
138 5f1e8105 2015-10-28 stephen.d if err != nil {
139 5f1e8105 2015-10-28 stephen.d return 0, err
140 5f1e8105 2015-10-28 stephen.d }
141 5f1e8105 2015-10-28 stephen.d
142 5f1e8105 2015-10-28 stephen.d mrr, ok := resp.Message.(*MessageRread)
143 5f1e8105 2015-10-28 stephen.d if !ok {
144 5f1e8105 2015-10-28 stephen.d return 0, fmt.Errorf("invalid rpc response for read message: %v", resp)
145 5f1e8105 2015-10-28 stephen.d }
146 5f1e8105 2015-10-28 stephen.d
147 5f1e8105 2015-10-28 stephen.d return copy(p, mrr.Data), nil
148 8a7ec697 2015-10-26 adrien }
149 8a7ec697 2015-10-26 adrien
150 8a7ec697 2015-10-26 adrien func (c *client) Write(ctx context.Context, fid Fid, p []byte, offset int64) (n int, err error) {
151 5f1e8105 2015-10-28 stephen.d // TODO(stevvooe): Split up writes into multiple messages based on iounit.
152 5f1e8105 2015-10-28 stephen.d // For now, we just support full blast. I mean, why not?
153 5f1e8105 2015-10-28 stephen.d fcall := &Fcall{
154 5f1e8105 2015-10-28 stephen.d Type: Twrite,
155 5f1e8105 2015-10-28 stephen.d Message: &MessageTwrite{
156 5f1e8105 2015-10-28 stephen.d Fid: fid,
157 5f1e8105 2015-10-28 stephen.d Offset: uint64(offset),
158 5f1e8105 2015-10-28 stephen.d Data: p,
159 5f1e8105 2015-10-28 stephen.d },
160 5f1e8105 2015-10-28 stephen.d }
161 5f1e8105 2015-10-28 stephen.d
162 e6bcde66 2015-10-29 stephen.d resp, err := c.transport.send(ctx, fcall)
163 5f1e8105 2015-10-28 stephen.d if err != nil {
164 5f1e8105 2015-10-28 stephen.d return 0, err
165 5f1e8105 2015-10-28 stephen.d }
166 5f1e8105 2015-10-28 stephen.d
167 97423e8b 2015-10-29 stephen.d mrr, ok := resp.Message.(*MessageRwrite)
168 5f1e8105 2015-10-28 stephen.d if !ok {
169 e6bcde66 2015-10-29 stephen.d return 0, fmt.Errorf("invalid rpc response for write message: %v", resp)
170 5f1e8105 2015-10-28 stephen.d }
171 5f1e8105 2015-10-28 stephen.d
172 5f1e8105 2015-10-28 stephen.d return int(mrr.Count), nil
173 8a7ec697 2015-10-26 adrien }
174 8a7ec697 2015-10-26 adrien
175 e6bcde66 2015-10-29 stephen.d func (c *client) Open(ctx context.Context, fid Fid, mode uint8) (Qid, uint32, error) {
176 e6bcde66 2015-10-29 stephen.d fcall := newFcall(&MessageTopen{
177 e6bcde66 2015-10-29 stephen.d Fid: fid,
178 e6bcde66 2015-10-29 stephen.d Mode: mode,
179 e6bcde66 2015-10-29 stephen.d })
180 e6bcde66 2015-10-29 stephen.d
181 e6bcde66 2015-10-29 stephen.d resp, err := c.transport.send(ctx, fcall)
182 e6bcde66 2015-10-29 stephen.d if err != nil {
183 e6bcde66 2015-10-29 stephen.d return Qid{}, 0, err
184 e6bcde66 2015-10-29 stephen.d }
185 e6bcde66 2015-10-29 stephen.d
186 97423e8b 2015-10-29 stephen.d respmsg, ok := resp.Message.(*MessageRopen)
187 e6bcde66 2015-10-29 stephen.d if !ok {
188 e6bcde66 2015-10-29 stephen.d return Qid{}, 0, fmt.Errorf("invalid rpc response for open message: %v", resp)
189 e6bcde66 2015-10-29 stephen.d }
190 e6bcde66 2015-10-29 stephen.d
191 fb37ce2a 2015-10-30 stephen.d return respmsg.Qid, respmsg.IOUnit, nil
192 8a7ec697 2015-10-26 adrien }
193 8a7ec697 2015-10-26 adrien
194 fb37ce2a 2015-10-30 stephen.d func (c *client) Create(ctx context.Context, parent Fid, name string, perm uint32, mode uint32) (Qid, uint32, error) {
195 8a7ec697 2015-10-26 adrien panic("not implemented")
196 8a7ec697 2015-10-26 adrien }
197 8a7ec697 2015-10-26 adrien
198 74ec7ac9 2015-10-30 stephen.d func (c *client) Stat(ctx context.Context, fid Fid) (Dir, error) {
199 74ec7ac9 2015-10-30 stephen.d fcall := newFcall(MessageTstat{Fid: fid})
200 74ec7ac9 2015-10-30 stephen.d
201 74ec7ac9 2015-10-30 stephen.d resp, err := c.transport.send(ctx, fcall)
202 74ec7ac9 2015-10-30 stephen.d if err != nil {
203 74ec7ac9 2015-10-30 stephen.d return Dir{}, err
204 74ec7ac9 2015-10-30 stephen.d }
205 74ec7ac9 2015-10-30 stephen.d
206 74ec7ac9 2015-10-30 stephen.d respmsg, ok := resp.Message.(*MessageRstat)
207 74ec7ac9 2015-10-30 stephen.d if !ok {
208 74ec7ac9 2015-10-30 stephen.d return Dir{}, fmt.Errorf("invalid rpc response for stat message: %v", resp)
209 74ec7ac9 2015-10-30 stephen.d }
210 74ec7ac9 2015-10-30 stephen.d
211 74ec7ac9 2015-10-30 stephen.d return respmsg.Stat, nil
212 8a7ec697 2015-10-26 adrien }
213 8a7ec697 2015-10-26 adrien
214 8a7ec697 2015-10-26 adrien func (c *client) WStat(context.Context, Fid, Dir) error {
215 8a7ec697 2015-10-26 adrien panic("not implemented")
216 8a7ec697 2015-10-26 adrien }
217 8a7ec697 2015-10-26 adrien
218 fb37ce2a 2015-10-30 stephen.d func (c *client) flush(ctx context.Context, tag Tag) error {
219 fb37ce2a 2015-10-30 stephen.d // TODO(stevvooe): We need to fire and forget flush messages when a call
220 fb37ce2a 2015-10-30 stephen.d // context gets cancelled.
221 fb37ce2a 2015-10-30 stephen.d
222 fb37ce2a 2015-10-30 stephen.d panic("not implemented")
223 fb37ce2a 2015-10-30 stephen.d }