Network debugging
This commit is contained in:
parent
268566c165
commit
7da0368758
|
@ -7,13 +7,16 @@
|
||||||
|
|
||||||
import Cocoa
|
import Cocoa
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
import GeminiProtocol
|
||||||
|
|
||||||
@NSApplicationMain
|
@NSApplicationMain
|
||||||
class AppDelegate: NSObject, NSApplicationDelegate {
|
class AppDelegate: NSObject, NSApplicationDelegate {
|
||||||
|
|
||||||
var window: NSWindow!
|
var window: NSWindow!
|
||||||
|
|
||||||
|
var connection: GeminiConnection!
|
||||||
|
let url = URL(string: "gemini://localhost:1965/overview.gmi")!
|
||||||
|
|
||||||
func applicationDidFinishLaunching(_ aNotification: Notification) {
|
func applicationDidFinishLaunching(_ aNotification: Notification) {
|
||||||
// Create the SwiftUI view that provides the window contents.
|
// Create the SwiftUI view that provides the window contents.
|
||||||
let contentView = ContentView()
|
let contentView = ContentView()
|
||||||
|
@ -29,12 +32,38 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
||||||
window.contentView = NSHostingView(rootView: contentView)
|
window.contentView = NSHostingView(rootView: contentView)
|
||||||
window.title = "Gemini"
|
window.title = "Gemini"
|
||||||
window.makeKeyAndOrderFront(nil)
|
window.makeKeyAndOrderFront(nil)
|
||||||
|
|
||||||
|
connection = GeminiConnection(endpoint: .url(url), delegate: self)
|
||||||
}
|
}
|
||||||
|
|
||||||
func applicationWillTerminate(_ aNotification: Notification) {
|
func applicationWillTerminate(_ aNotification: Notification) {
|
||||||
// Insert code here to tear down your application
|
// Insert code here to tear down your application
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var alreadyReceived = false
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension AppDelegate: GeminiConnectionDelegate {
|
||||||
|
func connectionReady(_ connection: GeminiConnection) {
|
||||||
|
print("!! Ready")
|
||||||
|
let req = try! GeminiRequest(url: url)
|
||||||
|
connection.sendRequest(req)
|
||||||
|
}
|
||||||
|
|
||||||
|
func connection(_ connection: GeminiConnection, receivedData data: Data?, header: GeminiResponseHeader) {
|
||||||
|
if !alreadyReceived {
|
||||||
|
alreadyReceived = true
|
||||||
|
print("!! Status: \(header.status)")
|
||||||
|
print("!! Meta: '\(header.meta)'")
|
||||||
|
}
|
||||||
|
if let data = data {
|
||||||
|
print(String(data: data, encoding: .utf8)!)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func connectionCompleted(_ connection: GeminiConnection) {
|
||||||
|
print("!! completed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,9 +2,11 @@
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
<key>com.apple.security.app-sandbox</key>
|
<key>com.apple.security.app-sandbox</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>com.apple.security.files.user-selected.read-only</key>
|
<key>com.apple.security.files.user-selected.read-only</key>
|
||||||
<true/>
|
<true/>
|
||||||
|
<key>com.apple.security.network.client</key>
|
||||||
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|
|
@ -8,19 +8,19 @@
|
||||||
import Foundation
|
import Foundation
|
||||||
import Network
|
import Network
|
||||||
|
|
||||||
protocol GeminiConnectionDelegate: class {
|
public protocol GeminiConnectionDelegate: class {
|
||||||
func connectionReady(_ connection: GeminiConnection)
|
func connectionReady(_ connection: GeminiConnection)
|
||||||
func connection(_ connection: GeminiConnection, receivedData data: Data?, header: GeminiResponseHeader)
|
func connection(_ connection: GeminiConnection, receivedData data: Data?, header: GeminiResponseHeader)
|
||||||
func connectionCompleted(_ connection: GeminiConnection)
|
func connectionCompleted(_ connection: GeminiConnection)
|
||||||
}
|
}
|
||||||
|
|
||||||
class GeminiConnection {
|
public class GeminiConnection {
|
||||||
|
|
||||||
weak var delegate: GeminiConnectionDelegate?
|
public weak var delegate: GeminiConnectionDelegate?
|
||||||
|
|
||||||
private var connection: NWConnection?
|
private var connection: NWConnection?
|
||||||
|
|
||||||
init(endpoint: NWEndpoint, delegate: GeminiConnectionDelegate? = nil) {
|
public init(endpoint: NWEndpoint, delegate: GeminiConnectionDelegate? = nil) {
|
||||||
self.connection = NWConnection(to: endpoint, using: .gemini)
|
self.connection = NWConnection(to: endpoint, using: .gemini)
|
||||||
self.delegate = delegate
|
self.delegate = delegate
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ class GeminiConnection {
|
||||||
|
|
||||||
var report: NWConnection.PendingDataTransferReport!
|
var report: NWConnection.PendingDataTransferReport!
|
||||||
|
|
||||||
func sendRequest(_ request: GeminiRequest) {
|
public func sendRequest(_ request: GeminiRequest) {
|
||||||
guard let connection = connection else { return }
|
guard let connection = connection else { return }
|
||||||
|
|
||||||
let message = NWProtocolFramer.Message(geminiRequest: request)
|
let message = NWProtocolFramer.Message(geminiRequest: request)
|
||||||
|
|
|
@ -7,10 +7,10 @@
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
struct GeminiRequest {
|
public struct GeminiRequest {
|
||||||
let url: URL
|
public let url: URL
|
||||||
|
|
||||||
init(url: URL) throws {
|
public init(url: URL) throws {
|
||||||
if url.absoluteString.count > 1024 {
|
if url.absoluteString.count > 1024 {
|
||||||
throw Error.urlTooLong
|
throw Error.urlTooLong
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ struct GeminiRequest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension GeminiRequest {
|
public extension GeminiRequest {
|
||||||
enum Error: Swift.Error {
|
enum Error: Swift.Error {
|
||||||
case urlTooLong
|
case urlTooLong
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,11 +8,14 @@
|
||||||
import Foundation
|
import Foundation
|
||||||
import UniformTypeIdentifiers
|
import UniformTypeIdentifiers
|
||||||
|
|
||||||
struct GeminiResponse {
|
public struct GeminiResponse {
|
||||||
let status: StatusCode
|
public let status: StatusCode
|
||||||
let meta: String
|
public let meta: String
|
||||||
let body: Data?
|
public let body: Data?
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public extension GeminiResponse {
|
||||||
// Helpers
|
// Helpers
|
||||||
var rawMimeType: String? {
|
var rawMimeType: String? {
|
||||||
guard status.isSuccess else { return nil }
|
guard status.isSuccess else { return nil }
|
||||||
|
@ -53,7 +56,7 @@ struct GeminiResponse {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension GeminiResponse {
|
public extension GeminiResponse {
|
||||||
enum StatusCode: Int {
|
enum StatusCode: Int {
|
||||||
// All statuses and subtypes
|
// All statuses and subtypes
|
||||||
case input = 10
|
case input = 10
|
||||||
|
@ -89,7 +92,7 @@ extension GeminiResponse {
|
||||||
}
|
}
|
||||||
|
|
||||||
extension GeminiResponse.StatusCode: CustomStringConvertible {
|
extension GeminiResponse.StatusCode: CustomStringConvertible {
|
||||||
var description: String {
|
public var description: String {
|
||||||
switch self {
|
switch self {
|
||||||
case .input:
|
case .input:
|
||||||
return "input"
|
return "input"
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
struct GeminiResponseHeader {
|
public struct GeminiResponseHeader {
|
||||||
let status: GeminiResponse.StatusCode
|
public let status: GeminiResponse.StatusCode
|
||||||
let meta: String
|
public let meta: String
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue