Skip to content

Commit f9bc330

Browse files
optimize websocket continue frame (#5861)
* optimize websocket continue frame * optimize code * add test * send close frame and close connection * fix code * optimize code * optimize code
1 parent 6a1b960 commit f9bc330

32 files changed

+1201
-105
lines changed

ext-src/php_swoole_http.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ struct Context {
168168
std::shared_ptr<String> zlib_buffer;
169169
#endif
170170

171+
std::shared_ptr<String> frame_buffer;
171172
WebSocketSettings websocket_settings;
172173

173174
Request request;

ext-src/php_swoole_websocket.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,14 @@
2222

2323
#include "swoole_websocket.h"
2424

25+
#define SW_WEBSOCKET_DEFAULT_BUFFER 4096
26+
2527
void swoole_websocket_apply_setting(swoole::WebSocketSettings &settings, zend_array *vht, bool in_server);
2628
void swoole_websocket_recv_frame(const swoole::WebSocketSettings &settings,
27-
swoole::coroutine::Socket *sock,
28-
zval *return_value,
29-
double timeout);
29+
std::shared_ptr<swoole::String> &frame_buffer,
30+
swoole::coroutine::Socket *sock,
31+
zval *return_value,
32+
double timeout);
3033
ssize_t swoole_websocket_send_frame(const swoole::WebSocketSettings &settings,
3134
swoole::coroutine::Socket *sock,
3235
uchar opcode,
@@ -48,7 +51,7 @@ struct FrameObject {
4851
uint16_t code;
4952
zval *data;
5053

51-
FrameObject(zval *data, zend_long _opcode = 0, zend_long _flags = 0);
54+
FrameObject(zval *data, zend_long _opcode = 0, zend_long _flags = 0, zend_long _code = 0);
5255
size_t get_data_size() {
5356
return (data && ZVAL_IS_STRING(data)) ? Z_STRLEN_P(data) : 0;
5457
}

ext-src/stubs/php_swoole_http_client_coro.stub.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,4 +68,8 @@ public function push(mixed $data, int $opcode = SWOOLE_WEBSOCKET_OPCODE_TEXT, in
6868
public function recv(float $timeout = 0): bool|\Swoole\WebSocket\Frame|string {}
6969

7070
public function close(): bool {}
71+
72+
public function ping(string $data = ""): bool {}
73+
74+
public function disconnect(int $code = SWOOLE_WEBSOCKET_CLOSE_NORMAL, string $reason = ""): bool {}
7175
}

ext-src/stubs/php_swoole_http_client_coro_arginfo.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* This is a generated file, edit the .stub.php file instead.
2-
* Stub hash: 28dc018fd61b650e58652c1c6515521ae3f7ae4c */
2+
* Stub hash: 0a2812dfe8710fd837631eac1b134656bf0f7487 */
33

44
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Swoole_Coroutine_Http_Client___construct, 0, 0, 1)
55
ZEND_ARG_TYPE_INFO(0, host, IS_STRING, 0)
@@ -112,3 +112,12 @@ ZEND_END_ARG_INFO()
112112

113113
#define arginfo_class_Swoole_Coroutine_Http_Client_close arginfo_class_Swoole_Coroutine_Http_Client_getDefer
114114

115+
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Swoole_Coroutine_Http_Client_ping, 0, 0, _IS_BOOL, 0)
116+
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, data, IS_STRING, 0, "\"\"")
117+
ZEND_END_ARG_INFO()
118+
119+
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Swoole_Coroutine_Http_Client_disconnect, 0, 0, _IS_BOOL, 0)
120+
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, code, IS_LONG, 0, "SWOOLE_WEBSOCKET_CLOSE_NORMAL")
121+
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, reason, IS_STRING, 0, "\"\"")
122+
ZEND_END_ARG_INFO()
123+

