summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authormojganii <mojgan.jelodar@codic.se>2025-03-20 15:54:50 +0100
committermojganii <mojgan.jelodar@codic.se>2025-04-15 15:38:45 +0200
commitf8aeeb42fa5cc7f1cc428bb4b34cb8d5de09bb51 (patch)
tree7c6c740793dc53b39ae916d5f688a81e94218c6f
parent59f4f47a1ed3e89d6273ba1cb8a9749ef45e49b9 (diff)
downloadmullvadvpn-f8aeeb42fa5cc7f1cc428bb4b34cb8d5de09bb51.tar.xz
mullvadvpn-f8aeeb42fa5cc7f1cc428bb4b34cb8d5de09bb51.zip
Call sendProblemReport from Rust in Swift
-rw-r--r--ios/MullvadREST/ApiHandlers/RESTAPIProxy.swift14
-rw-r--r--ios/MullvadREST/Extensions/String+UnsafePointer.swift16
-rw-r--r--ios/MullvadREST/MullvadAPI/APIRequest/APIRequest.swift5
-rw-r--r--ios/MullvadREST/MullvadAPI/MullvadApiRequestFactory.swift28
-rw-r--r--ios/MullvadREST/Transport/APITransport.swift1
-rw-r--r--ios/MullvadVPN.xcodeproj/project.pbxproj4
-rw-r--r--ios/MullvadVPN/View controllers/ProblemReport/ProblemReportInteractor.swift7
-rw-r--r--mullvad-api/src/lib.rs2
-rw-r--r--mullvad-ios/src/api_client/mod.rs2
-rw-r--r--mullvad-ios/src/api_client/response.rs1
-rw-r--r--mullvad-ios/src/api_client/send_problem_report.rs30
11 files changed, 93 insertions, 17 deletions
diff --git a/ios/MullvadREST/ApiHandlers/RESTAPIProxy.swift b/ios/MullvadREST/ApiHandlers/RESTAPIProxy.swift
index d45745446e..39585a88b7 100644
--- a/ios/MullvadREST/ApiHandlers/RESTAPIProxy.swift
+++ b/ios/MullvadREST/ApiHandlers/RESTAPIProxy.swift
@@ -263,6 +263,20 @@ extension REST {
let newExpiry: Date
}
+ public struct ProblemReportRequest: Codable, Sendable {
+ public let address: String
+ public let message: String
+ public let log: String
+ public let metadata: [String: String]
+
+ public init(address: String, message: String, log: String, metadata: [String: String]) {
+ self.address = address
+ self.message = message
+ self.log = log
+ self.metadata = metadata
+ }
+ }
+
private struct SubmitVoucherRequest: Encodable, Sendable {
let voucherCode: String
}
diff --git a/ios/MullvadREST/Extensions/String+UnsafePointer.swift b/ios/MullvadREST/Extensions/String+UnsafePointer.swift
new file mode 100644
index 0000000000..4d60a1c77e
--- /dev/null
+++ b/ios/MullvadREST/Extensions/String+UnsafePointer.swift
@@ -0,0 +1,16 @@
+//
+// String+UnsafePointer.swift
+// MullvadVPN
+//
+// Created by Mojgan on 2025-03-19.
+// Copyright © 2025 Mullvad VPN AB. All rights reserved.
+//
+import Foundation
+extension String {
+ func toUnsafePointer() -> UnsafePointer<UInt8>? {
+ guard let data = self.data(using: .utf8) else { return nil }
+ let buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: data.count)
+ data.copyBytes(to: buffer, count: data.count)
+ return UnsafePointer(buffer)
+ }
+}
diff --git a/ios/MullvadREST/MullvadAPI/APIRequest/APIRequest.swift b/ios/MullvadREST/MullvadAPI/APIRequest/APIRequest.swift
index 68e7e41663..7810230464 100644
--- a/ios/MullvadREST/MullvadAPI/APIRequest/APIRequest.swift
+++ b/ios/MullvadREST/MullvadAPI/APIRequest/APIRequest.swift
@@ -9,6 +9,8 @@
public enum APIRequest: Codable, Sendable {
case getAddressList(_ retryStrategy: REST.RetryStrategy)
case getRelayList(_ retryStrategy: REST.RetryStrategy, etag: String?)
+ case sendProblemReport(_ retryStrategy: REST.RetryStrategy, problemReportRequest: REST.ProblemReportRequest)
+
case createAccount(_ retryStrategy: REST.RetryStrategy)
case getAccount(_ retryStrategy: REST.RetryStrategy, accountNumber: String)
case deleteAccount(_ retryStrategy: REST.RetryStrategy, accountNumber: String)
@@ -19,6 +21,8 @@ public enum APIRequest: Codable, Sendable {
"get-address-list"
case .getRelayList:
"get-relay-list"
+ case .sendProblemReport:
+ "send-problem-report"
case .createAccount:
"create-account"
case .getAccount:
@@ -33,6 +37,7 @@ public enum APIRequest: Codable, Sendable {
case
let .getAddressList(strategy),
let .getRelayList(strategy, _),
+ let .sendProblemReport(strategy, _),
let .createAccount(strategy),
let .getAccount(strategy, _),
let .deleteAccount(strategy, _):
diff --git a/ios/MullvadREST/MullvadAPI/MullvadApiRequestFactory.swift b/ios/MullvadREST/MullvadAPI/MullvadApiRequestFactory.swift
index 298d3ac31f..970f70ef76 100644
--- a/ios/MullvadREST/MullvadAPI/MullvadApiRequestFactory.swift
+++ b/ios/MullvadREST/MullvadAPI/MullvadApiRequestFactory.swift
@@ -39,6 +39,13 @@ public struct MullvadApiRequestFactory: Sendable {
retryStrategy.toRustStrategy(),
etag
))
+ case let .sendProblemReport(retryStrategy, problemReportRequest):
+ MullvadApiCancellable(handle: mullvad_api_send_problem_report(
+ apiContext.context,
+ rawCompletionPointer,
+ retryStrategy.toRustStrategy(),
+ problemReportRequest.toRust()
+ ))
case let .getAccount(retryStrategy, accountNumber: accountNumber):
MullvadApiCancellable(handle: mullvad_api_get_account(
apiContext.context,
@@ -67,3 +74,24 @@ public struct MullvadApiRequestFactory: Sendable {
extension REST {
public typealias MullvadApiRequestHandler = (((MullvadApiResponse) throws -> Void)?) -> MullvadApiCancellable
}
+
+private extension REST.ProblemReportRequest {
+ func toRust() -> UnsafePointer<SwiftProblemReportRequest> {
+ let structPointer = UnsafeMutablePointer<SwiftProblemReportRequest>.allocate(capacity: 1)
+
+ let addressPointer = address.toUnsafePointer()
+ let messagePointer = message.toUnsafePointer()
+ let logPointer = log.toUnsafePointer()
+
+ structPointer.initialize(to: SwiftProblemReportRequest(
+ address: addressPointer,
+ address_len: UInt(address.utf8.count),
+ message: messagePointer,
+ message_len: UInt(message.utf8.count),
+ log: logPointer,
+ log_len: UInt(log.utf8.count)
+ ))
+
+ return UnsafePointer(structPointer)
+ }
+}
diff --git a/ios/MullvadREST/Transport/APITransport.swift b/ios/MullvadREST/Transport/APITransport.swift
index 9af1f2779f..d0bf7db48d 100644
--- a/ios/MullvadREST/Transport/APITransport.swift
+++ b/ios/MullvadREST/Transport/APITransport.swift
@@ -34,7 +34,6 @@ public final class APITransport: APITransportProtocol {
let apiRequest = requestFactory.makeRequest(request)
return apiRequest { response in
-
let error: APIError? = if !response.success {
APIError(
statusCode: Int(response.statusCode),
diff --git a/ios/MullvadVPN.xcodeproj/project.pbxproj b/ios/MullvadVPN.xcodeproj/project.pbxproj
index 050bd50e1c..8c64f72340 100644
--- a/ios/MullvadVPN.xcodeproj/project.pbxproj
+++ b/ios/MullvadVPN.xcodeproj/project.pbxproj
@@ -977,6 +977,7 @@
F062000A2CB7EB42002E6DB9 /* CGSize+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = F06200092CB7EB42002E6DB9 /* CGSize+Helpers.swift */; };
F062000C2CB7EB5D002E6DB9 /* UIImage+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = F062000B2CB7EB5D002E6DB9 /* UIImage+Helpers.swift */; };
F062B94D2C16E09700B6D47A /* TunnelSettingsManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F062B94C2C16E09700B6D47A /* TunnelSettingsManagerTests.swift */; };
+ F0647C322D8AF1E800D2C489 /* String+UnsafePointer.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0647C312D8AF1CD00D2C489 /* String+UnsafePointer.swift */; };
F072D3CF2C07122400906F64 /* SettingsUpdaterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F072D3CE2C07122400906F64 /* SettingsUpdaterTests.swift */; };
F072D3D22C071AD100906F64 /* ShadowsocksLoaderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F072D3D12C071AD100906F64 /* ShadowsocksLoaderTests.swift */; };
F073FCB32C6617D70062EA1D /* TunnelStore+Stubs.swift in Sources */ = {isa = PBXBuildFile; fileRef = F073FCB22C6617D70062EA1D /* TunnelStore+Stubs.swift */; };
@@ -2404,6 +2405,7 @@
F06200092CB7EB42002E6DB9 /* CGSize+Helpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CGSize+Helpers.swift"; sourceTree = "<group>"; };
F062000B2CB7EB5D002E6DB9 /* UIImage+Helpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImage+Helpers.swift"; sourceTree = "<group>"; };
F062B94C2C16E09700B6D47A /* TunnelSettingsManagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelSettingsManagerTests.swift; sourceTree = "<group>"; };
+ F0647C312D8AF1CD00D2C489 /* String+UnsafePointer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+UnsafePointer.swift"; sourceTree = "<group>"; };
F072D3CE2C07122400906F64 /* SettingsUpdaterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsUpdaterTests.swift; sourceTree = "<group>"; };
F072D3D12C071AD100906F64 /* ShadowsocksLoaderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShadowsocksLoaderTests.swift; sourceTree = "<group>"; };
F073FCB22C6617D70062EA1D /* TunnelStore+Stubs.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "TunnelStore+Stubs.swift"; sourceTree = "<group>"; };
@@ -4325,6 +4327,7 @@
7AD63A422CDA661B00445268 /* Extensions */ = {
isa = PBXGroup;
children = (
+ F0647C312D8AF1CD00D2C489 /* String+UnsafePointer.swift */,
7AD63A432CDA662900445268 /* UInt+Counting.swift */,
);
path = Extensions;
@@ -5812,6 +5815,7 @@
F06045EA2B23217E00B2D37A /* ShadowsocksTransport.swift in Sources */,
06799AFC28F98EE300ACD94E /* AddressCache.swift in Sources */,
7ADCB2D82B6A6EB300C88F89 /* AnyRelay.swift in Sources */,
+ F0647C322D8AF1E800D2C489 /* String+UnsafePointer.swift in Sources */,
06799AF028F98E4800ACD94E /* REST.swift in Sources */,
06799ADF28F98E4800ACD94E /* RESTDevicesProxy.swift in Sources */,
06799ADA28F98E4800ACD94E /* RESTResponseHandler.swift in Sources */,
diff --git a/ios/MullvadVPN/View controllers/ProblemReport/ProblemReportInteractor.swift b/ios/MullvadVPN/View controllers/ProblemReport/ProblemReportInteractor.swift
index 6640473e4a..55fc1df7d3 100644
--- a/ios/MullvadVPN/View controllers/ProblemReport/ProblemReportInteractor.swift
+++ b/ios/MullvadVPN/View controllers/ProblemReport/ProblemReportInteractor.swift
@@ -80,13 +80,10 @@ final class ProblemReportInteractor: @unchecked Sendable {
metadata: metadataDict
)
- _ = self.apiProxy.sendProblemReport(
- request,
- retryStrategy: .default
- ) { result in
+ _ = self.apiProxy.mullvadSendProblemReport(request, retryStrategy: .default, completionHandler: { result in
DispatchQueue.main.async {
completion(result)
}
- }
+ })
}
}
diff --git a/mullvad-api/src/lib.rs b/mullvad-api/src/lib.rs
index 987098c591..eb3589ac67 100644
--- a/mullvad-api/src/lib.rs
+++ b/mullvad-api/src/lib.rs
@@ -687,7 +687,7 @@ impl ProblemReportProxy {
log: &str,
metadata: &BTreeMap<String, String>,
) -> impl Future<Output = Result<(), rest::Error>> {
- let future = self.porblem_report_response(email, message, log, metadata);
+ let future = self.porblem_report_response(email, message, log, metadata);
async move {
future.await?;
diff --git a/mullvad-ios/src/api_client/mod.rs b/mullvad-ios/src/api_client/mod.rs
index 234724530e..1018ef4b95 100644
--- a/mullvad-ios/src/api_client/mod.rs
+++ b/mullvad-ios/src/api_client/mod.rs
@@ -15,7 +15,7 @@ mod cancellation;
mod completion;
mod response;
mod retry_strategy;
-mod send_problem_report;
+mod send_problem_report;
#[repr(C)]
pub struct SwiftApiContext(*const ApiContext);
diff --git a/mullvad-ios/src/api_client/response.rs b/mullvad-ios/src/api_client/response.rs
index 90f1552ffd..3b017e37c6 100644
--- a/mullvad-ios/src/api_client/response.rs
+++ b/mullvad-ios/src/api_client/response.rs
@@ -8,7 +8,6 @@ use mullvad_api::{
RelayListProxy, StatusCode,
};
-
#[repr(C)]
pub struct SwiftMullvadApiResponse {
body: *mut u8,
diff --git a/mullvad-ios/src/api_client/send_problem_report.rs b/mullvad-ios/src/api_client/send_problem_report.rs
index f96f8926d2..1d2547298f 100644
--- a/mullvad-ios/src/api_client/send_problem_report.rs
+++ b/mullvad-ios/src/api_client/send_problem_report.rs
@@ -13,7 +13,7 @@ use super::{
};
use mullvad_api::rest::Error;
-use std::{collections::BTreeMap};
+use std::collections::BTreeMap;
use std::slice;
use tokio::task::JoinHandle;
@@ -35,10 +35,15 @@ pub unsafe extern "C" fn mullvad_api_send_problem_report(
let api_context = api_context.into_rust_context();
let retry_strategy = unsafe { retry_strategy.into_rust() };
- let problem_report_request = match unsafe { ProblemReportRequest::from_swift_parameters(request) } {
+ let problem_report_request = match unsafe {
+ ProblemReportRequest::from_swift_parameters(request)
+ } {
Some(req) => req,
None => {
- let err = Error::ApiError(rest::StatusCode::BAD_REQUEST, "Failed to send problem report: invalid address, message, or log data.".to_string());
+ let err = Error::ApiError(
+ rest::StatusCode::BAD_REQUEST,
+ "Failed to send problem report: invalid address, message, or log data.".to_string(),
+ );
log::error!("{err:?}");
completion.finish(SwiftMullvadApiResponse::rest_error(err));
return SwiftCancelHandle::empty();
@@ -72,7 +77,14 @@ async fn mullvad_api_send_problem_report_inner(
let api = ProblemReportProxy::new(rest_client);
let empty_metadata: BTreeMap<String, String> = BTreeMap::new();
- let future_factory = || api.porblem_report_response(&problem_report_request.address, &problem_report_request.message, &(String::from_utf8_lossy(&problem_report_request.log)), &empty_metadata);
+ let future_factory = || {
+ api.porblem_report_response(
+ &problem_report_request.address,
+ &problem_report_request.message,
+ &(String::from_utf8_lossy(&problem_report_request.log)),
+ &empty_metadata,
+ )
+ };
let should_retry = |result: &Result<_, rest::Error>| match result {
Err(err) => err.is_network_error(),
@@ -81,7 +93,6 @@ async fn mullvad_api_send_problem_report_inner(
let response = retry_future(future_factory, should_retry, retry_strategy.delays()).await?;
SwiftMullvadApiResponse::with_body(response).await
-
}
#[repr(C)]
@@ -100,7 +111,6 @@ struct ProblemReportRequest {
log: Vec<u8>,
}
-
unsafe impl Send for SwiftProblemReportRequest {}
impl ProblemReportRequest {
@@ -119,6 +129,10 @@ impl ProblemReportRequest {
let message = String::from_utf8(message_slice.to_vec()).ok()?;
let log = log_slice.to_vec();
- Some(Self { address, message, log })
+ Some(Self {
+ address,
+ message,
+ log,
+ })
}
-} \ No newline at end of file
+}