1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3 * Copyright 2007-2012 Red Hat, Inc.
4 * Copyright 2012 Nokia Corporation
5 */
6
7 #include "test-utils.h"
8 #include "libsoup/soup-socket-private.h"
9
10 #include <fcntl.h>
11 #include <gio/gnetworking.h>
12
13 #ifdef G_OS_WIN32
14 #include <io.h>
15 #endif
16
17 static void
do_unconnected_socket_test(void)18 do_unconnected_socket_test (void)
19 {
20 SoupAddress *localhost;
21 SoupSocket *sock;
22 SoupSocket *client;
23 SoupAddress *addr;
24 guint res;
25 struct sockaddr_in in_localhost;
26
27 g_test_bug ("673083");
28
29 in_localhost.sin_family = AF_INET;
30 in_localhost.sin_port = 0;
31 in_localhost.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
32
33 localhost = soup_address_new_from_sockaddr (
34 (struct sockaddr *) &in_localhost, sizeof (in_localhost));
35 g_assert_true (localhost != NULL);
36 res = soup_address_resolve_sync (localhost, NULL);
37 g_assert_cmpuint (res, ==, SOUP_STATUS_OK);
38
39 sock = soup_socket_new (SOUP_SOCKET_LOCAL_ADDRESS, localhost,
40 NULL);
41 g_assert_true (sock != NULL);
42
43 addr = soup_socket_get_local_address (sock);
44 g_assert_true (addr != NULL);
45 g_assert_cmpstr (soup_address_get_physical (addr), ==, "127.0.0.1");
46 g_assert_cmpuint (soup_address_get_port (addr), ==, 0);
47
48 /* fails with ENOTCONN */
49 g_test_expect_message ("libsoup", G_LOG_LEVEL_WARNING,
50 "*socket not connected*");
51 addr = soup_socket_get_remote_address (sock);
52 g_test_assert_expected_messages ();
53 g_assert_null (addr);
54
55 res = soup_socket_listen (sock);
56 g_assert_true (res);
57
58 addr = soup_socket_get_local_address (sock);
59 g_assert_true (addr != NULL);
60 g_assert_cmpstr (soup_address_get_physical (addr), ==, "127.0.0.1");
61 g_assert_cmpuint (soup_address_get_port (addr), >, 0);
62
63 client = soup_socket_new (SOUP_SOCKET_REMOTE_ADDRESS,
64 soup_socket_get_local_address (sock),
65 NULL);
66 res = soup_socket_connect_sync (client, NULL);
67 g_assert_cmpuint (res, ==, SOUP_STATUS_OK);
68 addr = soup_socket_get_local_address (client);
69 g_assert_true (addr != NULL);
70 addr = soup_socket_get_remote_address (client);
71 g_assert_true (addr != NULL);
72 g_assert_cmpstr (soup_address_get_physical (addr), ==, "127.0.0.1");
73 g_assert_cmpuint (soup_address_get_port (addr), >, 0);
74 g_object_unref (client);
75
76 client = soup_socket_new (SOUP_SOCKET_REMOTE_ADDRESS,
77 soup_socket_get_local_address (sock),
78 NULL);
79 /* save it for later */
80
81 /* listening socket fails with ENOTCONN */
82 g_test_expect_message ("libsoup", G_LOG_LEVEL_WARNING,
83 /* We can't check the error message since it comes from
84 * libc and is locale-dependent.
85 */
86 "*");
87 addr = soup_socket_get_remote_address (sock);
88 g_test_assert_expected_messages ();
89 g_assert_null (addr);
90
91 soup_socket_disconnect (sock);
92
93 g_test_expect_message ("libsoup", G_LOG_LEVEL_WARNING,
94 /* This error message comes from soup-socket.c though */
95 "*socket not connected*");
96 addr = soup_socket_get_remote_address (sock);
97 g_test_assert_expected_messages ();
98 g_assert_null (addr);
99
100 /* has never been connected */
101 g_test_expect_message ("libsoup", G_LOG_LEVEL_WARNING,
102 "*socket not connected*");
103 addr = soup_socket_get_local_address (client);
104 g_test_assert_expected_messages ();
105 g_assert_null (addr);
106
107 res = soup_socket_connect_sync (client, NULL);
108 g_assert_cmpuint (res, ==, SOUP_STATUS_CANT_CONNECT);
109
110 g_test_expect_message ("libsoup", G_LOG_LEVEL_WARNING,
111 "*socket not connected*");
112 addr = soup_socket_get_local_address (client);
113 g_test_assert_expected_messages ();
114 g_assert_null (addr);
115
116 g_object_unref (localhost);
117 g_object_unref (client);
118 g_object_unref (sock);
119 }
120
121 static void
do_socket_from_fd_client_test(void)122 do_socket_from_fd_client_test (void)
123 {
124 SoupServer *server;
125 SoupURI *uri;
126 GSocket *gsock;
127 SoupSocket *sock;
128 SoupAddress *local, *remote;
129 GSocketAddress *gaddr;
130 gboolean is_server;
131 GError *error = NULL;
132
133 server = soup_test_server_new (SOUP_TEST_SERVER_DEFAULT);
134 uri = soup_test_server_get_uri (server, "http", "127.0.0.1");
135
136 gsock = g_socket_new (G_SOCKET_FAMILY_IPV4,
137 G_SOCKET_TYPE_STREAM,
138 G_SOCKET_PROTOCOL_DEFAULT,
139 &error);
140 g_assert_no_error (error);
141
142 gaddr = g_inet_socket_address_new_from_string ("127.0.0.1", uri->port);
143 g_socket_connect (gsock, gaddr, NULL, &error);
144 g_object_unref (gaddr);
145 g_assert_no_error (error);
146 g_assert_true (g_socket_is_connected (gsock));
147
148 gaddr = g_socket_get_local_address (gsock, &error);
149 g_assert_no_error (error);
150
151 sock = g_initable_new (SOUP_TYPE_SOCKET, NULL, &error,
152 SOUP_SOCKET_FD, g_socket_get_fd (gsock),
153 NULL);
154 g_assert_no_error (error);
155 g_assert_nonnull (sock);
156
157 g_object_get (G_OBJECT (sock),
158 SOUP_SOCKET_LOCAL_ADDRESS, &local,
159 SOUP_SOCKET_REMOTE_ADDRESS, &remote,
160 SOUP_SOCKET_IS_SERVER, &is_server,
161 NULL);
162 g_assert_cmpint (soup_socket_get_fd (sock), ==, g_socket_get_fd (gsock));
163 g_assert_false (is_server);
164 g_assert_true (soup_socket_is_connected (sock));
165
166 g_assert_cmpstr (soup_address_get_physical (local), ==, "127.0.0.1");
167 g_assert_cmpint (soup_address_get_port (local), ==, g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (gaddr)));
168 g_assert_cmpstr (soup_address_get_physical (remote), ==, "127.0.0.1");
169 g_assert_cmpint (soup_address_get_port (remote), ==, uri->port);
170
171 g_object_unref (local);
172 g_object_unref (remote);
173 g_object_unref (gaddr);
174
175 g_object_unref (sock);
176 g_object_unref (gsock);
177
178 soup_test_server_quit_unref (server);
179 soup_uri_free (uri);
180 }
181
182 static void
do_socket_from_fd_server_test(void)183 do_socket_from_fd_server_test (void)
184 {
185 GSocket *gsock;
186 SoupSocket *sock;
187 SoupAddress *local;
188 GSocketAddress *gaddr;
189 gboolean is_server;
190 GError *error = NULL;
191
192 gsock = g_socket_new (G_SOCKET_FAMILY_IPV4,
193 G_SOCKET_TYPE_STREAM,
194 G_SOCKET_PROTOCOL_DEFAULT,
195 &error);
196 g_assert_no_error (error);
197
198 gaddr = g_inet_socket_address_new_from_string ("127.0.0.1", 0);
199 g_socket_bind (gsock, gaddr, TRUE, &error);
200 g_object_unref (gaddr);
201 g_assert_no_error (error);
202 g_socket_listen (gsock, &error);
203 g_assert_no_error (error);
204 g_assert_false (g_socket_is_connected (gsock));
205
206 gaddr = g_socket_get_local_address (gsock, &error);
207 g_assert_no_error (error);
208
209 sock = g_initable_new (SOUP_TYPE_SOCKET, NULL, &error,
210 SOUP_SOCKET_GSOCKET, gsock,
211 NULL);
212 g_assert_no_error (error);
213 g_assert_nonnull (sock);
214
215 g_object_get (G_OBJECT (sock),
216 SOUP_SOCKET_LOCAL_ADDRESS, &local,
217 SOUP_SOCKET_IS_SERVER, &is_server,
218 NULL);
219 g_assert_cmpint (soup_socket_get_fd (sock), ==, g_socket_get_fd (gsock));
220 g_assert_true (is_server);
221 g_assert_true (soup_socket_is_connected (sock));
222
223 g_assert_cmpstr (soup_address_get_physical (local), ==, "127.0.0.1");
224 g_assert_cmpint (soup_address_get_port (local), ==, g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (gaddr)));
225 g_object_unref (local);
226 g_object_unref (gaddr);
227
228 g_object_unref (sock);
229
230 /* Closing the SoupSocket should have closed the GSocket */
231 g_assert_true (g_socket_is_closed (gsock));
232
233 g_object_unref (gsock);
234 }
235
236 static void
do_socket_from_fd_bad_test(void)237 do_socket_from_fd_bad_test (void)
238 {
239 GSocket *gsock, *gsock2, *gsockcli;
240 SoupSocket *sock, *sock2;
241 SoupAddress *local, *remote;
242 GSocketAddress *gaddr;
243 gboolean is_server;
244 int fd;
245 GError *error = NULL;
246
247 /* Importing a non-socket fd gives an error */
248 fd = open (g_test_get_filename (G_TEST_DIST, "test-cert.pem", NULL), O_RDONLY);
249 g_assert_cmpint (fd, !=, -1);
250
251 sock = g_initable_new (SOUP_TYPE_SOCKET, NULL, &error,
252 SOUP_SOCKET_FD, fd,
253 NULL);
254 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED);
255 g_clear_error (&error);
256 g_assert_null (sock);
257 close (fd);
258
259 /* Importing an unconnected socket gives an error */
260 gsock = g_socket_new (G_SOCKET_FAMILY_IPV4,
261 G_SOCKET_TYPE_STREAM,
262 G_SOCKET_PROTOCOL_DEFAULT,
263 &error);
264 g_assert_no_error (error);
265 g_assert_false (g_socket_is_connected (gsock));
266
267 sock = g_initable_new (SOUP_TYPE_SOCKET, NULL, &error,
268 SOUP_SOCKET_FD, g_socket_get_fd (gsock),
269 NULL);
270 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED);
271 g_clear_error (&error);
272 g_assert_null (sock);
273 g_object_unref (gsock);
274
275 /* Importing a non-listening server-side socket works, but
276 * gives the wrong answer for soup_socket_is_server().
277 */
278 gsock = g_socket_new (G_SOCKET_FAMILY_IPV4,
279 G_SOCKET_TYPE_STREAM,
280 G_SOCKET_PROTOCOL_DEFAULT,
281 &error);
282 g_assert_no_error (error);
283
284 gaddr = g_inet_socket_address_new_from_string ("127.0.0.1", 0);
285 g_socket_bind (gsock, gaddr, TRUE, &error);
286 g_object_unref (gaddr);
287 g_assert_no_error (error);
288 g_socket_listen (gsock, &error);
289 g_assert_no_error (error);
290 g_assert_false (g_socket_is_connected (gsock));
291
292 gaddr = g_socket_get_local_address (gsock, &error);
293 g_assert_no_error (error);
294
295 gsockcli = g_socket_new (G_SOCKET_FAMILY_IPV4,
296 G_SOCKET_TYPE_STREAM,
297 G_SOCKET_PROTOCOL_DEFAULT,
298 &error);
299 g_assert_no_error (error);
300
301 g_socket_connect (gsockcli, gaddr, NULL, &error);
302 g_assert_no_error (error);
303 g_assert_true (g_socket_is_connected (gsockcli));
304
305 gsock2 = g_socket_accept (gsock, NULL, &error);
306 g_assert_no_error (error);
307 g_assert_nonnull (gsock2);
308
309 sock2 = g_initable_new (SOUP_TYPE_SOCKET, NULL, &error,
310 SOUP_SOCKET_GSOCKET, gsock2,
311 NULL);
312 g_assert_no_error (error);
313 g_assert_nonnull (sock2);
314
315 g_object_get (G_OBJECT (sock2),
316 SOUP_SOCKET_LOCAL_ADDRESS, &local,
317 SOUP_SOCKET_REMOTE_ADDRESS, &remote,
318 SOUP_SOCKET_IS_SERVER, &is_server,
319 NULL);
320 g_assert_cmpint (soup_socket_get_fd (sock2), ==, g_socket_get_fd (gsock2));
321 g_assert_true (soup_socket_is_connected (sock2));
322 /* This is wrong, but can't be helped. */
323 g_assert_false (is_server);
324
325 g_assert_cmpstr (soup_address_get_physical (local), ==, "127.0.0.1");
326 g_assert_cmpint (soup_address_get_port (local), ==, g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (gaddr)));
327 g_object_unref (gaddr);
328
329 gaddr = g_socket_get_local_address (gsockcli, &error);
330 g_assert_no_error (error);
331 g_assert_cmpstr (soup_address_get_physical (remote), ==, "127.0.0.1");
332 g_assert_cmpint (soup_address_get_port (remote), ==, g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (gaddr)));
333 g_object_unref (gaddr);
334
335 g_object_unref (local);
336 g_object_unref (remote);
337
338 g_object_unref (sock2);
339
340 g_object_unref (gsock);
341 g_object_unref (gsock2);
342 g_object_unref (gsockcli);
343 }
344
345 int
main(int argc,char ** argv)346 main (int argc, char **argv)
347 {
348 int ret;
349
350 test_init (argc, argv, NULL);
351
352 g_test_add_func ("/sockets/unconnected", do_unconnected_socket_test);
353 g_test_add_func ("/sockets/from-fd/client", do_socket_from_fd_client_test);
354 g_test_add_func ("/sockets/from-fd/server", do_socket_from_fd_server_test);
355 g_test_add_func ("/sockets/from-fd/bad", do_socket_from_fd_bad_test);
356
357 ret = g_test_run ();
358
359 test_cleanup ();
360 return ret;
361 }
362