Files
proxypin/ios/ProxyPin/vpn/ConnectionManager.swift
2025-05-31 06:54:44 +08:00

127 lines
4.8 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//
// ConnectionManager.swift
// ProxyPin
//
// Created by wanghongen on 2024/9/16.
//
import Foundation
import Network
import os.log
//VPN
class ConnectionManager : CloseableConnection{
//static let instance = ConnectionManager()
private var table: [String: Connection] = [:]
public var proxyAddress: NWEndpoint?
private let defaultPorts: [UInt16] = [80, 443, 8080, 8088, 8888, 9000]
func getConnection(nwProtocol: NWProtocol, ip: UInt32, port: UInt16, srcIp: UInt32, srcPort: UInt16) -> Connection? {
let key = Connection.getConnectionKey(nwProtocol: nwProtocol, destIp: ip, destPort: port, sourceIp: srcIp, sourcePort: srcPort)
return getConnectionByKey(key: key)
}
func getConnectionByKey(key: String) -> Connection? {
return table[key]
}
func createTCPConnection(ip: UInt32, port: UInt16, srcIp: UInt32, srcPort: UInt16) -> Connection {
let key = Connection.getConnectionKey(nwProtocol: .TCP, destIp: ip, destPort: port, sourceIp: srcIp, sourcePort: srcPort)
if let existingConnection = table[key] {
return existingConnection
}
let connection = Connection(nwProtocol: .TCP, sourceIp: srcIp, sourcePort: srcPort, destinationIp: ip, destinationPort: port, connectionCloser: self)
let ipString = PacketUtil.intToIPAddress(ip)
let endpoint: NWEndpoint
if (proxyAddress == nil || !defaultPorts.contains(port) || isPrivateIP(ipString)) {
endpoint = NWEndpoint.hostPort(host: NWEndpoint.Host(ipString), port: NWEndpoint.Port(rawValue: port)!)
// 使 TCP
let parameters = NWParameters.tcp
let nwConnection = NWConnection(to: endpoint, using: parameters)
connection.channel = nwConnection
connection.isInitConnect = true
}
self.table[key] = connection
os_log("Created TCP connection %{public}@", log: OSLog.default, type: .default, key)
return connection
}
private func isPrivateIP(_ ip: String) -> Bool {
return ip.hasPrefix("10.") ||
ip.hasPrefix("172.") && (16...31).contains(Int(ip.split(separator: ".")[1]) ?? -1) ||
ip.hasPrefix("192.168.")
}
func createUDPConnection(ip: UInt32, port: UInt16, srcIp: UInt32, srcPort: UInt16) -> Connection {
let key = Connection.getConnectionKey(nwProtocol: .UDP, destIp: ip, destPort: port, sourceIp: srcIp, sourcePort: srcPort)
if let existingConnection = table[key] {
return existingConnection
}
let connection = Connection(nwProtocol: .UDP, sourceIp: srcIp, sourcePort: srcPort, destinationIp: ip, destinationPort: port, connectionCloser: self)
let endpoint = NWEndpoint.hostPort(host: NWEndpoint.Host((PacketUtil.intToIPAddress(ip))), port: NWEndpoint.Port(rawValue: port)!)
let nwConnection = NWConnection(to: endpoint, using: .udp)
connection.channel = nwConnection
os_log("Created UDP connection %{public}@", log: OSLog.default, type: .default, key)
self.table[key] = connection
return connection
}
func closeConnection(connection: Connection) {
closeConnection(
nwProtocol: connection.nwProtocol, ip: connection.destinationIp, port: connection.destinationPort,
srcIp: connection.sourceIp, srcPort: connection.sourcePort
)
}
//
func closeConnection(nwProtocol: NWProtocol, ip: UInt32, port: UInt16, srcIp: UInt32, srcPort: UInt16) {
let key = Connection.getConnectionKey(nwProtocol: nwProtocol, destIp: ip, destPort: port, sourceIp: srcIp, sourcePort: srcPort)
if let connection = self.table.removeValue(forKey: key) {
if connection.channel?.state != .cancelled {
connection.channel?.cancel()
os_log("Closed connection %{public}@", log: OSLog.default, type: .debug, key)
} else {
os_log("Connection %{public}@ is already cancelled", log: OSLog.default, type: .debug, key)
}
}
}
//PSH
func addClientData(data: Data, connection: Connection) {
guard data.count > 0 else {
return
}
connection.addSendData(data: data)
}
func keepSessionAlive(connection: Connection) {
let key = Connection.getConnectionKey(
nwProtocol: connection.nwProtocol,
destIp: connection.destinationIp,
destPort: connection.destinationPort,
sourceIp: connection.sourceIp,
sourcePort: connection.sourcePort
)
self.table[key] = connection
}
}