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 [ + + + - : 6542 : 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 : 2440 : g_socket_control_message_get_size (GSocketControlMessage *message) 70 : : { 71 : 2440 : g_return_val_if_fail (G_IS_SOCKET_CONTROL_MESSAGE (message), 0); 72 : : 73 : 2440 : 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 : 1220 : g_socket_control_message_get_level (GSocketControlMessage *message) 89 : : { 90 : 1220 : g_return_val_if_fail (G_IS_SOCKET_CONTROL_MESSAGE (message), 0); 91 : : 92 : 1220 : 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 : 1220 : g_socket_control_message_get_msg_type (GSocketControlMessage *message) 108 : : { 109 : 1220 : g_return_val_if_fail (G_IS_SOCKET_CONTROL_MESSAGE (message), 0); 110 : : 111 : 1220 : 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 : 1220 : g_socket_control_message_serialize (GSocketControlMessage *message, 130 : : gpointer data) 131 : : { 132 : 1220 : g_return_if_fail (G_IS_SOCKET_CONTROL_MESSAGE (message)); 133 : : 134 : 1220 : G_SOCKET_CONTROL_MESSAGE_GET_CLASS (message)->serialize (message, data); 135 : : } 136 : : 137 : : 138 : : static void 139 : 1238 : g_socket_control_message_init (GSocketControlMessage *message) 140 : : { 141 : 1238 : } 142 : : 143 : : static void 144 : 98 : g_socket_control_message_class_init (GSocketControlMessageClass *class) 145 : : { 146 : 98 : } 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 : 16 : 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 : 16 : g_type_ensure (G_TYPE_UNIX_CREDENTIALS_MESSAGE); 181 : 16 : g_type_ensure (G_TYPE_UNIX_FD_MESSAGE); 182 : : #endif 183 : : 184 : 16 : message_types = g_type_children (G_TYPE_SOCKET_CONTROL_MESSAGE, &n_message_types); 185 : : 186 : 16 : message = NULL; 187 [ + - ]: 31 : for (i = 0; i < n_message_types; i++) 188 : : { 189 : : GSocketControlMessageClass *class; 190 : : 191 : 31 : class = g_type_class_ref (message_types[i]); 192 : 31 : message = class->deserialize (level, type, size, data); 193 : 31 : g_type_class_unref (class); 194 : : 195 [ + + ]: 31 : if (message != NULL) 196 : 16 : break; 197 : : } 198 : : 199 : 16 : 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 : 16 : return message; 212 : : }