diff --git a/Sources/Multiaddr/Address.swift b/Sources/Multiaddr/Address.swift index 7a975e1..d477e1e 100644 --- a/Sources/Multiaddr/Address.swift +++ b/Sources/Multiaddr/Address.swift @@ -95,7 +95,8 @@ extension Address { switch addrProtocol { case .tcp, .udp, .dccp, .sctp: guard addressData.count == 2 else { throw MultiaddrError.parseAddressFail } - return String(addressData.uint16.bigEndian) + guard let uint16 = addressData.uint16 else { throw MultiaddrError.parseAddressFail } + return String(uint16.bigEndian) case .ip4: return try IPv4.string(for: addressData) case .ip6: diff --git a/Sources/Multiaddr/Extensions/Data+Multiaddr.swift b/Sources/Multiaddr/Extensions/Data+Multiaddr.swift index 702a1b2..ad09558 100644 --- a/Sources/Multiaddr/Extensions/Data+Multiaddr.swift +++ b/Sources/Multiaddr/Extensions/Data+Multiaddr.swift @@ -19,9 +19,25 @@ import Foundation extension Data { - var uint16: UInt16 { - withUnsafeBytes { - $0.load(as: UInt16.self) + + var uint16: UInt16? { + self.value(ofType: UInt16.self, at: 0, convertEndian: true) + } + + var uint32: UInt32? { + self.value(ofType: UInt32.self, at: 0, convertEndian: true) + } + + fileprivate func value(ofType: T.Type, at offset: Int, convertEndian: Bool = false) -> T? { + let byteCount = MemoryLayout.size + let startIndex = self.index(self.startIndex, offsetBy: offset) + let endIndex = self.index(startIndex, offsetBy: byteCount) + guard self.endIndex >= endIndex else { return nil } + let bytes = self[startIndex...size else { throw MultiaddrError.parseIPv4AddressFail } + guard let uint32 = data.uint32 else { + throw MultiaddrError.parseIPv4AddressFail + } var output = Data(count: Int(INET_ADDRSTRLEN)) - var address = in_addr(s_addr: data.uint32) + var address = in_addr(s_addr: uint32) guard let presentationBytes = output.withUnsafeMutableBytes({ @@ -59,14 +62,6 @@ struct IPv4 { } } -extension Data { - var uint32: UInt32 { - withUnsafeBytes { - $0.load(as: UInt32.self) - } - } -} - extension BinaryInteger { // returns little endian; use .bigEndian.bytes for BE. var bytes: Data { diff --git a/Sources/Multiaddr/Protocol Helpers/Onion.swift b/Sources/Multiaddr/Protocol Helpers/Onion.swift index fa10186..b7c0291 100644 --- a/Sources/Multiaddr/Protocol Helpers/Onion.swift +++ b/Sources/Multiaddr/Protocol Helpers/Onion.swift @@ -34,7 +34,6 @@ struct Onion { guard let portValue = UInt16(port) else { throw MultiaddrError.invalidPortValue } guard portValue != 0 else { throw MultiaddrError.invalidPortValue } - //base32DecodeToData(host) guard var onionData = try? BaseEncoding.decode(host, as: .base32).data else { throw MultiaddrError.invalidOnionHostAddress } @@ -48,12 +47,14 @@ struct Onion { static func string(for data: Data) throws -> String { guard data.count == 12 else { throw MultiaddrError.invalidOnionHostAddress } + let addressBytes = data.prefix(10) + let addressEncodedString = addressBytes.asString(base: .base32).lowercased() + let portBytes = data.suffix(2) + guard let port = portBytes.uint16 else { throw MultiaddrError.invalidPortValue } + let portString = String(port.bigEndian) - //base32Encode(addressBytes).lowercased() - let addressEncodedString = addressBytes.asString(base: .base32).lowercased() - let portString = String(portBytes.uint16.bigEndian) return "\(addressEncodedString):\(portString)" } } @@ -73,7 +74,6 @@ struct Onion3 { guard let portValue = UInt16(port) else { throw MultiaddrError.invalidPortValue } guard portValue != 0 else { throw MultiaddrError.invalidPortValue } - //base32DecodeToData(host) guard var onionData = try? BaseEncoding.decode(host, as: .base32).data else { throw MultiaddrError.invalidOnionHostAddress } @@ -88,11 +88,12 @@ struct Onion3 { static func string(for data: Data) throws -> String { //guard data.count == 52 else { throw MultiaddrError.invalidOnionHostAddress } let portBytes = Data(data.suffix(2)) - let addressBytes = Data(data.dropLast(2)) + guard let port = portBytes.uint16 else { throw MultiaddrError.invalidPortValue } + let portString = String(port.bigEndian) - //base32Encode(addressBytes).lowercased() + let addressBytes = Data(data.dropLast(2)) let addressEncodedString = addressBytes.asString(base: .base32).lowercased() - let portString = String(portBytes.uint16.bigEndian) + return "\(addressEncodedString):\(portString)" } }