Fix #109: Use free port on Mac

This commit is contained in:
Chen-I Lim 2021-04-01 08:15:06 -07:00
parent b1f6622bb1
commit 37adf0a081
5 changed files with 83 additions and 0 deletions

View File

@ -7,6 +7,7 @@
objects = {
/* Begin PBXBuildFile section */
8014951C261598D600A51700 /* PortUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8014951B261598D600A51700 /* PortUtils.swift */; };
80D6DEBB252E13CB00AEED9E /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80D6DEBA252E13CB00AEED9E /* AppDelegate.swift */; };
80D6DEBD252E13CB00AEED9E /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80D6DEBC252E13CB00AEED9E /* ViewController.swift */; };
80D6DEBF252E13CD00AEED9E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 80D6DEBE252E13CD00AEED9E /* Assets.xcassets */; };
@ -35,6 +36,7 @@
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
8014951B261598D600A51700 /* PortUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PortUtils.swift; sourceTree = "<group>"; };
80D6DEB7252E13CB00AEED9E /* Focalboard.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Focalboard.app; sourceTree = BUILT_PRODUCTS_DIR; };
80D6DEBA252E13CB00AEED9E /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
80D6DEBC252E13CB00AEED9E /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
@ -103,6 +105,7 @@
isa = PBXGroup;
children = (
80D6DEBA252E13CB00AEED9E /* AppDelegate.swift */,
8014951B261598D600A51700 /* PortUtils.swift */,
80D6DEBC252E13CB00AEED9E /* ViewController.swift */,
80D6DF17252F9BDE00AEED9E /* AutoSaveWindowController.swift */,
80D6DEBE252E13CD00AEED9E /* Assets.xcassets */,
@ -283,6 +286,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
8014951C261598D600A51700 /* PortUtils.swift in Sources */,
80D6DF18252F9BDE00AEED9E /* AutoSaveWindowController.swift in Sources */,
80D6DEBD252E13CB00AEED9E /* ViewController.swift in Sources */,
80D6DEBB252E13CB00AEED9E /* AppDelegate.swift in Sources */,

View File

@ -88,7 +88,16 @@ class AppDelegate: NSObject, NSApplicationDelegate {
return "su-" + randomNumber
}
private func getFreePort() {
if PortUtils.isPortFree(in_port_t(serverPort)) {
return
}
serverPort = Int(PortUtils.getFreePort())
}
private func startServer() {
getFreePort()
sessionToken = generateSessionToken()
let cwdUrl = webFolder()

View File

@ -578,6 +578,13 @@
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="hB3-LF-h0Y"/>
<menuItem title="Diagnostics Info" id="oQB-FY-dcB">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="showDiagnosticsInfo:" target="Ady-hI-5gd" id="hkZ-Xn-3T1"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="dRF-4R-egy"/>
<menuItem title="Show Sidebar" keyEquivalent="s" id="kIP-vf-haE">
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
<connections>

View File

@ -0,0 +1,52 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import Foundation
class PortUtils {
static func isPortFree(_ port: in_port_t) -> Bool {
let socketFileDescriptor = socket(AF_INET, SOCK_STREAM, 0)
if socketFileDescriptor == -1 {
return false
}
var addr = sockaddr_in()
let sizeOfSockkAddr = MemoryLayout<sockaddr_in>.size
addr.sin_len = __uint8_t(sizeOfSockkAddr)
addr.sin_family = sa_family_t(AF_INET)
addr.sin_port = Int(OSHostByteOrder()) == OSLittleEndian ? _OSSwapInt16(port) : port
addr.sin_addr = in_addr(s_addr: inet_addr("127.0.0.1"))
addr.sin_zero = (0, 0, 0, 0, 0, 0, 0, 0)
var bind_addr = sockaddr()
memcpy(&bind_addr, &addr, Int(sizeOfSockkAddr))
if Darwin.bind(socketFileDescriptor, &bind_addr, socklen_t(sizeOfSockkAddr)) == -1 {
release(socket: socketFileDescriptor)
return false
}
if listen(socketFileDescriptor, SOMAXCONN ) == -1 {
release(socket: socketFileDescriptor)
return false
}
release(socket: socketFileDescriptor)
return true
}
private static func release(socket: Int32) {
Darwin.shutdown(socket, SHUT_RDWR)
close(socket)
}
static func getFreePort() -> in_port_t {
var portNum: in_port_t = 0
for i in 50000..<65000 {
let isFree = isPortFree(in_port_t(i))
if isFree {
portNum = in_port_t(i)
return portNum
}
}
return in_port_t(0)
}
}

View File

@ -45,6 +45,17 @@ class ViewController:
WKWebsiteDataStore.default().removeData(ofTypes: websiteDataTypes as! Set<String>, modifiedSince: date, completionHandler:{ })
}
@IBAction func showDiagnosticsInfo(_ sender: NSObject) {
let appDelegate = NSApplication.shared.delegate as! AppDelegate
let alert: NSAlert = NSAlert()
alert.messageText = "Diagnostics info"
alert.informativeText = "Port: \(appDelegate.serverPort)"
alert.alertStyle = .informational
alert.addButton(withTitle: "OK")
alert.runModal()
}
@objc func onServerStarted() {
NSLog("onServerStarted")
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {