react-native-simple-openvpn icon indicating copy to clipboard operation
react-native-simple-openvpn copied to clipboard

RNSimpleOpenvpn.connect call triggers event duplications in addVpnStateListener on IOS

Open hamsterhomka opened this issue 11 months ago • 0 comments

Bug description: On iOS, each time RNSimpleOpenvpn.connect() is called, it duplicates the next event received by addVpnStateListener, causing events to stack indefinitely.

To Reproduce:

import { useEffect } from 'react';
import { Button, Platform, View } from 'react-native';
import RNSimpleOpenvpn, { addVpnStateListener, removeVpnStateListener } from 'react-native-simple-openvpn';


const vpnConfig = `your ovpn config`;


const isIPhone = Platform.OS === 'ios';

const App = () => {
  useEffect(() => {
    async function observeVpn() {
      if (isIPhone) {
        console.log('is iphone');
        await RNSimpleOpenvpn.observeState();
      }

      // The event gets duplicated after each RNSimpleOpenvpn.connect() call.
      addVpnStateListener((event) => {
        console.log(event, 'event');
      });
    }

    observeVpn();

    return async () => {
      if (isIPhone) {
        await RNSimpleOpenvpn.stopObserveState();
      }

      removeVpnStateListener();
    };
  });

  async function startOvpn() {
    console.log('startOvpn');

    try {
      await RNSimpleOpenvpn.connect({
        notificationTitle: 'title',
        ovpnString: vpnConfig,
        providerBundleIdentifier: 'com.hamsterhomka.yourapp.networkextension',
        localizedDescription: 'hello world',
      });

      console.log('startOvpn success');
    } catch (error) {
      console.log('error');
      console.error(error);
    }
  }

  async function stopOvpn() {
    try {
      await RNSimpleOpenvpn.disconnect();
    } catch (error) {
      console.error(error);
    }
  }

  return (
    <View style={ {paddingTop: 200} }>
      {/* Calling startOvpn causes event duplication in addVpnStateListener when an event is fired. */}
      <Button title="open" onPress={ startOvpn } />
      <Button title="stop" onPress={ stopOvpn } />
    </View>
  );
};

export default App;

It seems the issue lies in the iOS native code, as both addVpnStateListener and RNSimpleOpenvpn.observeState() are only called once.

Only closing and reopening the app resets the number of fired events, indicating that the issue lies in the native code rather than the JavaScript code. In the development build, the "Reload" button doesn't reset the number of fired events.

Expected behavior: Events in addVpnStateListener should not be duplicated. The callback should be invoked only once per listener trigger.

Screenshots/Videos:

Image

Environment:

  • OS: IOS
  • OS version: 18.0.1
  • react-native version: 0.74.5
  • react-native-simple-openvpn version: 2.1.2

On Android everything works just fine.

Anyone with an idea on how to fix this issue, please help! Thank you in advance!

hamsterhomka avatar Feb 10 '25 21:02 hamsterhomka