/src/glib/gio/gipv6tclassmessage.c
Line | Count | Source |
1 | | /* GIO - GLib Input, Output and Streaming Library |
2 | | * |
3 | | * Copyright © 2025 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 | | * See the included COPYING file for more information. |
13 | | * |
14 | | * Authors: Jakub Adam <jakub.adam@collabora.com> |
15 | | */ |
16 | | |
17 | | /** |
18 | | * GIPv6TclassMessage: |
19 | | * |
20 | | * Contains the Traffic Class byte of an IPv6 header. |
21 | | * |
22 | | * This consists of the DSCP field as per |
23 | | * [RFC 2474](https://www.rfc-editor.org/rfc/rfc2474#section-3), |
24 | | * and the ECN field as per |
25 | | * [RFC 3168](https://www.rfc-editor.org/rfc/rfc3168#section-5). |
26 | | * |
27 | | * It may be received using [method@Gio.Socket.receive_message] over UDP sockets |
28 | | * (i.e. sockets in the `G_SOCKET_FAMILY_IPV6` family with |
29 | | * `G_SOCKET_TYPE_DATAGRAM` type). The message is not meant for sending. To set |
30 | | * Traffic Class field to be used in datagrams sent on a [class@Gio.Socket] use: |
31 | | * ```c |
32 | | * g_socket_set_option (socket, IPPROTO_IPV6, IPV6_TCLASS, <TC value>, &error); |
33 | | * ``` |
34 | | * |
35 | | * Since: 2.88 |
36 | | */ |
37 | | |
38 | | #include "gipv6tclassmessage.h" |
39 | | |
40 | | #include <gio/gnetworking.h> |
41 | | |
42 | | struct _GIPv6TclassMessage |
43 | | { |
44 | | GSocketControlMessage parent_instance; |
45 | | |
46 | | /*< private >*/ |
47 | | |
48 | | guint8 tclass; |
49 | | }; |
50 | | |
51 | 0 | G_DEFINE_TYPE (GIPv6TclassMessage, g_ipv6_tclass_message, G_TYPE_SOCKET_CONTROL_MESSAGE); |
52 | 0 |
|
53 | 0 | static void |
54 | 0 | g_ipv6_tclass_message_init (GIPv6TclassMessage *message) |
55 | 0 | { |
56 | 0 | } |
57 | | |
58 | | static gsize |
59 | | g_ipv6_tclass_message_get_size (GSocketControlMessage *message) |
60 | 0 | { |
61 | 0 | return sizeof (int); |
62 | 0 | } |
63 | | |
64 | | static int |
65 | | g_ipv6_tclass_message_get_level (GSocketControlMessage *message) |
66 | 0 | { |
67 | 0 | return IPPROTO_IPV6; |
68 | 0 | } |
69 | | |
70 | | static int |
71 | | g_ipv6_tclass_message_get_msg_type (GSocketControlMessage *message) |
72 | 0 | { |
73 | 0 | return IPV6_TCLASS; |
74 | 0 | } |
75 | | |
76 | | static void |
77 | | g_ipv6_tclass_message_serialize (GSocketControlMessage *message, gpointer data) |
78 | 0 | { |
79 | 0 | *(int *) data = G_IPV6_TCLASS_MESSAGE (message)->tclass; |
80 | 0 | } |
81 | | |
82 | | static GSocketControlMessage * |
83 | | g_ipv6_tclass_message_deserialize (gint level, gint type, gsize size, gpointer data) |
84 | 0 | { |
85 | 0 | GIPv6TclassMessage *message; |
86 | |
|
87 | 0 | if (level != IPPROTO_IPV6 || type != IPV6_TCLASS) |
88 | 0 | return NULL; |
89 | | |
90 | 0 | if (size != sizeof (int)) |
91 | 0 | return NULL; |
92 | | |
93 | 0 | message = g_object_new (G_TYPE_IPV6_TCLASS_MESSAGE, NULL); |
94 | 0 | message->tclass = *(int *) data; |
95 | |
|
96 | 0 | return G_SOCKET_CONTROL_MESSAGE (message); |
97 | 0 | } |
98 | | |
99 | | static void |
100 | | g_ipv6_tclass_message_class_init (GIPv6TclassMessageClass *klass) |
101 | 0 | { |
102 | 0 | GSocketControlMessageClass *scm_class = G_SOCKET_CONTROL_MESSAGE_CLASS (klass); |
103 | |
|
104 | 0 | scm_class->get_size = g_ipv6_tclass_message_get_size; |
105 | 0 | scm_class->get_level = g_ipv6_tclass_message_get_level; |
106 | 0 | scm_class->get_type = g_ipv6_tclass_message_get_msg_type; |
107 | 0 | scm_class->serialize = g_ipv6_tclass_message_serialize; |
108 | 0 | scm_class->deserialize = g_ipv6_tclass_message_deserialize; |
109 | 0 | } |
110 | | |
111 | | /** |
112 | | * g_ipv6_tclass_message_new: |
113 | | * @dscp: the DSCP value of the message |
114 | | * @ecn: the ECN value of the message |
115 | | * |
116 | | * Creates a new traffic class message with given DSCP and ECN values. |
117 | | * |
118 | | * Returns: (transfer full): a new traffic class message |
119 | | * Since: 2.88 |
120 | | */ |
121 | | GSocketControlMessage * |
122 | | g_ipv6_tclass_message_new (guint8 dscp, GEcnCodePoint ecn) |
123 | 0 | { |
124 | 0 | GIPv6TclassMessage *msg = g_object_new (G_TYPE_IPV6_TCLASS_MESSAGE, NULL); |
125 | |
|
126 | 0 | msg->tclass = (dscp << 2) | ecn; |
127 | |
|
128 | 0 | return (GSocketControlMessage *) msg; |
129 | 0 | } |
130 | | |
131 | | /** |
132 | | * g_ipv6_tclass_message_get_dscp: |
133 | | * @message: a traffic class message |
134 | | * |
135 | | * Gets the differentiated services code point stored in @message. |
136 | | * |
137 | | * Returns: A DSCP value as described in [RFC 2474](https://www.rfc-editor.org/rfc/rfc2474.html#section-3). |
138 | | * |
139 | | * Since: 2.88 |
140 | | */ |
141 | | guint8 |
142 | | g_ipv6_tclass_message_get_dscp (GIPv6TclassMessage *message) |
143 | 0 | { |
144 | 0 | return message->tclass >> 2; |
145 | 0 | } |
146 | | |
147 | | /** |
148 | | * g_ipv6_tclass_message_get_ecn: |
149 | | * @message: a traffic class message |
150 | | * |
151 | | * Gets the Explicit Congestion Notification code point stored in @message. |
152 | | * |
153 | | * Returns: An ECN value as described in [RFC 3168](https://www.rfc-editor.org/rfc/rfc3168#section-5). |
154 | | * |
155 | | * Since: 2.88 |
156 | | */ |
157 | | GEcnCodePoint |
158 | | g_ipv6_tclass_message_get_ecn (GIPv6TclassMessage *message) |
159 | 0 | { |
160 | 0 | return message->tclass & 0x3; |
161 | 0 | } |