Blame


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