Replace NEKit dependency with reduced subset
This commit is contained in:
113
GlassVPN/zhuhaow-NEKit/Socket/ProxySocket/DirectProxySocket.swift
Executable file
113
GlassVPN/zhuhaow-NEKit/Socket/ProxySocket/DirectProxySocket.swift
Executable file
@@ -0,0 +1,113 @@
|
||||
import Foundation
|
||||
|
||||
/// This class just forwards data directly.
|
||||
/// - note: It is designed to work with tun2socks only.
|
||||
public class DirectProxySocket: ProxySocket {
|
||||
enum DirectProxyReadStatus: CustomStringConvertible {
|
||||
case invalid,
|
||||
forwarding,
|
||||
stopped
|
||||
|
||||
var description: String {
|
||||
switch self {
|
||||
case .invalid:
|
||||
return "invalid"
|
||||
case .forwarding:
|
||||
return "forwarding"
|
||||
case .stopped:
|
||||
return "stopped"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum DirectProxyWriteStatus {
|
||||
case invalid,
|
||||
forwarding,
|
||||
stopped
|
||||
|
||||
var description: String {
|
||||
switch self {
|
||||
case .invalid:
|
||||
return "invalid"
|
||||
case .forwarding:
|
||||
return "forwarding"
|
||||
case .stopped:
|
||||
return "stopped"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var readStatus: DirectProxyReadStatus = .invalid
|
||||
private var writeStatus: DirectProxyWriteStatus = .invalid
|
||||
|
||||
public var readStatusDescription: String {
|
||||
return readStatus.description
|
||||
}
|
||||
|
||||
public var writeStatusDescription: String {
|
||||
return writeStatus.description
|
||||
}
|
||||
|
||||
/**
|
||||
Begin reading and processing data from the socket.
|
||||
|
||||
- note: Since there is nothing to read and process before forwarding data, this just calls `delegate?.didReceiveRequest`.
|
||||
*/
|
||||
override public func openSocket() {
|
||||
super.openSocket()
|
||||
|
||||
guard !isCancelled else {
|
||||
return
|
||||
}
|
||||
|
||||
if let address = socket.destinationIPAddress, let port = socket.destinationPort {
|
||||
session = ConnectSession(host: address.presentation, port: Int(port.value))
|
||||
|
||||
observer?.signal(.receivedRequest(session!, on: self))
|
||||
delegate?.didReceive(session: session!, from: self)
|
||||
} else {
|
||||
forceDisconnect()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Response to the `AdapterSocket` on the other side of the `Tunnel` which has succefully connected to the remote server.
|
||||
|
||||
- parameter adapter: The `AdapterSocket`.
|
||||
*/
|
||||
override public func respondTo(adapter: AdapterSocket) {
|
||||
super.respondTo(adapter: adapter)
|
||||
|
||||
guard !isCancelled else {
|
||||
return
|
||||
}
|
||||
|
||||
readStatus = .forwarding
|
||||
writeStatus = .forwarding
|
||||
|
||||
observer?.signal(.readyForForward(self))
|
||||
delegate?.didBecomeReadyToForwardWith(socket: self)
|
||||
}
|
||||
|
||||
/**
|
||||
The socket did read some data.
|
||||
|
||||
- parameter data: The data read from the socket.
|
||||
- parameter from: The socket where the data is read from.
|
||||
*/
|
||||
override open func didRead(data: Data, from: RawTCPSocketProtocol) {
|
||||
super.didRead(data: data, from: from)
|
||||
delegate?.didRead(data: data, from: self)
|
||||
}
|
||||
|
||||
/**
|
||||
The socket did send some data.
|
||||
|
||||
- parameter data: The data which have been sent to remote (acknowledged). Note this may not be available since the data may be released to save memory.
|
||||
- parameter by: The socket where the data is sent out.
|
||||
*/
|
||||
override open func didWrite(data: Data?, by: RawTCPSocketProtocol) {
|
||||
super.didWrite(data: data, by: by)
|
||||
delegate?.didWrite(data: data, by: self)
|
||||
}
|
||||
}
|
||||
207
GlassVPN/zhuhaow-NEKit/Socket/ProxySocket/HTTPProxySocket.swift
Executable file
207
GlassVPN/zhuhaow-NEKit/Socket/ProxySocket/HTTPProxySocket.swift
Executable file
@@ -0,0 +1,207 @@
|
||||
import Foundation
|
||||
|
||||
public class HTTPProxySocket: ProxySocket {
|
||||
enum HTTPProxyReadStatus: CustomStringConvertible {
|
||||
case invalid,
|
||||
readingFirstHeader,
|
||||
pendingFirstHeader,
|
||||
readingHeader,
|
||||
readingContent,
|
||||
stopped
|
||||
|
||||
var description: String {
|
||||
switch self {
|
||||
case .invalid:
|
||||
return "invalid"
|
||||
case .readingFirstHeader:
|
||||
return "reading first header"
|
||||
case .pendingFirstHeader:
|
||||
return "waiting to send first header"
|
||||
case .readingHeader:
|
||||
return "reading header (forwarding)"
|
||||
case .readingContent:
|
||||
return "reading content (forwarding)"
|
||||
case .stopped:
|
||||
return "stopped"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum HTTPProxyWriteStatus: CustomStringConvertible {
|
||||
case invalid,
|
||||
sendingConnectResponse,
|
||||
forwarding,
|
||||
stopped
|
||||
|
||||
var description: String {
|
||||
switch self {
|
||||
case .invalid:
|
||||
return "invalid"
|
||||
case .sendingConnectResponse:
|
||||
return "sending response header for CONNECT"
|
||||
case .forwarding:
|
||||
return "waiting to begin forwarding data"
|
||||
case .stopped:
|
||||
return "stopped"
|
||||
}
|
||||
}
|
||||
}
|
||||
/// The remote host to connect to.
|
||||
public var destinationHost: String!
|
||||
|
||||
/// The remote port to connect to.
|
||||
public var destinationPort: Int!
|
||||
|
||||
private var currentHeader: HTTPHeader!
|
||||
|
||||
private let scanner: HTTPStreamScanner = HTTPStreamScanner()
|
||||
|
||||
private var readStatus: HTTPProxyReadStatus = .invalid
|
||||
private var writeStatus: HTTPProxyWriteStatus = .invalid
|
||||
|
||||
public var isConnectCommand = false
|
||||
|
||||
public var readStatusDescription: String {
|
||||
return readStatus.description
|
||||
}
|
||||
|
||||
public var writeStatusDescription: String {
|
||||
return writeStatus.description
|
||||
}
|
||||
|
||||
/**
|
||||
Begin reading and processing data from the socket.
|
||||
*/
|
||||
override public func openSocket() {
|
||||
super.openSocket()
|
||||
|
||||
guard !isCancelled else {
|
||||
return
|
||||
}
|
||||
|
||||
readStatus = .readingFirstHeader
|
||||
socket.readDataTo(data: Utils.HTTPData.DoubleCRLF)
|
||||
}
|
||||
|
||||
override public func readData() {
|
||||
guard !isCancelled else {
|
||||
return
|
||||
}
|
||||
|
||||
// Return the first header we read when the socket was opened if the proxy command is not CONNECT.
|
||||
if readStatus == .pendingFirstHeader {
|
||||
delegate?.didRead(data: currentHeader.toData(), from: self)
|
||||
readStatus = .readingContent
|
||||
return
|
||||
}
|
||||
|
||||
switch scanner.nextAction {
|
||||
case .readContent(let length):
|
||||
readStatus = .readingContent
|
||||
if length > 0 {
|
||||
socket.readDataTo(length: length)
|
||||
} else {
|
||||
socket.readData()
|
||||
}
|
||||
case .readHeader:
|
||||
readStatus = .readingHeader
|
||||
socket.readDataTo(data: Utils.HTTPData.DoubleCRLF)
|
||||
case .stop:
|
||||
readStatus = .stopped
|
||||
disconnect()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// swiftlint:disable function_body_length
|
||||
// swiftlint:disable cyclomatic_complexity
|
||||
/**
|
||||
The socket did read some data.
|
||||
|
||||
- parameter data: The data read from the socket.
|
||||
- parameter from: The socket where the data is read from.
|
||||
*/
|
||||
override public func didRead(data: Data, from: RawTCPSocketProtocol) {
|
||||
super.didRead(data: data, from: from)
|
||||
|
||||
let result: HTTPStreamScanner.Result
|
||||
do {
|
||||
result = try scanner.input(data)
|
||||
} catch let error {
|
||||
disconnect(becauseOf: error)
|
||||
return
|
||||
}
|
||||
|
||||
switch (readStatus, result) {
|
||||
case (.readingFirstHeader, .header(let header)):
|
||||
currentHeader = header
|
||||
currentHeader.removeProxyHeader()
|
||||
currentHeader.rewriteToRelativePath()
|
||||
|
||||
destinationHost = currentHeader.host
|
||||
destinationPort = currentHeader.port
|
||||
isConnectCommand = currentHeader.isConnect
|
||||
|
||||
if !isConnectCommand {
|
||||
readStatus = .pendingFirstHeader
|
||||
} else {
|
||||
readStatus = .readingContent
|
||||
}
|
||||
|
||||
session = ConnectSession(host: destinationHost!, port: destinationPort!)
|
||||
observer?.signal(.receivedRequest(session!, on: self))
|
||||
delegate?.didReceive(session: session!, from: self)
|
||||
case (.readingHeader, .header(let header)):
|
||||
currentHeader = header
|
||||
currentHeader.removeProxyHeader()
|
||||
currentHeader.rewriteToRelativePath()
|
||||
|
||||
delegate?.didRead(data: currentHeader.toData(), from: self)
|
||||
case (.readingContent, .content(let content)):
|
||||
delegate?.didRead(data: content, from: self)
|
||||
default:
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
The socket did send some data.
|
||||
|
||||
- parameter data: The data which have been sent to remote (acknowledged). Note this may not be available since the data may be released to save memory.
|
||||
- parameter by: The socket where the data is sent out.
|
||||
*/
|
||||
override public func didWrite(data: Data?, by: RawTCPSocketProtocol) {
|
||||
super.didWrite(data: data, by: by)
|
||||
|
||||
switch writeStatus {
|
||||
case .sendingConnectResponse:
|
||||
writeStatus = .forwarding
|
||||
observer?.signal(.readyForForward(self))
|
||||
delegate?.didBecomeReadyToForwardWith(socket: self)
|
||||
default:
|
||||
delegate?.didWrite(data: data, by: self)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Response to the `AdapterSocket` on the other side of the `Tunnel` which has succefully connected to the remote server.
|
||||
|
||||
- parameter adapter: The `AdapterSocket`.
|
||||
*/
|
||||
public override func respondTo(adapter: AdapterSocket) {
|
||||
super.respondTo(adapter: adapter)
|
||||
|
||||
guard !isCancelled else {
|
||||
return
|
||||
}
|
||||
|
||||
if isConnectCommand {
|
||||
writeStatus = .sendingConnectResponse
|
||||
write(data: Utils.HTTPData.ConnectSuccessResponse)
|
||||
} else {
|
||||
writeStatus = .forwarding
|
||||
observer?.signal(.readyForForward(self))
|
||||
delegate?.didBecomeReadyToForwardWith(socket: self)
|
||||
}
|
||||
}
|
||||
}
|
||||
178
GlassVPN/zhuhaow-NEKit/Socket/ProxySocket/ProxySocket.swift
Executable file
178
GlassVPN/zhuhaow-NEKit/Socket/ProxySocket/ProxySocket.swift
Executable file
@@ -0,0 +1,178 @@
|
||||
import Foundation
|
||||
|
||||
/// The socket which encapsulates the logic to handle connection to proxies.
|
||||
open class ProxySocket: NSObject, SocketProtocol, RawTCPSocketDelegate {
|
||||
/// Received `ConnectSession`.
|
||||
public var session: ConnectSession?
|
||||
|
||||
public var observer: Observer<ProxySocketEvent>?
|
||||
|
||||
private var _cancelled = false
|
||||
var isCancelled: Bool {
|
||||
return _cancelled
|
||||
}
|
||||
|
||||
open override var description: String {
|
||||
if let session = session {
|
||||
return "<\(typeName) host:\(session.host) port: \(session.port))>"
|
||||
} else {
|
||||
return "<\(typeName)>"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Init a `ProxySocket` with a raw TCP socket.
|
||||
|
||||
- parameter socket: The raw TCP socket.
|
||||
*/
|
||||
public init(socket: RawTCPSocketProtocol, observe: Bool = true) {
|
||||
self.socket = socket
|
||||
|
||||
super.init()
|
||||
|
||||
self.socket.delegate = self
|
||||
|
||||
if observe {
|
||||
observer = ObserverFactory.currentFactory?.getObserverForProxySocket(self)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Begin reading and processing data from the socket.
|
||||
*/
|
||||
open func openSocket() {
|
||||
guard !isCancelled else {
|
||||
return
|
||||
}
|
||||
|
||||
observer?.signal(.socketOpened(self))
|
||||
}
|
||||
|
||||
/**
|
||||
Response to the `AdapterSocket` on the other side of the `Tunnel` which has succefully connected to the remote server.
|
||||
|
||||
- parameter adapter: The `AdapterSocket`.
|
||||
*/
|
||||
open func respondTo(adapter: AdapterSocket) {
|
||||
guard !isCancelled else {
|
||||
return
|
||||
}
|
||||
|
||||
observer?.signal(.askedToResponseTo(adapter, on: self))
|
||||
}
|
||||
|
||||
/**
|
||||
Read data from the socket.
|
||||
- warning: This should only be called after the last read is finished, i.e., `delegate?.didReadData()` is called.
|
||||
*/
|
||||
open func readData() {
|
||||
guard !isCancelled else {
|
||||
return
|
||||
}
|
||||
|
||||
socket.readData()
|
||||
}
|
||||
|
||||
/**
|
||||
Send data to remote.
|
||||
|
||||
- parameter data: Data to send.
|
||||
- warning: This should only be called after the last write is finished, i.e., `delegate?.didWriteData()` is called.
|
||||
*/
|
||||
open func write(data: Data) {
|
||||
guard !isCancelled else {
|
||||
return
|
||||
}
|
||||
|
||||
socket.write(data: data)
|
||||
}
|
||||
|
||||
/**
|
||||
Disconnect the socket elegantly.
|
||||
*/
|
||||
open func disconnect(becauseOf error: Error? = nil) {
|
||||
guard !isCancelled else {
|
||||
return
|
||||
}
|
||||
|
||||
_status = .disconnecting
|
||||
_cancelled = true
|
||||
session?.disconnected(becauseOf: error, by: .proxy)
|
||||
socket.disconnect()
|
||||
observer?.signal(.disconnectCalled(self))
|
||||
}
|
||||
|
||||
/**
|
||||
Disconnect the socket immediately.
|
||||
*/
|
||||
open func forceDisconnect(becauseOf error: Error? = nil) {
|
||||
guard !isCancelled else {
|
||||
return
|
||||
}
|
||||
|
||||
_status = .disconnecting
|
||||
_cancelled = true
|
||||
session?.disconnected(becauseOf: error, by: .proxy)
|
||||
socket.forceDisconnect()
|
||||
observer?.signal(.forceDisconnectCalled(self))
|
||||
}
|
||||
|
||||
// MARK: SocketProtocol Implementation
|
||||
|
||||
/// The underlying TCP socket transmitting data.
|
||||
public var socket: RawTCPSocketProtocol!
|
||||
|
||||
/// The delegate instance.
|
||||
weak public var delegate: SocketDelegate?
|
||||
|
||||
var _status: SocketStatus = .established
|
||||
/// The current connection status of the socket.
|
||||
public var status: SocketStatus {
|
||||
return _status
|
||||
}
|
||||
|
||||
// MARK: RawTCPSocketDelegate Protocol Implementation
|
||||
/**
|
||||
The socket did disconnect.
|
||||
|
||||
- parameter socket: The socket which did disconnect.
|
||||
*/
|
||||
open func didDisconnectWith(socket: RawTCPSocketProtocol) {
|
||||
_status = .closed
|
||||
observer?.signal(.disconnected(self))
|
||||
delegate?.didDisconnectWith(socket: self)
|
||||
}
|
||||
|
||||
/**
|
||||
The socket did read some data.
|
||||
|
||||
- parameter data: The data read from the socket.
|
||||
- parameter withTag: The tag given when calling the `readData` method.
|
||||
- parameter from: The socket where the data is read from.
|
||||
*/
|
||||
open func didRead(data: Data, from: RawTCPSocketProtocol) {
|
||||
observer?.signal(.readData(data, on: self))
|
||||
}
|
||||
|
||||
/**
|
||||
The socket did send some data.
|
||||
|
||||
- parameter data: The data which have been sent to remote (acknowledged). Note this may not be available since the data may be released to save memory.
|
||||
- parameter from: The socket where the data is sent out.
|
||||
*/
|
||||
open func didWrite(data: Data?, by: RawTCPSocketProtocol) {
|
||||
observer?.signal(.wroteData(data, on: self))
|
||||
}
|
||||
|
||||
/**
|
||||
The socket did connect to remote.
|
||||
|
||||
- note: This never happens for `ProxySocket`.
|
||||
|
||||
- parameter socket: The connected socket.
|
||||
*/
|
||||
open func didConnectWith(socket: RawTCPSocketProtocol) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
244
GlassVPN/zhuhaow-NEKit/Socket/ProxySocket/SOCKS5ProxySocket.swift
Executable file
244
GlassVPN/zhuhaow-NEKit/Socket/ProxySocket/SOCKS5ProxySocket.swift
Executable file
@@ -0,0 +1,244 @@
|
||||
import Foundation
|
||||
|
||||
public class SOCKS5ProxySocket: ProxySocket {
|
||||
enum SOCKS5ProxyReadStatus: CustomStringConvertible {
|
||||
case invalid,
|
||||
readingVersionIdentifierAndNumberOfMethods,
|
||||
readingMethods,
|
||||
readingConnectHeader,
|
||||
readingIPv4Address,
|
||||
readingDomainLength,
|
||||
readingDomain,
|
||||
readingIPv6Address,
|
||||
readingPort,
|
||||
forwarding,
|
||||
stopped
|
||||
|
||||
var description: String {
|
||||
switch self {
|
||||
case .invalid:
|
||||
return "invalid"
|
||||
case .readingVersionIdentifierAndNumberOfMethods:
|
||||
return "reading version and methods"
|
||||
case .readingMethods:
|
||||
return "reading methods"
|
||||
case .readingConnectHeader:
|
||||
return "reading connect header"
|
||||
case .readingIPv4Address:
|
||||
return "IPv4 address"
|
||||
case .readingDomainLength:
|
||||
return "domain length"
|
||||
case .readingDomain:
|
||||
return "domain"
|
||||
case .readingIPv6Address:
|
||||
return "IPv6 address"
|
||||
case .readingPort:
|
||||
return "reading port"
|
||||
case .forwarding:
|
||||
return "forwarding"
|
||||
case .stopped:
|
||||
return "stopped"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum SOCKS5ProxyWriteStatus: CustomStringConvertible {
|
||||
case invalid,
|
||||
sendingResponse,
|
||||
forwarding,
|
||||
stopped
|
||||
|
||||
var description: String {
|
||||
switch self {
|
||||
case .invalid:
|
||||
return "invalid"
|
||||
case .sendingResponse:
|
||||
return "sending response"
|
||||
case .forwarding:
|
||||
return "forwarding"
|
||||
case .stopped:
|
||||
return "stopped"
|
||||
}
|
||||
}
|
||||
}
|
||||
/// The remote host to connect to.
|
||||
public var destinationHost: String!
|
||||
|
||||
/// The remote port to connect to.
|
||||
public var destinationPort: Int!
|
||||
|
||||
private var readStatus: SOCKS5ProxyReadStatus = .invalid
|
||||
private var writeStatus: SOCKS5ProxyWriteStatus = .invalid
|
||||
|
||||
public var readStatusDescription: String {
|
||||
return readStatus.description
|
||||
}
|
||||
|
||||
public var writeStatusDescription: String {
|
||||
return writeStatus.description
|
||||
}
|
||||
|
||||
/**
|
||||
Begin reading and processing data from the socket.
|
||||
*/
|
||||
override public func openSocket() {
|
||||
super.openSocket()
|
||||
|
||||
guard !isCancelled else {
|
||||
return
|
||||
}
|
||||
|
||||
readStatus = .readingVersionIdentifierAndNumberOfMethods
|
||||
socket.readDataTo(length: 2)
|
||||
}
|
||||
|
||||
// swiftlint:disable function_body_length
|
||||
// swiftlint:disable cyclomatic_complexity
|
||||
/**
|
||||
The socket did read some data.
|
||||
|
||||
- parameter data: The data read from the socket.
|
||||
- parameter from: The socket where the data is read from.
|
||||
*/
|
||||
override public func didRead(data: Data, from: RawTCPSocketProtocol) {
|
||||
super.didRead(data: data, from: from)
|
||||
|
||||
switch readStatus {
|
||||
case .forwarding:
|
||||
delegate?.didRead(data: data, from: self)
|
||||
case .readingVersionIdentifierAndNumberOfMethods:
|
||||
data.withUnsafeBytes { pointer in
|
||||
let p = pointer.bindMemory(to: Int8.self)
|
||||
|
||||
guard p.baseAddress!.pointee == 5 else {
|
||||
// TODO: notify observer
|
||||
self.disconnect()
|
||||
return
|
||||
}
|
||||
|
||||
guard p.baseAddress!.successor().pointee > 0 else {
|
||||
// TODO: notify observer
|
||||
self.disconnect()
|
||||
return
|
||||
}
|
||||
|
||||
self.readStatus = .readingMethods
|
||||
self.socket.readDataTo(length: Int(p.baseAddress!.successor().pointee))
|
||||
}
|
||||
case .readingMethods:
|
||||
// TODO: check for 0x00 in read data
|
||||
|
||||
let response = Data([0x05, 0x00])
|
||||
// we would not be able to read anything before the data is written out, so no need to handle the dataWrote event.
|
||||
write(data: response)
|
||||
readStatus = .readingConnectHeader
|
||||
socket.readDataTo(length: 4)
|
||||
case .readingConnectHeader:
|
||||
data.withUnsafeBytes { pointer in
|
||||
let p = pointer.bindMemory(to: Int8.self)
|
||||
|
||||
guard p.baseAddress!.pointee == 5 && p.baseAddress!.successor().pointee == 1 else {
|
||||
// TODO: notify observer
|
||||
self.disconnect()
|
||||
return
|
||||
}
|
||||
switch p.baseAddress!.advanced(by: 3).pointee {
|
||||
case 1:
|
||||
readStatus = .readingIPv4Address
|
||||
socket.readDataTo(length: 4)
|
||||
case 3:
|
||||
readStatus = .readingDomainLength
|
||||
socket.readDataTo(length: 1)
|
||||
case 4:
|
||||
readStatus = .readingIPv6Address
|
||||
socket.readDataTo(length: 16)
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
case .readingIPv4Address:
|
||||
var address = Data(count: Int(INET_ADDRSTRLEN))
|
||||
_ = data.withUnsafeBytes { data_ptr in
|
||||
address.withUnsafeMutableBytes { addr_ptr in
|
||||
inet_ntop(AF_INET, data_ptr.baseAddress!, addr_ptr.bindMemory(to: Int8.self).baseAddress!, socklen_t(INET_ADDRSTRLEN))
|
||||
}
|
||||
}
|
||||
|
||||
destinationHost = String(data: address, encoding: .utf8)
|
||||
|
||||
readStatus = .readingPort
|
||||
socket.readDataTo(length: 2)
|
||||
case .readingIPv6Address:
|
||||
var address = Data(count: Int(INET6_ADDRSTRLEN))
|
||||
_ = data.withUnsafeBytes { data_ptr in
|
||||
address.withUnsafeMutableBytes { addr_ptr in
|
||||
inet_ntop(AF_INET6, data_ptr.baseAddress!, addr_ptr.bindMemory(to: Int8.self).baseAddress!, socklen_t(INET6_ADDRSTRLEN))
|
||||
}
|
||||
}
|
||||
|
||||
destinationHost = String(data: address, encoding: .utf8)
|
||||
|
||||
readStatus = .readingPort
|
||||
socket.readDataTo(length: 2)
|
||||
case .readingDomainLength:
|
||||
readStatus = .readingDomain
|
||||
socket.readDataTo(length: Int(data.first!))
|
||||
case .readingDomain:
|
||||
destinationHost = String(data: data, encoding: .utf8)
|
||||
readStatus = .readingPort
|
||||
socket.readDataTo(length: 2)
|
||||
case .readingPort:
|
||||
data.withUnsafeBytes {
|
||||
destinationPort = Int($0.load(as: UInt16.self).bigEndian)
|
||||
}
|
||||
|
||||
readStatus = .forwarding
|
||||
session = ConnectSession(host: destinationHost, port: destinationPort)
|
||||
observer?.signal(.receivedRequest(session!, on: self))
|
||||
delegate?.didReceive(session: session!, from: self)
|
||||
default:
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
The socket did send some data.
|
||||
|
||||
- parameter data: The data which have been sent to remote (acknowledged). Note this may not be available since the data may be released to save memory.
|
||||
- parameter from: The socket where the data is sent out.
|
||||
*/
|
||||
override public func didWrite(data: Data?, by: RawTCPSocketProtocol) {
|
||||
super.didWrite(data: data, by: by)
|
||||
|
||||
switch writeStatus {
|
||||
case .forwarding:
|
||||
delegate?.didWrite(data: data, by: self)
|
||||
case .sendingResponse:
|
||||
writeStatus = .forwarding
|
||||
observer?.signal(.readyForForward(self))
|
||||
delegate?.didBecomeReadyToForwardWith(socket: self)
|
||||
default:
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Response to the `AdapterSocket` on the other side of the `Tunnel` which has succefully connected to the remote server.
|
||||
|
||||
- parameter adapter: The `AdapterSocket`.
|
||||
*/
|
||||
override public func respondTo(adapter: AdapterSocket) {
|
||||
super.respondTo(adapter: adapter)
|
||||
|
||||
guard !isCancelled else {
|
||||
return
|
||||
}
|
||||
|
||||
var responseBytes = [UInt8](repeating: 0, count: 10)
|
||||
responseBytes[0...3] = [0x05, 0x00, 0x00, 0x01]
|
||||
let responseData = Data(responseBytes)
|
||||
|
||||
writeStatus = .sendingResponse
|
||||
write(data: responseData)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user