X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=afs.c;h=2e11539c44a52d9287a201e9b0d3d390531fe42f;hp=c4e8d16968ee2c3e484b49330df493bccc097b10;hb=61250cf03241bf73662dac3753e44660a572fa2a;hpb=97f53e18953fc2013c0b14f0261ac385e45b0284 diff --git a/afs.c b/afs.c index c4e8d169..2e11539c 100644 --- a/afs.c +++ b/afs.c @@ -10,15 +10,15 @@ #include #include "server.cmdline.h" #include "para.h" +#include "error.h" #include "string.h" #include "afh.h" +#include "afs.h" #include "server.h" -#include "error.h" #include /* readdir() */ #include #include #include "net.h" -#include "afs.h" #include "ipc.h" #include "list.h" #include "sched.h" @@ -75,6 +75,11 @@ struct command_task { struct task task; }; +static int server_socket; +static struct command_task command_task_struct; +static struct signal_task signal_task_struct; + + /** * A random number used to "authenticate" the connection. * @@ -425,6 +430,40 @@ int stdin_command(int fd, struct osl_object *arg_obj, callback_function *f, return ret; } +int pass_afd(int fd, char *buf, size_t size) +{ + struct msghdr msg = {.msg_iov = NULL}; + struct cmsghdr *cmsg; + char control[255]; + int ret; + struct iovec iov; + + iov.iov_base = buf; + iov.iov_len = size; + + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + + msg.msg_control = control; + msg.msg_controllen = sizeof(control); + + cmsg = CMSG_FIRSTHDR(&msg); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = CMSG_LEN(sizeof(int)); + *(int *)CMSG_DATA(cmsg) = fd; + + /* Sum of the length of all control messages in the buffer */ + msg.msg_controllen = cmsg->cmsg_len; + PARA_NOTICE_LOG("passing %zu bytes and fd %d\n", size, fd); + ret = sendmsg(server_socket, &msg, 0); + if (ret < 0) { + ret = -ERRNO_TO_PARA_ERROR(errno); + return ret; + } + return 1; +} + /** * Open the audio file with highest score. * @@ -437,33 +476,35 @@ int stdin_command(int fd, struct osl_object *arg_obj, callback_function *f, * * \sa close_audio_file(), open_and_update_audio_file(). */ -int open_next_audio_file(struct audio_file_data *afd) +int open_next_audio_file(void) { struct osl_row *aft_row; - int ret; - for (;;) { - ret = score_get_best(&aft_row, &afd->score); - if (ret < 0) - return ret; - ret = open_and_update_audio_file(aft_row, afd); - if (ret >= 0) - return ret; - } -} + struct audio_file_data afd; + int ret, shmid; + char buf[8]; -/** - * Free all resources which were allocated by open_next_audio_file(). - * - * \param afd The structure previously filled in by open_next_audio_file(). - * - * \return The return value of the underlying call to para_munmap(). - * - * \sa open_next_audio_file(). - */ -int close_audio_file(struct audio_file_data *afd) -{ - free(afd->afhi.chunk_table); - return para_munmap(afd->map.data, afd->map.size); + PARA_NOTICE_LOG("getting next af\n"); + ret = score_get_best(&aft_row, &afd.score); + if (ret < 0) + return ret; + ret = open_and_update_audio_file(aft_row, &afd); + if (ret < 0) + return ret; + shmid = ret; + PARA_NOTICE_LOG("shmid: %u\n", shmid); + if (!write_ok(server_socket)) { + PARA_EMERG_LOG("afs_socket not writable\n"); + goto destroy; + } + *(uint32_t *)buf = NEXT_AUDIO_FILE; + *(uint32_t *)(buf + 4) = (uint32_t)shmid; + ret = pass_afd(afd.fd, buf, 8); + if (ret >= 0) + return ret; + PARA_ERROR_LOG("%s\n", PARA_STRERROR(-ret)); +destroy: + shm_destroy(shmid); + return ret; } static enum play_mode init_admissible_files(void) @@ -572,10 +613,6 @@ static int open_afs_tables(void) return ret; } -static int server_socket; -static struct command_task command_task_struct; -static struct signal_task signal_task_struct; - static void unregister_tasks(void) { unregister_task(&command_task_struct.task); @@ -639,6 +676,7 @@ static void command_pre_select(struct sched *s, struct task *t) struct command_task *ct = t->private_data; struct afs_client *client; + para_fd_set(server_socket, &s->rfds, &s->max_fileno); para_fd_set(ct->fd, &s->rfds, &s->max_fileno); list_for_each_entry(client, &afs_client_list, node) para_fd_set(client->fd, &s->rfds, &s->max_fileno); @@ -700,6 +738,27 @@ out: return ret; } +static void execute_server_command(void) +{ + char buf[8]; + int ret = recv_bin_buffer(server_socket, buf, sizeof(buf) - 1); + + if (ret <= 0) { + if (ret < 0) + PARA_ERROR_LOG("%s\n", PARA_STRERROR(-ret)); + return; + } + buf[ret] = '\0'; + PARA_NOTICE_LOG("received: %s\n", buf); + if (!strcmp(buf, "new")) { + ret = open_next_audio_file(); + PARA_NOTICE_LOG("ret: %d\n", ret); + return; + } + PARA_ERROR_LOG("unknown command\n"); + +} + static void execute_afs_command(int fd, uint32_t expected_cookie) { uint32_t cookie; @@ -741,7 +800,10 @@ static void command_post_select(struct sched *s, struct task *t) struct sockaddr_un unix_addr; struct afs_client *client, *tmp; - /* First, check the list of connected clients. */ + if (FD_ISSET(server_socket, &s->rfds)) + execute_server_command(); + + /* Check the list of connected clients. */ list_for_each_entry_safe(client, tmp, &afs_client_list, node) { if (FD_ISSET(client->fd, &s->rfds)) execute_afs_command(client->fd, ct->cookie); @@ -756,7 +818,7 @@ static void command_post_select(struct sched *s, struct task *t) list_del(&client->node); free(client); } - /* Next, accept connections on the local socket. */ + /* Accept connections on the local socket. */ if (!FD_ISSET(ct->fd, &s->rfds)) goto out; t->ret = para_accept(ct->fd, &unix_addr, sizeof(unix_addr));