in adapters/tlsio_bearssl.c [1255:1403]
void tlsio_bearssl_dowork(CONCRETE_IO_HANDLE tls_io)
{
unsigned char *buffer;
size_t bufferLen;
unsigned long bearResult;
int lasterr;
if (tls_io != NULL)
{
TLS_IO_INSTANCE *tls_io_instance = (TLS_IO_INSTANCE *)tls_io;
if (tls_io_instance->tlsio_state == TLSIO_STATE_NOT_OPEN)
{
// Not open do nothing
}
else
{
if (tls_io_instance->tlsio_state != TLSIO_STATE_OPENING_UNDERLYING_IO && tls_io_instance->tlsio_state != TLSIO_STATE_CLOSING)
{
bearResult = br_ssl_engine_current_state(&tls_io_instance->sc.eng);
if (bearResult & BR_SSL_SENDREC)
{
// The engine has data to send
buffer = br_ssl_engine_sendrec_buf(&tls_io_instance->sc.eng, &bufferLen);
if (xio_send(tls_io_instance->socket_io, buffer, bufferLen, NULL, NULL) != 0)
{
LogError("Error in xio_send.");
indicate_error(tls_io_instance);
}
else
{
br_ssl_engine_sendrec_ack(&tls_io_instance->sc.eng, bufferLen);
}
}
bearResult = br_ssl_engine_current_state(&tls_io_instance->sc.eng);
if (bearResult & BR_SSL_RECVREC)
{
// The engine can accept data from the peer if there is any
LIST_ITEM_HANDLE first_pending_io = singlylinkedlist_get_head_item(tls_io_instance->pending_todecrypt_list);
if (first_pending_io != NULL)
{
PENDING_TLS_IO *pending_tls_io = (PENDING_TLS_IO*)singlylinkedlist_item_get_value(first_pending_io);
if (pending_tls_io != NULL)
{
buffer = br_ssl_engine_recvrec_buf(&tls_io_instance->sc.eng, &bufferLen);
if (bufferLen == 0)
{
LogError("Zero length buffer returned by BearSSL");
indicate_error(tls_io_instance);
}
else
{
if (pending_tls_io->size < bufferLen)
{
bufferLen = pending_tls_io->size;
}
memcpy(buffer, pending_tls_io->bytes, bufferLen);
br_ssl_engine_recvrec_ack(&tls_io_instance->sc.eng, bufferLen);
if (bufferLen < pending_tls_io->size)
{
pending_tls_io->size -= bufferLen;
memcpy(pending_tls_io->bytes, pending_tls_io->bytes + bufferLen, pending_tls_io->size);
}
else
{
free(pending_tls_io->bytes);
free(pending_tls_io);
(void)singlylinkedlist_remove(tls_io_instance->pending_todecrypt_list, first_pending_io);
}
}
}
}
}
bearResult = br_ssl_engine_current_state(&tls_io_instance->sc.eng);
if (bearResult & BR_SSL_SENDAPP)
{
if (tls_io_instance->tlsio_state == TLSIO_STATE_IN_HANDSHAKE)
{
tls_io_instance->tlsio_state = TLSIO_STATE_OPEN;
indicate_open_complete(tls_io_instance, IO_OPEN_OK);
}
// Engine is ready for application data - send it if we have any
LIST_ITEM_HANDLE first_pending_io = singlylinkedlist_get_head_item(tls_io_instance->pending_toencrypt_list);
if (first_pending_io != NULL)
{
PENDING_TLS_IO *pending_tls_io = (PENDING_TLS_IO*)singlylinkedlist_item_get_value(first_pending_io);
if (pending_tls_io != NULL)
{
buffer = br_ssl_engine_sendapp_buf(&tls_io_instance->sc.eng, &bufferLen);
if (pending_tls_io->size < bufferLen)
{
bufferLen = pending_tls_io->size;
}
memcpy(buffer, pending_tls_io->bytes, bufferLen);
br_ssl_engine_sendapp_ack(&tls_io_instance->sc.eng, bufferLen);
if (bufferLen < pending_tls_io->size)
{
pending_tls_io->size -= bufferLen;
memcpy(pending_tls_io->bytes, pending_tls_io->bytes + bufferLen, pending_tls_io->size);
}
else
{
pending_tls_io->on_send_complete(pending_tls_io->callback_context, IO_SEND_OK);
free(pending_tls_io->bytes);
free(pending_tls_io);
(void)singlylinkedlist_remove(tls_io_instance->pending_toencrypt_list, first_pending_io);
br_ssl_engine_flush(&tls_io_instance->sc.eng, 0);
}
}
}
}
bearResult = br_ssl_engine_current_state(&tls_io_instance->sc.eng);
if (bearResult & BR_SSL_RECVAPP)
{
// Application data is waiting to be forwarded
buffer = br_ssl_engine_recvapp_buf(&tls_io_instance->sc.eng, &bufferLen);
tls_io_instance->on_bytes_received(tls_io_instance->on_bytes_received_context, buffer, bufferLen);
br_ssl_engine_recvapp_ack(&tls_io_instance->sc.eng, bufferLen);
}
}
if ((lasterr = br_ssl_engine_last_error(&tls_io_instance->sc.eng)) != 0)
{
LogError("BearSSL reported an error: %d", lasterr);
indicate_error(tls_io_instance);
}
xio_dowork(tls_io_instance->socket_io);
}
}
}