PortUtils.swift
TLDR
This file contains a class called PortUtils
that provides methods for checking if a port is free and getting a free port.
Methods
isPortFree
This method takes a port number as input and checks if the port is available for use. It creates a socket file descriptor and sets up a socket address structure. It then attempts to bind the socket to the given port and if successful, it listens on the socket for incoming connections. If any of these steps fail, the socket is released and the method returns false
. If all steps are successful, the method returns true
.
getFreePort
This method iterates through a range of port numbers from 50000 to 65000 and calls the isPortFree
method for each port to check if it is available. It returns the first free port it finds, or 0 if no free port is found.
// 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)
}
}