Branch data Line data Source code
1 : : /* GIO - GLib Input, Output and Streaming Library
2 : : *
3 : : * Copyright © 2009 Codethink Limited
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: Ryan Lortie <desrt@desrt.ca>
15 : : */
16 : :
17 : : /**
18 : : * GSocketControlMessage:
19 : : *
20 : : * A `GSocketControlMessage` is a special-purpose utility message that
21 : : * can be sent to or received from a [class@Gio.Socket]. These types of
22 : : * messages are often called ‘ancillary data’.
23 : : *
24 : : * The message can represent some sort of special instruction to or
25 : : * information from the socket or can represent a special kind of
26 : : * transfer to the peer (for example, sending a file descriptor over
27 : : * a UNIX socket).
28 : : *
29 : : * These messages are sent with [method@Gio.Socket.send_message] and received
30 : : * with [method@Gio.Socket.receive_message].
31 : : *
32 : : * To extend the set of control message that can be sent, subclass this
33 : : * class and override the `get_size`, `get_level`, `get_type` and `serialize`
34 : : * methods.
35 : : *
36 : : * To extend the set of control messages that can be received, subclass
37 : : * this class and implement the `deserialize` method. Also, make sure your
38 : : * class is registered with the [type@GObject.Type] type system before calling
39 : : * [method@Gio.Socket.receive_message] to read such a message.
40 : : *
41 : : * Since: 2.22
42 : : */
43 : :
44 : : #include "config.h"
45 : : #include "gsocketcontrolmessage.h"
46 : : #include "gnetworkingprivate.h"
47 : : #include "glibintl.h"
48 : :
49 : : #ifndef G_OS_WIN32
50 : : #include "gunixcredentialsmessage.h"
51 : : #include "gunixfdmessage.h"
52 : : #endif
53 : :
54 : :
55 : 8533 : G_DEFINE_ABSTRACT_TYPE (GSocketControlMessage, g_socket_control_message, G_TYPE_OBJECT)
56 : :
57 : : /**
58 : : * g_socket_control_message_get_size:
59 : : * @message: a #GSocketControlMessage
60 : : *
61 : : * Returns the space required for the control message, not including
62 : : * headers or alignment.
63 : : *
64 : : * Returns: The number of bytes required.
65 : : *
66 : : * Since: 2.22
67 : : */
68 : : gsize
69 : 3234 : g_socket_control_message_get_size (GSocketControlMessage *message)
70 : : {
71 : 3234 : g_return_val_if_fail (G_IS_SOCKET_CONTROL_MESSAGE (message), 0);
72 : :
73 : 3234 : return G_SOCKET_CONTROL_MESSAGE_GET_CLASS (message)->get_size (message);
74 : : }
75 : :
76 : : /**
77 : : * g_socket_control_message_get_level:
78 : : * @message: a #GSocketControlMessage
79 : : *
80 : : * Returns the "level" (i.e. the originating protocol) of the control message.
81 : : * This is often SOL_SOCKET.
82 : : *
83 : : * Returns: an integer describing the level
84 : : *
85 : : * Since: 2.22
86 : : */
87 : : int
88 : 1617 : g_socket_control_message_get_level (GSocketControlMessage *message)
89 : : {
90 : 1617 : g_return_val_if_fail (G_IS_SOCKET_CONTROL_MESSAGE (message), 0);
91 : :
92 : 1617 : return G_SOCKET_CONTROL_MESSAGE_GET_CLASS (message)->get_level (message);
93 : : }
94 : :
95 : : /**
96 : : * g_socket_control_message_get_msg_type:
97 : : * @message: a #GSocketControlMessage
98 : : *
99 : : * Returns the protocol specific type of the control message.
100 : : * For instance, for UNIX fd passing this would be SCM_RIGHTS.
101 : : *
102 : : * Returns: an integer describing the type of control message
103 : : *
104 : : * Since: 2.22
105 : : */
106 : : int
107 : 1617 : g_socket_control_message_get_msg_type (GSocketControlMessage *message)
108 : : {
109 : 1617 : g_return_val_if_fail (G_IS_SOCKET_CONTROL_MESSAGE (message), 0);
110 : :
111 : 1617 : return G_SOCKET_CONTROL_MESSAGE_GET_CLASS (message)->get_type (message);
112 : : }
113 : :
114 : : /**
115 : : * g_socket_control_message_serialize:
116 : : * @message: a #GSocketControlMessage
117 : : * @data: (not nullable): A buffer to write data to
118 : : *
119 : : * Converts the data in the message to bytes placed in the
120 : : * message.
121 : : *
122 : : * @data is guaranteed to have enough space to fit the size
123 : : * returned by g_socket_control_message_get_size() on this
124 : : * object.
125 : : *
126 : : * Since: 2.22
127 : : */
128 : : void
129 : 1617 : g_socket_control_message_serialize (GSocketControlMessage *message,
130 : : gpointer data)
131 : : {
132 : 1617 : g_return_if_fail (G_IS_SOCKET_CONTROL_MESSAGE (message));
133 : :
134 : 1617 : G_SOCKET_CONTROL_MESSAGE_GET_CLASS (message)->serialize (message, data);
135 : : }
136 : :
137 : :
138 : : static void
139 : 1636 : g_socket_control_message_init (GSocketControlMessage *message)
140 : : {
141 : 1636 : }
142 : :
143 : : static void
144 : 99 : g_socket_control_message_class_init (GSocketControlMessageClass *class)
145 : : {
146 : 99 : }
147 : :
148 : : /**
149 : : * g_socket_control_message_deserialize:
150 : : * @level: a socket level
151 : : * @type: a socket control message type for the given @level
152 : : * @size: the size of the data in bytes
153 : : * @data: (array length=size) (element-type guint8): pointer to the message data
154 : : *
155 : : * Tries to deserialize a socket control message of a given
156 : : * @level and @type. This will ask all known (to GType) subclasses
157 : : * of #GSocketControlMessage if they can understand this kind
158 : : * of message and if so deserialize it into a #GSocketControlMessage.
159 : : *
160 : : * If there is no implementation for this kind of control message, %NULL
161 : : * will be returned.
162 : : *
163 : : * Returns: (nullable) (transfer full): the deserialized message or %NULL
164 : : *
165 : : * Since: 2.22
166 : : */
167 : : GSocketControlMessage *
168 : 17 : g_socket_control_message_deserialize (int level,
169 : : int type,
170 : : gsize size,
171 : : gpointer data)
172 : : {
173 : : GSocketControlMessage *message;
174 : : GType *message_types;
175 : : guint n_message_types;
176 : : guint i;
177 : :
178 : : /* Ensure we know about the built in types */
179 : : #ifndef G_OS_WIN32
180 : 17 : g_type_ensure (G_TYPE_UNIX_CREDENTIALS_MESSAGE);
181 : 17 : g_type_ensure (G_TYPE_UNIX_FD_MESSAGE);
182 : : #endif
183 : :
184 : 17 : message_types = g_type_children (G_TYPE_SOCKET_CONTROL_MESSAGE, &n_message_types);
185 : :
186 : 17 : message = NULL;
187 : 33 : for (i = 0; i < n_message_types; i++)
188 : : {
189 : : GSocketControlMessageClass *class;
190 : :
191 : 33 : class = g_type_class_ref (message_types[i]);
192 : 33 : message = class->deserialize (level, type, size, data);
193 : 33 : g_type_class_unref (class);
194 : :
195 : 33 : if (message != NULL)
196 : 17 : break;
197 : : }
198 : :
199 : 17 : g_free (message_types);
200 : :
201 : : /* It's not a bug if we can't deserialize the control message - for
202 : : * example, the control message may be be discarded if it is deemed
203 : : * empty, see e.g.
204 : : *
205 : : * https://gitlab.gnome.org/GNOME/glib/commit/ec91ed00f14c70cca9749347b8ebc19d72d9885b
206 : : *
207 : : * Therefore, it's not appropriate to print a warning about not
208 : : * being able to deserialize the message.
209 : : */
210 : :
211 : 17 : return message;
212 : : }
|