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