SSL_write с повторными попытками? - PullRequest
0 голосов
/ 15 февраля 2020

Моя цель - написать функцию, которая пишет сообщение через соединение 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} продолжит возвращаться. Это действительно правильный способ сделать это?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...