request.c (9613B)
1 /* 2 This file is part of GNUnet. 3 Copyright (C) 2024 GNUnet e.V. 4 5 GNUnet is free software: you can redistribute it and/or modify it 6 under the terms of the GNU Affero General Public License as published 7 by the Free Software Foundation, either version 3 of the License, 8 or (at your option) any later version. 9 10 GNUnet is distributed in the hope that it will be useful, but 11 WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Affero General Public License for more details. 14 15 You should have received a copy of the GNU Affero General Public License 16 along with this program. If not, see <http://www.gnu.org/licenses/>. 17 18 SPDX-License-Identifier: AGPL3.0-or-later 19 */ 20 /* 21 * @author Tobias Frisch 22 * @file request.c 23 */ 24 25 #include "request.h" 26 27 #ifndef MESSENGER_APPLICATION_NO_PORTAL 28 #include <libportal/portal.h> 29 #endif 30 31 #ifdef MESSENGER_APPLICATION_NO_PORTAL 32 33 static gboolean 34 _request_timeout_call(gpointer user_data) 35 { 36 g_assert(user_data); 37 38 MESSENGER_Request* request = (MESSENGER_Request*) user_data; 39 40 MESSENGER_Application *app = request->application; 41 MESSENGER_RequestCallback callback = request->callback; 42 gpointer data = request->user_data; 43 44 request_cleanup(request); 45 request_drop(request); 46 47 if (callback) 48 callback(app, TRUE, FALSE, data); 49 50 return FALSE; 51 } 52 53 #endif 54 55 MESSENGER_Request* 56 request_new(MESSENGER_Application *application, 57 MESSENGER_RequestCallback callback, 58 GCancellable *cancellable, 59 gpointer user_data) 60 { 61 g_assert((application) && (cancellable)); 62 63 MESSENGER_Request* request = g_malloc(sizeof(MESSENGER_Request)); 64 65 request->application = application; 66 request->callback = callback; 67 request->cancellable = cancellable; 68 request->user_data = user_data; 69 70 #ifdef MESSENGER_APPLICATION_NO_PORTAL 71 request->timeout = util_immediate_add( 72 G_SOURCE_FUNC(_request_timeout_call), 73 request 74 ); 75 #endif 76 77 application->requests = g_list_append( 78 application->requests, 79 request 80 ); 81 82 return request; 83 } 84 85 #ifndef MESSENGER_APPLICATION_NO_PORTAL 86 static void 87 _request_background_callback(GObject *source_object, 88 GAsyncResult *result, 89 gpointer user_data) 90 { 91 g_assert((source_object) && (result) && (user_data)); 92 93 XdpPortal *portal = XDP_PORTAL(source_object); 94 MESSENGER_Request *request = (MESSENGER_Request*) user_data; 95 96 request_cleanup(request); 97 98 MESSENGER_Application *app = request->application; 99 MESSENGER_RequestCallback callback = request->callback; 100 gpointer data = request->user_data; 101 102 GError *error = NULL; 103 gboolean success = xdp_portal_request_background_finish( 104 portal, result, &error 105 ); 106 107 request_drop(request); 108 109 gboolean error_value = false; 110 if (error) 111 { 112 g_printerr("ERROR: %s\n", error->message); 113 g_error_free(error); 114 115 error_value = true; 116 } 117 118 if (callback) 119 callback(app, success, error_value, data); 120 } 121 #endif 122 123 MESSENGER_Request* 124 request_new_background(MESSENGER_Application *application, 125 XdpBackgroundFlags flags, 126 MESSENGER_RequestCallback callback, 127 gpointer user_data) 128 { 129 g_assert((application) && (callback)); 130 131 GCancellable* cancellable = g_cancellable_new(); 132 133 if (!cancellable) 134 return NULL; 135 136 MESSENGER_Request* request = request_new( 137 application, 138 callback, 139 cancellable, 140 user_data 141 ); 142 143 #ifndef MESSENGER_APPLICATION_NO_PORTAL 144 xdp_portal_request_background( 145 application->portal, 146 application->parent, 147 NULL, 148 NULL, 149 flags, 150 cancellable, 151 _request_background_callback, 152 request 153 ); 154 #endif 155 156 return request; 157 } 158 159 #ifndef MESSENGER_APPLICATION_NO_PORTAL 160 static void 161 _request_camera_callback(GObject *source_object, 162 GAsyncResult *result, 163 gpointer user_data) 164 { 165 g_assert((source_object) && (result) && (user_data)); 166 167 XdpPortal *portal = (XdpPortal*) source_object; 168 MESSENGER_Request *request = (MESSENGER_Request*) user_data; 169 170 request_cleanup(request); 171 172 MESSENGER_Application *app = request->application; 173 MESSENGER_RequestCallback callback = request->callback; 174 gpointer data = request->user_data; 175 176 GError *error = NULL; 177 gboolean success = xdp_portal_access_camera_finish( 178 portal, result, &error 179 ); 180 181 request_drop(request); 182 183 gboolean error_value = false; 184 if (error) 185 { 186 g_printerr("ERROR: %s\n", error->message); 187 g_error_free(error); 188 189 error_value = true; 190 } 191 192 if (callback) 193 callback(app, success, error_value, data); 194 } 195 #endif 196 197 MESSENGER_Request* 198 request_new_camera(MESSENGER_Application *application, 199 XdpCameraFlags flags, 200 MESSENGER_RequestCallback callback, 201 gpointer user_data) 202 { 203 g_assert((application) && (callback)); 204 205 GCancellable* cancellable = g_cancellable_new(); 206 207 if (!cancellable) 208 return NULL; 209 210 MESSENGER_Request* request = request_new( 211 application, 212 callback, 213 cancellable, 214 user_data 215 ); 216 217 #ifndef MESSENGER_APPLICATION_NO_PORTAL 218 xdp_portal_access_camera( 219 application->portal, 220 application->parent, 221 flags, 222 cancellable, 223 _request_camera_callback, 224 request 225 ); 226 #endif 227 228 return request; 229 } 230 231 #ifndef MESSENGER_APPLICATION_NO_PORTAL 232 static void 233 _request_session_start_callback(GObject *source_object, 234 GAsyncResult *result, 235 gpointer user_data) 236 { 237 g_assert((source_object) && (result) && (user_data)); 238 239 XdpSession *session = (XdpSession*) source_object; 240 MESSENGER_Request *request = (MESSENGER_Request*) user_data; 241 242 request_cleanup(request); 243 244 MESSENGER_Application *app = request->application; 245 MESSENGER_RequestCallback callback = request->callback; 246 gpointer data = request->user_data; 247 248 GError *error = NULL; 249 gboolean success = xdp_session_start_finish( 250 session, 251 result, 252 &error 253 ); 254 255 application_set_active_session(app, success? session : NULL); 256 request_drop(request); 257 258 gboolean error_value = false; 259 if (error) 260 { 261 g_printerr("ERROR: %s\n", error->message); 262 g_error_free(error); 263 264 error_value = true; 265 } 266 267 if (callback) 268 callback(app, success, error_value, data); 269 } 270 271 static void 272 _request_screencast_callback(GObject *source_object, 273 GAsyncResult *result, 274 gpointer user_data) 275 { 276 g_assert((source_object) && (result) && (user_data)); 277 278 XdpPortal *portal = (XdpPortal*) source_object; 279 MESSENGER_Request *request = (MESSENGER_Request*) user_data; 280 281 request_cleanup(request); 282 283 MESSENGER_Application *app = request->application; 284 MESSENGER_RequestCallback callback = request->callback; 285 gpointer data = request->user_data; 286 287 GError *error = NULL; 288 XdpSession *session = xdp_portal_create_screencast_session_finish( 289 portal, result, &error 290 ); 291 292 if (session) 293 application_set_active_session(app, session); 294 request_drop(request); 295 296 gboolean error_value = false; 297 if (error) 298 { 299 g_printerr("ERROR: %s\n", error->message); 300 g_error_free(error); 301 302 error_value = true; 303 } 304 305 if (!session) 306 goto skip_session_start; 307 308 GCancellable* cancellable = g_cancellable_new(); 309 310 if (!cancellable) 311 goto skip_session_start; 312 313 request = request_new( 314 app, 315 callback, 316 cancellable, 317 data 318 ); 319 320 xdp_session_start( 321 session, 322 app->parent, 323 cancellable, 324 _request_session_start_callback, 325 request 326 ); 327 328 return; 329 330 skip_session_start: 331 if (callback) 332 callback(app, false, error_value, data); 333 } 334 #endif 335 336 MESSENGER_Request* 337 request_new_screencast(MESSENGER_Application *application, 338 XdpOutputType outputs, 339 XdpScreencastFlags flags, 340 XdpCursorMode cursor_mode, 341 XdpPersistMode persist_mode, 342 MESSENGER_RequestCallback callback, 343 gpointer user_data) 344 { 345 g_assert((application) && (callback)); 346 347 GCancellable* cancellable = g_cancellable_new(); 348 349 if (!cancellable) 350 return NULL; 351 352 MESSENGER_Request* request = request_new( 353 application, 354 callback, 355 cancellable, 356 user_data 357 ); 358 359 #ifndef MESSENGER_APPLICATION_NO_PORTAL 360 xdp_portal_create_screencast_session( 361 application->portal, 362 outputs, 363 flags, 364 cursor_mode, 365 persist_mode, 366 NULL, 367 cancellable, 368 _request_screencast_callback, 369 request 370 ); 371 #endif 372 373 return request; 374 } 375 376 void 377 request_cancel(MESSENGER_Request *request) 378 { 379 g_assert(request); 380 381 #ifdef MESSENGER_APPLICATION_NO_PORTAL 382 if (request->timeout) 383 util_source_remove(request->timeout); 384 385 request->timeout = 0; 386 #endif 387 388 if (!request->cancellable) 389 return; 390 391 if (!g_cancellable_is_cancelled(request->cancellable)) 392 g_cancellable_cancel(request->cancellable); 393 } 394 395 void 396 request_cleanup(MESSENGER_Request *request) 397 { 398 g_assert(request); 399 400 #ifdef MESSENGER_APPLICATION_NO_PORTAL 401 if (request->timeout) 402 util_source_remove(request->timeout); 403 404 request->timeout = 0; 405 #endif 406 407 if (!request->cancellable) 408 return; 409 410 g_object_unref(request->cancellable); 411 request->cancellable = NULL; 412 } 413 414 void 415 request_drop(MESSENGER_Request *request) 416 { 417 g_assert(request); 418 419 if (request->application->requests) 420 request->application->requests = g_list_remove( 421 request->application->requests, 422 request 423 ); 424 425 request_delete(request); 426 } 427 428 void 429 request_delete(MESSENGER_Request *request) 430 { 431 g_assert(request); 432 433 request_cleanup(request); 434 g_free(request); 435 }