| | 566 | struct cdbus_async_call_context |
| | 567 | { |
| | 568 | void * context; |
| | 569 | void (* callback)(void * context, void * cookie, DBusMessage * reply_ptr); |
| | 570 | dbus_uint64_t cookie[0]; |
| | 571 | }; |
| | 572 | |
| | 573 | #define ctx_ptr ((struct cdbus_async_call_context *)user_data) |
| | 574 | |
| | 575 | static void cdbus_async_call_reply_handler(DBusPendingCall * pending_call_ptr, void * user_data) |
| | 576 | { |
| | 577 | DBusMessage * reply_ptr; |
| | 578 | |
| | 579 | reply_ptr = dbus_pending_call_steal_reply(pending_call_ptr); |
| | 580 | if (reply_ptr == NULL) |
| | 581 | { |
| | 582 | log_error("pending call notify called but reply is NULL"); |
| | 583 | } |
| | 584 | else |
| | 585 | { |
| | 586 | ctx_ptr->callback(ctx_ptr->context, ctx_ptr->cookie, reply_ptr); |
| | 587 | ctx_ptr->callback = NULL; /* mark that callback is already called */ |
| | 588 | |
| | 589 | dbus_message_unref(reply_ptr); |
| | 590 | } |
| | 591 | } |
| | 592 | |
| | 593 | static void cdbus_async_call_reply_context_free(void * user_data) |
| | 594 | { |
| | 595 | if (ctx_ptr->callback != NULL) |
| | 596 | { |
| | 597 | ctx_ptr->callback(ctx_ptr->context, ctx_ptr->cookie, NULL); |
| | 598 | } |
| | 599 | |
| | 600 | free(ctx_ptr); |
| | 601 | } |
| | 602 | |
| | 603 | #undef ctx_ptr |
| | 604 | |
| | 605 | bool |
| | 606 | cdbus_call_async( |
| | 607 | DBusMessage * request_ptr, |
| | 608 | void * context, |
| | 609 | void * cookie, |
| | 610 | size_t cookie_size, |
| | 611 | void (* callback)(void * context, void * cookie, DBusMessage * reply_ptr)) |
| | 612 | { |
| | 613 | bool ret; |
| | 614 | DBusPendingCall * pending_call_ptr; |
| | 615 | struct cdbus_async_call_context * ctx_ptr; |
| | 616 | |
| | 617 | ret = false; |
| | 618 | |
| | 619 | if (!dbus_connection_send_with_reply(cdbus_g_dbus_connection, request_ptr, &pending_call_ptr, DBUS_TIMEOUT_INFINITE)) |
| | 620 | { |
| | 621 | log_error("dbus_connection_send_with_reply() failed."); |
| | 622 | goto exit; |
| | 623 | } |
| | 624 | |
| | 625 | if (pending_call_ptr == NULL) |
| | 626 | { |
| | 627 | log_error("dbus_connection_send_with_reply() returned NULL pending call object pointer."); |
| | 628 | goto exit; |
| | 629 | } |
| | 630 | |
| | 631 | ctx_ptr = malloc(sizeof(struct cdbus_async_call_context) + cookie_size); |
| | 632 | if (ctx_ptr == NULL) |
| | 633 | { |
| | 634 | log_error("malloc() failed to allocate cdbus_async_call_context struct with cookie size of %zu", cookie_size); |
| | 635 | goto unref; |
| | 636 | } |
| | 637 | |
| | 638 | ctx_ptr->context = context; |
| | 639 | ctx_ptr->callback = callback; |
| | 640 | memcpy(ctx_ptr->cookie, cookie, cookie_size); |
| | 641 | |
| | 642 | ret = dbus_pending_call_set_notify(pending_call_ptr, cdbus_async_call_reply_handler, ctx_ptr, cdbus_async_call_reply_context_free); |
| | 643 | if (!ret) |
| | 644 | { |
| | 645 | log_error("dbus_pending_call_set_notify() failed."); |
| | 646 | goto free; |
| | 647 | } |
| | 648 | |
| | 649 | goto unref; |
| | 650 | |
| | 651 | free: |
| | 652 | free(ctx_ptr); |
| | 653 | unref: |
| | 654 | dbus_pending_call_unref(pending_call_ptr); |
| | 655 | exit: |
| | 656 | return ret; |
| | 657 | } |
| | 658 | |