9 #include "server.cmdline.h"
10 extern struct gengetopt_args_info conf;
11 /** the list of connected clients **/
12 static struct list_head clients;
13 static int listen_fd = -1;
14 static struct sender *self;
16 /** describes one connected client */
18 /** the dccp socket */
20 /** address information about the client */
21 struct sockaddr_in addr;
22 /** the position of this client in the client list */
23 struct list_head node;
24 int header_sent; /* non-zero if audio file header has been sent */
27 static void dccp_pre_select(__unused struct audio_format *af, int *max_fileno, fd_set *rfds,
28 __unused fd_set *wfds)
32 FD_SET(listen_fd, rfds);
33 *max_fileno = MAX(*max_fileno, listen_fd);
36 static void dccp_post_select(__unused struct audio_format *af, fd_set *rfds,
37 __unused fd_set *wfds)
39 struct dccp_client *dc;
42 if (!FD_ISSET(listen_fd, rfds))
44 PARA_NOTICE_LOG("%s", "accepting...\n");
45 dc = para_calloc(sizeof(struct dccp_client));
46 ret = para_accept(listen_fd, &dc->addr, sizeof(struct sockaddr_in));
48 PARA_ERROR_LOG("%s", PARA_STRERROR(-ret));
51 PARA_NOTICE_LOG("%s", "connection\n");
53 list_add(&dc->node, &clients);
56 static int dccp_open(void)
58 struct sockaddr_in servaddr;
61 ret = dccp_get_socket();
66 bzero(&servaddr, sizeof(servaddr));
67 servaddr.sin_family = AF_INET;
68 servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
69 servaddr.sin_port = htons(conf.dccp_port_arg);
70 ret = bind(listen_fd, (struct sockaddr *)&servaddr, sizeof(servaddr));
73 ret = dccp_set_socket(listen_fd);
76 ret = listen(listen_fd, 0);
78 return -E_DCCP_LISTEN;
79 PARA_DEBUG_LOG("listening on fd %d\n", listen_fd);
83 static void dccp_shutdown_client(struct dccp_client *dc)
90 static void dccp_send(__unused struct audio_format *af,
91 long unsigned current_chunk,
92 __unused long unsigned chunks_sent, const char *buf, size_t len)
94 struct dccp_client *dc, *tmp;
98 if (listen_fd < 0 || !len)
101 list_for_each_entry_safe(dc, tmp, &clients, node) {
102 if (!_write_ok(dc->fd))
104 if (!dc->header_sent && af->get_header_info && current_chunk) {
105 header_buf = af->get_header_info(&header_len);
106 if (!header_buf || header_len <= 0)
107 continue; /* header not yet available */
108 ret = write(dc->fd, header_buf, header_len);
109 if (ret != header_len) {
110 dccp_shutdown_client(dc);
113 if (!_write_ok(dc->fd))
116 PARA_DEBUG_LOG("writing %d bytes to fd %d\n", len, dc->fd);
117 ret = write(dc->fd, buf, len);
119 dccp_shutdown_client(dc);
123 static void dccp_shutdown_clients(void)
125 struct dccp_client *dc, *tmp;
127 list_for_each_entry_safe(dc, tmp, &clients, node)
128 dccp_shutdown_client(dc);
131 static char *dccp_info(void)
135 struct dccp_client *dc, *tmp;
138 list_for_each_entry_safe(dc, tmp, &clients, node)
140 buf = make_message("%d connected clients\n", num_clients);
144 static char *dccp_help(void)
146 return make_message("no help available\n");
149 void dccp_send_init(struct sender *s)
153 INIT_LIST_HEAD(&clients);
156 s->pre_select = dccp_pre_select;
157 s->post_select = dccp_post_select;
158 s->shutdown_clients = dccp_shutdown_clients;
160 s->client_cmds[SENDER_ON] = NULL;
161 s->client_cmds[SENDER_OFF] = NULL;
162 s->client_cmds[SENDER_DENY] = NULL;
163 s->client_cmds[SENDER_ALLOW] = NULL;
164 s->client_cmds[SENDER_ADD] = NULL;
165 s->client_cmds[SENDER_DELETE] = NULL;
169 PARA_ERROR_LOG("%s\n", PARA_STRERROR(-ret));
171 s->status = SENDER_ON;