ext-src/stubs/php_swoole_http_response.stub.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,10 @@ public function push(\Swoole\WebSocket\Frame|string $data, int $opcode = SWOOLE_
1717
public function recv(float $timeout = 0): \Swoole\WebSocket\Frame|false|string {}
1818
public function close(): bool {}
1919
public function trailer(string $key, string $value): bool {}
20-
public function ping(): bool {}
20+
public function ping(string $data = ''): bool {}
2121
public function goaway(int $error_code = SWOOLE_HTTP2_ERROR_NO_ERROR, string $debug_data = ''): bool {}
2222
public function status(int $http_code, string $reason = ''): bool {}
23+
public function disconnect(int $code = SWOOLE_WEBSOCKET_CLOSE_NORMAL, string $reason = ""): bool {}
2324
public function __destruct() {}
2425
}
2526
}

ext-src/stubs/php_swoole_http_response_arginfo.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* This is a generated file, edit the .stub.php file instead.
2-
* Stub hash: 8797137fe315a9dec64e349bad8bd72529895bf9 */
2+
* Stub hash: 1a9de3282e3f5ad468a56ef68064dd824b21ad58 */
33

44
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Swoole_Http_Response_write, 0, 1, _IS_BOOL, 0)
55
ZEND_ARG_TYPE_INFO(0, content, IS_STRING, 0)
@@ -83,7 +83,9 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Swoole_Http_Response_trail
8383
ZEND_ARG_TYPE_INFO(0, value, IS_STRING, 0)
8484
ZEND_END_ARG_INFO()
8585

86-
#define arginfo_class_Swoole_Http_Response_ping arginfo_class_Swoole_Http_Response_initHeader
86+
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Swoole_Http_Response_ping, 0, 0, _IS_BOOL, 0)
87+
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, data, IS_STRING, 0, "\'\'")
88+
ZEND_END_ARG_INFO()
8789

8890
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Swoole_Http_Response_goaway, 0, 0, _IS_BOOL, 0)
8991
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, error_code, IS_LONG, 0, "SWOOLE_HTTP2_ERROR_NO_ERROR")
@@ -95,5 +97,11 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Swoole_Http_Response_statu
9597
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, reason, IS_STRING, 0, "\'\'")
9698
ZEND_END_ARG_INFO()
9799

100+
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Swoole_Http_Response_disconnect, 0, 0, _IS_BOOL, 0)
101+
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, code, IS_LONG, 0, "SWOOLE_WEBSOCKET_CLOSE_NORMAL")
102+
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, reason, IS_STRING, 0, "\"\"")
103+
ZEND_END_ARG_INFO()
104+
98105
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Swoole_Http_Response___destruct, 0, 0, 0)
99106
ZEND_END_ARG_INFO()
107+

ext-src/stubs/php_swoole_websocket.stub.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ public function isEstablished(int $fd): bool {}
66
public static function pack(\Swoole\WebSocket\Frame|string $data, int $opcode = WEBSOCKET_OPCODE_TEXT, int $flags = SWOOLE_WEBSOCKET_FLAG_FIN): string {}
77
public static function unpack(string $data): \Swoole\WebSocket\Frame {}
88
public function disconnect(int $fd, int $code = SWOOLE_WEBSOCKET_CLOSE_NORMAL, string $reason = ""): bool {}
9+
public function ping(int $fd, string $data = ""): bool {}
910
}
1011

1112
class Frame {

ext-src/stubs/php_swoole_websocket_arginfo.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* This is a generated file, edit the .stub.php file instead.
2-
* Stub hash: d65d6116461119fccd59f50c68d941aaece8b63b */
2+
* Stub hash: d7b75f2efbda42013e5b8a83aa0dab8ab761e127 */
33

44
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Swoole_WebSocket_Server_push, 0, 2, _IS_BOOL, 0)
55
ZEND_ARG_TYPE_INFO(0, fd, IS_LONG, 0)
@@ -28,9 +28,15 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Swoole_WebSocket_Server_di
2828
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, reason, IS_STRING, 0, "\"\"")
2929
ZEND_END_ARG_INFO()
3030

