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 class MessageHeader { | 7 class MessageHeader { |
8 static const int kSimpleMessageSize = 16; | 8 static const int kSimpleMessageSize = 16; |
9 // TODO(yzshen): In order to work with other bindings which still interprets | 9 // TODO(yzshen): In order to work with other bindings which still interprets |
10 // the |version| field as |num_fields|, set it to version 2 for now. | 10 // the |version| field as |num_fields|, set it to version 2 for now. |
11 static const int kSimpleMessageVersion = 2; | 11 static const int kSimpleMessageVersion = 2; |
12 static const int kMessageWithRequestIdSize = 24; | 12 static const int kMessageWithRequestIdSize = 24; |
13 // TODO(yzshen): In order to work with other bindings which still interprets | 13 // TODO(yzshen): In order to work with other bindings which still interprets |
14 // the |version| field as |num_fields|, set it to version 3 for now. | 14 // the |version| field as |num_fields|, set it to version 3 for now. |
15 static const int kMessageWithRequestIdVersion = 3; | 15 static const int kMessageWithRequestIdVersion = 3; |
16 static const int kMessageTypeOffset = StructDataHeader.kHeaderSize; | 16 static const int kMessageTypeOffset = StructDataHeader.kHeaderSize; |
17 static const int kMessageFlagsOffset = kMessageTypeOffset + 4; | 17 static const int kMessageFlagsOffset = kMessageTypeOffset + 4; |
18 static const int kMessageRequestIdOffset = kMessageFlagsOffset + 4; | 18 static const int kMessageRequestIdOffset = kMessageFlagsOffset + 4; |
19 static const int kMessageExpectsResponse = 1 << 0; | 19 static const int kMessageExpectsResponse = 1 << 0; |
20 static const int kMessageIsResponse = 1 << 1; | 20 static const int kMessageIsResponse = 1 << 1; |
21 | 21 |
22 StructDataHeader _header; | 22 StructDataHeader _header; |
23 int type; | 23 int type; |
24 int flags; | 24 int flags; |
25 int requestId; | 25 int requestId; |
26 | 26 |
27 static bool mustHaveRequestId(int flags) => | 27 static bool mustHaveRequestId(int flags) => |
28 (flags & (kMessageExpectsResponse | kMessageIsResponse)) != 0; | 28 (flags & (kMessageExpectsResponse | kMessageIsResponse)) != 0; |
29 | 29 |
30 MessageHeader(this.type) : | 30 MessageHeader(this.type) |
31 _header = new StructDataHeader(kSimpleMessageSize, kSimpleMessageVersion), | 31 : _header = new StructDataHeader( |
32 flags = 0, | 32 kSimpleMessageSize, kSimpleMessageVersion), |
33 requestId = 0; | 33 flags = 0, |
| 34 requestId = 0; |
34 | 35 |
35 MessageHeader.withRequestId(this.type, this.flags, this.requestId) : | 36 MessageHeader.withRequestId(this.type, this.flags, this.requestId) |
36 _header = new StructDataHeader( | 37 : _header = new StructDataHeader( |
37 kMessageWithRequestIdSize, kMessageWithRequestIdVersion); | 38 kMessageWithRequestIdSize, kMessageWithRequestIdVersion); |
38 | 39 |
39 MessageHeader.fromMessage(Message message) { | 40 MessageHeader.fromMessage(Message message) { |
40 var decoder = new Decoder(message); | 41 var decoder = new Decoder(message); |
41 _header = decoder.decodeStructDataHeader(); | 42 _header = decoder.decodeStructDataHeader(); |
42 if (_header.size < kSimpleMessageSize) { | 43 if (_header.size < kSimpleMessageSize) { |
43 throw new MojoCodecError( | 44 throw new MojoCodecError('Incorrect message size. Got: ${_header.size} ' |
44 'Incorrect message size. Got: ${_header.size} ' | |
45 'wanted $kSimpleMessageSize'); | 45 'wanted $kSimpleMessageSize'); |
46 } | 46 } |
47 type = decoder.decodeUint32(kMessageTypeOffset); | 47 type = decoder.decodeUint32(kMessageTypeOffset); |
48 flags = decoder.decodeUint32(kMessageFlagsOffset); | 48 flags = decoder.decodeUint32(kMessageFlagsOffset); |
49 if (mustHaveRequestId(flags)) { | 49 if (mustHaveRequestId(flags)) { |
50 if (_header.size < kMessageWithRequestIdSize) { | 50 if (_header.size < kMessageWithRequestIdSize) { |
51 throw new MojoCodecError( | 51 throw new MojoCodecError('Incorrect message size. Got: ${_header.size} ' |
52 'Incorrect message size. Got: ${_header.size} ' | |
53 'wanted $kMessageWithRequestIdSize'); | 52 'wanted $kMessageWithRequestIdSize'); |
54 } | 53 } |
55 requestId = decoder.decodeUint64(kMessageRequestIdOffset); | 54 requestId = decoder.decodeUint64(kMessageRequestIdOffset); |
56 } else { | 55 } else { |
57 requestId = 0; | 56 requestId = 0; |
58 } | 57 } |
59 } | 58 } |
60 | 59 |
61 int get size => _header.size; | 60 int get size => _header.size; |
62 bool get hasRequestId => mustHaveRequestId(flags); | 61 bool get hasRequestId => mustHaveRequestId(flags); |
63 | 62 |
64 void encode(Encoder encoder) { | 63 void encode(Encoder encoder) { |
65 encoder.encodeStructDataHeader(_header); | 64 encoder.encodeStructDataHeader(_header); |
66 encoder.encodeUint32(type, kMessageTypeOffset); | 65 encoder.encodeUint32(type, kMessageTypeOffset); |
67 encoder.encodeUint32(flags, kMessageFlagsOffset); | 66 encoder.encodeUint32(flags, kMessageFlagsOffset); |
68 if (hasRequestId) { | 67 if (hasRequestId) { |
69 encoder.encodeUint64(requestId, kMessageRequestIdOffset); | 68 encoder.encodeUint64(requestId, kMessageRequestIdOffset); |
70 } | 69 } |
71 } | 70 } |
72 | 71 |
73 ServiceMessage get serviceMessage => new ServiceMessage(this); | |
74 | |
75 String toString() => "MessageHeader($_header, $type, $flags, $requestId)"; | 72 String toString() => "MessageHeader($_header, $type, $flags, $requestId)"; |
76 | 73 |
77 bool validateHeaderFlags(expectedFlags) => | 74 bool validateHeaderFlags(expectedFlags) => |
78 (flags & (kMessageExpectsResponse | kMessageIsResponse)) == expectedFlags; | 75 (flags & (kMessageExpectsResponse | kMessageIsResponse)) == expectedFlags; |
79 | 76 |
80 bool validateHeader(int expectedType, int expectedFlags) => | 77 bool validateHeader(int expectedType, int expectedFlags) => |
81 (type == expectedType) && validateHeaderFlags(expectedFlags); | 78 (type == expectedType) && validateHeaderFlags(expectedFlags); |
82 | 79 |
83 static void _validateDataHeader(StructDataHeader dataHeader) { | 80 static void _validateDataHeader(StructDataHeader dataHeader) { |
84 if (dataHeader.version < kSimpleMessageVersion) { | 81 if (dataHeader.version < kSimpleMessageVersion) { |
85 throw 'Incorrect version, expecting at least ' | 82 throw 'Incorrect version, expecting at least ' |
86 '$kSimpleMessageVersion, but got: ${dataHeader.version}.'; | 83 '$kSimpleMessageVersion, but got: ${dataHeader.version}.'; |
87 } | 84 } |
88 if (dataHeader.size < kSimpleMessageSize) { | 85 if (dataHeader.size < kSimpleMessageSize) { |
89 throw 'Incorrect message size, expecting at least $kSimpleMessageSize, ' | 86 throw 'Incorrect message size, expecting at least $kSimpleMessageSize, ' |
90 'but got: ${dataHeader.size}'; | 87 'but got: ${dataHeader.size}'; |
91 } | 88 } |
92 if ((dataHeader.version == kSimpleMessageVersion) && | 89 if ((dataHeader.version == kSimpleMessageVersion) && |
93 (dataHeader.size != kSimpleMessageSize)) { | 90 (dataHeader.size != kSimpleMessageSize)) { |
94 throw 'Incorrect message size for a message of version ' | 91 throw 'Incorrect message size for a message of version ' |
95 '$kSimpleMessageVersion, expecting $kSimpleMessageSize, ' | 92 '$kSimpleMessageVersion, expecting $kSimpleMessageSize, ' |
96 'but got ${dataHeader.size}'; | 93 'but got ${dataHeader.size}'; |
97 } | 94 } |
98 if ((dataHeader.version == kMessageWithRequestIdVersion) && | 95 if ((dataHeader.version == kMessageWithRequestIdVersion) && |
99 (dataHeader.size != kMessageWithRequestIdSize)) { | 96 (dataHeader.size != kMessageWithRequestIdSize)) { |
100 throw 'Incorrect message size for a message of version ' | 97 throw 'Incorrect message size for a message of version ' |
101 '$kMessageWithRequestIdVersion, expecting ' | 98 '$kMessageWithRequestIdVersion, expecting ' |
102 '$kMessageWithRequestIdSize, but got ${dataHeader.size}'; | 99 '$kMessageWithRequestIdSize, but got ${dataHeader.size}'; |
103 } | 100 } |
104 } | 101 } |
105 } | 102 } |
106 | 103 |
107 | |
108 class Message { | 104 class Message { |
109 final ByteData buffer; | 105 final ByteData buffer; |
110 final List<core.MojoHandle> handles; | 106 final List<core.MojoHandle> handles; |
111 Message(this.buffer, this.handles); | 107 Message(this.buffer, this.handles); |
112 String toString() => | 108 String toString() => |
113 "Message(numBytes=${buffer.lengthInBytes}, numHandles=${handles.length})"; | 109 "Message(numBytes=${buffer.lengthInBytes}, numHandles=${handles.length})"; |
114 } | 110 } |
115 | 111 |
116 | |
117 class ServiceMessage extends Message { | 112 class ServiceMessage extends Message { |
118 final MessageHeader header; | 113 final MessageHeader header; |
119 Message _payload; | 114 Message _payload; |
120 | 115 |
121 ServiceMessage(Message message, this.header) | 116 ServiceMessage(Message message, this.header) |
122 : super(message.buffer, message.handles); | 117 : super(message.buffer, message.handles); |
123 | 118 |
124 ServiceMessage.fromMessage(Message message) | 119 ServiceMessage.fromMessage(Message message) |
125 : this(message, new MessageHeader.fromMessage(message)); | 120 : this(message, new MessageHeader.fromMessage(message)); |
126 | 121 |
127 Message get payload { | 122 Message get payload { |
128 if (_payload == null) { | 123 if (_payload == null) { |
129 var truncatedBuffer = new ByteData.view(buffer.buffer, header.size); | 124 var truncatedBuffer = new ByteData.view(buffer.buffer, header.size); |
130 _payload = new Message(truncatedBuffer, handles); | 125 _payload = new Message(truncatedBuffer, handles); |
131 } | 126 } |
132 return _payload; | 127 return _payload; |
133 } | 128 } |
134 | 129 |
135 String toString() => "ServiceMessage($header, $_payload)"; | 130 String toString() => "ServiceMessage($header, $_payload)"; |
136 } | 131 } |
OLD | NEW |