Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(191)

Side by Side Diff: examples/dart/netcat/main.dart

Issue 1032743002: A crappy "netcat"-type example (in Dart). (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « examples/dart/netcat/BUILD.gn ('k') | sky/examples/terminal/terminal.sky » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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 import 'dart:async';
6 import 'dart:core';
7 import 'dart:typed_data';
8
9 import 'package:mojo/public/dart/application.dart';
10 import 'package:mojo/public/dart/bindings.dart';
11 import 'package:mojo/public/dart/core.dart';
12 import 'package:mojo/services/files/public/interfaces/file.mojom.dart' as files;
13 import 'package:mojo/services/files/public/interfaces/types.mojom.dart'
14 as files;
15 import 'package:mojo/services/network/public/interfaces/net_address.mojom.dart';
16 import 'package:mojo/services/network/public/interfaces/network_error.mojom.dart ';
17 import 'package:mojo/services/network/public/interfaces/network_service.mojom.da rt';
18 import 'package:mojo/services/network/public/interfaces/tcp_bound_socket.mojom.d art';
19 import 'package:mojo/services/network/public/interfaces/tcp_connected_socket.moj om.dart';
20 import 'package:mojo/services/terminal/public/interfaces/terminal_client.mojom.d art';
21
22 void ignoreFuture(Future f) {
23 f.catchError((e) {});
24 }
25
26 NetAddress makeIPv4NetAddress(List<int> addr, int port) {
27 var rv = new NetAddress();
28 rv.family = NetAddressFamily_IPV4;
29 rv.ipv4 = new NetAddressIPv4();
30 rv.ipv4.addr = new List<int>.from(addr);
31 rv.ipv4.port = port;
32 return rv;
33 }
34
35 void fputs(files.File f, String s) {
36 ignoreFuture(f.write((s + '\n').codeUnits, 0, files.Whence_FROM_CURRENT));
37 }
38
39 // Connects the terminal |File| and the socket.
40 // TODO(vtl):
41 // * Error handling: both connection/socket errors and terminal errors.
42 // * Relatedly, we should listen for _socketSender's peer being closed (also
43 // _socket, I guess).
44 // * Handle the socket send pipe being full (currently, we assume it's never
45 // full).
46 class Connector {
47 final Application _application;
48 final files.FileProxy _terminal;
49 TcpConnectedSocketProxy _socket;
50 MojoDataPipeProducer _socketSender;
51 MojoDataPipeConsumer _socketReceiver;
52 MojoEventStream _socketReceiverEventStream;
53 final ByteData _readBuffer;
54 final ByteData _writeBuffer;
55
56 // TODO(vtl): Don't just hard-code buffer sizes.
57 Connector(this._application, this._terminal)
58 : _readBuffer = new ByteData(16 * 1024),
59 _writeBuffer = new ByteData(16 * 1024);
60
61 Future connect(NetAddress remote_address) async {
62 var networkService = new NetworkServiceProxy.unbound();
63 _application.connectToService('mojo:network_service', networkService);
64
65 NetAddress local_address = makeIPv4NetAddress([0, 0, 0, 0], 0);
66 var boundSocket = new TcpBoundSocketProxy.unbound();
67 await networkService.ptr.createTcpBoundSocket(local_address, boundSocket);
68 await networkService.close();
69
70 var sendDataPipe = new MojoDataPipe();
71 _socketSender = sendDataPipe.producer;
72 var receiveDataPipe = new MojoDataPipe();
73 _socketReceiver = receiveDataPipe.consumer;
74 _socket = new TcpConnectedSocketProxy.unbound();
75 await boundSocket.ptr.connect(remote_address, sendDataPipe.consumer,
76 receiveDataPipe.producer, _socket);
77 await boundSocket.close();
78
79 // Set up reading from the terminal.
80 _startReadingFromTerminal();
81
82 // Set up reading from the socket.
83 _socketReceiverEventStream = new MojoEventStream(_socketReceiver.handle);
84 _socketReceiverEventStream.listen(_onSocketReceiverEvent);
85 }
86
87 void _startReadingFromTerminal() {
88 // TODO(vtl): Handle terminal errors.
89 _terminal.ptr
90 .read(_writeBuffer.lengthInBytes, 0, files.Whence_FROM_CURRENT)
91 .then(_onReadFromTerminal);
92 }
93
94 void _onReadFromTerminal(files.FileReadResponseParams p) {
95 if (p.error != files.Error_OK) {
96 // TODO(vtl): Do terminal errors.
97 return;
98 }
99
100 // TODO(vtl): Temporary hack: echo, since we don't have built-in echo
101 // support.
102 ignoreFuture(
103 _terminal.ptr.write(p.bytesRead, 0, files.Whence_FROM_CURRENT));
104
105 // TODO(vtl): Verify that |bytesRead.length| is within the expected range.
106 for (var i = 0, j = 0; i < p.bytesRead.length; i++, j++) {
107 // TODO(vtl): Temporary hack: Translate \r to \n, since we don't have
108 // built-in support for that.
109 if (p.bytesRead[i] == 13) {
110 _writeBuffer.setUint8(i, 10);
111 } else {
112 _writeBuffer.setUint8(i, p.bytesRead[i]);
113 }
114 }
115
116 // TODO(vtl): Handle the send data pipe being full (or closed).
117 _socketSender
118 .write(new ByteData.view(_writeBuffer.buffer, 0, p.bytesRead.length));
119
120 _startReadingFromTerminal();
121 }
122
123 void _onSocketReceiverEvent(List<int> event) {
124 var mojoSignals = new MojoHandleSignals(event[1]);
125 var shouldClose = false;
126 if (mojoSignals.isReadable) {
127 var numBytesRead = _socketReceiver.read(_readBuffer);
128 if (_socketReceiver.status.isOk) {
129 assert(numBytesRead > 0);
130 _terminal.ptr.write(_readBuffer.buffer.asUint8List(0, numBytesRead), 0,
131 files.Whence_FROM_CURRENT);
132 _socketReceiverEventStream.enableReadEvents();
133 } else {
134 shouldClose = true;
135 }
136 } else if (mojoSignals.isPeerClosed) {
137 shouldClose = true;
138 } else {
139 throw 'Unexpected handle event: $mojoSignals';
140 }
141 if (shouldClose) {
142 _socketReceiverEventStream.close();
143 _socketReceiverEventStream = null;
144 fputs(_terminal.ptr, 'Connection closed.');
145 }
146 }
147 }
148
149 class TerminalClientImpl implements TerminalClient {
150 TerminalClientStub _stub;
151 Application _application;
152 String _resolvedUrl;
153
154 TerminalClientImpl(
155 this._application, this._resolvedUrl, MojoMessagePipeEndpoint endpoint) {
156 _stub = new TerminalClientStub.fromEndpoint(endpoint, this);
157 }
158
159 @override
160 void connectToTerminal(files.FileProxy terminal) {
161 var url = Uri.parse(_resolvedUrl);
162 NetAddress remote_address;
163 try {
164 remote_address = _getNetAddressFromUrl(url);
165 } catch (e) {
166 fputs(terminal.ptr, 'HALP: Add a query: ?host=<host>&port=<port>\n'
167 '(<host> must be "localhost" or n1.n2.n3.n4)\n\n'
168 'Got query parameters:\n' + url.queryParameters.toString());
169 ignoreFuture(terminal.close());
170 return;
171 }
172
173 // TODO(vtl): Currently, we only do IPv4, so this should work.
174 fputs(terminal.ptr, 'Connecting to: ' +
175 remote_address.ipv4.addr.join('.') +
176 ':' +
177 remote_address.ipv4.port.toString() +
178 '...');
179
180 var connector = new Connector(_application, terminal);
181 connector.connect(remote_address);
182 }
183
184 // Note: May throw all sorts of things.
185 static NetAddress _getNetAddressFromUrl(Uri url) {
186 var params = url.queryParameters;
187 var host = params['host'];
188 return makeIPv4NetAddress(
189 (host == 'localhost') ? [127, 0, 0, 1] : Uri.parseIPv4Address(host),
190 int.parse(params['port']));
191 }
192 }
193
194 class NetcatApplication extends Application {
195 NetcatApplication.fromHandle(MojoHandle handle) : super.fromHandle(handle);
196
197 @override
198 void acceptConnection(String requestorUrl, String resolvedUrl,
199 ApplicationConnection connection) {
200 connection.provideService(TerminalClientName,
201 (endpoint) => new TerminalClientImpl(this, resolvedUrl, endpoint));
202 }
203 }
204
205 main(List args) {
206 MojoHandle appHandle = new MojoHandle(args[0]);
207 String url = args[1];
208 new NetcatApplication.fromHandle(appHandle)
209 ..onError = (() {
210 assert(MojoHandle.reportLeakedHandles());
211 });
212 }
OLDNEW
« no previous file with comments | « examples/dart/netcat/BUILD.gn ('k') | sky/examples/terminal/terminal.sky » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698