31+
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Swoole_WebSocket_Server_ping, 0, 1, _IS_BOOL, 0)
32+
ZEND_ARG_TYPE_INFO(0, fd, IS_LONG, 0)
33+
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, data, IS_STRING, 0, "\"\"")
34+
ZEND_END_ARG_INFO()
35+
3136
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Swoole_WebSocket_Frame___toString, 0, 0, IS_STRING, 0)
3237
ZEND_END_ARG_INFO()
3338

3439
#define arginfo_class_Swoole_WebSocket_Frame_pack arginfo_class_Swoole_WebSocket_Server_pack
3540

3641
#define arginfo_class_Swoole_WebSocket_Frame_unpack arginfo_class_Swoole_WebSocket_Server_unpack
42+

ext-src/swoole_http_client_coro.cc

Lines changed: 67 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ class Client {
140140
* allowing access to the sent Request data even after the connection has been closed.
141141
*/
142142
String *tmp_write_buffer = nullptr;
143+
std::shared_ptr<String> frame_buffer;
143144
bool connection_close = false;
144145
bool completed = false;
145146
bool event_stream = false;
@@ -204,7 +205,10 @@ class Client {
204205
void recv_websocket_frame(zval *return_value, double timeout = 0);
205206
void add_header(const char *key, size_t key_len, const char *str, size_t length) const;
206207
bool upgrade(const std::string &path);
207-
bool push(zval *zdata, zend_long opcode = websocket::OPCODE_TEXT, uint8_t flags = websocket::FLAG_FIN);
208+
bool push(zval *zdata,
209+
zend_long opcode = websocket::OPCODE_TEXT,
210+
uint8_t flags = websocket::FLAG_FIN,
211+
zend_long code = websocket::CLOSE_NORMAL);
208212
bool close(bool should_be_reset = true);
209213
void socket_dtor();
210214

@@ -326,6 +330,8 @@ static PHP_METHOD(swoole_http_client_coro, upgrade);
326330
static PHP_METHOD(swoole_http_client_coro, push);
327331
static PHP_METHOD(swoole_http_client_coro, recv);
328332
static PHP_METHOD(swoole_http_client_coro, close);
333+
static PHP_METHOD(swoole_http_client_coro, ping);
334+
static PHP_METHOD(swoole_http_client_coro, disconnect);
329335
SW_EXTERN_C_END
330336

331337
// clang-format off
@@ -361,6 +367,8 @@ static const zend_function_entry swoole_http_client_coro_methods[] =
361367
PHP_ME(swoole_http_client_coro, push, arginfo_class_Swoole_Coroutine_Http_Client_push, ZEND_ACC_PUBLIC)
362368
PHP_ME(swoole_http_client_coro, recv, arginfo_class_Swoole_Coroutine_Http_Client_recv, ZEND_ACC_PUBLIC)
363369
PHP_ME(swoole_http_client_coro, close, arginfo_class_Swoole_Coroutine_Http_Client_close, ZEND_ACC_PUBLIC)
370+
PHP_ME(swoole_http_client_coro, ping, arginfo_class_Swoole_Coroutine_Http_Client_ping, ZEND_ACC_PUBLIC)
371+
PHP_ME(swoole_http_client_coro, disconnect, arginfo_class_Swoole_Coroutine_Http_Client_disconnect, ZEND_ACC_PUBLIC)
364372
PHP_FE_END
365373
};
366374

@@ -1524,9 +1532,21 @@ bool Client::recv_response(double timeout) {
15241532
}
15251533

15261534
void Client::recv_websocket_frame(zval *return_value, double timeout) {
1527-
swoole_websocket_recv_frame(websocket_settings, socket, return_value, timeout);
1535+
swoole_websocket_recv_frame(websocket_settings, frame_buffer, socket, return_value, timeout);
15281536
if (ZVAL_IS_EMPTY_STRING(return_value)) {
1529-
close();
1537+
close();
1538+
return;
1539+
}
1540+
if (sw_unlikely(ZVAL_IS_FALSE(return_value))) {
1541+
php_swoole_socket_set_error_properties(zobject, socket);
1542+
zend::object_set(zobject, ZEND_STRL("statusCode"), HTTP_ESTATUS_SERVER_RESET);
1543+
if (socket->errCode != ETIMEDOUT) {
1544+
close();
1545+
}
1546+
return;
1547+
}
1548+
if (sw_unlikely(ZVAL_IS_NULL(return_value))) {
1549+
ZVAL_FALSE(return_value);
15301550
}
15311551
}
15321552

@@ -1551,7 +1571,7 @@ bool Client::upgrade(const std::string &path) {
15511571
return exec(path);
15521572
}
15531573

1554-
bool Client::push(zval *zdata, zend_long opcode, uint8_t flags) {
1574+
bool Client::push(zval *zdata, zend_long opcode, uint8_t flags, zend_long code) {
15551575
if (sw_unlikely(!websocket)) {
15561576
swoole_set_last_error(SW_ERROR_WEBSOCKET_HANDSHAKE_FAILED);
15571577
php_swoole_fatal_error(E_WARNING, "websocket handshake failed, cannot push data");
@@ -1567,7 +1587,7 @@ bool Client::push(zval *zdata, zend_long opcode, uint8_t flags) {
15671587

15681588
String *buffer = socket->get_write_buffer();
15691589

1570-
FrameObject frame(zdata, opcode, flags);
1590+
FrameObject frame(zdata, opcode, flags, code);
15711591

15721592
if (websocket_settings.mask) {
15731593
frame.flags |= WebSocket::FLAG_MASK;
@@ -1591,9 +1611,9 @@ bool Client::push(zval *zdata, zend_long opcode, uint8_t flags) {
15911611
zend::object_set(zobject, ZEND_STRL("statusCode"), HTTP_ESTATUS_SERVER_RESET);
15921612
close();
15931613
return false;
1614+
} else {
1615+
return true;
15941616
}
1595-
1596-
return true;
15971617
}
15981618

15991619
void Client::reset() {
@@ -2188,3 +2208,43 @@ static PHP_METHOD(swoole_http_client_coro, getPeerCert) {
21882208
phc->getpeercert(return_value);
21892209
}
21902210
#endif
2211+
2212+
static PHP_METHOD(swoole_http_client_coro, ping) {
2213+
Client *phc = http_client_coro_get_client(ZEND_THIS);
2214+
if (!phc->is_available() || !phc->websocket) {
2215+
RETURN_FALSE;
2216+
}
2217+
2218+
zend_string *zdata = zend_empty_string;
2219+
2220+
ZEND_PARSE_PARAMETERS_START(0, 1)
2221+
Z_PARAM_OPTIONAL
2222+
Z_PARAM_STR(zdata)
2223+
ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
2224+
2225+
zval zpayload = {};
2226+
ZVAL_STR(&zpayload, zdata);
2227+
RETURN_BOOL(phc->push(&zpayload, WebSocket::OPCODE_PING, WebSocket::FLAG_FIN));
2228+
}
2229+
2230+
static PHP_METHOD(swoole_http_client_coro, disconnect) {
2231+
Client *phc = http_client_coro_get_client(ZEND_THIS);
2232+
if (!phc->is_available() || !phc->websocket) {
2233+
RETURN_FALSE;
2234+
}
2235+
2236+
zend_long code = WebSocket::CLOSE_NORMAL;
2237+
zend_string *reason = zend_empty_string;
2238+
2239+
ZEND_PARSE_PARAMETERS_START(0, 2)
2240+
Z_PARAM_OPTIONAL
2241+
Z_PARAM_LONG(code)
2242+
Z_PARAM_STR(reason)
2243+
ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
2244+
2245+
zval zpayload = {};
2246+
ZVAL_STR(&zpayload, reason);
2247+
2248+
RETVAL_BOOL(phc->push(&zpayload, WebSocket::OPCODE_CLOSE, WebSocket::FLAG_FIN, code));
2249+
phc->close(); // Regardless of the outcome, the connection will be closed.
2250+
}

0 commit comments

Comments
 (0)