Compare commits
2 commits
72b7f1467b
...
1da00ecdf3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1da00ecdf3 | ||
|
|
baf1408060 |
11 changed files with 1783 additions and 80 deletions
|
|
@ -42,8 +42,8 @@
|
|||
D0D4E5A62C8D9E65007F820A /* BurrowCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0D4E5312C8D996F007F820A /* BurrowCore.framework */; };
|
||||
D0F4FAD32C8DC79C0068730A /* BurrowCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0D4E5312C8D996F007F820A /* BurrowCore.framework */; };
|
||||
D0F7594E2C8DAB6B00126CF3 /* GRPC in Frameworks */ = {isa = PBXBuildFile; productRef = D078F7E02C8DA375008A8CEC /* GRPC */; };
|
||||
D0F759612C8DB24B00126CF3 /* grpc-swift-config.json in Sources */ = {isa = PBXBuildFile; fileRef = D0D4E4962C8D921A007F820A /* grpc-swift-config.json */; };
|
||||
D0F759622C8DB24B00126CF3 /* swift-protobuf-config.json in Sources */ = {isa = PBXBuildFile; fileRef = D0D4E4972C8D921A007F820A /* swift-protobuf-config.json */; };
|
||||
D0FA10012D10200100112233 /* burrow.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0FA10032D10200100112233 /* burrow.pb.swift */; };
|
||||
D0FA10022D10200100112233 /* burrow.grpc.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0FA10042D10200100112233 /* burrow.grpc.swift */; };
|
||||
D0F7597E2C8DB30500126CF3 /* CGRPCZlib in Frameworks */ = {isa = PBXBuildFile; productRef = D0F7597D2C8DB30500126CF3 /* CGRPCZlib */; };
|
||||
D0F7598D2C8DB3DA00126CF3 /* Client.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0D4E4992C8D921A007F820A /* Client.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
|
@ -154,8 +154,6 @@
|
|||
D0BCC6032A09535900AD070D /* libburrow.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libburrow.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D0BF09582C8E6789000D8DEC /* UI.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = UI.xcconfig; sourceTree = "<group>"; };
|
||||
D0D4E4952C8D921A007F820A /* burrow.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = burrow.proto; sourceTree = "<group>"; };
|
||||
D0D4E4962C8D921A007F820A /* grpc-swift-config.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "grpc-swift-config.json"; sourceTree = "<group>"; };
|
||||
D0D4E4972C8D921A007F820A /* swift-protobuf-config.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "swift-protobuf-config.json"; sourceTree = "<group>"; };
|
||||
D0D4E4992C8D921A007F820A /* Client.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Client.swift; sourceTree = "<group>"; };
|
||||
D0D4E49A2C8D921A007F820A /* Logging.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Logging.swift; sourceTree = "<group>"; };
|
||||
D0D4E49E2C8D921A007F820A /* Network.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Network.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -179,6 +177,8 @@
|
|||
D0D4E58E2C8D9D0A007F820A /* Constants.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Constants.h; sourceTree = "<group>"; };
|
||||
D0D4E58F2C8D9D0A007F820A /* Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = "<group>"; };
|
||||
D0D4E5902C8D9D0A007F820A /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = "<group>"; };
|
||||
D0FA10032D10200100112233 /* burrow.pb.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Generated/burrow.pb.swift; sourceTree = "<group>"; };
|
||||
D0FA10042D10200100112233 /* burrow.grpc.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Generated/burrow.grpc.swift; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
|
|
@ -317,8 +317,8 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
D0D4E4952C8D921A007F820A /* burrow.proto */,
|
||||
D0D4E4962C8D921A007F820A /* grpc-swift-config.json */,
|
||||
D0D4E4972C8D921A007F820A /* swift-protobuf-config.json */,
|
||||
D0FA10032D10200100112233 /* burrow.pb.swift */,
|
||||
D0FA10042D10200100112233 /* burrow.grpc.swift */,
|
||||
);
|
||||
path = Client;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -428,8 +428,6 @@
|
|||
);
|
||||
dependencies = (
|
||||
D0F7598A2C8DB34200126CF3 /* PBXTargetDependency */,
|
||||
D0F7595E2C8DB24400126CF3 /* PBXTargetDependency */,
|
||||
D0F759602C8DB24400126CF3 /* PBXTargetDependency */,
|
||||
);
|
||||
name = Core;
|
||||
packageProductDependencies = (
|
||||
|
|
@ -617,8 +615,8 @@
|
|||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D0F759612C8DB24B00126CF3 /* grpc-swift-config.json in Sources */,
|
||||
D0F759622C8DB24B00126CF3 /* swift-protobuf-config.json in Sources */,
|
||||
D0FA10012D10200100112233 /* burrow.pb.swift in Sources */,
|
||||
D0FA10022D10200100112233 /* burrow.grpc.swift in Sources */,
|
||||
D0F7598D2C8DB3DA00126CF3 /* Client.swift in Sources */,
|
||||
D0D4E56B2C8D9C2F007F820A /* Logging.swift in Sources */,
|
||||
);
|
||||
|
|
@ -689,14 +687,6 @@
|
|||
target = D0D4E5302C8D996F007F820A /* Core */;
|
||||
targetProxy = D0F4FAD12C8DC7960068730A /* PBXContainerItemProxy */;
|
||||
};
|
||||
D0F7595E2C8DB24400126CF3 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
productRef = D0F7595D2C8DB24400126CF3 /* GRPCSwiftPlugin */;
|
||||
};
|
||||
D0F759602C8DB24400126CF3 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
productRef = D0F7595F2C8DB24400126CF3 /* SwiftProtobufPlugin */;
|
||||
};
|
||||
D0F7598A2C8DB34200126CF3 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
productRef = D0F759892C8DB34200126CF3 /* GRPC */;
|
||||
|
|
@ -921,16 +911,6 @@
|
|||
package = D0B1D10E2C436152004B7823 /* XCRemoteSwiftPackageReference "swift-async-algorithms" */;
|
||||
productName = AsyncAlgorithms;
|
||||
};
|
||||
D0F7595D2C8DB24400126CF3 /* GRPCSwiftPlugin */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = D0D4E4822C8D8EF6007F820A /* XCRemoteSwiftPackageReference "grpc-swift" */;
|
||||
productName = "plugin:GRPCSwiftPlugin";
|
||||
};
|
||||
D0F7595F2C8DB24400126CF3 /* SwiftProtobufPlugin */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = D0D4E4852C8D8F29007F820A /* XCRemoteSwiftPackageReference "swift-protobuf" */;
|
||||
productName = "plugin:SwiftProtobufPlugin";
|
||||
};
|
||||
D0F7597D2C8DB30500126CF3 /* CGRPCZlib */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = D0D4E4822C8D8EF6007F820A /* XCRemoteSwiftPackageReference "grpc-swift" */;
|
||||
|
|
|
|||
761
Apple/Core/Client/Generated/burrow.grpc.swift
Normal file
761
Apple/Core/Client/Generated/burrow.grpc.swift
Normal file
|
|
@ -0,0 +1,761 @@
|
|||
//
|
||||
// DO NOT EDIT.
|
||||
// swift-format-ignore-file
|
||||
//
|
||||
// Generated by the protocol buffer compiler.
|
||||
// Source: burrow.proto
|
||||
//
|
||||
import GRPC
|
||||
import NIO
|
||||
import NIOConcurrencyHelpers
|
||||
import SwiftProtobuf
|
||||
|
||||
|
||||
/// Usage: instantiate `Burrow_TunnelClient`, then call methods of this protocol to make API calls.
|
||||
public protocol Burrow_TunnelClientProtocol: GRPCClient {
|
||||
var serviceName: String { get }
|
||||
var interceptors: Burrow_TunnelClientInterceptorFactoryProtocol? { get }
|
||||
|
||||
func tunnelConfiguration(
|
||||
_ request: Burrow_Empty,
|
||||
callOptions: CallOptions?,
|
||||
handler: @escaping (Burrow_TunnelConfigurationResponse) -> Void
|
||||
) -> ServerStreamingCall<Burrow_Empty, Burrow_TunnelConfigurationResponse>
|
||||
|
||||
func tunnelStart(
|
||||
_ request: Burrow_Empty,
|
||||
callOptions: CallOptions?
|
||||
) -> UnaryCall<Burrow_Empty, Burrow_Empty>
|
||||
|
||||
func tunnelStop(
|
||||
_ request: Burrow_Empty,
|
||||
callOptions: CallOptions?
|
||||
) -> UnaryCall<Burrow_Empty, Burrow_Empty>
|
||||
|
||||
func tunnelStatus(
|
||||
_ request: Burrow_Empty,
|
||||
callOptions: CallOptions?,
|
||||
handler: @escaping (Burrow_TunnelStatusResponse) -> Void
|
||||
) -> ServerStreamingCall<Burrow_Empty, Burrow_TunnelStatusResponse>
|
||||
}
|
||||
|
||||
extension Burrow_TunnelClientProtocol {
|
||||
public var serviceName: String {
|
||||
return "burrow.Tunnel"
|
||||
}
|
||||
|
||||
/// Server streaming call to TunnelConfiguration
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - request: Request to send to TunnelConfiguration.
|
||||
/// - callOptions: Call options.
|
||||
/// - handler: A closure called when each response is received from the server.
|
||||
/// - Returns: A `ServerStreamingCall` with futures for the metadata and status.
|
||||
public func tunnelConfiguration(
|
||||
_ request: Burrow_Empty,
|
||||
callOptions: CallOptions? = nil,
|
||||
handler: @escaping (Burrow_TunnelConfigurationResponse) -> Void
|
||||
) -> ServerStreamingCall<Burrow_Empty, Burrow_TunnelConfigurationResponse> {
|
||||
return self.makeServerStreamingCall(
|
||||
path: Burrow_TunnelClientMetadata.Methods.tunnelConfiguration.path,
|
||||
request: request,
|
||||
callOptions: callOptions ?? self.defaultCallOptions,
|
||||
interceptors: self.interceptors?.makeTunnelConfigurationInterceptors() ?? [],
|
||||
handler: handler
|
||||
)
|
||||
}
|
||||
|
||||
/// Unary call to TunnelStart
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - request: Request to send to TunnelStart.
|
||||
/// - callOptions: Call options.
|
||||
/// - Returns: A `UnaryCall` with futures for the metadata, status and response.
|
||||
public func tunnelStart(
|
||||
_ request: Burrow_Empty,
|
||||
callOptions: CallOptions? = nil
|
||||
) -> UnaryCall<Burrow_Empty, Burrow_Empty> {
|
||||
return self.makeUnaryCall(
|
||||
path: Burrow_TunnelClientMetadata.Methods.tunnelStart.path,
|
||||
request: request,
|
||||
callOptions: callOptions ?? self.defaultCallOptions,
|
||||
interceptors: self.interceptors?.makeTunnelStartInterceptors() ?? []
|
||||
)
|
||||
}
|
||||
|
||||
/// Unary call to TunnelStop
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - request: Request to send to TunnelStop.
|
||||
/// - callOptions: Call options.
|
||||
/// - Returns: A `UnaryCall` with futures for the metadata, status and response.
|
||||
public func tunnelStop(
|
||||
_ request: Burrow_Empty,
|
||||
callOptions: CallOptions? = nil
|
||||
) -> UnaryCall<Burrow_Empty, Burrow_Empty> {
|
||||
return self.makeUnaryCall(
|
||||
path: Burrow_TunnelClientMetadata.Methods.tunnelStop.path,
|
||||
request: request,
|
||||
callOptions: callOptions ?? self.defaultCallOptions,
|
||||
interceptors: self.interceptors?.makeTunnelStopInterceptors() ?? []
|
||||
)
|
||||
}
|
||||
|
||||
/// Server streaming call to TunnelStatus
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - request: Request to send to TunnelStatus.
|
||||
/// - callOptions: Call options.
|
||||
/// - handler: A closure called when each response is received from the server.
|
||||
/// - Returns: A `ServerStreamingCall` with futures for the metadata and status.
|
||||
public func tunnelStatus(
|
||||
_ request: Burrow_Empty,
|
||||
callOptions: CallOptions? = nil,
|
||||
handler: @escaping (Burrow_TunnelStatusResponse) -> Void
|
||||
) -> ServerStreamingCall<Burrow_Empty, Burrow_TunnelStatusResponse> {
|
||||
return self.makeServerStreamingCall(
|
||||
path: Burrow_TunnelClientMetadata.Methods.tunnelStatus.path,
|
||||
request: request,
|
||||
callOptions: callOptions ?? self.defaultCallOptions,
|
||||
interceptors: self.interceptors?.makeTunnelStatusInterceptors() ?? [],
|
||||
handler: handler
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@available(*, deprecated)
|
||||
extension Burrow_TunnelClient: @unchecked Sendable {}
|
||||
|
||||
@available(*, deprecated, renamed: "Burrow_TunnelNIOClient")
|
||||
public final class Burrow_TunnelClient: Burrow_TunnelClientProtocol {
|
||||
private let lock = Lock()
|
||||
private var _defaultCallOptions: CallOptions
|
||||
private var _interceptors: Burrow_TunnelClientInterceptorFactoryProtocol?
|
||||
public let channel: GRPCChannel
|
||||
public var defaultCallOptions: CallOptions {
|
||||
get { self.lock.withLock { return self._defaultCallOptions } }
|
||||
set { self.lock.withLockVoid { self._defaultCallOptions = newValue } }
|
||||
}
|
||||
public var interceptors: Burrow_TunnelClientInterceptorFactoryProtocol? {
|
||||
get { self.lock.withLock { return self._interceptors } }
|
||||
set { self.lock.withLockVoid { self._interceptors = newValue } }
|
||||
}
|
||||
|
||||
/// Creates a client for the burrow.Tunnel service.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - channel: `GRPCChannel` to the service host.
|
||||
/// - defaultCallOptions: Options to use for each service call if the user doesn't provide them.
|
||||
/// - interceptors: A factory providing interceptors for each RPC.
|
||||
public init(
|
||||
channel: GRPCChannel,
|
||||
defaultCallOptions: CallOptions = CallOptions(),
|
||||
interceptors: Burrow_TunnelClientInterceptorFactoryProtocol? = nil
|
||||
) {
|
||||
self.channel = channel
|
||||
self._defaultCallOptions = defaultCallOptions
|
||||
self._interceptors = interceptors
|
||||
}
|
||||
}
|
||||
|
||||
public struct Burrow_TunnelNIOClient: Burrow_TunnelClientProtocol {
|
||||
public var channel: GRPCChannel
|
||||
public var defaultCallOptions: CallOptions
|
||||
public var interceptors: Burrow_TunnelClientInterceptorFactoryProtocol?
|
||||
|
||||
/// Creates a client for the burrow.Tunnel service.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - channel: `GRPCChannel` to the service host.
|
||||
/// - defaultCallOptions: Options to use for each service call if the user doesn't provide them.
|
||||
/// - interceptors: A factory providing interceptors for each RPC.
|
||||
public init(
|
||||
channel: GRPCChannel,
|
||||
defaultCallOptions: CallOptions = CallOptions(),
|
||||
interceptors: Burrow_TunnelClientInterceptorFactoryProtocol? = nil
|
||||
) {
|
||||
self.channel = channel
|
||||
self.defaultCallOptions = defaultCallOptions
|
||||
self.interceptors = interceptors
|
||||
}
|
||||
}
|
||||
|
||||
@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
|
||||
public protocol Burrow_TunnelAsyncClientProtocol: GRPCClient {
|
||||
static var serviceDescriptor: GRPCServiceDescriptor { get }
|
||||
var interceptors: Burrow_TunnelClientInterceptorFactoryProtocol? { get }
|
||||
|
||||
func makeTunnelConfigurationCall(
|
||||
_ request: Burrow_Empty,
|
||||
callOptions: CallOptions?
|
||||
) -> GRPCAsyncServerStreamingCall<Burrow_Empty, Burrow_TunnelConfigurationResponse>
|
||||
|
||||
func makeTunnelStartCall(
|
||||
_ request: Burrow_Empty,
|
||||
callOptions: CallOptions?
|
||||
) -> GRPCAsyncUnaryCall<Burrow_Empty, Burrow_Empty>
|
||||
|
||||
func makeTunnelStopCall(
|
||||
_ request: Burrow_Empty,
|
||||
callOptions: CallOptions?
|
||||
) -> GRPCAsyncUnaryCall<Burrow_Empty, Burrow_Empty>
|
||||
|
||||
func makeTunnelStatusCall(
|
||||
_ request: Burrow_Empty,
|
||||
callOptions: CallOptions?
|
||||
) -> GRPCAsyncServerStreamingCall<Burrow_Empty, Burrow_TunnelStatusResponse>
|
||||
}
|
||||
|
||||
@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
|
||||
extension Burrow_TunnelAsyncClientProtocol {
|
||||
public static var serviceDescriptor: GRPCServiceDescriptor {
|
||||
return Burrow_TunnelClientMetadata.serviceDescriptor
|
||||
}
|
||||
|
||||
public var interceptors: Burrow_TunnelClientInterceptorFactoryProtocol? {
|
||||
return nil
|
||||
}
|
||||
|
||||
public func makeTunnelConfigurationCall(
|
||||
_ request: Burrow_Empty,
|
||||
callOptions: CallOptions? = nil
|
||||
) -> GRPCAsyncServerStreamingCall<Burrow_Empty, Burrow_TunnelConfigurationResponse> {
|
||||
return self.makeAsyncServerStreamingCall(
|
||||
path: Burrow_TunnelClientMetadata.Methods.tunnelConfiguration.path,
|
||||
request: request,
|
||||
callOptions: callOptions ?? self.defaultCallOptions,
|
||||
interceptors: self.interceptors?.makeTunnelConfigurationInterceptors() ?? []
|
||||
)
|
||||
}
|
||||
|
||||
public func makeTunnelStartCall(
|
||||
_ request: Burrow_Empty,
|
||||
callOptions: CallOptions? = nil
|
||||
) -> GRPCAsyncUnaryCall<Burrow_Empty, Burrow_Empty> {
|
||||
return self.makeAsyncUnaryCall(
|
||||
path: Burrow_TunnelClientMetadata.Methods.tunnelStart.path,
|
||||
request: request,
|
||||
callOptions: callOptions ?? self.defaultCallOptions,
|
||||
interceptors: self.interceptors?.makeTunnelStartInterceptors() ?? []
|
||||
)
|
||||
}
|
||||
|
||||
public func makeTunnelStopCall(
|
||||
_ request: Burrow_Empty,
|
||||
callOptions: CallOptions? = nil
|
||||
) -> GRPCAsyncUnaryCall<Burrow_Empty, Burrow_Empty> {
|
||||
return self.makeAsyncUnaryCall(
|
||||
path: Burrow_TunnelClientMetadata.Methods.tunnelStop.path,
|
||||
request: request,
|
||||
callOptions: callOptions ?? self.defaultCallOptions,
|
||||
interceptors: self.interceptors?.makeTunnelStopInterceptors() ?? []
|
||||
)
|
||||
}
|
||||
|
||||
public func makeTunnelStatusCall(
|
||||
_ request: Burrow_Empty,
|
||||
callOptions: CallOptions? = nil
|
||||
) -> GRPCAsyncServerStreamingCall<Burrow_Empty, Burrow_TunnelStatusResponse> {
|
||||
return self.makeAsyncServerStreamingCall(
|
||||
path: Burrow_TunnelClientMetadata.Methods.tunnelStatus.path,
|
||||
request: request,
|
||||
callOptions: callOptions ?? self.defaultCallOptions,
|
||||
interceptors: self.interceptors?.makeTunnelStatusInterceptors() ?? []
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
|
||||
extension Burrow_TunnelAsyncClientProtocol {
|
||||
public func tunnelConfiguration(
|
||||
_ request: Burrow_Empty,
|
||||
callOptions: CallOptions? = nil
|
||||
) -> GRPCAsyncResponseStream<Burrow_TunnelConfigurationResponse> {
|
||||
return self.performAsyncServerStreamingCall(
|
||||
path: Burrow_TunnelClientMetadata.Methods.tunnelConfiguration.path,
|
||||
request: request,
|
||||
callOptions: callOptions ?? self.defaultCallOptions,
|
||||
interceptors: self.interceptors?.makeTunnelConfigurationInterceptors() ?? []
|
||||
)
|
||||
}
|
||||
|
||||
public func tunnelStart(
|
||||
_ request: Burrow_Empty,
|
||||
callOptions: CallOptions? = nil
|
||||
) async throws -> Burrow_Empty {
|
||||
return try await self.performAsyncUnaryCall(
|
||||
path: Burrow_TunnelClientMetadata.Methods.tunnelStart.path,
|
||||
request: request,
|
||||
callOptions: callOptions ?? self.defaultCallOptions,
|
||||
interceptors: self.interceptors?.makeTunnelStartInterceptors() ?? []
|
||||
)
|
||||
}
|
||||
|
||||
public func tunnelStop(
|
||||
_ request: Burrow_Empty,
|
||||
callOptions: CallOptions? = nil
|
||||
) async throws -> Burrow_Empty {
|
||||
return try await self.performAsyncUnaryCall(
|
||||
path: Burrow_TunnelClientMetadata.Methods.tunnelStop.path,
|
||||
request: request,
|
||||
callOptions: callOptions ?? self.defaultCallOptions,
|
||||
interceptors: self.interceptors?.makeTunnelStopInterceptors() ?? []
|
||||
)
|
||||
}
|
||||
|
||||
public func tunnelStatus(
|
||||
_ request: Burrow_Empty,
|
||||
callOptions: CallOptions? = nil
|
||||
) -> GRPCAsyncResponseStream<Burrow_TunnelStatusResponse> {
|
||||
return self.performAsyncServerStreamingCall(
|
||||
path: Burrow_TunnelClientMetadata.Methods.tunnelStatus.path,
|
||||
request: request,
|
||||
callOptions: callOptions ?? self.defaultCallOptions,
|
||||
interceptors: self.interceptors?.makeTunnelStatusInterceptors() ?? []
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
|
||||
public struct Burrow_TunnelAsyncClient: Burrow_TunnelAsyncClientProtocol {
|
||||
public var channel: GRPCChannel
|
||||
public var defaultCallOptions: CallOptions
|
||||
public var interceptors: Burrow_TunnelClientInterceptorFactoryProtocol?
|
||||
|
||||
public init(
|
||||
channel: GRPCChannel,
|
||||
defaultCallOptions: CallOptions = CallOptions(),
|
||||
interceptors: Burrow_TunnelClientInterceptorFactoryProtocol? = nil
|
||||
) {
|
||||
self.channel = channel
|
||||
self.defaultCallOptions = defaultCallOptions
|
||||
self.interceptors = interceptors
|
||||
}
|
||||
}
|
||||
|
||||
public protocol Burrow_TunnelClientInterceptorFactoryProtocol: Sendable {
|
||||
|
||||
/// - Returns: Interceptors to use when invoking 'tunnelConfiguration'.
|
||||
func makeTunnelConfigurationInterceptors() -> [ClientInterceptor<Burrow_Empty, Burrow_TunnelConfigurationResponse>]
|
||||
|
||||
/// - Returns: Interceptors to use when invoking 'tunnelStart'.
|
||||
func makeTunnelStartInterceptors() -> [ClientInterceptor<Burrow_Empty, Burrow_Empty>]
|
||||
|
||||
/// - Returns: Interceptors to use when invoking 'tunnelStop'.
|
||||
func makeTunnelStopInterceptors() -> [ClientInterceptor<Burrow_Empty, Burrow_Empty>]
|
||||
|
||||
/// - Returns: Interceptors to use when invoking 'tunnelStatus'.
|
||||
func makeTunnelStatusInterceptors() -> [ClientInterceptor<Burrow_Empty, Burrow_TunnelStatusResponse>]
|
||||
}
|
||||
|
||||
public enum Burrow_TunnelClientMetadata {
|
||||
public static let serviceDescriptor = GRPCServiceDescriptor(
|
||||
name: "Tunnel",
|
||||
fullName: "burrow.Tunnel",
|
||||
methods: [
|
||||
Burrow_TunnelClientMetadata.Methods.tunnelConfiguration,
|
||||
Burrow_TunnelClientMetadata.Methods.tunnelStart,
|
||||
Burrow_TunnelClientMetadata.Methods.tunnelStop,
|
||||
Burrow_TunnelClientMetadata.Methods.tunnelStatus,
|
||||
]
|
||||
)
|
||||
|
||||
public enum Methods {
|
||||
public static let tunnelConfiguration = GRPCMethodDescriptor(
|
||||
name: "TunnelConfiguration",
|
||||
path: "/burrow.Tunnel/TunnelConfiguration",
|
||||
type: GRPCCallType.serverStreaming
|
||||
)
|
||||
|
||||
public static let tunnelStart = GRPCMethodDescriptor(
|
||||
name: "TunnelStart",
|
||||
path: "/burrow.Tunnel/TunnelStart",
|
||||
type: GRPCCallType.unary
|
||||
)
|
||||
|
||||
public static let tunnelStop = GRPCMethodDescriptor(
|
||||
name: "TunnelStop",
|
||||
path: "/burrow.Tunnel/TunnelStop",
|
||||
type: GRPCCallType.unary
|
||||
)
|
||||
|
||||
public static let tunnelStatus = GRPCMethodDescriptor(
|
||||
name: "TunnelStatus",
|
||||
path: "/burrow.Tunnel/TunnelStatus",
|
||||
type: GRPCCallType.serverStreaming
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Usage: instantiate `Burrow_NetworksClient`, then call methods of this protocol to make API calls.
|
||||
public protocol Burrow_NetworksClientProtocol: GRPCClient {
|
||||
var serviceName: String { get }
|
||||
var interceptors: Burrow_NetworksClientInterceptorFactoryProtocol? { get }
|
||||
|
||||
func networkAdd(
|
||||
_ request: Burrow_Network,
|
||||
callOptions: CallOptions?
|
||||
) -> UnaryCall<Burrow_Network, Burrow_Empty>
|
||||
|
||||
func networkList(
|
||||
_ request: Burrow_Empty,
|
||||
callOptions: CallOptions?,
|
||||
handler: @escaping (Burrow_NetworkListResponse) -> Void
|
||||
) -> ServerStreamingCall<Burrow_Empty, Burrow_NetworkListResponse>
|
||||
|
||||
func networkReorder(
|
||||
_ request: Burrow_NetworkReorderRequest,
|
||||
callOptions: CallOptions?
|
||||
) -> UnaryCall<Burrow_NetworkReorderRequest, Burrow_Empty>
|
||||
|
||||
func networkDelete(
|
||||
_ request: Burrow_NetworkDeleteRequest,
|
||||
callOptions: CallOptions?
|
||||
) -> UnaryCall<Burrow_NetworkDeleteRequest, Burrow_Empty>
|
||||
}
|
||||
|
||||
extension Burrow_NetworksClientProtocol {
|
||||
public var serviceName: String {
|
||||
return "burrow.Networks"
|
||||
}
|
||||
|
||||
/// Unary call to NetworkAdd
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - request: Request to send to NetworkAdd.
|
||||
/// - callOptions: Call options.
|
||||
/// - Returns: A `UnaryCall` with futures for the metadata, status and response.
|
||||
public func networkAdd(
|
||||
_ request: Burrow_Network,
|
||||
callOptions: CallOptions? = nil
|
||||
) -> UnaryCall<Burrow_Network, Burrow_Empty> {
|
||||
return self.makeUnaryCall(
|
||||
path: Burrow_NetworksClientMetadata.Methods.networkAdd.path,
|
||||
request: request,
|
||||
callOptions: callOptions ?? self.defaultCallOptions,
|
||||
interceptors: self.interceptors?.makeNetworkAddInterceptors() ?? []
|
||||
)
|
||||
}
|
||||
|
||||
/// Server streaming call to NetworkList
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - request: Request to send to NetworkList.
|
||||
/// - callOptions: Call options.
|
||||
/// - handler: A closure called when each response is received from the server.
|
||||
/// - Returns: A `ServerStreamingCall` with futures for the metadata and status.
|
||||
public func networkList(
|
||||
_ request: Burrow_Empty,
|
||||
callOptions: CallOptions? = nil,
|
||||
handler: @escaping (Burrow_NetworkListResponse) -> Void
|
||||
) -> ServerStreamingCall<Burrow_Empty, Burrow_NetworkListResponse> {
|
||||
return self.makeServerStreamingCall(
|
||||
path: Burrow_NetworksClientMetadata.Methods.networkList.path,
|
||||
request: request,
|
||||
callOptions: callOptions ?? self.defaultCallOptions,
|
||||
interceptors: self.interceptors?.makeNetworkListInterceptors() ?? [],
|
||||
handler: handler
|
||||
)
|
||||
}
|
||||
|
||||
/// Unary call to NetworkReorder
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - request: Request to send to NetworkReorder.
|
||||
/// - callOptions: Call options.
|
||||
/// - Returns: A `UnaryCall` with futures for the metadata, status and response.
|
||||
public func networkReorder(
|
||||
_ request: Burrow_NetworkReorderRequest,
|
||||
callOptions: CallOptions? = nil
|
||||
) -> UnaryCall<Burrow_NetworkReorderRequest, Burrow_Empty> {
|
||||
return self.makeUnaryCall(
|
||||
path: Burrow_NetworksClientMetadata.Methods.networkReorder.path,
|
||||
request: request,
|
||||
callOptions: callOptions ?? self.defaultCallOptions,
|
||||
interceptors: self.interceptors?.makeNetworkReorderInterceptors() ?? []
|
||||
)
|
||||
}
|
||||
|
||||
/// Unary call to NetworkDelete
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - request: Request to send to NetworkDelete.
|
||||
/// - callOptions: Call options.
|
||||
/// - Returns: A `UnaryCall` with futures for the metadata, status and response.
|
||||
public func networkDelete(
|
||||
_ request: Burrow_NetworkDeleteRequest,
|
||||
callOptions: CallOptions? = nil
|
||||
) -> UnaryCall<Burrow_NetworkDeleteRequest, Burrow_Empty> {
|
||||
return self.makeUnaryCall(
|
||||
path: Burrow_NetworksClientMetadata.Methods.networkDelete.path,
|
||||
request: request,
|
||||
callOptions: callOptions ?? self.defaultCallOptions,
|
||||
interceptors: self.interceptors?.makeNetworkDeleteInterceptors() ?? []
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@available(*, deprecated)
|
||||
extension Burrow_NetworksClient: @unchecked Sendable {}
|
||||
|
||||
@available(*, deprecated, renamed: "Burrow_NetworksNIOClient")
|
||||
public final class Burrow_NetworksClient: Burrow_NetworksClientProtocol {
|
||||
private let lock = Lock()
|
||||
private var _defaultCallOptions: CallOptions
|
||||
private var _interceptors: Burrow_NetworksClientInterceptorFactoryProtocol?
|
||||
public let channel: GRPCChannel
|
||||
public var defaultCallOptions: CallOptions {
|
||||
get { self.lock.withLock { return self._defaultCallOptions } }
|
||||
set { self.lock.withLockVoid { self._defaultCallOptions = newValue } }
|
||||
}
|
||||
public var interceptors: Burrow_NetworksClientInterceptorFactoryProtocol? {
|
||||
get { self.lock.withLock { return self._interceptors } }
|
||||
set { self.lock.withLockVoid { self._interceptors = newValue } }
|
||||
}
|
||||
|
||||
/// Creates a client for the burrow.Networks service.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - channel: `GRPCChannel` to the service host.
|
||||
/// - defaultCallOptions: Options to use for each service call if the user doesn't provide them.
|
||||
/// - interceptors: A factory providing interceptors for each RPC.
|
||||
public init(
|
||||
channel: GRPCChannel,
|
||||
defaultCallOptions: CallOptions = CallOptions(),
|
||||
interceptors: Burrow_NetworksClientInterceptorFactoryProtocol? = nil
|
||||
) {
|
||||
self.channel = channel
|
||||
self._defaultCallOptions = defaultCallOptions
|
||||
self._interceptors = interceptors
|
||||
}
|
||||
}
|
||||
|
||||
public struct Burrow_NetworksNIOClient: Burrow_NetworksClientProtocol {
|
||||
public var channel: GRPCChannel
|
||||
public var defaultCallOptions: CallOptions
|
||||
public var interceptors: Burrow_NetworksClientInterceptorFactoryProtocol?
|
||||
|
||||
/// Creates a client for the burrow.Networks service.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - channel: `GRPCChannel` to the service host.
|
||||
/// - defaultCallOptions: Options to use for each service call if the user doesn't provide them.
|
||||
/// - interceptors: A factory providing interceptors for each RPC.
|
||||
public init(
|
||||
channel: GRPCChannel,
|
||||
defaultCallOptions: CallOptions = CallOptions(),
|
||||
interceptors: Burrow_NetworksClientInterceptorFactoryProtocol? = nil
|
||||
) {
|
||||
self.channel = channel
|
||||
self.defaultCallOptions = defaultCallOptions
|
||||
self.interceptors = interceptors
|
||||
}
|
||||
}
|
||||
|
||||
@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
|
||||
public protocol Burrow_NetworksAsyncClientProtocol: GRPCClient {
|
||||
static var serviceDescriptor: GRPCServiceDescriptor { get }
|
||||
var interceptors: Burrow_NetworksClientInterceptorFactoryProtocol? { get }
|
||||
|
||||
func makeNetworkAddCall(
|
||||
_ request: Burrow_Network,
|
||||
callOptions: CallOptions?
|
||||
) -> GRPCAsyncUnaryCall<Burrow_Network, Burrow_Empty>
|
||||
|
||||
func makeNetworkListCall(
|
||||
_ request: Burrow_Empty,
|
||||
callOptions: CallOptions?
|
||||
) -> GRPCAsyncServerStreamingCall<Burrow_Empty, Burrow_NetworkListResponse>
|
||||
|
||||
func makeNetworkReorderCall(
|
||||
_ request: Burrow_NetworkReorderRequest,
|
||||
callOptions: CallOptions?
|
||||
) -> GRPCAsyncUnaryCall<Burrow_NetworkReorderRequest, Burrow_Empty>
|
||||
|
||||
func makeNetworkDeleteCall(
|
||||
_ request: Burrow_NetworkDeleteRequest,
|
||||
callOptions: CallOptions?
|
||||
) -> GRPCAsyncUnaryCall<Burrow_NetworkDeleteRequest, Burrow_Empty>
|
||||
}
|
||||
|
||||
@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
|
||||
extension Burrow_NetworksAsyncClientProtocol {
|
||||
public static var serviceDescriptor: GRPCServiceDescriptor {
|
||||
return Burrow_NetworksClientMetadata.serviceDescriptor
|
||||
}
|
||||
|
||||
public var interceptors: Burrow_NetworksClientInterceptorFactoryProtocol? {
|
||||
return nil
|
||||
}
|
||||
|
||||
public func makeNetworkAddCall(
|
||||
_ request: Burrow_Network,
|
||||
callOptions: CallOptions? = nil
|
||||
) -> GRPCAsyncUnaryCall<Burrow_Network, Burrow_Empty> {
|
||||
return self.makeAsyncUnaryCall(
|
||||
path: Burrow_NetworksClientMetadata.Methods.networkAdd.path,
|
||||
request: request,
|
||||
callOptions: callOptions ?? self.defaultCallOptions,
|
||||
interceptors: self.interceptors?.makeNetworkAddInterceptors() ?? []
|
||||
)
|
||||
}
|
||||
|
||||
public func makeNetworkListCall(
|
||||
_ request: Burrow_Empty,
|
||||
callOptions: CallOptions? = nil
|
||||
) -> GRPCAsyncServerStreamingCall<Burrow_Empty, Burrow_NetworkListResponse> {
|
||||
return self.makeAsyncServerStreamingCall(
|
||||
path: Burrow_NetworksClientMetadata.Methods.networkList.path,
|
||||
request: request,
|
||||
callOptions: callOptions ?? self.defaultCallOptions,
|
||||
interceptors: self.interceptors?.makeNetworkListInterceptors() ?? []
|
||||
)
|
||||
}
|
||||
|
||||
public func makeNetworkReorderCall(
|
||||
_ request: Burrow_NetworkReorderRequest,
|
||||
callOptions: CallOptions? = nil
|
||||
) -> GRPCAsyncUnaryCall<Burrow_NetworkReorderRequest, Burrow_Empty> {
|
||||
return self.makeAsyncUnaryCall(
|
||||
path: Burrow_NetworksClientMetadata.Methods.networkReorder.path,
|
||||
request: request,
|
||||
callOptions: callOptions ?? self.defaultCallOptions,
|
||||
interceptors: self.interceptors?.makeNetworkReorderInterceptors() ?? []
|
||||
)
|
||||
}
|
||||
|
||||
public func makeNetworkDeleteCall(
|
||||
_ request: Burrow_NetworkDeleteRequest,
|
||||
callOptions: CallOptions? = nil
|
||||
) -> GRPCAsyncUnaryCall<Burrow_NetworkDeleteRequest, Burrow_Empty> {
|
||||
return self.makeAsyncUnaryCall(
|
||||
path: Burrow_NetworksClientMetadata.Methods.networkDelete.path,
|
||||
request: request,
|
||||
callOptions: callOptions ?? self.defaultCallOptions,
|
||||
interceptors: self.interceptors?.makeNetworkDeleteInterceptors() ?? []
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
|
||||
extension Burrow_NetworksAsyncClientProtocol {
|
||||
public func networkAdd(
|
||||
_ request: Burrow_Network,
|
||||
callOptions: CallOptions? = nil
|
||||
) async throws -> Burrow_Empty {
|
||||
return try await self.performAsyncUnaryCall(
|
||||
path: Burrow_NetworksClientMetadata.Methods.networkAdd.path,
|
||||
request: request,
|
||||
callOptions: callOptions ?? self.defaultCallOptions,
|
||||
interceptors: self.interceptors?.makeNetworkAddInterceptors() ?? []
|
||||
)
|
||||
}
|
||||
|
||||
public func networkList(
|
||||
_ request: Burrow_Empty,
|
||||
callOptions: CallOptions? = nil
|
||||
) -> GRPCAsyncResponseStream<Burrow_NetworkListResponse> {
|
||||
return self.performAsyncServerStreamingCall(
|
||||
path: Burrow_NetworksClientMetadata.Methods.networkList.path,
|
||||
request: request,
|
||||
callOptions: callOptions ?? self.defaultCallOptions,
|
||||
interceptors: self.interceptors?.makeNetworkListInterceptors() ?? []
|
||||
)
|
||||
}
|
||||
|
||||
public func networkReorder(
|
||||
_ request: Burrow_NetworkReorderRequest,
|
||||
callOptions: CallOptions? = nil
|
||||
) async throws -> Burrow_Empty {
|
||||
return try await self.performAsyncUnaryCall(
|
||||
path: Burrow_NetworksClientMetadata.Methods.networkReorder.path,
|
||||
request: request,
|
||||
callOptions: callOptions ?? self.defaultCallOptions,
|
||||
interceptors: self.interceptors?.makeNetworkReorderInterceptors() ?? []
|
||||
)
|
||||
}
|
||||
|
||||
public func networkDelete(
|
||||
_ request: Burrow_NetworkDeleteRequest,
|
||||
callOptions: CallOptions? = nil
|
||||
) async throws -> Burrow_Empty {
|
||||
return try await self.performAsyncUnaryCall(
|
||||
path: Burrow_NetworksClientMetadata.Methods.networkDelete.path,
|
||||
request: request,
|
||||
callOptions: callOptions ?? self.defaultCallOptions,
|
||||
interceptors: self.interceptors?.makeNetworkDeleteInterceptors() ?? []
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
|
||||
public struct Burrow_NetworksAsyncClient: Burrow_NetworksAsyncClientProtocol {
|
||||
public var channel: GRPCChannel
|
||||
public var defaultCallOptions: CallOptions
|
||||
public var interceptors: Burrow_NetworksClientInterceptorFactoryProtocol?
|
||||
|
||||
public init(
|
||||
channel: GRPCChannel,
|
||||
defaultCallOptions: CallOptions = CallOptions(),
|
||||
interceptors: Burrow_NetworksClientInterceptorFactoryProtocol? = nil
|
||||
) {
|
||||
self.channel = channel
|
||||
self.defaultCallOptions = defaultCallOptions
|
||||
self.interceptors = interceptors
|
||||
}
|
||||
}
|
||||
|
||||
public protocol Burrow_NetworksClientInterceptorFactoryProtocol: Sendable {
|
||||
|
||||
/// - Returns: Interceptors to use when invoking 'networkAdd'.
|
||||
func makeNetworkAddInterceptors() -> [ClientInterceptor<Burrow_Network, Burrow_Empty>]
|
||||
|
||||
/// - Returns: Interceptors to use when invoking 'networkList'.
|
||||
func makeNetworkListInterceptors() -> [ClientInterceptor<Burrow_Empty, Burrow_NetworkListResponse>]
|
||||
|
||||
/// - Returns: Interceptors to use when invoking 'networkReorder'.
|
||||
func makeNetworkReorderInterceptors() -> [ClientInterceptor<Burrow_NetworkReorderRequest, Burrow_Empty>]
|
||||
|
||||
/// - Returns: Interceptors to use when invoking 'networkDelete'.
|
||||
func makeNetworkDeleteInterceptors() -> [ClientInterceptor<Burrow_NetworkDeleteRequest, Burrow_Empty>]
|
||||
}
|
||||
|
||||
public enum Burrow_NetworksClientMetadata {
|
||||
public static let serviceDescriptor = GRPCServiceDescriptor(
|
||||
name: "Networks",
|
||||
fullName: "burrow.Networks",
|
||||
methods: [
|
||||
Burrow_NetworksClientMetadata.Methods.networkAdd,
|
||||
Burrow_NetworksClientMetadata.Methods.networkList,
|
||||
Burrow_NetworksClientMetadata.Methods.networkReorder,
|
||||
Burrow_NetworksClientMetadata.Methods.networkDelete,
|
||||
]
|
||||
)
|
||||
|
||||
public enum Methods {
|
||||
public static let networkAdd = GRPCMethodDescriptor(
|
||||
name: "NetworkAdd",
|
||||
path: "/burrow.Networks/NetworkAdd",
|
||||
type: GRPCCallType.unary
|
||||
)
|
||||
|
||||
public static let networkList = GRPCMethodDescriptor(
|
||||
name: "NetworkList",
|
||||
path: "/burrow.Networks/NetworkList",
|
||||
type: GRPCCallType.serverStreaming
|
||||
)
|
||||
|
||||
public static let networkReorder = GRPCMethodDescriptor(
|
||||
name: "NetworkReorder",
|
||||
path: "/burrow.Networks/NetworkReorder",
|
||||
type: GRPCCallType.unary
|
||||
)
|
||||
|
||||
public static let networkDelete = GRPCMethodDescriptor(
|
||||
name: "NetworkDelete",
|
||||
path: "/burrow.Networks/NetworkDelete",
|
||||
type: GRPCCallType.unary
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
566
Apple/Core/Client/Generated/burrow.pb.swift
Normal file
566
Apple/Core/Client/Generated/burrow.pb.swift
Normal file
|
|
@ -0,0 +1,566 @@
|
|||
// DO NOT EDIT.
|
||||
// swift-format-ignore-file
|
||||
// swiftlint:disable all
|
||||
//
|
||||
// Generated by the Swift generator plugin for the protocol buffer compiler.
|
||||
// Source: burrow.proto
|
||||
//
|
||||
// For information on using the generated types, please see the documentation:
|
||||
// https://github.com/apple/swift-protobuf/
|
||||
|
||||
import Foundation
|
||||
import SwiftProtobuf
|
||||
|
||||
// If the compiler emits an error on this type, it is because this file
|
||||
// was generated by a version of the `protoc` Swift plug-in that is
|
||||
// incompatible with the version of SwiftProtobuf to which you are linking.
|
||||
// Please ensure that you are building against the same version of the API
|
||||
// that was used to generate this file.
|
||||
fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck {
|
||||
struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {}
|
||||
typealias Version = _2
|
||||
}
|
||||
|
||||
public enum Burrow_NetworkType: SwiftProtobuf.Enum, Swift.CaseIterable {
|
||||
public typealias RawValue = Int
|
||||
case wireGuard // = 0
|
||||
case tailnet // = 1
|
||||
case UNRECOGNIZED(Int)
|
||||
|
||||
public init() {
|
||||
self = .wireGuard
|
||||
}
|
||||
|
||||
public init?(rawValue: Int) {
|
||||
switch rawValue {
|
||||
case 0: self = .wireGuard
|
||||
case 1: self = .tailnet
|
||||
default: self = .UNRECOGNIZED(rawValue)
|
||||
}
|
||||
}
|
||||
|
||||
public var rawValue: Int {
|
||||
switch self {
|
||||
case .wireGuard: return 0
|
||||
case .tailnet: return 1
|
||||
case .UNRECOGNIZED(let i): return i
|
||||
}
|
||||
}
|
||||
|
||||
// The compiler won't synthesize support with the UNRECOGNIZED case.
|
||||
public static let allCases: [Burrow_NetworkType] = [
|
||||
.wireGuard,
|
||||
.tailnet,
|
||||
]
|
||||
|
||||
}
|
||||
|
||||
public enum Burrow_State: SwiftProtobuf.Enum, Swift.CaseIterable {
|
||||
public typealias RawValue = Int
|
||||
case stopped // = 0
|
||||
case running // = 1
|
||||
case UNRECOGNIZED(Int)
|
||||
|
||||
public init() {
|
||||
self = .stopped
|
||||
}
|
||||
|
||||
public init?(rawValue: Int) {
|
||||
switch rawValue {
|
||||
case 0: self = .stopped
|
||||
case 1: self = .running
|
||||
default: self = .UNRECOGNIZED(rawValue)
|
||||
}
|
||||
}
|
||||
|
||||
public var rawValue: Int {
|
||||
switch self {
|
||||
case .stopped: return 0
|
||||
case .running: return 1
|
||||
case .UNRECOGNIZED(let i): return i
|
||||
}
|
||||
}
|
||||
|
||||
// The compiler won't synthesize support with the UNRECOGNIZED case.
|
||||
public static let allCases: [Burrow_State] = [
|
||||
.stopped,
|
||||
.running,
|
||||
]
|
||||
|
||||
}
|
||||
|
||||
public struct Burrow_NetworkReorderRequest: Sendable {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
// methods supported on all messages.
|
||||
|
||||
public var id: Int32 = 0
|
||||
|
||||
public var index: Int32 = 0
|
||||
|
||||
public var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
public init() {}
|
||||
}
|
||||
|
||||
public struct Burrow_WireGuardPeer: Sendable {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
// methods supported on all messages.
|
||||
|
||||
public var endpoint: String = String()
|
||||
|
||||
public var subnet: [String] = []
|
||||
|
||||
public var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
public init() {}
|
||||
}
|
||||
|
||||
public struct Burrow_WireGuardNetwork: Sendable {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
// methods supported on all messages.
|
||||
|
||||
public var address: String = String()
|
||||
|
||||
public var dns: String = String()
|
||||
|
||||
public var peer: [Burrow_WireGuardPeer] = []
|
||||
|
||||
public var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
public init() {}
|
||||
}
|
||||
|
||||
public struct Burrow_NetworkDeleteRequest: Sendable {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
// methods supported on all messages.
|
||||
|
||||
public var id: Int32 = 0
|
||||
|
||||
public var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
public init() {}
|
||||
}
|
||||
|
||||
public struct Burrow_Network: @unchecked Sendable {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
// methods supported on all messages.
|
||||
|
||||
public var id: Int32 = 0
|
||||
|
||||
public var type: Burrow_NetworkType = .wireGuard
|
||||
|
||||
public var payload: Data = Data()
|
||||
|
||||
public var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
public init() {}
|
||||
}
|
||||
|
||||
public struct Burrow_NetworkListResponse: Sendable {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
// methods supported on all messages.
|
||||
|
||||
public var network: [Burrow_Network] = []
|
||||
|
||||
public var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
public init() {}
|
||||
}
|
||||
|
||||
public struct Burrow_Empty: Sendable {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
// methods supported on all messages.
|
||||
|
||||
public var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
public init() {}
|
||||
}
|
||||
|
||||
public struct Burrow_TunnelStatusResponse: Sendable {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
// methods supported on all messages.
|
||||
|
||||
public var state: Burrow_State = .stopped
|
||||
|
||||
public var start: SwiftProtobuf.Google_Protobuf_Timestamp {
|
||||
get {return _start ?? SwiftProtobuf.Google_Protobuf_Timestamp()}
|
||||
set {_start = newValue}
|
||||
}
|
||||
/// Returns true if `start` has been explicitly set.
|
||||
public var hasStart: Bool {return self._start != nil}
|
||||
/// Clears the value of `start`. Subsequent reads from it will return its default value.
|
||||
public mutating func clearStart() {self._start = nil}
|
||||
|
||||
public var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
public init() {}
|
||||
|
||||
fileprivate var _start: SwiftProtobuf.Google_Protobuf_Timestamp? = nil
|
||||
}
|
||||
|
||||
public struct Burrow_TunnelConfigurationResponse: Sendable {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
// methods supported on all messages.
|
||||
|
||||
public var addresses: [String] = []
|
||||
|
||||
public var mtu: Int32 = 0
|
||||
|
||||
public var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
public init() {}
|
||||
}
|
||||
|
||||
// MARK: - Code below here is support for the SwiftProtobuf runtime.
|
||||
|
||||
fileprivate let _protobuf_package = "burrow"
|
||||
|
||||
extension Burrow_NetworkType: SwiftProtobuf._ProtoNameProviding {
|
||||
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
0: .same(proto: "WireGuard"),
|
||||
1: .same(proto: "Tailnet"),
|
||||
]
|
||||
}
|
||||
|
||||
extension Burrow_State: SwiftProtobuf._ProtoNameProviding {
|
||||
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
0: .same(proto: "Stopped"),
|
||||
1: .same(proto: "Running"),
|
||||
]
|
||||
}
|
||||
|
||||
extension Burrow_NetworkReorderRequest: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
public static let protoMessageName: String = _protobuf_package + ".NetworkReorderRequest"
|
||||
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .same(proto: "id"),
|
||||
2: .same(proto: "index"),
|
||||
]
|
||||
|
||||
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every case branch when no optimizations are
|
||||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch fieldNumber {
|
||||
case 1: try { try decoder.decodeSingularInt32Field(value: &self.id) }()
|
||||
case 2: try { try decoder.decodeSingularInt32Field(value: &self.index) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if self.id != 0 {
|
||||
try visitor.visitSingularInt32Field(value: self.id, fieldNumber: 1)
|
||||
}
|
||||
if self.index != 0 {
|
||||
try visitor.visitSingularInt32Field(value: self.index, fieldNumber: 2)
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
public static func ==(lhs: Burrow_NetworkReorderRequest, rhs: Burrow_NetworkReorderRequest) -> Bool {
|
||||
if lhs.id != rhs.id {return false}
|
||||
if lhs.index != rhs.index {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
extension Burrow_WireGuardPeer: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
public static let protoMessageName: String = _protobuf_package + ".WireGuardPeer"
|
||||
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .same(proto: "endpoint"),
|
||||
2: .same(proto: "subnet"),
|
||||
]
|
||||
|
||||
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every case branch when no optimizations are
|
||||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch fieldNumber {
|
||||
case 1: try { try decoder.decodeSingularStringField(value: &self.endpoint) }()
|
||||
case 2: try { try decoder.decodeRepeatedStringField(value: &self.subnet) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if !self.endpoint.isEmpty {
|
||||
try visitor.visitSingularStringField(value: self.endpoint, fieldNumber: 1)
|
||||
}
|
||||
if !self.subnet.isEmpty {
|
||||
try visitor.visitRepeatedStringField(value: self.subnet, fieldNumber: 2)
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
public static func ==(lhs: Burrow_WireGuardPeer, rhs: Burrow_WireGuardPeer) -> Bool {
|
||||
if lhs.endpoint != rhs.endpoint {return false}
|
||||
if lhs.subnet != rhs.subnet {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
extension Burrow_WireGuardNetwork: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
public static let protoMessageName: String = _protobuf_package + ".WireGuardNetwork"
|
||||
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .same(proto: "address"),
|
||||
2: .same(proto: "dns"),
|
||||
3: .same(proto: "peer"),
|
||||
]
|
||||
|
||||
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every case branch when no optimizations are
|
||||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch fieldNumber {
|
||||
case 1: try { try decoder.decodeSingularStringField(value: &self.address) }()
|
||||
case 2: try { try decoder.decodeSingularStringField(value: &self.dns) }()
|
||||
case 3: try { try decoder.decodeRepeatedMessageField(value: &self.peer) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if !self.address.isEmpty {
|
||||
try visitor.visitSingularStringField(value: self.address, fieldNumber: 1)
|
||||
}
|
||||
if !self.dns.isEmpty {
|
||||
try visitor.visitSingularStringField(value: self.dns, fieldNumber: 2)
|
||||
}
|
||||
if !self.peer.isEmpty {
|
||||
try visitor.visitRepeatedMessageField(value: self.peer, fieldNumber: 3)
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
public static func ==(lhs: Burrow_WireGuardNetwork, rhs: Burrow_WireGuardNetwork) -> Bool {
|
||||
if lhs.address != rhs.address {return false}
|
||||
if lhs.dns != rhs.dns {return false}
|
||||
if lhs.peer != rhs.peer {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
extension Burrow_NetworkDeleteRequest: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
public static let protoMessageName: String = _protobuf_package + ".NetworkDeleteRequest"
|
||||
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .same(proto: "id"),
|
||||
]
|
||||
|
||||
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every case branch when no optimizations are
|
||||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch fieldNumber {
|
||||
case 1: try { try decoder.decodeSingularInt32Field(value: &self.id) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if self.id != 0 {
|
||||
try visitor.visitSingularInt32Field(value: self.id, fieldNumber: 1)
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
public static func ==(lhs: Burrow_NetworkDeleteRequest, rhs: Burrow_NetworkDeleteRequest) -> Bool {
|
||||
if lhs.id != rhs.id {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
extension Burrow_Network: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
public static let protoMessageName: String = _protobuf_package + ".Network"
|
||||
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .same(proto: "id"),
|
||||
2: .same(proto: "type"),
|
||||
3: .same(proto: "payload"),
|
||||
]
|
||||
|
||||
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every case branch when no optimizations are
|
||||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch fieldNumber {
|
||||
case 1: try { try decoder.decodeSingularInt32Field(value: &self.id) }()
|
||||
case 2: try { try decoder.decodeSingularEnumField(value: &self.type) }()
|
||||
case 3: try { try decoder.decodeSingularBytesField(value: &self.payload) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if self.id != 0 {
|
||||
try visitor.visitSingularInt32Field(value: self.id, fieldNumber: 1)
|
||||
}
|
||||
if self.type != .wireGuard {
|
||||
try visitor.visitSingularEnumField(value: self.type, fieldNumber: 2)
|
||||
}
|
||||
if !self.payload.isEmpty {
|
||||
try visitor.visitSingularBytesField(value: self.payload, fieldNumber: 3)
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
public static func ==(lhs: Burrow_Network, rhs: Burrow_Network) -> Bool {
|
||||
if lhs.id != rhs.id {return false}
|
||||
if lhs.type != rhs.type {return false}
|
||||
if lhs.payload != rhs.payload {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
extension Burrow_NetworkListResponse: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
public static let protoMessageName: String = _protobuf_package + ".NetworkListResponse"
|
||||
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .same(proto: "network"),
|
||||
]
|
||||
|
||||
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every case branch when no optimizations are
|
||||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch fieldNumber {
|
||||
case 1: try { try decoder.decodeRepeatedMessageField(value: &self.network) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if !self.network.isEmpty {
|
||||
try visitor.visitRepeatedMessageField(value: self.network, fieldNumber: 1)
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
public static func ==(lhs: Burrow_NetworkListResponse, rhs: Burrow_NetworkListResponse) -> Bool {
|
||||
if lhs.network != rhs.network {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
extension Burrow_Empty: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
public static let protoMessageName: String = _protobuf_package + ".Empty"
|
||||
public static let _protobuf_nameMap = SwiftProtobuf._NameMap()
|
||||
|
||||
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
// Load everything into unknown fields
|
||||
while try decoder.nextFieldNumber() != nil {}
|
||||
}
|
||||
|
||||
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
public static func ==(lhs: Burrow_Empty, rhs: Burrow_Empty) -> Bool {
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
extension Burrow_TunnelStatusResponse: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
public static let protoMessageName: String = _protobuf_package + ".TunnelStatusResponse"
|
||||
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .same(proto: "state"),
|
||||
2: .same(proto: "start"),
|
||||
]
|
||||
|
||||
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every case branch when no optimizations are
|
||||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch fieldNumber {
|
||||
case 1: try { try decoder.decodeSingularEnumField(value: &self.state) }()
|
||||
case 2: try { try decoder.decodeSingularMessageField(value: &self._start) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every if/case branch local when no optimizations
|
||||
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
|
||||
// https://github.com/apple/swift-protobuf/issues/1182
|
||||
if self.state != .stopped {
|
||||
try visitor.visitSingularEnumField(value: self.state, fieldNumber: 1)
|
||||
}
|
||||
try { if let v = self._start {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 2)
|
||||
} }()
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
public static func ==(lhs: Burrow_TunnelStatusResponse, rhs: Burrow_TunnelStatusResponse) -> Bool {
|
||||
if lhs.state != rhs.state {return false}
|
||||
if lhs._start != rhs._start {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
extension Burrow_TunnelConfigurationResponse: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
public static let protoMessageName: String = _protobuf_package + ".TunnelConfigurationResponse"
|
||||
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .same(proto: "addresses"),
|
||||
2: .same(proto: "mtu"),
|
||||
]
|
||||
|
||||
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every case branch when no optimizations are
|
||||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch fieldNumber {
|
||||
case 1: try { try decoder.decodeRepeatedStringField(value: &self.addresses) }()
|
||||
case 2: try { try decoder.decodeSingularInt32Field(value: &self.mtu) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if !self.addresses.isEmpty {
|
||||
try visitor.visitRepeatedStringField(value: self.addresses, fieldNumber: 1)
|
||||
}
|
||||
if self.mtu != 0 {
|
||||
try visitor.visitSingularInt32Field(value: self.mtu, fieldNumber: 2)
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
public static func ==(lhs: Burrow_TunnelConfigurationResponse, rhs: Burrow_TunnelConfigurationResponse) -> Bool {
|
||||
if lhs.addresses != rhs.addresses {return false}
|
||||
if lhs.mtu != rhs.mtu {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
{
|
||||
"invocations": [
|
||||
{
|
||||
"protoFiles": [
|
||||
"burrow.proto",
|
||||
],
|
||||
"server": false,
|
||||
"visibility": "public"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
{
|
||||
"invocations": [
|
||||
{
|
||||
"protoFiles": [
|
||||
"burrow.proto",
|
||||
],
|
||||
"visibility": "public"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -284,6 +284,7 @@ private struct AccountDraft {
|
|||
var identityName = ""
|
||||
var wireGuardConfig = ""
|
||||
|
||||
var discoveryEmail = ""
|
||||
var tailnetProvider: TailnetProvider = .tailscale
|
||||
var authority = ""
|
||||
var tailnet = ""
|
||||
|
|
@ -327,6 +328,9 @@ private struct ConfigurationSheetView: View {
|
|||
@State private var errorMessage: String?
|
||||
@State private var loginSessionID: String?
|
||||
@State private var loginStatus: TailnetLoginStatus?
|
||||
@State private var discoveryStatus: TailnetDiscoveryResponse?
|
||||
@State private var discoveryError: String?
|
||||
@State private var isDiscoveringTailnet = false
|
||||
@State private var authorityProbeStatus: TailnetAuthorityProbeStatus?
|
||||
@State private var authorityProbeError: String?
|
||||
@State private var isProbingAuthority = false
|
||||
|
|
@ -449,6 +453,9 @@ private struct ConfigurationSheetView: View {
|
|||
.onChange(of: draft.authority) { _, _ in
|
||||
resetAuthorityProbe()
|
||||
}
|
||||
.onChange(of: draft.discoveryEmail) { _, _ in
|
||||
resetTailnetDiscoveryFeedback()
|
||||
}
|
||||
.onDisappear {
|
||||
pollingTask?.cancel()
|
||||
webAuthenticationTask?.cancel()
|
||||
|
|
@ -459,7 +466,37 @@ private struct ConfigurationSheetView: View {
|
|||
@ViewBuilder
|
||||
private var tailnetSections: some View {
|
||||
Section("Connection") {
|
||||
Picker("Provider", selection: $draft.tailnetProvider) {
|
||||
TextField("Email address", text: $draft.discoveryEmail)
|
||||
.textInputAutocapitalization(.never)
|
||||
.keyboardType(.emailAddress)
|
||||
.burrowLoginField()
|
||||
.autocorrectionDisabled()
|
||||
|
||||
Button {
|
||||
discoverTailnetAuthority()
|
||||
} label: {
|
||||
Label {
|
||||
Text(isDiscoveringTailnet ? "Finding Server" : "Find Server")
|
||||
} icon: {
|
||||
Image(systemName: isDiscoveringTailnet ? "hourglass" : "at.circle")
|
||||
}
|
||||
}
|
||||
.buttonStyle(.borderless)
|
||||
.disabled(isDiscoveringTailnet || normalizedOptional(draft.discoveryEmail) == nil)
|
||||
|
||||
if let discoveryStatus {
|
||||
tailnetDiscoveryCard(status: discoveryStatus, failure: nil)
|
||||
} else if let discoveryError {
|
||||
tailnetDiscoveryCard(status: nil, failure: discoveryError)
|
||||
}
|
||||
|
||||
Picker(
|
||||
"Provider",
|
||||
selection: Binding(
|
||||
get: { draft.tailnetProvider },
|
||||
set: { applyTailnetProvider($0) }
|
||||
)
|
||||
) {
|
||||
ForEach(TailnetProvider.allCases) { provider in
|
||||
Text(provider.title).tag(provider)
|
||||
}
|
||||
|
|
@ -503,14 +540,14 @@ private struct ConfigurationSheetView: View {
|
|||
}
|
||||
|
||||
Section("Authentication") {
|
||||
if draft.tailnetProvider.usesWebLogin {
|
||||
if tailnetUsesWebLogin {
|
||||
tailnetWebLoginCard
|
||||
} else {
|
||||
TextField("Username", text: $draft.username)
|
||||
.burrowLoginField()
|
||||
.autocorrectionDisabled()
|
||||
Picker("Authentication", selection: $draft.authMode) {
|
||||
ForEach([AccountAuthMode.none, .password, .preauthKey]) { mode in
|
||||
ForEach(availableTailnetAuthModes) { mode in
|
||||
Text(mode.title).tag(mode)
|
||||
}
|
||||
}
|
||||
|
|
@ -583,7 +620,7 @@ private struct ConfigurationSheetView: View {
|
|||
HStack(spacing: 8) {
|
||||
summaryBadge(draft.tailnetProvider.title)
|
||||
summaryBadge(
|
||||
draft.tailnetProvider.usesWebLogin ? "Web Sign-In" : draft.authMode.title
|
||||
tailnetUsesWebLogin ? "Web Sign-In" : draft.authMode.title
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -656,7 +693,7 @@ private struct ConfigurationSheetView: View {
|
|||
.foregroundStyle(.secondary)
|
||||
}
|
||||
} else {
|
||||
Text("Burrow launches the local bridge, then opens the real Tailscale sign-in page in-app.")
|
||||
Text("Burrow launches the local bridge, then opens the real provider sign-in page in-app.")
|
||||
.font(.footnote)
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
|
|
@ -696,6 +733,41 @@ private struct ConfigurationSheetView: View {
|
|||
)
|
||||
}
|
||||
|
||||
private func tailnetDiscoveryCard(
|
||||
status: TailnetDiscoveryResponse?,
|
||||
failure: String?
|
||||
) -> some View {
|
||||
VStack(alignment: .leading, spacing: 6) {
|
||||
if let status {
|
||||
Text("Discovered \(status.provider.title)")
|
||||
.font(.subheadline.weight(.medium))
|
||||
Text(status.authority)
|
||||
.font(.footnote.monospaced())
|
||||
.foregroundStyle(.secondary)
|
||||
.textSelection(.enabled)
|
||||
if let oidcIssuer = status.oidcIssuer {
|
||||
Text("OIDC: \(oidcIssuer)")
|
||||
.font(.footnote)
|
||||
.foregroundStyle(.secondary)
|
||||
.lineLimit(3)
|
||||
.textSelection(.enabled)
|
||||
}
|
||||
} else if let failure {
|
||||
Text("Discovery failed")
|
||||
.font(.subheadline.weight(.medium))
|
||||
.foregroundStyle(.red)
|
||||
Text(failure)
|
||||
.font(.footnote)
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
}
|
||||
.padding(12)
|
||||
.background(
|
||||
RoundedRectangle(cornerRadius: 16)
|
||||
.fill(.thinMaterial)
|
||||
)
|
||||
}
|
||||
|
||||
private func summaryBadge(_ label: String) -> some View {
|
||||
Text(label)
|
||||
.font(.caption.weight(.medium))
|
||||
|
|
@ -762,12 +834,12 @@ private struct ConfigurationSheetView: View {
|
|||
}
|
||||
}
|
||||
|
||||
if !draft.tailnetProvider.usesWebLogin {
|
||||
if availableTailnetAuthModes.count > 1 {
|
||||
Menu("Authentication") {
|
||||
ForEach([AccountAuthMode.none, .password, .preauthKey]) { mode in
|
||||
ForEach(availableTailnetAuthModes) { mode in
|
||||
Button(mode.title) {
|
||||
draft.authMode = mode
|
||||
if mode == .none {
|
||||
if mode == .none || mode == .web {
|
||||
draft.secret = ""
|
||||
}
|
||||
}
|
||||
|
|
@ -848,7 +920,7 @@ private struct ConfigurationSheetView: View {
|
|||
case .tor:
|
||||
return "Save Account"
|
||||
case .tailnet:
|
||||
if draft.tailnetProvider.usesWebLogin {
|
||||
if tailnetUsesWebLogin {
|
||||
return loginStatus?.running == true ? "Save Account" : "Start Sign-In"
|
||||
}
|
||||
return "Save Account"
|
||||
|
|
@ -865,12 +937,12 @@ private struct ConfigurationSheetView: View {
|
|||
if normalizedOptional(draft.accountName) == nil || normalizedOptional(draft.identityName) == nil {
|
||||
return true
|
||||
}
|
||||
if draft.tailnetProvider.usesWebLogin {
|
||||
return false
|
||||
}
|
||||
if draft.tailnetProvider.requiresControlURL && normalizedOptional(draft.authority) == nil {
|
||||
return true
|
||||
}
|
||||
if tailnetUsesWebLogin {
|
||||
return false
|
||||
}
|
||||
if draft.authMode != .none && normalizedOptional(draft.secret) == nil {
|
||||
return true
|
||||
}
|
||||
|
|
@ -955,14 +1027,14 @@ private struct ConfigurationSheetView: View {
|
|||
}
|
||||
|
||||
private func submitTailnet() async throws {
|
||||
if draft.tailnetProvider.usesWebLogin {
|
||||
if tailnetUsesWebLogin {
|
||||
if loginStatus?.running == true {
|
||||
webAuthenticationTask?.cancel()
|
||||
webAuthenticationTask = nil
|
||||
try await saveTailnetAccount(secret: nil, username: nil)
|
||||
dismiss()
|
||||
} else {
|
||||
try await startTailscaleLogin()
|
||||
try await startTailnetLogin()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
@ -973,13 +1045,13 @@ private struct ConfigurationSheetView: View {
|
|||
dismiss()
|
||||
}
|
||||
|
||||
private func startTailscaleLogin() async throws {
|
||||
private func startTailnetLogin() async throws {
|
||||
let response = try await TailnetBridgeClient.startLogin(
|
||||
TailnetLoginStartRequest(
|
||||
accountName: normalized(draft.accountName, fallback: "default"),
|
||||
identityName: normalized(draft.identityName, fallback: "apple"),
|
||||
hostname: normalizedOptional(draft.hostname),
|
||||
controlURL: draft.tailnetProvider.defaultAuthority
|
||||
controlURL: normalizedOptional(draft.authority) ?? draft.tailnetProvider.defaultAuthority
|
||||
)
|
||||
)
|
||||
loginSessionID = response.sessionID
|
||||
|
|
@ -1010,7 +1082,7 @@ private struct ConfigurationSheetView: View {
|
|||
case .tailnetLogin:
|
||||
draft.tailnetProvider = .tailscale
|
||||
do {
|
||||
try await startTailscaleLogin()
|
||||
try await startTailnetLogin()
|
||||
} catch {
|
||||
errorMessage = error.localizedDescription
|
||||
}
|
||||
|
|
@ -1078,14 +1150,14 @@ private struct ConfigurationSheetView: View {
|
|||
let provider = draft.tailnetProvider
|
||||
let title = titleOrFallback(
|
||||
hostnameFallback(
|
||||
from: provider.usesWebLogin ? (loginStatus?.tailnetName ?? "") : draft.authority,
|
||||
from: tailnetUsesWebLogin ? (loginStatus?.tailnetName ?? "") : draft.authority,
|
||||
fallback: provider.title
|
||||
)
|
||||
)
|
||||
|
||||
let payload = TailnetNetworkPayload(
|
||||
provider: provider,
|
||||
authority: normalizedOptional(provider.defaultAuthority ?? draft.authority),
|
||||
authority: normalizedOptional(draft.authority) ?? normalizedOptional(provider.defaultAuthority ?? ""),
|
||||
account: normalized(draft.accountName, fallback: "default"),
|
||||
identity: normalized(draft.identityName, fallback: "apple"),
|
||||
tailnet: normalizedOptional(loginStatus?.tailnetName ?? draft.tailnet),
|
||||
|
|
@ -1094,7 +1166,7 @@ private struct ConfigurationSheetView: View {
|
|||
|
||||
var noteParts: [String] = [
|
||||
provider.title,
|
||||
provider.usesWebLogin
|
||||
tailnetUsesWebLogin
|
||||
? "State: \(loginStatus?.backendState ?? "NeedsLogin")"
|
||||
: "Auth: \(draft.authMode.title)",
|
||||
]
|
||||
|
|
@ -1123,7 +1195,7 @@ private struct ConfigurationSheetView: View {
|
|||
hostname: payload.hostname,
|
||||
username: username,
|
||||
tailnet: payload.tailnet,
|
||||
authMode: provider.usesWebLogin ? .web : draft.authMode,
|
||||
authMode: tailnetUsesWebLogin ? .web : draft.authMode,
|
||||
note: noteParts.joined(separator: " • "),
|
||||
createdAt: .now,
|
||||
updatedAt: .now
|
||||
|
|
@ -1155,18 +1227,25 @@ private struct ConfigurationSheetView: View {
|
|||
}
|
||||
|
||||
private func applyTailnetProvider(_ provider: TailnetProvider) {
|
||||
resetTailnetDiscoveryFeedback()
|
||||
draft.tailnetProvider = provider
|
||||
applyTailnetDefaults(for: provider)
|
||||
}
|
||||
|
||||
private func applyTailnetDefaults(for provider: TailnetProvider) {
|
||||
draft.authority = provider.defaultAuthority ?? ""
|
||||
if provider.usesWebLogin {
|
||||
loginStatus = nil
|
||||
loginSessionID = nil
|
||||
pollingTask?.cancel()
|
||||
if provider == .tailscale {
|
||||
draft.authMode = .web
|
||||
draft.username = ""
|
||||
draft.secret = ""
|
||||
} else {
|
||||
if draft.authMode == .web {
|
||||
if !availableTailnetAuthModes.contains(draft.authMode) {
|
||||
draft.authMode = provider.supportsWebLogin ? .web : .none
|
||||
}
|
||||
if draft.authMode == .web && !provider.supportsWebLogin {
|
||||
draft.authMode = .none
|
||||
}
|
||||
}
|
||||
|
|
@ -1202,6 +1281,41 @@ private struct ConfigurationSheetView: View {
|
|||
authorityProbeError = nil
|
||||
}
|
||||
|
||||
private func resetTailnetDiscoveryFeedback() {
|
||||
discoveryStatus = nil
|
||||
discoveryError = nil
|
||||
}
|
||||
|
||||
private func discoverTailnetAuthority() {
|
||||
guard let email = normalizedOptional(draft.discoveryEmail) else {
|
||||
discoveryStatus = nil
|
||||
discoveryError = "Enter an email address first."
|
||||
return
|
||||
}
|
||||
|
||||
isDiscoveringTailnet = true
|
||||
discoveryStatus = nil
|
||||
discoveryError = nil
|
||||
|
||||
Task { @MainActor in
|
||||
defer { isDiscoveringTailnet = false }
|
||||
do {
|
||||
let discovery = try await TailnetDiscoveryClient.discover(email: email)
|
||||
discoveryStatus = discovery
|
||||
draft.tailnetProvider = discovery.provider
|
||||
draft.authority = discovery.authority
|
||||
if discovery.provider.supportsWebLogin, discovery.oidcIssuer != nil {
|
||||
draft.authMode = .web
|
||||
draft.username = ""
|
||||
draft.secret = ""
|
||||
}
|
||||
probeTailnetAuthority()
|
||||
} catch {
|
||||
discoveryError = error.localizedDescription
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func pasteWireGuardConfiguration() {
|
||||
guard let clipboardString else { return }
|
||||
draft.wireGuardConfig = clipboardString
|
||||
|
|
@ -1247,6 +1361,21 @@ private struct ConfigurationSheetView: View {
|
|||
return host
|
||||
}
|
||||
|
||||
private var tailnetUsesWebLogin: Bool {
|
||||
draft.authMode == .web && draft.tailnetProvider.supportsWebLogin
|
||||
}
|
||||
|
||||
private var availableTailnetAuthModes: [AccountAuthMode] {
|
||||
switch draft.tailnetProvider {
|
||||
case .tailscale:
|
||||
[.web]
|
||||
case .headscale:
|
||||
[.web, .none, .password, .preauthKey]
|
||||
case .burrow:
|
||||
[.none, .password, .preauthKey]
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private func labeledValue(_ label: String, _ value: String) -> some View {
|
||||
VStack(alignment: .leading, spacing: 2) {
|
||||
|
|
|
|||
|
|
@ -33,6 +33,13 @@ struct TailnetLoginStartRequest: Codable, Sendable {
|
|||
var controlURL: String?
|
||||
}
|
||||
|
||||
struct TailnetDiscoveryResponse: Codable, Sendable {
|
||||
var domain: String
|
||||
var provider: TailnetProvider
|
||||
var authority: String
|
||||
var oidcIssuer: String?
|
||||
}
|
||||
|
||||
struct TailnetLoginStatus: Codable, Sendable {
|
||||
var backendState: String
|
||||
var authURL: String?
|
||||
|
|
@ -91,7 +98,7 @@ enum TailnetBridgeClient {
|
|||
return try decoder.decode(TailnetLoginStatus.self, from: data)
|
||||
}
|
||||
|
||||
private static func validate(response: URLResponse, data: Data) throws {
|
||||
fileprivate static func validate(response: URLResponse, data: Data) throws {
|
||||
guard let http = response as? HTTPURLResponse else {
|
||||
throw URLError(.badServerResponse)
|
||||
}
|
||||
|
|
@ -104,6 +111,32 @@ enum TailnetBridgeClient {
|
|||
}
|
||||
}
|
||||
|
||||
enum TailnetDiscoveryClient {
|
||||
private static let baseURL = URL(string: "http://127.0.0.1:8080")!
|
||||
|
||||
static func discover(email: String) async throws -> TailnetDiscoveryResponse {
|
||||
guard var components = URLComponents(
|
||||
url: baseURL.appendingPathComponent("v1/tailnet/discover"),
|
||||
resolvingAgainstBaseURL: false
|
||||
) else {
|
||||
throw URLError(.badURL)
|
||||
}
|
||||
components.queryItems = [
|
||||
URLQueryItem(name: "email", value: email)
|
||||
]
|
||||
guard let url = components.url else {
|
||||
throw URLError(.badURL)
|
||||
}
|
||||
|
||||
let (data, response) = try await URLSession.shared.data(from: url)
|
||||
try TailnetBridgeClient.validate(response: response, data: data)
|
||||
|
||||
let decoder = JSONDecoder()
|
||||
decoder.keyDecodingStrategy = .convertFromSnakeCase
|
||||
return try decoder.decode(TailnetDiscoveryResponse.self, from: data)
|
||||
}
|
||||
}
|
||||
|
||||
enum TailnetAuthorityProbeClient {
|
||||
static func probe(provider: TailnetProvider, authority: String) async throws -> TailnetAuthorityProbeStatus {
|
||||
let normalizedAuthority = normalizeAuthority(authority)
|
||||
|
|
@ -308,8 +341,13 @@ enum TailnetProvider: String, CaseIterable, Codable, Identifiable, Sendable {
|
|||
}
|
||||
}
|
||||
|
||||
var usesWebLogin: Bool {
|
||||
self == .tailscale
|
||||
var supportsWebLogin: Bool {
|
||||
switch self {
|
||||
case .tailscale, .headscale:
|
||||
true
|
||||
case .burrow:
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
var requiresControlURL: Bool {
|
||||
|
|
@ -332,7 +370,7 @@ enum TailnetProvider: String, CaseIterable, Codable, Identifiable, Sendable {
|
|||
case .tailscale:
|
||||
"Use Tailscale's real browser login flow."
|
||||
case .headscale:
|
||||
"Store a Headscale control-plane endpoint and credentials."
|
||||
"Use your Headscale control plane with browser or key-based sign-in."
|
||||
case .burrow:
|
||||
"Store Burrow control-plane credentials."
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,17 +5,18 @@ use std::{env, path::Path};
|
|||
|
||||
use anyhow::{Context, Result};
|
||||
use axum::{
|
||||
extract::{Json, Path as AxumPath, State},
|
||||
extract::{Json, Path as AxumPath, Query, State},
|
||||
http::{header::AUTHORIZATION, HeaderMap, StatusCode},
|
||||
response::IntoResponse,
|
||||
routing::{get, post},
|
||||
Router,
|
||||
};
|
||||
use serde::Deserialize;
|
||||
use tokio::signal;
|
||||
|
||||
use crate::control::{
|
||||
LocalAuthRequest, LocalAuthResponse, MapRequest, MapResponse, RegisterRequest,
|
||||
RegisterResponse, BURROW_TAILNET_DOMAIN,
|
||||
discovery, LocalAuthRequest, LocalAuthResponse, MapRequest, MapResponse, RegisterRequest,
|
||||
RegisterResponse, TailnetDiscovery, BURROW_TAILNET_DOMAIN,
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
|
@ -105,6 +106,11 @@ struct AppState {
|
|||
tailscale: tailscale::TailscaleBridgeManager,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct TailnetDiscoveryQuery {
|
||||
email: String,
|
||||
}
|
||||
|
||||
type AppResult<T> = Result<T, (StatusCode, String)>;
|
||||
|
||||
pub async fn serve() -> Result<()> {
|
||||
|
|
@ -139,6 +145,7 @@ pub fn build_router(config: AuthServerConfig) -> Router {
|
|||
.route("/v1/auth/login", post(login_local))
|
||||
.route("/v1/control/register", post(control_register))
|
||||
.route("/v1/control/map", post(control_map))
|
||||
.route("/v1/tailnet/discover", get(tailnet_discover))
|
||||
.route("/v1/tailscale/login/start", post(tailscale_login_start))
|
||||
.route("/v1/tailscale/login/:session_id", get(tailscale_login_status))
|
||||
.with_state(AppState {
|
||||
|
|
@ -205,6 +212,19 @@ async fn control_map(
|
|||
Ok(Json(response))
|
||||
}
|
||||
|
||||
async fn tailnet_discover(
|
||||
Query(query): Query<TailnetDiscoveryQuery>,
|
||||
) -> AppResult<Json<TailnetDiscovery>> {
|
||||
if query.email.trim().is_empty() {
|
||||
return Err((StatusCode::BAD_REQUEST, "email is required".to_owned()));
|
||||
}
|
||||
|
||||
let discovery = discovery::discover_tailnet(&query.email)
|
||||
.await
|
||||
.map_err(|err| (StatusCode::BAD_GATEWAY, err.to_string()))?;
|
||||
Ok(Json(discovery))
|
||||
}
|
||||
|
||||
async fn tailscale_login_start(
|
||||
State(state): State<AppState>,
|
||||
Json(request): Json<tailscale::TailscaleLoginStartRequest>,
|
||||
|
|
@ -394,4 +414,17 @@ mod tests {
|
|||
assert!(map.dns.expect("dns").magic_dns);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn tailnet_discover_requires_email() -> Result<()> {
|
||||
let app = build_router(AuthServerConfig::default());
|
||||
let response = app
|
||||
.oneshot(
|
||||
Request::get("/v1/tailnet/discover?email=")
|
||||
.body(Body::empty())?,
|
||||
)
|
||||
.await?;
|
||||
assert_eq!(response.status(), StatusCode::BAD_REQUEST);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
212
burrow/src/control/discovery.rs
Normal file
212
burrow/src/control/discovery.rs
Normal file
|
|
@ -0,0 +1,212 @@
|
|||
use anyhow::{anyhow, Context, Result};
|
||||
use reqwest::{Client, StatusCode, Url};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::TailnetProvider;
|
||||
|
||||
pub const TAILNET_DISCOVERY_REL: &str = "https://burrow.net/rel/tailnet-control-server";
|
||||
const TAILNET_DISCOVERY_PATH: &str = "/.well-known/burrow-tailnet";
|
||||
const WEBFINGER_PATH: &str = "/.well-known/webfinger";
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub struct TailnetDiscovery {
|
||||
pub domain: String,
|
||||
pub provider: TailnetProvider,
|
||||
pub authority: String,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub oidc_issuer: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, Deserialize)]
|
||||
struct WebFingerDocument {
|
||||
#[serde(default)]
|
||||
links: Vec<WebFingerLink>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, Deserialize)]
|
||||
struct WebFingerLink {
|
||||
#[serde(default)]
|
||||
rel: String,
|
||||
#[serde(default)]
|
||||
href: Option<String>,
|
||||
}
|
||||
|
||||
pub async fn discover_tailnet(email: &str) -> Result<TailnetDiscovery> {
|
||||
let domain = email_domain(email)?;
|
||||
let base_url = Url::parse(&format!("https://{domain}"))
|
||||
.with_context(|| format!("invalid discovery domain {domain}"))?;
|
||||
let client = Client::builder()
|
||||
.user_agent("burrow-tailnet-discovery")
|
||||
.timeout(std::time::Duration::from_secs(10))
|
||||
.build()
|
||||
.context("failed to build tailnet discovery client")?;
|
||||
discover_tailnet_at(&client, email, &base_url).await
|
||||
}
|
||||
|
||||
pub async fn discover_tailnet_at(
|
||||
client: &Client,
|
||||
email: &str,
|
||||
base_url: &Url,
|
||||
) -> Result<TailnetDiscovery> {
|
||||
let domain = email_domain(email)?;
|
||||
|
||||
if let Some(discovery) = discover_well_known(client, base_url).await? {
|
||||
return Ok(TailnetDiscovery { domain, ..discovery });
|
||||
}
|
||||
|
||||
if let Some(authority) = discover_webfinger(client, email, base_url).await? {
|
||||
return Ok(TailnetDiscovery {
|
||||
domain,
|
||||
provider: TailnetProvider::Headscale,
|
||||
authority,
|
||||
oidc_issuer: None,
|
||||
});
|
||||
}
|
||||
|
||||
Err(anyhow!("no tailnet discovery metadata found for {domain}"))
|
||||
}
|
||||
|
||||
pub fn email_domain(email: &str) -> Result<String> {
|
||||
let trimmed = email.trim();
|
||||
let (_, domain) = trimmed
|
||||
.rsplit_once('@')
|
||||
.ok_or_else(|| anyhow!("email address must include a domain"))?;
|
||||
let domain = domain.trim().trim_matches('.').to_ascii_lowercase();
|
||||
if domain.is_empty() {
|
||||
return Err(anyhow!("email address must include a domain"));
|
||||
}
|
||||
Ok(domain)
|
||||
}
|
||||
|
||||
async fn discover_well_known(client: &Client, base_url: &Url) -> Result<Option<TailnetDiscovery>> {
|
||||
let url = base_url
|
||||
.join(TAILNET_DISCOVERY_PATH)
|
||||
.context("failed to build tailnet discovery URL")?;
|
||||
let response = client
|
||||
.get(url)
|
||||
.header("accept", "application/json")
|
||||
.send()
|
||||
.await
|
||||
.context("tailnet well-known request failed")?;
|
||||
|
||||
match response.status() {
|
||||
StatusCode::OK => response
|
||||
.json::<TailnetDiscovery>()
|
||||
.await
|
||||
.context("invalid tailnet discovery document")
|
||||
.map(Some),
|
||||
StatusCode::NOT_FOUND => Ok(None),
|
||||
status => Err(anyhow!("tailnet well-known lookup failed with HTTP {status}")),
|
||||
}
|
||||
}
|
||||
|
||||
async fn discover_webfinger(client: &Client, email: &str, base_url: &Url) -> Result<Option<String>> {
|
||||
let mut url = base_url
|
||||
.join(WEBFINGER_PATH)
|
||||
.context("failed to build webfinger URL")?;
|
||||
url.query_pairs_mut()
|
||||
.append_pair("resource", &format!("acct:{email}"))
|
||||
.append_pair("rel", TAILNET_DISCOVERY_REL);
|
||||
|
||||
let response = client
|
||||
.get(url)
|
||||
.header("accept", "application/jrd+json, application/json")
|
||||
.send()
|
||||
.await
|
||||
.context("tailnet webfinger request failed")?;
|
||||
|
||||
match response.status() {
|
||||
StatusCode::OK => {
|
||||
let document = response
|
||||
.json::<WebFingerDocument>()
|
||||
.await
|
||||
.context("invalid webfinger document")?;
|
||||
Ok(document
|
||||
.links
|
||||
.into_iter()
|
||||
.find(|link| link.rel == TAILNET_DISCOVERY_REL)
|
||||
.and_then(|link| link.href)
|
||||
.filter(|href| !href.trim().is_empty()))
|
||||
}
|
||||
StatusCode::NOT_FOUND => Ok(None),
|
||||
status => Err(anyhow!("tailnet webfinger lookup failed with HTTP {status}")),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use axum::{routing::get, Router};
|
||||
use serde_json::json;
|
||||
use tokio::net::TcpListener;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn extracts_domain_from_email() {
|
||||
assert_eq!(email_domain("Contact@Burrow.net").unwrap(), "burrow.net");
|
||||
assert!(email_domain("contact").is_err());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn discovers_from_well_known_document() -> Result<()> {
|
||||
let router = Router::new().route(
|
||||
TAILNET_DISCOVERY_PATH,
|
||||
get(|| async {
|
||||
axum::Json(json!({
|
||||
"domain": "burrow.net",
|
||||
"provider": "headscale",
|
||||
"authority": "https://ts.burrow.net",
|
||||
"oidc_issuer": "https://auth.burrow.net/application/o/ts/"
|
||||
}))
|
||||
}),
|
||||
);
|
||||
|
||||
let listener = TcpListener::bind("127.0.0.1:0").await?;
|
||||
let base_url = Url::parse(&format!("http://{}", listener.local_addr()?))?;
|
||||
let server = tokio::spawn(async move { axum::serve(listener, router).await });
|
||||
|
||||
let client = Client::builder().build()?;
|
||||
let discovery = discover_tailnet_at(&client, "contact@burrow.net", &base_url).await?;
|
||||
assert_eq!(discovery.provider, TailnetProvider::Headscale);
|
||||
assert_eq!(discovery.authority, "https://ts.burrow.net");
|
||||
assert_eq!(discovery.domain, "burrow.net");
|
||||
|
||||
server.abort();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn falls_back_to_webfinger_authority() -> Result<()> {
|
||||
let router = Router::new()
|
||||
.route(
|
||||
TAILNET_DISCOVERY_PATH,
|
||||
get(|| async { (StatusCode::NOT_FOUND, "") }),
|
||||
)
|
||||
.route(
|
||||
WEBFINGER_PATH,
|
||||
get(|| async {
|
||||
axum::Json(json!({
|
||||
"subject": "acct:contact@burrow.net",
|
||||
"links": [
|
||||
{
|
||||
"rel": TAILNET_DISCOVERY_REL,
|
||||
"href": "https://ts.burrow.net"
|
||||
}
|
||||
]
|
||||
}))
|
||||
}),
|
||||
);
|
||||
|
||||
let listener = TcpListener::bind("127.0.0.1:0").await?;
|
||||
let base_url = Url::parse(&format!("http://{}", listener.local_addr()?))?;
|
||||
let server = tokio::spawn(async move { axum::serve(listener, router).await });
|
||||
|
||||
let client = Client::builder().build()?;
|
||||
let discovery = discover_tailnet_at(&client, "contact@burrow.net", &base_url).await?;
|
||||
assert_eq!(discovery.provider, TailnetProvider::Headscale);
|
||||
assert_eq!(discovery.authority, "https://ts.burrow.net");
|
||||
|
||||
server.abort();
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
pub mod config;
|
||||
pub mod discovery;
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
|
|
@ -6,6 +7,7 @@ use serde::{Deserialize, Serialize};
|
|||
use serde_json::Value;
|
||||
|
||||
pub use config::{TailnetConfig, TailnetProvider};
|
||||
pub use discovery::{TailnetDiscovery, TAILNET_DISCOVERY_REL};
|
||||
|
||||
pub const BURROW_CAPABILITY_VERSION: i32 = 1;
|
||||
pub const BURROW_TAILNET_DOMAIN: &str = "burrow.net";
|
||||
|
|
|
|||
|
|
@ -259,9 +259,12 @@ in
|
|||
encode gzip zstd
|
||||
@oidcConfig path /.well-known/openid-configuration
|
||||
redir @oidcConfig https://${config.services.burrow.authentik.domain}/application/o/${config.services.burrow.authentik.forgejoProviderSlug}/.well-known/openid-configuration 308
|
||||
@tailnetConfig path /.well-known/burrow-tailnet
|
||||
header @tailnetConfig Content-Type application/json
|
||||
respond @tailnetConfig "{\"domain\":\"${cfg.siteDomain}\",\"provider\":\"headscale\",\"authority\":\"https://${config.services.burrow.headscale.domain}\",\"oidc_issuer\":\"https://${config.services.burrow.authentik.domain}/application/o/${config.services.burrow.authentik.headscaleProviderSlug}/\"}" 200
|
||||
@webfinger path /.well-known/webfinger
|
||||
header @webfinger Content-Type application/jrd+json
|
||||
respond @webfinger "{\"subject\":\"{query.resource}\",\"links\":[{\"rel\":\"http://openid.net/specs/connect/1.0/issuer\",\"href\":\"https://${config.services.burrow.authentik.domain}/application/o/${config.services.burrow.authentik.forgejoProviderSlug}/\"}]}" 200
|
||||
respond @webfinger "{\"subject\":\"{query.resource}\",\"links\":[{\"rel\":\"http://openid.net/specs/connect/1.0/issuer\",\"href\":\"https://${config.services.burrow.authentik.domain}/application/o/${config.services.burrow.authentik.forgejoProviderSlug}/\"},{\"rel\":\"https://burrow.net/rel/tailnet-control-server\",\"href\":\"https://${config.services.burrow.headscale.domain}\"}]}" 200
|
||||
@root path /
|
||||
redir @root ${homeRepoUrl} 308
|
||||
respond 404
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue