diff --git a/airsync-mac/Components/Buttons/SaveAndRestartButton.swift b/airsync-mac/Components/Buttons/SaveAndRestartButton.swift index 0c5d6d46..46d55fb4 100644 --- a/airsync-mac/Components/Buttons/SaveAndRestartButton.swift +++ b/airsync-mac/Components/Buttons/SaveAndRestartButton.swift @@ -15,14 +15,14 @@ struct SaveAndRestartButton: View { let port: String let version: String let onSave: ((Device) -> Void)? - let onRestart: ((UInt16) -> Void)? + let onRestart: ((UInt32) -> Void)? @ObservedObject var appState: AppState = .shared var body: some View { HStack { Button(title, systemImage: systemImage) { - let portNumber = UInt16(port) ?? Defaults.serverPort + let portNumber = UInt32(port) ?? Defaults.serverPort let ipAddress = WebSocketServer.shared.getLocalIPAddress( adapterName: appState.selectedNetworkAdapterName ) ?? "N/A" diff --git a/airsync-mac/Constants/Constants.swift b/airsync-mac/Constants/Constants.swift index 6e0356e3..d7ebc067 100644 --- a/airsync-mac/Constants/Constants.swift +++ b/airsync-mac/Constants/Constants.swift @@ -9,6 +9,6 @@ import Foundation // Constants.swift enum Defaults { - static let serverPort: UInt16 = 6996 + static let serverPort: UInt32 = 6996 } diff --git a/airsync-mac/Core/AppState.swift b/airsync-mac/Core/AppState.swift index 31a6bac6..52d1ad1a 100644 --- a/airsync-mac/Core/AppState.swift +++ b/airsync-mac/Core/AppState.swift @@ -30,7 +30,7 @@ class AppState: ObservableObject { let adbPortValue = UserDefaults.standard.integer(forKey: "adbPort") let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "2.0.0" - self.adbPort = adbPortValue == 0 ? 5555 : UInt16(adbPortValue) + self.adbPort = adbPortValue == 0 ? 5555 : UInt32(adbPortValue) self.mirroringPlus = UserDefaults.standard.bool(forKey: "mirroringPlus") self.adbEnabled = UserDefaults.standard.bool(forKey: "adbEnabled") self.showMenubarText = UserDefaults.standard.bool(forKey: "showMenubarText") @@ -120,7 +120,7 @@ class AppState: ObservableObject { @Published var notifications: [Notification] = [] @Published var status: DeviceStatus? = nil @Published var myDevice: Device? = nil - @Published var port: UInt16 = Defaults.serverPort + @Published var port: UInt32 = Defaults.serverPort @Published var androidApps: [String: AndroidApp] = [:] @Published var deviceWallpapers: [String: String] = [:] // key = deviceName-ip, value = file path @@ -182,7 +182,7 @@ class AppState: ObservableObject { } } - @Published var adbPort: UInt16 { + @Published var adbPort: UInt32 { didSet { UserDefaults.standard.set(adbPort, forKey: "adbPort") } diff --git a/airsync-mac/Core/QuickConnect/QuickConnectManager.swift b/airsync-mac/Core/QuickConnect/QuickConnectManager.swift index 5aeb9904..cbd2ef7a 100644 --- a/airsync-mac/Core/QuickConnect/QuickConnectManager.swift +++ b/airsync-mac/Core/QuickConnect/QuickConnectManager.swift @@ -88,7 +88,7 @@ class QuickConnectManager: ObservableObject { ) } - private func getCurrentMacPort() -> UInt16? { + private func getCurrentMacPort() -> UInt32? { return WebSocketServer.shared.localPort } @@ -188,7 +188,7 @@ class QuickConnectManager: ObservableObject { var addr = sockaddr_in() addr.sin_family = sa_family_t(AF_INET) - addr.sin_port = UInt16(Self.ANDROID_UDP_WAKEUP_PORT).bigEndian + addr.sin_port = in_port_t(UInt32(Self.ANDROID_UDP_WAKEUP_PORT).bigEndian) inet_aton(device.ipAddress, &addr.sin_addr) let messageData = udpMessage.data(using: .utf8) ?? Data() diff --git a/airsync-mac/Core/Util/CLI/ADBConnector.swift b/airsync-mac/Core/Util/CLI/ADBConnector.swift index 502b448c..f404e196 100644 --- a/airsync-mac/Core/Util/CLI/ADBConnector.swift +++ b/airsync-mac/Core/Util/CLI/ADBConnector.swift @@ -112,15 +112,15 @@ Raw output: } let lines = trimmedMDNSOutput.components(separatedBy: .newlines) - var tlsPort: UInt16? - var normalPort: UInt16? + var tlsPort: UInt32? + var normalPort: UInt32? for line in lines { guard let range = line.range(of: "\(ip):") else { continue } let remaining = line[range.upperBound...] if let portStr = remaining.split(separator: " ").first, - let port = UInt16(portStr) { + let port = UInt32(portStr) { if line.contains("_adb-tls-connect._tcp"), tlsPort == nil { tlsPort = port } else if line.contains("_adb._tcp"), normalPort == nil { @@ -262,7 +262,7 @@ Raw output: static func startScrcpy( ip: String, - port: UInt16, + port: UInt32, deviceName: String, desktop: Bool? = false, package: String? = nil diff --git a/airsync-mac/Core/WebSocket/WebSocketServer.swift b/airsync-mac/Core/WebSocket/WebSocketServer.swift index b5a635db..627f2e0b 100644 --- a/airsync-mac/Core/WebSocket/WebSocketServer.swift +++ b/airsync-mac/Core/WebSocket/WebSocketServer.swift @@ -18,7 +18,7 @@ import CryptoKit enum WebSocketStatus { case stopped case starting - case started(port: UInt16, ip: String?) + case started(port: UInt32, ip: String?) case failed(error: String) } @@ -29,7 +29,7 @@ class WebSocketServer: ObservableObject { private var activeSessions: [WebSocketSession] = [] @Published var symmetricKey: SymmetricKey? - @Published var localPort: UInt16? + @Published var localPort: UInt32? @Published var localIPAddress: String? @Published var connectedDevice: Device? @@ -70,14 +70,23 @@ class WebSocketServer: ObservableObject { } } - func start(port: UInt16 = Defaults.serverPort) { + func start(port: UInt32 = Defaults.serverPort) { DispatchQueue.main.async { AppState.shared.webSocketStatus = .starting } DispatchQueue.main.asyncAfter(deadline: .now() + 1) { do { - try self.server.start(port) + guard port > 0 && port <= 65_535 else { + let msg = "[websocket] Invalid port \(port). Must be in 1...65535." + DispatchQueue.main.async { + AppState.shared.webSocketStatus = .failed(error: msg) + } + print(msg) + return + } + + try self.server.start(in_port_t(port)) let ip = self.getLocalIPAddress(adapterName: AppState.shared.selectedNetworkAdapterName) DispatchQueue.main.async { @@ -304,13 +313,13 @@ class WebSocketServer: ObservableObject { } // mark first-time pairing - if UserDefaults.standard.hasPairedDeviceOnce == false { - UserDefaults.standard.hasPairedDeviceOnce = true - } - - // Send Mac info response to Android - sendMacInfoResponse() - } + if UserDefaults.standard.hasPairedDeviceOnce == false { + UserDefaults.standard.hasPairedDeviceOnce = true + } + + // Send Mac info response to Android + sendMacInfoResponse() + } case .notification: diff --git a/airsync-mac/Screens/ScannerView/ScannerView.swift b/airsync-mac/Screens/ScannerView/ScannerView.swift index 3865f9c1..9e0fc81a 100644 --- a/airsync-mac/Screens/ScannerView/ScannerView.swift +++ b/airsync-mac/Screens/ScannerView/ScannerView.swift @@ -236,7 +236,7 @@ struct ScannerView: View { let text = generateQRText( ip: validIP, - port: UInt16(appState.myDevice?.port ?? Int(Defaults.serverPort)), + port: UInt32(appState.myDevice?.port ?? Int(Defaults.serverPort)), name: appState.myDevice?.name, key: WebSocketServer.shared.getSymmetricKeyBase64() ?? "" ) ?? "That doesn't look right, QR Generation failed" @@ -267,7 +267,7 @@ struct ScannerView: View { } } -func generateQRText(ip: String?, port: UInt16?, name: String?, key: String) -> String? { +func generateQRText(ip: String?, port: UInt32?, name: String?, key: String) -> String? { guard let ip = ip, let port = port else { return nil } diff --git a/airsync-mac/Screens/Settings/SettingsView.swift b/airsync-mac/Screens/Settings/SettingsView.swift index bb0d4aca..80c389d7 100644 --- a/airsync-mac/Screens/Settings/SettingsView.swift +++ b/airsync-mac/Screens/Settings/SettingsView.swift @@ -44,7 +44,7 @@ struct SettingsView: View { currentIPAddress = WebSocketServer.shared.getLocalIPAddress(adapterName: appState.selectedNetworkAdapterName) ?? "N/A" WebSocketServer.shared.stop() - if let port = UInt16(port) { + if let port = UInt32(port) { WebSocketServer.shared.start(port: port) } else { WebSocketServer.shared.start() @@ -205,4 +205,4 @@ struct SettingsView: View { } } -} +} \ No newline at end of file diff --git a/airsync-mac/airsync_macApp.swift b/airsync-mac/airsync_macApp.swift index 16e6665d..b02171e7 100644 --- a/airsync-mac/airsync_macApp.swift +++ b/airsync-mac/airsync_macApp.swift @@ -42,8 +42,16 @@ struct airsync_macApp: App { } } - let devicePort = UInt16(AppState.shared.myDevice?.port ?? Int(Defaults.serverPort)) - WebSocketServer.shared.start(port: devicePort) + let rawPortInt = AppState.shared.myDevice?.port ?? Int(Defaults.serverPort) + let chosenPort: UInt32 + if rawPortInt <= 0 || rawPortInt > 65_535 { + print("[main-app] Invalid configured port \(rawPortInt). Falling back to 8080.") + chosenPort = UInt32(8080) + } + else { + chosenPort = UInt32(rawPortInt) + } + WebSocketServer.shared.start(port: UInt32(chosenPort)) Timer.scheduledTimer(withTimeInterval: 10, repeats: true) { _ in AppState.shared.syncWithSystemNotifications() @@ -112,7 +120,7 @@ struct airsync_macApp: App { if let device = appState.device, appState.adbConnected { ADBConnector.startScrcpy( ip: device.ipAddress, - port: appState.adbPort, + port: UInt32(appState.adbPort), deviceName: device.name, package: nil ) @@ -129,7 +137,7 @@ struct airsync_macApp: App { if let device = appState.device { ADBConnector.startScrcpy( ip: device.ipAddress, - port: appState.adbPort, + port: UInt32(appState.adbPort), deviceName: device.name, package: app.packageName ) diff --git a/appcast.xml b/appcast.xml index 9dad7e09..7ef86e49 100644 --- a/appcast.xml +++ b/appcast.xml @@ -3,12 +3,12 @@ AirSync - 2.0.33 - Tue, 23 Sep 2025 18:08:30 +0530 - 8 - 2.0.33 - 14.6 - + 2.1.1 + Thu, 02 Oct 2025 01:34:35 +0530 + 11 + 2.1.1 + 14.5 +