@@ -140,6 +140,7 @@ class Client {
140
140
* allowing access to the sent Request data even after the connection has been closed.
141
141
*/
142
142
String *tmp_write_buffer = nullptr ;
143
+ std::shared_ptr<String> frame_buffer;
143
144
bool connection_close = false ;
144
145
bool completed = false ;
145
146
bool event_stream = false ;
@@ -204,7 +205,10 @@ class Client {
204
205
void recv_websocket_frame (zval *return_value, double timeout = 0 );
205
206
void add_header (const char *key, size_t key_len, const char *str, size_t length) const ;
206
207
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);
208
212
bool close (bool should_be_reset = true );
209
213
void socket_dtor ();
210
214
@@ -326,6 +330,8 @@ static PHP_METHOD(swoole_http_client_coro, upgrade);
326
330
static PHP_METHOD (swoole_http_client_coro, push);
327
331
static PHP_METHOD (swoole_http_client_coro, recv);
328
332
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);
329
335
SW_EXTERN_C_END
330
336
331
337
// clang-format off
@@ -361,6 +367,8 @@ static const zend_function_entry swoole_http_client_coro_methods[] =
361
367
PHP_ME (swoole_http_client_coro, push, arginfo_class_Swoole_Coroutine_Http_Client_push, ZEND_ACC_PUBLIC)
362
368
PHP_ME (swoole_http_client_coro, recv, arginfo_class_Swoole_Coroutine_Http_Client_recv, ZEND_ACC_PUBLIC)
363
369
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)
364
372
PHP_FE_END
365
373
};
366
374
@@ -1524,9 +1532,21 @@ bool Client::recv_response(double timeout) {
1524
1532
}
1525
1533
1526
1534
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);
1528
1536
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);
1530
1550
}
1531
1551
}
1532
1552
@@ -1551,7 +1571,7 @@ bool Client::upgrade(const std::string &path) {
1551
1571
return exec (path);
1552
1572
}
1553
1573
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 ) {
1555
1575
if (sw_unlikely (!websocket)) {
1556
1576
swoole_set_last_error (SW_ERROR_WEBSOCKET_HANDSHAKE_FAILED);
1557
1577
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) {
1567
1587
1568
1588
String *buffer = socket->get_write_buffer ();
1569
1589
1570
- FrameObject frame (zdata, opcode, flags);
1590
+ FrameObject frame (zdata, opcode, flags, code );
1571
1591
1572
1592
if (websocket_settings.mask ) {
1573
1593
frame.flags |= WebSocket::FLAG_MASK;
@@ -1591,9 +1611,9 @@ bool Client::push(zval *zdata, zend_long opcode, uint8_t flags) {
1591
1611
zend::object_set (zobject, ZEND_STRL (" statusCode" ), HTTP_ESTATUS_SERVER_RESET);
1592
1612
close ();
1593
1613
return false ;
1614
+ } else {
1615
+ return true ;
1594
1616
}
1595
-
1596
- return true ;
1597
1617
}
1598
1618
1599
1619
void Client::reset () {
@@ -2188,3 +2208,43 @@ static PHP_METHOD(swoole_http_client_coro, getPeerCert) {
2188
2208
phc->getpeercert (return_value);
2189
2209
}
2190
2210
#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