ngx_event_openssl.c

来自「Nginx是一个高性能的HTTP和反向代理服务器」· C语言 代码 · 共 1,975 行 · 第 1/4 页

C
1,975
字号
        if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) {            return NGX_ERROR;        }        return NGX_AGAIN;    }    if (sslerr == SSL_ERROR_WANT_WRITE) {        c->write->ready = 0;        c->read->handler = ngx_ssl_handshake_handler;        c->write->handler = ngx_ssl_handshake_handler;        if (ngx_handle_write_event(c->write, 0) == NGX_ERROR) {            return NGX_ERROR;        }        return NGX_AGAIN;    }    err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;    c->ssl->no_wait_shutdown = 1;    c->ssl->no_send_shutdown = 1;    c->read->eof = 1;    if (sslerr == SSL_ERROR_ZERO_RETURN || ERR_peek_error() == 0) {        ngx_log_error(NGX_LOG_INFO, c->log, err,                      "peer closed connection in SSL handshake");        return NGX_ERROR;    }    c->read->error = 1;    ngx_ssl_connection_error(c, sslerr, err, "SSL_do_handshake() failed");    return NGX_ERROR;}static voidngx_ssl_handshake_handler(ngx_event_t *ev){    ngx_connection_t  *c;    c = ev->data;    ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,                   "SSL handshake handler: %d", ev->write);    if (ev->timedout) {        c->ssl->handler(c);        return;    }    if (ngx_ssl_handshake(c) == NGX_AGAIN) {        return;    }    c->ssl->handler(c);}ssize_tngx_ssl_recv_chain(ngx_connection_t *c, ngx_chain_t *cl){    u_char     *last;    ssize_t     n, bytes;    ngx_buf_t  *b;    bytes = 0;    b = cl->buf;    last = b->last;    for ( ;; ) {        n = ngx_ssl_recv(c, last, b->end - last);        if (n > 0) {            last += n;            bytes += n;            if (last == b->end) {                cl = cl->next;                if (cl == NULL) {                    return bytes;                }                b = cl->buf;                last = b->last;            }            continue;        }        if (bytes) {            return bytes;        }        return n;    }}ssize_tngx_ssl_recv(ngx_connection_t *c, u_char *buf, size_t size){    int  n, bytes;    if (c->ssl->last == NGX_ERROR) {        c->read->error = 1;        return NGX_ERROR;    }    if (c->ssl->last == NGX_DONE) {        c->read->ready = 0;        c->read->eof = 1;        return 0;    }    bytes = 0;    ngx_ssl_clear_error(c->log);    /*     * SSL_read() may return data in parts, so try to read     * until SSL_read() would return no data     */    for ( ;; ) {        n = SSL_read(c->ssl->connection, buf, size);        ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_read: %d", n);        if (n > 0) {            bytes += n;        }        c->ssl->last = ngx_ssl_handle_recv(c, n);        if (c->ssl->last == NGX_OK) {            size -= n;            if (size == 0) {                return bytes;            }            buf += n;            continue;        }        if (bytes) {            return bytes;        }        switch (c->ssl->last) {        case NGX_DONE:            c->read->ready = 0;            c->read->eof = 1;            return 0;        case NGX_ERROR:            c->read->error = 1;            /* fall thruogh */        case NGX_AGAIN:            return c->ssl->last;        }    }}static ngx_int_tngx_ssl_handle_recv(ngx_connection_t *c, int n){    int        sslerr;    ngx_err_t  err;    if (n > 0) {        if (c->ssl->saved_write_handler) {            c->write->handler = c->ssl->saved_write_handler;            c->ssl->saved_write_handler = NULL;            c->write->ready = 1;            if (ngx_handle_write_event(c->write, 0) == NGX_ERROR) {                return NGX_ERROR;            }            ngx_post_event(c->write, &ngx_posted_events);        }        return NGX_OK;    }    sslerr = SSL_get_error(c->ssl->connection, n);    err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;    ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", sslerr);    if (sslerr == SSL_ERROR_WANT_READ) {        c->read->ready = 0;        return NGX_AGAIN;    }    if (sslerr == SSL_ERROR_WANT_WRITE) {        ngx_log_error(NGX_LOG_INFO, c->log, 0,                      "peer started SSL renegotiation");        c->write->ready = 0;        if (ngx_handle_write_event(c->write, 0) == NGX_ERROR) {            return NGX_ERROR;        }        /*         * we do not set the timer because there is already the read event timer         */        if (c->ssl->saved_write_handler == NULL) {            c->ssl->saved_write_handler = c->write->handler;            c->write->handler = ngx_ssl_write_handler;        }        return NGX_AGAIN;    }    c->ssl->no_wait_shutdown = 1;    c->ssl->no_send_shutdown = 1;    if (sslerr == SSL_ERROR_ZERO_RETURN || ERR_peek_error() == 0) {        ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,                       "peer shutdown SSL cleanly");        return NGX_DONE;    }    ngx_ssl_connection_error(c, sslerr, err, "SSL_read() failed");    return NGX_ERROR;}static voidngx_ssl_write_handler(ngx_event_t *wev){    ngx_connection_t  *c;    c = wev->data;    c->read->handler(c->read);}/* * OpenSSL has no SSL_writev() so we copy several bufs into our 16K buffer * before the SSL_write() call to decrease a SSL overhead. * * Besides for protocols such as HTTP it is possible to always buffer * the output to decrease a SSL overhead some more. */ngx_chain_t *ngx_ssl_send_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit){    int          n;    ngx_uint_t   flush;    ssize_t      send, size;    ngx_buf_t   *buf;    if (!c->ssl->buffer        || (in && in->next == NULL && !(c->buffered & NGX_SSL_BUFFERED)))    {        /*         * we avoid a buffer copy if         *     we do not need to buffer the output         *     or the incoming buf is a single and our buffer is empty         */        while (in) {            if (ngx_buf_special(in->buf)) {                in = in->next;                continue;            }            n = ngx_ssl_write(c, in->buf->pos, in->buf->last - in->buf->pos);            if (n == NGX_ERROR) {                return NGX_CHAIN_ERROR;            }            if (n == NGX_AGAIN) {                c->buffered |= NGX_SSL_BUFFERED;                return in;            }            in->buf->pos += n;            if (in->buf->pos == in->buf->last) {                in = in->next;            }        }        return in;    }    /* the maximum limit size is the maximum uint32_t value - the page size */    if (limit == 0 || limit > (off_t) (NGX_MAX_UINT32_VALUE - ngx_pagesize)) {        limit = NGX_MAX_UINT32_VALUE - ngx_pagesize;    }    buf = c->ssl->buf;    if (buf == NULL) {        buf = ngx_create_temp_buf(c->pool, NGX_SSL_BUFSIZE);        if (buf == NULL) {            return NGX_CHAIN_ERROR;        }        c->ssl->buf = buf;    }    if (buf->start == NULL) {        buf->start = ngx_palloc(c->pool, NGX_SSL_BUFSIZE);        if (buf->start == NULL) {            return NGX_CHAIN_ERROR;        }        buf->pos = buf->start;        buf->last = buf->start;        buf->end = buf->start + NGX_SSL_BUFSIZE;    }    send = 0;    flush = (in == NULL) ? 1 : 0;    for ( ;; ) {        while (in && buf->last < buf->end) {            if (in->buf->last_buf || in->buf->flush) {                flush = 1;            }            if (ngx_buf_special(in->buf)) {                in = in->next;                continue;            }            size = in->buf->last - in->buf->pos;            if (size > buf->end - buf->last) {                size = buf->end - buf->last;            }            if (send + size > limit) {                size = (ssize_t) (limit - send);                flush = 1;            }            ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,                           "SSL buf copy: %d", size);            ngx_memcpy(buf->last, in->buf->pos, size);            buf->last += size;            in->buf->pos += size;            if (in->buf->pos == in->buf->last) {                in = in->next;            }        }        size = buf->last - buf->pos;        if (!flush && buf->last < buf->end && c->ssl->buffer) {            break;        }        n = ngx_ssl_write(c, buf->pos, size);        if (n == NGX_ERROR) {            return NGX_CHAIN_ERROR;        }        if (n == NGX_AGAIN) {            c->buffered |= NGX_SSL_BUFFERED;            return in;        }        buf->pos += n;        send += n;        c->sent += n;        if (n < size) {            break;        }        if (buf->pos == buf->last) {            buf->pos = buf->start;            buf->last = buf->start;        }        if (in == NULL || send == limit) {            break;        }    }    if (buf->pos < buf->last) {        c->buffered |= NGX_SSL_BUFFERED;    } else {        c->buffered &= ~NGX_SSL_BUFFERED;    }    return in;}ssize_tngx_ssl_write(ngx_connection_t *c, u_char *data, size_t size){    int        n, sslerr;    ngx_err_t  err;    ngx_ssl_clear_error(c->log);    ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL to write: %d", size);    n = SSL_write(c->ssl->connection, data, size);    ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_write: %d", n);    if (n > 0) {        if (c->ssl->saved_read_handler) {            c->read->handler = c->ssl->saved_read_handler;            c->ssl->saved_read_handler = NULL;            c->read->ready = 1;            if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) {                return NGX_ERROR;            }            ngx_post_event(c->read, &ngx_posted_events);        }        return n;    }    sslerr = SSL_get_error(c->ssl->connection, n);    err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;    ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", sslerr);    if (sslerr == SSL_ERROR_WANT_WRITE) {        c->write->ready = 0;        return NGX_AGAIN;    }    if (sslerr == SSL_ERROR_WANT_READ) {        ngx_log_error(NGX_LOG_INFO, c->log, 0,                      "peer started SSL renegotiation");        c->read->ready = 0;        if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) {            return NGX_ERROR;        }        /*         * we do not set the timer because there is already         * the write event timer         */        if (c->ssl->saved_read_handler == NULL) {            c->ssl->saved_read_handler = c->read->handler;            c->read->handler = ngx_ssl_read_handler;        }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?