<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">I also have a few thought on the TLS API, particularly on the stream side. I think we can leverage swift as a protocol oriented language, so instead of sending one / some buffers, we can do something like<div class=""><br class=""><div class=""><div class="">protocol RawBytesRepresentable {</div><div class="">&nbsp; &nbsp; var temporaryBytesBuffer: UnsafeRawBufferPointer { get } // allocation method provided in the user's side</div><div class="">&nbsp; &nbsp; func bufferDestory() // deallocate method, provided by user and performed on the TLS’s side</div><div class="">}</div><div class=""><br class=""></div><div class="">func tlsWrite(contents: inout AnyCollection&lt;RawBytesRepresentable&gt;) {</div><div class="">&nbsp; &nbsp; for buffer in contents {</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; … copy to BIO …</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; buffer.bufferDestory()</div><div class="">&nbsp; &nbsp;}</div><div class="">&nbsp; &nbsp;…omit….</div><div class="">} &nbsp; &nbsp; &nbsp;</div><div class=""><br class=""></div><div class="">We will have the benefit on transmitting swift structs / classes (as long as they confirms the protocol) and minimize unnecessary memory allocations. (For example for some structure implicitly contain its storage there’s will be no more allocation at all and the destroy method can simply be an empty function).</div><div class=""><br class=""></div><div class="">Personally an idea TLS framework for me is that it returns a TLSContext object that I can somehow poll just like a socket and file descriptor (can be done by eventfd/kqueue), I mean normal you have to read from a socket, then it to the TLS, and then to check if the TLS has enough data to process and if not you feed it again.&nbsp;</div><div class=""><br class=""></div><div class="">Having a customize reader (how to read from a source) and writer (how to write to a source) is just amazing since I can tell the TLS how to do that by themselves and hence reduce the complexity of the main event loop by a lot.</div><div class=""><br class=""></div><div class="">For example if I’m communicating to an embed device using TLS on top of I2C</div><div class=""><br class=""></div><div class="">public struct Little_device :&nbsp;&nbsp;TransportManagementDelegate&nbsp;{</div><div class="">&nbsp; &nbsp; // teach the TLS framework to write with i2c</div><div class="">&nbsp; &nbsp; public func writer(contents: AnyCollection&lt;RawBytesRepresentable&gt;) {</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>i2c_write(my_device, contents)</div><div class="">&nbsp; &nbsp; }</div><div class="">&nbsp; &nbsp; // teach the TLS how to read from an i2c bus</div><div class="">&nbsp; &nbsp; public func reader() -&gt; AnyCollection&lt;RawBytesRepresentable&gt; {</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp;var readStack = Stack&lt;Payload&gt;()&nbsp;</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp;while (some_condition) {</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;readStack.push(i2c_read(my_device,))</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp;}</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp;return readStack</div><div class="">&nbsp; &nbsp; }</div><div class="">}</div><div class=""><br class=""></div><div class="">let&nbsp;tls_context&nbsp;= TLSServer(source: some_source_dont_have_2_be_fd)</div><div class="">my_event_loop.add(tls_context)</div><div class=""><br class=""></div><div class="">…omit….now some where in the event loop</div><div class="">var newConnection = triggered_server_context.accept() // tls accept performed here</div><div class="">my_event_loop.add(newConnection)</div><div class=""><br class=""></div><div><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><div class="">Why do these methods all have "on" prefixes? I'm not totally sure I understand the intended usage here, but I see two possibilities:</div><div class=""><br class=""></div><div class="">* These are imperative commands. `onAccept` says that the TLS engine should accept a connection, `onSend` means it should send some data, etc. In that case, these should not have any prefix—they should just be `accept`, `send`, etc.</div><div class=""><br class=""></div><div class="">* These are essentially delegate methods notifying the TLS engine of an event. `onAccept` says that the system has accepted a connection and the TLS engine should do what it needs to do with it, `onSend` means the system is about to send data and it needs the TLS engine to modify it, etc. If so, Swift APIs more often use words like `should`, `will`, or `did` than `on`, particularly since they're more precise about the timing of the delegate method compared to the actual event.</div></div></div></div></blockquote><div><br class=""></div><div>I totally agree that the on-prefix is not quite swift like and the ‘will' and ‘did’ part.&nbsp;</div><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><blockquote type="cite" class=""><div class=""><div class=""><p class=""><b class=""></b></p></div></div></blockquote>I take it the parameter is some sort of abstraction wrapping e.g. a socket. So why is it called a `TransportManagementDelegate`? Shouldn't its name include words like `Connection` or `Socket` or `IOHandle` or something?</div><div class=""><br class=""></div><div class="">Do we want the parameter to be labeled `IORef`? That's not very idiomatic; it doesn't read well or follow the Swift naming guidelines.</div><div class=""><br class=""></div><div class="">You say this is for both clients and servers. When does a TLS client have a listening connection that it `accept`s connections on?</div><div class=""><br class=""></div><div class="">Is it called at different times or in different ways than `onServerCreate`?<br class=""></div></div></div></blockquote><div><br class=""></div><div>I can understand this one, even on LiberalSSL you have to manually call tls_accept() after you accept() it from the socket, so it will indeed make some sense to include this method, especially usefully when the user want to store the TLS context somewhere.&nbsp;</div><blockquote type="cite" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><div class=""><br class=""></div><div class="">This sounds like the TLS engine owns the network connection (at least by this point) and is responsible for writing to it. Does that mean `accept` and `connect` take ownership of the connection and hold on to it? If you have several different simultaneous connections, how do you know which connection this should write to? Or does a given TLSService only own one connection at a time? If so, does the transport management layer create a new TLSService instance for each connection? How? If each TLSService is bound to one connection, shouldn't it be created already knowing the connection it's going to use?</div></div></div></blockquote><div><br class=""></div><div>The thing about TLS is that itself is a separate layer from the transport layer but it is act like an extra transport layer itself, where accept/connect need to do twice (one on the transport layer, one of the TLS layer), and I can understand the users might want to inject something in between each procedure. For some reasons, depends on how the user want to use TLS for it can be one (real) connection but multiple (tls) connection, for example wrapping TLS in an extra layer of protocol. In this case having an abstract TLSContext representing the TLS connection is more appropriate then have the TLS framework take over the control of the socket.</div><br class=""></div><div>Michael</div><br class=""></div></div></body></html>