I would like to add adapter for networking framework to socket-based transport layer at libgit2 library.
This library creates ssl context as
/// TCP, right?
st->ctx = SSLCreateContext(NULL, kSSLClientSide, kSSLStreamType);
and sets security protocols as
/// TLS
SSLSetProtocolVersionMin(st->ctx, kTLSProtocol1)
SSLSetProtocolVersionMax(st->ctx, kTLSProtocol12)
libgit2 library defines an interface for socket-based api.
You have to provide read/write functions for each "socket-based" adapter.
The adapter write
function signature is
static ssize_t adapter_write(git_stream *stream, const char *data, size_t len, int flags)
SecureTransport
is relying on socket-based functions and it uses straightforward approach without callbacks. Read something, get result.
Networking
framework suggests a different approach with callbacks. So, instead of reading data in do-while loops, you have to add callbacks with "received/sent" partial result.
To adapt callback API I've added semaphore.
Although I'm not sure this approach is efficient in terms of nw_connections.
/// Rough draft
static ssize_t apple_network_adapter_write(git_stream *stream, const char *data, size_t len, int flags)
{
apple_network_adapter_stream *st = (apple_network_adapter_stream *) stream;
size_t data_len, processed;
OSStatus ret;
GIT_UNUSED(flags);
data_len = min(len, SSIZE_MAX);
nw_connection_t connection = ... ;/// retrieve connection
dispatch_data_t ddata = dispatch_data_create(data, data_len, NULL, DISPATCH_DATA_DESTRUCTOR_DEFAULT);
nw_content_context_t context = NW_CONNECTION_DEFAULT_MESSAGE_CONTEXT;
/// We have to add semaphores for this API.
/// Otherwise, it won't be able to "be" synced.
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
__block int errno = 0;
__block processed_length = -1;
nw_connection_send(connection, ddata, context, true, ^(nw_error_t _Nullable error) {
if (error == NULL) {
processed = len;
}
else {
errno = nw_error_get_error_code(error);
}
dispatch_semaphore_signal(semaphore);
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
ret = errno;
if (ret != noErr) {
return apple_network_adapter_error(ret);
}
GIT_ASSERT(processed < SSIZE_MAX);
return (ssize_t)processed;
}
Also I find another hint with it that nearly every object in networking framework is defined as NSObjectProtocol
object.