diff --git a/README.md b/README.md index accd7b27..c464504d 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ int main() * This project supports `Linux`, `macOS`, `Windows`, `Android` and other operating systems. * `Windows` version is currently released as an independent [branch](https://github.com/sogou/workflow/tree/windows), using `iocp` to implement asynchronous networking. All user interfaces are consistent with the `Linux` version. * Supports all CPU platforms, including 32 or 64-bit `x86` processors, big-endian or little-endian `arm` processors, `loongson` processors. -* Master branch requires SSL and `OpenSSL 1.1` or above is recommended. Fully compatible with BoringSSL. If you don't like SSL, you may checkout the [nossl](https://github.com/sogou/workflow/tree/nossl) branch. +* Master branch requires `OpenSSL 1.1` or above, and BoringSSL is fully compatible. If you don't like SSL, you may checkout the [nossl](https://github.com/sogou/workflow/tree/nossl) branch. * Uses the `C++11` standard and therefore, it should be compiled with a compiler which supports `C++11`. Does not rely on `boost` or `asio`. * No other dependencies. However, if you need `Kafka` protocol, some compression libraries should be installed, including `lz4`, `zstd` and `snappy`. diff --git a/README_cn.md b/README_cn.md index 97b64af3..1a55a3f3 100644 --- a/README_cn.md +++ b/README_cn.md @@ -44,7 +44,7 @@ int main() * 项目支持``Linux``,``macOS``,``Windows``,``Android``等操作系统。 * ``Windows``版以[windows](https://github.com/sogou/workflow/tree/windows)分支发布,使用``iocp``实现异步网络。用户接口与``Linux``版一致。 * 支持所有CPU平台,包括32或64位``x86``处理器,大端或小端``arm``处理器,国产``loongson``龙芯处理器实测支持。 -* 需要依赖于``OpenSSL``,推荐``OpenSSL 1.1``及以上版本。 +* 需要依赖于``OpenSSL 1.1``或以上版本,也兼容BoringSSL。 * 不喜欢SSL的用户可以使用[nossl](https://github.com/sogou/workflow/tree/nossl)分支,代码更简洁。 * 项目使用了``C++11``标准,需要用支持``C++11``的编译器编译。但不依赖``boost``或``asio``。 * 项目无其它依赖。如需使用``kafka``协议,需自行安装``lz4``,``zstd``和``snappy``几个压缩库。 diff --git a/src/protocol/MySQLMessage.cc b/src/protocol/MySQLMessage.cc index 6e0e2179..8eaeeafc 100644 --- a/src/protocol/MySQLMessage.cc +++ b/src/protocol/MySQLMessage.cc @@ -542,7 +542,7 @@ int MySQLRSAAuthRequest::encode(struct iovec vectors[], int max) EVP_PKEY_CTX *pkey_ctx; int ret = -1; - bio = BIO_new_mem_buf((void *)public_key_.c_str(), public_key_.size()); + bio = BIO_new_mem_buf(public_key_.c_str(), public_key_.size()); if (bio) { pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL); diff --git a/src/protocol/SSLWrapper.cc b/src/protocol/SSLWrapper.cc new file mode 100644 index 00000000..f7a80474 --- /dev/null +++ b/src/protocol/SSLWrapper.cc @@ -0,0 +1,287 @@ +/* + Copyright (c) 2021 Sogou, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + Author: Xie Han (xiehan@sogou-inc.com) +*/ + +#include +#include +#include +#include +#include "SSLWrapper.h" + +namespace protocol +{ + +int SSLHandshaker::encode(struct iovec vectors[], int max) +{ + BIO *wbio = SSL_get_wbio(this->ssl); + char *ptr; + long len; + int ret; + + ret = SSL_do_handshake(this->ssl); + if (ret <= 0) + { + ret = SSL_get_error(this->ssl, ret); + if (ret != SSL_ERROR_WANT_READ) + { + if (ret != SSL_ERROR_SYSCALL) + errno = -ret; + + return -1; + } + } + + len = BIO_get_mem_data(wbio, &ptr); + if (len > 0) + { + vectors[0].iov_base = ptr; + vectors[0].iov_len = len; + return 1; + } + else if (len == 0) + return 0; + else + return -1; +} + +static int __ssl_handshake(const void *buf, size_t *size, SSL *ssl, + char **ptr, long *len) +{ + BIO *wbio = SSL_get_wbio(ssl); + BIO *rbio = SSL_get_rbio(ssl); + int ret; + + ret = BIO_write(rbio, buf, *size); + if (ret <= 0) + return -1; + + *size = ret; + ret = SSL_do_handshake(ssl); + if (ret <= 0) + { + ret = SSL_get_error(ssl, ret); + if (ret != SSL_ERROR_WANT_READ) + { + if (ret != SSL_ERROR_SYSCALL) + errno = -ret; + + return -1; + } + + ret = 0; + } + + *len = BIO_get_mem_data(wbio, ptr); + if (*len < 0) + return -1; + + return ret; +} + +int SSLHandshaker::append(const void *buf, size_t *size) +{ + BIO *wbio = SSL_get_wbio(this->ssl); + char *ptr; + long len; + long n; + int ret; + + BIO_reset(wbio); + ret = __ssl_handshake(buf, size, this->ssl, &ptr, &len); + if (ret != 0) + return ret; + + if (len > 0) + { + n = this->feedback(ptr, len); + BIO_reset(wbio); + } + else + n = 0; + + if (n == len) + return ret; + + if (n >= 0) + errno = ENOBUFS; + + return -1; +} + +int SSLWrapper::encode(struct iovec vectors[], int max) +{ + BIO *wbio = SSL_get_wbio(this->ssl); + struct iovec *iov; + char *ptr; + long len; + int ret; + + ret = this->ProtocolWrapper::encode(vectors, max); + if ((unsigned int)ret > (unsigned int)max) + return ret; + + max = ret; + for (iov = vectors; iov < vectors + max; iov++) + { + if (iov->iov_len > 0) + { + ret = SSL_write(this->ssl, iov->iov_base, iov->iov_len); + if (ret <= 0) + { + ret = SSL_get_error(this->ssl, ret); + if (ret != SSL_ERROR_SYSCALL) + errno = -ret; + + return -1; + } + } + } + + len = BIO_get_mem_data(wbio, &ptr); + if (len > 0) + { + vectors[0].iov_base = ptr; + vectors[0].iov_len = len; + return 1; + } + else if (len == 0) + return 0; + else + return -1; +} + +#define BUFSIZE 8192 + +int SSLWrapper::append_message() +{ + char buf[BUFSIZE]; + int ret; + + while ((ret = SSL_read(this->ssl, buf, BUFSIZE)) > 0) + { + size_t nleft = ret; + char *p = buf; + size_t n; + + do + { + n = nleft; + ret = this->ProtocolWrapper::append(p, &n); + if (ret == 0) + { + nleft -= n; + p += n; + } + else + return ret; + + } while (nleft > 0); + } + + ret = SSL_get_error(this->ssl, ret); + if (ret != SSL_ERROR_WANT_READ) + { + if (ret != SSL_ERROR_SYSCALL) + errno = -ret; + + return -1; + } + + return 0; +} + +int SSLWrapper::append(const void *buf, size_t *size) +{ + BIO *wbio = SSL_get_wbio(this->ssl); + BIO *rbio = SSL_get_rbio(this->ssl); + int ret; + + BIO_reset(wbio); + ret = BIO_write(rbio, buf, *size); + if (ret <= 0) + return -1; + + *size = ret; + return this->append_message(); +} + +int SSLWrapper::feedback(const void *buf, size_t size) +{ + BIO *wbio = SSL_get_wbio(this->ssl); + char *ptr; + long len; + long n; + int ret; + + if (size == 0) + return 0; + + ret = SSL_write(this->ssl, buf, size); + if (ret <= 0) + { + ret = SSL_get_error(this->ssl, ret); + if (ret != SSL_ERROR_SYSCALL) + errno = -ret; + + return -1; + } + + len = BIO_get_mem_data(wbio, &ptr); + if (len >= 0) + { + n = this->ProtocolWrapper::feedback(ptr, len); + BIO_reset(wbio); + if (n == len) + return size; + + if (ret > 0) + errno = ENOBUFS; + } + + return -1; +} + +int ServerSSLWrapper::append(const void *buf, size_t *size) +{ + BIO *wbio = SSL_get_wbio(this->ssl); + char *ptr; + long len; + long n; + + BIO_reset(wbio); + if (__ssl_handshake(buf, size, this->ssl, &ptr, &len) < 0) + return -1; + + if (len > 0) + { + n = this->ProtocolMessage::feedback(ptr, len); + BIO_reset(wbio); + } + else + n = 0; + + if (n == len) + return this->append_message(); + + if (n >= 0) + errno = ENOBUFS; + + return -1; +} + +} + diff --git a/src/server/WFServer.cc b/src/server/WFServer.cc index 73a2b9b2..0ba8fcad 100644 --- a/src/server/WFServer.cc +++ b/src/server/WFServer.cc @@ -114,18 +114,15 @@ int WFServerBase::create_listen_fd() WFConnection *WFServerBase::new_connection(int accept_fd) { - if (++this->conn_count <= this->params.max_connections || - this->drain(1) == 1) + if (++this->conn_count > this->params.max_connections && + this->drain(1) <= 0) { - int reuse = 1; - setsockopt(accept_fd, SOL_SOCKET, SO_REUSEADDR, - &reuse, sizeof (int)); - return new WFServerConnection(&this->conn_count); + this->conn_count--; + errno = EMFILE; + return NULL; } - this->conn_count--; - errno = EMFILE; - return NULL; + return new WFServerConnection(&this->conn_count); } void WFServerBase::delete_connection(WFConnection *conn) diff --git a/tutorial/tutorial-14-consul_cli.cc b/tutorial/tutorial-14-consul_cli.cc index 49cc973d..6674c950 100644 --- a/tutorial/tutorial-14-consul_cli.cc +++ b/tutorial/tutorial-14-consul_cli.cc @@ -158,9 +158,9 @@ void sig_handler(int signo) { } int main(int argc, char *argv[]) { - if (argc < 3) + if (argc != 3) { - fprintf(stderr, "USAGE: %s url type(discover/register/deregister)

\n", argv[0]); + fprintf(stderr, "USAGE: %s \n", argv[0]); exit(1); } @@ -213,7 +213,7 @@ int main(int argc, char *argv[]) } else { - fprintf(stderr, "USAGE: %s url

[compress_type/d]\n", argv[0]); + fprintf(stderr, "USAGE: %s \n", argv[0]); exit(1); }