• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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