Skip to content

Commit 7c6764d

Browse files
authored
Optimize ReactorPoll to pass all unit tests (#5792)
1 parent e87afd4 commit 7c6764d

File tree

14 files changed

+193
-160
lines changed

14 files changed

+193
-160
lines changed

ext-src/swoole_http_client_coro.cc

Lines changed: 58 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ class Client {
8787
std::string basic_auth;
8888

8989
/* for response parser */
90-
char *tmp_header_field_name = nullptr;
90+
const char *tmp_header_field_name = nullptr;
9191
int tmp_header_field_name_len = 0;
9292
String *body = nullptr;
9393
#ifdef SW_HAVE_COMPRESSION
@@ -119,12 +119,16 @@ class Client {
119119
zval *zobject = &_zobject;
120120
zval zsocket;
121121
zend::Callable *write_func = nullptr;
122+
/**
123+
* Retain the send buffer object of the Socket after the Socket object is destroyed,
124+
* allowing access to the sent Request data even after the connection has been closed.
125+
*/
122126
String *tmp_write_buffer = nullptr;
123127
bool connection_close = false;
124128

125-
Client(zval *zobject, std::string host, zend_long port = 80, zend_bool ssl = false);
129+
Client(const zval *zobject, const std::string &host, zend_long port = 80, zend_bool ssl = false);
126130

127-
bool is_available() {
131+
bool is_available() const {
128132
if (sw_unlikely(!socket || !socket->is_connected())) {
129133
php_swoole_socket_set_error_properties(zobject, SW_ERROR_CLIENT_NO_CONNECTION);
130134
return false;
@@ -143,9 +147,8 @@ class Client {
143147
#ifdef SW_HAVE_ZSTD
144148
ZSTD_DStream *zstd_stream = nullptr;
145149
#endif
146-
bool bind(std::string address, int port = 0);
147150
bool connect();
148-
void set_error(int error, const char *msg, int status);
151+
void set_error(int error, const char *msg, int status) const;
149152
bool keep_liveness();
150153
bool send_request();
151154
void reset();
@@ -165,10 +168,9 @@ class Client {
165168

166169
static void create_token(int length, char *buf) {
167170
char characters[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!\"§$%&/()=[]{}";
168-
int i;
169171
assert(length < 1024);
170-
for (i = 0; i < length; i++) {
171-
buf[i] = characters[rand() % (sizeof(characters) - 1)];
172+
for (int i = 0; i < length; i++) {
173+
buf[i] = characters[swoole_random_int() % (sizeof(characters) - 1)];
172174
}
173175
buf[length] = '\0';
174176
}
@@ -177,23 +179,21 @@ class Client {
177179
#ifdef SW_HAVE_COMPRESSION
178180
bool decompress_response(const char *in, size_t in_len);
179181
#endif
180-
void apply_setting(zval *zset, const bool check_all = true);
182+
void apply_setting(zval *zset, bool check_all = true);
181183
void set_basic_auth(const std::string &username, const std::string &password);
182-
bool exec(std::string _path);
184+
bool exec(const std::string &_path);
183185
bool recv_response(double timeout = 0);
184186
bool recv_websocket_frame(zval *zframe, double timeout = 0);
185-
void add_header(const char *key, size_t key_len, const char *str, size_t length);
186-
bool upgrade(std::string path);
187+
void add_header(const char *key, size_t key_len, const char *str, size_t length) const;
188+
bool upgrade(const std::string &path);
187189
bool push(zval *zdata, zend_long opcode = websocket::OPCODE_TEXT, uint8_t flags = websocket::FLAG_FIN);
188-
bool close(const bool should_be_reset = true);
190+
bool close(bool should_be_reset = true);
189191
void socket_dtor();
190192

191193
void get_header_out(zval *return_value) {
192194
String *buffer = nullptr;
193195
if (socket == nullptr) {
194-
if (tmp_write_buffer) {
195-
buffer = tmp_write_buffer;
196-
}
196+
buffer = tmp_write_buffer;
197197
} else {
198198
buffer = socket->get_write_buffer();
199199
}
@@ -384,17 +384,17 @@ void php_swoole_http_parse_set_cookies(const char *at, size_t length, zval *zcoo
384384
}
385385

386386
static int http_parser_on_header_field(swoole_http_parser *parser, const char *at, size_t length) {
387-
Client *http = (Client *) parser->data;
388-
http->tmp_header_field_name = (char *) at;
387+
auto *http = static_cast<Client *>(parser->data);
388+
http->tmp_header_field_name = at;
389389
http->tmp_header_field_name_len = length;
390390
return 0;
391391
}
392392

393393
static int http_parser_on_header_value(swoole_http_parser *parser, const char *at, size_t length) {
394-
Client *http = (Client *) parser->data;
394+
auto *http = static_cast<Client *>(parser->data);
395395
zval *zobject = (zval *) http->zobject;
396396

397-
char *header_name = http->tmp_header_field_name;
397+
const char *header_name = http->tmp_header_field_name;
398398
size_t header_len = http->tmp_header_field_name_len;
399399
zend::CharPtr _header_name;
400400

@@ -428,7 +428,7 @@ static int http_parser_on_header_value(swoole_http_parser *parser, const char *a
428428
}
429429
#ifdef SW_HAVE_COMPRESSION
430430
else if (SW_STREQ(header_name, header_len, "content-encoding")) {
431-
if (0) {
431+
if (false) {
432432
}
433433
#ifdef SW_HAVE_BROTLI
434434
else if (SW_STR_ISTARTS_WITH(at, length, "br")) {
@@ -459,7 +459,7 @@ static int http_parser_on_header_value(swoole_http_parser *parser, const char *a
459459
}
460460

461461
static int http_parser_on_headers_complete(swoole_http_parser *parser) {
462-
Client *http = (Client *) parser->data;
462+
auto *http = static_cast<Client *>(parser->data);
463463
if (http->method == SW_HTTP_HEAD || parser->status_code == SW_HTTP_NO_CONTENT) {
464464
return 1;
465465
}
@@ -475,7 +475,7 @@ static inline ssize_t http_client_co_write(int sockfd, const void *buf, size_t c
475475
}
476476

477477
static int http_parser_on_body(swoole_http_parser *parser, const char *at, size_t length) {
478-
Client *http = (Client *) parser->data;
478+
auto *http = static_cast<Client *>(parser->data);
479479
if (http->write_func) {
480480
zval zargv[2];
481481
zargv[0] = *http->zobject;
@@ -533,8 +533,8 @@ static int http_parser_on_body(swoole_http_parser *parser, const char *at, size_
533533
}
534534

535535
static int http_parser_on_message_complete(swoole_http_parser *parser) {
536-
Client *http = (Client *) parser->data;
537-
zval *zobject = (zval *) http->zobject;
536+
auto *http = static_cast<Client *>(parser->data);
537+
const zval *zobject = http->zobject;
538538

539539
if (parser->upgrade && !http->websocket) {
540540
// not support, continue.
@@ -559,9 +559,9 @@ static int http_parser_on_message_complete(swoole_http_parser *parser) {
559559
}
560560
}
561561

562-
Client::Client(zval *zobject, std::string host, zend_long port, zend_bool ssl) {
563-
this->socket_type = network::Socket::convert_to_type(host);
562+
Client::Client(const zval *zobject, const std::string &host, zend_long port, zend_bool ssl) {
564563
this->host = host;
564+
this->socket_type = network::Socket::convert_to_type(this->host);
565565
this->use_default_port = port == 0;
566566
if (this->use_default_port) {
567567
port = ssl ? 443 : 80;
@@ -609,7 +609,7 @@ bool Client::decompress_response(const char *in, size_t in_len) {
609609
gzip_stream.avail_in = in_len;
610610
gzip_stream.total_in = 0;
611611

612-
while (1) {
612+
while (true) {
613613
total_out = gzip_stream.total_out;
614614
gzip_stream.avail_out = body->size - body->length;
615615
gzip_stream.next_out = (Bytef *) (body->str + body->length);
@@ -657,7 +657,7 @@ bool Client::decompress_response(const char *in, size_t in_len) {
657657

658658
const char *next_in = in;
659659
size_t available_in = in_len;
660-
while (1) {
660+
while (true) {
661661
size_t available_out = body->size - body->length, reserved_available_out = available_out;
662662
char *next_out = body->str + body->length;
663663
size_t total_out;
@@ -780,9 +780,7 @@ void Client::apply_setting(zval *zset, const bool check_all) {
780780
}
781781
#endif
782782
if (php_swoole_array_get_value(vht, "write_func", ztmp)) {
783-
if (write_func) {
784-
delete write_func;
785-
}
783+
delete write_func;
786784
write_func = sw_callable_create(ztmp);
787785
}
788786
}
@@ -811,7 +809,7 @@ void Client::set_basic_auth(const std::string &username, const std::string &pass
811809
}
812810
}
813811

814-
void Client::add_header(const char *key, size_t key_len, const char *str, size_t length) {
812+
void Client::add_header(const char *key, size_t key_len, const char *str, size_t length) const {
815813
zval *zheaders =
816814
sw_zend_read_and_convert_property_array(swoole_http_client_coro_ce, zobject, ZEND_STRL("headers"), 0);
817815

@@ -863,7 +861,7 @@ bool Client::connect() {
863861
socket->set_timeout(_timeout, Socket::TIMEOUT_CONNECT);
864862
socket->set_resolve_context(&resolve_context_);
865863
socket->set_dtor([this](Socket *_socket) { socket_dtor(); });
866-
// socket->set_buffer_allocator(&SWOOLE_G(zend_string_allocator));
864+
socket->set_buffer_allocator(sw_zend_string_allocator());
867865

868866
if (!socket->connect(host, port)) {
869867
set_error(socket->errCode, socket->errMsg, HTTP_ESTATUS_CONNECT_FAILED);
@@ -876,7 +874,7 @@ bool Client::connect() {
876874
return true;
877875
}
878876

879-
void Client::set_error(int error, const char *msg, int status) {
877+
void Client::set_error(int error, const char *msg, int status) const {
880878
auto ce = swoole_http_client_coro_ce;
881879
auto obj = SW_Z8_OBJ_P(zobject);
882880
zend_update_property_long(ce, obj, ZEND_STRL("errCode"), error);
@@ -907,7 +905,7 @@ bool Client::send_request() {
907905
uint32_t header_flag = 0x0;
908906
zval *zmethod, *zheaders, *zbody, *zupload_files, *zcookies, *z_download_file;
909907

910-
if (path.length() == 0) {
908+
if (path.empty()) {
911909
php_swoole_socket_set_error_properties(zobject, SW_ERROR_INVALID_PARAMS);
912910
return false;
913911
}
@@ -1071,7 +1069,7 @@ bool Client::send_request() {
10711069
if (SW_STRCASEEQ(key, keylen, "Connection")) {
10721070
header_flag |= HTTP_HEADER_CONNECTION;
10731071
if (SW_STRCASEEQ(str_value.val(), str_value.len(), "close")) {
1074-
keep_alive = 0;
1072+
keep_alive = false;
10751073
}
10761074
}
10771075
}
@@ -1196,16 +1194,16 @@ bool Client::send_request() {
11961194
// upload files
11971195
SW_HASHTABLE_FOREACH_START2(Z_ARRVAL_P(zupload_files), key, keylen, keytype, zvalue) {
11981196
HashTable *ht = Z_ARRVAL_P(zvalue);
1199-
if (!(zname = zend_hash_str_find(ht, ZEND_STRL("name")))) {
1197+
if (!((zname = zend_hash_str_find(ht, ZEND_STRL("name"))))) {
12001198
continue;
12011199
}
1202-
if (!(zfilename = zend_hash_str_find(ht, ZEND_STRL("filename")))) {
1200+
if (!((zfilename = zend_hash_str_find(ht, ZEND_STRL("filename"))))) {
12031201
continue;
12041202
}
1205-
if (!(zsize = zend_hash_str_find(ht, ZEND_STRL("size")))) {
1203+
if (!((zsize = zend_hash_str_find(ht, ZEND_STRL("size"))))) {
12061204
continue;
12071205
}
1208-
if (!(ztype = zend_hash_str_find(ht, ZEND_STRL("type")))) {
1206+
if (!((ztype = zend_hash_str_find(ht, ZEND_STRL("type"))))) {
12091207
continue;
12101208
}
12111209
// strlen("%.*s")*4 = 16
@@ -1383,7 +1381,7 @@ bool Client::send_request() {
13831381
return true;
13841382
}
13851383

1386-
bool Client::exec(std::string _path) {
1384+
bool Client::exec(const std::string &_path) {
13871385
path = _path;
13881386
// bzero when make a new reqeust
13891387
resolve_context_ = {};
@@ -1504,7 +1502,7 @@ bool Client::recv_response(double timeout) {
15041502
* TODO: Sec-WebSocket-Accept check
15051503
*/
15061504
if (websocket) {
1507-
socket->open_length_check = 1;
1505+
socket->open_length_check = true;
15081506
socket->protocol.package_length_size = SW_WEBSOCKET_HEADER_LEN;
15091507
socket->protocol.package_length_offset = 0;
15101508
socket->protocol.package_body_offset = 0;
@@ -1546,22 +1544,22 @@ bool Client::recv_websocket_frame(zval *zframe, double timeout) {
15461544
}
15471545
}
15481546

1549-
bool Client::upgrade(std::string path) {
1547+
bool Client::upgrade(const std::string &path) {
15501548
defer = false;
15511549
char buf[SW_WEBSOCKET_KEY_LENGTH + 1];
15521550
zval *zheaders =
15531551
sw_zend_read_and_convert_property_array(swoole_http_client_coro_ce, zobject, ZEND_STRL("requestHeaders"), 0);
15541552
zend_update_property_string(swoole_http_client_coro_ce, SW_Z8_OBJ_P(zobject), ZEND_STRL("requestMethod"), "GET");
15551553
create_token(SW_WEBSOCKET_KEY_LENGTH, buf);
1556-
add_assoc_string(zheaders, "Connection", (char *) "Upgrade");
1557-
add_assoc_string(zheaders, "Upgrade", (char *) "websocket");
1558-
add_assoc_string(zheaders, "Sec-WebSocket-Version", (char *) SW_WEBSOCKET_VERSION);
1554+
add_assoc_string(zheaders, "Connection", "Upgrade");
1555+
add_assoc_string(zheaders, "Upgrade", "websocket");
1556+
add_assoc_string(zheaders, "Sec-WebSocket-Version", SW_WEBSOCKET_VERSION);
15591557
add_assoc_str_ex(zheaders,
15601558
ZEND_STRL("Sec-WebSocket-Key"),
15611559
php_base64_encode((const unsigned char *) buf, SW_WEBSOCKET_KEY_LENGTH));
15621560
#ifdef SW_HAVE_ZLIB
15631561
if (websocket_compression) {
1564-
add_assoc_string(zheaders, "Sec-Websocket-Extensions", (char *) SW_WEBSOCKET_EXTENSION_DEFLATE);
1562+
add_assoc_string(zheaders, "Sec-Websocket-Extensions", SW_WEBSOCKET_EXTENSION_DEFLATE);
15651563
}
15661564
#endif
15671565
return exec(path);
@@ -1640,13 +1638,11 @@ void Client::reset() {
16401638
}
16411639

16421640
void Client::socket_dtor() {
1643-
zend_update_property_bool(Z_OBJCE_P(zobject), SW_Z8_OBJ_P(zobject), ZEND_STRL("connected"), 0);
1644-
zend_update_property_null(Z_OBJCE_P(zobject), SW_Z8_OBJ_P(zobject), ZEND_STRL("socket"));
1645-
if (tmp_write_buffer) {
1646-
delete tmp_write_buffer;
1647-
}
1641+
delete tmp_write_buffer;
16481642
tmp_write_buffer = socket->pop_write_buffer();
16491643
socket = nullptr;
1644+
zend_update_property_bool(Z_OBJCE_P(zobject), SW_Z8_OBJ_P(zobject), ZEND_STRL("connected"), 0);
1645+
zend_update_property_null(Z_OBJCE_P(zobject), SW_Z8_OBJ_P(zobject), ZEND_STRL("socket"));
16501646
zval_ptr_dtor(&zsocket);
16511647
ZVAL_NULL(&zsocket);
16521648
}
@@ -1678,22 +1674,17 @@ bool Client::close(const bool should_be_reset) {
16781674

16791675
Client::~Client() {
16801676
close();
1681-
if (body) {
1682-
delete body;
1683-
}
1684-
if (tmp_write_buffer) {
1685-
delete tmp_write_buffer;
1686-
}
1687-
if (write_func) {
1688-
delete write_func;
1689-
}
1677+
delete body;
1678+
delete tmp_write_buffer;
1679+
delete write_func;
16901680
}
16911681

16921682
static sw_inline HttpClientObject *http_client_coro_fetch_object(zend_object *obj) {
1693-
return (HttpClientObject *) ((char *) obj - swoole_http_client_coro_handlers.offset);
1683+
return reinterpret_cast<HttpClientObject *>(reinterpret_cast<char *>(obj) -
1684+
swoole_http_client_coro_handlers.offset);
16941685
}
16951686

1696-
static sw_inline Client *http_client_coro_get_client(zval *zobject) {
1687+
static sw_inline Client *http_client_coro_get_client(const zval *zobject) {
16971688
Client *phc = http_client_coro_fetch_object(Z_OBJ_P(zobject))->client;
16981689
if (UNEXPECTED(!phc)) {
16991690
swoole_fatal_error(SW_ERROR_WRONG_OPERATION, "must call constructor first");
@@ -1711,7 +1702,7 @@ static void http_client_coro_free_object(zend_object *object) {
17111702
}
17121703

17131704
static zend_object *http_client_coro_create_object(zend_class_entry *ce) {
1714-
HttpClientObject *hcc = (HttpClientObject *) zend_object_alloc(sizeof(HttpClientObject), ce);
1705+
auto *hcc = (HttpClientObject *) zend_object_alloc(sizeof(HttpClientObject), ce);
17151706
zend_object_std_init(&hcc->std, ce);
17161707
object_properties_init(&hcc->std, ce);
17171708
hcc->std.handlers = &swoole_http_client_coro_handlers;
@@ -1782,7 +1773,7 @@ static PHP_METHOD(swoole_http_client_coro, __construct) {
17821773
char *host;
17831774
size_t host_len;
17841775
zend_long port = 0;
1785-
zend_bool ssl = 0;
1776+
zend_bool ssl = false;
17861777

17871778
ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_THROW, 1, 3)
17881779
Z_PARAM_STRING(host, host_len)
@@ -1841,7 +1832,7 @@ static PHP_METHOD(swoole_http_client_coro, getDefer) {
18411832

18421833
static PHP_METHOD(swoole_http_client_coro, setDefer) {
18431834
Client *phc = http_client_coro_get_client(ZEND_THIS);
1844-
zend_bool defer = 1;
1835+
zend_bool defer = true;
18451836

18461837
ZEND_PARSE_PARAMETERS_START(0, 1)
18471838
Z_PARAM_OPTIONAL

include/swoole_reactor.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,10 @@ class Reactor {
261261
return !_socket->removed && _socket->events;
262262
}
263263

264+
bool exists(const int fd) const {
265+
return sockets_.find(fd) != sockets_.end();
266+
}
267+
264268
int get_timeout_msec() const {
265269
return defer_tasks == nullptr ? timeout_msec : 0;
266270
}

src/coroutine/socket.cc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1630,6 +1630,9 @@ Socket::~Socket() {
16301630
SW_ASSERT(!has_bound() && socket->removed);
16311631
}
16321632
#endif
1633+
if (dtor_ != nullptr) {
1634+
dtor_(this);
1635+
}
16331636
delete read_buffer;
16341637
delete write_buffer;
16351638
if (socket == nullptr) {
@@ -1639,9 +1642,6 @@ Socket::~Socket() {
16391642
#ifdef SW_USE_OPENSSL
16401643
ssl_shutdown();
16411644
#endif
1642-
if (dtor_ != nullptr) {
1643-
dtor_(this);
1644-
}
16451645
socket->free();
16461646
}
16471647

0 commit comments

Comments
 (0)