1 /*
2 * Copyright (c) 2011-2012 - Mauro Carvalho Chehab
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation version 2
7 * of the License.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 * Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
18 *
19 */
20
21 #define _XOPEN_SOURCE 600
22
23 #define _FILE_OFFSET_BITS 64
24 #define _LARGEFILE_SOURCE 1
25 #define _LARGEFILE64_SOURCE 1
26
27 #ifdef HAVE_BACKTRACE
28 #include <execinfo.h>
29 #endif
30
31 #include <argp.h>
32 #include <endian.h>
33 #include <netinet/in.h>
34 #include <poll.h>
35 #include <pthread.h>
36 #include <search.h>
37 #include <signal.h>
38 #include <stdarg.h>
39 #include <stdlib.h>
40 #include <stdio.h>
41 #include <signal.h>
42 #include <syslog.h>
43 #include <sys/socket.h>
44 #include <unistd.h>
45
46 #include <netdb.h>
47 #include <netinet/in.h>
48 #include <netinet/tcp.h>
49
50 #include "../../lib/libdvbv5/dvb-fe-priv.h"
51 #include "../../lib/libdvbv5/dvb-dev-priv.h"
52 #include "libdvbv5/dvb-file.h"
53 #include "libdvbv5/dvb-dev.h"
54
55 #ifdef ENABLE_NLS
56 # define _(string) gettext(string)
57 # include "gettext.h"
58 # include <locale.h>
59 # include <langinfo.h>
60 # include <iconv.h>
61 #else
62 # define _(string) string
63 #endif
64
65 # define N_(string) string
66
67 /* Max number of open files */
68 #define NUM_FOPEN 1024
69
70 /*
71 * Argument processing data and logic
72 */
73
74 #define PROGRAM_NAME "dvbv5-daemon"
75
76 const char *argp_program_version = PROGRAM_NAME " version " V4L_UTILS_VERSION;
77 const char *argp_program_bug_address = "Mauro Carvalho Chehab <mchehab@kernel.org>";
78
79 #define CMD_SIZE 80
80
81 static const char doc[] = N_(
82 "\nA DVB remote daemon using API version 5\n");
83
84 static const struct argp_option options[] = {
85 {"verbose", 'v', 0, 0, N_("enables debug messages"), 0},
86 {"port", 'p', "5555", 0, N_("port to listen"), 0},
87 {"help", '?', 0, 0, N_("Give this help list"), -1},
88 {"usage", -3, 0, 0, N_("Give a short usage message")},
89 {"version", 'V', 0, 0, N_("Print program version"), -1},
90 { 0, 0, 0, 0, 0, 0 }
91 };
92
93 static int port = 0;
94 static int verbose = 0;
95
parse_opt(int k,char * arg,struct argp_state * state)96 static error_t parse_opt(int k, char *arg, struct argp_state *state)
97 {
98 switch (k) {
99 case 'p':
100 port = atoi(arg);
101 break;
102 case 'v':
103 verbose ++;
104 break;
105 case '?':
106 argp_state_help(state, state->out_stream,
107 ARGP_HELP_SHORT_USAGE | ARGP_HELP_LONG
108 | ARGP_HELP_DOC);
109 fprintf(state->out_stream, _("\nReport bugs to %s.\n"), argp_program_bug_address);
110 exit(0);
111 case 'V':
112 fprintf (state->out_stream, "%s\n", argp_program_version);
113 exit(0);
114 case -3:
115 argp_state_help(state, state->out_stream, ARGP_HELP_USAGE);
116 exit(0);
117 default:
118 return ARGP_ERR_UNKNOWN;
119 }
120 return 0;
121 }
122
123 static struct argp argp = {
124 .options = options,
125 .parser = parse_opt,
126 .doc = doc,
127 };
128
129 /*
130 * Local log
131 *
132 * Error messages should ideally be sent to the remote end, but, if
133 * an error happens during the processing of a packet, we need to
134 * report locally, as reporting remotely may not work.
135 */
136 static const struct loglevel {
137 const char *name;
138 const char *color;
139 int fd;
140 } loglevels[9] = {
141 {N_("EMERG "), "\033[31m", STDERR_FILENO },
142 {N_("ALERT "), "\033[31m", STDERR_FILENO },
143 {N_("CRITICAL "), "\033[31m", STDERR_FILENO },
144 {N_("ERROR "), "\033[31m", STDERR_FILENO },
145 {N_("WARNING "), "\033[33m", STDOUT_FILENO },
146 {NULL, "\033[36m", STDOUT_FILENO }, /* NOTICE */
147 {NULL, NULL, STDOUT_FILENO }, /* INFO */
148 {N_("DEBUG "), "\033[32m", STDOUT_FILENO },
149 {NULL, "\033[0m", STDOUT_FILENO }, /* reset*/
150 };
151 #define LOG_COLOROFF 8
152
local_log(int level,const char * fmt,...)153 void local_log(int level, const char *fmt, ...)
154 {
155 if(level > sizeof(loglevels) / sizeof(struct loglevel) - 2) // ignore LOG_COLOROFF as well
156 level = LOG_INFO;
157 va_list ap;
158 va_start(ap, fmt);
159 FILE *out = stdout;
160 if (STDERR_FILENO == loglevels[level].fd)
161 out = stderr;
162 if (loglevels[level].color && isatty(loglevels[level].fd))
163 fputs(loglevels[level].color, out);
164 if (loglevels[level].name)
165 fprintf(out, "%s", _(loglevels[level].name));
166 vfprintf(out, fmt, ap);
167 fprintf(out, "\n");
168 if(loglevels[level].color && isatty(loglevels[level].fd))
169 fputs(loglevels[LOG_COLOROFF].color, out);
170 va_end(ap);
171 }
172
173 #define info(fmt, arg...) do {\
174 local_log(LOG_INFO, fmt, ##arg); \
175 } while (0)
176
177 #define warn(fmt, arg...) do {\
178 local_log(LOG_WARNING, fmt, ##arg); \
179 } while (0)
180
181 #define err(fmt, arg...) do {\
182 local_log(LOG_ERR, "%s: " fmt, __FUNCTION__, ##arg); \
183 } while (0)
184
185 #define dbg(fmt, arg...) do {\
186 local_log(LOG_DEBUG, "%s: " fmt, __FUNCTION__, ##arg); \
187 } while (0)
188
189 #define local_perror(msg) do {\
190 local_log(LOG_ERR, "%s: %s: %m (%d)", __FUNCTION__, msg, errno); \
191 } while (0)
192
193 /*
194 * Static data used by the code
195 */
196
197 static pthread_mutex_t msg_mutex;
198 static pthread_mutex_t dvb_read_mutex;
199 static pthread_t read_id = 0;
200
201 struct dvb_descriptors {
202 int uid;
203 struct dvb_open_descriptor *open_dev;
204 };
205
206 static struct dvb_device *dvb = NULL;
207 static void *desc_root = NULL;
208 static int dvb_fd = -1;
209
210 static struct pollfd fds[NUM_FOPEN];
211 static nfds_t numfds = 0;
212
213 static char output_charset[256] = "utf-8";
214 static char default_charset[256] = "iso-8859-1";
215
stack_dump(void)216 static void stack_dump(void)
217 {
218 #ifdef HAVE_BACKTRACE
219 int i, nptrs = 0;
220 void *buffer[10];
221 char **strings = NULL;
222
223 nptrs = backtrace(buffer, sizeof(buffer));
224
225 if (nptrs) {
226 strings = backtrace_symbols(buffer, nptrs);
227 dbg("Stack:");
228 }
229
230 for (i = 0; i < nptrs; i++)
231 dbg(" %s", strings[i]);
232
233 free(strings);
234 #endif
235 }
236
237 /*
238 * Open dev descriptor handling
239 */
240
dvb_desc_compare(const void * __a,const void * __b)241 static int dvb_desc_compare(const void *__a, const void *__b)
242 {
243 const struct dvb_descriptors *a = __a, *b = __b;
244
245 return (b->uid - a->uid);
246 }
247
get_open_dev(int uid)248 static struct dvb_open_descriptor *get_open_dev(int uid)
249 {
250 struct dvb_descriptors desc, **p;
251
252 if (!desc_root)
253 return NULL;
254
255 desc.uid = uid;
256 p = tfind(&desc, &desc_root, dvb_desc_compare);
257
258 if (!p) {
259 err("open element not retrieved!");
260 return NULL;
261 }
262
263 return (*p)->open_dev;
264 }
265
destroy_open_dev(int uid)266 static void destroy_open_dev(int uid)
267 {
268 struct dvb_descriptors desc, **p;
269
270 desc.uid = uid;
271 p = tdelete(&desc, &desc_root, dvb_desc_compare);
272 if (!p)
273 err("can't destroy opened element");
274 }
275
free_opendevs(void * node)276 static void free_opendevs(void *node)
277 {
278 struct dvb_descriptors *desc = node;
279
280 if (verbose)
281 dbg("closing dev %p", desc, desc->open_dev);
282
283 dvb_dev_close(desc->open_dev);
284 free (desc);
285 }
286
close_all_devs(void)287 static void close_all_devs(void)
288 {
289 dvb_fd = -1;
290 numfds = 0;
291 tdestroy(desc_root, free_opendevs);
292
293 desc_root = NULL;
294 }
295
296 /*
297 * Signal handling logic
298 */
299
sigterm_handler(int const sig_class)300 static void sigterm_handler(int const sig_class)
301 {
302 info(PROGRAM_NAME" interrupted.");
303
304 pthread_exit(NULL);
305
306 close_all_devs();
307 dvb_dev_free(dvb);
308 }
309
start_signal_handler(void)310 static void start_signal_handler(void)
311 {
312 struct sigaction action;
313
314 sigemptyset(&action.sa_mask);
315 action.sa_flags = 0;
316 action.sa_handler = sigterm_handler;
317 sigaction(SIGTERM, &action, NULL);
318 }
319
stop_signal_handler(void)320 static void stop_signal_handler(void)
321 {
322 struct sigaction action;
323
324 sigemptyset(&action.sa_mask);
325 action.sa_flags = 0;
326 action.sa_handler = SIG_DFL;
327 sigaction(SIGTERM, &action, NULL);
328 }
329
330 /*
331 * Functions to send/receive messages to the client
332 */
333
__prepare_data(char * buf,const size_t size,const char * fmt,va_list ap)334 static ssize_t __prepare_data(char *buf, const size_t size,
335 const char *fmt, va_list ap)
336 {
337 char *p = buf, *endp = &buf[size], *s;
338 int len;
339 int32_t i32;
340 uint64_t u64;
341
342 while (*fmt && *fmt != '%') fmt++;
343 if (*fmt == '%') fmt++;
344 while (*fmt) {
345 switch (*fmt++) {
346 case 's': /* string */
347 s = va_arg(ap, char *);
348 if (s)
349 len = strlen(s);
350 else
351 len = 0;
352 if (p + len + 4 > endp) {
353 dbg("buffer to short for string");
354 stack_dump();
355 return -1;
356 }
357 i32 = htobe32(len);
358 memcpy(p, &i32, 4);
359 p += 4;
360 if (s)
361 memcpy(p, s, len);
362 p += len;
363 break;
364 case 'p': /* binary data with specified length */
365 s = va_arg(ap, char *);
366 len = va_arg(ap, ssize_t);
367 if (p + len + 4 > endp) {
368 dbg("buffer to short for string");
369 stack_dump();
370 return -1;
371 }
372 i32 = htobe32(len);
373 memcpy(p, &i32, 4);
374 p += 4;
375 memcpy(p, s, len);
376 p += len;
377 break;
378 case 'i': /* 32-bit int */
379 if (p + 4 > endp) {
380 dbg("buffer to short for int32_t");
381 stack_dump();
382 return -1;
383 }
384
385 i32 = htobe32(va_arg(ap, int32_t));
386 memcpy(p, &i32, 4);
387 p += 4;
388 break;
389 case 'l': /* 64-bit unsigned int */
390 if (*fmt++ != 'u') {
391 dbg("invalid long format character: '%c'", *fmt);
392 stack_dump();
393 break;
394 }
395 if (p + 8 > endp) {
396 dbg("buffer to short for uint64_t");
397 stack_dump();
398 return -1;
399 }
400 u64 = htobe64(va_arg(ap, uint64_t));
401 memcpy(p, &u64, 8);
402 p += 8;
403 break;
404 default:
405 dbg("invalid format character: '%c'", *fmt);
406 stack_dump();
407 }
408 while (*fmt && *fmt != '%') fmt++;
409 if (*fmt == '%') fmt++;
410 }
411 return p - buf;
412 }
413
414
415 static ssize_t prepare_data(char *buf, const size_t size,
416 const char *fmt, ...)
417 __attribute__ (( format( printf, 3, 4 )));
418
prepare_data(char * buf,const size_t size,const char * fmt,...)419 static ssize_t prepare_data(char *buf, const size_t size,
420 const char *fmt, ...)
421 {
422 va_list ap;
423 int ret;
424
425 va_start(ap, fmt);
426 ret = __prepare_data(buf, size, fmt, ap);
427 va_end(ap);
428
429 return ret;
430 }
431
send_buf(int fd,const char * buf,size_t size)432 static int send_buf(int fd, const char *buf, size_t size)
433 {
434 int ret;
435 int32_t i32;
436
437 if (fd < 0)
438 return ECONNRESET;
439
440 pthread_mutex_lock(&msg_mutex);
441 i32 = htobe32(size);
442 ret = send(fd, (void *)&i32, 4, MSG_MORE);
443 if (ret >= 0)
444 ret = send(fd, buf, size, 0);
445 pthread_mutex_unlock(&msg_mutex);
446 if (ret < 0) {
447 local_perror("write");
448 if (ret == ECONNRESET)
449 close_all_devs();
450
451 return errno;
452 }
453
454 return ret;
455 }
456
457 static ssize_t send_data(int fd, const char *fmt, ...)
458 __attribute__ (( format( printf, 2, 3 )));
459
send_data(int fd,const char * fmt,...)460 static ssize_t send_data(int fd, const char *fmt, ...)
461 {
462 char buf[REMOTE_BUF_SIZE];
463 va_list ap;
464 int ret;
465
466 if (verbose)
467 dbg("called %s(fd, \"%s\", ...)", __FUNCTION__, fmt);
468
469 va_start(ap, fmt);
470 ret = __prepare_data(buf, sizeof(buf), fmt, ap);
471 va_end(ap);
472 if (ret < 0)
473 return ret;
474
475 return send_buf(fd, buf, ret);
476 }
477
478 static ssize_t scan_data(char *buf, int buf_size, const char *fmt, ...)
479 __attribute__ (( format( scanf, 3, 4 )));
480
scan_data(char * buf,int buf_size,const char * fmt,...)481 static ssize_t scan_data(char *buf, int buf_size, const char *fmt, ...)
482 {
483 char *p = buf, *endp = &buf[buf_size], *s;
484 int len;
485 int32_t *i32;
486 uint64_t *u64;
487 va_list ap;
488
489 va_start(ap, fmt);
490 while (*fmt && *fmt != '%') fmt++;
491 if (*fmt == '%') fmt++;
492 while (*fmt) {
493 switch (*fmt++) {
494 case 's': /* string */
495 s = va_arg(ap, char *);
496 if (p + 4 > endp) {
497 dbg("buffer to short for string length");
498 stack_dump();
499 return -1;
500 }
501 len = be32toh(*(int32_t *)p);
502 p += 4;
503 if (p + len > endp) {
504 dbg("buffer to short for string");
505 stack_dump();
506 return -1;
507 }
508
509 memcpy(s, p, len);
510 s[len] = '\0';
511 p += len;
512 break;
513 case 'i': /* 32-bit int */
514 if (p + 4 > endp) {
515 dbg("buffer to short for int32_t");
516 stack_dump();
517 return -1;
518 }
519 i32 = va_arg(ap, int32_t *);
520
521 *i32 = be32toh(*(int32_t *)p);
522 p += 4;
523 break;
524 case 'l': /* 64-bit unsigned int */
525 if (*fmt++ != 'u') {
526 dbg("invalid long format character: '%c'", *fmt);
527 stack_dump();
528 break;
529 }
530 if (p + 8 > endp) {
531 dbg("buffer to short for uint64_t");
532 stack_dump();
533 return -1;
534 }
535 u64 = va_arg(ap, uint64_t *);
536
537 *u64 = be32toh(*(uint64_t *)p);
538 p += 8;
539 break;
540 default:
541 dbg("invalid format character: '%c'", *fmt);
542 stack_dump();
543 }
544 while (*fmt && *fmt != '%') fmt++;
545 if (*fmt == '%') fmt++;
546 }
547 va_end(ap);
548
549 return p - buf;
550 }
551
552 /*
553 * Remote log
554 */
dvb_remote_log(void * priv,int level,const char * fmt,...)555 void dvb_remote_log(void *priv, int level, const char *fmt, ...)
556 {
557 int ret;
558 char *buf;
559
560 va_list ap;
561 int fd = *(int*)priv;
562
563 va_start(ap, fmt);
564 ret = vasprintf(&buf, fmt, ap);
565 if (ret <= 0) {
566 local_perror("vasprintf");
567 return;
568 }
569
570 va_end(ap);
571
572 if (fd >= 0)
573 send_data(fd, "%i%s%i%s", 0, "log", level, buf);
574 else
575 local_log(level, buf);
576
577 free(buf);
578 }
579
dev_change_monitor(char * sysname,enum dvb_dev_change_type type,void * user_priv)580 static int dev_change_monitor(char *sysname,
581 enum dvb_dev_change_type type, void *user_priv)
582 {
583 send_data(dvb_fd, "%i%s%i%s", 0, "dev_change", type, sysname);
584
585 return 0;
586 }
587
588
589 /*
590 * command handler methods
591 */
daemon_get_version(uint32_t seq,char * cmd,int fd,char * buf,ssize_t size)592 static int daemon_get_version(uint32_t seq, char *cmd, int fd,
593 char *buf, ssize_t size)
594 {
595 int ret = 0;
596
597 return send_data(fd, "%i%s%i%s", seq, cmd, ret, argp_program_version);
598 }
599
dev_find(uint32_t seq,char * cmd,int fd,char * buf,ssize_t size)600 static int dev_find(uint32_t seq, char *cmd, int fd, char *buf, ssize_t size)
601 {
602 int enable_monitor = 0, ret;
603 dvb_dev_change_t handler = NULL;
604
605 ret = scan_data(buf, size, "%i", &enable_monitor);
606 if (ret < 0)
607 goto error;
608
609 if (enable_monitor)
610 handler = &dev_change_monitor;
611
612 ret = dvb_dev_find(dvb, handler, NULL);
613
614 error:
615 return send_data(fd, "%i%s%i", seq, cmd, ret);
616 }
617
dev_stop_monitor(uint32_t seq,char * cmd,int fd,char * buf,ssize_t size)618 static int dev_stop_monitor(uint32_t seq, char *cmd, int fd,
619 char *buf, ssize_t size)
620 {
621 dvb_dev_stop_monitor(dvb);
622
623 return send_data(fd, "%i%s%i", seq, cmd, 0);
624 }
625
dev_seek_by_adapter(uint32_t seq,char * cmd,int fd,char * buf,ssize_t size)626 static int dev_seek_by_adapter(uint32_t seq, char *cmd, int fd,
627 char *buf, ssize_t size)
628 {
629 struct dvb_dev_list *dev;
630 int adapter, num, type, ret;
631
632 ret = scan_data(buf, size, "%i%i%i", &adapter, &num, &type);
633 if (ret < 0)
634 goto error;
635
636 dev = dvb_dev_seek_by_adapter(dvb, adapter, num, type);
637 if (!dev)
638 goto error;
639
640 return send_data(fd, "%i%s%i%s%s%s%i%s%s%s%s%s", seq, cmd, ret,
641 dev->syspath, dev->path, dev->sysname, dev->dvb_type,
642 dev->bus_addr, dev->bus_id, dev->manufacturer,
643 dev->product, dev->serial);
644 error:
645 return send_data(fd, "%i%s%i", seq, cmd, ret);
646 }
647
dev_get_dev_info(uint32_t seq,char * cmd,int fd,char * buf,ssize_t size)648 static int dev_get_dev_info(uint32_t seq, char *cmd, int fd,
649 char *buf, ssize_t size)
650 {
651 struct dvb_dev_list *dev;
652 char sysname[REMOTE_BUF_SIZE];
653 int ret;
654
655 ret = scan_data(buf, size, "%s", sysname);
656 if (ret < 0)
657 goto error;
658
659 dev = dvb_get_dev_info(dvb, sysname);
660 if (!dev)
661 goto error;
662
663 return send_data(fd, "%i%s%i%s%s%s%i%s%s%s%s%s", seq, cmd, ret,
664 dev->syspath, dev->path, dev->sysname, dev->dvb_type,
665 dev->bus_addr, dev->bus_id, dev->manufacturer,
666 dev->product, dev->serial);
667 error:
668 return send_data(fd, "%i%s%i", seq, cmd, ret);
669 }
670
read_data(void * privdata)671 static void *read_data(void *privdata)
672 {
673 struct dvb_open_descriptor *open_dev;
674 int timeout;
675 int ret, read_ret = -1, fd, i;
676 char databuf[REMOTE_BUF_SIZE];
677 char buf[REMOTE_BUF_SIZE + 32], *p;
678 size_t size;
679 size_t count;
680 struct pollfd __fds[NUM_FOPEN];
681 nfds_t __numfds;
682
683 timeout = 10; /* ms */
684 while (1) {
685 pthread_mutex_lock(&dvb_read_mutex);
686 if (!numfds) {
687 pthread_mutex_unlock(&dvb_read_mutex);
688 break;
689 }
690 __numfds = numfds;
691 memcpy(__fds, fds, sizeof(fds));
692 pthread_mutex_unlock(&dvb_read_mutex);
693
694 ret = poll(__fds, __numfds, timeout);
695 if (!ret)
696 continue;
697 if (ret < 0) {
698 err("poll");
699 continue;
700 }
701
702 for (i = 0; i < __numfds; i++) {
703 if (__fds[i].revents & (POLLERR | POLLHUP | POLLNVAL))
704 continue;
705 if (__fds[i].revents)
706 break;
707 }
708
709 /*
710 * it means that one error condition happened.
711 * Likely the file was closed.
712 */
713 if (i == __numfds)
714 continue;
715
716 fd = __fds[i].fd;
717
718 if (!desc_root)
719 break;
720
721 open_dev = get_open_dev(fd);
722 if (!open_dev) {
723 err("Couldn't find opened file %d", fd);
724 continue;
725 }
726
727 count = REMOTE_BUF_SIZE;
728 read_ret = dvb_dev_read(open_dev, databuf, count);
729 if (verbose) {
730 if (read_ret < 0)
731 dbg("#%d: read error: %d on %p", fd, read_ret, open_dev);
732 else
733 dbg("#%d: read %ul bytes (count %d)", fd, read_ret, count);
734 }
735
736 /* Initialize to the start of the buffer */
737 p = buf;
738 size = sizeof(buf);
739
740 ret = prepare_data(p, size, "%i%s%i%i", 0, "data_read",
741 read_ret, fd);
742 if (ret < 0) {
743 err("Failed to prepare answer to dvb_read()");
744 break;
745 }
746
747 p += ret;
748 size -= ret;
749
750 if (read_ret > 0) {
751 if (read_ret > size) {
752 dbg("buffer to short to store read data!");
753 read_ret = -EOVERFLOW;
754 } else {
755 memcpy(p, databuf, read_ret);
756 p += read_ret;
757 }
758 }
759
760 ret = send_buf(dvb_fd, buf, p - buf);
761 if (ret < 0) {
762 err("Error %d sending buffer\n", ret);
763 if (ret == ECONNRESET) {
764 close_all_devs();
765 break;
766 }
767 continue;
768 }
769 }
770
771 dbg("Finishing kthread");
772 read_id = 0;
773 return NULL;
774 }
775
dev_open(uint32_t seq,char * cmd,int fd,char * buf,ssize_t size)776 static int dev_open(uint32_t seq, char *cmd, int fd, char *buf, ssize_t size)
777 {
778 struct dvb_open_descriptor *open_dev;
779 struct dvb_dev_list *dev;
780 struct dvb_descriptors *desc, **p;
781 int ret, flags, uid;
782 char sysname[REMOTE_BUF_SIZE];
783
784 desc = calloc(1, sizeof(*desc));
785 if (!desc) {
786 local_perror("calloc");
787 ret = -ENOMEM;
788 goto error;
789 }
790
791 ret = scan_data(buf, size, "%s%i", sysname, &flags);
792 if (ret < 0) {
793 free(desc);
794 goto error;
795 }
796
797 /*
798 * Discard requests for O_NONBLOCK, as the daemon will use threads
799 * to handle unblocked reads.
800 */
801 flags &= ~O_NONBLOCK;
802
803 open_dev = dvb_dev_open(dvb, sysname, flags);
804 if (!open_dev) {
805 ret = -errno;
806 free(desc);
807 goto error;
808 }
809
810
811 if (verbose)
812 dbg("open dev handler for %s: %p with uid#%d", sysname, open_dev, open_dev->fd);
813
814 dev = open_dev->dev;
815 if (dev->dvb_type == DVB_DEVICE_DEMUX ||
816 dev->dvb_type == DVB_DEVICE_DVR) {
817 pthread_mutex_lock(&dvb_read_mutex);
818 fds[numfds].fd = open_dev->fd;
819 fds[numfds].events = POLLIN | POLLPRI;
820 numfds++;
821 pthread_mutex_unlock(&dvb_read_mutex);
822 }
823
824 if (!read_id) {
825 ret = pthread_create(&read_id, NULL, read_data, NULL);
826 if (ret < 0) {
827 local_perror("pthread_create");
828 pthread_mutex_unlock(&msg_mutex);
829 free(desc);
830 return -1;
831 }
832 }
833
834 pthread_mutex_unlock(&msg_mutex);
835 uid = open_dev->fd;
836
837 desc->uid = uid;
838 desc->open_dev = open_dev;
839
840 /* Add element to the desc_root tree */
841 p = tsearch(desc, &desc_root, dvb_desc_compare);
842 if (!p) {
843 local_perror("tsearch");
844 uid = 0;
845 } else if (*p != desc) {
846 err("uid %d was already opened!", uid);
847 }
848
849 pthread_mutex_unlock(&msg_mutex);
850
851 ret = uid;
852 error:
853 return send_data(fd, "%i%s%i", seq, cmd, ret);
854 }
855
dev_close(uint32_t seq,char * cmd,int fd,char * buf,ssize_t size)856 static int dev_close(uint32_t seq, char *cmd, int fd, char *buf, ssize_t size)
857 {
858 struct dvb_open_descriptor *open_dev;
859 int uid, ret, i;
860
861 ret = scan_data(buf, size, "%i", &uid);
862 if (ret < 0)
863 goto error;
864
865 open_dev = get_open_dev(uid);
866 if (!open_dev) {
867 err("Can't find uid to close");
868 ret = -1;
869 goto error;
870 }
871
872 /* Delete fd from the opened array */
873 pthread_mutex_lock(&dvb_read_mutex);
874 for (i = 0; i < numfds; i++) {
875 if (fds[i].fd != open_dev->fd)
876 continue;
877 if (i < numfds - 1)
878 memmove(&fds[i], &fds[i + 1],
879 sizeof(*fds)*(numfds - i - 1));
880 numfds--;
881 break;
882 }
883 pthread_mutex_unlock(&dvb_read_mutex);
884 if (read_id && !numfds) {
885 pthread_cancel(read_id);
886 read_id = 0;
887 }
888
889 dvb_dev_close(open_dev);
890 destroy_open_dev(uid);
891
892 error:
893 return send_data(fd, "%i%s%i", seq, cmd, ret);
894 }
895
dev_dmx_stop(uint32_t seq,char * cmd,int fd,char * buf,ssize_t size)896 static int dev_dmx_stop(uint32_t seq, char *cmd, int fd,
897 char *buf, ssize_t size)
898 {
899 struct dvb_open_descriptor *open_dev;
900 int uid, ret;
901
902 ret = scan_data(buf, size, "%i", &uid);
903 if (ret < 0)
904 goto error;
905
906 open_dev = get_open_dev(uid);
907 if (!open_dev) {
908 ret = -1;
909 err("Can't find uid to stop");
910 goto error;
911 }
912
913 dvb_dev_dmx_stop(open_dev);
914
915 error:
916 return send_data(fd, "%i%s%i", seq, cmd, ret);
917 }
918
dev_set_bufsize(uint32_t seq,char * cmd,int fd,char * buf,ssize_t size)919 static int dev_set_bufsize(uint32_t seq, char *cmd, int fd,
920 char *buf, ssize_t size)
921 {
922 struct dvb_open_descriptor *open_dev;
923 int uid, ret, bufsize;
924
925 ret = scan_data(buf, size, "%i%i", &uid, &bufsize);
926 if (ret < 0)
927 goto error;
928
929 open_dev = get_open_dev(uid);
930 if (!open_dev) {
931 ret = -1;
932 err("Can't find uid to stop");
933 goto error;
934 }
935
936 dvb_dev_set_bufsize(open_dev, bufsize);
937
938 error:
939 return send_data(fd, "%i%s%i", seq, cmd, ret);
940 }
941
dev_dmx_set_pesfilter(uint32_t seq,char * cmd,int fd,char * buf,ssize_t size)942 static int dev_dmx_set_pesfilter(uint32_t seq, char *cmd, int fd,
943 char *buf, ssize_t size)
944 {
945 struct dvb_open_descriptor *open_dev;
946 int uid, ret, pid, type, output, bufsize;
947
948 ret = scan_data(buf, size, "%i%i%i%i%i",
949 &uid, &pid, &type, &output, &bufsize);
950 if (ret < 0)
951 goto error;
952
953 open_dev = get_open_dev(uid);
954 if (!open_dev) {
955 ret = -1;
956 err("Can't find uid to set pesfilter");
957 goto error;
958 }
959
960 ret = dvb_dev_dmx_set_pesfilter(open_dev, pid, type, output, bufsize);
961
962 error:
963 return send_data(fd, "%i%s%i", seq, cmd, ret);
964 }
965
dev_dmx_set_section_filter(uint32_t seq,char * cmd,int fd,char * buf,ssize_t size)966 static int dev_dmx_set_section_filter(uint32_t seq, char *cmd, int fd,
967 char *buf, ssize_t size)
968 {
969 struct dvb_open_descriptor *open_dev;
970 int uid, ret, pid, filtsize, flags;
971 unsigned char filter[17], mask[17], mode[17];
972
973 ret = scan_data(buf, size, "%i%i%i%s%s%s%i",
974 &uid, &pid, &filtsize, filter, mask, mode, &flags);
975 if (ret < 0)
976 goto error;
977
978 open_dev = get_open_dev(uid);
979 if (!open_dev) {
980 ret = -1;
981 err("Can't find uid to set section filter");
982 goto error;
983 }
984
985 ret = dvb_dev_dmx_set_section_filter(open_dev, pid, filtsize, filter,
986 mask, mode, flags);
987
988 error:
989 return send_data(fd, "%i%s%i", seq, cmd, ret);
990 }
991
dev_dmx_get_pmt_pid(uint32_t seq,char * cmd,int fd,char * buf,ssize_t size)992 static int dev_dmx_get_pmt_pid(uint32_t seq, char *cmd, int fd,
993 char *buf, ssize_t size)
994 {
995 struct dvb_open_descriptor *open_dev;
996 int uid, ret, sid;
997
998 ret = scan_data(buf, size, "%i%i", &uid, &sid);
999 if (ret < 0)
1000 goto error;
1001
1002 open_dev = get_open_dev(uid);
1003 if (!open_dev) {
1004 ret = -1;
1005 err("Can't find uid to get PMT PID");
1006 goto error;
1007 }
1008
1009 ret = dvb_dev_dmx_get_pmt_pid(open_dev, sid);
1010
1011 error:
1012 return send_data(fd, "%i%s%i", seq, cmd, ret);
1013 }
1014
dev_scan(uint32_t seq,char * cmd,int fd,char * buf,ssize_t size)1015 static int dev_scan(uint32_t seq, char *cmd, int fd, char *buf, ssize_t size)
1016 {
1017 int ret = -1;
1018
1019 /*
1020 * FIXME: There are too many stuff here! Maybe we should
1021 * split this into smaller per-table calls.
1022 */
1023
1024 #if 0
1025 struct dvb_open_descriptor *open_dev;
1026 int uid;
1027
1028 ret = scan_data(buf, size, "%i%i", &uid);
1029 if (ret < 0)
1030 goto error;
1031
1032 open_dev = get_open_dev(uid);
1033 if (!open_dev) {
1034 ret = -1;
1035 err("Can't find uid to scan");
1036 goto error;
1037 }
1038
1039 ret = dvb_scan(foo);
1040
1041 error:
1042 return send_data(fd, "%i%s%i", seq, cmd, ret);
1043 #else
1044 return send_data(fd, "%i%s%i", seq, cmd, ret);
1045 #endif
1046 }
1047
dev_set_sys(uint32_t seq,char * cmd,int fd,char * buf,ssize_t size)1048 static int dev_set_sys(uint32_t seq, char *cmd, int fd,
1049 char *buf, ssize_t size)
1050 {
1051 struct dvb_v5_fe_parms_priv *parms = (void *)dvb->fe_parms;
1052 struct dvb_v5_fe_parms *p = (void *)parms;
1053 int sys = 0, ret;
1054
1055 ret = scan_data(buf, size, "%i", &sys);
1056 if (ret < 0)
1057 goto error;
1058
1059 ret = __dvb_set_sys(p, sys);
1060 error:
1061 return send_data(fd, "%i%s%i", seq, cmd, ret);
1062 }
1063
dev_get_parms(uint32_t seq,char * cmd,int fd,char * inbuf,ssize_t insize)1064 static int dev_get_parms(uint32_t seq, char *cmd, int fd,
1065 char *inbuf, ssize_t insize)
1066 {
1067 struct dvb_v5_fe_parms_priv *parms = (void *)dvb->fe_parms;
1068 struct dvb_v5_fe_parms *par = (void *)parms;
1069 struct dvb_frontend_info *info = &par->info;
1070 int ret, i;
1071 char buf[REMOTE_BUF_SIZE], lnb_name[80] = "", *p = buf;
1072 size_t size = sizeof(buf);
1073
1074 if (verbose)
1075 dbg("dev_get_parms called");
1076
1077 ret = __dvb_fe_get_parms(par);
1078 if (ret < 0)
1079 goto error;
1080
1081 /* Send first the public params */
1082
1083 ret = prepare_data(p, size, "%i%s%i%s%i%i%i%i%i%i%i", seq, cmd, ret,
1084 info->name, info->frequency_min,
1085 info->frequency_max, info->frequency_stepsize,
1086 info->frequency_tolerance, info->symbol_rate_min,
1087 info->symbol_rate_max, info->symbol_rate_tolerance);
1088 if (ret < 0)
1089 goto error;
1090
1091 p += ret;
1092 size -= ret;
1093
1094 if (par->lnb)
1095 strcpy(lnb_name, par->lnb->name);
1096
1097 ret = prepare_data(p, size, "%i%i%i%i%i%i%i%s%i%i%i%i%s%s",
1098 par->version, par->has_v5_stats, par->current_sys,
1099 par->num_systems, par->legacy_fe, par->abort,
1100 par->lna, lnb_name,
1101 par->sat_number, par->freq_bpf, par->diseqc_wait,
1102 par->verbose, par->default_charset,
1103 par->output_charset);
1104 if (ret < 0)
1105 goto error;
1106
1107 p += ret;
1108 size -= ret;
1109
1110 for (i = 0; i < MAX_DELIVERY_SYSTEMS; i++) {
1111 ret = prepare_data(p, size, "%i", par->systems[i]);
1112 if (ret < 0)
1113 goto error;
1114
1115 p += ret;
1116 size -= ret;
1117 }
1118
1119 /* Now, send the private ones - except for stats */
1120
1121 ret = prepare_data(p, size, "%i%i%i%i",
1122 parms->n_props,
1123 parms->country,
1124 parms->high_band,
1125 parms->freq_offset);
1126 if (ret < 0)
1127 goto error;
1128
1129 p += ret;
1130 size -= ret;
1131
1132 for (i = 0; i < parms->n_props; i++) {
1133 ret = prepare_data(p, size, "%i%i",
1134 parms->dvb_prop[i].cmd,
1135 parms->dvb_prop[i].u.data);
1136 if (ret < 0)
1137 goto error;
1138
1139 p += ret;
1140 size -= ret;
1141 }
1142
1143 strcpy(output_charset, par->output_charset);
1144 strcpy(default_charset, par->default_charset);
1145
1146 return send_buf(fd, buf, p - buf);
1147 error:
1148 return send_data(fd, "%i%s%i", seq, cmd, ret);
1149 }
1150
dev_set_parms(uint32_t seq,char * cmd,int fd,char * buf,ssize_t size)1151 static int dev_set_parms(uint32_t seq, char *cmd, int fd,
1152 char *buf, ssize_t size)
1153 {
1154 struct dvb_v5_fe_parms_priv *parms = (void *)dvb->fe_parms;
1155 struct dvb_v5_fe_parms *par = (void *)parms;
1156 int ret, i;
1157 char *p = buf;
1158 const char *old_lnb = "";
1159 char new_lnb[256];
1160
1161 if (verbose)
1162 dbg("dev_set_parms called");
1163
1164 /* first the public params that aren't read only */
1165
1166 /* Get current LNB name */
1167 if (par->lnb)
1168 old_lnb = par->lnb->name;
1169
1170 ret = scan_data(p, size, "%i%i%s%i%i%i%i%s%s",
1171 &par->abort, &par->lna, new_lnb,
1172 &par->sat_number, &par->freq_bpf, &par->diseqc_wait,
1173 &par->verbose, default_charset, output_charset);
1174
1175 if (ret < 0)
1176 goto error;
1177
1178 p += ret;
1179 size -= ret;
1180
1181 /* Now, the private ones */
1182
1183 ret = scan_data(p, size, "%i", &i);
1184 if (ret < 0)
1185 goto error;
1186 parms->country = i;
1187
1188 p += ret;
1189 size -= ret;
1190
1191 for (i = 0; i < parms->n_props; i++) {
1192 ret = scan_data(p, size, "%i%i",
1193 &parms->dvb_prop[i].cmd,
1194 &parms->dvb_prop[i].u.data);
1195 if (ret < 0)
1196 goto error;
1197
1198 p += ret;
1199 size -= ret;
1200 }
1201
1202 if (!*new_lnb) {
1203 par->lnb = NULL;
1204 } else if (strcmp(old_lnb, new_lnb)) {
1205 int lnb = dvb_sat_search_lnb(new_lnb);
1206
1207 if (lnb < 0) {
1208 dvb_logerr("Invalid lnb: %s", new_lnb);
1209 ret = -1;
1210 goto error;
1211 }
1212
1213 par->lnb = dvb_sat_get_lnb(lnb);
1214 }
1215
1216 par->output_charset = output_charset;
1217 par->default_charset = default_charset;
1218
1219 ret = __dvb_fe_set_parms(par);
1220
1221 error:
1222 return send_data(fd, "%i%s%i", seq, cmd, ret);
1223 }
1224
dev_get_stats(uint32_t seq,char * cmd,int fd,char * inbuf,ssize_t insize)1225 static int dev_get_stats(uint32_t seq, char *cmd, int fd,
1226 char *inbuf, ssize_t insize)
1227 {
1228 struct dvb_v5_fe_parms_priv *parms = (void *)dvb->fe_parms;
1229 struct dvb_v5_stats *st = &parms->stats;
1230 struct dvb_v5_fe_parms *par = (void *)parms;
1231 int ret, i;
1232 char buf[REMOTE_BUF_SIZE], *p = buf;
1233 size_t size = sizeof(buf);
1234
1235 if (verbose)
1236 dbg("dev_get_stats called");
1237
1238 ret = __dvb_fe_get_stats(par);
1239 if (ret < 0)
1240 goto error;
1241
1242 ret = prepare_data(p, size, "%i%s%i%i", seq, cmd, ret, st->prev_status);
1243 if (ret < 0)
1244 goto error;
1245
1246 p += ret;
1247 size -= ret;
1248
1249 for (i = 0; i < DTV_NUM_STATS_PROPS; i++) {
1250 ret = prepare_data(p, size, "%i%i",
1251 st->prop[i].cmd,
1252 st->prop[i].u.data);
1253 if (ret < 0)
1254 goto error;
1255
1256 p += ret;
1257 size -= ret;
1258 }
1259 for (i = 0; i < MAX_DTV_STATS; i++) {
1260 struct dvb_v5_counters *prev = st->prev;
1261 struct dvb_v5_counters *cur = st->cur;
1262
1263 ret = prepare_data(p, size, "%i%i%i",
1264 st->has_post_ber[i],
1265 st->has_pre_ber[i],
1266 st->has_per[i]);
1267 if (ret < 0)
1268 goto error;
1269
1270 p += ret;
1271 size -= ret;
1272
1273 #pragma GCC diagnostic ignored "-Wformat"
1274 ret = prepare_data(p, size,
1275 "%lu%lu%lu%lu%lu%lu%lu%lu%lu%lu%lu%lu",
1276 prev->pre_bit_count,
1277 prev->pre_bit_error,
1278 prev->post_bit_count,
1279 prev->post_bit_error,
1280 prev->block_count,
1281 prev->block_error,
1282 cur->pre_bit_count,
1283 cur->pre_bit_error,
1284 cur->post_bit_count,
1285 cur->post_bit_error,
1286 cur->block_count,
1287 cur->block_error);
1288 #pragma GCC diagnostic pop
1289 if (ret < 0)
1290 goto error;
1291
1292 p += ret;
1293 size -= ret;
1294 }
1295
1296 return send_buf(fd, buf, p - buf);
1297 error:
1298 return send_data(fd, "%i%s%i", seq, cmd, ret);
1299 }
1300
1301 /*
1302 * Structure with all methods with RPC calls
1303 */
1304
1305 typedef int (*method_handler) (uint32_t seq, char *cmd, int fd,
1306 char *buf, ssize_t size);
1307
1308 struct method_types {
1309 char *name;
1310 method_handler handler;
1311 int locks_dvb;
1312 };
1313
1314 static const struct method_types methods[] = {
1315 {"daemon_get_version", &daemon_get_version, 1},
1316 {"dev_find", &dev_find, 0},
1317 {"dev_stop_monitor", &dev_stop_monitor, 0},
1318 {"dev_seek_by_adapter", &dev_seek_by_adapter, 0},
1319 {"dev_get_dev_info", &dev_get_dev_info, 0},
1320 {"dev_open", &dev_open, 0},
1321 {"dev_close", &dev_close, 0},
1322 {"dev_dmx_stop", &dev_dmx_stop, 0},
1323 {"dev_set_bufsize", &dev_set_bufsize, 0},
1324 {"dev_dmx_set_pesfilter", &dev_dmx_set_pesfilter, 0},
1325 {"dev_dmx_set_section_filter", &dev_dmx_set_section_filter, 0},
1326 {"dev_dmx_get_pmt_pid", &dev_dmx_get_pmt_pid, 0},
1327
1328 {"dev_scan", &dev_scan, 0},
1329
1330 {"dev_set_sys", &dev_set_sys, 0},
1331 {"fe_get_parms", &dev_get_parms, 0},
1332 {"fe_set_parms", &dev_set_parms, 0},
1333 {"fe_get_stats", &dev_get_stats, 0},
1334
1335 {}
1336 };
1337
start_server(void * fd_pointer)1338 static void *start_server(void *fd_pointer)
1339 {
1340 const struct method_types *method;
1341 int fd = *(int *)fd_pointer, ret, flag = 1;
1342 char buf[REMOTE_BUF_SIZE + 8], cmd[CMD_SIZE], *p;
1343 ssize_t size;
1344 uint32_t seq;
1345 int bufsize;
1346
1347 if (verbose)
1348 dbg("Opening socket %d", fd);
1349
1350 /* Set a large buffer for read() to work better */
1351 bufsize = REMOTE_BUF_SIZE;
1352 if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF,
1353 (void *)&bufsize, (int)sizeof(bufsize))) {
1354 dbg("Failed to set a large buffer size");
1355 };
1356
1357 /* Disable Naggle algorithm, as we want errors to be sent ASAP */
1358 if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int))) {
1359 dbg("Failed to avoid TCP delays");
1360 };
1361
1362 /* Command dispatcher */
1363 do {
1364 size = recv(fd, buf, 4, MSG_WAITALL);
1365 if (size <= 0)
1366 break;
1367 size = (uint32_t)buf[0] << 24 | (uint32_t)buf[1] << 16 |
1368 (uint32_t)buf[2] << 8 | (uint32_t)buf[3];
1369 size = recv(fd, buf, size, MSG_WAITALL);
1370 if (size <= 0)
1371 break;
1372
1373 ret = scan_data(buf, size, "%i%s", &seq, cmd);
1374 if (ret < 0) {
1375 if (verbose)
1376 dbg("message too short: %ld", size);
1377 send_data(fd, "%i%s%i%s", 0, "log", LOG_ERR,
1378 "msg too short");
1379 continue;
1380 }
1381
1382 p = buf + ret;
1383 size -= ret;
1384
1385 if (verbose)
1386 dbg("received command: %i '%s'", seq, cmd);
1387
1388 if (size > buf + sizeof(buf) - p) {
1389 if (verbose)
1390 dbg("data length too big: %d", size);
1391 send_data(fd, "%i%s%i%s", 0, "log", LOG_ERR,
1392 "data length too big");
1393 continue;
1394 }
1395
1396 method = methods;
1397 while (method->name) {
1398 if (!strcmp(cmd, method->name)) {
1399 if (dvb_fd > 0 || method->locks_dvb) {
1400 ret = method->handler(seq, cmd,
1401 fd, p, size);
1402 if (ret < 0)
1403 break;
1404 if (method->locks_dvb)
1405 dvb_fd = fd;
1406 break;
1407 }
1408 send_data(fd, "%i%s%i%s", 0, "log", LOG_ERR,
1409 "daemon busy");
1410 break;
1411 }
1412 method++;
1413 }
1414 if (!method->name) {
1415 if (verbose)
1416 dbg("invalid command: %s", cmd);
1417 send_data(fd, "%i%s%i%s", 0, "log", LOG_ERR,
1418 "invalid command");
1419 }
1420 } while (1);
1421
1422 if (verbose)
1423 dbg("Closing socket %d", fd);
1424
1425 close(fd);
1426 if (read_id) {
1427 pthread_cancel(read_id);
1428 read_id = 0;
1429 }
1430 if (dvb_fd > 0)
1431 close_all_devs();
1432
1433 return NULL;
1434 }
1435
1436 /*
1437 * main program
1438 */
1439
main(int argc,char * argv[])1440 int main(int argc, char *argv[])
1441 {
1442 int ret;
1443 int sockfd;
1444 socklen_t addrlen;
1445 struct sockaddr_in serv_addr, cli_addr;
1446
1447 #ifdef ENABLE_NLS
1448 setlocale (LC_ALL, "");
1449 bindtextdomain (PACKAGE, LOCALEDIR);
1450 textdomain (PACKAGE);
1451 #endif
1452
1453 if (argp_parse(&argp, argc, argv, ARGP_NO_HELP | ARGP_NO_EXIT, 0, 0)) {
1454 argp_help(&argp, stderr, ARGP_HELP_SHORT_USAGE, PROGRAM_NAME);
1455 return -1;
1456 }
1457
1458 if (!port) {
1459 argp_help(&argp, stderr, ARGP_HELP_SHORT_USAGE, PROGRAM_NAME);
1460 return -1;
1461 }
1462
1463 /* Allocate DVB structure and start seek for devices */
1464 dvb = dvb_dev_alloc();
1465 if (!dvb) {
1466 err("Can't allocate DVB data\n");
1467 return -1;
1468 }
1469
1470 dvb_dev_find(dvb, 0, NULL);
1471
1472 /* Create a socket */
1473 sockfd = socket(AF_INET, SOCK_STREAM, 0);
1474 if (sockfd < 0) {
1475 local_perror("socket");
1476 goto error;
1477 }
1478
1479 /* Initialize listen address struct */
1480 memset((char *) &serv_addr, 0, sizeof(serv_addr));
1481 serv_addr.sin_family = AF_INET;
1482 serv_addr.sin_addr.s_addr = INADDR_ANY;
1483 serv_addr.sin_port = htons(port);
1484
1485 /* Bind to the address */
1486 ret = bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
1487 if (ret < 0) {
1488 local_perror("bind");
1489 goto error;
1490 }
1491
1492 /* FIXME: should allow the caller to set the verbosity */
1493 dvb_dev_set_logpriv(dvb, 1, dvb_remote_log, &dvb_fd);
1494
1495 /* Listen up to 5 connections */
1496 listen(sockfd, 5);
1497 addrlen = sizeof(cli_addr);
1498
1499 start_signal_handler();
1500 pthread_mutex_init(&msg_mutex, NULL);
1501 pthread_mutex_init(&dvb_read_mutex, NULL);
1502
1503 /* Accept actual connection from the client */
1504
1505 warn("Support for Digital TV remote access is still highly experimental.\n"
1506 "\nKnown issues:\n"
1507 " - Abort needed to be implemented in a proper way;\n"
1508 " - Need to make more stuff opaque, as touching on fields at the local\n"
1509 " end is not automatically reflected remotely;\n"
1510 " - The libdvbv5 API support is incomplete: it misses satellite, scan\n"
1511 " and other functions;\n\n");
1512
1513 info(PROGRAM_NAME" started.");
1514
1515 while (1) {
1516 int fd;
1517 pthread_t id;
1518
1519 if (verbose)
1520 dbg("waiting for connections");
1521 fd = accept(sockfd, (struct sockaddr *)&cli_addr, &addrlen);
1522 if (fd < 0) {
1523 local_perror("accept");
1524 break;
1525 }
1526
1527 if (verbose)
1528 dbg("accepted connection %d", fd);
1529 ret = pthread_create(&id, NULL, start_server, (void *)&fd);
1530 if (ret < 0) {
1531 local_perror("pthread_create");
1532 break;
1533 }
1534 }
1535
1536 /* Just in case we add some way for the remote part to stop the daemon */
1537 stop_signal_handler();
1538
1539 error:
1540 info(PROGRAM_NAME" stopped.");
1541
1542 pthread_exit(NULL);
1543
1544 if (dvb)
1545 dvb_dev_free(dvb);
1546
1547 return -1;
1548 }
1549