how to get framer transport properties

I'm implementing custom protocol using NWListener and NWProtocolFramerImplementation
with transport options using
Code Block
let parameters = NWParameters(dtls: nil, udp: NWProtocolUDP.Options())
parameters.defaultProtocolStack.applicationProtocols = [NWProtocolFramer.Options(definition: CustomProtocol.definition)]
let listener = try NWListener(using: parameters, on: port)

same for TCP with appropriate options.
how should we can get transport options(UDP|TCP) from framer when receiving data in parseInput ?
Because implementations for TCP and UDP can be different.
I am not touching protocol stacking intentionally as this is whole another topic.


Replies

how should we can get transport options(UDP|TCP) from framer when receiving data in parseInput ?

One way to do this would be to define a type value in your MessageHeader and try to build a MessageHeader in handleInput based on the expected size of your message header. For example, if you had:

Code Block swift
enum MessageType: UInt32 {
    case tcp = 6
    case udp = 17
}


Then define
Code Block swift
struct MessageHeader: Codable {
    let type: UInt32
    let length: UInt32
/* Additional logic here */
}


A rough implementation of getting the type would then look like:
Code Block swift
func handleInput(framer: NWProtocolFramer.Instance) -> Int {
while true {
var tempHeader: MessageHeader? = nil
let headerSize = MessageHeader.encodedSize
let parsed = framer.parseInput(minimumIncompleteLength: 0,
maximumLength: headerSize) { (buffer, isComplete) -> Int in
guard let buffer = buffer else {
return 0
}
if buffer.count < headerSize {
return 0
}
/* This may seem strange but what we are doing here is setting the tempHeader and
returning a parsed value to allow the code below to execute. tempHeader is unwrapped and
used to get the length/type below. Once the length and type are obtained deliverInputNoCopy
can be called to read the length from the header. */
tempHeader = MessageHeader(buffer)
return headerSize
}
/* If you can't parse out a complete header, stop parsing and ask for headerSize more bytes. */
guard parsed, let header = tempHeader else {
return headerSize
}
/* Create an object to deliver the message. */
var messageType = MessageType.original
if let parsedMessageType = MessageType(rawValue: header.type) {
messageType = parsedMessageType
}
/* Additional logic here */
}
}

Try it out and see if this works for your use-case. Another great resource here is Building a Custom Peer-to-Peer Protocol.


Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com