1 #include "test_core.h"
2 #include "test_server.h"
3 #include "test_process.h"
4
5 #define GREETER "Hello Swoole"
6 #define GREETER_SIZE sizeof(GREETER)
7
8 using swoole::network::AsyncClient;
9 using swoole::network::Client;
10 using swoole::test::Process;
11 using swoole::test::Server;
12 using swoole::Pipe;
13
TEST(client,tcp)14 TEST(client, tcp) {
15 int ret;
16 char buf[128];
17
18 pid_t pid;
19
20 Process proc([](Process *proc) {
21 on_receive_lambda_type receive_fn = [](ON_RECEIVE_PARAMS) {
22 SERVER_THIS->send(req->info.fd, req->data, req->info.len);
23 };
24
25 Server serv(TEST_HOST, TEST_PORT, swoole::Server::MODE_BASE, SW_SOCK_TCP);
26 serv.on("onReceive", (void *) receive_fn);
27 serv.start();
28 });
29
30 pid = proc.start();
31
32 sleep(1); // wait for the test server to start
33
34 Client cli(SW_SOCK_TCP, false);
35 ASSERT_NE(cli.socket, nullptr);
36 ret = cli.connect(&cli, TEST_HOST, TEST_PORT, -1, 0);
37 ASSERT_EQ(ret, 0);
38 ret = cli.send(&cli, SW_STRS(GREETER), 0);
39 ASSERT_GT(ret, 0);
40 ret = cli.recv(&cli, buf, 128, 0);
41 ASSERT_EQ(ret, GREETER_SIZE);
42 ASSERT_STREQ(GREETER, buf);
43
44 kill(pid, SIGTERM);
45 int status;
46 wait(&status);
47 }
48
TEST(client,udp)49 TEST(client, udp) {
50 int ret;
51 char buf[128];
52
53 pid_t pid;
54
55 Process proc([](Process *proc) {
56 on_packet_lambda_type packet_fn = [](ON_PACKET_PARAMS) {
57 swoole::DgramPacket *packet = (swoole::DgramPacket *) req->data;
58 SERVER_THIS->sendto(packet->socket_addr, packet->data, packet->length, req->info.server_fd);
59 };
60
61 Server serv(TEST_HOST, TEST_PORT, swoole::Server::MODE_BASE, SW_SOCK_UDP);
62 serv.on("onPacket", (void *) packet_fn);
63 serv.start();
64 });
65
66 pid = proc.start();
67
68 sleep(1); // wait for the test server to start
69
70 Client cli(SW_SOCK_UDP, false);
71 ASSERT_NE(cli.socket, nullptr);
72 ret = cli.connect(&cli, TEST_HOST, TEST_PORT, -1, 0);
73 ASSERT_EQ(ret, 0);
74 ret = cli.send(&cli, SW_STRS(GREETER), 0);
75 ASSERT_GT(ret, 0);
76 ret = cli.recv(&cli, buf, 128, 0);
77 ASSERT_EQ(ret, GREETER_SIZE);
78 ASSERT_STREQ(GREETER, buf);
79
80 kill(pid, SIGTERM);
81 int status;
82 wait(&status);
83 }
84
TEST(client,async_tcp)85 TEST(client, async_tcp) {
86 pid_t pid;
87
88 Pipe p(true);
89 ASSERT_TRUE(p.ready());
90
91 Process proc([&p](Process *proc) {
92 on_receive_lambda_type receive_fn = [](ON_RECEIVE_PARAMS) {
93 SERVER_THIS->send(req->info.fd, req->data, req->info.len);
94 };
95
96 Server serv(TEST_HOST, TEST_PORT, swoole::Server::MODE_BASE, SW_SOCK_TCP);
97
98 serv.set_private_data("pipe", &p);
99
100 serv.on("onReceive", (void *) receive_fn);
101
102 on_workerstart_lambda_type worker_start_fn = [](ON_WORKERSTART_PARAMS) {
103 Pipe *p = (Pipe *) SERVER_THIS->get_private_data("pipe");
104 int64_t value = 1;
105 p->write(&value, sizeof(value));
106 };
107
108 serv.on("onWorkerStart", (void *) worker_start_fn);
109
110 serv.start();
111 });
112
113 pid = proc.start();
114 int64_t value;
115 p.set_timeout(10);
116 p.read(&value, sizeof(value));
117
118 swoole_event_init(SW_EVENTLOOP_WAIT_EXIT);
119
120 AsyncClient ac(SW_SOCK_TCP);
121
122 ac.on_connect([](AsyncClient *ac) { ac->send(SW_STRS(GREETER)); });
123
124 ac.on_close([](AsyncClient *ac) {
125
126 });
127 ac.on_error([](AsyncClient *ac) {
128
129 });
130
131 ac.on_receive([](AsyncClient *ac, const char *data, size_t len) {
132 ASSERT_EQ(len, GREETER_SIZE);
133 ASSERT_STREQ(GREETER, data);
134 ac->close();
135 });
136
137 bool retval = ac.connect(TEST_HOST, TEST_PORT);
138 EXPECT_TRUE(retval);
139
140 swoole_event_wait();
141
142 kill(pid, SIGTERM);
143 int status;
144 wait(&status);
145 }
146
TEST(client,connect_refuse)147 TEST(client, connect_refuse) {
148 int ret;
149 Client cli(SW_SOCK_TCP, false);
150 ret = cli.connect(&cli, TEST_HOST, TEST_PORT + 10001, -1, 0);
151 ASSERT_EQ(ret, -1);
152 ASSERT_EQ(swoole_get_last_error(), ECONNREFUSED);
153 }
154
TEST(client,connect_timeout)155 TEST(client, connect_timeout) {
156 int ret;
157 Client cli(SW_SOCK_TCP, false);
158 ret = cli.connect(&cli, "19.168.0.99", TEST_PORT + 10001, 0.2, 0);
159 ASSERT_EQ(ret, -1);
160 ASSERT_EQ(swoole_get_last_error(), ETIMEDOUT);
161 }
162
TEST(client,shutdown_write)163 TEST(client, shutdown_write) {
164 signal(SIGPIPE, SIG_IGN);
165 int ret;
166 Client cli(SW_SOCK_TCP, false);
167 ret = cli.connect(&cli, "www.baidu.com", 80, -1, 0);
168 ASSERT_EQ(ret, 0);
169 cli.shutdown(SHUT_WR);
170 ssize_t retval = cli.send(&cli, SW_STRL("hello world"), 0);
171 ASSERT_EQ(retval, -1);
172 ASSERT_EQ(swoole_get_last_error(), EPIPE);
173 }
174
TEST(client,shutdown_read)175 TEST(client, shutdown_read) {
176 signal(SIGPIPE, SIG_IGN);
177 int ret;
178 Client cli(SW_SOCK_TCP, false);
179 ret = cli.connect(&cli, "www.baidu.com", 80, -1, 0);
180 ASSERT_EQ(ret, 0);
181
182 cli.shutdown(SHUT_RD);
183 ssize_t retval = cli.send(&cli, SW_STRL("hello world\r\n\r\n"), 0);
184 ASSERT_GT(retval, 0);
185
186 char buf[1024];
187 retval = cli.recv(&cli, buf, sizeof(buf), 0);
188 ASSERT_EQ(retval, 0);
189 }
190
TEST(client,shutdown_all)191 TEST(client, shutdown_all) {
192 signal(SIGPIPE, SIG_IGN);
193 int ret;
194 Client cli(SW_SOCK_TCP, false);
195 ret = cli.connect(&cli, "www.baidu.com", 80, -1, 0);
196 ASSERT_EQ(ret, 0);
197
198 cli.shutdown(SHUT_RDWR);
199
200 ssize_t retval = cli.send(&cli, SW_STRL("hello world\r\n\r\n"), 0);
201 ASSERT_EQ(retval, -1);
202 ASSERT_EQ(swoole_get_last_error(), EPIPE);
203
204 char buf[1024];
205 retval = cli.recv(&cli, buf, sizeof(buf), 0);
206 ASSERT_EQ(retval, 0);
207 }
208
209 #ifdef SW_USE_OPENSSL
TEST(client,ssl_1)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
TEST(client,http_proxy)248 TEST(client, http_proxy) {
249 // skip in github action
250 if (swoole::test::is_github_ci()) {
251 return;
252 }
253
254 int ret;
255
256 bool connected = false;
257 bool closed = false;
258 swoole::String buf(65536);
259
260 swoole_event_init(SW_EVENTLOOP_WAIT_EXIT);
261
262 Client client(SW_SOCK_TCP, true);
263 client.enable_ssl_encrypt();
264 client.set_http_proxy(TEST_HTTP_PROXY_HOST, TEST_HTTP_PROXY_PORT);
265
266 client.onConnect = [&connected](Client *cli) {
267 connected = true;
268 cli->send(cli, SW_STRL("GET / HTTP/1.1\r\n"
269 "Host: www.baidu.com\r\n"
270 "Connection: close\r\n"
271 "User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36"
272 "\r\n\r\n"), 0);
273 };
274
275 client.onError = [](Client *cli) {
276 };
277 client.onClose = [&closed](Client *cli) {
278 closed = true;
279 };
280 client.onReceive = [&buf](Client *cli, const char *data, size_t length) {
281 buf.append(data, length);
282 };
283 ret = client.connect(&client, "www.baidu.com", 443, -1, 0);
284 ASSERT_EQ(ret, 0);
285
286 swoole_event_wait();
287
288 ASSERT_TRUE(connected);
289 ASSERT_TRUE(closed);
290 ASSERT_TRUE(buf.contains("Baidu"));
291 }
292 #endif
293
294