Skip to content

Commit d0a9d10

Browse files
authored
optimize code (swoole#4015)
* optimize code * add http proxy tests * fix tests * fix tests[2]
1 parent b1a0dcc commit d0a9d10

File tree

6 files changed

+137
-38
lines changed

6 files changed

+137
-38
lines changed

core-tests/include/test_core.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
#define TEST_TMP_DIR "/tmp/swoole_core_test_dir"
2222
#define TEST_JPG_FILE "/examples/test.jpg"
2323
#define TEST_JPG_MD5SUM "64a42b4c0f3c65a14c23b60d3880a917"
24+
#define TEST_HTTP_PROXY_PORT 8888
25+
#define TEST_HTTP_PROXY_HOST "127.0.0.1"
2426

2527
#define ASSERT_MEMEQ(x,y,n) ASSERT_EQ(memcmp((x), (y), n), 0)
2628

core-tests/src/network/client.cpp

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,3 +205,84 @@ TEST(client, shutdown_all) {
205205
retval = cli.recv(&cli, buf, sizeof(buf), 0);
206206
ASSERT_EQ(retval, 0);
207207
}
208+
209+
#ifdef SW_USE_OPENSSL
210+
TEST(client, ssl_1) {
211+
int ret;
212+
213+
bool connected = false;
214+
bool closed = false;
215+
swoole::String buf(65536);
216+
217+
swoole_event_init(SW_EVENTLOOP_WAIT_EXIT);
218+
219+
Client client(SW_SOCK_TCP, true);
220+
client.enable_ssl_encrypt();
221+
client.onConnect = [&connected](Client *cli) {
222+
connected = true;
223+
cli->send(cli, SW_STRL("GET / HTTP/1.1\r\n"
224+
"Host: www.baidu.com\r\n"
225+
"Connection: close\r\n"
226+
"User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36"
227+
"\r\n\r\n"), 0);
228+
};
229+
230+
client.onError = [](Client *cli) {
231+
};
232+
client.onClose = [&closed](Client *cli) {
233+
closed = true;
234+
};
235+
client.onReceive = [&buf](Client *cli, const char *data, size_t length) {
236+
buf.append(data, length);
237+
};
238+
ret = client.connect(&client, "www.baidu.com", 443, -1, 0);
239+
ASSERT_EQ(ret, 0);
240+
241+
swoole_event_wait();
242+
243+
ASSERT_TRUE(connected);
244+
ASSERT_TRUE(closed);
245+
ASSERT_TRUE(buf.contains("Baidu"));
246+
}
247+
248+
TEST(client, http_proxy) {
249+
int ret;
250+
251+
bool connected = false;
252+
bool closed = false;
253+
swoole::String buf(65536);
254+
255+
swoole_event_init(SW_EVENTLOOP_WAIT_EXIT);
256+
257+
Client client(SW_SOCK_TCP, true);
258+
client.enable_ssl_encrypt();
259+
client.set_http_proxy(TEST_HTTP_PROXY_HOST, TEST_HTTP_PROXY_PORT);
260+
261+
client.onConnect = [&connected](Client *cli) {
262+
connected = true;
263+
cli->send(cli, SW_STRL("GET / HTTP/1.1\r\n"
264+
"Host: www.baidu.com\r\n"
265+
"Connection: close\r\n"
266+
"User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36"
267+
"\r\n\r\n"), 0);
268+
};
269+
270+
client.onError = [](Client *cli) {
271+
};
272+
client.onClose = [&closed](Client *cli) {
273+
closed = true;
274+
};
275+
client.onReceive = [&buf](Client *cli, const char *data, size_t length) {
276+
buf.append(data, length);
277+
};
278+
ret = client.connect(&client, "www.baidu.com", 443, -1, 0);
279+
ASSERT_EQ(ret, 0);
280+
281+
swoole_event_wait();
282+
283+
ASSERT_TRUE(connected);
284+
ASSERT_TRUE(closed);
285+
ASSERT_TRUE(buf.contains("Baidu"));
286+
}
287+
#endif
288+

ext-src/swoole_server_port.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -580,10 +580,12 @@ static PHP_METHOD(swoole_server_port, set) {
580580
SSLContext *context = new SSLContext();
581581
*context = *port->ssl_context;
582582
if (!php_swoole_server_set_ssl_option(Z_ARRVAL_P(current), context)) {
583+
delete context;
583584
RETURN_FALSE;
584585
}
585586
if (!port->ssl_add_sni_cert(std::string(key->val, key->len), context)) {
586587
php_swoole_fatal_error(E_ERROR, "ssl_add_sni_cert() failed");
588+
delete context;
587589
RETURN_FALSE;
588590
}
589591
} ZEND_HASH_FOREACH_END();

include/swoole_client.h

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -104,12 +104,12 @@ class Client {
104104
std::shared_ptr<SSLContext> ssl_context = nullptr;
105105
#endif
106106

107-
void (*onConnect)(Client *cli) = nullptr;
108-
void (*onError)(Client *cli) = nullptr;
109-
void (*onReceive)(Client *cli, const char *data, uint32_t length) = nullptr;
110-
void (*onClose)(Client *cli) = nullptr;
111-
void (*onBufferFull)(Client *cli) = nullptr;
112-
void (*onBufferEmpty)(Client *cli) = nullptr;
107+
std::function<void (Client *cli)> onConnect = nullptr;
108+
std::function<void (Client *cli)> onError = nullptr;
109+
std::function<void (Client *cli, const char *, size_t)> onReceive = nullptr;
110+
std::function<void (Client *cli)> onClose = nullptr;
111+
std::function<void (Client *cli)> onBufferFull = nullptr;
112+
std::function<void (Client *cli)> onBufferEmpty = nullptr;
113113

114114
int (*connect)(Client *cli, const char *host, int port, double _timeout, int sock_flag) = nullptr;
115115
ssize_t (*send)(Client *cli, const char *data, size_t length, int flags) = nullptr;
@@ -120,6 +120,12 @@ class Client {
120120
Client(enum swSocket_type type, bool async);
121121
~Client();
122122

123+
void set_http_proxy(const std::string &host, int port) {
124+
http_proxy = new swoole::HttpProxy;
125+
http_proxy->proxy_host = host;
126+
http_proxy->proxy_port = port;
127+
}
128+
123129
int sleep();
124130
int wakeup();
125131
int shutdown(int __how);
@@ -235,7 +241,7 @@ class AsyncClient : public SyncClient {
235241
std::function<void(AsyncClient *)> _onConnect = nullptr;
236242
std::function<void(AsyncClient *)> _onError = nullptr;
237243
std::function<void(AsyncClient *)> _onClose = nullptr;
238-
std::function<void(AsyncClient *, const char *data, uint32_t length)> _onReceive = nullptr;
244+
std::function<void(AsyncClient *, const char *data, size_t length)> _onReceive = nullptr;
239245

240246
public:
241247
AsyncClient(enum swSocket_type _type) : SyncClient(_type, true) {}
@@ -254,7 +260,7 @@ class AsyncClient : public SyncClient {
254260
AsyncClient *ac = (AsyncClient *) cli->object;
255261
ac->_onClose(ac);
256262
};
257-
client.onReceive = [](Client *cli, const char *data, uint32_t length) {
263+
client.onReceive = [](Client *cli, const char *data, size_t length) {
258264
AsyncClient *ac = (AsyncClient *) cli->object;
259265
ac->_onReceive(ac, data, length);
260266
};

include/swoole_ssl.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,10 @@ struct SSLContext {
126126
return context;
127127
}
128128

129+
bool ready() {
130+
return context != nullptr;
131+
}
132+
129133
void set_protocols(uint32_t _protocols) {
130134
protocols = _protocols;
131135
}

src/network/client.cc

Lines changed: 34 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -271,22 +271,26 @@ int Client::enable_ssl_encrypt() {
271271
}
272272

273273
int Client::ssl_handshake() {
274-
if (socket->ssl) {
274+
if (socket->ssl_state == SW_SSL_STATE_READY) {
275275
return SW_ERR;
276276
}
277-
ssl_context->http_v2 = http2;
278-
if (!ssl_context->create()) {
279-
return SW_ERR;
280-
}
281-
socket->ssl_send_ = 1;
282-
if (socket->ssl_create(ssl_context.get(), SW_SSL_CLIENT) < 0) {
283-
return SW_ERR;
277+
if (!ssl_context->ready()) {
278+
ssl_context->http_v2 = http2;
279+
if (!ssl_context->create()) {
280+
return SW_ERR;
281+
}
284282
}
283+
if (!socket->ssl) {
284+
socket->ssl_send_ = 1;
285+
if (socket->ssl_create(ssl_context.get(), SW_SSL_CLIENT) < 0) {
286+
return SW_ERR;
287+
}
285288
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
286-
if (!ssl_context->tls_host_name.empty()) {
287-
SSL_set_tlsext_host_name(socket->ssl, ssl_context->tls_host_name.c_str());
288-
}
289+
if (!ssl_context->tls_host_name.empty()) {
290+
SSL_set_tlsext_host_name(socket->ssl, ssl_context->tls_host_name.c_str());
291+
}
289292
#endif
293+
}
290294
if (socket->ssl_connect() < 0) {
291295
return SW_ERR;
292296
}
@@ -454,7 +458,7 @@ int Client::close() {
454458
timer = nullptr;
455459
}
456460
// onClose callback
457-
if (active && onClose) {
461+
if (active) {
458462
active = 0;
459463
onClose(this);
460464
}
@@ -584,8 +588,8 @@ static int Client_tcp_connect_async(Client *cli, const char *host, int port, dou
584588
cli->buffer = new String(cli->input_buffer_size);
585589
}
586590

587-
if (!(cli->onConnect && cli->onError && cli->onClose)) {
588-
swWarn("onConnect/onError/onClose callback have not set");
591+
if (!(cli->onConnect && cli->onError && cli->onClose && cli->onReceive)) {
592+
swWarn("onConnect/onError/onReceive/onClose callback have not set");
589593
return SW_ERR;
590594
}
591595

@@ -772,6 +776,11 @@ static int Client_udp_connect(Client *cli, const char *host, int port, double ti
772776
return SW_ERR;
773777
}
774778

779+
if (cli->async && !cli->onReceive) {
780+
swWarn("onReceive callback have not set");
781+
return SW_ERR;
782+
}
783+
775784
cli->active = 1;
776785
cli->timeout = timeout;
777786
int bufsize = Socket::default_buffer_size;
@@ -950,11 +959,12 @@ static int Client_onStreamRead(Reactor *reactor, Event *event) {
950959
if (cli->ssl_handshake() < 0) {
951960
goto _connect_fail;
952961
} else {
953-
cli->socket->ssl_state = SW_SSL_STATE_WAIT_STREAM;
954-
return swoole_event_set(event->socket, SW_EVENT_WRITE);
955-
}
956-
if (cli->onConnect) {
957-
execute_onConnect(cli);
962+
if (cli->socket->ssl_state == SW_SSL_STATE_READY) {
963+
execute_onConnect(cli);
964+
}
965+
else if (cli->socket->ssl_state == SW_SSL_STATE_WAIT_STREAM && cli->socket->ssl_want_write) {
966+
swoole_event_set(event->socket, SW_EVENT_WRITE);
967+
}
958968
}
959969
return SW_OK;
960970
}
@@ -986,9 +996,7 @@ static int Client_onStreamRead(Reactor *reactor, Event *event) {
986996
} else
987997
#endif
988998
{
989-
if (cli->onConnect) {
990-
execute_onConnect(cli);
991-
}
999+
execute_onConnect(cli);
9921000
}
9931001
return SW_OK;
9941002
}
@@ -1001,9 +1009,9 @@ static int Client_onStreamRead(Reactor *reactor, Event *event) {
10011009
if (cli->socket->ssl_state != SW_SSL_STATE_READY) {
10021010
return SW_OK;
10031011
}
1004-
// ssl handshake sucess
1005-
else if (cli->onConnect) {
1012+
else {
10061013
execute_onConnect(cli);
1014+
return SW_OK;
10071015
}
10081016
}
10091017
#endif
@@ -1205,18 +1213,14 @@ static int Client_onWrite(Reactor *reactor, Event *event) {
12051213
}
12061214
_connect_success:
12071215
#endif
1208-
if (cli->onConnect) {
1209-
execute_onConnect(cli);
1210-
}
1216+
execute_onConnect(cli);
12111217
} else {
12121218
#ifdef SW_USE_OPENSSL
12131219
_connect_fail:
12141220
#endif
12151221
cli->active = 0;
12161222
cli->close();
1217-
if (cli->onError) {
1218-
cli->onError(cli);
1219-
}
1223+
cli->onError(cli);
12201224
}
12211225

12221226
return SW_OK;

0 commit comments

Comments
 (0)