Моя цель - написать функцию, которая пишет сообщение через соединение SSL, с повторными попытками, если необходимо. Кроме того, он должен отключить SSL-соединение при необходимости, закрыть основной транспорт TCP и вернуть -1, если полная запись невозможна. Я пытался использовать документы на SSL_write , SSL_get_error и SSL_shutdown в качестве руководства.
// returns 0 on success or -1 if the write can't be completed (in which case the SSL conn is
// shutdown (if possible) and freed and the underlying transport is closed).
int SSLWriteAll(SSL *ssl, void *buf, size_t size) {
size_t written = 0;
while (written < size) {
ERR_clear_error();
int ret = SSL_write(ssl, buf + written, size);
int err = SSL_get_error(ssl, ret);
switch (err) {
case SSL_ERROR_NONE:
// no err, the ret is the # of bytes written
written += ret;
break;
case SSL_ERROR_WANT_WRITE:
case SSL_ERROR_WANT_READ:
// docs say the I/O op should just be retried here, but they also say
// this can happen infinitely many times, so maybe we should have a limit
break;
case SSL_ERROR_SYSCALL:
case SSL_ERROR_SSL:
// these are the only errors I saw listed for which SSL_shutdown must not be called
closeTransportAndFree:
close(SSL_get_fd(ssl));
SSL_free(ssl);
return -1;
default:
// any other error carries no indication that we should retry,
// so let's just scrap the connection
shutdownSSL:
while (1) {
ERR_clear_error();
err = SSL_shutdown(ssl);
switch (err) {
case SSL_ERROR_NONE:
// shutdown succeeded, now close the transport and free the conn
goto closeTransportAndFree;
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
// idk how this is possible, but apparently we just need to retry
// shutting down the conn
break;
case SSL_ERROR_SYSCALL:
case SSL_ERROR_SSL:
// explicitly told we shouldn't shutdown the conn
fprintf(stderr, "failed to shutdown conn: %d\n", err);
ERR_print_errors_fp(stderr);
// fallthrough
default:
goto closeTransportAndFree;
}
}
}
}
if (written != size) {
fprintf(stderr, "internal err, wanted to write: %zu bytes, but wrote %zu\n", size, written);
goto shutdownSSL;
}
return 0;
}
Idk, но это кажется безумно запутанным просто написать сообщение через соединение. Существует даже вероятность бесконечной жесткости l oop, если SSL_ERROR_WANT_{READ,WRITE}
продолжит возвращаться. Это действительно правильный способ сделать это?