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

Unified 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « examples/dart/netcat/BUILD.gn ('k') | sky/examples/terminal/terminal.sky » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: examples/dart/netcat/main.dart
diff --git a/examples/dart/netcat/main.dart b/examples/dart/netcat/main.dart
new file mode 100644
index 0000000000000000000000000000000000000000..629ae9f2a5a60a43bf523822d642a7d14fa67788
--- /dev/null
+++ b/examples/dart/netcat/main.dart
@@ -0,0 +1,212 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:core';
+import 'dart:typed_data';
+
+import 'package:mojo/public/dart/application.dart';
+import 'package:mojo/public/dart/bindings.dart';
+import 'package:mojo/public/dart/core.dart';
+import 'package:mojo/services/files/public/interfaces/file.mojom.dart' as files;
+import 'package:mojo/services/files/public/interfaces/types.mojom.dart'
+ as files;
+import 'package:mojo/services/network/public/interfaces/net_address.mojom.dart';
+import 'package:mojo/services/network/public/interfaces/network_error.mojom.dart';
+import 'package:mojo/services/network/public/interfaces/network_service.mojom.dart';
+import 'package:mojo/services/network/public/interfaces/tcp_bound_socket.mojom.dart';
+import 'package:mojo/services/network/public/interfaces/tcp_connected_socket.mojom.dart';
+import 'package:mojo/services/terminal/public/interfaces/terminal_client.mojom.dart';
+
+void ignoreFuture(Future f) {
+ f.catchError((e) {});
+}
+
+NetAddress makeIPv4NetAddress(List<int> addr, int port) {
+ var rv = new NetAddress();
+ rv.family = NetAddressFamily_IPV4;
+ rv.ipv4 = new NetAddressIPv4();
+ rv.ipv4.addr = new List<int>.from(addr);
+ rv.ipv4.port = port;
+ return rv;
+}
+
+void fputs(files.File f, String s) {
+ ignoreFuture(f.write((s + '\n').codeUnits, 0, files.Whence_FROM_CURRENT));
+}
+
+// Connects the terminal |File| and the socket.
+// TODO(vtl):
+// * Error handling: both connection/socket errors and terminal errors.
+// * Relatedly, we should listen for _socketSender's peer being closed (also
+// _socket, I guess).
+// * Handle the socket send pipe being full (currently, we assume it's never
+// full).
+class Connector {
+ final Application _application;
+ final files.FileProxy _terminal;
+ TcpConnectedSocketProxy _socket;
+ MojoDataPipeProducer _socketSender;
+ MojoDataPipeConsumer _socketReceiver;
+ MojoEventStream _socketReceiverEventStream;
+ final ByteData _readBuffer;
+ final ByteData _writeBuffer;
+
+ // TODO(vtl): Don't just hard-code buffer sizes.
+ Connector(this._application, this._terminal)
+ : _readBuffer = new ByteData(16 * 1024),
+ _writeBuffer = new ByteData(16 * 1024);
+
+ Future connect(NetAddress remote_address) async {
+ var networkService = new NetworkServiceProxy.unbound();
+ _application.connectToService('mojo:network_service', networkService);
+
+ NetAddress local_address = makeIPv4NetAddress([0, 0, 0, 0], 0);
+ var boundSocket = new TcpBoundSocketProxy.unbound();
+ await networkService.ptr.createTcpBoundSocket(local_address, boundSocket);
+ await networkService.close();
+
+ var sendDataPipe = new MojoDataPipe();
+ _socketSender = sendDataPipe.producer;
+ var receiveDataPipe = new MojoDataPipe();
+ _socketReceiver = receiveDataPipe.consumer;
+ _socket = new TcpConnectedSocketProxy.unbound();
+ await boundSocket.ptr.connect(remote_address, sendDataPipe.consumer,
+ receiveDataPipe.producer, _socket);
+ await boundSocket.close();
+
+ // Set up reading from the terminal.
+ _startReadingFromTerminal();
+
+ // Set up reading from the socket.
+ _socketReceiverEventStream = new MojoEventStream(_socketReceiver.handle);
+ _socketReceiverEventStream.listen(_onSocketReceiverEvent);
+ }
+
+ void _startReadingFromTerminal() {
+ // TODO(vtl): Handle terminal errors.
+ _terminal.ptr
+ .read(_writeBuffer.lengthInBytes, 0, files.Whence_FROM_CURRENT)
+ .then(_onReadFromTerminal);
+ }
+
+ void _onReadFromTerminal(files.FileReadResponseParams p) {
+ if (p.error != files.Error_OK) {
+ // TODO(vtl): Do terminal errors.
+ return;
+ }
+
+ // TODO(vtl): Temporary hack: echo, since we don't have built-in echo
+ // support.
+ ignoreFuture(
+ _terminal.ptr.write(p.bytesRead, 0, files.Whence_FROM_CURRENT));
+
+ // TODO(vtl): Verify that |bytesRead.length| is within the expected range.
+ for (var i = 0, j = 0; i < p.bytesRead.length; i++, j++) {
+ // TODO(vtl): Temporary hack: Translate \r to \n, since we don't have
+ // built-in support for that.
+ if (p.bytesRead[i] == 13) {
+ _writeBuffer.setUint8(i, 10);
+ } else {
+ _writeBuffer.setUint8(i, p.bytesRead[i]);
+ }
+ }
+
+ // TODO(vtl): Handle the send data pipe being full (or closed).
+ _socketSender
+ .write(new ByteData.view(_writeBuffer.buffer, 0, p.bytesRead.length));
+
+ _startReadingFromTerminal();
+ }
+
+ void _onSocketReceiverEvent(List<int> event) {
+ var mojoSignals = new MojoHandleSignals(event[1]);
+ var shouldClose = false;
+ if (mojoSignals.isReadable) {
+ var numBytesRead = _socketReceiver.read(_readBuffer);
+ if (_socketReceiver.status.isOk) {
+ assert(numBytesRead > 0);
+ _terminal.ptr.write(_readBuffer.buffer.asUint8List(0, numBytesRead), 0,
+ files.Whence_FROM_CURRENT);
+ _socketReceiverEventStream.enableReadEvents();
+ } else {
+ shouldClose = true;
+ }
+ } else if (mojoSignals.isPeerClosed) {
+ shouldClose = true;
+ } else {
+ throw 'Unexpected handle event: $mojoSignals';
+ }
+ if (shouldClose) {
+ _socketReceiverEventStream.close();
+ _socketReceiverEventStream = null;
+ fputs(_terminal.ptr, 'Connection closed.');
+ }
+ }
+}
+
+class TerminalClientImpl implements TerminalClient {
+ TerminalClientStub _stub;
+ Application _application;
+ String _resolvedUrl;
+
+ TerminalClientImpl(
+ this._application, this._resolvedUrl, MojoMessagePipeEndpoint endpoint) {
+ _stub = new TerminalClientStub.fromEndpoint(endpoint, this);
+ }
+
+ @override
+ void connectToTerminal(files.FileProxy terminal) {
+ var url = Uri.parse(_resolvedUrl);
+ NetAddress remote_address;
+ try {
+ remote_address = _getNetAddressFromUrl(url);
+ } catch (e) {
+ fputs(terminal.ptr, 'HALP: Add a query: ?host=<host>&port=<port>\n'
+ '(<host> must be "localhost" or n1.n2.n3.n4)\n\n'
+ 'Got query parameters:\n' + url.queryParameters.toString());
+ ignoreFuture(terminal.close());
+ return;
+ }
+
+ // TODO(vtl): Currently, we only do IPv4, so this should work.
+ fputs(terminal.ptr, 'Connecting to: ' +
+ remote_address.ipv4.addr.join('.') +
+ ':' +
+ remote_address.ipv4.port.toString() +
+ '...');
+
+ var connector = new Connector(_application, terminal);
+ connector.connect(remote_address);
+ }
+
+ // Note: May throw all sorts of things.
+ static NetAddress _getNetAddressFromUrl(Uri url) {
+ var params = url.queryParameters;
+ var host = params['host'];
+ return makeIPv4NetAddress(
+ (host == 'localhost') ? [127, 0, 0, 1] : Uri.parseIPv4Address(host),
+ int.parse(params['port']));
+ }
+}
+
+class NetcatApplication extends Application {
+ NetcatApplication.fromHandle(MojoHandle handle) : super.fromHandle(handle);
+
+ @override
+ void acceptConnection(String requestorUrl, String resolvedUrl,
+ ApplicationConnection connection) {
+ connection.provideService(TerminalClientName,
+ (endpoint) => new TerminalClientImpl(this, resolvedUrl, endpoint));
+ }
+}
+
+main(List args) {
+ MojoHandle appHandle = new MojoHandle(args[0]);
+ String url = args[1];
+ new NetcatApplication.fromHandle(appHandle)
+ ..onError = (() {
+ assert(MojoHandle.reportLeakedHandles());
+ });
+}
« 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