#include <fnmatch.h>
#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 <dirent.h> /* readdir() */
#include <sys/mman.h>
#include <sys/time.h>
#include "net.h"
-#include "afs.h"
#include "ipc.h"
#include "list.h"
#include "sched.h"
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.
*
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.
*
*
* \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)
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);
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);
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;
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);
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));