point-source / dart_ping

Multi-platform network ping utility for Dart
31 stars 14 forks source link

Moving to universal_io #40

Closed guyluz11 closed 1 year ago

guyluz11 commented 1 year ago

Currently this package is using io package which is missing support for the web.

I am suggesting moving to universal_io package as it has exactly the same functionality and method names and adds support for the web, it is quite popular to just switch projects to it.

guyluz11 commented 1 year ago

Closing as Will not implement

As discussed in the pr itself

here are a handful of ways to send a ping request:

Bind to a raw socket and construct an ICMP packet and send it over the socket
Link to a library that is already capable of sending ICMP packets
Command/run an executable that is already capable of sending ICMP packets

All the research I've done on this topic up till now suggests the following:

Browsers will not allow code (js or wasm) to bind to a native udp or tcp socket on the host system (seemingly for valid security reasons)
Browsers provide a limited api which js and wasm can use and it does not provide a way to import or link libraries/binaries on the host system that are not provided explicitly or natively by the browser's engine
Browsers will not allow js or wasm to arbitrarily execute a binary on the host computer via shell or process

Given these deliberate limitations which are there to ensure the security of the host, it is not currently feasible to "ping" from any application running inside a web browser. Neither js or wasm is capable of this at this time.

Additionally, since this dart_ping library makes use of host system binaries (with the exception of iOS) to ping other systems, it does not contain any code capable of constructing an ICMP packet. Even if we managed to compile this library to js or wasm, it would be useless because there is no "ping binary for web" that it can call.

As for point 2 of your post, I intentionally do not want this package to show web support because of the reasons above. If this were to show support for web, it would technically be misinformation as far as pub.dev is concerned because this package does not and cannot function on web even if it compiles without error. I would rather not mislead the community on this point.

Regarding your app and web support, I would love for your app to support web and simply inform the user that the ping function is not available in web mode. It seems you should be able to make use of conditional imports to avoid importing this package when compiling for web (much as universal_io, etc do). That way, you can manage how your app deals with the feature incompatibility without affecting the specifications of this package.

ckerens commented 1 year ago

If you need a web implementation it is pretty trivial to implement by wrapping it in an API. The pings come from the server and not the web browser. Here is a very basic example I put together for reference:

import 'dart:io';

import 'package:shelf/shelf.dart';
import 'package:shelf/shelf_io.dart';
import 'package:shelf_router/shelf_router.dart';
import 'package:dart_ping/dart_ping.dart';

// Configure routes.
final _router = Router()
  ..get('/', _rootHandler)
  ..get('/ping/<ip>', _pingHandler);

Response _rootHandler(Request req) {
  return Response.ok('Hello, World!\n');
}

Response _pingHandler(Request pingRequest) {
  final ipAddress = pingRequest.params['ip'] ?? '127.0.0.1';
  doPing(ipAddress);
  return Response.ok('Pinging $ipAddress');
}

void doPing(String ipAddress) {

  //print('Running command: ${ping.command}');

  final ping = Ping(ipAddress, count: 5, timeout: 1);
  print('Pinging $ipAddress');

  ping.stream.listen((event) {
    print(event);
  });
}

void main(List<String> args) async {
  // Use any available host or container IP (usually `0.0.0.0`).
  final ip = InternetAddress.anyIPv4;

  // Configure a pipeline that logs requests.
  final handler = Pipeline().addMiddleware(logRequests()).addHandler(_router);

  // For running in containers, we respect the PORT environment variable.
  final port = int.parse(Platform.environment['PORT'] ?? '8080');
  final server = await serve(handler, ip, port);
  print('Server listening on port ${server.port}');
}