OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 part of bindings; | 5 part of bindings; |
6 | 6 |
7 abstract class Interface { | 7 abstract class Interface { |
8 core.MojoMessagePipeEndpoint _endpoint; | 8 core.MojoMessagePipeEndpoint _endpoint; |
9 core.MojoHandle _handle; | 9 core.MojoHandle _handle; |
10 List _sendQueue; | 10 List _sendQueue; |
11 bool _isOpen; | 11 bool _isOpen; |
12 | 12 |
13 Message handleMessage(MessageReader reader); | 13 Future<Message> handleMessage(MessageReader reader); |
14 | 14 |
15 Interface(this._endpoint) { | 15 Interface(core.MojoMessagePipeEndpoint endpoint) : |
16 _endpoint = endpoint, | |
17 _sendQueue = [], | |
18 _handle = new core.MojoHandle(endpoint.handle), | |
19 _isOpen = false; | |
20 | |
21 Interface.fromHandle(int handle) { | |
22 _endpoint = | |
23 new core.MojoMessagePipeEndpoint(new core.RawMojoHandle(handle)); | |
16 _sendQueue = []; | 24 _sendQueue = []; |
17 _handle = new core.MojoHandle(_endpoint.handle); | 25 _handle = new core.MojoHandle(_endpoint.handle); |
18 _isOpen = false; | 26 _isOpen = false; |
19 } | 27 } |
20 | 28 |
29 void _doRead() { | |
30 assert(_handle.readyRead); | |
31 | |
32 // Query how many bytes are available. | |
33 var result = _endpoint.query(); | |
34 if (!result.status.isOk && !result.status.isResourceExhausted) { | |
35 // If something else happens, it means the handle wasn't really ready | |
36 // for reading, which indicates a bug in MojoHandle or the | |
37 // handle watcher. | |
38 throw "message pipe query failed: ${result.status} for $_handle"; | |
39 } | |
abarth-chromium
2015/01/04 08:46:07
If these conditions represent bugs, do we need to
zra
2015/01/05 15:45:41
No. Changed to asserts here and in client.dart.
| |
40 | |
41 // Read the data and view as a message. | |
42 var bytes = new ByteData(result.bytesRead); | |
43 var handles = new List<core.RawMojoHandle>(result.handlesRead); | |
44 result = _endpoint.read(bytes, result.bytesRead, handles); | |
45 if (!result.status.isOk && !result.status.isResourceExhausted) { | |
46 // If something else happens, it means the handle wasn't really ready | |
47 // for reading, which indicates a bug in MojoHandle or the | |
48 // handle watcher. | |
49 throw "message pipe read failed: ${result.status}"; | |
50 } | |
51 var message = new Message(bytes, handles); | |
52 var reader = new MessageReader(message); | |
53 | |
54 // Prepare the response. | |
55 var responseFuture = handleMessage(reader); | |
56 | |
57 // If there's a response, queue it up for sending. | |
58 if (responseFuture != null) { | |
59 responseFuture.then((response) { | |
60 _sendQueue.add(response); | |
61 if (_sendQueue.length == 1) { | |
62 _handle.enableWriteEvents(); | |
63 } | |
64 }); | |
65 } | |
66 } | |
67 | |
68 void _doWrite() { | |
69 if (_sendQueue.length > 0) { | |
70 assert(_handle.readyWrite); | |
71 var responseMessage = _sendQueue.removeAt(0); | |
72 _endpoint.write(responseMessage.buffer, | |
73 responseMessage.buffer.lengthInBytes, | |
74 responseMessage.handles); | |
75 if (!_endpoint.status.isOk) { | |
76 throw "message pipe write failed: ${_endpoint.status}"; | |
77 } | |
78 } | |
79 } | |
80 | |
21 StreamSubscription<int> listen() { | 81 StreamSubscription<int> listen() { |
22 _isOpen = true; | 82 _isOpen = true; |
23 return _handle.listen((int mojoSignal) { | 83 return _handle.listen((List<int> event) { |
24 if (core.MojoHandleSignals.isReadable(mojoSignal)) { | 84 var signalsWatched = new core.MojoHandleSignals(event[0]); |
25 // Query how many bytes are available. | 85 var signalsReceived = new core.MojoHandleSignals(event[1]); |
26 var result = _endpoint.query(); | 86 if (signalsReceived.isPeerClosed) { |
27 if (!result.status.isOk && !result.status.isResourceExhausted) { | 87 close(); |
28 // If something else happens, it means the handle wasn't really ready | 88 return; |
29 // for reading, which indicates a bug in MojoHandle or the | 89 } |
30 // event listener. | |
31 throw new Exception("message pipe query failed: ${result.status}"); | |
32 } | |
33 | 90 |
34 // Read the data and view as a message. | 91 if (signalsReceived.isReadable) { |
35 var bytes = new ByteData(result.bytesRead); | 92 _doRead(); |
36 var handles = new List<core.RawMojoHandle>(result.handlesRead); | 93 } |
37 result = _endpoint.read(bytes, result.bytesRead, handles); | |
38 if (!result.status.isOk && !result.status.isResourceExhausted) { | |
39 // If something else happens, it means the handle wasn't really ready | |
40 // for reading, which indicates a bug in MojoHandle or the | |
41 // event listener. | |
42 throw new Exception("message pipe read failed: ${result.status}"); | |
43 } | |
44 var message = new Message(bytes, handles); | |
45 var reader = new MessageReader(message); | |
46 | 94 |
47 // Prepare the response. | 95 if (signalsReceived.isWritable) { |
48 var responseMessage = handleMessage(reader); | 96 _doWrite(); |
49 // If there's a response, queue it up for sending. | |
50 if (responseMessage != null) { | |
51 _sendQueue.add(responseMessage); | |
52 if ((_sendQueue.length > 0) && !_handle.writeEnabled()) { | |
53 _handle.enableWriteEvents(); | |
54 } | |
55 } | |
56 } | 97 } |
57 if (core.MojoHandleSignals.isWritable(mojoSignal)) { | 98 |
58 if (_sendQueue.length > 0) { | 99 if (_sendQueue.length == 0) { |
59 var responseMessage = _sendQueue.removeAt(0); | 100 var withoutWritable = signalsWatched - core.MojoHandleSignals.WRITABLE; |
60 _endpoint.write(responseMessage.buffer, | 101 _handle.enableSignals(withoutWritable); |
61 responseMessage.buffer.lengthInBytes, | 102 } else { |
62 responseMessage.handles); | 103 _handle.enableSignals(signalsWatched); |
63 if (!_endpoint.status.isOk) { | |
64 throw new Exception("message pipe write failed"); | |
65 } | |
66 } | |
67 if ((_sendQueue.length == 0) && _handle.writeEnabled()) { | |
68 _handle.disableWriteEvents(); | |
69 } | |
70 } | |
71 if (core.MojoHandleSignals.isNone(mojoSignal)) { | |
72 // The handle watcher will send MojoHandleSignals.NONE when the other | |
73 // endpoint of the pipe is closed. | |
74 _handle.close(); | |
75 } | 104 } |
76 }); | 105 }); |
77 } | 106 } |
78 | 107 |
108 void close() { | |
109 // TODO(zra): Cancel outstanding Futures started in _doRead? | |
110 if (_isOpen) { | |
111 _handle.close(); | |
112 _isOpen = false; | |
113 _handle = null; | |
114 } | |
115 } | |
116 | |
79 Message buildResponse(Type t, int name, Object response) { | 117 Message buildResponse(Type t, int name, Object response) { |
80 var builder = new MessageBuilder(name, align(getEncodedSize(t))); | 118 var builder = new MessageBuilder(name, align(getEncodedSize(t))); |
81 builder.encodeStruct(t, response); | 119 builder.encodeStruct(t, response); |
82 return builder.finish(); | 120 return builder.finish(); |
83 } | 121 } |
84 | 122 |
85 Message buildResponseWithID( | 123 Message buildResponseWithID( |
86 Type t, int name, int id, int flags, Object response) { | 124 Type t, int name, int id, int flags, Object response) { |
87 var builder = new MessageWithRequestIDBuilder( | 125 var builder = new MessageWithRequestIDBuilder( |
88 name, align(getEncodedSize(t)), id, flags); | 126 name, align(getEncodedSize(t)), id, flags); |
89 builder.encodeStruct(t, response); | 127 builder.encodeStruct(t, response); |
90 return builder.finish(); | 128 return builder.finish(); |
91 } | 129 } |
92 | 130 |
93 void enqueueMessage(Type t, int name, Object msg) { | 131 void enqueueMessage(Type t, int name, Object msg) { |
94 var builder = new MessageBuilder(name, align(getEncodedSize(t))); | 132 var builder = new MessageBuilder(name, align(getEncodedSize(t))); |
95 builder.encodeStruct(t, msg); | 133 builder.encodeStruct(t, msg); |
96 var message = builder.finish(); | 134 var message = builder.finish(); |
97 _sendQueue.add(message); | 135 _sendQueue.add(message); |
98 if (!_handle.writeEnabled()) { | 136 _handle.enableWriteEvents(); |
99 _handle.enableWriteEvents(); | |
100 } | |
101 } | 137 } |
102 | 138 |
103 Future enqueueMessageWithRequestID(Type t, int name, int id, Object msg) { | 139 Future enqueueMessageWithRequestID(Type t, int name, int id, Object msg) { |
104 throw new Exception("The client Mixin should not expect a response"); | 140 // TODO(zra): Is this correct? |
141 throw "The client interface should not expect a response"; | |
105 } | 142 } |
106 | 143 |
107 bool get isOpen => _isOpen; | 144 bool get isOpen => _isOpen; |
145 core.MojoMessagePipeEndpoint get endpoint => _endpoint; | |
108 } | 146 } |
OLD | NEW |