summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xCMakeLists.txt2
-rwxr-xr-xinclude/notification.h40
-rwxr-xr-xsrc/notification.c149
3 files changed, 190 insertions, 1 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4c230df..7fa2c0a 100755
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -57,7 +57,7 @@ FOREACH(flag ${pkgs_CFLAGS})
SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
ENDFOREACH(flag)
-SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden -g -Wall")
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden -g -Wall -Wno-unused-result")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}")
SET(CMAKE_SKIP_BUILD_RPATH TRUE)
diff --git a/include/notification.h b/include/notification.h
index ddc7e9c..0243f75 100755
--- a/include/notification.h
+++ b/include/notification.h
@@ -1885,6 +1885,46 @@ notification_error_e notification_op_get_data(notification_op *noti_op,
void *data);
/**
+ * @brief Wait for a response coming for this notification
+ * @details The notification should have the EXECUTE_TYPE_RESPONDING flag
+ * @remarks
+ * @param[in] noti notification handle
+ * @param[in] timeout in seconds - 0 for infinite
+ * @param[out] integer response
+ * @param[out] text response
+ * @return NOTIFICATION_ERROR_NONE if success, other value if failure
+ * @retval NOTIFICATION_ERROR_NONE - success
+ * @retval NOTIFICATION_ERROR_INVALID_DATA - invalid parameter
+ * @retval NOTIFICATION_ERROR_NO_MEMORY - not enough memory
+ * @pre notification handle should be created by notification_new().
+ * @post
+ * @see
+ */
+notification_error_e notification_wait_response(notification_h noti,
+ int timeout,
+ int *respi,
+ char **respc);
+
+/**
+ * @brief Send a response for a waiting notification
+ * @details
+ * @remarks
+ * @param[in] noti notification handle
+ * @param[in] integer response
+ * @param[in] text response
+ * @return NOTIFICATION_ERROR_NONE if success, other value if failure
+ * @retval NOTIFICATION_ERROR_NONE - success
+ * @retval NOTIFICATION_ERROR_INVALID_DATA - invalid parameter
+ * @retval NOTIFICATION_ERROR_NO_MEMORY - not enough memory
+ * @pre notification handle should be created by notification_new().
+ * @post
+ * @see
+ */
+notification_error_e notification_send_response(notification_h noti,
+ int respi,
+ char *respc);
+
+/**
* @}
*/
diff --git a/src/notification.c b/src/notification.c
index f11ac22..17b9985 100755
--- a/src/notification.c
+++ b/src/notification.c
@@ -19,11 +19,16 @@
*
*/
+#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
+#include <sys/socket.h>
+#include <sys/syscall.h>
+#include <sys/time.h>
+#include <sys/un.h>
#include <libintl.h>
#include <dbus/dbus.h>
#include <dbus/dbus-glib-lowlevel.h>
@@ -2805,3 +2810,147 @@ EXPORT_API notification_error_e notification_delete_group_by_priv_id(const char
}
return NOTIFICATION_ERROR_NONE;
}
+
+EXPORT_API notification_error_e notification_wait_response(notification_h noti,
+ int timeout,
+ int *respi,
+ char **respc)
+{
+ bundle *b, *bc = NULL;
+ pid_t tid;
+ const char *tid_c;
+ int sock_fd, msg_fd;
+ char *sock_path;
+ struct sockaddr_un sock_addr;
+ char msg_buffer[1024];
+ ssize_t msg_size;
+ struct timeval timeout_tv;
+ char *resp;
+
+ /* a response packet *must* have an execute option TYPE_RESPONDING
+ with an associated bundle.
+ If its bundle does not already contain a "tid" hint (which
+ complex applications such as xwalk may overwrite), we will
+ try to find the TID and set it in the bundle ourselves. */
+ notification_get_execute_option (noti, NOTIFICATION_EXECUTE_TYPE_RESPONDING,
+ NULL, &b);
+
+ if (b == NULL)
+ return NOTIFICATION_ERROR_INVALID_DATA;
+
+ tid_c = bundle_get_val(b, "tid");
+ if (tid_c == NULL) {
+ tid = syscall(SYS_gettid);
+ asprintf((char **)&tid_c, "%d", tid);
+ bc = bundle_dup(b);
+ bundle_add(bc, "tid", tid_c);
+ notification_set_execute_option (noti, NOTIFICATION_EXECUTE_TYPE_RESPONDING,
+ NULL, NULL, bc);
+ notification_update(noti);
+ }
+
+ sock_fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
+ if (sock_fd == -1)
+ return NOTIFICATION_ERROR_NO_MEMORY;
+
+ sock_addr.sun_family = AF_UNIX;
+ asprintf(&sock_path, "/tmp/.notification-%s", tid_c);
+ strncpy(sock_addr.sun_path, sock_path, sizeof(sock_addr.sun_path) - 1);
+ if (bind(sock_fd, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) == -1) {
+ close(sock_fd);
+ free(sock_path);
+ free((char *)tid_c);
+ return NOTIFICATION_ERROR_NO_MEMORY;
+ }
+
+ if (timeout > 0) {
+ timeout_tv.tv_sec = timeout;
+ timeout_tv.tv_usec = 0;
+ setsockopt(sock_fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout_tv, sizeof(timeout_tv));
+ setsockopt(sock_fd, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout_tv, sizeof(timeout_tv));
+ }
+
+ listen(sock_fd, 1);
+ msg_fd = accept(sock_fd, NULL, 0);
+ do {
+ msg_size = read(msg_fd, msg_buffer, 1024);
+ } while (msg_size > 0);
+
+ resp = strtok(msg_buffer, "\n");
+ if (resp) {
+ *respi = atoi(resp);
+ if (respc != NULL) {
+ resp = strtok(NULL, "\n");
+ if (resp)
+ *respc = resp;
+ else
+ *respc = NULL;
+ }
+ } else {
+ *respi = 0;
+ if (respc != NULL)
+ *respc = NULL;
+ }
+
+ close(sock_fd);
+ unlink(sock_path);
+ free(sock_path);
+ free((char *)tid_c);
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API notification_error_e notification_send_response(notification_h noti,
+ int respi,
+ char *respc)
+{
+ bundle *b = NULL;
+ notification_h notic;
+ int notic_id;
+ char *notic_pkgname;
+ int tid;
+ const char *tid_c;
+ int sock_fd;
+ char *sock_path;
+ struct sockaddr_un sock_addr;
+ char *msg_buffer;
+
+ notification_get_id(noti, NULL, &notic_id);
+ notification_get_pkgname(noti, &notic_pkgname);
+ notic = notification_load(notic_pkgname, notic_id);
+ notification_get_execute_option (notic, NOTIFICATION_EXECUTE_TYPE_RESPONDING,
+ NULL, &b);
+
+ if (b == NULL)
+ return NOTIFICATION_ERROR_INVALID_DATA;
+
+ tid_c = bundle_get_val(b, "tid");
+ if (tid_c == NULL)
+ return NOTIFICATION_ERROR_INVALID_DATA;
+ tid = atoi(tid_c);
+
+ sock_fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
+ if (sock_fd == -1)
+ return NOTIFICATION_ERROR_NO_MEMORY;
+
+ sock_addr.sun_family = AF_UNIX;
+ asprintf(&sock_path, "/tmp/.notification-%d", tid);
+ strncpy(sock_addr.sun_path, sock_path, sizeof(sock_addr.sun_path) - 1);
+ if (connect(sock_fd, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) == -1) {
+ close(sock_fd);
+ free(sock_path);
+ return NOTIFICATION_ERROR_NO_MEMORY;
+ }
+
+ if (respc)
+ asprintf(&msg_buffer, "%d\n%s\n", respi, respc);
+ else
+ asprintf(&msg_buffer, "%d\n", respi);
+ write(sock_fd, msg_buffer, strlen(msg_buffer) + 1);
+
+ close(sock_fd);
+ free(sock_path);
+ free(msg_buffer);
+
+ return NOTIFICATION_ERROR_NONE;
+}