7272import java .util .concurrent .ConcurrentHashMap ;
7373import java .util .concurrent .locks .ReentrantReadWriteLock ;
7474
75- public class MainService extends Service {
75+ import net .christianbeier .droidvnc_ng .ifaceutils .IfCollector ;
76+ import net .christianbeier .droidvnc_ng .ifaceutils .NetIfData ;
77+ import net .christianbeier .droidvnc_ng .ifaceutils .NetworkInterfaceTester ;
78+
79+ public class MainService extends Service implements NetworkInterfaceTester .OnNetworkStateChangedListener {
7680
7781 private static final String TAG = "MainService" ;
7882 static final int NOTIFICATION_ID = 11 ;
@@ -82,6 +86,7 @@ public class MainService extends Service {
8286 public static final String ACTION_CONNECT_REPEATER = "net.christianbeier.droidvnc_ng.ACTION_CONNECT_REPEATER" ;
8387 public static final String EXTRA_REQUEST_ID = "net.christianbeier.droidvnc_ng.EXTRA_REQUEST_ID" ;
8488 public static final String EXTRA_REQUEST_SUCCESS = "net.christianbeier.droidvnc_ng.EXTRA_REQUEST_SUCCESS" ;
89+ public static final String EXTRA_LISTEN_INTERFACE = "net.christianbeier.droidvnc_ng.EXTRA_LISTEN_INTERFACE" ;
8590 public static final String EXTRA_HOST = "net.christianbeier.droidvnc_ng.EXTRA_HOST" ;
8691 public static final String EXTRA_PORT = "net.christianbeier.droidvnc_ng.EXTRA_PORT" ;
8792 public static final String EXTRA_REPEATER_ID = "net.christianbeier.droidvnc_ng.EXTRA_REPEATER_ID" ;
@@ -119,9 +124,19 @@ public class MainService extends Service {
119124
120125 final static String ACTION_HANDLE_NOTIFICATION_RESULT = "action_handle_notification_result" ;
121126
127+
122128 final static String ACTION_HANDLE_MEDIA_PROJECTION_RESULT = "action_handle_media_projection_result" ;
123129 final static String EXTRA_MEDIA_PROJECTION_STATE = "state_media_projection" ;
124130
131+ private static final String PREFS_KEY_SERVER_LAST_LISTEN_INTERFACE = "server_last_listen_interface" ;
132+ private static final String PREFS_KEY_SERVER_LAST_PORT = "server_last_port" ;
133+ private static final String PREFS_KEY_SERVER_LAST_PASSWORD = "server_last_password" ;
134+ private static final String PREFS_KEY_SERVER_LAST_FILE_TRANSFER = "server_last_file_transfer" ;
135+ private static final String PREFS_KEY_SERVER_LAST_SHOW_POINTERS = "server_last_show_pointers" ;
136+ private static final String PREFS_KEY_SERVER_LAST_FALLBACK_SCREEN_CAPTURE = "server_last_fallback_screen_capture" ;
137+ private static final String PREFS_KEY_SERVER_LAST_START_REQUEST_ID = "server_last_start_request_id" ;
138+
139+
125140 private int mResultCode ;
126141 private Intent mResultData ;
127142 private PowerManager .WakeLock mWakeLock ;
@@ -209,7 +224,7 @@ public void onServiceUnregistered(NsdServiceInfo nsdServiceInfo) {
209224 }
210225
211226 @ SuppressWarnings ("BooleanMethodIsAlwaysInverted" )
212- private native boolean vncStartServer (int width , int height , int port , String desktopName , String password , String httpRootDir );
227+ private native boolean vncStartServer (int width , int height , String listenIf , int port , String desktopName , String password , String httpRootDir );
213228 private native boolean vncStopServer ();
214229 private native boolean vncIsActive ();
215230 private native long vncConnectReverse (String host , int port );
@@ -234,6 +249,7 @@ public void onCreate() {
234249 Log .d (TAG , "onCreate" );
235250
236251 instance = this ;
252+ NetworkInterfaceTester .getInstance (this ).addOnNetworkStateChangedListener (this );
237253
238254 if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .O ) {
239255 /*
@@ -404,18 +420,24 @@ public int onStartCommand(Intent intent, int flags, int startId)
404420 startScreenCapture ();
405421 } else {
406422 DisplayMetrics displayMetrics = Utils .getDisplayMetrics (this , Display .DEFAULT_DISPLAY );
423+
407424 Intent startIntent = Objects .requireNonNull (MainServicePersistData .loadStartIntent (this ));
425+ String listenIf = startIntent .getStringExtra (EXTRA_LISTEN_INTERFACE ) != null ? startIntent .getStringExtra (EXTRA_LISTEN_INTERFACE ) : PreferenceManager .getDefaultSharedPreferences (this ).getString (Constants .PREFS_KEY_SETTINGS_LISTEN_INTERFACE , mDefaults .getListenInterface ());
426+ String listenAddress = MainService .getInterfaceListeningIPv4Address (listenIf );
408427 int port = startIntent .getIntExtra (EXTRA_PORT , PreferenceManager .getDefaultSharedPreferences (this ).getInt (Constants .PREFS_KEY_SETTINGS_PORT , mDefaults .getPort ()));
409428 String password = startIntent .getStringExtra (EXTRA_PASSWORD ) != null ? startIntent .getStringExtra (EXTRA_PASSWORD ) : PreferenceManager .getDefaultSharedPreferences (this ).getString (Constants .PREFS_KEY_SETTINGS_PASSWORD , mDefaults .getPassword ());
429+
410430 // get device name
411431 String name = Utils .getDeviceName (this );
412432
413433 boolean status = vncStartServer (displayMetrics .widthPixels ,
414434 displayMetrics .heightPixels ,
435+ listenAddress ,
415436 port ,
416437 name ,
417438 password ,
418439 getFilesDir ().getAbsolutePath () + File .separator + "novnc" );
440+
419441 Intent answer = new Intent (ACTION_START );
420442 answer .putExtra (EXTRA_REQUEST_ID , startIntent .getStringExtra (EXTRA_REQUEST_ID ));
421443 answer .putExtra (EXTRA_REQUEST_SUCCESS , status );
@@ -454,11 +476,16 @@ public int onStartCommand(Intent intent, int flags, int startId)
454476 if (mResultCode != 0 && mResultData != null
455477 || (Build .VERSION .SDK_INT >= 30 && startIntent .getBooleanExtra (EXTRA_FALLBACK_SCREEN_CAPTURE , false ))) {
456478 DisplayMetrics displayMetrics = Utils .getDisplayMetrics (this , Display .DEFAULT_DISPLAY );
479+
480+ String listenIf = startIntent .getStringExtra (EXTRA_LISTEN_INTERFACE ) != null ? startIntent .getStringExtra (EXTRA_LISTEN_INTERFACE ) : PreferenceManager .getDefaultSharedPreferences (this ).getString (Constants .PREFS_KEY_SETTINGS_LISTEN_INTERFACE , mDefaults .getListenInterface ());
481+ String listenAddress = MainService .getInterfaceListeningIPv4Address (listenIf );
457482 int port = startIntent .getIntExtra (EXTRA_PORT , PreferenceManager .getDefaultSharedPreferences (this ).getInt (Constants .PREFS_KEY_SETTINGS_PORT , mDefaults .getPort ()));
458483 String password = startIntent .getStringExtra (EXTRA_PASSWORD ) != null ? startIntent .getStringExtra (EXTRA_PASSWORD ) : PreferenceManager .getDefaultSharedPreferences (this ).getString (Constants .PREFS_KEY_SETTINGS_PASSWORD , mDefaults .getPassword ());
484+
459485 String name = Utils .getDeviceName (this );
460486 boolean status = vncStartServer (displayMetrics .widthPixels ,
461487 displayMetrics .heightPixels ,
488+ listenAddress ,
462489 port ,
463490 name ,
464491 password ,
@@ -520,6 +547,13 @@ public int onStartCommand(Intent intent, int flags, int startId)
520547 MainServicePersistData .saveStartIntent (this , intent );
521548 final SharedPreferences prefs = PreferenceManager .getDefaultSharedPreferences (this );
522549 SharedPreferences .Editor ed = prefs .edit ();
550+
551+
552+ ed .putString (PREFS_KEY_SERVER_LAST_LISTEN_INTERFACE , intent .getStringExtra (EXTRA_LISTEN_INTERFACE ) != null ? intent .getStringExtra (EXTRA_LISTEN_INTERFACE ) : prefs .getString (Constants .PREFS_KEY_SETTINGS_LISTEN_INTERFACE , mDefaults .getListenInterface ()));
553+ ed .putInt (PREFS_KEY_SERVER_LAST_PORT , intent .getIntExtra (EXTRA_PORT , prefs .getInt (Constants .PREFS_KEY_SETTINGS_PORT , mDefaults .getPort ())));
554+ ed .putString (PREFS_KEY_SERVER_LAST_PASSWORD , intent .getStringExtra (EXTRA_PASSWORD ) != null ? intent .getStringExtra (EXTRA_PASSWORD ) : prefs .getString (Constants .PREFS_KEY_SETTINGS_PASSWORD , mDefaults .getPassword ()));
555+ ed .putBoolean (PREFS_KEY_SERVER_LAST_FILE_TRANSFER , intent .getBooleanExtra (EXTRA_FILE_TRANSFER , prefs .getBoolean (Constants .PREFS_KEY_SETTINGS_FILE_TRANSFER , mDefaults .getFileTransfer ())));
556+
523557 ed .putBoolean (Constants .PREFS_KEY_INPUT_LAST_ENABLED , !intent .getBooleanExtra (EXTRA_VIEW_ONLY , prefs .getBoolean (Constants .PREFS_KEY_SETTINGS_VIEW_ONLY , mDefaults .getViewOnly ())));
524558 ed .putFloat (Constants .PREFS_KEY_SERVER_LAST_SCALING , intent .getFloatExtra (EXTRA_SCALING , prefs .getFloat (Constants .PREFS_KEY_SETTINGS_SCALING , mDefaults .getScaling ())));
525559 ed .apply ();
@@ -874,6 +908,7 @@ private void sendBroadcastToOthersAndUs(Intent intent) {
874908 }
875909 }
876910
911+
877912 static boolean isServerActive () {
878913 try {
879914 return instance .vncIsActive ();
@@ -890,13 +925,41 @@ static int getClientCount() {
890925 }
891926 }
892927
928+
929+
893930 /**
894- * Get non-loopback IPv4 addresses.
895- * @return A list of strings, each containing one IPv4 address.
931+ * This returns A SINGLE ipv4 address for the selected option id (representing an interface)... giving the possibility
932+ * to the server to listen to that address only.
933+ * @param ifName name that defines the interface to be used (may be an actual interface name or an option id, like "any" and "loopback")
934+ * @return null if the interface is 0.0.0.0 (any), otherwise, the needed ipv4
896935 */
897- static ArrayList <String > getIPv4s () {
936+ static String getInterfaceListeningIPv4Address (String ifName ) {
937+ if (!NetIfData .isOptionIdAny (ifName )) {
938+ ArrayList <String > ipv4s = null ;
939+
940+ if (NetIfData .isOptionIdLoopback (ifName )) {
941+ ipv4s = Utils .getIPv4ForInterface (IfCollector .getInstance ().getLoopback ().getNetworkInterface ());
942+
943+ } else {
944+ ipv4s = Utils .getIPv4ForInterface (ifName );
945+
946+ }
947+
948+ if (ipv4s .size () > 0 ) {
949+ return ipv4s .get (0 );
950+ }
951+ }
952+
953+ return null ;
954+ }
955+
898956
899- Set <String > hosts = new LinkedHashSet <>();
957+ /**
958+ * Get all available IPv4 addresses for reaching the current running server.
959+ * @return A list of strings, each containing one IPv4 address.
960+ */
961+ static ArrayList <String > getReachableIPv4s () {
962+ ArrayList <String > hosts = new ArrayList <>();
900963
901964 // if running on Chrome OS, this prop is set and contains the device's IPv4 address,
902965 // see https://chromeos.dev/en/games/optimizing-games-networking
@@ -906,29 +969,48 @@ static ArrayList<String> getIPv4s() {
906969 }
907970
908971 // not running on Chrome OS
909- try {
910- // thanks go to https://stackoverflow.com/a/20103869/361413
911- Enumeration <NetworkInterface > nis = NetworkInterface .getNetworkInterfaces ();
912- NetworkInterface ni ;
913- while (nis .hasMoreElements ()) {
914- ni = nis .nextElement ();
915- if (!ni .isLoopback ()/*not loopback*/ && ni .isUp ()/*it works now*/ ) {
916- for (InterfaceAddress ia : ni .getInterfaceAddresses ()) {
917- //filter for ipv4/ipv6
918- if (ia .getAddress ().getAddress ().length == 4 ) {
919- //4 for ipv4, 16 for ipv6
920- hosts .add (ia .getAddress ().toString ().replaceAll ("/" , "" ));
921- }
922- }
972+ String listenInterface = MainService .getListenInterface ();
973+ IfCollector ifColl = IfCollector .getInstance ();
974+ ArrayList <String > ipv4s = null ;
975+
976+ if (NetIfData .isOptionIdAny (listenInterface )) {
977+ // Any mode: get all the available NICs and add their IPv4
978+ for (int i = 0 ; i < ifColl .getSize (); i ++) {
979+ NetIfData nid = ifColl .getNetIf (i );
980+ ipv4s = Utils .getIPv4ForInterface (nid .getNetworkInterface ());
981+ for (String ipv4 : ipv4s ) {
982+ hosts .add (ipv4 );
923983 }
924984 }
925- } catch (SocketException e ) {
926- //unused
985+
986+ } else {
987+ // Single interface: get all its IPv4 addresses
988+ if (NetIfData .isOptionIdLoopback (listenInterface )) {
989+ ipv4s = Utils .getIPv4ForInterface (ifColl .getLoopback ().getNetworkInterface ());
990+
991+ } else {
992+ ipv4s = Utils .getIPv4ForInterface (listenInterface );
993+ }
994+
995+ for (String ipv4 : ipv4s ) {
996+ hosts .add (ipv4 );
997+ }
927998 }
928999
9291000 return new ArrayList <>(hosts );
9301001 }
9311002
1003+
1004+
1005+ static String getListenInterface () {
1006+ try {
1007+ SharedPreferences prefs = PreferenceManager .getDefaultSharedPreferences (instance );
1008+ return prefs .getString (PREFS_KEY_SERVER_LAST_LISTEN_INTERFACE , new Defaults (instance ).getListenInterface ());
1009+ } catch (Exception e ) {
1010+ return null ;
1011+ }
1012+ }
1013+
9321014 static int getPort () {
9331015 try {
9341016 return Objects .requireNonNull (MainServicePersistData .loadStartIntent (instance )).getIntExtra (EXTRA_PORT , PreferenceManager .getDefaultSharedPreferences (instance ).getInt (Constants .PREFS_KEY_SETTINGS_PORT , instance .mDefaults .getPort ()));
@@ -1044,6 +1126,7 @@ static Notification getCurrentNotification() {
10441126 }
10451127 }
10461128
1129+
10471130 /**
10481131 * Helper that adds {@link #EXTRA_FALLBACK_SCREEN_CAPTURE} to the given intent if
10491132 * PROJECT_MEDIA app op is not set.
@@ -1070,4 +1153,16 @@ static void addFallbackScreenCaptureIfNotAppOp(Context context, Intent intent) {
10701153 intent .putExtra (MainService .EXTRA_FALLBACK_SCREEN_CAPTURE , useFallback );
10711154 }
10721155
1156+
1157+
1158+
1159+
1160+ public void onNetworkStateChanged (NetworkInterfaceTester nit ) {
1161+ if (isServerActive ()) {
1162+ if (!nit .isIfEnabled (getListenInterface ())) {
1163+ // Stop if the server is active but the interface is not!
1164+ this .stopSelf ();
1165+ }
1166+ }
1167+ }
10731168}
0 commit comments