From 8eeca981d984b6f840be06590bdc82592b1dacd8 Mon Sep 17 00:00:00 2001 From: neon443 <69979447+neon443@users.noreply.github.com> Date: Thu, 26 Feb 2026 22:34:32 +0000 Subject: [PATCH] added client and server, can send text messages :yay: (maybe we can have chat :sob:) fix client being server --- Scream.xcodeproj/project.pbxproj | 12 ++++-- Scream/AppDelegate.swift | 4 +- Scream/UDPClient.swift | 62 ++++++++++++++++++++++++++ Scream/UDPServer.swift | 74 ++++++++++++++++---------------- 4 files changed, 109 insertions(+), 43 deletions(-) create mode 100644 Scream/UDPClient.swift diff --git a/Scream.xcodeproj/project.pbxproj b/Scream.xcodeproj/project.pbxproj index 68d4d27..a2a1726 100644 --- a/Scream.xcodeproj/project.pbxproj +++ b/Scream.xcodeproj/project.pbxproj @@ -7,8 +7,9 @@ objects = { /* Begin PBXBuildFile section */ + A909CC142F50FFDA00D98D39 /* UDPServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = A909CC132F50FFDA00D98D39 /* UDPServer.swift */; }; A94E29F72F09B569006E583D /* ScreamPacket.swift in Sources */ = {isa = PBXBuildFile; fileRef = A94E29F62F09B569006E583D /* ScreamPacket.swift */; }; - A98010132F50D19D00A58EF7 /* UDPServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = A98010122F50D19D00A58EF7 /* UDPServer.swift */; }; + A98010132F50D19D00A58EF7 /* UDPClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = A98010122F50D19D00A58EF7 /* UDPClient.swift */; }; A98010152F50D9B100A58EF7 /* CaptureVideoPreview.swift in Sources */ = {isa = PBXBuildFile; fileRef = A98010142F50D9B100A58EF7 /* CaptureVideoPreview.swift */; }; A98E8BF02F05B2A0006D4458 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A98E8BEB2F05B2A0006D4458 /* AppDelegate.swift */; }; A98E8BF12F05B2A0006D4458 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A98E8BEC2F05B2A0006D4458 /* Assets.xcassets */; }; @@ -39,8 +40,9 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + A909CC132F50FFDA00D98D39 /* UDPServer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UDPServer.swift; sourceTree = ""; }; A94E29F62F09B569006E583D /* ScreamPacket.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScreamPacket.swift; sourceTree = ""; }; - A98010122F50D19D00A58EF7 /* UDPServer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UDPServer.swift; sourceTree = ""; }; + A98010122F50D19D00A58EF7 /* UDPClient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UDPClient.swift; sourceTree = ""; }; A98010142F50D9B100A58EF7 /* CaptureVideoPreview.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CaptureVideoPreview.swift; sourceTree = ""; }; A98E8BC02F05B26B006D4458 /* Scream.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Scream.app; sourceTree = BUILT_PRODUCTS_DIR; }; A98E8BCE2F05B26D006D4458 /* ScreamTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ScreamTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -127,7 +129,8 @@ children = ( A98E8BEB2F05B2A0006D4458 /* AppDelegate.swift */, A98E8BFC2F05D28D006D4458 /* ScreenRecorder.swift */, - A98010122F50D19D00A58EF7 /* UDPServer.swift */, + A98010122F50D19D00A58EF7 /* UDPClient.swift */, + A909CC132F50FFDA00D98D39 /* UDPServer.swift */, A9D7225E2F070FE600050BB0 /* CaptureEngine.swift */, A94E29F62F09B569006E583D /* ScreamPacket.swift */, A98010162F50DD4600A58EF7 /* Views */, @@ -290,11 +293,12 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + A909CC142F50FFDA00D98D39 /* UDPServer.swift in Sources */, A94E29F72F09B569006E583D /* ScreamPacket.swift in Sources */, A98E8BF02F05B2A0006D4458 /* AppDelegate.swift in Sources */, A9D7225F2F070FE600050BB0 /* CaptureEngine.swift in Sources */, A98E8BFD2F05D28D006D4458 /* ScreenRecorder.swift in Sources */, - A98010132F50D19D00A58EF7 /* UDPServer.swift in Sources */, + A98010132F50D19D00A58EF7 /* UDPClient.swift in Sources */, A98010152F50D9B100A58EF7 /* CaptureVideoPreview.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Scream/AppDelegate.swift b/Scream/AppDelegate.swift index e294d33..e6aab3c 100644 --- a/Scream/AppDelegate.swift +++ b/Scream/AppDelegate.swift @@ -10,7 +10,8 @@ import Cocoa @main class AppDelegate: NSObject, NSApplicationDelegate { let sr = ScreenRecorder() - let udpserver = UDPServerImplementation(port: 03067) + let udpclient = UDPClientImplementation(port: 03067) + let udpserver = UDPServerImplementation(host: "localhost", port: 03067, initialMessage: "kys") @IBOutlet var window: NSWindow! @@ -20,6 +21,7 @@ class AppDelegate: NSObject, NSApplicationDelegate { } } @IBAction func Button2(_ sender: Any) { + udpclient.start() udpserver.start() } diff --git a/Scream/UDPClient.swift b/Scream/UDPClient.swift new file mode 100644 index 0000000..5714e00 --- /dev/null +++ b/Scream/UDPClient.swift @@ -0,0 +1,62 @@ +// +// UDPClient.swift +// Scream +// +// Created by neon443 on 26/02/2026. +// + +import Foundation +import Network + +final class UDPClientImplementation: Sendable { + private let connectionListener: NWListener + + //init a udp client at x port + init(port: UInt16) { + connectionListener = try! NWListener( + using: .udp, + on: NWEndpoint.Port(integerLiteral: port) + ) + + connectionListener.newConnectionHandler = { [weak self] connection in + connection.start(queue: .global()) + self?.receive(on: connection) + } + + connectionListener.stateUpdateHandler = { state in + print("state: \(state)") + } + } +} + +protocol UDPClient { + func start() + func stop() +} + +extension UDPClientImplementation: UDPClient { + func start() { + connectionListener.start(queue: .global()) + print("client started") + } + + func stop() { + connectionListener.cancel() + print("client stoped") + } +} + +private extension UDPClientImplementation { + func receive(on connection: NWConnection) { + connection.receiveMessage { data, contentContext, isComplete, error in + if let error { + print("error \(error)") + } + + if let data, + let message = String(data: data, encoding: .utf8) { + print(message) + } + } + } +} diff --git a/Scream/UDPServer.swift b/Scream/UDPServer.swift index cede375..45e5693 100644 --- a/Scream/UDPServer.swift +++ b/Scream/UDPServer.swift @@ -8,55 +8,53 @@ import Foundation import Network -final class UDPServerImplementation: Sendable { - private let connectionListener: NWListener - - //init a udp server at x port - init(port: UInt16) { - connectionListener = try! NWListener( - using: .udp, - on: NWEndpoint.Port(integerLiteral: port) - ) - - connectionListener.newConnectionHandler = { [weak self] connection in - connection.start(queue: .global()) - self?.receive(on: connection) - } - - connectionListener.stateUpdateHandler = { state in - print("state: \(state)") - } - } -} - protocol UDPServer { func start() func stop() + func send(message: String) +} + +final class UDPServerImplementation: Sendable { + private let connection: NWConnection + + init(host: String, port: UInt16, initialMessage: String) { + connection = NWConnection( + host: NWEndpoint.Host(host), + port: NWEndpoint.Port(integerLiteral: port), + using: .udp + ) + connection.stateUpdateHandler = { [weak self] state in + print("server state is \(state)") + if state == .ready { + self?.send(message: initialMessage) + } + } + } } extension UDPServerImplementation: UDPServer { func start() { - connectionListener.start(queue: .global()) - print("server started") + connection.start(queue: .global()) + print("server startedf") } func stop() { - connectionListener.cancel() - print("server stoped") + connection.cancel() + print("server stopped") } -} - -private extension UDPServerImplementation { - func receive(on connection: NWConnection) { - connection.receiveMessage { data, contentContext, isComplete, error in - if let error { - print("error \(error)") - } - - if let data, - let message = String(data: data, encoding: .utf8) { - print(message) - } + + func send(message: String) { + guard let data = message.data(using: .utf8) else { + print("server: encode message failed") + return } + + connection.send(content: data, completion: .contentProcessed({ error in + if let error { + print("server: failed to send \(error)") + } else { + print("server: message sent") + } + })) } }