Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions airsync-mac/Components/Buttons/SaveAndRestartButton.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
2 changes: 1 addition & 1 deletion airsync-mac/Constants/Constants.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@ import Foundation

// Constants.swift
enum Defaults {
static let serverPort: UInt16 = 6996
static let serverPort: UInt32 = 6996
}

6 changes: 3 additions & 3 deletions airsync-mac/Core/AppState.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -182,7 +182,7 @@ class AppState: ObservableObject {
}
}

@Published var adbPort: UInt16 {
@Published var adbPort: UInt32 {
didSet {
UserDefaults.standard.set(adbPort, forKey: "adbPort")
}
Expand Down
4 changes: 2 additions & 2 deletions airsync-mac/Core/QuickConnect/QuickConnectManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ class QuickConnectManager: ObservableObject {
)
}

private func getCurrentMacPort() -> UInt16? {
private func getCurrentMacPort() -> UInt32? {
return WebSocketServer.shared.localPort
}

Expand Down Expand Up @@ -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()
Expand Down
8 changes: 4 additions & 4 deletions airsync-mac/Core/Util/CLI/ADBConnector.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -262,7 +262,7 @@ Raw output:

static func startScrcpy(
ip: String,
port: UInt16,
port: UInt32,
deviceName: String,
desktop: Bool? = false,
package: String? = nil
Expand Down
31 changes: 20 additions & 11 deletions airsync-mac/Core/WebSocket/WebSocketServer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}

Expand All @@ -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?
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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:
Expand Down
4 changes: 2 additions & 2 deletions airsync-mac/Screens/ScannerView/ScannerView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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
}
Expand Down
4 changes: 2 additions & 2 deletions airsync-mac/Screens/Settings/SettingsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -205,4 +205,4 @@ struct SettingsView: View {
}
}

}
}
16 changes: 12 additions & 4 deletions airsync-mac/airsync_macApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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
)
Expand All @@ -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
)
Expand Down
12 changes: 6 additions & 6 deletions appcast.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
<channel>
<title>AirSync</title>
<item>
<title>2.0.33</title>
<pubDate>Tue, 23 Sep 2025 18:08:30 +0530</pubDate>
<sparkle:version>8</sparkle:version>
<sparkle:shortVersionString>2.0.33</sparkle:shortVersionString>
<sparkle:minimumSystemVersion>14.6</sparkle:minimumSystemVersion>
<enclosure url="https://github.com/sameerasw/airsync-mac/releases/download/v2.0.33-BETA/AirSync.dmg" length="22636823" type="application/octet-stream" sparkle:edSignature="yblEGKg6JqfjP4v1dLhju4rwuqKgcx5T6/NNHl5ry8i5v3lDlxuSpEzqqOPYMrDmvjndYSR2GSaFrkE30xxSCw=="/>
<title>2.1.1</title>
<pubDate>Thu, 02 Oct 2025 01:34:35 +0530</pubDate>
<sparkle:version>11</sparkle:version>
<sparkle:shortVersionString>2.1.1</sparkle:shortVersionString>
<sparkle:minimumSystemVersion>14.5</sparkle:minimumSystemVersion>
<enclosure url="https://github.com/sameerasw/airsync-mac/releases/download/v2.1.1/AirSync.dmg" length="22756657" type="application/octet-stream" sparkle:edSignature="WaHziQTEYjGLn4+FZAIodyJGWG4y11Zhc1jPWkgNf3STn53jqOiWxOjZ/De+qfzPKp9XjIccT/HIelCmP/z0CA=="/>
</item>
</channel>
</rss>