98 lines
2.2 KiB
Swift
98 lines
2.2 KiB
Swift
//
|
|
// Logger.swift
|
|
// PacketTunnel
|
|
//
|
|
// Created by Jerry Bool on 2022/12/6.
|
|
//
|
|
|
|
import Foundation
|
|
|
|
class Logger {
|
|
|
|
static let ENABLE_LOGGING = true
|
|
|
|
static var vpnLogFile: URL? = {
|
|
FileManager.default.vpnLogFile?.truncate()
|
|
}()
|
|
|
|
static func log(_ message: String, to: URL?) {
|
|
guard ENABLE_LOGGING,
|
|
let url = to,
|
|
let data = message.trimmingCharacters(in: .whitespacesAndNewlines).appending("\n").data(using: .utf8),
|
|
let fh = try? FileHandle(forUpdating: url)
|
|
else {
|
|
return
|
|
}
|
|
|
|
defer {
|
|
fh.closeFile()
|
|
}
|
|
|
|
fh.seekToEndOfFile()
|
|
fh.write(data)
|
|
}
|
|
|
|
private static var logFsObject: DispatchSourceFileSystemObject? {
|
|
didSet {
|
|
oldValue?.cancel()
|
|
}
|
|
}
|
|
|
|
private static var logText = ""
|
|
|
|
static func tailFile(_ url: URL?, _ update: ((_ logText: String) -> Void)? = nil) {
|
|
|
|
// Stop and remove the previous watched content.
|
|
// (Will implicitely call #stop through `didSet` hook!)
|
|
logFsObject = nil
|
|
|
|
guard let url = url,
|
|
let fh = try? FileHandle(forReadingFrom: url)
|
|
else {
|
|
return
|
|
}
|
|
|
|
let ui = {
|
|
let data = fh.readDataToEndOfFile()
|
|
|
|
if let content = String(data: data, encoding: .utf8) {
|
|
logText.append(content)
|
|
|
|
update?(logText)
|
|
}
|
|
}
|
|
|
|
logText = ""
|
|
ui()
|
|
|
|
logFsObject = DispatchSource.makeFileSystemObjectSource(
|
|
fileDescriptor: fh.fileDescriptor,
|
|
eventMask: [.extend, .delete, .link],
|
|
queue: .main)
|
|
|
|
logFsObject?.setEventHandler {
|
|
guard let data = logFsObject?.data else {
|
|
return
|
|
}
|
|
|
|
if data.contains(.delete) || data.contains(.link) {
|
|
DispatchQueue.main.async {
|
|
tailFile(url, update)
|
|
}
|
|
}
|
|
|
|
if data.contains(.extend) {
|
|
ui()
|
|
}
|
|
}
|
|
|
|
logFsObject?.setCancelHandler {
|
|
try? fh.close()
|
|
|
|
logText = ""
|
|
}
|
|
|
|
logFsObject?.resume()
|
|
}
|
|
}
|