/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * Copyright 2007-2012 Red Hat, Inc. * Copyright 2012 Nokia Corporation */ #include "test-utils.h" #include "libsoup/soup-socket-private.h" #include #include #ifdef G_OS_WIN32 #include #endif static void do_unconnected_socket_test (void) { SoupAddress *localhost; SoupSocket *sock; SoupSocket *client; SoupAddress *addr; guint res; struct sockaddr_in in_localhost; g_test_bug ("673083"); in_localhost.sin_family = AF_INET; in_localhost.sin_port = 0; in_localhost.sin_addr.s_addr = htonl (INADDR_LOOPBACK); localhost = soup_address_new_from_sockaddr ( (struct sockaddr *) &in_localhost, sizeof (in_localhost)); g_assert_true (localhost != NULL); res = soup_address_resolve_sync (localhost, NULL); g_assert_cmpuint (res, ==, SOUP_STATUS_OK); sock = soup_socket_new (SOUP_SOCKET_LOCAL_ADDRESS, localhost, NULL); g_assert_true (sock != NULL); addr = soup_socket_get_local_address (sock); g_assert_true (addr != NULL); g_assert_cmpstr (soup_address_get_physical (addr), ==, "127.0.0.1"); g_assert_cmpuint (soup_address_get_port (addr), ==, 0); /* fails with ENOTCONN */ g_test_expect_message ("libsoup", G_LOG_LEVEL_WARNING, "*socket not connected*"); addr = soup_socket_get_remote_address (sock); g_test_assert_expected_messages (); g_assert_null (addr); res = soup_socket_listen (sock); g_assert_true (res); addr = soup_socket_get_local_address (sock); g_assert_true (addr != NULL); g_assert_cmpstr (soup_address_get_physical (addr), ==, "127.0.0.1"); g_assert_cmpuint (soup_address_get_port (addr), >, 0); client = soup_socket_new (SOUP_SOCKET_REMOTE_ADDRESS, soup_socket_get_local_address (sock), NULL); res = soup_socket_connect_sync (client, NULL); g_assert_cmpuint (res, ==, SOUP_STATUS_OK); addr = soup_socket_get_local_address (client); g_assert_true (addr != NULL); addr = soup_socket_get_remote_address (client); g_assert_true (addr != NULL); g_assert_cmpstr (soup_address_get_physical (addr), ==, "127.0.0.1"); g_assert_cmpuint (soup_address_get_port (addr), >, 0); g_object_unref (client); client = soup_socket_new (SOUP_SOCKET_REMOTE_ADDRESS, soup_socket_get_local_address (sock), NULL); /* save it for later */ /* listening socket fails with ENOTCONN */ g_test_expect_message ("libsoup", G_LOG_LEVEL_WARNING, /* We can't check the error message since it comes from * libc and is locale-dependent. */ "*"); addr = soup_socket_get_remote_address (sock); g_test_assert_expected_messages (); g_assert_null (addr); soup_socket_disconnect (sock); g_test_expect_message ("libsoup", G_LOG_LEVEL_WARNING, /* This error message comes from soup-socket.c though */ "*socket not connected*"); addr = soup_socket_get_remote_address (sock); g_test_assert_expected_messages (); g_assert_null (addr); /* has never been connected */ g_test_expect_message ("libsoup", G_LOG_LEVEL_WARNING, "*socket not connected*"); addr = soup_socket_get_local_address (client); g_test_assert_expected_messages (); g_assert_null (addr); res = soup_socket_connect_sync (client, NULL); g_assert_cmpuint (res, ==, SOUP_STATUS_CANT_CONNECT); g_test_expect_message ("libsoup", G_LOG_LEVEL_WARNING, "*socket not connected*"); addr = soup_socket_get_local_address (client); g_test_assert_expected_messages (); g_assert_null (addr); g_object_unref (localhost); g_object_unref (client); g_object_unref (sock); } static void do_socket_from_fd_client_test (void) { SoupServer *server; SoupURI *uri; GSocket *gsock; SoupSocket *sock; SoupAddress *local, *remote; GSocketAddress *gaddr; gboolean is_server; GError *error = NULL; server = soup_test_server_new (SOUP_TEST_SERVER_DEFAULT); uri = soup_test_server_get_uri (server, "http", "127.0.0.1"); gsock = g_socket_new (G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_DEFAULT, &error); g_assert_no_error (error); gaddr = g_inet_socket_address_new_from_string ("127.0.0.1", uri->port); g_socket_connect (gsock, gaddr, NULL, &error); g_object_unref (gaddr); g_assert_no_error (error); g_assert_true (g_socket_is_connected (gsock)); gaddr = g_socket_get_local_address (gsock, &error); g_assert_no_error (error); sock = g_initable_new (SOUP_TYPE_SOCKET, NULL, &error, SOUP_SOCKET_FD, g_socket_get_fd (gsock), NULL); g_assert_no_error (error); g_assert_nonnull (sock); g_object_get (G_OBJECT (sock), SOUP_SOCKET_LOCAL_ADDRESS, &local, SOUP_SOCKET_REMOTE_ADDRESS, &remote, SOUP_SOCKET_IS_SERVER, &is_server, NULL); g_assert_cmpint (soup_socket_get_fd (sock), ==, g_socket_get_fd (gsock)); g_assert_false (is_server); g_assert_true (soup_socket_is_connected (sock)); g_assert_cmpstr (soup_address_get_physical (local), ==, "127.0.0.1"); g_assert_cmpint (soup_address_get_port (local), ==, g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (gaddr))); g_assert_cmpstr (soup_address_get_physical (remote), ==, "127.0.0.1"); g_assert_cmpint (soup_address_get_port (remote), ==, uri->port); g_object_unref (local); g_object_unref (remote); g_object_unref (gaddr); g_object_unref (sock); g_object_unref (gsock); soup_test_server_quit_unref (server); soup_uri_free (uri); } static void do_socket_from_fd_server_test (void) { GSocket *gsock; SoupSocket *sock; SoupAddress *local; GSocketAddress *gaddr; gboolean is_server; GError *error = NULL; gsock = g_socket_new (G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_DEFAULT, &error); g_assert_no_error (error); gaddr = g_inet_socket_address_new_from_string ("127.0.0.1", 0); g_socket_bind (gsock, gaddr, TRUE, &error); g_object_unref (gaddr); g_assert_no_error (error); g_socket_listen (gsock, &error); g_assert_no_error (error); g_assert_false (g_socket_is_connected (gsock)); gaddr = g_socket_get_local_address (gsock, &error); g_assert_no_error (error); sock = g_initable_new (SOUP_TYPE_SOCKET, NULL, &error, SOUP_SOCKET_GSOCKET, gsock, NULL); g_assert_no_error (error); g_assert_nonnull (sock); g_object_get (G_OBJECT (sock), SOUP_SOCKET_LOCAL_ADDRESS, &local, SOUP_SOCKET_IS_SERVER, &is_server, NULL); g_assert_cmpint (soup_socket_get_fd (sock), ==, g_socket_get_fd (gsock)); g_assert_true (is_server); g_assert_true (soup_socket_is_connected (sock)); g_assert_cmpstr (soup_address_get_physical (local), ==, "127.0.0.1"); g_assert_cmpint (soup_address_get_port (local), ==, g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (gaddr))); g_object_unref (local); g_object_unref (gaddr); g_object_unref (sock); /* Closing the SoupSocket should have closed the GSocket */ g_assert_true (g_socket_is_closed (gsock)); g_object_unref (gsock); } static void do_socket_from_fd_bad_test (void) { GSocket *gsock, *gsock2, *gsockcli; SoupSocket *sock, *sock2; SoupAddress *local, *remote; GSocketAddress *gaddr; gboolean is_server; int fd; GError *error = NULL; /* Importing a non-socket fd gives an error */ fd = open (g_test_get_filename (G_TEST_DIST, "test-cert.pem", NULL), O_RDONLY); g_assert_cmpint (fd, !=, -1); sock = g_initable_new (SOUP_TYPE_SOCKET, NULL, &error, SOUP_SOCKET_FD, fd, NULL); g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED); g_clear_error (&error); g_assert_null (sock); close (fd); /* Importing an unconnected socket gives an error */ gsock = g_socket_new (G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_DEFAULT, &error); g_assert_no_error (error); g_assert_false (g_socket_is_connected (gsock)); sock = g_initable_new (SOUP_TYPE_SOCKET, NULL, &error, SOUP_SOCKET_FD, g_socket_get_fd (gsock), NULL); g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED); g_clear_error (&error); g_assert_null (sock); g_object_unref (gsock); /* Importing a non-listening server-side socket works, but * gives the wrong answer for soup_socket_is_server(). */ gsock = g_socket_new (G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_DEFAULT, &error); g_assert_no_error (error); gaddr = g_inet_socket_address_new_from_string ("127.0.0.1", 0); g_socket_bind (gsock, gaddr, TRUE, &error); g_object_unref (gaddr); g_assert_no_error (error); g_socket_listen (gsock, &error); g_assert_no_error (error); g_assert_false (g_socket_is_connected (gsock)); gaddr = g_socket_get_local_address (gsock, &error); g_assert_no_error (error); gsockcli = g_socket_new (G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_DEFAULT, &error); g_assert_no_error (error); g_socket_connect (gsockcli, gaddr, NULL, &error); g_assert_no_error (error); g_assert_true (g_socket_is_connected (gsockcli)); gsock2 = g_socket_accept (gsock, NULL, &error); g_assert_no_error (error); g_assert_nonnull (gsock2); sock2 = g_initable_new (SOUP_TYPE_SOCKET, NULL, &error, SOUP_SOCKET_GSOCKET, gsock2, NULL); g_assert_no_error (error); g_assert_nonnull (sock2); g_object_get (G_OBJECT (sock2), SOUP_SOCKET_LOCAL_ADDRESS, &local, SOUP_SOCKET_REMOTE_ADDRESS, &remote, SOUP_SOCKET_IS_SERVER, &is_server, NULL); g_assert_cmpint (soup_socket_get_fd (sock2), ==, g_socket_get_fd (gsock2)); g_assert_true (soup_socket_is_connected (sock2)); /* This is wrong, but can't be helped. */ g_assert_false (is_server); g_assert_cmpstr (soup_address_get_physical (local), ==, "127.0.0.1"); g_assert_cmpint (soup_address_get_port (local), ==, g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (gaddr))); g_object_unref (gaddr); gaddr = g_socket_get_local_address (gsockcli, &error); g_assert_no_error (error); g_assert_cmpstr (soup_address_get_physical (remote), ==, "127.0.0.1"); g_assert_cmpint (soup_address_get_port (remote), ==, g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (gaddr))); g_object_unref (gaddr); g_object_unref (local); g_object_unref (remote); g_object_unref (sock2); g_object_unref (gsock); g_object_unref (gsock2); g_object_unref (gsockcli); } int main (int argc, char **argv) { int ret; test_init (argc, argv, NULL); g_test_add_func ("/sockets/unconnected", do_unconnected_socket_test); g_test_add_func ("/sockets/from-fd/client", do_socket_from_fd_client_test); g_test_add_func ("/sockets/from-fd/server", do_socket_from_fd_server_test); g_test_add_func ("/sockets/from-fd/bad", do_socket_from_fd_bad_test); ret = g_test_run (); test_cleanup (); return ret; }