0

everyone,

using the Swiftyping library, I perform a ping test n times on an ip address that I give to the function via a Post call.

 routes.post("ping") { req async throws -> PingTestResult in
        
        var testResult = PingTestResult(latency: [], Date: "", packetsTrasmitted: 0, packetsReceived: 0, packetLoss: 0.0, rtMin: "", rtMax: "", rtAvg: "", rtStdDev: "")
        
        let pingConfig = try req.content.decode(PingConfig.self)
        
        print("\nhostname: \(pingConfig.host!), to be ping: \(pingConfig.n!)\n")
        
        testResult = await ping.waitForDataFromPing(hostname: pingConfig.host!, n: pingConfig.n!)
        
        return testResult
    }

Here the function to make the ping test:

func startPinging(hostname: String, n: Int) async throws  {
            
    do{
        ping = try SwiftyPing(host: hostname, configuration: PingConfiguration(interval: 1.0,with: 1), queue: DispatchQueue.global())
        ping?.targetCount = n
           
        ping?.observer = { response in
            DispatchQueue.main.async {

                
                var latency = String(format: "%.3f ms", response.duration * 1000)
                
                if let error = response.error {
                    if error == .requestTimeout{
                        latency = "Timeout \(latency)"
                    } else{
                        print(error)
                        latency = error.localizedDescription
                    }
                }
                let message = "\nPing Test #\(response.trueSequenceNumber): \(latency)\n"
               
                
                self.latArray.append(latency)
                
                print(message)
                
            }
            
        }
         
        ping?.finished = {(result) in
            DispatchQueue.main.async {
                
                let dateformatter = DateFormatter()
                dateformatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
                dateformatter.timeZone = TimeZone.current
                
                let date = dateformatter.string(from: self.currentdate)
                
                let rtMin = String(format: "%.3f ms", result.roundtrip!.minimum * 1000)
                
                let rtMax = String(format: "%.3f ms", result.roundtrip!.maximum * 1000)
                
                let rtAvg = String(format: "%.3f ms", result.roundtrip!.average * 1000)
                
                let rtStdDev = String(format: "%.3f ms", result.roundtrip!.standardDeviation * 1000)
                
                var message = "\n--- \(hostname) ping statistics ---\n"
                message += "\nTest Date: \(date)\n"
                message += "\nTest Performed: \(n)\n"
                message += "\nPackets Trasmitted: \(result.packetsTransmitted)\n"
                message += "\nPackets Received: \(result.packetsReceived)\n"
                if let loss = result.packetLoss{
                    message += String(format: "\nPacket Loss: %.1f%% \n", loss * 100)
                } else {
                    message += "\n"
                }
           
                
                if result.roundtrip != nil {
                    message += "\nRound-trip Min: \(rtMin)"
                    message += "\nRound-trip Min: \(rtMax)"
                    message += "\nRound-trip Min: \(rtAvg)"
                    message += "\nRound-trip Min: \(rtStdDev)"
                }
            
    
            print(message)

            self.pingResult = PingTestResult(latency: self.latArray, Date: date, packetsTrasmitted: result.packetsTransmitted, packetsReceived: result.packetsReceived, packetLoss: result.packetLoss! * 100, rtMin: rtMin, rtMax: rtMax, rtAvg: rtAvg, rtStdDev: rtStdDev)
                
            }   
        }
        
        try self.ping?.startPinging()
        
        
    } catch {
        print("Pinging \(hostname) not possibile. Error: \(error.localizedDescription)")
    }

}

    func waitForDataFromPing(hostname: String, n: Int) async -> PingTestResult {
    try? await self.startPinging(hostname: hostname, n: n)
    return self.pingResult
}

the problem I am experiencing is that when the ping test ends, I cannot return the test data. Is there any way by which the result values can be returned from the DispatchQueue?

enter image description here

Chip Jarred
  • 2,600
  • 7
  • 12
MichaelG
  • 9
  • 2
  • Use escaping closure to get your desired result. Here is the link https://stackoverflow.com/questions/39504180/escaping-closures-in-swift – Muhammad Salman Oct 24 '22 at 11:04
  • 3
    You can’t. You should move completely from GCD to Swift Concurrency using `Task`s, `Actor`s and `Continuation`s – vadian Oct 24 '22 at 11:25
  • I mostly agree with @vadian, but if for some reason you need (or really want) to stick to GCD, and want to return a value from the `async` call instead of continuing your code that uses it in the closure, you'll need some kind of Promise/Future. There are several out there, and I have my own ([Async](https://github.com/chipjarred/Async)). I like mine because in addition to a completion-handler style, it allows storing away the future as a place holder value, similar to C++'s `std::future`, which I find useful for certain situations, but I use it less since Swift added `async`/`await`. – Chip Jarred Oct 24 '22 at 12:25
  • thanks for the tips, the use of continuations solved my problem – MichaelG Nov 02 '22 at 09:39

0 Answers0