mirror of
https://github.com/Drop-OSS/libtailscale.git
synced 2026-07-01 06:41:57 -04:00
40f559c067
updates tailscale/tailscale#13937 Adds a Makefile for building various targets. Adds support for building iOS compatible libtailscale_ios.a. Removes SOCKS5 support for iOS where it looks like the CFNetwork support is lacking. Fixes a few unexported symbols in TailscaleKit. Added macOS sample app.
112 lines
3.4 KiB
Swift
112 lines
3.4 KiB
Swift
// Copyright (c) Tailscale Inc & AUTHORS
|
|
// SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
import Foundation
|
|
import Combine
|
|
|
|
/// ConnectionState indicates the state of individual TSConnection instances
|
|
public enum ConnectionState {
|
|
case idle ///< Reads and writes are not possible. Connections will transition to connected automatically
|
|
case connected ///< Connected and ready to read/write
|
|
case closed ///< Closed and ready to be disposed of. Closed connections cannot be reconnected.
|
|
case failed ///< The attempt to dial the connection failed
|
|
}
|
|
|
|
|
|
/// ListnerState indicates the state of individual TSListener instances
|
|
public enum ListenterState {
|
|
case idle ///< Waiting.
|
|
case listening ///< Listening
|
|
case closed ///< Closed and ready to be disposed of.
|
|
case failed ///< The attempt to start the listener failed
|
|
}
|
|
|
|
typealias TailscaleHandle = Int32
|
|
typealias TailscaleConnection = Int32
|
|
typealias TailscaleListener = Int32
|
|
|
|
/// Outgoing connections are used to send data to other endpoints
|
|
/// on the tailnet.
|
|
///
|
|
/// For HTTP(s), consider using URLSession.tailscaleSession
|
|
public actor OutgoingConnection {
|
|
private var tailscale: TailscaleHandle
|
|
private var proto: NetProtocol
|
|
private var address: String
|
|
private var conn: TailscaleConnection = 0
|
|
|
|
private let logger: LogSink
|
|
|
|
/// The state of the connection. Listen for transitions to determine
|
|
/// if the connection may be used for send/receive operations.
|
|
public var state: ConnectionState = .idle
|
|
|
|
/// Creates a new outgoing connection
|
|
///
|
|
/// @param tailscale The tailscale Server to use
|
|
/// @param address The remote address and port
|
|
/// @param proto The ip protocol
|
|
/// @param logger
|
|
///
|
|
/// @throws TailscaleError on failure
|
|
init(tailscale: TailscaleHandle,
|
|
to address: String,
|
|
proto: NetProtocol,
|
|
logger: LogSink) async throws {
|
|
|
|
self.logger = logger
|
|
self.proto = proto
|
|
self.address = address
|
|
self.tailscale = tailscale
|
|
}
|
|
|
|
/// Connects the outgoing connection to the remote. On success, the
|
|
/// connection state will be .connected.
|
|
///
|
|
/// @See tailscale_dial in Tailscale.h
|
|
///
|
|
/// @throws TailscaleError on failure
|
|
func connect() async throws {
|
|
let res = tailscale_dial(tailscale, proto.rawValue, address, &conn)
|
|
|
|
guard res == 0 else {
|
|
self.state = .failed
|
|
throw TailscaleError.fromPosixErrCode(res, tailscale.getErrorMessage())
|
|
}
|
|
|
|
self.state = .connected
|
|
}
|
|
|
|
deinit {
|
|
if conn != 0 {
|
|
unistd.close(conn)
|
|
}
|
|
}
|
|
|
|
/// Closes the outgoing connection. Further sends are not possible.
|
|
/// Connections will be closed on deallocation. Sets the connection
|
|
/// state to .closed
|
|
public func close() {
|
|
if conn != 0 {
|
|
unistd.close(conn)
|
|
conn = 0
|
|
}
|
|
state = .closed
|
|
}
|
|
|
|
/// Sends the given data to the connection
|
|
///
|
|
/// @throws TailscaleError on failure
|
|
public func send(_ data: Data) throws {
|
|
guard state == .connected else {
|
|
throw TailscaleError.connectionClosed
|
|
}
|
|
|
|
let bytesWritten = unistd.write(conn, data.withUnsafeBytes { $0.baseAddress! }, data.count)
|
|
|
|
if bytesWritten != data.count {
|
|
throw TailscaleError.shortWrite
|
|
}
|
|
}
|
|
}
|