main

mattermost/focalboard

Last updated at: 28/12/2023 01:37

PortUtils.swift

TLDR

The PortUtils.swift file contains a PortUtils class with two methods: isPortFree and getFreePort. The isPortFree method checks if a specific port is free, and the getFreePort method returns an available port number.

Methods

isPortFree

This method checks if a given port number is free or in use. It creates a socket file descriptor and attempts to bind it to the specified port. If the port is free, the method returns true; otherwise, it returns false.

getFreePort

This method iterates from port number 50000 to 65000 and calls the isPortFree method for each port. It returns the first available (free) port number found within the specified range. If no free port is found, it returns 0.

// 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)
	}
}