Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ipAddress is empty on handler in Release mode (On M series chip Macs). #31

Open
adarshurs opened this issue May 27, 2024 · 3 comments
Open

Comments

@adarshurs
Copy link

adarshurs commented May 27, 2024

`
broadcastConnection = try UDPBroadcastConnection(
port: 35602,
handler: { (response: (ipAddress: String, port: Int, response: [UInt8])) -> Void in
print("Received from (response.ipAddress):(response.port):\n\n(response.response)")
// it's empty
},
errorHandler: { (error) in
print(error)
})

`

Hi, I have been using this library in one of our apps, It's been working fine, recently I updated the app, everything worked good in Debug Mode but after releasing the app to the App Store, our app users started complaining that it's not working. Upon investigating I found out that ipAddress parameter in the handler is empty when app is running on Release Mode. Could anyone please look into this? @gunterhager , @kenji21

Edit : Just for clarity, everything else is working fine, it broadcasts the message and receive responses from the devices available but just ipAddress field is returning empty in Release mode

Edit 2 : I just found out, this issue happens when the app is built on M series chip of Macs, everything works fine on Intel chip macs

Thank you

@adarshurs adarshurs changed the title ipAddress is empty on hadler in Release mode. ipAddress is empty on handler in Release mode. May 27, 2024
@adarshurs adarshurs changed the title ipAddress is empty on handler in Release mode. ipAddress is empty on handler in Release mode (On M series chip Macs). May 27, 2024
@vitkuzmenko
Copy link

We faced some issues. The app was built on an M1 chip.

@gunterhager
Copy link
Owner

I'm really sorry that I can't help you there. I have never used the framework on a Mac and currently have no resources to investigate here. Furthermore I think that modern apps should use NWConnection instead of my package for UDP broadcasts although I can't give you any details since I never used this.

@luca-rmg
Copy link

The problem is happening also on iOS, building with Xcode 15.4 in Release mode.

To fix it you can replace 'getEndpointFromSocketAddress' method with my implementation:

private func getEndpointFromSocketAddress(socketAddressPointer: UnsafePointer<sockaddr>) throws -> (host: String, port: Int) {
        let mAddress = UnsafeMutablePointer<sockaddr>.allocate(capacity: 1)
        mAddress.initialize(to: socketAddressPointer.pointee)
        
        guard
            let host = Self.extractAddress(mAddress),
            let port = Self.extractPort(mAddress)
        else {
            throw ConnectionError.getEndpointFailed(socketAddress: mAddress.pointee)
        }
        
        return (host: host, port: port)
    }
    
    fileprivate static func extractAddress(_ address: UnsafeMutablePointer<sockaddr>?) -> String? {
        guard let address = address else { return nil }
        
        if (address.pointee.sa_family == sa_family_t(AF_INET)) {
            return self.extractAddress_ipv4(address)
        }
        else if (address.pointee.sa_family == sa_family_t(AF_INET6)) {
            return self.extractAddress_ipv6(address)
        }

        return nil
    }

    fileprivate static func extractPort(_ address: UnsafeMutablePointer<sockaddr>?) -> Int? {
        guard let address = address else { return nil }
        
        if (address.pointee.sa_family == sa_family_t(AF_INET)) {
            let socketAddressInet = UnsafeRawPointer(address).load(as: sockaddr_in.self)
            return Int(UInt16(socketAddressInet.sin_port).byteSwapped)
        }
        else if (address.pointee.sa_family == sa_family_t(AF_INET6)) {
            let socketAddressInet6 = UnsafeRawPointer(address).load(as: sockaddr_in6.self)
            return Int(UInt16(socketAddressInet6.sin6_port).byteSwapped)
        }

        return nil
    }
    
    fileprivate static func socketLength4(_ addr: sockaddr) -> UInt32 {
        return socklen_t(addr.sa_len)
    }

    fileprivate static func extractAddress_ipv4(_ address: UnsafeMutablePointer<sockaddr>) -> String? {
        return address.withMemoryRebound(to: sockaddr.self, capacity: 1) { addr in
            var address: String? = nil
            var hostname = [CChar](repeating: 0, count: Int(2049))
            if (getnameinfo(&addr.pointee, socklen_t(socketLength4(addr.pointee)), &hostname,
                            socklen_t(hostname.count), nil, socklen_t(0), NI_NUMERICHOST) == 0) {
                address = String(cString: hostname)
            }
            else {
                //            var error = String.fromCString(gai_strerror(errno))!
                //            println("ERROR: \(error)")
            }
            return address
            
        }
    }
    
    fileprivate static func extractAddress_ipv6(_ address: UnsafeMutablePointer<sockaddr>) -> String? {
        var ip: [Int8] = [Int8](repeating: Int8(0), count: Int(INET6_ADDRSTRLEN))
        return inetNtoP(address, ip: &ip)
    }

    fileprivate static func inetNtoP(_ addr: UnsafeMutablePointer<sockaddr>, ip: UnsafeMutablePointer<Int8>) -> String? {
        return addr.withMemoryRebound(to: sockaddr_in6.self, capacity: 1) { addr6 in
            let conversion:UnsafePointer<CChar> = inet_ntop(AF_INET6, &addr6.pointee.sin6_addr, ip, socklen_t(INET6_ADDRSTRLEN))
            return String(cString: conversion)
        }
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants