Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | |
| 2 // for details. All rights reserved. Use of this source code is governed by a | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 /** | |
| 6 * Base class for all RpcProxy's | |
|
Siggi Cherem (dart-lang)
2011/11/11 23:41:51
generally use the dart-doc style through-out (e.g.
| |
| 7 * | |
| 8 * RpcProxy objects run in the "client" isolate and have a SendPort which | |
| 9 * they use to send messages to RpcReceiver objects running in a "service" | |
| 10 * isolate. | |
| 11 */ | |
| 12 | |
| 13 class RpcProxy { | |
| 14 final Future<SendPort> futurePort; | |
|
Ben Laurie (Google)
2011/11/11 21:51:43
_futurePort?
| |
| 15 RpcProxy(this.futurePort); | |
| 16 | |
| 17 /** | |
| 18 * Called by derived classes to send a command through a SendPort to | |
| 19 * an RpcReceiver. | |
| 20 * | |
| 21 * parameters: | |
| 22 * command - String identifying what command to execute | |
| 23 * args - optional list of arguments to the command (this may contain other | |
| 24 * RpcProxy objects to refer to other target objects in the service | |
| 25 * isolate). | |
|
Ben Laurie (Google)
2011/11/11 21:51:43
How does that work? I don't see code to send RpcPr
mattsh
2011/11/11 22:16:02
Right. That's not in this CL yet, but plan to add
Siggi Cherem (dart-lang)
2011/11/11 23:41:51
is the purpose of this to establish a bi-direction
| |
| 26 * | |
| 27 * returns: | |
| 28 * a Future object that will be set to the value that was | |
| 29 * received as a reply to the SendPort call. | |
| 30 */ | |
| 31 Future sendCommand(String command, List args) { | |
| 32 Completer completer = new Completer(); | |
| 33 futurePort.then((SendPort port) { | |
| 34 port.call({"command" : command, "args" : args}).receive((value, ignoreRe plyTo) { | |
|
Siggi Cherem (dart-lang)
2011/11/11 23:41:51
80
| |
| 35 assert(ignoreReplyTo === null); | |
| 36 value = _filterException(value); | |
| 37 if (value is Exception) { | |
| 38 completer.completeException(value); | |
| 39 } else { | |
| 40 completer.complete(value); | |
| 41 } | |
| 42 } | |
| 43 ); | |
| 44 }); | |
| 45 return completer.future; | |
| 46 } | |
| 47 | |
| 48 // TODO (mattsh) hack, remove once we have serializable exceptions | |
| 49 Object _filterException(Object value) { | |
| 50 // Check if value is a serialized exception. | |
| 51 Exception e = RpcException.parse(value); | |
| 52 if (e != null) { | |
| 53 return e; | |
| 54 } else { | |
| 55 return value; | |
| 56 } | |
| 57 } | |
| 58 } | |
| 59 | |
| 60 | |
| 61 | |
| 62 /** | |
| 63 * Base class for all Receivers | |
| 64 * | |
| 65 * RpcReceiver objects have a ReceivePort, where they receive commands (from | |
| 66 * RpcProxy objects) that they interpret and translate into method | |
| 67 * calls on a "target" object. | |
| 68 * | |
| 69 * All RpcReceiver derived classes must implement the [receiveCommand] abstract | |
| 70 * method (where they actually command messages and call | |
| 71 * appropriate methods on the target object). | |
| 72 * | |
| 73 */ | |
| 74 class RpcReceiver { | |
| 75 | |
| 76 // static map of containing all receivers in this isolate. This is used | |
| 77 // to be able to find a receiver and target, given a SendPort. | |
| 78 static Map<SendPort, RpcReceiver> _receivers; | |
| 79 static _register(RpcReceiver receiver) { | |
| 80 if (_receivers == null) { | |
| 81 _receivers = new Map<SendPort, RpcReceiver>(); | |
| 82 } | |
| 83 _receivers[receiver._receivePort.toSendPort()] = receiver; | |
| 84 } | |
| 85 | |
| 86 static void closeAll() { | |
| 87 for (RpcReceiver receiver in _receivers.getValues()) { | |
| 88 receiver._receivePort.close(); | |
| 89 } | |
| 90 } | |
| 91 | |
| 92 // the port that this receiver will listen on | |
| 93 final ReceivePort _receivePort; | |
| 94 | |
| 95 RpcReceiver(this._receivePort) { | |
| 96 // place this receiver in the receiver registry | |
| 97 _register(this); | |
| 98 | |
| 99 // start listening on the receive port for command messages | |
| 100 _receivePort.receive((var message, SendPort replyTo) { | |
| 101 String command = message["command"]; | |
| 102 List<Object> args = message["args"]; | |
| 103 | |
| 104 // Call the derived RpcReceiver to execute the command | |
| 105 // (if the command throws an exception, then catch the | |
| 106 // exception, serialize it, and send as the reply) | |
| 107 Object reply; | |
| 108 try { | |
| 109 reply = receiveCommand(message["command"], args); | |
| 110 } catch (Object e) { | |
| 111 reply = RpcException.format(e); | |
| 112 } | |
| 113 | |
| 114 // send reply back to the proxy | |
| 115 replyTo.send(reply, null); | |
| 116 }); | |
| 117 } | |
| 118 | |
| 119 /** | |
| 120 * (implemented by derived classes). | |
| 121 * | |
| 122 * parameters - | |
| 123 * command - String identifying what command to execute | |
| 124 * on the target object | |
| 125 * args - list of arguments to the command (if any arguments | |
| 126 * were ReceivePorts, these have been translated to the | |
| 127 * corresponding target objects, so this List79 will not | |
| 128 * contain any ReceivePorts) | |
| 129 */ | |
| 130 abstract Object receiveCommand(String command, List args); | |
| 131 } | |
| 132 | |
| 133 // TODO - hack - need better way to serialize exceptions. For now | |
| 134 // we take the message, and prefix with a recognizable string. | |
| 135 class RpcException implements Exception { | |
| 136 | |
| 137 static final String prefix = "RpcException:"; | |
| 138 | |
| 139 final String message; | |
| 140 const RpcException(this.message); | |
| 141 | |
| 142 String toString() { | |
| 143 return message; | |
| 144 } | |
| 145 | |
| 146 static String format(Exception e) { | |
| 147 return prefix + e.toString(); | |
| 148 } | |
| 149 | |
| 150 static RpcException parse(Object object) { | |
| 151 if (object === null || !(object is String)) { | |
| 152 return null; | |
| 153 } | |
| 154 String s = object; | |
| 155 if (!s.startsWith(prefix)) { | |
| 156 return null; | |
| 157 } | |
| 158 return new RpcException(s.substring(prefix.length, s.length)); | |
| 159 } | |
| 160 } | |
| OLD | NEW |