// // Copyright (c) ZeroC, Inc. All rights reserved. // import Dispatch import Foundation import Ice import TestCommon class PingReplyI: PingReply { var _replies: Int32 = 0 var _lock = os_unfair_lock() var _semaphore = DispatchSemaphore(value: 0) func reset() { withLock(&_lock) { _replies = 0 } } func reply(current _: Current) throws { withLock(&_lock) { _replies += 1 _semaphore.signal() } } func waitReply(expectedReplies: Int, timeout: Int) -> Bool { let end = DispatchTime.now() + .milliseconds(timeout) while _replies < expectedReplies { let begin = DispatchTime.now() let delay = end.uptimeNanoseconds - begin.uptimeNanoseconds if delay > 0 { if _semaphore.wait(timeout: end) == .timedOut { break } } else { break } } return _replies == expectedReplies } } public func allTests(_ helper: TestHelper) throws { func test(_ value: Bool, file: String = #file, line: Int = #line) throws { try helper.test(value, file: file, line: line) } let communicator = helper.communicator() communicator.getProperties().setProperty(key: "ReplyAdapter.Endpoints", value: "udp") let adapter = try communicator.createObjectAdapter("ReplyAdapter") var replyI = PingReplyI() var reply = try uncheckedCast(prx: adapter.addWithUUID(PingReplyDisp(replyI)), type: PingReplyPrx.self).ice_datagram() try adapter.activate() let output = helper.getWriter() output.write("testing udp... ") var base = try communicator.stringToProxy("test:\(helper.getTestEndpoint(num: 0, prot: "udp"))")!.ice_datagram() let obj = uncheckedCast(prx: base, type: TestIntfPrx.self) var ret = false for _ in 0 ..< 5 { replyI.reset() try obj.ping(reply) try obj.ping(reply) try obj.ping(reply) ret = replyI.waitReply(expectedReplies: 3, timeout: 2000) if ret { break // Success } // If the 3 datagrams were not received within the 2 seconds, we try again to // receive 3 new datagrams using a new object. We give up after 5 retries. replyI = PingReplyI() reply = try uncheckedCast(prx: adapter.addWithUUID(PingReplyDisp(replyI)), type: PingReplyPrx.self).ice_datagram() } try test(ret) if communicator.getProperties().getPropertyAsInt("Ice.Override.Compress") == 0 { // // Only run this test if compression is disabled, the test expect fixed message size // to be sent over the wire. // var seq: ByteSeq do { seq = ByteSeq(repeating: 0, count: 1024) while true { seq = ByteSeq(repeating: 0, count: seq.count * 2 + 10) replyI.reset() try obj.sendByteSeq(seq: seq, reply: reply) _ = replyI.waitReply(expectedReplies: 1, timeout: 10000) } } catch is Ice.DatagramLimitException { // // The server's Ice.UDP.RcvSize property is set to 16384, which means that DatagramLimitException // will be throw when try to send a packet bigger than that. // try test(seq.count > 16384) } try obj.ice_getConnection()!.close(.GracefullyWithWait) communicator.getProperties().setProperty(key: "Ice.UDP.SndSize", value: "64000") seq = ByteSeq(repeating: 0, count: 50000) do { replyI.reset() try obj.sendByteSeq(seq: seq, reply: reply) let b = replyI.waitReply(expectedReplies: 1, timeout: 500) // // The server's Ice.UDP.RcvSize property is set to 16384, which means this packet // should not be delivered. // try test(!b) } catch is Ice.DatagramLimitException {} } output.writeLine("ok") output.write("testing udp multicast... ") var endpoint = "" // // Use loopback to prevent other machines to answer. // if communicator.getProperties().getProperty("Ice.IPv6") == "1" { endpoint += "udp -h \"ff15::1:1\" --interface \"::1\"" } else { endpoint += "udp -h 239.255.1.1 --interface 127.0.0.1" } endpoint += " -p " endpoint += "\(helper.getTestPort(num: 10))" base = try communicator.stringToProxy("test -d:\(endpoint)")! let objMcast = uncheckedCast(prx: base, type: TestIntfPrx.self) for _ in 0 ..< 5 { replyI.reset() do { try objMcast.ping(reply) ret = replyI.waitReply(expectedReplies: 5, timeout: 5000) } catch is Ice.SocketException where communicator.getProperties().getProperty("Ice.IPv6") == "1" { output.write("(not supported) ") ret = true } if ret { break } replyI = PingReplyI() reply = try uncheckedCast(prx: adapter.addWithUUID(PingReplyDisp(replyI)).ice_datagram(), type: PingReplyPrx.self) } if ret { output.writeLine("ok") } else { output.writeLine("failed(is a firewall enabled?)") } output.write("testing udp bi-dir connection... ") try obj.ice_getConnection()!.setAdapter(adapter) for _ in 0 ..< 5 { replyI.reset() try obj.pingBiDir(reply.ice_getIdentity()) try obj.pingBiDir(reply.ice_getIdentity()) try obj.pingBiDir(reply.ice_getIdentity()) ret = replyI.waitReply(expectedReplies: 3, timeout: 2000) if ret { break // Success } replyI = PingReplyI() reply = try uncheckedCast(prx: adapter.addWithUUID(PingReplyDisp(replyI)), type: PingReplyPrx.self).ice_datagram() } try test(ret) output.writeLine("ok") // // Sending the replies back on the multicast UDP connection doesn't work for most // platform(it works for macOS Leopard but not Snow Leopard, doesn't work on SLES, // Windows...). For Windows, see UdpTransceiver constructor for the details. So // we don't run this test. // // Console.Out.Write("testing udp bi-dir connection... "); // nRetry = 5; // while(nRetry-- > 0) // { // replyI.reset(); // objMcast.pingBiDir(reply.ice_getIdentity()); // ret = replyI.waitReply(5, 2000); // if(ret) // { // break; // Success // } // replyI = new PingReplyI(); // reply =(PingReplyPrx)PingReplyPrxHelper.uncheckedCast(adapter.addWithUUID(replyI)).ice_datagram(); // } // if(!ret) // { // Console.Out.WriteLine("failed(is a firewall enabled?)"); // } // else // { // Console.Out.WriteLine("ok"); // } }