2019-05-30 17:10:50 -07:00
|
|
|
//
|
|
|
|
|
// ServerProtocol.swift
|
|
|
|
|
// AltServer
|
|
|
|
|
//
|
|
|
|
|
// Created by Riley Testut on 5/24/19.
|
|
|
|
|
// Copyright © 2019 Riley Testut. All rights reserved.
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
import Foundation
|
2019-11-18 14:49:17 -08:00
|
|
|
import AltSign
|
2019-05-30 17:10:50 -07:00
|
|
|
|
|
|
|
|
public let ALTServerServiceType = "_altserver._tcp"
|
|
|
|
|
|
|
|
|
|
// Can only automatically conform ALTServerError.Code to Codable, not ALTServerError itself
|
|
|
|
|
extension ALTServerError.Code: Codable {}
|
|
|
|
|
|
2019-11-18 14:49:17 -08:00
|
|
|
protocol ServerMessageProtocol: Codable
|
2019-05-30 17:10:50 -07:00
|
|
|
{
|
2019-06-21 11:20:03 -07:00
|
|
|
var version: Int { get }
|
|
|
|
|
var identifier: String { get }
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-18 14:49:17 -08:00
|
|
|
public enum ServerRequest: Decodable
|
|
|
|
|
{
|
|
|
|
|
case anisetteData(AnisetteDataRequest)
|
|
|
|
|
case prepareApp(PrepareAppRequest)
|
|
|
|
|
case beginInstallation(BeginInstallationRequest)
|
|
|
|
|
case unknown(identifier: String, version: Int)
|
|
|
|
|
|
|
|
|
|
var identifier: String {
|
|
|
|
|
switch self
|
|
|
|
|
{
|
|
|
|
|
case .anisetteData(let request): return request.identifier
|
|
|
|
|
case .prepareApp(let request): return request.identifier
|
|
|
|
|
case .beginInstallation(let request): return request.identifier
|
|
|
|
|
case .unknown(let identifier, _): return identifier
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var version: Int {
|
|
|
|
|
switch self
|
|
|
|
|
{
|
|
|
|
|
case .anisetteData(let request): return request.version
|
|
|
|
|
case .prepareApp(let request): return request.version
|
|
|
|
|
case .beginInstallation(let request): return request.version
|
|
|
|
|
case .unknown(_, let version): return version
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private enum CodingKeys: String, CodingKey
|
|
|
|
|
{
|
|
|
|
|
case identifier
|
|
|
|
|
case version
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public init(from decoder: Decoder) throws
|
|
|
|
|
{
|
|
|
|
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
|
|
|
|
|
|
|
|
|
let version = try container.decode(Int.self, forKey: .version)
|
|
|
|
|
|
|
|
|
|
let identifier = try container.decode(String.self, forKey: .identifier)
|
|
|
|
|
switch identifier
|
|
|
|
|
{
|
|
|
|
|
case "AnisetteDataRequest":
|
|
|
|
|
let request = try AnisetteDataRequest(from: decoder)
|
|
|
|
|
self = .anisetteData(request)
|
|
|
|
|
|
|
|
|
|
case "PrepareAppRequest":
|
|
|
|
|
let request = try PrepareAppRequest(from: decoder)
|
|
|
|
|
self = .prepareApp(request)
|
|
|
|
|
|
|
|
|
|
case "BeginInstallationRequest":
|
|
|
|
|
let request = try BeginInstallationRequest(from: decoder)
|
|
|
|
|
self = .beginInstallation(request)
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
self = .unknown(identifier: identifier, version: version)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public enum ServerResponse: Decodable
|
|
|
|
|
{
|
|
|
|
|
case anisetteData(AnisetteDataResponse)
|
|
|
|
|
case installationProgress(InstallationProgressResponse)
|
|
|
|
|
case error(ErrorResponse)
|
|
|
|
|
case unknown(identifier: String, version: Int)
|
|
|
|
|
|
|
|
|
|
var identifier: String {
|
|
|
|
|
switch self
|
|
|
|
|
{
|
|
|
|
|
case .anisetteData(let response): return response.identifier
|
|
|
|
|
case .installationProgress(let response): return response.identifier
|
|
|
|
|
case .error(let response): return response.identifier
|
|
|
|
|
case .unknown(let identifier, _): return identifier
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var version: Int {
|
|
|
|
|
switch self
|
|
|
|
|
{
|
|
|
|
|
case .anisetteData(let response): return response.version
|
|
|
|
|
case .installationProgress(let response): return response.version
|
|
|
|
|
case .error(let response): return response.version
|
|
|
|
|
case .unknown(_, let version): return version
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private enum CodingKeys: String, CodingKey
|
|
|
|
|
{
|
|
|
|
|
case identifier
|
|
|
|
|
case version
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public init(from decoder: Decoder) throws
|
|
|
|
|
{
|
|
|
|
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
|
|
|
|
|
|
|
|
|
let version = try container.decode(Int.self, forKey: .version)
|
|
|
|
|
|
|
|
|
|
let identifier = try container.decode(String.self, forKey: .identifier)
|
|
|
|
|
switch identifier
|
|
|
|
|
{
|
|
|
|
|
case "AnisetteDataResponse":
|
|
|
|
|
let response = try AnisetteDataResponse(from: decoder)
|
|
|
|
|
self = .anisetteData(response)
|
|
|
|
|
|
|
|
|
|
case "InstallationProgressResponse":
|
|
|
|
|
let response = try InstallationProgressResponse(from: decoder)
|
|
|
|
|
self = .installationProgress(response)
|
|
|
|
|
|
|
|
|
|
case "ErrorResponse":
|
|
|
|
|
let response = try ErrorResponse(from: decoder)
|
|
|
|
|
self = .error(response)
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
self = .unknown(identifier: identifier, version: version)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public struct AnisetteDataRequest: ServerMessageProtocol
|
|
|
|
|
{
|
|
|
|
|
public var version = 1
|
|
|
|
|
public var identifier = "AnisetteDataRequest"
|
|
|
|
|
|
|
|
|
|
public init()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public struct AnisetteDataResponse: ServerMessageProtocol
|
2019-06-21 11:20:03 -07:00
|
|
|
{
|
|
|
|
|
public var version = 1
|
2019-11-18 14:49:17 -08:00
|
|
|
public var identifier = "AnisetteDataResponse"
|
|
|
|
|
|
|
|
|
|
public var anisetteData: ALTAnisetteData
|
|
|
|
|
|
|
|
|
|
private enum CodingKeys: String, CodingKey
|
|
|
|
|
{
|
|
|
|
|
case identifier
|
|
|
|
|
case version
|
|
|
|
|
case anisetteData
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public init(anisetteData: ALTAnisetteData)
|
|
|
|
|
{
|
|
|
|
|
self.anisetteData = anisetteData
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public init(from decoder: Decoder) throws
|
|
|
|
|
{
|
|
|
|
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
|
|
|
|
self.version = try container.decode(Int.self, forKey: .version)
|
|
|
|
|
self.identifier = try container.decode(String.self, forKey: .identifier)
|
|
|
|
|
|
|
|
|
|
let json = try container.decode([String: String].self, forKey: .anisetteData)
|
|
|
|
|
|
|
|
|
|
if let anisetteData = ALTAnisetteData(json: json)
|
|
|
|
|
{
|
|
|
|
|
self.anisetteData = anisetteData
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
throw DecodingError.dataCorruptedError(forKey: CodingKeys.anisetteData, in: container, debugDescription: "Couuld not parse anisette data from JSON")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public func encode(to encoder: Encoder) throws
|
|
|
|
|
{
|
|
|
|
|
var container = encoder.container(keyedBy: CodingKeys.self)
|
|
|
|
|
try container.encode(self.version, forKey: .version)
|
|
|
|
|
try container.encode(self.identifier, forKey: .identifier)
|
|
|
|
|
|
|
|
|
|
let json = self.anisetteData.json()
|
|
|
|
|
try container.encode(json, forKey: .anisetteData)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public struct PrepareAppRequest: ServerMessageProtocol
|
|
|
|
|
{
|
|
|
|
|
public var version = 1
|
|
|
|
|
public var identifier = "PrepareAppRequest"
|
2019-06-21 11:20:03 -07:00
|
|
|
|
2019-05-30 17:10:50 -07:00
|
|
|
public var udid: String
|
|
|
|
|
public var contentSize: Int
|
|
|
|
|
|
|
|
|
|
public init(udid: String, contentSize: Int)
|
|
|
|
|
{
|
|
|
|
|
self.udid = udid
|
|
|
|
|
self.contentSize = contentSize
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-18 14:49:17 -08:00
|
|
|
public struct BeginInstallationRequest: ServerMessageProtocol
|
2019-05-30 17:10:50 -07:00
|
|
|
{
|
2019-06-21 11:20:03 -07:00
|
|
|
public var version = 1
|
2019-11-18 14:49:17 -08:00
|
|
|
public var identifier = "BeginInstallationRequest"
|
2019-06-21 11:20:03 -07:00
|
|
|
|
|
|
|
|
public init()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-18 14:49:17 -08:00
|
|
|
public struct ErrorResponse: ServerMessageProtocol
|
2019-06-21 11:20:03 -07:00
|
|
|
{
|
|
|
|
|
public var version = 1
|
2019-11-18 14:49:17 -08:00
|
|
|
public var identifier = "ErrorResponse"
|
2019-06-21 11:20:03 -07:00
|
|
|
|
2019-11-18 14:49:17 -08:00
|
|
|
public var error: ALTServerError {
|
|
|
|
|
return ALTServerError(self.errorCode)
|
|
|
|
|
}
|
|
|
|
|
private var errorCode: ALTServerError.Code
|
2019-06-10 15:03:47 -07:00
|
|
|
|
2019-11-18 14:49:17 -08:00
|
|
|
public init(error: ALTServerError)
|
|
|
|
|
{
|
|
|
|
|
self.errorCode = error.code
|
2019-05-30 17:10:50 -07:00
|
|
|
}
|
2019-11-18 14:49:17 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public struct InstallationProgressResponse: ServerMessageProtocol
|
|
|
|
|
{
|
|
|
|
|
public var version = 1
|
|
|
|
|
public var identifier = "InstallationProgressResponse"
|
|
|
|
|
|
|
|
|
|
public var progress: Double
|
2019-05-30 17:10:50 -07:00
|
|
|
|
2019-11-18 14:49:17 -08:00
|
|
|
public init(progress: Double)
|
2019-05-30 17:10:50 -07:00
|
|
|
{
|
2019-06-10 15:03:47 -07:00
|
|
|
self.progress = progress
|
2019-05-30 17:10:50 -07:00
|
|
|
}
|
|
|
|
|
}
|