如何获取底层套接字读取缓冲区大小?

时间:2014-05-01 12:36:07

标签: c openssl

原始套接字的api:

int sz;
ioctlsocket(sock, FIONREAD, &sz); 
::recv(sock, buff, sz, 0);

ioctlsocket 可用于获取传入缓冲区大小,但如何使用openssl获取它:

int sz = what?
SSL_read(pSSL, buff, sz);

3 个答案:

答案 0 :(得分:1)

  

但如何使用openssl获取[传入缓冲区大小]?

OpenSSL使用BIO s。写缓冲区有BIO_get_write_buf_size,但读缓冲区没有相应的控制。您可以使用BIO_set_read_buffer_size设置读取缓冲区大小。但我相信为BIO设置缓冲区,而不是套接字上的I / O缓冲区。请参阅struct bio_bio_st中的crypto/bio/bss_bio.c以及BIO_f_buffer(3)BIO_s_bio(3)上的文档。

您应该可以在BIO_get_fd上致电BIO以获取基础套接字,然后使用ioctlioctlsocket。您可以在BIO中找到SSL*。 OpenSSL方便地有SSL_get_rbioSSL_get_wbio。来自ssl/ssl.h

struct ssl_st
    {
    /* protocol version
     * (one of SSL2_VERSION, SSL3_VERSION, TLS1_VERSION, DTLS1_VERSION)
     */
    int version;
    int type; /* SSL_ST_CONNECT or SSL_ST_ACCEPT */

    const SSL_METHOD *method; /* SSLv3 */

    /* There are 2 BIO's even though they are normally both the
     * same.  This is so data can be read and written to different
     * handlers */

#ifndef OPENSSL_NO_BIO
    BIO *rbio; /* used by SSL_read */
    BIO *wbio; /* used by SSL_write */
    BIO *bbio; /* used during session-id reuse to concatenate messages */
#else
    char *rbio; /* used by SSL_read */
    char *wbio; /* used by SSL_write */
    char *bbio;
#endif
    /* This holds a variable that indicates what we were doing
     * when a 0 or -1 is returned.  This is needed for
     * non-blocking IO so we know what request needs re-doing when
     * in SSL_accept or SSL_connect */
    int rwstate;
    ...
};

答案 1 :(得分:0)

感谢jww代码和标题更正。

这是我的代码

// create ssl connection
ctx = SSL_CTX_new(SSLv23_client_method()); 
pSSL = SSL_new(ctx);
sbio = BIO_new_socket(raw_socket, BIO_NOCLOSE); 
SSL_set_bio(pSSL, sbio, sbio); 
SSL_set_fd(pSSL, raw_socket);
SSL_connect(pSSL)

// send
SSL_write(pSSL, s.c_str(), s.length());

// receive
int sock_fd;
int r = BIO_get_fd(sbio, &sock_fd); // <------------------
cout << r << endl; // output -2

甚至使用BIO_new_socket和SSL_set_fd中使用的 raw_socket

ulong sz = 0;
while(sz == 0) { // <--------- it loops forever, even server echoes data
    if(ioctlsocket(raw_socket, FIONREAD, &sz) != 0) {
        throw "get_recv_size";
    }
    Sleep(0);
}
raw_socket ,BIO中使用的底层套接字是不同的?

答案 2 :(得分:0)

OP基本上问到“缓冲区应该传递给SSL_read有多大?”建立jww的答案,并且 - 这是关键 - 如果您不介意使用可能在未来版本的OpenSSL中更改的内容,那么很容易获得读取缓冲区大小。

注意:这是基于openssl 1.0.2e

获取BIO,因为jww描述了使用SSL_get_rbio()。 BIO大小存储在BIO内的BIO_F_BUFFER_CTX中。这可以在文件crypto / bio / bf_cuff.c中找到:

static int buffer_new(BIO *bi)
{
    BIO_F_BUFFER_CTX *ctx;

    ctx = (BIO_F_BUFFER_CTX *)OPENSSL_malloc(sizeof(BIO_F_BUFFER_CTX));
    if (ctx == NULL)
        return (0);
    ctx->ibuf = (char *)OPENSSL_malloc(DEFAULT_BUFFER_SIZE);
    if (ctx->ibuf == NULL) {
        OPENSSL_free(ctx);
        return (0);
    }
    ctx->obuf = (char *)OPENSSL_malloc(DEFAULT_BUFFER_SIZE);
    if (ctx->obuf == NULL) {
        OPENSSL_free(ctx->ibuf);
        OPENSSL_free(ctx);
        return (0);
    }
    ctx->ibuf_size = DEFAULT_BUFFER_SIZE;
    ctx->obuf_size = DEFAULT_BUFFER_SIZE;
    ctx->ibuf_len = 0;
    ctx->ibuf_off = 0;
    ctx->obuf_len = 0;
    ctx->obuf_off = 0;

    bi->init = 1;
    bi->ptr = (char *)ctx;
    bi->flags = 0;
    return (1);
}

获取读取缓冲区大小可以通过使用:

来完成
((BIO_F_BUFFER_CTX*)bio->ptr)->ibuf_size;

其中 bio 是表示要查询的BIO的变量。 ptr 变量需要从char *转换回来。

请注意,这适用于任何BIO,例如从BIO_new_ssl_connect(ctx)返回的BIO等。

相关问题