Branch data Line data Source code
1 : : /* GLib testing framework examples and tests
2 : : *
3 : : * Copyright © 2026 Collabora Ltd.
4 : : *
5 : : * SPDX-License-Identifier: LGPL-2.1-or-later
6 : : *
7 : : * This library is free software; you can redistribute it and/or
8 : : * modify it under the terms of the GNU Lesser General Public
9 : : * License as published by the Free Software Foundation; either
10 : : * version 2.1 of the License, or (at your option) any later version.
11 : : *
12 : : * This library is distributed in the hope that it will be useful,
13 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 : : * Lesser General Public License for more details.
16 : : *
17 : : * You should have received a copy of the GNU Lesser General
18 : : * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 : : *
20 : : * Authors: Jakub Adam <jakub.adam@collabora.com>
21 : : */
22 : :
23 : : #include <gio/gio.h>
24 : : #include <gio/giptosmessage.h>
25 : : #include <gio/gnetworking.h>
26 : :
27 : : /* See the g_test_skip() calls below for platform-specific reasons why this test
28 : : * code sometimes needs to be skipped. */
29 : : #if ! (defined(G_OS_WIN32) || defined(__APPLE__) || defined(__GNU__) || defined(_AIX) || defined(__sun__))
30 : :
31 : : static GSocketControlMessage *
32 : 2 : send_recv_control_message (GSocketFamily family, GSocketControlMessage *msg)
33 : : {
34 : : GSocket *wsock;
35 : : GSocket *rsock;
36 : : GInetAddress *addr;
37 : : GSocketAddress *sockaddr;
38 : : GOutputVector ov;
39 : : GInputVector iv;
40 : : GSocketControlMessage *result;
41 : : GSocketControlMessage **mv;
42 : : gint num_msg;
43 : 2 : GError *error = NULL;
44 : : gchar recvbuf[20];
45 : : gssize sent;
46 : :
47 : 2 : const gchar MESSAGE[] = "TOSMESSAGE";
48 : :
49 : 2 : wsock = g_socket_new (family, G_SOCKET_TYPE_DATAGRAM, G_SOCKET_PROTOCOL_UDP, &error);
50 : 2 : g_assert_no_error (error);
51 : :
52 : 2 : rsock = g_socket_new (family, G_SOCKET_TYPE_DATAGRAM, G_SOCKET_PROTOCOL_UDP, &error);
53 : 2 : g_assert_no_error (error);
54 : :
55 : 2 : addr = g_inet_address_new_loopback (family);
56 : 2 : sockaddr = g_inet_socket_address_new (addr, 0);
57 : :
58 : 2 : g_socket_bind (wsock, sockaddr, TRUE, &error);
59 : 2 : g_assert_no_error (error);
60 : :
61 : 2 : g_socket_bind (rsock, sockaddr, TRUE, &error);
62 : 2 : g_assert_no_error (error);
63 : :
64 : 2 : g_clear_object (&sockaddr);
65 : 2 : g_clear_object (&addr);
66 : :
67 : 2 : sockaddr = g_socket_get_local_address (rsock, &error);
68 : 2 : g_assert_no_error (error);
69 : :
70 : 2 : if (family == G_SOCKET_FAMILY_IPV4)
71 : : {
72 : 1 : g_socket_set_option (rsock, IPPROTO_IP, IP_RECVTOS, 1, &error);
73 : : }
74 : : else
75 : : {
76 : 1 : g_socket_set_option (rsock, IPPROTO_IPV6, IPV6_RECVTCLASS, 1, &error);
77 : : }
78 : 2 : g_assert_no_error (error);
79 : :
80 : 2 : ov.buffer = MESSAGE;
81 : 2 : ov.size = strlen (MESSAGE) + 1;
82 : :
83 : 2 : sent = g_socket_send_message (wsock, sockaddr, &ov, 1, &msg, 1, 0, NULL, &error);
84 : 2 : g_assert_no_error (error);
85 : 2 : g_assert_cmpint (sent, ==, ov.size);
86 : :
87 : 2 : iv.buffer = recvbuf;
88 : 2 : iv.size = sizeof (recvbuf);
89 : 2 : g_socket_receive_message (rsock, NULL, &iv, 1, &mv, &num_msg, NULL, NULL, &error);
90 : 2 : g_assert_no_error (error);
91 : :
92 : 2 : g_assert_cmpstr (MESSAGE, ==, recvbuf);
93 : 2 : g_assert_cmpint (num_msg, ==, 1);
94 : :
95 : 2 : result = mv[0];
96 : 2 : g_clear_pointer (&mv, g_free);
97 : :
98 : 2 : g_clear_object (&sockaddr);
99 : 2 : g_clear_object (&wsock);
100 : 2 : g_clear_object (&rsock);
101 : :
102 : 2 : return g_steal_pointer (&result);
103 : : }
104 : :
105 : : const guint8 DSCP = 0x25;
106 : : const GEcnCodePoint ECN = G_ECN_ECT_0;
107 : :
108 : : #endif
109 : :
110 : : static void
111 : 2 : test_ip_tos (void)
112 : : {
113 : : #if defined(G_OS_WIN32)
114 : 1 : g_test_skip ("GSocketControlMessage not supported on Windows.");
115 : : #elif defined(__APPLE__)
116 : : g_test_skip ("IP_TOS not supported on macOS.");
117 : : #elif defined(__GNU__)
118 : : g_test_skip ("IP_RECVTOS not supported on Hurd");
119 : : #elif defined(_AIX)
120 : : g_test_skip ("IP_RECVTOS not supported on AIX");
121 : : #elif defined(__sun__)
122 : : g_test_skip ("IP_RECVTOS not supported on Solaris");
123 : : #else
124 : : GIPTosMessage *smsg;
125 : : GIPTosMessage *rmsg;
126 : :
127 : 1 : smsg = G_IP_TOS_MESSAGE (g_ip_tos_message_new (DSCP, ECN));
128 : 1 : rmsg = G_IP_TOS_MESSAGE (send_recv_control_message (G_SOCKET_FAMILY_IPV4, G_SOCKET_CONTROL_MESSAGE (smsg)));
129 : :
130 : 1 : g_assert_cmpint (g_ip_tos_message_get_dscp (rmsg), ==, g_ip_tos_message_get_dscp (smsg));
131 : 1 : g_assert_cmpint (g_ip_tos_message_get_ecn (rmsg), ==, g_ip_tos_message_get_ecn (smsg));
132 : :
133 : 1 : g_clear_object (&smsg);
134 : 1 : g_clear_object (&rmsg);
135 : : #endif
136 : 2 : }
137 : :
138 : : static void
139 : 2 : test_ipv6_tclass (void)
140 : : {
141 : : #if defined(G_OS_WIN32)
142 : 1 : g_test_skip ("GSocketControlMessage not supported on Windows.");
143 : : #elif defined(__APPLE__)
144 : : g_test_skip ("IPV6_TCLASS not supported on macOS.");
145 : : #elif defined(__GNU__)
146 : : g_test_skip ("IPV6_RECVTCLASS not supported on Hurd");
147 : : #elif defined(_AIX)
148 : : g_test_skip ("IPV6_RECVTCLASS not supported on AIX");
149 : : #elif defined(__sun__)
150 : : g_test_skip ("IPV6_RECVTCLASS not supported on Solaris");
151 : : #else
152 : : GIPv6TclassMessage *smsg;
153 : : GIPv6TclassMessage *rmsg;
154 : :
155 : 1 : smsg = G_IPV6_TCLASS_MESSAGE (g_ipv6_tclass_message_new (DSCP, ECN));
156 : 1 : rmsg = G_IPV6_TCLASS_MESSAGE (send_recv_control_message (G_SOCKET_FAMILY_IPV6, G_SOCKET_CONTROL_MESSAGE (smsg)));
157 : :
158 : 1 : g_assert_cmpint (g_ipv6_tclass_message_get_dscp (rmsg), ==, g_ipv6_tclass_message_get_dscp (smsg));
159 : 1 : g_assert_cmpint (g_ipv6_tclass_message_get_ecn (rmsg), ==, g_ipv6_tclass_message_get_ecn (smsg));
160 : :
161 : 1 : g_clear_object (&smsg);
162 : 1 : g_clear_object (&rmsg);
163 : : #endif
164 : 2 : }
165 : :
166 : : int
167 : 2 : main (int argc, char **argv)
168 : : {
169 : 2 : g_test_init (&argc, &argv, NULL);
170 : :
171 : 2 : g_test_add_func ("/iptosmessage/iptos", test_ip_tos);
172 : 2 : g_test_add_func ("/iptosmessage/ipv6tclass", test_ipv6_tclass);
173 : :
174 : 2 : return g_test_run ();
175 : : }
|