#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
+typedef struct client_channel_s {
+ int fd;
+ pid_t pid;
+ uid_t uid;
+ GRecMutex mutex;
+} client_channel_t;
+
struct aul_request_s {
int cmd;
int clifd;
aul_handler aul;
subapp_handler subapp;
data_control_provider_handler dcp;
+ GList* clients;
+ GRecMutex mutex;
} launch_context;
static launch_context __context;
+static void __destroy_client_channel(gpointer data)
+{
+ client_channel_t *channel = data;
+
+ g_rec_mutex_lock(&channel->mutex);
+ g_rec_mutex_unlock(&channel->mutex);
+ g_rec_mutex_clear(&channel->mutex);
+
+ free(channel);
+}
+
+static client_channel_t *__create_client_channel(int fd, pid_t pid, uid_t uid)
+{
+ client_channel_t *channel;
+
+ channel = calloc(1, sizeof(client_channel_t));
+ if (!channel) {
+ _E("Out of memory");
+ return NULL;
+ }
+
+ g_rec_mutex_init(&channel->mutex);
+
+ channel->fd = fd;
+ channel->pid = pid;
+ channel->uid = uid;
+
+ return channel;
+}
+
+static void __add_client_channel(client_channel_t *channel)
+{
+ g_rec_mutex_lock(&__context.mutex);
+ __context.clients = g_list_append(__context.clients, channel);
+ g_rec_mutex_unlock(&__context.mutex);
+}
+
+static void __remove_client_channel(client_channel_t *channel)
+{
+ g_rec_mutex_lock(&__context.mutex);
+ __context.clients = g_list_remove(__context.clients, channel);
+ g_rec_mutex_unlock(&__context.mutex);
+}
+
+static client_channel_t *__find_client_channel(int fd)
+{
+ client_channel_t *channel;
+ GList *iter;
+
+ g_rec_mutex_lock(&__context.mutex);
+ iter = __context.clients;
+ while (iter) {
+ channel = iter->data;
+ if (channel->fd == fd) {
+ g_rec_mutex_unlock(&__context.mutex);
+ return channel;
+ }
+
+ iter = g_list_next(iter);
+ }
+ g_rec_mutex_unlock(&__context.mutex);
+
+ return NULL;
+}
+
static void __invoke_aul_handler(aul_type type, bundle *b)
{
if (__context.aul.callback)
aul_watchdog_stop();
}
+static void __dispatch_app_connect(aul_request_h req)
+{
+}
+
static dispatcher __dispatcher[] = {
[APP_START] = __dispatch_app_start,
[APP_START_RES] = __dispatch_app_start,
[APP_TERM_BG_INSTANCE] = __dispatch_app_term_bg_inst,
[WATCHDOG_ENABLE] = __dispatch_watchdog_enable,
[WATCHDOG_DISABLE] = __dispatch_watchdog_disable,
+ [APP_CONNECT] = __dispatch_app_connect,
};
static void __destroy_request(struct aul_request_s *req)
static int __send_result(struct aul_request_s *req, int res)
{
+ client_channel_t *channel;
int ret;
- if (req->cmd != WIDGET_GET_CONTENT && req->clifd > 0) {
- ret = aul_sock_send_result(req->clifd, res);
- req->clifd = -1;
+ if (req->cmd != WIDGET_GET_CONTENT && req->clifd >= 0) {
+ channel = __find_client_channel(req->clifd);
+ if (!channel) {
+ _E("Failed to find client channel. fd(%d)", req->clifd);
+ return -1;
+ }
+
+ g_rec_mutex_lock(&channel->mutex);
+ ret = aul_sock_send_result_v2(req->clifd, res, false);
+ g_rec_mutex_unlock(&channel->mutex);
if (ret < 0) {
_E("Failed to send result. cmd(%s:%d)",
aul_cmd_convert_to_string(req->cmd),
if (!__context.initialized) {
_W("Ignore request(%d)", req->cmd);
- __send_result(req, -1);
__destroy_request(req);
return G_SOURCE_REMOVE;
}
return G_SOURCE_REMOVE;
}
-static bool __worker_io_job_cb(int fd, void *user_data)
+static void __process_app_pkt(app_pkt_t *pkt, int clifd)
{
- aul_worker_h worker = user_data;
struct aul_request_s *req;
- app_pkt_t *pkt;
bundle *b = NULL;
- int clifd;
+
+ if (pkt->opt & AUL_SOCK_BUNDLE) {
+ b = bundle_decode(pkt->data, pkt->len);
+ if (!b) {
+ _E("Failed to decode the packet");
+ return;
+ }
+ }
+
+ req = __create_request(pkt->cmd, clifd, b);
+ if (!req) {
+ bundle_free(b);
+ return;
+ }
+
+ g_idle_add(__dispatch_request, req);
+}
+
+static bool __received_event_cb(int fd, int condition, void *user_data)
+{
+ aul_worker_h worker = user_data;
+ client_channel_t *channel;
+ app_pkt_t *pkt;
+ int ret;
+
+ channel = __find_client_channel(fd);
+ if (!channel) {
+ _E("Failed to find client channel. fd(%d)", fd);
+ return false;
+ }
+
+ if (condition & (AUL_IO_HUP | AUL_IO_ERR | AUL_IO_NVAL)) {
+ _E("IO error occurred. condition(%d), fd(%d)", condition, fd);
+ __remove_client_channel(channel);
+ __destroy_client_channel(channel);
+ return false;
+ }
+
+ g_rec_mutex_lock(&channel->mutex);
+ ret = aul_sock_recv_reply_pkt_v2(fd, &pkt, false);
+ g_rec_mutex_unlock(&channel->mutex);
+ if (ret != 0) {
+ _E("Failed to receive the packet. error(%d)", ret);
+ return true;
+ }
+
+ __process_app_pkt(pkt, fd);
+ aul_worker_add_anr_timer(worker, pkt->cmd);
+ free(pkt);
+
+ return true;
+}
+
+static bool __connected_event_cb(int fd, int condition, void *user_data)
+{
+ int cond = AUL_IO_IN | AUL_IO_HUP | AUL_IO_ERR | AUL_IO_NVAL;
+ aul_worker_h worker = user_data;
+ client_channel_t *channel = NULL;
struct ucred cr;
+ int clifd;
+ app_pkt_t *pkt;
+ int ret;
pkt = aul_sock_recv_pkt(fd, &clifd, &cr);
if (!pkt) {
return true;
}
+ _W("pid(%d), clifd(%d), cmd(%d)", cr.pid, clifd, pkt->cmd);
if (pkt->cmd != WIDGET_GET_CONTENT) {
if (pkt->opt & AUL_SOCK_NOREPLY) {
close(clifd);
clifd = -1;
- }
- }
-
- if (pkt->opt & AUL_SOCK_BUNDLE) {
- b = bundle_decode(pkt->data, pkt->len);
- if (!b) {
- _E("Failed to decode the packet");
- if (clifd > 0)
+ } else {
+ channel = __create_client_channel(clifd,
+ cr.pid, cr.uid);
+ if (!channel) {
+ free(pkt);
close(clifd);
- free(pkt);
- return true;
+ return true;
+ }
+
+ __add_client_channel(channel);
}
}
- req = __create_request(pkt->cmd, clifd, b);
+ __process_app_pkt(pkt, clifd);
+ aul_worker_add_anr_timer(worker, pkt->cmd);
+
+ if (pkt->cmd == WIDGET_GET_CONTENT)
+ clifd = -1;
+
free(pkt);
- if (!req) {
- bundle_free(b);
+
+ if (clifd < 0)
return true;
- }
- aul_worker_add_anr_timer(worker, req->cmd);
- g_idle_add(__dispatch_request, req);
+ ret = aul_worker_add_io_job(worker, "client", clifd, cond,
+ __received_event_cb, worker);
+ if (ret < 0) {
+ _E("Failed to add io job. error(%d)", ret);
+ __remove_client_channel(channel);
+ __destroy_client_channel(channel);
+ return true;
+ }
return true;
}
static void __finalize_context(void)
{
+ if (!__context.initialized)
+ return;
+
if (__context.worker) {
aul_worker_destroy(__context.worker);
__context.worker = NULL;
}
+ g_rec_mutex_lock(&__context.mutex);
+ if (__context.clients) {
+ g_list_free_full(__context.clients, __destroy_client_channel);
+ __context.clients = NULL;
+ }
+
+ g_rec_mutex_unlock(&__context.mutex);
+ g_rec_mutex_clear(&__context.mutex);
+
__context.initialized = false;
}
int ret;
int fd;
+ if (__context.initialized) {
+ _E("Already initialized");
+ return AUL_R_OK;
+ }
+
fd = aul_initialize();
if (fd < 0) {
_E("Failed to initialize aul");
return fd;
}
+ g_rec_mutex_init(&__context.mutex);
+
__context.worker = aul_worker_create("aul+");
if (!__context.worker) {
__finalize_context();
return AUL_R_ERROR;
}
- ret = aul_worker_add_io_job(__context.worker, "AUL", fd,
- __worker_io_job_cb, __context.worker);
+ ret = aul_worker_add_io_job(__context.worker, "server", fd, AUL_IO_IN,
+ __connected_event_cb, __context.worker);
if (ret < 0) {
__finalize_context();
return ret;
return 0;
}
+static GIOCondition __convert_aul_io_condition(int condition)
+{
+ GIOCondition cond = 0;
+
+ if (condition & AUL_IO_IN)
+ cond |= G_IO_IN;
+ if (condition & AUL_IO_OUT)
+ cond |= G_IO_OUT;
+ if (condition & AUL_IO_PRI)
+ cond |= G_IO_PRI;
+ if (condition & AUL_IO_HUP)
+ cond |= G_IO_HUP;
+ if (condition & AUL_IO_ERR)
+ cond |= G_IO_ERR;
+ if (condition & AUL_IO_NVAL)
+ cond |= G_IO_NVAL;
+
+ return cond;
+}
+
+static int __convert_g_io_condition(GIOCondition condition)
+{
+ int cond = 0;
+
+ if (condition & G_IO_IN)
+ cond |= AUL_IO_IN;
+ if (condition & G_IO_OUT)
+ cond |= AUL_IO_OUT;
+ if (condition & G_IO_PRI)
+ cond |= AUL_IO_PRI;
+ if (condition & G_IO_HUP)
+ cond |= AUL_IO_HUP;
+ if (condition & G_IO_ERR)
+ cond |= AUL_IO_ERR;
+ if (condition & G_IO_NVAL)
+ cond |= AUL_IO_NVAL;
+
+ return cond;
+}
+
static gboolean __io_job_handler(GIOChannel *io, GIOCondition condition,
gpointer data)
{
struct job_s *job = (struct job_s *)data;
aul_worker_io_job_cb callback;
GSource *source;
+ int cond;
source = g_main_current_source();
if (!source || g_source_is_destroyed(source)) {
return G_SOURCE_REMOVE;
}
- if (condition & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
- _E("[__JOB__] name(%s), condition(%d)", job->name, condition);
- job->tag = 0;
- return G_SOURCE_REMOVE;
- }
-
+ cond = __convert_g_io_condition(condition);
callback = (aul_worker_io_job_cb)job->callback;
- if (callback(fd, job->user_data))
+ if (callback(fd, cond, job->user_data))
return G_SOURCE_CONTINUE;
_I("[__JOB__] name(%s)", job->name);
}
int aul_worker_add_io_job(aul_worker_h handle, const char *job_name,
- int fd, aul_worker_io_job_cb callback, void *user_data)
+ int fd, int condition, aul_worker_io_job_cb callback,
+ void *user_data)
{
- GIOCondition cond = G_IO_IN | G_IO_PRI | G_IO_HUP | G_IO_ERR |
- G_IO_NVAL;
+ GIOCondition cond = __convert_aul_io_condition(condition);
struct aul_worker_s *worker = (struct aul_worker_s *)handle;
struct job_s *job;
GIOChannel *channel;