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
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ cleancontent:

.PHONY: clean
clean:
@echo Cleaning the build files...
@echo Cleaning build files...
@rm -rf bin/ libexec/
@rm -rf _site _serve
@$(SWIFT) package clean
3 changes: 1 addition & 2 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -261,8 +261,7 @@ let package = Package(
.target(
name: "TerminalProgress",
dependencies: [
.product(name: "ContainerizationOS", package: "containerization"),
.product(name: "SendableProperty", package: "containerization"),
.product(name: "ContainerizationOS", package: "containerization")
]
),
.testTarget(
Expand Down
52 changes: 32 additions & 20 deletions Sources/Services/ContainerNetworkService/ReservedVmnetNetwork.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,23 +21,27 @@ import ContainerizationExtras
import Dispatch
import Foundation
import Logging
import SendableProperty
import Synchronization
import SystemConfiguration
import XPC
import vmnet

/// Creates a vmnet network with reservation APIs.
@available(macOS 26, *)
public final class ReservedVmnetNetwork: Network {
@SendablePropertyUnchecked
private var _state: NetworkState
private let log: Logger
private struct State {
var networkState: NetworkState
var network: vmnet_network_ref?
}

private struct NetworkInfo {
let network: vmnet_network_ref
let subnet: CIDRAddress
let gateway: IPv4Address
}

@SendableProperty
private var network: vmnet_network_ref?
@SendableProperty
private var interface: interface_ref?
private let networkLock = NSLock()
private let stateMutex: Mutex<State>
private let log: Logger

/// Configure a bridge network that allows external system access using
/// network address translation.
Expand All @@ -51,26 +55,33 @@ public final class ReservedVmnetNetwork: Network {

log.info("creating vmnet network")
self.log = log
_state = .created(configuration)
let initialState = State(networkState: .created(configuration))
stateMutex = Mutex(initialState)
log.info("created vmnet network")
}

public var state: NetworkState {
get async { _state }
stateMutex.withLock { $0.networkState }
}

public nonisolated func withAdditionalData(_ handler: (XPCMessage?) throws -> Void) throws {
try networkLock.withLock {
try handler(network.map { try Self.serialize_network_ref(ref: $0) })
try stateMutex.withLock { state in
try handler(state.network.map { try Self.serialize_network_ref(ref: $0) })
}
}

public func start() async throws {
guard case .created(let configuration) = _state else {
throw ContainerizationError(.invalidArgument, message: "cannot start network that is in \(_state.state) state")
}
try stateMutex.withLock { state in
guard case .created(let configuration) = state.networkState else {
throw ContainerizationError(.invalidArgument, message: "cannot start network that is in \(state.networkState.state) state")
}

let networkInfo = try startNetwork(configuration: configuration, log: log)

try startNetwork(configuration: configuration, log: log)
let networkStatus = NetworkStatus(address: networkInfo.subnet.description, gateway: networkInfo.gateway.description)
state.networkState = NetworkState.running(configuration, networkStatus)
state.network = networkInfo.network
}
}

private static func serialize_network_ref(ref: vmnet_network_ref) throws -> XPCMessage {
Expand All @@ -81,7 +92,7 @@ public final class ReservedVmnetNetwork: Network {
return XPCMessage(object: refObject)
}

private func startNetwork(configuration: NetworkConfiguration, log: Logger) throws {
private func startNetwork(configuration: NetworkConfiguration, log: Logger) throws -> NetworkInfo {
log.info(
"starting vmnet network",
metadata: [
Expand Down Expand Up @@ -125,7 +136,6 @@ public final class ReservedVmnetNetwork: Network {
guard let network = vmnet_network_create(vmnetConfiguration, &status), status == .VMNET_SUCCESS else {
throw ContainerizationError(.unsupported, message: "failed to create vmnet network with status \(status)")
}
self.network = network

// retrieve the subnet since the caller may not have provided one
var subnetAddr = in_addr()
Expand All @@ -137,7 +147,7 @@ public final class ReservedVmnetNetwork: Network {
let upper = IPv4Address(fromValue: lower.value + ~maskValue)
let runningSubnet = try CIDRAddress(lower: lower, upper: upper)
let runningGateway = IPv4Address(fromValue: runningSubnet.lower.value + 1)
self._state = .running(configuration, NetworkStatus(address: runningSubnet.description, gateway: runningGateway.description))

log.info(
"started vmnet network",
metadata: [
Expand All @@ -146,5 +156,7 @@ public final class ReservedVmnetNetwork: Network {
"cidr": "\(runningSubnet)",
]
)

return NetworkInfo(network: network, subnet: runningSubnet, gateway: runningGateway)
}
}
4 changes: 2 additions & 2 deletions Sources/SocketForwarder/UDPForwarder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ private final class UDPProxyBackend: ChannelInboundHandler, Sendable {
self.serverAddress = serverAddress
self.frontendChannel = frontendChannel
self.log = log
let state = State(queuedPayloads: Deque(), channel: nil)
self.state = Mutex(state)
let initialState = State(queuedPayloads: Deque(), channel: nil)
self.state = Mutex(initialState)
}

func channelRead(context: ChannelHandlerContext, data: NIOAny) {
Expand Down
6 changes: 4 additions & 2 deletions Sources/TerminalProgress/ProgressBar+Terminal.swift
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,10 @@ extension ProgressBar {
var text = text

// Clears previously printed characters if the new string is shorter.
text += String(repeating: " ", count: max(printedWidth - text.count, 0))
printedWidth = text.count
printedWidth.withLock {
text += String(repeating: " ", count: max($0 - text.count, 0))
$0 = text.count
}
state.withLock {
$0.output = text
}
Expand Down
4 changes: 1 addition & 3 deletions Sources/TerminalProgress/ProgressBar.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,13 @@
//===----------------------------------------------------------------------===//

import Foundation
import SendableProperty
import Synchronization

/// A progress bar that updates itself as tasks are completed.
public final class ProgressBar: Sendable {
let config: ProgressConfig
let state: Mutex<State>
@SendableProperty
var printedWidth = 0
let printedWidth = Mutex(0)
let term: FileHandle?
let termQueue = DispatchQueue(label: "com.apple.container.ProgressBar")
private let standardError = StandardError()
Expand Down