Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-3.0-or-later
2 : : // SPDX-FileCopyrightText: Andy Holmes <andrew.g.r.holmes@gmail.com>
3 : :
4 : : #define G_LOG_DOMAIN "valent-bluez-channel"
5 : :
6 : : #include "config.h"
7 : :
8 : : #include <valent.h>
9 : :
10 : : #include "valent-bluez-channel.h"
11 : : #include "valent-bluez-muxer.h"
12 : :
13 : :
14 : : struct _ValentBluezChannel
15 : : {
16 : : ValentChannel parent_instance;
17 : :
18 : : ValentBluezMuxer *muxer;
19 : : };
20 : :
21 [ + + + - ]: 7 : G_DEFINE_FINAL_TYPE (ValentBluezChannel, valent_bluez_channel, VALENT_TYPE_CHANNEL)
22 : :
23 : : typedef enum {
24 : : PROP_MUXER = 1,
25 : : } ValentBluezChannelProperty;
26 : :
27 : : static GParamSpec *properties[PROP_MUXER + 1] = { NULL, };
28 : :
29 : :
30 : : /*
31 : : * ValentChannel
32 : : */
33 : : static void
34 : 1 : valent_bluez_channel_download_task (GTask *task,
35 : : gpointer source_object,
36 : : gpointer task_data,
37 : : GCancellable *cancellable)
38 : : {
39 : 1 : ValentBluezChannel *self = VALENT_BLUEZ_CHANNEL (source_object);
40 : 1 : JsonNode *packet = (JsonNode *)task_data;
41 : 1 : JsonObject *info;
42 : 1 : const char *uuid;
43 : 1 : g_autoptr (GIOStream) stream = NULL;
44 : 1 : goffset size;
45 : 1 : GError *error = NULL;
46 : :
47 : : /* Payload Info
48 : : */
49 : 1 : info = valent_packet_get_payload_full (packet, &size, &error);
50 [ - + ]: 1 : if (info == NULL)
51 : : {
52 : 0 : g_task_return_error (task, g_steal_pointer (&error));
53 : 0 : return;
54 : : }
55 : :
56 [ + - ]: 1 : if ((uuid = json_object_get_string_member (info, "uuid")) == NULL ||
57 [ - + ]: 1 : *uuid == '\0')
58 : : {
59 : 0 : g_task_return_new_error_literal (task,
60 : : VALENT_PACKET_ERROR,
61 : : VALENT_PACKET_ERROR_INVALID_FIELD,
62 : : "Invalid \"uuid\" field");
63 : 0 : return;
64 : : }
65 : :
66 : : /* Open a new channel
67 : : */
68 : 1 : valent_object_lock (VALENT_OBJECT (self));
69 : 1 : stream = valent_bluez_muxer_channel_accept (self->muxer,
70 : : uuid,
71 : : cancellable,
72 : : &error);
73 : 1 : valent_object_unlock (VALENT_OBJECT (self));
74 [ - + ]: 1 : if (stream == NULL)
75 : : {
76 : 0 : g_task_return_error (task, g_steal_pointer (&error));
77 : 0 : return;
78 : : }
79 : :
80 : 1 : g_task_return_pointer (task, g_object_ref (stream), g_object_unref);
81 : : }
82 : :
83 : : static void
84 : 1 : valent_bluez_channel_download (ValentChannel *channel,
85 : : JsonNode *packet,
86 : : GCancellable *cancellable,
87 : : GAsyncReadyCallback callback,
88 : : gpointer user_data)
89 : : {
90 : 2 : g_autoptr (GTask) task = NULL;
91 : :
92 [ - + ]: 1 : g_assert (VALENT_IS_CHANNEL (channel));
93 [ + - ]: 1 : g_assert (VALENT_IS_PACKET (packet));
94 [ - + - - : 1 : g_assert (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
- - - - ]
95 : :
96 : 1 : task = g_task_new (channel, cancellable, callback, user_data);
97 [ + - ]: 1 : g_task_set_source_tag (task, valent_bluez_channel_download);
98 : 1 : g_task_set_task_data (task,
99 : 1 : json_node_ref (packet),
100 : : (GDestroyNotify)json_node_unref);
101 [ + - ]: 1 : g_task_run_in_thread (task, valent_bluez_channel_download_task);
102 : 1 : }
103 : :
104 : : static void
105 : 1 : valent_bluez_channel_upload_task (GTask *task,
106 : : gpointer source_object,
107 : : gpointer task_data,
108 : : GCancellable *cancellable)
109 : : {
110 : 1 : ValentBluezChannel *self = VALENT_BLUEZ_CHANNEL (source_object);
111 : 1 : JsonNode *packet = (JsonNode *)task_data;
112 : 1 : JsonObject *info;
113 : 1 : g_autoptr (GIOStream) stream = NULL;
114 : 1 : g_autofree char *uuid = NULL;
115 : 1 : GError *error = NULL;
116 : :
117 : : /* Payload Info
118 : : */
119 : 1 : uuid = g_uuid_string_random ();
120 : 1 : info = json_object_new();
121 : 1 : json_object_set_string_member (info, "uuid", uuid);
122 : 1 : valent_packet_set_payload_info (packet, info);
123 : :
124 : : /* Open a new channel
125 : : */
126 : 1 : valent_object_lock (VALENT_OBJECT (self));
127 : 1 : stream = valent_bluez_muxer_channel_open (self->muxer,
128 : : uuid,
129 : : cancellable,
130 : : &error);
131 : 1 : valent_object_unlock (VALENT_OBJECT (self));
132 [ - + ]: 1 : if (stream == NULL)
133 : : {
134 : 0 : g_task_return_error (task, g_steal_pointer (&error));
135 : 0 : return;
136 : : }
137 : :
138 : : /* Notify the device we're ready
139 : : */
140 : 1 : valent_channel_write_packet (VALENT_CHANNEL (self),
141 : : packet,
142 : : cancellable,
143 : : NULL,
144 : : NULL);
145 : 1 : g_task_return_pointer (task, g_object_ref (stream), g_object_unref);
146 : : }
147 : :
148 : : static void
149 : 1 : valent_bluez_channel_upload (ValentChannel *channel,
150 : : JsonNode *packet,
151 : : GCancellable *cancellable,
152 : : GAsyncReadyCallback callback,
153 : : gpointer user_data)
154 : : {
155 : 2 : g_autoptr (GTask) task = NULL;
156 : :
157 [ - + ]: 1 : g_assert (VALENT_IS_CHANNEL (channel));
158 [ + - ]: 1 : g_assert (VALENT_IS_PACKET (packet));
159 [ - + - - : 1 : g_assert (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
- - - - ]
160 : :
161 : 1 : task = g_task_new (channel, cancellable, callback, user_data);
162 [ + - ]: 1 : g_task_set_source_tag (task, valent_bluez_channel_upload);
163 : 1 : g_task_set_task_data (task,
164 : 1 : json_node_ref (packet),
165 : : (GDestroyNotify)json_node_unref);
166 [ + - ]: 1 : g_task_run_in_thread (task, valent_bluez_channel_upload_task);
167 : 1 : }
168 : :
169 : : /*
170 : : * GObject
171 : : */
172 : : static void
173 : 4 : valent_bluez_channel_finalize (GObject *object)
174 : : {
175 : 4 : ValentBluezChannel *self = VALENT_BLUEZ_CHANNEL (object);
176 : :
177 : 4 : valent_object_lock (VALENT_OBJECT (self));
178 [ + - ]: 4 : g_clear_object (&self->muxer);
179 : 4 : valent_object_unlock (VALENT_OBJECT (self));
180 : :
181 : 4 : G_OBJECT_CLASS (valent_bluez_channel_parent_class)->finalize (object);
182 : 4 : }
183 : :
184 : : static void
185 : 1 : valent_bluez_channel_get_property (GObject *object,
186 : : guint prop_id,
187 : : GValue *value,
188 : : GParamSpec *pspec)
189 : : {
190 : 1 : ValentBluezChannel *self = VALENT_BLUEZ_CHANNEL (object);
191 : :
192 [ + - ]: 1 : switch ((ValentBluezChannelProperty)prop_id)
193 : : {
194 : : case PROP_MUXER:
195 : 1 : valent_object_lock (VALENT_OBJECT (self));
196 : 1 : g_value_set_object (value, self->muxer);
197 : 1 : valent_object_unlock (VALENT_OBJECT (self));
198 : 1 : break;
199 : :
200 : 0 : default:
201 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
202 : : }
203 : 1 : }
204 : :
205 : : static void
206 : 4 : valent_bluez_channel_set_property (GObject *object,
207 : : guint prop_id,
208 : : const GValue *value,
209 : : GParamSpec *pspec)
210 : : {
211 : 4 : ValentBluezChannel *self = VALENT_BLUEZ_CHANNEL (object);
212 : :
213 [ + - ]: 4 : switch ((ValentBluezChannelProperty)prop_id)
214 : : {
215 : : case PROP_MUXER:
216 : 4 : valent_object_lock (VALENT_OBJECT (self));
217 : 4 : self->muxer = g_value_dup_object (value);
218 : 4 : valent_object_unlock (VALENT_OBJECT (self));
219 : 4 : break;
220 : :
221 : 0 : default:
222 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
223 : : }
224 : 4 : }
225 : :
226 : : static void
227 : 1 : valent_bluez_channel_class_init (ValentBluezChannelClass *klass)
228 : : {
229 : 1 : GObjectClass *object_class = G_OBJECT_CLASS (klass);
230 : 1 : ValentChannelClass *channel_class = VALENT_CHANNEL_CLASS (klass);
231 : :
232 : 1 : object_class->finalize = valent_bluez_channel_finalize;
233 : 1 : object_class->get_property = valent_bluez_channel_get_property;
234 : 1 : object_class->set_property = valent_bluez_channel_set_property;
235 : :
236 : 1 : channel_class->download = valent_bluez_channel_download;
237 : 1 : channel_class->upload = valent_bluez_channel_upload;
238 : :
239 : : /**
240 : : * ValentBluezChannel:muxer:
241 : : *
242 : : * The [class@Valent.BluezMuxer] responsible for muxing and demuxing data.
243 : : */
244 : 2 : properties [PROP_MUXER] =
245 : 1 : g_param_spec_object ("muxer", NULL, NULL,
246 : : VALENT_TYPE_BLUEZ_MUXER,
247 : : (G_PARAM_READWRITE |
248 : : G_PARAM_CONSTRUCT_ONLY |
249 : : G_PARAM_EXPLICIT_NOTIFY |
250 : : G_PARAM_STATIC_STRINGS));
251 : :
252 : 1 : g_object_class_install_properties (object_class, G_N_ELEMENTS (properties), properties);
253 : 1 : }
254 : :
255 : : static void
256 : 4 : valent_bluez_channel_init (ValentBluezChannel *self)
257 : : {
258 : 4 : }
259 : :
|