Network debugging

This commit is contained in:
Shadowfacts 2020-07-13 18:22:36 -04:00
parent 268566c165
commit 7da0368758
Signed by: shadowfacts
GPG Key ID: 94A5AB95422746E5
6 changed files with 57 additions and 23 deletions

View File

@ -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")
}
}

View File

@ -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>

View File

@ -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)

View File

@ -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
} }

View File

@ -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"

View File

@ -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
} }