Blame


1 40d4a02d 2015-11-03 stephen.d package p9pnew
2 40d4a02d 2015-11-03 stephen.d
3 b714e9e0 2015-11-05 stephen.d import "golang.org/x/net/context"
4 40d4a02d 2015-11-03 stephen.d
5 b714e9e0 2015-11-05 stephen.d // Handler defines an interface for 9p message handlers. A handler
6 b714e9e0 2015-11-05 stephen.d // implementation could be used to intercept calls of all types before sending
7 b714e9e0 2015-11-05 stephen.d // them to the next handler.
8 b714e9e0 2015-11-05 stephen.d type Handler interface {
9 b714e9e0 2015-11-05 stephen.d Handle(ctx context.Context, msg Message) (Message, error)
10 40d4a02d 2015-11-03 stephen.d
11 b714e9e0 2015-11-05 stephen.d // TODO(stevvooe): Right now, this interface is functianally identical to
12 b714e9e0 2015-11-05 stephen.d // roundtripper. If we find that this is sufficient on the server-side, we
13 b714e9e0 2015-11-05 stephen.d // may unify the types. For now, we leave them separated to differentiate
14 b714e9e0 2015-11-05 stephen.d // between them.
15 40d4a02d 2015-11-03 stephen.d }
16 40d4a02d 2015-11-03 stephen.d
17 b714e9e0 2015-11-05 stephen.d // HandlerFunc is a convenience type for defining inline handlers.
18 b714e9e0 2015-11-05 stephen.d type HandlerFunc func(ctx context.Context, msg Message) (Message, error)
19 b714e9e0 2015-11-05 stephen.d
20 b714e9e0 2015-11-05 stephen.d func (fn HandlerFunc) Handle(ctx context.Context, msg Message) (Message, error) {
21 b714e9e0 2015-11-05 stephen.d return fn(ctx, msg)
22 40d4a02d 2015-11-03 stephen.d }
23 40d4a02d 2015-11-03 stephen.d
24 b714e9e0 2015-11-05 stephen.d // Dispatch returns a handler that dispatches messages to the target session.
25 b714e9e0 2015-11-05 stephen.d // No concurrency is managed by the returned handler. It simply turns messages
26 b714e9e0 2015-11-05 stephen.d // into function calls on the session.
27 b714e9e0 2015-11-05 stephen.d func Dispatch(session Session) Handler {
28 b714e9e0 2015-11-05 stephen.d return HandlerFunc(func(ctx context.Context, msg Message) (Message, error) {
29 b714e9e0 2015-11-05 stephen.d switch msg := msg.(type) {
30 b714e9e0 2015-11-05 stephen.d case MessageTauth:
31 b714e9e0 2015-11-05 stephen.d qid, err := session.Auth(ctx, msg.Afid, msg.Uname, msg.Aname)
32 b714e9e0 2015-11-05 stephen.d if err != nil {
33 b714e9e0 2015-11-05 stephen.d return nil, err
34 b714e9e0 2015-11-05 stephen.d }
35 40d4a02d 2015-11-03 stephen.d
36 b714e9e0 2015-11-05 stephen.d return MessageRauth{Qid: qid}, nil
37 b714e9e0 2015-11-05 stephen.d case MessageTattach:
38 b714e9e0 2015-11-05 stephen.d qid, err := session.Attach(ctx, msg.Fid, msg.Afid, msg.Uname, msg.Aname)
39 b714e9e0 2015-11-05 stephen.d if err != nil {
40 b714e9e0 2015-11-05 stephen.d return nil, err
41 b714e9e0 2015-11-05 stephen.d }
42 40d4a02d 2015-11-03 stephen.d
43 b714e9e0 2015-11-05 stephen.d return MessageRattach{
44 b714e9e0 2015-11-05 stephen.d Qid: qid,
45 b714e9e0 2015-11-05 stephen.d }, nil
46 b714e9e0 2015-11-05 stephen.d case MessageTwalk:
47 b714e9e0 2015-11-05 stephen.d // TODO(stevvooe): This is one of the places where we need to manage
48 b714e9e0 2015-11-05 stephen.d // fid allocation lifecycle. We need to reserve the fid, then, if this
49 b714e9e0 2015-11-05 stephen.d // call succeeds, we should alloc the fid for future uses. Also need
50 b714e9e0 2015-11-05 stephen.d // to interact correctly with concurrent clunk and the flush of this
51 b714e9e0 2015-11-05 stephen.d // walk message.
52 b714e9e0 2015-11-05 stephen.d qids, err := session.Walk(ctx, msg.Fid, msg.Newfid, msg.Wnames...)
53 b714e9e0 2015-11-05 stephen.d if err != nil {
54 b714e9e0 2015-11-05 stephen.d return nil, err
55 b714e9e0 2015-11-05 stephen.d }
56 40d4a02d 2015-11-03 stephen.d
57 b714e9e0 2015-11-05 stephen.d return MessageRwalk{
58 b714e9e0 2015-11-05 stephen.d Qids: qids,
59 b714e9e0 2015-11-05 stephen.d }, nil
60 b714e9e0 2015-11-05 stephen.d case MessageTopen:
61 b714e9e0 2015-11-05 stephen.d qid, iounit, err := session.Open(ctx, msg.Fid, msg.Mode)
62 b714e9e0 2015-11-05 stephen.d if err != nil {
63 b714e9e0 2015-11-05 stephen.d return nil, err
64 b714e9e0 2015-11-05 stephen.d }
65 40d4a02d 2015-11-03 stephen.d
66 b714e9e0 2015-11-05 stephen.d return MessageRopen{
67 b714e9e0 2015-11-05 stephen.d Qid: qid,
68 b714e9e0 2015-11-05 stephen.d IOUnit: iounit,
69 b714e9e0 2015-11-05 stephen.d }, nil
70 b714e9e0 2015-11-05 stephen.d case MessageTcreate:
71 b714e9e0 2015-11-05 stephen.d qid, iounit, err := session.Create(ctx, msg.Fid, msg.Name, msg.Perm, msg.Mode)
72 b714e9e0 2015-11-05 stephen.d if err != nil {
73 b714e9e0 2015-11-05 stephen.d return nil, err
74 b714e9e0 2015-11-05 stephen.d }
75 40d4a02d 2015-11-03 stephen.d
76 b714e9e0 2015-11-05 stephen.d return MessageRcreate{
77 b714e9e0 2015-11-05 stephen.d Qid: qid,
78 b714e9e0 2015-11-05 stephen.d IOUnit: iounit,
79 b714e9e0 2015-11-05 stephen.d }, nil
80 b714e9e0 2015-11-05 stephen.d case MessageTread:
81 b714e9e0 2015-11-05 stephen.d p := make([]byte, int(msg.Count))
82 b714e9e0 2015-11-05 stephen.d n, err := session.Read(ctx, msg.Fid, p, int64(msg.Offset))
83 b714e9e0 2015-11-05 stephen.d if err != nil {
84 b714e9e0 2015-11-05 stephen.d return nil, err
85 b714e9e0 2015-11-05 stephen.d }
86 40d4a02d 2015-11-03 stephen.d
87 b714e9e0 2015-11-05 stephen.d return MessageRread{
88 b714e9e0 2015-11-05 stephen.d Data: p[:n],
89 b714e9e0 2015-11-05 stephen.d }, nil
90 b714e9e0 2015-11-05 stephen.d case MessageTwrite:
91 b714e9e0 2015-11-05 stephen.d n, err := session.Write(ctx, msg.Fid, msg.Data, int64(msg.Offset))
92 b714e9e0 2015-11-05 stephen.d if err != nil {
93 b714e9e0 2015-11-05 stephen.d return nil, err
94 b714e9e0 2015-11-05 stephen.d }
95 40d4a02d 2015-11-03 stephen.d
96 b714e9e0 2015-11-05 stephen.d return MessageRwrite{
97 b714e9e0 2015-11-05 stephen.d Count: uint32(n),
98 b714e9e0 2015-11-05 stephen.d }, nil
99 b714e9e0 2015-11-05 stephen.d case MessageTclunk:
100 b714e9e0 2015-11-05 stephen.d // TODO(stevvooe): Manage the clunking of file descriptors based on
101 b714e9e0 2015-11-05 stephen.d // walk and attach call progression.
102 b714e9e0 2015-11-05 stephen.d if err := session.Clunk(ctx, msg.Fid); err != nil {
103 b714e9e0 2015-11-05 stephen.d return nil, err
104 b714e9e0 2015-11-05 stephen.d }
105 40d4a02d 2015-11-03 stephen.d
106 b714e9e0 2015-11-05 stephen.d return MessageRclunk{}, nil
107 b714e9e0 2015-11-05 stephen.d case MessageTremove:
108 b714e9e0 2015-11-05 stephen.d if err := session.Remove(ctx, msg.Fid); err != nil {
109 b714e9e0 2015-11-05 stephen.d return nil, err
110 b714e9e0 2015-11-05 stephen.d }
111 40d4a02d 2015-11-03 stephen.d
112 b714e9e0 2015-11-05 stephen.d return MessageRremove{}, nil
113 b714e9e0 2015-11-05 stephen.d case MessageTstat:
114 b714e9e0 2015-11-05 stephen.d dir, err := session.Stat(ctx, msg.Fid)
115 b714e9e0 2015-11-05 stephen.d if err != nil {
116 b714e9e0 2015-11-05 stephen.d return nil, err
117 b714e9e0 2015-11-05 stephen.d }
118 40d4a02d 2015-11-03 stephen.d
119 b714e9e0 2015-11-05 stephen.d return MessageRstat{
120 b714e9e0 2015-11-05 stephen.d Stat: dir,
121 b714e9e0 2015-11-05 stephen.d }, nil
122 b714e9e0 2015-11-05 stephen.d case MessageTwstat:
123 b714e9e0 2015-11-05 stephen.d if err := session.WStat(ctx, msg.Fid, msg.Stat); err != nil {
124 b714e9e0 2015-11-05 stephen.d return nil, err
125 b714e9e0 2015-11-05 stephen.d }
126 40d4a02d 2015-11-03 stephen.d
127 b714e9e0 2015-11-05 stephen.d return MessageRwstat{}, nil
128 b714e9e0 2015-11-05 stephen.d default:
129 b714e9e0 2015-11-05 stephen.d return nil, ErrUnknownMsg
130 40d4a02d 2015-11-03 stephen.d }
131 b714e9e0 2015-11-05 stephen.d })
132 40d4a02d 2015-11-03 stephen.d }