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 + -
显示快捷键?