Skip to content

Commit

Permalink
Refactor EndpointInfo in Swift (#3195)
Browse files Browse the repository at this point in the history
  • Loading branch information
bernardnormier authored Nov 27, 2024
1 parent 75f1462 commit 1f5003d
Show file tree
Hide file tree
Showing 9 changed files with 243 additions and 381 deletions.
6 changes: 4 additions & 2 deletions swift/src/Ice/CommunicatorI.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@ class CommunicatorI: LocalObject<ICECommunicator>, Communicator {
self.initData = initData
do {
classGraphDepthMax = try initData.properties!.getIcePropertyAsInt("Ice.ClassGraphDepthMax")
precondition(classGraphDepthMax >= 1 && classGraphDepthMax <= 0x7FFF_FFFF, "Ice.ClassGraphDepthMax must be >= 0 and <= 0x7FFF_FFFF")
precondition(
classGraphDepthMax >= 1 && classGraphDepthMax <= 0x7FFF_FFFF,
"Ice.ClassGraphDepthMax must be >= 0 and <= 0x7FFF_FFFF")
traceSlicing = try initData.properties!.getIcePropertyAsInt("Ice.Trace.Slicing") > 0
acceptClassCycles = try initData.properties!.getIcePropertyAsInt("Ice.AcceptClassCycles") > 0
} catch {
} catch {
fatalError("\(error)")
}

Expand Down
180 changes: 147 additions & 33 deletions swift/src/Ice/Endpoint.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,77 +2,191 @@

import Foundation

/// The user-level interface to an endpoint.
public protocol Endpoint: AnyObject, CustomStringConvertible {
/// Return a string representation of the endpoint.
///
/// - returns: `String` - The string representation of the endpoint.
func toString() -> String

/// Returns the endpoint information.
///
/// - returns: `EndpointInfo?` - The endpoint information class.
func getInfo() -> EndpointInfo?
}

public typealias EndpointSeq = [Endpoint]

/// Base class providing access to the endpoint details.
public protocol EndpointInfo: AnyObject {
open class EndpointInfo {
/// The information of the underlying endpoint or null if there's no underlying endpoint.
var underlying: EndpointInfo? { get set }
public let underlying: EndpointInfo?
/// The timeout for the endpoint in milliseconds. 0 means non-blocking, -1 means no timeout.
var timeout: Int32 { get set }
public let timeout: Int32
/// Specifies whether or not compression should be used if available when using this endpoint.
var compress: Bool { get set }
public let compress: Bool

/// Returns the type of the endpoint.
///
/// - returns: `Int16` - The endpoint type.
func type() -> Int16
public func type() -> Int16 {
underlying?.type() ?? -1
}

/// Returns true if this endpoint is a datagram endpoint.
///
/// - returns: `Bool` - True for a datagram endpoint.
func datagram() -> Bool
public func datagram() -> Bool {
underlying?.datagram() ?? false
}

/// Returns true if this endpoint is a secure endpoint.
///
/// - returns: `Bool` - True for a secure endpoint.
func secure() -> Bool
}
public func secure() -> Bool {
underlying?.secure() ?? false
}

/// The user-level interface to an endpoint.
public protocol Endpoint: AnyObject, CustomStringConvertible {
/// Return a string representation of the endpoint.
///
/// - returns: `String` - The string representation of the endpoint.
func toString() -> String
public init(underlying: EndpointInfo) {
self.underlying = underlying
self.timeout = underlying.timeout
self.compress = underlying.compress
}

/// Returns the endpoint information.
///
/// - returns: `EndpointInfo?` - The endpoint information class.
func getInfo() -> EndpointInfo?
public init(timeout: Int32, compress: Bool) {
self.underlying = nil
self.timeout = timeout
self.compress = compress
}
}

/// Provides access to the address details of a IP endpoint.
public protocol IPEndpointInfo: EndpointInfo {
open class IPEndpointInfo: EndpointInfo {
/// The host or address configured with the endpoint.
var host: String { get set }
public let host: String
/// The port number.
var port: Int32 { get set }
public let port: Int32
/// The source IP address.
var sourceAddress: String { get set }
public let sourceAddress: String

public init(timeout: Int32, compress: Bool, host: String, port: Int32, sourceAddress: String) {
self.host = host
self.port = port
self.sourceAddress = sourceAddress
super.init(timeout: timeout, compress: compress)
}
}

/// Provides access to a TCP endpoint information.
public protocol TCPEndpointInfo: IPEndpointInfo {}
public final class TCPEndpointInfo: IPEndpointInfo {
private let _type: Int16
private let _secure: Bool

public override func type() -> Int16 {
_type
}

public override func secure() -> Bool {
_secure
}

internal init(
timeout: Int32, compress: Bool, host: String, port: Int32, sourceAddress: String, type: Int16, secure: Bool
) {
self._type = type
self._secure = secure
super.init(timeout: timeout, compress: compress, host: host, port: port, sourceAddress: sourceAddress)
}
}

/// Provides access to an UDP endpoint information.
public protocol UDPEndpointInfo: IPEndpointInfo {
public final class UDPEndpointInfo: IPEndpointInfo {
/// The multicast interface.
var mcastInterface: String { get set }
public let mcastInterface: String
/// The multicast time-to-live (or hops).
var mcastTtl: Int32 { get set }
public let mcastTtl: Int32

public override func type() -> Int16 {
UDPEndpointType
}

public override func datagram() -> Bool {
true
}

internal init(
compress: Bool, host: String, port: Int32, sourceAddress: String, mcastInterface: String, mcastTtl: Int32
) {
self.mcastInterface = mcastInterface
self.mcastTtl = mcastTtl
super.init(timeout: -1, compress: compress, host: host, port: port, sourceAddress: sourceAddress)
}
}

/// Provides access to a WebSocket endpoint information.
public protocol WSEndpointInfo: EndpointInfo {
public final class WSEndpointInfo: EndpointInfo {
/// The URI configured with the endpoint.
var resource: String { get set }
public let resource: String

internal init(underlying: EndpointInfo, resource: String) {
self.resource = resource
super.init(underlying: underlying)
}
}

/// Provides access to an IAP endpoint information.
public final class IAPEndpointInfo: EndpointInfo {
/// The accessory manufacturer or empty to not match against a manufacturer.
public let manufacturer: String
/// The accessory model number or empty to not match against a model number.
public let modelNumber: String
/// The accessory name or empty to not match against the accessory name.
public let name: String
/// The protocol supported by the accessory.
public let `protocol`: String

private let _type: Int16
private let _secure: Bool

public override func type() -> Int16 {
_type
}

public override func secure() -> Bool {
_secure
}

internal init(
timeout: Int32, compress: Bool, manufacturer: String, modelNumber: String, name: String, protocol: String,
type: Int16, secure: Bool
) {
self.manufacturer = manufacturer
self.modelNumber = modelNumber
self.name = name
self.`protocol` = `protocol`
self._type = type
self._secure = secure
super.init(timeout: timeout, compress: compress)
}
}

/// Provides access to the details of an opaque endpoint.
public protocol OpaqueEndpointInfo: EndpointInfo {
public final class OpaqueEndpointInfo: EndpointInfo {
/// The encoding version of the opaque endpoint (to decode or encode the rawBytes).
var rawEncoding: EncodingVersion { get set }
public let rawEncoding: EncodingVersion
/// The raw encoding of the opaque endpoint.
var rawBytes: ByteSeq { get set }
}
public let rawBytes: ByteSeq

public typealias EndpointSeq = [Endpoint]
private let _type: Int16

public override func type() -> Int16 {
_type
}

internal init(type: Int16, rawEncoding: EncodingVersion, rawBytes: ByteSeq) {
self.rawEncoding = rawEncoding
self.rawBytes = rawBytes
self._type = type
super.init(timeout: -1, compress: false)
}
}
138 changes: 0 additions & 138 deletions swift/src/Ice/EndpointI.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,144 +35,6 @@ public func == (lhs: Endpoint?, rhs: Endpoint?) -> Bool {
}
}

// We implement EndpointInfo as a LocalObject that delegates to an ObjC/C++ object.
// The alternative - delegating to the Endpoint object - is not practical since the public API
// of Endpoint in C++ does not expose type, datagram or secure.
class EndpointInfoI: LocalObject<ICEEndpointInfo>, EndpointInfo {
var underlying: EndpointInfo?
var timeout: Int32
var compress: Bool

init(handle: ICEEndpointInfo, underlying: EndpointInfo?, timeout: Int32, compress: Bool) {
self.underlying = underlying
self.timeout = timeout
self.compress = compress
super.init(handle: handle)
}

func type() -> Int16 {
return handle.getType()
}

func datagram() -> Bool {
return handle.getDatagram()
}

func secure() -> Bool {
return handle.getSecure()
}
}

// This class is logically abstract and only derived classes should be created.
class IPEndpointInfoI: EndpointInfoI, IPEndpointInfo {
var host: String
var port: Int32
var sourceAddress: String

init(
handle: ICEEndpointInfo,
underlying: EndpointInfo?,
timeout: Int32,
compress: Bool,
host: String,
port: Int32,
sourceAddress: String
) {
self.host = host
self.port = port
self.sourceAddress = sourceAddress
super.init(handle: handle, underlying: underlying, timeout: timeout, compress: compress)
}
}

class TCPEndpointInfoI: IPEndpointInfoI, TCPEndpointInfo {}

class UDPEndpointInfoI: IPEndpointInfoI, UDPEndpointInfo {
var mcastInterface: String
var mcastTtl: Int32

init(
handle: ICEEndpointInfo,
underlying: EndpointInfo?,
timeout: Int32,
compress: Bool,
host: String,
port: Int32,
sourceAddress: String,
mcastInterface: String,
mcastTtl: Int32
) {
self.mcastInterface = mcastInterface
self.mcastTtl = mcastTtl
super.init(
handle: handle,
underlying: underlying,
timeout: timeout,
compress: compress,
host: host,
port: port,
sourceAddress: sourceAddress)
}
}

class WSEndpointInfoI: EndpointInfoI, WSEndpointInfo {
var resource: String

init(
handle: ICEEndpointInfo, underlying: EndpointInfo?, timeout: Int32, compress: Bool,
resource: String
) {
self.resource = resource
super.init(handle: handle, underlying: underlying, timeout: timeout, compress: compress)
}
}

class OpaqueEndpointInfoI: EndpointInfoI, OpaqueEndpointInfo {
var rawEncoding: EncodingVersion
var rawBytes: ByteSeq

init(
handle: ICEEndpointInfo,
underlying: EndpointInfo?,
timeout: Int32,
compress: Bool,
rawEncoding: EncodingVersion,
rawBytes: ByteSeq
) {
self.rawEncoding = rawEncoding
self.rawBytes = rawBytes
super.init(handle: handle, underlying: underlying, timeout: timeout, compress: compress)
}
}

//
// IceSSL
//
class SSLEndpointInfoI: EndpointInfoI, SSLEndpointInfo {}

#if os(iOS) || os(watchOS) || os(tvOS)

// IceIAP (iOS only)
class IAPEndpointInfoI: EndpointInfoI, IAPEndpointInfo {
var manufacturer: String
var modelNumber: String
var name: String
var `protocol`: String

init(
handle: ICEEndpointInfo, underlying: EndpointInfo?, timeout: Int32, compress: Bool,
manufacturer: String, modelNumber: String, name: String, protocol: String
) {
self.manufacturer = manufacturer
self.modelNumber = modelNumber
self.name = name
self.protocol = `protocol`
super.init(handle: handle, underlying: underlying, timeout: timeout, compress: compress)
}
}

#endif

//
// Internal helpers to convert from ObjC to Swift objects
//
Expand Down
Loading

0 comments on commit 1f5003d

Please sign in to comment.