Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scan different subnet other than local one #127

Merged
merged 4 commits into from
Mar 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ if (keystorePropertiesFile.exists()) {
}

android {
compileSdkVersion 33
compileSdkVersion 34

sourceSets {
main.java.srcDirs += 'src/main/kotlin'
Expand All @@ -41,7 +41,7 @@ android {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "org.fsociety.vernet"
minSdkVersion 19
targetSdkVersion 33
targetSdkVersion 34
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
}
Expand Down
17 changes: 17 additions & 0 deletions lib/helper/app_settings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ class AppSettings {
static const String _socketTimeoutKey = 'AppSettings-SOCKET_TIMEOUT';
static const String _pingCountKey = 'AppSettings-PING_COUNT';
static const String _inAppInternetKey = 'AppSettings-IN-APP-INTERNET';
static const String _customSubnetKey = 'AppSettings-CUSTOM-SUBNET';
int _firstSubnet = 1;
int _lastSubnet = 254;
int _socketTimeout = 500;
int _pingCount = 5;
bool _inAppInternet = false;
String _customSubnet = '';

static final AppSettings _instance = AppSettings._();

Expand All @@ -23,6 +25,10 @@ class AppSettings {
int get socketTimeout => _socketTimeout;
int get pingCount => _pingCount;
bool get inAppInternet => _inAppInternet;
String get customSubnet => _customSubnet;
String get gatewayIP => _customSubnet.isNotEmpty
? _customSubnet.substring(0, _customSubnet.lastIndexOf('.'))
: _customSubnet;

Future<bool> setFirstSubnet(int firstSubnet) async {
_firstSubnet = firstSubnet;
Expand Down Expand Up @@ -54,6 +60,12 @@ class AppSettings {
.setBool(_inAppInternetKey, _inAppInternet);
}

Future<bool> setCustomSubnet(String customSubnet) async {
_customSubnet = customSubnet;
return (await SharedPreferences.getInstance())
.setString(_customSubnetKey, _customSubnet);
}

Future<void> load() async {
debugPrint("Fetching all app settings");
_firstSubnet =
Expand All @@ -80,5 +92,10 @@ class AppSettings {
(await SharedPreferences.getInstance()).getBool(_inAppInternetKey) ??
_inAppInternet;
debugPrint("In-App Internet : $_inAppInternet");

_customSubnet =
(await SharedPreferences.getInstance()).getString(_customSubnetKey) ??
_customSubnet;
debugPrint("Custom Subnet : $_customSubnet");
}
}
2 changes: 1 addition & 1 deletion lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Future<void> main() async {
configureDependencies(Env.prod);
WidgetsFlutterBinding.ensureInitialized();
final appDocDirectory = await getApplicationDocumentsDirectory();
await configureNetworkTools(appDocDirectory.path);
await configureNetworkToolsFlutter(appDocDirectory.path);
final bool allowed = await ConsentLoader.isConsentPageShown();

// load app settings
Expand Down
71 changes: 38 additions & 33 deletions lib/pages/host_scan_page/host_scna_bloc/host_scan_bloc.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'dart:async';

import 'package:bloc/bloc.dart';
import 'package:flutter/foundation.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:injectable/injectable.dart';
import 'package:network_info_plus/network_info_plus.dart';
Expand Down Expand Up @@ -39,47 +40,51 @@ class HostScanBloc extends Bloc<HostScanEvent, HostScanState> {
) async {
emit(const HostScanState.loadInProgress());
ip = await NetworkInfo().getWifiIP();
subnet = ip!.substring(0, ip!.lastIndexOf('.'));
gatewayIp = await NetworkInfo().getWifiGatewayIP();

gatewayIp = appSettings.customSubnet.isNotEmpty
? appSettings.customSubnet
: await NetworkInfo().getWifiGatewayIP();
subnet = gatewayIp!.substring(0, gatewayIp!.lastIndexOf('.'));
add(const HostScanEvent.startNewScan());
}

Future<void> _startNewScanBuiltInIsolate(
StartNewScan event,
Emitter<HostScanState> emit,
) async {
MdnsScannerService.instance
.searchMdnsDevices()
.then((List<ActiveHost> activeHostList) async {
for (final ActiveHost activeHost in activeHostList) {
final int index = indexOfActiveHost(activeHost.address);
final MdnsInfo? mDns = await activeHost.mdnsInfo;
if (mDns == null) {
continue;
}

if (index == -1) {
deviceInTheNetworkList.add(
DeviceInTheNetwork.createFromActiveHost(
activeHost: activeHost,
currentDeviceIp: ip!,
gatewayIp: gatewayIp!,
mdns: mDns,
mac: (await activeHost.arpData)?.macAddress,
),
);
} else {
deviceInTheNetworkList[index] = deviceInTheNetworkList[index]
..mdns = mDns;
// mdns scanner causes crash on macos while running app.
if (!kDebugMode) {
MdnsScannerService.instance
.searchMdnsDevices()
.then((List<ActiveHost> activeHostList) async {
for (final ActiveHost activeHost in activeHostList) {
final int index = indexOfActiveHost(activeHost.address);
final MdnsInfo? mDns = await activeHost.mdnsInfo;
if (mDns == null) {
continue;
}

if (index == -1) {
deviceInTheNetworkList.add(
DeviceInTheNetwork.createFromActiveHost(
activeHost: activeHost,
currentDeviceIp: ip!,
gatewayIp: gatewayIp!,
mdns: mDns,
mac: (await activeHost.arpData)?.macAddress,
),
);
} else {
deviceInTheNetworkList[index] = deviceInTheNetworkList[index]
..mdns = mDns;
}

deviceInTheNetworkList.sort(sort);

emit(const HostScanState.loadInProgress());
emit(HostScanState.foundNewDevice(deviceInTheNetworkList));
}

deviceInTheNetworkList.sort(sort);

emit(const HostScanState.loadInProgress());
emit(HostScanState.foundNewDevice(deviceInTheNetworkList));
}
});
});
}

final streamController = HostScannerService.instance.getAllPingableDevices(
subnet!,
Expand Down
15 changes: 9 additions & 6 deletions lib/pages/host_scan_page/widgets/host_scan_widget.dart
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:vernet/main.dart';
import 'package:vernet/pages/host_scan_page/device_in_the_network.dart';
import 'package:vernet/pages/host_scan_page/host_scna_bloc/host_scan_bloc.dart';
import 'package:vernet/pages/network_troubleshoot/port_scan_page.dart';
// import 'package:vernet/pages/port_scan_page/port_scan_page.dart';

class HostScanWidget extends StatelessWidget {
@override
Expand All @@ -17,16 +17,19 @@ class HostScanWidget extends StatelessWidget {
return Center(
child: Container(
margin: const EdgeInsets.all(30),
child: const Column(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
CircularProgressIndicator(),
SizedBox(
const CircularProgressIndicator(),
const SizedBox(
height: 30,
),
Text(
'Searching for devices in your local network',
style: TextStyle(
appSettings.gatewayIP.isNotEmpty
? 'Searching for devices in ${appSettings.gatewayIP} network'
: 'Searching for devices in your local network',
textAlign: TextAlign.center,
style: const TextStyle(
fontSize: 18,
color: Colors.blue,
),
Expand Down
1 change: 1 addition & 0 deletions lib/pages/network_troubleshoot/port_scan_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ class _PortScanPageState extends State<PortScanPage>
_targetIPEditingController.text,
timeout: Duration(milliseconds: appSettings.socketTimeout),
progressCallback: _handleProgress,
async: true,
)
.listen(_handleEvent, onDone: _handleOnDone);
} else {
Expand Down
22 changes: 22 additions & 0 deletions lib/pages/settings_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'package:vernet/api/update_checker.dart';
import 'package:vernet/helper/utils_helper.dart';
import 'package:vernet/main.dart';
import 'package:vernet/models/dark_theme_provider.dart';
import 'package:vernet/ui/settings_dialog/custom_subnet_dialog.dart';
import 'package:vernet/ui/settings_dialog/first_subnet_dialog.dart';
import 'package:vernet/ui/settings_dialog/last_subnet_dialog.dart';
import 'package:vernet/ui/settings_dialog/ping_count_dialog.dart';
Expand Down Expand Up @@ -137,6 +138,27 @@ class _SettingsPageState extends State<SettingsPage> {
},
),
),
Card(
child: ListTile(
title: const Text(StringValue.customSubnet),
subtitle: const Text(StringValue.customSubnetDesc),
trailing: Text(
appSettings.customSubnet,
style: Theme.of(context)
.textTheme
.titleSmall
?.copyWith(color: Theme.of(context).colorScheme.secondary),
),
onTap: () async {
await showDialog(
context: context,
builder: (context) => const CustomSubnetDialog(),
);
await appSettings.load();
setState(() {});
},
),
),
Card(
child: ListTile(
title: const Text('Check for Updates'),
Expand Down
45 changes: 45 additions & 0 deletions lib/ui/settings_dialog/custom_subnet_dialog.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import 'package:flutter/material.dart';
import 'package:vernet/main.dart';
import 'package:vernet/ui/base_settings_dialog.dart';
import 'package:vernet/values/strings.dart';

class CustomSubnetDialog extends StatefulWidget {
const CustomSubnetDialog({super.key});

@override
State<CustomSubnetDialog> createState() => _CustomSubnetDialogState();
}

class _CustomSubnetDialogState extends BaseSettingsDialog<CustomSubnetDialog> {
@override
String getDialogTitle() {
return StringValue.customSubnet;
}

@override
String getHintText() {
return StringValue.customSubnetHint;
}

@override
String getInitialValue() {
return appSettings.customSubnet;
}

@override
TextInputType getKeyBoardType() {
return TextInputType.number;
}

@override
void onSubmit(String value) {
if (value != appSettings.customSubnet) {
appSettings.setCustomSubnet(value);
}
}

@override
String? validate(String? value) {
return null;
}
}
5 changes: 5 additions & 0 deletions lib/values/strings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,9 @@ class StringValue {
static const String pingCount = 'Ping Count';
static const String pingCountDesc =
'Number of times ping request should be sent';

static const String customSubnet = 'Custom Subnet';
static const String customSubnetDesc =
'Scan a custom subnet instead of local one.';
static const String customSubnetHint = 'Enter Gateway IP e.g., 10.102.200.1';
}
Loading