diff --git a/client/cmake/macos_ne.cmake b/client/cmake/macos_ne.cmake index 05c4e4ca..58c367a9 100644 --- a/client/cmake/macos_ne.cmake +++ b/client/cmake/macos_ne.cmake @@ -84,12 +84,12 @@ set_target_properties(${PROJECT} PROPERTIES XCODE_ATTRIBUTE_LD_RUNPATH_SEARCH_PATHS "@executable_path/../Frameworks" XCODE_EMBED_APP_EXTENSIONS networkextension - # XCODE_ATTRIBUTE_CODE_SIGN_STYLE Automatic - XCODE_ATTRIBUTE_CODE_SIGN_STYLE Manual - XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "Apple Distribution: Privacy Technologies OU (X7UJ388FXK)" - XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY[variant=Debug] "Apple Development: TRAN VIET ANH (Y372SYT4WL)" - XCODE_ATTRIBUTE_PROVISIONING_PROFILE_SPECIFIER "Mac AppStore AmneziaVPN" - XCODE_ATTRIBUTE_PROVISIONING_PROFILE_SPECIFIER[variant=Debug] "org.amnezia.AmneziaVPNManual" + XCODE_ATTRIBUTE_CODE_SIGN_STYLE Automatic + # XCODE_ATTRIBUTE_CODE_SIGN_STYLE Manual + # XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "Apple Distribution: Privacy Technologies OU (X7UJ388FXK)" + # XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY[variant=Debug] "Apple Development: TRAN VIET ANH (Y372SYT4WL)" + # XCODE_ATTRIBUTE_PROVISIONING_PROFILE_SPECIFIER "Mac AppStore AmneziaVPN" + # XCODE_ATTRIBUTE_PROVISIONING_PROFILE_SPECIFIER[variant=Debug] "org.amnezia.AmneziaVPNManual" ) set_target_properties(${PROJECT} PROPERTIES XCODE_ATTRIBUTE_SWIFT_VERSION "5.0" diff --git a/client/macos/networkextension/CMakeLists.txt b/client/macos/networkextension/CMakeLists.txt index 92ad1f26..49a33b63 100644 --- a/client/macos/networkextension/CMakeLists.txt +++ b/client/macos/networkextension/CMakeLists.txt @@ -29,12 +29,12 @@ set_target_properties(networkextension PROPERTIES XCODE_ATTRIBUTE_APPLICATION_EXTENSION_API_ONLY "YES" XCODE_ATTRIBUTE_ENABLE_BITCODE "NO" - # XCODE_ATTRIBUTE_CODE_SIGN_STYLE Automatic - XCODE_ATTRIBUTE_CODE_SIGN_STYLE Manual - XCODE_ATTRIBUTE_PROVISIONING_PROFILE_SPECIFIER "Mac AppStore network-extension" - XCODE_ATTRIBUTE_PROVISIONING_PROFILE_SPECIFIER[variant=Debug] "amnezia.AmneziaVPN.network-extensionManual" - XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "Apple Distribution: Privacy Technologies OU (X7UJ388FXK)" - XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY[variant=Debug] "Apple Development: TRAN VIET ANH (Y372SYT4WL)" + XCODE_ATTRIBUTE_CODE_SIGN_STYLE Automatic + # XCODE_ATTRIBUTE_CODE_SIGN_STYLE Manual + # XCODE_ATTRIBUTE_PROVISIONING_PROFILE_SPECIFIER "Mac AppStore network-extension" + # XCODE_ATTRIBUTE_PROVISIONING_PROFILE_SPECIFIER[variant=Debug] "amnezia.AmneziaVPN.network-extensionManual" + # XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "Apple Distribution: Privacy Technologies OU (X7UJ388FXK)" + # XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY[variant=Debug] "Apple Development: TRAN VIET ANH (Y372SYT4WL)" XCODE_ATTRIBUTE_INFOPLIST_FILE ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist.in diff --git a/client/platforms/ios/PacketTunnelProvider+WireGuard.swift b/client/platforms/ios/PacketTunnelProvider+WireGuard.swift index 6e073df9..7a5c125b 100644 --- a/client/platforms/ios/PacketTunnelProvider+WireGuard.swift +++ b/client/platforms/ios/PacketTunnelProvider+WireGuard.swift @@ -118,7 +118,7 @@ extension PacketTunnelProvider { if let lastHandshakeValue = lastHandshakeString, let handshakeValue = Int64(lastHandshakeValue) { lastHandshake = handshakeValue } else { - lastHandshake = -2 // Trả về lỗi nếu không có giá trị last_handshake_time_sec + lastHandshake = -2 } let response: [String: Any] = [ diff --git a/client/platforms/ios/ios_controller.h b/client/platforms/ios/ios_controller.h index 85580769..616e2446 100644 --- a/client/platforms/ios/ios_controller.h +++ b/client/platforms/ios/ios_controller.h @@ -46,6 +46,7 @@ public: void disconnectVpn(); void vpnStatusDidChange(void *pNotification); + void vpnConfigurationDidChange(void *pNotification); void getBackendLogs(std::function &&callback); @@ -55,6 +56,9 @@ public: QString openFile(); void requestInetAccess(); + + void stopForHandshake(); + void waitForHandshake(); signals: void connectionStateChanged(Vpn::ConnectionState state); void bytesChanged(quint64 receivedBytes, quint64 sentBytes); diff --git a/client/platforms/ios/ios_controller.mm b/client/platforms/ios/ios_controller.mm index 8ba9aaac..ccf01e90 100644 --- a/client/platforms/ios/ios_controller.mm +++ b/client/platforms/ios/ios_controller.mm @@ -7,7 +7,7 @@ #include #include #include - +#include #include "../protocols/vpnprotocol.h" #import "ios_controller_wrapper.h" @@ -60,6 +60,8 @@ Vpn::ConnectionState iosStatusToState(NEVPNStatus status) { namespace { IosController* s_instance = nullptr; +QTimer *m_handshakeTimer = nullptr; +bool is_WireGuard = false; } IosController::IosController() : QObject() @@ -207,21 +209,27 @@ bool IosController::connectVpn(amnezia::Proto proto, const QJsonObject& configur if (proto == amnezia::Proto::OpenVpn) { + is_WireGuard = false; return setupOpenVPN(); } if (proto == amnezia::Proto::Cloak) { + is_WireGuard = false; return setupCloak(); } if (proto == amnezia::Proto::WireGuard) { + is_WireGuard = true; return setupWireGuard(); } if (proto == amnezia::Proto::Awg) { + is_WireGuard = true; return setupAwg(); } if (proto == amnezia::Proto::Xray) { + is_WireGuard = false; return setupXray(); } if (proto == amnezia::Proto::SSXray) { + is_WireGuard = false; return setupSSXray(); } @@ -252,31 +260,98 @@ void IosController::checkStatus() uint64_t txBytes = [response[@"tx_bytes"] intValue]; uint64_t rxBytes = [response[@"rx_bytes"] intValue]; - uint64_t last_handshake_time_sec = 0; - if (response[@"last_handshake_time_sec"] && ![response[@"last_handshake_time_sec"] isKindOfClass:[NSNull class]]) { - last_handshake_time_sec = [response[@"last_handshake_time_sec"] intValue]; - } else { - qDebug() << "Key last_handshake_time_sec is missing or null"; - } - - if (last_handshake_time_sec < 0) { - disconnectVpn(); - qDebug() << "Invalid handshake time, disconnecting VPN."; - } - emit bytesChanged(rxBytes - m_rxBytes, txBytes - m_txBytes); m_rxBytes = rxBytes; m_txBytes = txBytes; }); } +void IosController::stopForHandshake() { + if (m_handshakeTimer) { + if (m_handshakeTimer->isActive()) { + m_handshakeTimer->stop(); + } + m_handshakeTimer->deleteLater(); + m_handshakeTimer = nullptr; + + qDebug() << "Handshake monitoring stopped."; + } else { + qDebug() << "No active handshake monitoring to stop."; + } +} + + +void IosController::waitForHandshake() { + qDebug() << "Waiting for last_handshake_time_sec to be greater than 0..."; + + // Initialize the timer if it's null + if (!m_handshakeTimer) { + m_handshakeTimer = new QTimer(this); + + // Connect the timer's timeout signal to perform handshake checking + connect(m_handshakeTimer, &QTimer::timeout, this, [this]() { + // Prepare the message to check status + NSString *actionKey = [NSString stringWithUTF8String:MessageKey::action]; + NSString *actionValue = [NSString stringWithUTF8String:Action::getStatus]; + NSString *tunnelIdKey = [NSString stringWithUTF8String:MessageKey::tunnelId]; + NSString *tunnelIdValue = !m_tunnelId.isEmpty() ? m_tunnelId.toNSString() : @""; + + NSDictionary *message = @{actionKey: actionValue, tunnelIdKey: tunnelIdValue}; + + // Lambda to handle the response + auto checkHandshake = [this](NSDictionary *response) { + uint64_t last_handshake_time_sec = 0; + if (response && response[@"last_handshake_time_sec"] && + ![response[@"last_handshake_time_sec"] isKindOfClass:[NSNull class]]) { + last_handshake_time_sec = [response[@"last_handshake_time_sec"] unsignedLongLongValue]; + } + + qDebug() << "last_handshake_time_sec:" << last_handshake_time_sec; + + if (last_handshake_time_sec > 0) { + // Handshake successful, update state + qDebug() << "Handshake detected, updating state to CONNECTED."; + emit connectionStateChanged(Vpn::ConnectionState::Connected); + stopForHandshake(); + return; + } else { + if (last_handshake_time_sec == 0) { + // Keep retrying + emit connectionStateChanged(Vpn::ConnectionState::Connecting); + } else { + // Handle handshake failure and stop monitoring + emit connectionStateChanged(Vpn::ConnectionState::Disconnected); + stopForHandshake(); + return; + } + } + }; + + // Send the message to the VPN extension + sendVpnExtensionMessage(message, checkHandshake); + }); + + qDebug() << "Handshake timer initialized."; + } + + // Start the timer only if it's not already active + if (m_handshakeTimer && !m_handshakeTimer->isActive()) { + m_handshakeTimer->start(1000); // Retry every 1 second + qDebug() << "Handshake timer Retry every 1 second"; + } +} + void IosController::vpnStatusDidChange(void *pNotification) { NETunnelProviderSession *session = (NETunnelProviderSession *)pNotification; if (session /* && session == TunnelManager.session */ ) { qDebug() << "IosController::vpnStatusDidChange" << iosStatusToState(session.status) << session; - + if (is_WireGuard && session.status == NEVPNStatusConnected) + { + // use last_handshake_time + return; + } if (session.status == NEVPNStatusDisconnected) { if (@available(iOS 16.0, *)) { [session fetchLastDisconnectErrorWithCompletionHandler:^(NSError * _Nullable error) { @@ -371,6 +446,7 @@ void IosController::vpnStatusDidChange(void *pNotification) } else { qDebug() << "Disconnect error is unavailable on iOS < 16.0"; } + stopForHandshake(); } emit connectionStateChanged(iosStatusToState(session.status)); @@ -655,7 +731,7 @@ bool IosController::startWireGuard(const QString &config) tunnelProtocol.serverAddress = m_serverAddress; m_currentTunnel.protocolConfiguration = tunnelProtocol; - + waitForHandshake(); startTunnel(); }