summaryrefslogtreecommitdiff
path: root/src/media_controller_ipc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/media_controller_ipc.c')
-rwxr-xr-xsrc/media_controller_ipc.c424
1 files changed, 424 insertions, 0 deletions
diff --git a/src/media_controller_ipc.c b/src/media_controller_ipc.c
new file mode 100755
index 0000000..9c8beb0
--- /dev/null
+++ b/src/media_controller_ipc.c
@@ -0,0 +1,424 @@
+/*
+* Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#include <stdio.h>
+#include <glib.h>
+#include "media_controller_private.h"
+
+#define MAX_RETRY_COUNT 3
+#define MAX_WAIT_COUNT 100
+#define MC_SVC_NAME "mediacontroller"
+
+/* This checks if service daemon is running */
+static gboolean __is_service_activated()
+{
+ gboolean ret = FALSE;
+ ret = mc_ipc_send_message_to_server(MC_MSG_SERVER_CONNECTION, MC_SERVER_CONNECTION_MSG);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ mc_error("Failed to mc_ipc_send_message_to_server [%d]", ret);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static char *__make_key_for_map(const char *main_key, const char *sub_key)
+{
+ return g_strdup_printf("%s.%s", main_key, sub_key);
+}
+
+static void __mc_ipc_signal_cb(GDBusConnection *connection,
+ const gchar *sender_name,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *signal_name,
+ GVariant *parameters,
+ gpointer user_data)
+{
+ char *key = __make_key_for_map(interface_name, signal_name);
+ GList *listener_list = (GList *)user_data;
+ unsigned int i = 0;
+
+ mc_debug("__mc_ipc_signal_cb Received : ");
+
+ for (i = 0; i < g_list_length(listener_list); i++) {
+ mc_ipc_listener_s *listener = (mc_ipc_listener_s *)g_list_nth_data(listener_list, i);
+ if (listener && !strcmp(listener->key, key)) {
+ gchar *message = NULL;
+ int internal_flags = 0;
+ g_variant_get(parameters, "(i&s)", &internal_flags, &message);
+ if (!message) {
+ mc_error("g_variant_get() fail");
+ break;
+ }
+ mc_debug("Received : [%s] (flags = %x) from %s.%s", message, internal_flags, listener->interface_name, listener->signal_name);
+ listener->callback(listener->interface_name, listener->signal_name, message, 0, listener->user_data);
+ }
+ }
+}
+
+static gboolean _mc_ipc_is_listener_duplicated(GList *listener_list, const char *key)
+{
+ unsigned int i = 0;
+
+ for (i = 0; i < g_list_length(listener_list); i++) {
+ mc_ipc_listener_s *listener = (mc_ipc_listener_s *)g_list_nth_data((listener_list), i);
+ mc_retvm_if(listener && !strcmp(listener->key, key), TRUE, "listener[%s] is duplicated ", key);
+ }
+
+ return FALSE;
+}
+
+static guint _mc_ipc_signal_subscribe(GDBusConnection *connection, const char *interface_name, const char *signal_name, void *user_data)
+{
+ guint ret = g_dbus_connection_signal_subscribe(
+ connection,
+ NULL,
+ interface_name,
+ signal_name,
+ MC_DBUS_PATH,
+ NULL,
+ G_DBUS_SIGNAL_FLAGS_NONE,
+ __mc_ipc_signal_cb,
+ user_data,
+ NULL);
+
+ return ret;
+}
+
+static void _mc_ipc_signal_unsubscribe(GDBusConnection *connection, guint handler)
+{
+ g_dbus_connection_signal_unsubscribe(connection, handler);
+}
+
+int mc_ipc_get_dbus_connection(GDBusConnection **connection, int *dref_count)
+{
+ GError *error = NULL;
+ GDBusConnection *_connection = NULL;
+
+ if (*dref_count > 0) {
+ mc_retvm_if(!(*connection), MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "__dbus_conn is null");
+
+ mc_error("Reference count : %d", *dref_count);
+ return MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER;
+ }
+
+ _connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
+ if (!_connection) {
+ mc_error("g_bus_get_sync failed : %s", error ? error->message : "none");
+ if (error) g_error_free(error);
+ return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+ }
+
+ (*connection) = _connection;
+ (*dref_count)++;
+
+ mc_debug("Reference count : %d", *dref_count);
+
+ if (error) g_error_free(error);
+ return MEDIA_CONTROLLER_ERROR_NONE;
+}
+
+int mc_ipc_unref_dbus_connection(GDBusConnection *connection, int *dref_count)
+{
+ if (*dref_count > 1) {
+ mc_retvm_if(!connection, MEDIA_CONTROLLER_ERROR_INVALID_OPERATION, "__dbus_conn is null");
+ (*dref_count)--;
+ mc_debug("Reference count : %d", dref_count);
+ return MEDIA_CONTROLLER_ERROR_NONE;
+ } else if (*dref_count == 1) {
+ mc_retvm_if(!connection, MEDIA_CONTROLLER_ERROR_INVALID_OPERATION, "__dbus_conn is null");
+ (*dref_count)--;
+ mc_debug("Reference count : %d", *dref_count);
+ } else {
+ mc_retvm_if(connection, MEDIA_CONTROLLER_ERROR_NONE, "__dbus_conn is not null");
+ mc_debug("Reference count : %d", *dref_count);
+ return MEDIA_CONTROLLER_ERROR_NONE;
+ }
+
+ g_object_unref(connection);
+ connection = NULL;
+
+ return MEDIA_CONTROLLER_ERROR_NONE;
+}
+
+int mc_ipc_register_listener(GList *listener_list, GDBusConnection *connection, const char *interface_name, const char *signal_name, mc_signal_received_cb callback, void *user_data)
+{
+ char *key = NULL;
+ guint handler = 0;
+
+ mc_retvm_if(listener_list == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "listener_list is NULL");
+ mc_retvm_if(connection == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "connection is NULL");
+ mc_retvm_if(interface_name == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "interface_name is NULL");
+ mc_retvm_if(signal_name == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "signal_name is NULL");
+ mc_retvm_if(callback == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "callback is NULL");
+
+ key = __make_key_for_map(interface_name, signal_name);
+
+ if (_mc_ipc_is_listener_duplicated(listener_list, key)) {
+ mc_error("listener is duplicated");
+
+ MC_SAFE_FREE(key);
+ return MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER;
+ }
+
+ mc_ipc_listener_s *listener = (mc_ipc_listener_s *)g_malloc(sizeof(mc_ipc_listener_s));
+ if (listener == NULL) {
+ mc_error("Error memroy allocation");
+ MC_SAFE_FREE(key);
+ return MEDIA_CONTROLLER_ERROR_OUT_OF_MEMORY;
+ }
+
+ handler = _mc_ipc_signal_subscribe(connection, interface_name, signal_name, listener_list);
+
+ listener->dbus_conn = connection;
+ listener->interface_name = g_strdup(interface_name);
+ listener->signal_name = g_strdup(signal_name);
+ listener->callback = callback;
+ listener->user_data = user_data;
+ listener->handler = handler;
+ listener->key = key;
+
+ (listener_list) = g_list_append((listener_list), listener);
+
+ mc_debug("listener[%s.%s] is registered", interface_name, signal_name);
+
+ return MEDIA_CONTROLLER_ERROR_NONE;
+}
+
+int mc_ipc_unregister_listener(GList *listener_list, GDBusConnection *connection, const char *interface_name, const char *signal_name)
+{
+ int i = 0;
+ char *key = NULL;
+
+ mc_retvm_if(listener_list == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "listener_list is NULL");
+ mc_retvm_if(connection == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "connection is NULL");
+ mc_retvm_if(interface_name == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "interface_name is NULL");
+ mc_retvm_if(signal_name == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "signal_name is NULL");
+
+ key = __make_key_for_map(interface_name, signal_name);
+ if (key == NULL) {
+ mc_error("fail to get key");
+ return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+ }
+
+ for (i = g_list_length(listener_list) - 1; i >= 0; i--) {
+ mc_ipc_listener_s *listener = (mc_ipc_listener_s *)g_list_nth_data(listener_list, i);
+ if (listener && !strcmp(listener->key, key)) {
+ _mc_ipc_signal_unsubscribe(connection, listener->handler);
+ MC_SAFE_FREE(listener->interface_name);
+ MC_SAFE_FREE(listener->signal_name);
+ MC_SAFE_FREE(listener->key);
+ (listener_list) = g_list_remove(listener_list, listener);
+ MC_SAFE_FREE(listener);
+ mc_debug("listener[%s.%s] is unregistered", interface_name, signal_name);
+ }
+ }
+
+ MC_SAFE_FREE(key);
+
+ return MEDIA_CONTROLLER_ERROR_NONE;
+}
+
+int mc_ipc_unregister_all_listener(GList *listener_list, GDBusConnection *connection)
+{
+ int i = 0;
+
+ mc_retvm_if(connection == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "connection is NULL");
+ mc_retvm_if(listener_list == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "listener_list is NULL");
+
+ for (i = g_list_length(listener_list) - 1; i >= 0; i--) {
+ mc_ipc_listener_s *listener = (mc_ipc_listener_s *)g_list_nth_data(listener_list, i);
+ if (listener) {
+ _mc_ipc_signal_unsubscribe(connection, listener->handler);
+ MC_SAFE_FREE(listener->interface_name);
+ MC_SAFE_FREE(listener->signal_name);
+ MC_SAFE_FREE(listener->key);
+ (listener_list) = g_list_remove(listener_list, listener);
+ MC_SAFE_FREE(listener);
+ }
+ }
+
+ return MEDIA_CONTROLLER_ERROR_NONE;
+}
+
+int mc_ipc_send_message(GDBusConnection *connection, const char *dbus_name, const char *interface_name, const char *signal_name, const char *message, int flags)
+{
+ GError *error = NULL;
+
+ mc_retvm_if(connection == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "connection is NULL");
+ mc_retvm_if(!MC_STRING_VALID(signal_name), MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Invalid signal_name");
+ mc_retvm_if(!MC_STRING_VALID(message), MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Invalid message");
+
+ mc_debug("emit signal - interface_name [%s], signal_name [%s]", interface_name, signal_name);
+
+ gboolean emmiting = g_dbus_connection_emit_signal(
+ connection,
+ dbus_name,
+ MC_DBUS_PATH,
+ interface_name,
+ signal_name,
+ g_variant_new("(is)", 0, message),
+ &error);
+ if (!emmiting) {
+ mc_error("g_dbus_connection_emit_signal failed : %s", error ? error->message : "none");
+ if (error) {
+ mc_error("Error in g_dbus_connection_emit_signal");
+ g_error_free(error);
+ }
+ return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+ }
+
+ return MEDIA_CONTROLLER_ERROR_NONE;
+}
+
+int mc_ipc_send_message_to_server(mc_msg_type_e msg_type, const char *request_msg)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ int request_msg_size = 0;
+ int sockfd = -1;
+ mc_sock_info_s sock_info;
+ struct sockaddr_un serv_addr;
+ int retry_count = 0;
+
+ if (!MC_STRING_VALID(request_msg)) {
+ mc_error("invalid query");
+ return MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER;
+ }
+
+ request_msg_size = strlen(request_msg);
+ if (request_msg_size >= MAX_MSG_SIZE) {
+ mc_error("Query is Too long. [%d] query size limit is [%d]", request_msg_size, MAX_MSG_SIZE);
+ return MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER;
+ }
+
+ mc_comm_msg_s send_msg;
+ memset((void *)&send_msg, 0, sizeof(mc_comm_msg_s));
+
+ send_msg.msg_type = msg_type;
+ send_msg.pid = getpid();
+ send_msg.msg_size = request_msg_size;
+ strncpy(send_msg.msg, request_msg, sizeof(send_msg.msg) - 1);
+
+ /*Create Socket*/
+ ret = mc_ipc_create_client_socket(MC_TIMEOUT_SEC_5, &sock_info);
+ sockfd = sock_info.sock_fd;
+ mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, ret, "socket is not created properly");
+
+ /*Set server Address*/
+ memset(&serv_addr, 0, sizeof(serv_addr));
+ serv_addr.sun_family = AF_UNIX;
+ strncpy(serv_addr.sun_path, MC_IPC_PATH, sizeof(serv_addr.sun_path) - 1);
+
+ /* Connecting to the media db server */
+ if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
+ mc_stderror("connect error");
+ mc_ipc_delete_client_socket(&sock_info);
+ return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+ }
+
+ /* Send request */
+ if (send(sockfd, &send_msg, sizeof(send_msg), 0) != sizeof(send_msg)) {
+ mc_stderror("send failed");
+ mc_ipc_delete_client_socket(&sock_info);
+ return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+ }
+
+ /*Receive Response*/
+ int recv_msg_size = -1;
+ int recv_msg = -1;
+RETRY:
+ if ((recv_msg_size = recv(sockfd, &recv_msg, sizeof(recv_msg), 0)) < 0) {
+ mc_error("recv failed : [%d]", sockfd);
+ mc_stderror("recv failed");
+
+ if (errno == EINTR) {
+ mc_stderror("catch interrupt");
+ goto RETRY;
+ }
+
+ if (errno == EWOULDBLOCK) {
+ if (retry_count < MAX_RETRY_COUNT) {
+ mc_error("TIME OUT[%d]", retry_count);
+ retry_count++;
+ goto RETRY;
+ }
+
+ mc_ipc_delete_client_socket(&sock_info);
+ mc_error("Timeout. Can't try any more");
+ return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+ } else {
+ mc_stderror("recv failed");
+ mc_ipc_delete_client_socket(&sock_info);
+ return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+ }
+ }
+
+ mc_debug("RECEIVE OK [%d]", recv_msg);
+ ret = recv_msg;
+
+ mc_ipc_delete_client_socket(&sock_info);
+
+ return ret;
+}
+
+int mc_ipc_service_connect(void)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ int sockfd = -1;
+ mc_sock_info_s sock_info;
+ struct sockaddr_un serv_addr;
+ unsigned int retrycount = 0;
+
+ if (__is_service_activated() == TRUE) {
+ mc_debug("service is already running!");
+ return MEDIA_CONTROLLER_ERROR_NONE;
+ }
+
+ /*Create Socket*/
+ ret = mc_ipc_create_client_socket(MC_TIMEOUT_SEC_5, &sock_info);
+ sockfd = sock_info.sock_fd;
+ mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, ret, "socket is not created properly");
+
+ /*Set server Address*/
+ memset(&serv_addr, 0, sizeof(serv_addr));
+ serv_addr.sun_family = AF_UNIX;
+ strncpy(serv_addr.sun_path, MC_SOCK_ACTIVATION_PATH, sizeof(serv_addr.sun_path) - 1);
+
+ /* Connecting to the media db server */
+ if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
+ mc_stderror("connect error");
+ mc_ipc_delete_client_socket(&sock_info);
+ return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+ }
+
+ mc_ipc_delete_client_socket(&sock_info);
+
+ while((__is_service_activated() == FALSE) && (retrycount++ < MAX_WAIT_COUNT)) {
+ MC_MILLISEC_SLEEP(200);
+ mc_error("[No-Error] retry count [%d]", retrycount);
+ }
+
+ if (retrycount < MAX_WAIT_COUNT) {
+ mc_debug("CONNECT OK");
+ ret = MEDIA_CONTROLLER_ERROR_NONE;
+ } else {
+ mc_error("CONNECT FAIL");
+ ret = MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+ }
+
+ return ret;
+}