<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=""><div><blockquote type="cite" class=""><div class="">On Apr 4, 2017, at 9:32 AM, Gelareh Taban &lt;<a href="mailto:gtaban@us.ibm.com" class="">gtaban@us.ibm.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">I think perhaps there is misunderstanding about the role of TransportManager (perhaps naming is the problem after all!). This is not a singleton type of manager - rather it is a per connection manager and it "manages" for example the system socket calls. An instance of transport manager handles one connection. An instance of transport manager has one TLS delegate associated with that connection. Therefore, the delegate is associated with only one connection at a time.</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""></div></blockquote><div><br class=""></div><div>Oh, wow! You're right, I completely misunderstood that; I was under the impression that all of the instances in your diagram were long-lived, but it sounds like they're actually used for one connection/request and then thrown away (or perhaps reused in a pool—doesn't matter much either way).</div><div><br class=""></div><div>The use of "management" in these names definitely was part of why I misunderstood the proposal, because in Cocoa, a "manager" is almost always long-lived. Often it's a singleton or is frequently used as a singleton (`Foundation.FileManager`, `CoreLocation.CLLocationManager`, `Photos.PHImageManager`.) Sometimes it's associated with a long-lived object like a document (`Foundation.UndoManager`) or a text editing view (`AppKit.NSLayoutManager`). Very occasionally it's short-lived and manages some particular activity (`CoreData.NSMigrationManager`), but even that class is only short-lived because the activity it manages is relatively brief.</div><div><br class=""></div><div><div>Given that the transport manager and `SSLService` are both dedicated to a single connection, I suppose the idea is that the call to `onAccept` or `onConnect` permanently associates the `SSLService` with the `IORef`, an instance that allows it to communicate with the actual socket/connection. When `onReceive` wants to receive data, it should get it from the `IORef`; when `onSend` wants to send data, it should give it to the `IORef`.</div></div><div><br class=""></div><div>One more architectural question: What is the ownership relationship between the application, web server, HTTP management, and transport management layers? That is, is transport management the layer that drives everything else, or is it more of a utility type used by the other layers?</div><div><br class=""></div><div>For the moment, I will assume that the transport manager layer is subordinate to the application or web server.</div><br class=""><blockquote type="cite" class=""><div class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">If we assume the above, then it is not hard to see that once a context is created for a specific TLS connection, and stored by the TLS service object, the context can be passed between the various OpenSSL or Secure Transport calls.<span class="Apple-converted-space">&nbsp;</span></span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""></div></blockquote><div><br class=""></div><div>Yes, I do see that.</div><div><br class=""></div><div>With that in mind, I have a question about the commands: Why are `onServerCreate` and `onAccept` separate, and why are `onClientCreate` and `onConnect` separate? I understand that Secure Transport and OpenSSL do those tasks with separate calls, but is there a reason to perform them at different times? I would think that, by the time a `TLSService` has been instantiated, we have already received a connection and want to start reading data from it. (BlueSocket does appear to separate initialization from handshaking, but it also appears to initialize an `SSLService` before it begins listening, so I'm not sure that makes sense for us.) Eliminating `onServerCreate` and `onClientCreate` would therefore simply remove an opportunity for mistakes: it would no longer be possible to accidentally call `onAccept` on a client `TLSService` or `onConnect` on a server `TLSService`, or to forget one of the two initialization setps. (It also means fewer APIs to name. :^) )</div><div><br class=""></div><div>As for naming issues, here's what I would suggest.</div><div><br class=""></div><div>* * *</div><div><br class=""></div><div>I think the best way to think of the transport manager and the IORef is as two parts of a "connection". What you are calling the transport manager—or at least the relevant piece of it for this discussion—is a `Connection` object. A `Connection` object primarily exists to manage a `RawConnection` instance (equivalent to your `IORef`/`TransportManagerDelegate`), which represents an OS-level network connection. `Connection` tracks the `RawConnection`'s lifetime and adds various smart behaviors to it, including, of course, TLS.</div><div><br class=""></div><div>I will now briefly sketch `Connection` and `RawConnection`. Keep in mind that these are not exact specifications and aren't being proposed; they're just meant to generally describe the capabilities of these types. If you ask whether `Connection` should be `final` or argue that `RawConnection` should use traditional Unix socket function names, you're sort of missing the point.</div><div><br class=""></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>// A&nbsp;ConnectionConfiguration&nbsp;is some object from a higher layer in the application's stack that can&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>// provide configuration info for Connection. Most importantly, it provides the TLSService.</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>// In your diagram, the HTTP management, web server, and application layers might all conform.</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>protocol ConnectionConfiguration {</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>...</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>var tlsService: TLSService?</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>...</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>}</div><div><br class=""></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>class Connection {</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>// A bit about how I imagine a Connection would usually be created:</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>//&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>// For a client connection, convenience initializers (not shown here) would be used to specify&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>// a destination address, protocol, etc. These would create a system-level socket, convert&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>// it into a `RawConnection`, and pass that to `init(toServerVia:configuration:)`.</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>//&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>// For a server connection, a separate `Listener` type would listen to a socket, accept&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>// any connections, and call `init(fromClientVia:configuration:)` for them.</div><div><span class="Apple-tab-span" style="white-space:pre">                </span></div><div><span class="Apple-tab-span" style="white-space:pre">                </span>// A Connection may be created as a result of connecting to a server as a client.</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>// If so, it goes through this initializer.</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>init(toServerVia rawConnection: RawConnection, configuration: ConnectionConfiguration) throws</div><div><span class="Apple-tab-span" style="white-space:pre">                </span></div><div><span class="Apple-tab-span" style="white-space:pre">                </span>// A Connection may be created as a result of a client connecting to us as a server.</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>// If so, it goes through this initializer.</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>init(fromClientVia rawConnection: RawConnection, configuration: ConnectionConfiguration) throws</div><div><span class="Apple-tab-span" style="white-space:pre">                </span></div><div><span class="Apple-tab-span" style="white-space:pre">                </span>// The Connection will hold on to its RawConnection and to its TLSService, if it has one.</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>var rawConnection: RawConnection { get }</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>var tlsService: TLSService? { get }</div><div><span class="Apple-tab-span" style="white-space:pre">                </span></div><div><span class="Apple-tab-span" style="white-space:pre">                </span>// Synchronously sends data to the other endpoint. The provided data will all be sent before this&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>//&nbsp;method returns, unless an error occurs during sending. If the underlying connection&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>//&nbsp;closes before all data has been sent, this will throw an error. (The error might include&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>//&nbsp;unsent data; that's something to be designed later.)</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>func sendBytes(_ data: Data) throws</div><div><span class="Apple-tab-span" style="white-space:pre">                </span></div><div><span class="Apple-tab-span" style="white-space:pre">                </span>// Synchronously receives data from the other endpoint. This call will attempt to receive up to the&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>//&nbsp;indicated number of bytes. If the underlying connection closes before data has&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>//&nbsp;been received, this will throw an error. (Again, the error might include any data that&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>// was received; that's something to be designed later.)</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>//&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>// Note: I am not deciding whether this is blocking or nonblocking. It shouldn't affect the&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>// implementation of the TLSService either way—the underlying RawConnection will&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>// either block or it won't.</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>func receiveBytes(_ count: Int) throws -&gt; Data</div><div><span class="Apple-tab-span" style="white-space:pre">                </span></div><div><span class="Apple-tab-span" style="white-space:pre">                </span>// Closes the connection, notifying the other side if possible. Throws if the connection is&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>// already closed or if another error occurs.</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>func close() throws</div><div><span class="Apple-tab-span" style="white-space:pre">                </span></div><div><span class="Apple-tab-span" style="white-space:pre">                </span>// Indicates whether, to the `Connection`'s knowledge, the underlying connection has closed.&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>// If `true`, all other calls will throw; if `false`, they *may* throw, but it isn't certain.</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>var hasClosed: Bool { get {…} }</div><div><br class=""></div><div><span class="Apple-tab-span" style="white-space:pre">                </span>// Cleans up if the connection hasn't been closed yet.</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>deinit</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>}</div><div><br class=""></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>// A RawConnection represents whatever low-level OS resource is used to&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>// communicate with the network.</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>protocol RawConnection {</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>// These calls all just do the underlying thing that the `Connection` call does.</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>func sendBytes(_ data: Data) throws</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>func receiveBytes(_ count: Int) throws -&gt; Data</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>func close() throws</div><div><span class="Apple-tab-span" style="white-space:pre">                </span></div><div><span class="Apple-tab-span" style="white-space:pre">                </span>// Some RawConnections may simply wrap an OS file descriptor; if so, this&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>// property will return it so you can access and use it directly.</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>//&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>// Note: We may prefer a design where *all* RawConnections are *always*&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>// file descriptors. If so, we would eliminate the Optional on this type, but we'd&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>// still have the above methods. They basically wrap code that both `Connection`&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>// and a `TLSService` that wrapped a library like Secure Transport which didn't&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>// directly do I/O would call.</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>var fileDescriptor: Int32? { get }</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>}</div><div><br class=""></div><div>So, given these rough designs, here's what I propose for `TLSService`. To the extent that names from the above rough design are present in `TLSService`, they would eventually be adjusted to match names in the larger system—so if `RawConnection` turns out to be called `SocketSink` eventually, we would change both the parameter type and the parameter label for the first two methods.</div><div><br class=""></div><div><span class="Apple-tab-span" style="white-space: pre;">        </span>protocol TLSService {</div><div><span class="Apple-tab-span" style="white-space: pre;">                </span>// I'll talk about these two method names, and discuss alternatives, in the prose.</div><div><span class="Apple-tab-span" style="white-space:pre">                </span></div><div><span class="Apple-tab-span" style="white-space:pre">                </span>/// Called to indicate that the connection has connected to a server, and that it should&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>/// begin negotiating a TLS connection.</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>///&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>/// -Parameter rawConnection: The underlying OS-level connection. The `TLSService` should&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>///&nbsp;<span class="Apple-tab-span" style="white-space:pre">                        </span>negotiate over this raw connection during this call, and then hold onto the raw&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>///&nbsp;<span class="Apple-tab-span" style="white-space:pre">                        </span>connection for future calls to other methods.</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>/// -Throws: If the connection closes, TLS negotiation fails, or any other error occurs.</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>/// -Precondition: Neither `didConnectToServer` nor `didConnectFromClient` has previously been&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>///&nbsp;<span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">                        </span>called.</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>///&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>/// -Note: This will typically be called from `Connection(toServerVia:configuration:)`.</div><div><span class="Apple-tab-span" style="white-space: pre;">                </span>func didConnectToServer(via rawConnection: RawConnection) throws</div><div><span class="Apple-tab-span" style="white-space: pre;">                </span></div><div><div><span class="Apple-tab-span" style="white-space: pre;">                </span>/// Called to indicate that the connection has connected to a client, and that it should&nbsp;</div><div><span class="Apple-tab-span" style="white-space: pre;">                </span>/// wait for that client to begin negotiating a TLS connection, and then negotiate as a server.</div><div><span class="Apple-tab-span" style="white-space: pre;">                </span>///&nbsp;</div><div><span class="Apple-tab-span" style="white-space: pre;">                </span>/// -Parameter rawConnection: The underlying OS-level connection. The `TLSService` should&nbsp;</div><div><span class="Apple-tab-span" style="white-space: pre;">                </span>///&nbsp;<span class="Apple-tab-span" style="white-space: pre;">                        </span>negotiate over this raw connection during this call, and then hold onto the raw&nbsp;</div><div><span class="Apple-tab-span" style="white-space: pre;">                </span>///&nbsp;<span class="Apple-tab-span" style="white-space: pre;">                        </span>connection for future calls to other methods.</div><div><span class="Apple-tab-span" style="white-space: pre;">                </span>/// -Throws: If the connection closes, TLS negotiation fails, or any other error occurs.</div><div><span class="Apple-tab-span" style="white-space: pre;">                </span>/// -Precondition: Neither `didConnectToServer` nor `didConnectFromClient` has previously been&nbsp;</div><div><span class="Apple-tab-span" style="white-space: pre;">                </span>///&nbsp;<span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">                        </span>called.</div><div><span class="Apple-tab-span" style="white-space: pre;">                </span>///&nbsp;</div><div><span class="Apple-tab-span" style="white-space: pre;">                </span>/// -Note: This will typically be called from `Connection(fromClientVia:configuration:)`.</div><div><span class="Apple-tab-span" style="white-space: pre;">                </span>func didConnectFromClient(via rawConnection: RawConnection) throws</div><div><span class="Apple-tab-span" style="white-space:pre">                </span></div><div><span class="Apple-tab-span" style="white-space: pre;">                </span>// The next three calls do not have `will` or `did` prefixes because they are imperative:&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>// they do not merely tell the `TLSService` that something happened—they actually *cause*&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>// it to happen.</div><div class=""><span class="Apple-tab-span" style="white-space:pre">                </span></div><div class=""><span class="Apple-tab-span" style="white-space:pre">                </span>/// Called when the connection wants to send the indicated plaintext. This call should&nbsp;</div><div class=""><span class="Apple-tab-span" style="white-space:pre">                </span>/// encipher it, wrap it in TLS framing and protocol data, and send it through the raw&nbsp;</div><div class=""><span class="Apple-tab-span" style="white-space:pre">                </span>///&nbsp;connection.</div><div class=""><span class="Apple-tab-span" style="white-space:pre">                </span>///&nbsp;</div><div class=""><span class="Apple-tab-span" style="white-space:pre">                </span>/// -Parameter data: The plaintext data to send.</div><div class=""><span class="Apple-tab-span" style="white-space:pre">                </span>/// -Throws: If the connection closes, a TLS error occurs, or any other error occurs.</div><div class=""><span class="Apple-tab-span" style="white-space:pre">                </span>/// -Precondition: Either `didConnectToServer` or `didConnectFromClient` has been called.</div><div><span class="Apple-tab-span" style="white-space: pre;">                </span>///&nbsp;</div><div><span class="Apple-tab-span" style="white-space: pre;">                </span>/// -Note: This will typically be called from `Connection.sendBytes(_:)`.</div><div class=""><span class="Apple-tab-span" style="white-space:pre">                </span>func sendBytes(_ data: Data) throws</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">                </span>/// Called when the connection wants to receive data. This call should attempt to receive&nbsp;</div><div class=""><span class="Apple-tab-span" style="white-space:pre">                </span>/// the indicated number of bytes of TLS data, then interpret all TLS protocol messages,&nbsp;</div><div class=""><span class="Apple-tab-span" style="white-space:pre">                </span>/// extract any plaintext from it, and return it.</div><div class=""><span class="Apple-tab-span" style="white-space:pre">                </span>///&nbsp;</div><div class=""><span class="Apple-tab-span" style="white-space:pre">                </span>/// -Parameter count: The number of bytes to attempt to read.</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">                </span>/// -Throws: If the connection closes, a TLS error occurs, or any other error occurs.</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">                </span>/// -Precondition: Either `didConnectToServer` or `didConnectFromClient` has been called.</div><div><span class="Apple-tab-span" style="white-space: pre;">                </span>///&nbsp;</div><div><span class="Apple-tab-span" style="white-space: pre;">                </span>/// -Note: This will typically be called from `Connection.receiveBytes(_:)`.</div><div class=""><span class="Apple-tab-span" style="white-space:pre">                </span>func receiveBytes(_ count: Int) throws -&gt; Data</div><div class=""><span class="Apple-tab-span" style="white-space:pre">                </span></div><div class=""><span class="Apple-tab-span" style="white-space:pre">                </span>/// Called when the connection wants to close. This call should notify the other side of&nbsp;</div><div class=""><span class="Apple-tab-span" style="white-space:pre">                </span>/// the shutdown through a TLS alert and then close the connection.</div><div class=""><span class="Apple-tab-span" style="white-space:pre">                </span>///&nbsp;</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">                </span>/// -Throws: If the connection closes before it finishes, a TLS error occurs, or any other error occurs.</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">                </span>/// -Precondition: Either `didConnectToServer` or `didConnectFromClient` has been called.</div><div><span class="Apple-tab-span" style="white-space: pre;">                </span>///&nbsp;</div><div><span class="Apple-tab-span" style="white-space: pre;">                </span>/// -Note: This will typically be called from `Connection.close`.</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">                </span>func close() throws</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">                </span>/// Called when the `Connection` that owns this `TLSService` is about to deinitialize itself.</div><div class=""><span class="Apple-tab-span" style="white-space:pre">                </span>/// This is a good opportunity to tear down any state associated with the `TLSService`.</div><div class=""><span class="Apple-tab-span" style="white-space:pre">                </span>func willDeinitConnection()</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>}</div><div class=""><br class=""></div><div class="">A few points to talk about here:</div><div class=""><br class=""></div><div class="">* I am using `Data` here because you mentioned that you're interested in switching to that, but I'm actually pretty agnostic about whether we should use `Data`, `Unsafe(Mutable)RawBufferPointer`, `Unsafe(Mutable)BufferPointer&lt;UInt8&gt;`, or anything else out there. We might even use `Data` on the user-facing `Connection` interfaces, but use `Unsafe(Mutable)RawBufferPointer` in the `TLSService` and `RawConnection` interfaces for speed. My only concern with the buffer pointer design is that, if we try to `receiveBytes(_:)` and after de-TLSing it find that we have more data than will fit in the buffer, I'm not sure how we'd get the excess data back to the caller.</div><div class=""><br class=""></div><div class="">* The first two method names, for the methods used after accepting or connecting.</div><div class=""><br class=""></div><div class="">I chose these names because they read well, describe when they are called clearly, and match the names in the `Connection` sketch. However, they're a little bit...out there. I have two alternative suggestions:</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>* Traditional/conservative: `didConnect(via:)` and `didAccept(via:)`.</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>* Imperative: `negotiateAsClient(via:)` and `negotiateAsServer(via:)`.</div><div class=""><br class=""></div><div class=""><div>* `sendBytes`, `receiveBytes`, and `close`: These three calls are imperative because, at least in this design, they actually *cause* the thing indicated to happen—`sendBytes` actually sends the data, `receiveBytes` actually goes and gets the data, and `close()` actually causes a disconnect. If this weren't the case, and these calls were more like filters—for instance, `sendBytes` returned data for the caller to send over the connection, instead of actually calling the raw connection and asking it to be sent—then I would suggest `willSendBytes(_:)`, `didReceiveBytes(_:)`, and `willClose()`.</div></div><div><br class=""></div><div>* `willDeinitConnection()` here is defined as happening at connection deinit time, which may be slightly later than would be ideal. However, it seems like the logic necessary to make it happen as soon as possible would be a lot more complicated, so I'm not sure it's worth it to do so.</div><div><br class=""></div><div>* And finally, an overall design question: Would we be better off doing this as a sort of generalized filter or layer on the `Connection` object? This is, for instance, how OpenSSL works: it wraps the underlying I/O primitive in a BIO structure, then adds an "object" of sorts to that BIO which transparently applies TLS as you read and write. A similar approach in Swift would probably imagine this protocol not as a TLS-specific hook, but rather as a way to capture *all* operations on a connection and do arbitrary things with them. I'm not necessarily advocating this approach, because it couples the TLS system pretty strongly to our future socket abstraction, but I'm wondering if it was considered or not.</div><div><br class=""></div><div>* * *</div><div><br class=""></div><div>Anyway, I hope this is helpful. It certainly is long. :^)</div><div><br class=""></div></div></div><div class="">
<span class="Apple-style-span" style="border-collapse: separate; font-variant-ligatures: normal; font-variant-east-asian: normal; font-variant-position: normal; line-height: normal; border-spacing: 0px;"><div class=""><div style="font-size: 12px; " class="">--&nbsp;</div><div style="font-size: 12px; " class="">Brent Royal-Gordon</div><div style="font-size: 12px; " class="">Architechies</div></div></span>

</div>
<br class=""></body></html>