OLD | NEW |
(Empty) | |
| 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 |
| 3 # found in the LICENSE file. |
| 4 |
| 5 """Utility classes to handle sending and receiving messages.""" |
| 6 |
| 7 |
| 8 import weakref |
| 9 |
| 10 # pylint: disable=F0401 |
| 11 import mojo.system as system |
| 12 |
| 13 |
| 14 class Message(object): |
| 15 """A message for a message pipe. This contains data and handles.""" |
| 16 |
| 17 def __init__(self, data=None, handles=None): |
| 18 self.data = data |
| 19 self.handles = handles |
| 20 |
| 21 |
| 22 class MessageReceiver(object): |
| 23 """A class which implements this interface can receive Message objects.""" |
| 24 |
| 25 def Accept(self, message): |
| 26 """ |
| 27 Receive a Message. The MessageReceiver is allowed to mutate the message. |
| 28 |
| 29 Args: |
| 30 message: the received message. |
| 31 |
| 32 Returns: |
| 33 True if the message has been handled, False otherwise. |
| 34 """ |
| 35 raise NotImplementedError() |
| 36 |
| 37 |
| 38 class MessageReceiverWithResponder(MessageReceiver): |
| 39 """ |
| 40 A MessageReceiver that can also handle the response message generated from the |
| 41 given message. |
| 42 """ |
| 43 |
| 44 def AcceptWithResponder(self, message, responder): |
| 45 """ |
| 46 A variant on Accept that registers a MessageReceiver (known as the |
| 47 responder) to handle the response message generated from the given message. |
| 48 The responder's Accept method may be called as part of the call to |
| 49 AcceptWithResponder, or some time after its return. |
| 50 |
| 51 Args: |
| 52 message: the received message. |
| 53 responder: the responder that will receive the response. |
| 54 |
| 55 Returns: |
| 56 True if the message has been handled, False otherwise. |
| 57 """ |
| 58 raise NotImplementedError() |
| 59 |
| 60 |
| 61 class ConnectionErrorHandler(object): |
| 62 """ |
| 63 A ConnectionErrorHandler is notified of an error happening while using the |
| 64 bindings over message pipes. |
| 65 """ |
| 66 |
| 67 def OnError(self, result): |
| 68 raise NotImplementedError() |
| 69 |
| 70 |
| 71 class Connector(MessageReceiver): |
| 72 """ |
| 73 A Connector owns a message pipe and will send any received messages to the |
| 74 registered MessageReceiver. It also acts as a MessageReceiver and will send |
| 75 any message through the handle. |
| 76 |
| 77 The method Start must be called before the Connector will start listening to |
| 78 incoming messages. |
| 79 """ |
| 80 |
| 81 def __init__(self, handle): |
| 82 MessageReceiver.__init__(self) |
| 83 self._handle = handle |
| 84 self._cancellable = None |
| 85 self._incoming_message_receiver = None |
| 86 self._error_handler = None |
| 87 |
| 88 def __del__(self): |
| 89 if self._cancellable: |
| 90 self._cancellable() |
| 91 |
| 92 def SetIncomingMessageReceiver(self, message_receiver): |
| 93 """ |
| 94 Set the MessageReceiver that will receive message from the owned message |
| 95 pipe. |
| 96 """ |
| 97 self._incoming_message_receiver = message_receiver |
| 98 |
| 99 def SetErrorHandler(self, error_handler): |
| 100 """ |
| 101 Set the ConnectionErrorHandler that will be notified of errors on the owned |
| 102 message pipe. |
| 103 """ |
| 104 self._error_handler = error_handler |
| 105 |
| 106 def Start(self): |
| 107 assert not self._cancellable |
| 108 self._RegisterAsyncWaiterForRead() |
| 109 |
| 110 def Accept(self, message): |
| 111 result = self._handle.WriteMessage(message.data, message.handles) |
| 112 return result == system.RESULT_OK |
| 113 |
| 114 def _OnAsyncWaiterResult(self, result): |
| 115 self._cancellable = None |
| 116 if result == system.RESULT_OK: |
| 117 self._ReadOutstandingMessages() |
| 118 else: |
| 119 self._OnError(result) |
| 120 |
| 121 def _OnError(self, result): |
| 122 assert not self._cancellable |
| 123 if self._error_handler: |
| 124 self._error_handler.OnError(result) |
| 125 |
| 126 def _RegisterAsyncWaiterForRead(self) : |
| 127 assert not self._cancellable |
| 128 self._cancellable = self._handle.AsyncWait( |
| 129 system.HANDLE_SIGNAL_READABLE, |
| 130 system.DEADLINE_INDEFINITE, |
| 131 _WeakCallback(self._OnAsyncWaiterResult)) |
| 132 |
| 133 def _ReadOutstandingMessages(self): |
| 134 result = system.RESULT_OK |
| 135 while result == system.RESULT_OK: |
| 136 result = _ReadAndDispatchMessage(self._handle, |
| 137 self._incoming_message_receiver) |
| 138 if result == system.RESULT_SHOULD_WAIT: |
| 139 self._RegisterAsyncWaiterForRead() |
| 140 return |
| 141 self._OnError(result) |
| 142 |
| 143 |
| 144 def _WeakCallback(callback): |
| 145 func = callback.im_func |
| 146 self = callback.im_self |
| 147 if not self: |
| 148 return callback |
| 149 weak_self = weakref.ref(self) |
| 150 def Callback(*args, **kwargs): |
| 151 self = weak_self() |
| 152 if self: |
| 153 return func(self, *args, **kwargs) |
| 154 return Callback |
| 155 |
| 156 |
| 157 def _ReadAndDispatchMessage(handle, message_receiver): |
| 158 (result, _, sizes) = handle.ReadMessage() |
| 159 if result == system.RESULT_OK and message_receiver: |
| 160 message_receiver.Accept(Message(bytearray(), [])) |
| 161 if result != system.RESULT_RESOURCE_EXHAUSTED: |
| 162 return result |
| 163 (result, data, _) = handle.ReadMessage(bytearray(sizes[0])) |
| 164 if result == system.RESULT_OK and message_receiver: |
| 165 message_receiver.Accept(Message(data[0], data[1])) |
| 166 return result |
| 167 |
OLD | NEW |