-
Notifications
You must be signed in to change notification settings - Fork 705
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
I/O Abstraction Layer #358
Comments
I really love that this would probably make it easier to write end-to-end unit tests too. No having to wire up fds! Just an open question to think about: Should we emulate send/recv/read/write or readv/writev instead? There are good reasons we might move to the latter. For example if we want to do low-memory in-place encryption, we might have separate iovec entries for the TLS header, IV, plaintext, and then mac/tag. On the other side though: definitely a bit more complicated as callback functions go. |
I thought about the readv/writev case, and struggled to wrap my head around what would be an appropriate signature for the callback. The "io_context" object could be used to point to a structure defining the location (and number) of multiple "shared" buffers instead of a single buffer. The callback itself could use vector-based I/O if it wanted and would treat the context appropriately for each situation. Would we want to copy the signature of the readv/writev calls and have the callbacks take a iovec struct, or an array of stuffers? I'm inclined to say an array of stuffers but I could be missing something about the way we intend to use vector-based I/O. |
I like the approach. Clear path to falling back to our current behavior. Questions:
Re writev/readv: Is there any benefit to making the callback functions iovec-aware? I'm interpreting the callbacks as a simple source/sink for wire data. We could have s2n perform the vectorization outside the callbacks and invoke the callbacks once per element of the vector. |
I was trying to provoke discussion and it worked - but between the two of you I'm now thinking that alexEBlee's first take is the way to go. Keep it simple for now, and we can factor it into iovec later if we need/want to. Sounds like there's a good bit of subtlety there that we don't need to deal with right now. |
Is this resolved now that #360 has been merged? |
Currently, s2n is coupled with the transport layer and calls read/write directly on a file descriptor set by the parent application. Some applications manage I/O themselves, have restrictions on their TCP stack, use a custom transport layer, or cannot easily conform to a socket-style interface. I would like to add an abstraction layer to allow for additional customization for these types of applications.
Proposed Change
A minimally intrusive way to implement this would be with I/O callbacks. An application could define its own send and receive callbacks and register it with the s2n connection object:
s2n_flush() and s2n_read_full_record() would be modified to use these callbacks. The callbacks themselves would be of the form:
The format of the "io_context" is unrestricted and can be used to pass information to the custom callbacks. If the user does not explicitly set a callback, the current method of calling s2n_connection_set_fd() must be used. Behind the scenes, s2n_connection_set_fd() would be modified to create an "io_context" containing that file descriptor and register default send/recv callbacks.
The text was updated successfully, but these errors were encountered: