Skip to content

Commit 016e7f0

Browse files
committed
Use the Firewall API to get the device IP address
1 parent d45bab5 commit 016e7f0

File tree

3 files changed

+37
-49
lines changed

3 files changed

+37
-49
lines changed

ios/MullvadVPNUITests/Networking/FirewallAPIClient.swift

+34
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,40 @@ class FirewallAPIClient {
7777
}
7878
}
7979

80+
/// Gets the IP address of the device under test
81+
public func getDeviceIPAddress() throws -> String {
82+
let deviceIPURL = baseURL.appendingPathComponent("own-ip")
83+
let request = URLRequest(url: deviceIPURL)
84+
let completionHandlerInvokedExpectation = XCTestExpectation(
85+
description: "Completion handler for the request is invoked"
86+
)
87+
var deviceIPAddress = ""
88+
var requestError: Error?
89+
90+
let dataTask = URLSession.shared.dataTask(with: request) { data, _, _ in
91+
defer { completionHandlerInvokedExpectation.fulfill() }
92+
guard let data else {
93+
requestError = NetworkingError.internalError(reason: "Could not get device IP")
94+
return
95+
}
96+
97+
deviceIPAddress = String(data: data, encoding: .utf8)!
98+
}
99+
100+
dataTask.resume()
101+
102+
let waitResult = XCTWaiter.wait(for: [completionHandlerInvokedExpectation], timeout: 30)
103+
if waitResult != .completed {
104+
XCTFail("Failed to get device IP address - timeout")
105+
}
106+
107+
if let requestError {
108+
throw requestError
109+
}
110+
111+
return deviceIPAddress
112+
}
113+
80114
/// Remove all firewall rules associated to this device under test
81115
public func removeRules() {
82116
let removeRulesURL = baseURL.appendingPathComponent("remove-rules/\(sessionIdentifier)")

ios/MullvadVPNUITests/Networking/FirewallRule.swift

+3-3
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ struct FirewallRule {
3636

3737
/// Make a firewall rule blocking API access for the current device under test
3838
public static func makeBlockAPIAccessFirewallRule() throws -> FirewallRule {
39-
let deviceIPAddress = try Networking.getIPAddress()
39+
let deviceIPAddress = try FirewallAPIClient().getDeviceIPAddress()
4040
let apiIPAddress = try MullvadAPIWrapper.getAPIIPAddress()
4141
return FirewallRule(
4242
fromIPAddress: deviceIPAddress,
@@ -46,7 +46,7 @@ struct FirewallRule {
4646
}
4747

4848
public static func makeBlockAllTrafficRule(toIPAddress: String) throws -> FirewallRule {
49-
let deviceIPAddress = try Networking.getIPAddress()
49+
let deviceIPAddress = try FirewallAPIClient().getDeviceIPAddress()
5050

5151
return FirewallRule(
5252
fromIPAddress: deviceIPAddress,
@@ -56,7 +56,7 @@ struct FirewallRule {
5656
}
5757

5858
public static func makeBlockUDPTrafficRule(toIPAddress: String) throws -> FirewallRule {
59-
let deviceIPAddress = try Networking.getIPAddress()
59+
let deviceIPAddress = try FirewallAPIClient().getDeviceIPAddress()
6060

6161
return FirewallRule(
6262
fromIPAddress: deviceIPAddress,

ios/MullvadVPNUITests/Networking/Networking.swift

-46
Original file line numberDiff line numberDiff line change
@@ -22,52 +22,6 @@ struct DNSServerEntry: Decodable {
2222

2323
/// Class with methods for verifying network connectivity
2424
class Networking {
25-
/// Get IP address of the iOS device under test
26-
static func getIPAddress() throws -> String {
27-
var ipAddress: String
28-
// Get list of all interfaces on the local machine:
29-
var interfaceList: UnsafeMutablePointer<ifaddrs>?
30-
guard getifaddrs(&interfaceList) == 0, let firstInterfaceAddress = interfaceList else {
31-
throw NetworkingError.internalError(reason: "Failed to locate local networking interface")
32-
}
33-
34-
// For each interface
35-
for interfacePointer in sequence(first: firstInterfaceAddress, next: { $0.pointee.ifa_next }) {
36-
let flags = Int32(interfacePointer.pointee.ifa_flags)
37-
let interfaceAddress = interfacePointer.pointee.ifa_addr.pointee
38-
39-
// Check for running IPv4 interfaces. Skip the loopback interface.
40-
if (
41-
flags &
42-
(IFF_UP | IFF_RUNNING | IFF_LOOPBACK)
43-
) == (IFF_UP | IFF_RUNNING),
44-
interfaceAddress.sa_family == UInt8(AF_INET) {
45-
// Check if interface is en0 which is the WiFi connection on the iPhone
46-
let name = String(cString: interfacePointer.pointee.ifa_name)
47-
// Convert interface address to a human readable string:
48-
var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))
49-
if getnameinfo(
50-
interfacePointer.pointee.ifa_addr,
51-
socklen_t(interfaceAddress.sa_len),
52-
&hostname,
53-
socklen_t(hostname.count),
54-
nil,
55-
socklen_t(0),
56-
NI_NUMERICHOST
57-
) == 0 {
58-
ipAddress = String(cString: hostname)
59-
if ipAddress.starts(with: "192.168") {
60-
return ipAddress
61-
}
62-
}
63-
}
64-
}
65-
66-
freeifaddrs(interfaceList)
67-
68-
throw NetworkingError.internalError(reason: "No local IP found")
69-
}
70-
7125
/// Get configured ad serving domain
7226
private static func getAdServingDomain() throws -> String {
7327
guard let adServingDomain = Bundle(for: Networking.self)

0 commit comments

Comments
 (0)