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