mirror of
https://github.com/SoftEtherVPN/SoftEtherVPN.git
synced 2026-03-09 17:59:19 +03:00
184 lines
6.9 KiB
Swift
184 lines
6.9 KiB
Swift
import Foundation
|
|
import Network
|
|
import Security
|
|
import CryptoKit
|
|
|
|
/// SoftEtherProtocol manages the communication between iOS client and SoftEther VPN server
|
|
class SoftEtherProtocol {
|
|
|
|
// MARK: - Properties
|
|
|
|
private var secureConnection: SecureConnection?
|
|
private var isConnected = false
|
|
private var host: String = ""
|
|
private var port: UInt16 = 443
|
|
private var nextPacketId: UInt32 = 1
|
|
|
|
// MARK: - Public Methods
|
|
|
|
/// Connect to a SoftEther VPN server
|
|
/// - Parameters:
|
|
/// - host: The server hostname or IP address
|
|
/// - port: The server port (default: 443)
|
|
/// - completion: Callback with connection result
|
|
public func connect(to host: String, port: UInt16 = 443, completion: @escaping (Bool, Error?) -> Void) {
|
|
self.host = host
|
|
self.port = port
|
|
|
|
// Create a secure connection
|
|
secureConnection = SecureConnection(host: host, port: port)
|
|
|
|
// Connect using TLS
|
|
secureConnection?.connect { [weak self] success, error in
|
|
guard let self = self, success else {
|
|
completion(false, error ?? NSError(domain: "SoftEtherError", code: 1, userInfo: [NSLocalizedDescriptionKey: "TLS connection failed"]))
|
|
return
|
|
}
|
|
|
|
// After successful TLS connection, send the client signature
|
|
self.sendClientSignature { success, error in
|
|
if success {
|
|
self.isConnected = true
|
|
}
|
|
completion(success, error)
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Disconnect from the server
|
|
public func disconnect() {
|
|
secureConnection?.disconnect()
|
|
isConnected = false
|
|
}
|
|
|
|
// MARK: - Private Methods
|
|
|
|
/// Send the SoftEther client signature to identify as a legitimate client
|
|
/// - Parameter completion: Callback with result
|
|
private func sendClientSignature(completion: @escaping (Bool, Error?) -> Void) {
|
|
// Generate client signature using our specialized class
|
|
let signatureData = SoftEtherClientSignature.generateSignature()
|
|
|
|
// Create a packet with the signature data
|
|
let packetId = self.nextPacketId
|
|
self.nextPacketId += 1
|
|
|
|
let packet = SoftEtherPacket(type: 0x01, id: packetId, data: signatureData)
|
|
let packetData = packet.serialize()
|
|
|
|
print("Sending client signature packet: \(packetData.count) bytes")
|
|
|
|
// Send the packet
|
|
secureConnection?.send(data: packetData) { [weak self] error in
|
|
guard let self = self else { return }
|
|
|
|
if let error = error {
|
|
print("Error sending client signature: \(error)")
|
|
completion(false, error)
|
|
return
|
|
}
|
|
|
|
// After sending signature, wait for server response
|
|
self.receiveServerResponse { success, error in
|
|
completion(success, error)
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Receive and process server response after sending signature
|
|
/// - Parameter completion: Callback with result
|
|
private func receiveServerResponse(completion: @escaping (Bool, Error?) -> Void) {
|
|
secureConnection?.receive { data, error in
|
|
if let error = error {
|
|
print("Error receiving server response: \(error)")
|
|
completion(false, error)
|
|
return
|
|
}
|
|
|
|
guard let data = data, data.count > 4 else {
|
|
let error = NSError(domain: "SoftEtherError", code: 2, userInfo: [NSLocalizedDescriptionKey: "Invalid server response"])
|
|
print("Invalid server response: insufficient data")
|
|
completion(false, error)
|
|
return
|
|
}
|
|
|
|
print("Received server response: \(data.count) bytes")
|
|
|
|
// Parse the response packet
|
|
guard let packet = SoftEtherPacket(fromData: data) else {
|
|
let error = NSError(domain: "SoftEtherError", code: 3, userInfo: [NSLocalizedDescriptionKey: "Invalid packet format"])
|
|
print("Could not parse server response packet")
|
|
completion(false, error)
|
|
return
|
|
}
|
|
|
|
// Verify the response
|
|
let packetData = packet.getData()
|
|
let isValid = SoftEtherClientSignature.verifyServerResponse(packetData)
|
|
|
|
if isValid {
|
|
print("Server accepted our client signature")
|
|
completion(true, nil)
|
|
} else {
|
|
print("Server rejected our client signature")
|
|
let error = NSError(domain: "SoftEtherError", code: 4, userInfo: [NSLocalizedDescriptionKey: "Server rejected client signature"])
|
|
completion(false, error)
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Send a data packet to the server
|
|
/// - Parameters:
|
|
/// - data: Data to send
|
|
/// - completion: Callback with result
|
|
func sendData(data: Data, completion: @escaping (Bool, Error?) -> Void) {
|
|
guard isConnected else {
|
|
completion(false, NSError(domain: "SoftEtherError", code: 5, userInfo: [NSLocalizedDescriptionKey: "Not connected to server"]))
|
|
return
|
|
}
|
|
|
|
let packetId = self.nextPacketId
|
|
self.nextPacketId += 1
|
|
|
|
let packet = SoftEtherPacket(type: 0x05, id: packetId, data: data)
|
|
let packetData = packet.serialize()
|
|
|
|
secureConnection?.send(data: packetData) { error in
|
|
if let error = error {
|
|
completion(false, error)
|
|
return
|
|
}
|
|
|
|
completion(true, nil)
|
|
}
|
|
}
|
|
|
|
/// Receive data from the server
|
|
/// - Parameter completion: Callback with received data and result
|
|
func receiveData(completion: @escaping (Data?, Bool, Error?) -> Void) {
|
|
guard isConnected else {
|
|
completion(nil, false, NSError(domain: "SoftEtherError", code: 5, userInfo: [NSLocalizedDescriptionKey: "Not connected to server"]))
|
|
return
|
|
}
|
|
|
|
secureConnection?.receive { data, error in
|
|
if let error = error {
|
|
completion(nil, false, error)
|
|
return
|
|
}
|
|
|
|
guard let data = data, data.count > 4 else {
|
|
completion(nil, false, NSError(domain: "SoftEtherError", code: 2, userInfo: [NSLocalizedDescriptionKey: "Invalid server response"]))
|
|
return
|
|
}
|
|
|
|
// Parse the packet
|
|
guard let packet = SoftEtherPacket(fromData: data) else {
|
|
completion(nil, false, NSError(domain: "SoftEtherError", code: 3, userInfo: [NSLocalizedDescriptionKey: "Invalid packet format"]))
|
|
return
|
|
}
|
|
|
|
completion(packet.getData(), true, nil)
|
|
}
|
|
}
|
|
} |