1 /*
2 * Tvheadend - SAT-IP client
3 *
4 * Copyright (C) 2014 Jaroslav Kysela
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "tvheadend.h"
21 #include "input.h"
22 #include "htsbuf.h"
23 #include "htsmsg_xml.h"
24 #include "upnp.h"
25 #include "settings.h"
26 #include "satip/server.h"
27 #include "satip_private.h"
28 #include "dbus.h"
29
30 #include <arpa/inet.h>
31 #include <openssl/sha.h>
32
33 #if defined(PLATFORM_FREEBSD) || ENABLE_ANDROID
34 #include <sys/types.h>
35 #include <sys/socket.h>
36 #endif
37
38 static void satip_discovery_timer_cb(void *aux);
39
40 /*
41 *
42 */
43
44 static void
satip_device_dbus_notify(satip_device_t * sd,const char * sig_name)45 satip_device_dbus_notify( satip_device_t *sd, const char *sig_name )
46 {
47 #if ENABLE_DBUS_1
48 char buf[256], ubuf[UUID_HEX_SIZE];
49
50 htsmsg_t *msg = htsmsg_create_list();
51 htsmsg_add_str(msg, NULL, sd->sd_info.addr);
52 htsmsg_add_str(msg, NULL, sd->sd_info.location);
53 htsmsg_add_str(msg, NULL, sd->sd_info.server);
54 htsmsg_add_s64(msg, NULL, sd->sd_info.rtsp_port);
55 snprintf(buf, sizeof(buf), "/input/mpegts/satip/%s", idnode_uuid_as_str(&sd->th_id, ubuf));
56 dbus_emit_signal(buf, sig_name, msg);
57 #endif
58 }
59
60 static void
satip_device_block(const char * addr,int block)61 satip_device_block( const char *addr, int block )
62 {
63 extern const idclass_t satip_device_class;
64 tvh_hardware_t *th;
65 satip_device_t *sd;
66 satip_frontend_t *lfe;
67 int val = block < 0 ? 0 : block;
68
69 pthread_mutex_lock(&global_lock);
70 TVH_HARDWARE_FOREACH(th) {
71 if (!idnode_is_instance(&th->th_id, &satip_device_class))
72 continue;
73 sd = (satip_device_t *)th;
74 if (strcmp(sd->sd_info.addr, addr) == 0 && val != sd->sd_dbus_allow) {
75 sd->sd_dbus_allow = val;
76 if (block < 0) {
77 TAILQ_FOREACH(lfe, &sd->sd_frontends, sf_link)
78 mpegts_input_stop_all((mpegts_input_t *)lfe);
79 }
80 tvhinfo(LS_SATIP, "address %s is %s", addr,
81 block < 0 ? "stopped" : (block > 0 ? "allowed" : "disabled"));
82 }
83 }
84 pthread_mutex_unlock(&global_lock);
85 }
86
87 static char *
satip_device_addr(void * aux,const char * path,char * value)88 satip_device_addr( void *aux, const char *path, char *value )
89 {
90 if (strcmp(path, "/stop") == 0) {
91 satip_device_block(value, -1);
92 return strdup("ok");
93 } else if (strcmp(path, "/disable") == 0) {
94 satip_device_block(value, 0);
95 return strdup("ok");
96 } else if (strcmp(path, "/allow") == 0) {
97 satip_device_block(value, 1);
98 return strdup("ok");
99 }
100 return strdup("err");
101 }
102
103 /*
104 *
105 */
106 char *
satip_device_nicename(satip_device_t * sd,char * buf,int len)107 satip_device_nicename( satip_device_t *sd, char *buf, int len )
108 {
109 if (sd->sd_info.rtsp_port != 554)
110 snprintf(buf, len, "%s:%d", sd->sd_info.addr, sd->sd_info.rtsp_port);
111 else
112 snprintf(buf, len, "%s", sd->sd_info.addr);
113 return buf;
114 }
115
116 /*
117 * SAT-IP client
118 */
119
120 static htsmsg_t *
satip_device_class_save(idnode_t * in,char * filename,size_t fsize)121 satip_device_class_save ( idnode_t *in, char *filename, size_t fsize )
122 {
123 satip_device_t *sd = (satip_device_t *)in;
124 satip_frontend_t *lfe;
125 htsmsg_t *m, *l;
126 char ubuf[UUID_HEX_SIZE];
127
128 if (sd->sd_nosave)
129 return NULL;
130
131 m = htsmsg_create_map();
132 idnode_save(&sd->th_id, m);
133
134 l = htsmsg_create_map();
135 TAILQ_FOREACH(lfe, &sd->sd_frontends, sf_link)
136 satip_frontend_save(lfe, l);
137 htsmsg_add_msg(m, "frontends", l);
138
139 snprintf(filename, fsize, "input/satip/adapters/%s",
140 idnode_uuid_as_str(&sd->th_id, ubuf));
141 return m;
142 }
143
144 static const void *
satip_device_class_active_get(void * obj)145 satip_device_class_active_get ( void * obj )
146 {
147 static int active;
148 satip_device_t *sd = (satip_device_t *)obj;
149 satip_frontend_t *lfe;
150 active = 0;
151 TAILQ_FOREACH(lfe, &sd->sd_frontends, sf_link)
152 if (*(int *)mpegts_input_class_active_get(lfe)) {
153 active = 1;
154 break;
155 }
156 return &active;
157 }
158
159 static idnode_set_t *
satip_device_class_get_childs(idnode_t * in)160 satip_device_class_get_childs ( idnode_t *in )
161 {
162 satip_device_t *sd = (satip_device_t *)in;
163 idnode_set_t *is = idnode_set_create(0);
164 satip_frontend_t *lfe;
165
166 TAILQ_FOREACH(lfe, &sd->sd_frontends, sf_link)
167 idnode_set_add(is, &lfe->ti_id, NULL, NULL);
168 return is;
169 }
170
171 static const char *
satip_device_class_get_title(idnode_t * in,const char * lang)172 satip_device_class_get_title( idnode_t *in, const char *lang )
173 {
174 static char buf[256];
175 satip_device_t *sd = (satip_device_t *)in;
176 snprintf(buf, sizeof(buf),
177 "%s - %s", sd->sd_info.friendlyname, sd->sd_info.addr);
178 return buf;
179 }
180
181 static const char *satip_tunercfg_tab[] = {
182 "DVBS2-1",
183 "DVBS2-2",
184 "DVBS2-4",
185 "DVBS2-8",
186 "DVBC-1",
187 "DVBC-2",
188 "DVBC-4",
189 "DVBC-8",
190 "DVBT-1",
191 "DVBT-2",
192 "DVBT-4",
193 "DVBT-8",
194 "DVBS2-1,DVBT-1",
195 "DVBS2-2,DVBT-2",
196 "DVBT-1,DVBS2-1",
197 "DVBT-2,DVBS2-2",
198 "DVBS2-1,DVB-C1",
199 "DVBS2-2,DVB-C2",
200 "DVBC-1,DVBS2-1",
201 "DVBC-2,DVBS2-2",
202 NULL
203 };
204
205 static htsmsg_t *
satip_device_class_tunercfg_list(void * o,const char * lang)206 satip_device_class_tunercfg_list ( void *o, const char *lang )
207 {
208 htsmsg_t *l = htsmsg_create_list();
209 const char **p;
210 htsmsg_add_str(l, NULL, "Auto");
211 for (p = satip_tunercfg_tab; *p; p++)
212 htsmsg_add_str(l, NULL, *p);
213 return l;
214 }
215
216 static void
satip_device_class_tunercfg_notify(void * o,const char * lang)217 satip_device_class_tunercfg_notify ( void *o, const char *lang )
218 {
219 satip_device_t *sd = (satip_device_t *)o;
220 if (!sd->sd_inload)
221 satip_device_destroy_later(sd, 100);
222 }
223
224 CLASS_DOC(satip_client)
225
226 const idclass_t satip_device_class =
227 {
228 .ic_class = "satip_client",
229 .ic_event = "satip_client",
230 .ic_caption = N_("SAT>IP Client"),
231 .ic_doc = tvh_doc_satip_client_class,
232 .ic_save = satip_device_class_save,
233 .ic_get_childs = satip_device_class_get_childs,
234 .ic_get_title = satip_device_class_get_title,
235 .ic_properties = (const property_t[]){
236 {
237 .type = PT_BOOL,
238 .id = "active",
239 .name = N_("Active"),
240 .opts = PO_RDONLY | PO_NOSAVE | PO_NOUI,
241 .get = satip_device_class_active_get,
242 },
243 {
244 .type = PT_STR,
245 .id = "tunercfgu",
246 .name = N_("Tuner configuration"),
247 .desc = N_("Tuner configuration."),
248 .opts = PO_SORTKEY,
249 .off = offsetof(satip_device_t, sd_tunercfg),
250 .list = satip_device_class_tunercfg_list,
251 .notify = satip_device_class_tunercfg_notify,
252 .def.s = "Auto"
253 },
254 {
255 .type = PT_BOOL,
256 .id = "tcp_mode",
257 .name = N_("RTP/AVP/TCP (embedded data)"),
258 .desc = N_("Enable or disable RTP/AVP/TCP transfer mode "
259 "(embedded data in the RTSP session) support."),
260 .opts = PO_ADVANCED,
261 .off = offsetof(satip_device_t, sd_tcp_mode),
262 },
263 {
264 .type = PT_BOOL,
265 .id = "fast_switch",
266 .name = N_("Fast input switch"),
267 .desc = N_("Enable or disable fast input switching."),
268 .opts = PO_ADVANCED,
269 .off = offsetof(satip_device_t, sd_fast_switch),
270 },
271 {
272 .type = PT_BOOL,
273 .id = "fullmux_ok",
274 .name = N_("Full mux RX mode supported"),
275 .desc = N_("Enable or disable full mux mode."),
276 .opts = PO_ADVANCED,
277 .off = offsetof(satip_device_t, sd_fullmux_ok),
278 },
279 {
280 .type = PT_INT,
281 .id = "sigscale",
282 .name = N_("Signal scale (240 or 100)"),
283 .desc = N_("Not all SAT>IP servers use the same signal scaling. "
284 "Change this setting if the signal level displayed "
285 "within Tvheadend looks too low."),
286 .opts = PO_ADVANCED,
287 .off = offsetof(satip_device_t, sd_sig_scale),
288 },
289 {
290 .type = PT_INT,
291 .id = "pids_max",
292 .name = N_("Maximum PIDs"),
293 .desc = N_("Set the maxiumum packet identifiers your SAT>IP "
294 "server supports."),
295 .opts = PO_ADVANCED,
296 .off = offsetof(satip_device_t, sd_pids_max),
297 },
298 {
299 .type = PT_INT,
300 .id = "pids_len",
301 .name = N_("Maximum length of PIDs"),
302 .desc = N_("Maximum length in characters for the command "
303 "setting PIDs to the SAT>IP box."),
304 .opts = PO_ADVANCED,
305 .off = offsetof(satip_device_t, sd_pids_len),
306 },
307 {
308 .type = PT_BOOL,
309 .id = "pids_deladd",
310 .name = N_("addpids/delpids supported"),
311 .desc = N_("Enable if the SAT>IP box supports the "
312 "addpids/delpids commands."),
313 .opts = PO_ADVANCED,
314 .off = offsetof(satip_device_t, sd_pids_deladd),
315 },
316 {
317 .type = PT_BOOL,
318 .id = "fe",
319 .name = N_("FE supported"),
320 .desc = N_("Enable if the SAT>IP box supports the frontend "
321 "identifier. This allows the auto-tuner allocation, "
322 "but it might cause trouble for boxes with different "
323 "tuner reception connections like satellite inputs."),
324 .opts = PO_ADVANCED,
325 .off = offsetof(satip_device_t, sd_fe),
326 },
327 {
328 .type = PT_BOOL,
329 .id = "piloton",
330 .name = N_("Force pilot for DVB-S2"),
331 .desc = N_("Enable if the SAT>IP box requests plts=on "
332 "parameter in the SETUP RTSP command for DVB-S2 "
333 "muxes."),
334 .opts = PO_ADVANCED,
335 .off = offsetof(satip_device_t, sd_pilot_on),
336 },
337 {
338 .type = PT_BOOL,
339 .id = "pids21",
340 .name = N_("PIDs 21 in setup"),
341 .desc = N_("Enable if the SAT>IP box requires pids=21 "
342 "parameter in the SETUP RTSP command"),
343 .opts = PO_ADVANCED,
344 .off = offsetof(satip_device_t, sd_pids21),
345 },
346 {
347 .type = PT_STR,
348 .id = "bindaddr",
349 .name = N_("Local bind IP address"),
350 .desc = N_("Bind to specific local IP address."),
351 .opts = PO_ADVANCED,
352 .off = offsetof(satip_device_t, sd_bindaddr),
353 },
354 {
355 .type = PT_INT,
356 .id = "skip_ts",
357 .name = N_("Skip TS packets (0-200)"),
358 .desc = N_("Skip x number of transport packets."),
359 .opts = PO_EXPERT,
360 .off = offsetof(satip_device_t, sd_skip_ts),
361 },
362 {
363 .type = PT_BOOL,
364 .id = "disableworkarounds",
365 .name = N_("Disable device/firmware-specific workarounds"),
366 .opts = PO_ADVANCED,
367 .off = offsetof(satip_device_t, sd_disable_workarounds),
368 },
369 {
370 .type = PT_STR,
371 .id = "addr",
372 .name = N_("IP address"),
373 .desc = N_("Force all network connections to this tuner to be "
374 "made over the specified IP address, similar to "
375 "the setting for the SAT>IP device itself. Setting "
376 "this overrides the device-specific setting."),
377 .opts = PO_RDONLY | PO_NOSAVE,
378 .off = offsetof(satip_device_t, sd_info.addr),
379 },
380 {
381 .type = PT_INT,
382 .id = "rtsp",
383 .name = N_("RTSP port"),
384 .desc = N_("Current RTSP port."),
385 .opts = PO_RDONLY | PO_NOSAVE,
386 .off = offsetof(satip_device_t, sd_info.rtsp_port),
387 },
388 {
389 .type = PT_STR,
390 .id = "device_uuid",
391 .name = N_("UUID"),
392 .desc = N_("The SAT>IP server's universally unique identifier."),
393 .opts = PO_RDONLY,
394 .off = offsetof(satip_device_t, sd_info.uuid),
395 },
396 {
397 .type = PT_STR,
398 .id = "friendly",
399 .name = N_("Friendly name"),
400 .desc = N_("The SAT>IP server's name."),
401 .opts = PO_RDONLY | PO_NOSAVE,
402 .off = offsetof(satip_device_t, sd_info.friendlyname),
403 },
404 {
405 .type = PT_STR,
406 .id = "serialnum",
407 .name = N_("Serial number"),
408 .desc = N_("The device's serial number."),
409 .opts = PO_RDONLY | PO_NOSAVE,
410 .off = offsetof(satip_device_t, sd_info.serialnum),
411 },
412 {
413 .type = PT_STR,
414 .id = "tunercfg",
415 .name = N_("Tuner configuration"),
416 .desc = N_("Current tuner configuration."),
417 .opts = PO_RDONLY | PO_NOSAVE,
418 .off = offsetof(satip_device_t, sd_info.tunercfg),
419 },
420 {
421 .type = PT_STR,
422 .id = "manufacturer",
423 .name = N_("Manufacturer"),
424 .desc = N_("The manufacturer of the SAT>IP server."),
425 .opts = PO_RDONLY | PO_NOSAVE,
426 .off = offsetof(satip_device_t, sd_info.manufacturer),
427 },
428 {
429 .type = PT_STR,
430 .id = "manufurl",
431 .name = N_("Manufacturer URL"),
432 .desc = N_("Manufacturer's product information page for the device."),
433 .opts = PO_RDONLY | PO_NOSAVE,
434 .off = offsetof(satip_device_t, sd_info.manufacturerURL),
435 },
436 {
437 .type = PT_STR,
438 .id = "modeldesc",
439 .name = N_("Model description"),
440 .desc = N_("Manufacturer's product description."),
441 .opts = PO_RDONLY | PO_NOSAVE,
442 .off = offsetof(satip_device_t, sd_info.modeldesc),
443 },
444 {
445 .type = PT_STR,
446 .id = "modelname",
447 .name = N_("Model name"),
448 .desc = N_("Manufacturer's product name."),
449 .opts = PO_RDONLY | PO_NOSAVE,
450 .off = offsetof(satip_device_t, sd_info.modelname),
451 },
452 {
453 .type = PT_STR,
454 .id = "modelnum",
455 .name = N_("Model number"),
456 .desc = N_("Manufacturer's model number."),
457 .opts = PO_RDONLY | PO_NOSAVE,
458 .off = offsetof(satip_device_t, sd_info.modelnum),
459 },
460 {
461 .type = PT_STR,
462 .id = "bootid",
463 .name = N_("Boot ID"),
464 .desc = N_("The current boot ID."),
465 .opts = PO_RDONLY | PO_NOSAVE,
466 .off = offsetof(satip_device_t, sd_info.bootid),
467 },
468 {
469 .type = PT_STR,
470 .id = "configid",
471 .name = N_("Configuration ID"),
472 .desc = N_("The current configuration ID."),
473 .opts = PO_RDONLY | PO_NOSAVE,
474 .off = offsetof(satip_device_t, sd_info.configid),
475 },
476 {
477 .type = PT_STR,
478 .id = "deviceid",
479 .name = N_("Device ID"),
480 .desc = N_("The device ID."),
481 .opts = PO_RDONLY | PO_NOSAVE,
482 .off = offsetof(satip_device_t, sd_info.deviceid),
483 },
484 {
485 .type = PT_STR,
486 .id = "presentation",
487 .name = N_("Presentation"),
488 .desc = N_("Presentation details."),
489 .opts = PO_RDONLY | PO_NOSAVE,
490 .off = offsetof(satip_device_t, sd_info.presentation),
491 },
492 {
493 .type = PT_STR,
494 .id = "location",
495 .name = N_("Location"),
496 .desc = N_("Location details of the SAT>IP Server."),
497 .opts = PO_RDONLY | PO_NOSAVE,
498 .off = offsetof(satip_device_t, sd_info.location),
499 },
500 {
501 .type = PT_STR,
502 .id = "server",
503 .name = N_("Server"),
504 .desc = N_("Server details."),
505 .opts = PO_RDONLY | PO_NOSAVE,
506 .off = offsetof(satip_device_t, sd_info.server),
507 },
508 {
509 .type = PT_STR,
510 .id = "myaddr",
511 .name = N_("Local discovery IP address"),
512 .desc = N_("The SAT>IP's discovered IP address."),
513 .opts = PO_RDONLY | PO_NOSAVE,
514 .off = offsetof(satip_device_t, sd_info.myaddr),
515 },
516 {}
517 }
518 };
519
520 /*
521 * Create entry
522 */
523 static void
satip_device_calc_bin_uuid(uint8_t * uuid,const char * satip_uuid)524 satip_device_calc_bin_uuid( uint8_t *uuid, const char *satip_uuid )
525 {
526 SHA_CTX sha1;
527
528 SHA1_Init(&sha1);
529 SHA1_Update(&sha1, (void*)satip_uuid, strlen(satip_uuid));
530 SHA1_Final(uuid, &sha1);
531 }
532
533 static void
satip_device_calc_uuid(tvh_uuid_t * uuid,const char * satip_uuid)534 satip_device_calc_uuid( tvh_uuid_t *uuid, const char *satip_uuid )
535 {
536 uint8_t uuidbin[20];
537
538 sha1_calc(uuidbin, (const uint8_t *)satip_uuid, strlen(satip_uuid), NULL, 0);
539 bin2hex(uuid->hex, sizeof(uuid->hex), uuidbin, sizeof(uuidbin));
540 }
541
542 static void
satip_device_hack(satip_device_t * sd)543 satip_device_hack( satip_device_t *sd )
544 {
545 if(sd->sd_disable_workarounds)
546 return;
547 #if 0
548 /* V1.24.0.156 cannot be distinguished from V1.13.0.105 :-( */
549 /* hopefully, all users have V1.16.0.120+ now */
550 if (sd->sd_info.deviceid[0] &&
551 strcmp(sd->sd_info.server, "Linux/1.0 UPnP/1.1 IDL4K/1.0") == 0) {
552 /* AXE Linux distribution - Inverto firmware */
553 /* version V1.13.0.105 and probably less */
554 /* really ugly firmware - soooooo much restrictions */
555 sd->sd_fullmux_ok = 0;
556 sd->sd_pids_max = 32;
557 sd->sd_pids_deladd = 0;
558 tvhwarn(LS_SATIP, "Detected old Inverto firmware V1.13.0.105 and less");
559 tvhwarn(LS_SATIP, "Upgrade to V1.16.0.120 - http://http://www.inverto.tv/support/ - IDL400s");
560 } else
561 #endif
562 if (strstr(sd->sd_info.location, ":8888/octonet.xml")) {
563 /* OctopusNet requires pids in the SETUP RTSP command */
564 } else if (strstr(sd->sd_info.manufacturer, "Triax") &&
565 strstr(sd->sd_info.modelname, "TSS400")) {
566 sd->sd_fullmux_ok = 0;
567 sd->sd_pids_max = 64;
568 sd->sd_pilot_on = 1;
569 } else if (strcmp(sd->sd_info.modelname, "TVHeadend SAT>IP") == 0) {
570 sd->sd_pids_max = 128;
571 sd->sd_pids_len = 2048;
572 sd->sd_no_univ_lnb = 1;
573 if (strcmp(sd->sd_info.modelnum ?: "", "1.0"))
574 sd->sd_can_weight = 1;
575 } else if (strstr(sd->sd_info.manufacturer, "AVM Berlin") &&
576 strstr(sd->sd_info.modelname, "FRITZ!")) {
577 sd->sd_fullmux_ok = 0;
578 sd->sd_pids_deladd = 0;
579 sd->sd_pids21 = 1;
580 } else if (strstr(sd->sd_info.modelname, "EyeTV Netstream 4C")) {
581 sd->sd_fe = 0;
582 }
583 }
584
585 static satip_device_t *
satip_device_create(satip_device_info_t * info)586 satip_device_create( satip_device_info_t *info )
587 {
588 satip_device_t *sd = calloc(1, sizeof(satip_device_t));
589 tvh_uuid_t uuid;
590 htsmsg_t *conf = NULL, *feconf = NULL;
591 char *argv[10], *tunercfg;
592 int i, j, n, m, fenum, v2, save = 0;
593 dvb_fe_type_t type;
594 char buf2[60];
595
596 sd->sd_inload = 1;
597
598 satip_device_calc_uuid(&uuid, info->uuid);
599
600 conf = hts_settings_load("input/satip/adapters/%s", uuid.hex);
601
602 /* some sane defaults */
603 sd->sd_fast_switch = 1;
604 sd->sd_fullmux_ok = 1;
605 sd->sd_pids_len = 127;
606 sd->sd_pids_max = 32;
607 sd->sd_pids_deladd = 1;
608 sd->sd_fe = 1;
609 sd->sd_sig_scale = 240;
610 sd->sd_dbus_allow = 1;
611
612 if (!tvh_hardware_create0((tvh_hardware_t*)sd, &satip_device_class,
613 uuid.hex, conf)) {
614 /* Note: sd is freed in above fcn */
615 return NULL;
616 }
617
618 pthread_mutex_init(&sd->sd_tune_mutex, NULL);
619
620 TAILQ_INIT(&sd->sd_frontends);
621 TAILQ_INIT(&sd->sd_serialize_queue);
622
623 atomic_set(&sd->sd_wake_ref, 0);
624
625 /* we may check if uuid matches, but the SHA hash should be enough */
626 if (sd->sd_info.uuid)
627 free(sd->sd_info.uuid);
628
629 #define ASSIGN(x) sd->sd_info.x = info->x; info->x = NULL
630 ASSIGN(myaddr);
631 ASSIGN(addr);
632 ASSIGN(uuid);
633 ASSIGN(bootid);
634 ASSIGN(configid);
635 ASSIGN(deviceid);
636 ASSIGN(server);
637 ASSIGN(location);
638 ASSIGN(friendlyname);
639 ASSIGN(manufacturer);
640 ASSIGN(manufacturerURL);
641 ASSIGN(modeldesc);
642 ASSIGN(modelname);
643 ASSIGN(modelnum);
644 ASSIGN(serialnum);
645 ASSIGN(presentation);
646 ASSIGN(tunercfg);
647 #undef ASSIGN
648 sd->sd_info.rtsp_port = info->rtsp_port;
649 sd->sd_info.srcs = info->srcs;
650
651 /*
652 * device specific hacks
653 */
654 satip_device_hack(sd);
655
656 if (conf)
657 feconf = htsmsg_get_map(conf, "frontends");
658 save = !conf || !feconf;
659
660 tunercfg = sd->sd_tunercfg;
661 if (tunercfg == NULL)
662 tunercfg = sd->sd_tunercfg = strdup("Auto");
663 if (strncmp(tunercfg, "DVB", 3) && strncmp(tunercfg, "ATSC", 4))
664 tunercfg = sd->sd_info.tunercfg;
665
666 n = http_tokenize(tvh_strdupa(tunercfg), argv, 10, ',');
667 for (i = m = 0, fenum = 1; i < n; i++) {
668 type = DVB_TYPE_NONE;
669 v2 = 0;
670 if (strncmp(argv[i], "DVBS2-", 6) == 0) {
671 type = DVB_TYPE_S;
672 m = atoi(argv[i] + 6);
673 v2 = 1;
674 } else if (strncmp(argv[i], "DVBS-", 5) == 0) {
675 type = DVB_TYPE_S;
676 m = atoi(argv[i] + 5);
677 } else if (strncmp(argv[i], "DVBT2-", 6) == 0) {
678 type = DVB_TYPE_T;
679 m = atoi(argv[i] + 6);
680 v2 = 1;
681 } else if (strncmp(argv[i], "DVBT-", 5) == 0) {
682 type = DVB_TYPE_T;
683 m = atoi(argv[i] + 5);
684 } else if (strncmp(argv[i], "DVBC2-", 6) == 0) {
685 type = DVB_TYPE_C;
686 m = atoi(argv[i] + 6);
687 v2 = 1;
688 } else if (strncmp(argv[i], "DVBC-", 5) == 0) {
689 type = DVB_TYPE_C;
690 m = atoi(argv[i] + 5);
691 } else if (strncmp(argv[i], "ATSCT-", 6) == 0) {
692 type = DVB_TYPE_ATSC_T;
693 m = atoi(argv[i] + 6);
694 } else if (strncmp(argv[i], "ATSCC-", 6) == 0) {
695 type = DVB_TYPE_ATSC_C;
696 m = atoi(argv[i] + 6);
697 }
698 if (type == DVB_TYPE_NONE) {
699 tvherror(LS_SATIP, "%s: bad tuner type [%s]",
700 satip_device_nicename(sd, buf2, sizeof(buf2)), argv[i]);
701 } else if (m < 0 || m > 32) {
702 tvherror(LS_SATIP, "%s: bad tuner count [%s]",
703 satip_device_nicename(sd, buf2, sizeof(buf2)), argv[i]);
704 } else {
705 sd->sd_nosave = 1;
706 for (j = 0; j < m; j++)
707 if (satip_frontend_create(feconf, sd, type, v2, fenum))
708 fenum++;
709 sd->sd_nosave = 0;
710 }
711 }
712
713 if (save)
714 satip_device_changed(sd);
715
716 sd->sd_inload = 0;
717
718 htsmsg_destroy(conf);
719
720 satip_device_dbus_notify(sd, "start");
721
722 return sd;
723 }
724
725 static satip_device_t *
satip_device_find(const char * satip_uuid)726 satip_device_find( const char *satip_uuid )
727 {
728 tvh_hardware_t *th;
729 uint8_t binuuid[20];
730
731 satip_device_calc_bin_uuid(binuuid, satip_uuid);
732 TVH_HARDWARE_FOREACH(th) {
733 if (idnode_is_instance(&th->th_id, &satip_device_class) &&
734 memcmp(th->th_id.in_uuid.bin, binuuid, UUID_BIN_SIZE) == 0)
735 return (satip_device_t *)th;
736 }
737 return NULL;
738 }
739
740 static satip_device_t *
satip_device_find_by_descurl(const char * descurl)741 satip_device_find_by_descurl( const char *descurl )
742 {
743 tvh_hardware_t *th;
744
745 TVH_HARDWARE_FOREACH(th) {
746 if (idnode_is_instance(&th->th_id, &satip_device_class) &&
747 strcmp(((satip_device_t *)th)->sd_info.location, descurl) == 0)
748 return (satip_device_t *)th;
749 }
750 return NULL;
751 }
752
753 void
satip_device_destroy(satip_device_t * sd)754 satip_device_destroy( satip_device_t *sd )
755 {
756 satip_frontend_t *lfe;
757
758 lock_assert(&global_lock);
759
760 mtimer_disarm(&sd->sd_destroy_timer);
761
762 idnode_save_check(&sd->th_id, 0);
763
764 while ((lfe = TAILQ_FIRST(&sd->sd_frontends)) != NULL)
765 satip_frontend_delete(lfe);
766
767 satip_device_dbus_notify(sd, "stop");
768
769 #define FREEM(x) free(sd->sd_info.x)
770 FREEM(myaddr);
771 FREEM(addr);
772 FREEM(uuid);
773 FREEM(bootid);
774 FREEM(configid);
775 FREEM(deviceid);
776 FREEM(location);
777 FREEM(server);
778 FREEM(friendlyname);
779 FREEM(manufacturer);
780 FREEM(manufacturerURL);
781 FREEM(modeldesc);
782 FREEM(modelname);
783 FREEM(modelnum);
784 FREEM(serialnum);
785 FREEM(presentation);
786 FREEM(tunercfg);
787 #undef FREEM
788 free(sd->sd_bindaddr);
789 free(sd->sd_tunercfg);
790
791 tvh_hardware_delete((tvh_hardware_t*)sd);
792 free(sd);
793 }
794
795 static void
satip_device_destroy_cb(void * aux)796 satip_device_destroy_cb( void *aux )
797 {
798 satip_device_destroy((satip_device_t *)aux);
799 satip_device_discovery_start();
800 }
801
802 void
satip_device_destroy_later(satip_device_t * sd,int after)803 satip_device_destroy_later( satip_device_t *sd, int after )
804 {
805 mtimer_arm_rel(&sd->sd_destroy_timer, satip_device_destroy_cb, sd, ms2mono(after));
806 }
807
808 /*
809 * Discovery job
810 */
811
812 typedef struct satip_discovery {
813 TAILQ_ENTRY(satip_discovery) disc_link;
814 char *myaddr;
815 char *location;
816 char *server;
817 char *uuid;
818 char *bootid;
819 char *configid;
820 char *deviceid;
821 url_t url;
822 http_client_t *http_client;
823 int64_t http_start;
824 } satip_discovery_t;
825
826 TAILQ_HEAD(satip_discovery_queue, satip_discovery);
827
828 static int satip_enabled;
829 static int satip_discoveries_count;
830 static struct satip_discovery_queue satip_discoveries;
831 static upnp_service_t *satip_discovery_service;
832 static mtimer_t satip_discovery_timer;
833 static mtimer_t satip_discovery_static_timer;
834 static mtimer_t satip_discovery_timerq;
835 static mtimer_t satip_discovery_msearch_timer;
836 static str_list_t *satip_static_clients;
837
838 static void
satip_discovery_destroy(satip_discovery_t * d,int unlink)839 satip_discovery_destroy(satip_discovery_t *d, int unlink)
840 {
841 if (d == NULL)
842 return;
843 if (unlink) {
844 atomic_dec(&satip_discoveries_count, 1);
845 TAILQ_REMOVE(&satip_discoveries, d, disc_link);
846 }
847 if (d->http_client)
848 http_client_close(d->http_client);
849 urlreset(&d->url);
850 free(d->myaddr);
851 free(d->location);
852 free(d->server);
853 free(d->uuid);
854 free(d->bootid);
855 free(d->configid);
856 free(d->deviceid);
857 free(d);
858 }
859
860 static satip_discovery_t *
satip_discovery_find(satip_discovery_t * d)861 satip_discovery_find(satip_discovery_t *d)
862 {
863 satip_discovery_t *sd;
864
865 TAILQ_FOREACH(sd, &satip_discoveries, disc_link)
866 if (strcmp(sd->uuid, d->uuid) == 0)
867 return sd;
868 return NULL;
869 }
870
871 static void
satip_discovery_http_closed(http_client_t * hc,int errn)872 satip_discovery_http_closed(http_client_t *hc, int errn)
873 {
874 satip_discovery_t *d = hc->hc_aux;
875 char *s;
876 htsmsg_t *xml = NULL, *tags, *root, *device;
877 const char *friendlyname, *manufacturer, *manufacturerURL, *modeldesc;
878 const char *modelname, *modelnum, *serialnum;
879 const char *presentation, *tunercfg, *udn, *uuid;
880 const char *cs, *arg;
881 satip_device_info_t info;
882 char errbuf[100];
883 char *argv[10];
884 int i, n;
885
886 s = http_arg_get(&hc->hc_args, "Content-Type");
887 if (s) {
888 n = http_tokenize(s, argv, ARRAY_SIZE(argv), ';');
889 if (n <= 0 || strcasecmp(s, "text/xml")) {
890 errn = ENOENT;
891 s = NULL;
892 }
893 }
894 if (errn != 0 || s == NULL || hc->hc_code != 200 ||
895 hc->hc_data_size == 0 || hc->hc_data == NULL) {
896 tvherror(LS_SATIP, "Cannot get %s: %s", d->location, strerror(errn));
897 return;
898 }
899
900 if (tvhtrace_enabled()) {
901 tvhtrace(LS_SATIP, "received XML description from %s", hc->hc_host);
902 tvhlog_hexdump(LS_SATIP, hc->hc_data, hc->hc_data_size);
903 }
904
905 if (d->myaddr == NULL || d->myaddr[0] == '\0') {
906 struct sockaddr_storage ip;
907 socklen_t addrlen = sizeof(ip);
908 errbuf[0] = '\0';
909 getsockname(hc->hc_fd, (struct sockaddr *)&ip, &addrlen);
910 inet_ntop(ip.ss_family, IP_IN_ADDR(ip), errbuf, sizeof(errbuf));
911 free(d->myaddr);
912 d->myaddr = strdup(errbuf);
913 }
914
915 s = hc->hc_data + hc->hc_data_size - 1;
916 while (s != hc->hc_data && *s != '/')
917 s--;
918 if (s != hc->hc_data)
919 s--;
920 if (strncmp(s, "</root>", 7))
921 return;
922 /* Parse */
923 xml = htsmsg_xml_deserialize(hc->hc_data, errbuf, sizeof(errbuf));
924 hc->hc_data = NULL;
925 if (!xml) {
926 tvherror(LS_SATIP, "satip_discovery_desc htsmsg_xml_deserialize error %s", errbuf);
927 goto finish;
928 }
929 if ((tags = htsmsg_get_map(xml, "tags")) == NULL)
930 goto finish;
931 if ((root = htsmsg_get_map(tags, "root")) == NULL)
932 goto finish;
933 if ((device = htsmsg_get_map(root, "tags")) == NULL)
934 goto finish;
935 if ((device = htsmsg_get_map(device, "device")) == NULL)
936 goto finish;
937 if ((device = htsmsg_get_map(device, "tags")) == NULL)
938 goto finish;
939 if ((cs = htsmsg_xml_get_cdata_str(device, "deviceType")) == NULL)
940 goto finish;
941 if (strcmp(cs, "urn:ses-com:device:SatIPServer:1"))
942 goto finish;
943 if ((friendlyname = htsmsg_xml_get_cdata_str(device, "friendlyName")) == NULL)
944 goto finish;
945 if ((manufacturer = htsmsg_xml_get_cdata_str(device, "manufacturer")) == NULL)
946 manufacturer = "";
947 if ((manufacturerURL = htsmsg_xml_get_cdata_str(device, "manufacturerURL")) == NULL)
948 manufacturerURL = "";
949 if ((modeldesc = htsmsg_xml_get_cdata_str(device, "modelDescription")) == NULL)
950 modeldesc = "";
951 if ((modelname = htsmsg_xml_get_cdata_str(device, "modelName")) == NULL)
952 goto finish;
953 if ((modelnum = htsmsg_xml_get_cdata_str(device, "modelNumber")) == NULL)
954 modelnum = "";
955 if ((serialnum = htsmsg_xml_get_cdata_str(device, "serialNumber")) == NULL)
956 serialnum = "";
957 if ((presentation = htsmsg_xml_get_cdata_str(device, "presentationURL")) == NULL)
958 presentation = "";
959 if ((udn = htsmsg_xml_get_cdata_str(device, "UDN")) == NULL)
960 goto finish;
961 if ((tunercfg = htsmsg_xml_get_cdata_str(device, "urn:ses-com:satipX_SATIPCAP")) == NULL)
962 tunercfg = "";
963
964 uuid = NULL;
965 n = http_tokenize((char *)udn, argv, ARRAY_SIZE(argv), ':');
966 for (i = 0; i < n+1; i++)
967 if (argv[i] && strcmp(argv[i], "uuid") == 0) {
968 uuid = argv[++i];
969 break;
970 }
971 if (uuid == NULL || (d->uuid[0] && strcmp(uuid, d->uuid)))
972 goto finish;
973
974 info.rtsp_port = 554;
975 info.srcs = 4;
976
977 arg = http_arg_get(&hc->hc_args, "X-SATIP-RTSP-Port");
978 if (arg) {
979 i = atoi(arg);
980 if (i > 0 && i < 65535)
981 info.rtsp_port = i;
982 }
983 arg = http_arg_get(&hc->hc_args, "X-SATIP-Sources");
984 if (arg) {
985 i = atoi(arg);
986 if (i > 0 && i < 128)
987 info.srcs = i;
988 }
989
990 info.myaddr = strdup(d->myaddr);
991 info.addr = strdup(d->url.host);
992 info.uuid = strdup(uuid);
993 info.bootid = strdup(d->bootid);
994 info.configid = strdup(d->configid);
995 info.deviceid = strdup(d->deviceid);
996 info.location = strdup(d->location);
997 info.server = strdup(d->server);
998 info.friendlyname = strdup(friendlyname);
999 info.manufacturer = strdup(manufacturer);
1000 info.manufacturerURL = strdup(manufacturerURL);
1001 info.modeldesc = strdup(modeldesc);
1002 info.modelname = strdup(modelname);
1003 info.modelnum = strdup(modelnum);
1004 info.serialnum = strdup(serialnum);
1005 info.presentation = strdup(presentation);
1006 info.tunercfg = strdup(tunercfg);
1007 htsmsg_destroy(xml);
1008 xml = NULL;
1009 pthread_mutex_lock(&global_lock);
1010 if (!satip_device_find(info.uuid))
1011 satip_device_create(&info);
1012 pthread_mutex_unlock(&global_lock);
1013 free(info.myaddr);
1014 free(info.location);
1015 free(info.server);
1016 free(info.addr);
1017 free(info.uuid);
1018 free(info.bootid);
1019 free(info.configid);
1020 free(info.deviceid);
1021 free(info.friendlyname);
1022 free(info.manufacturer);
1023 free(info.manufacturerURL);
1024 free(info.modeldesc);
1025 free(info.modelname);
1026 free(info.modelnum);
1027 free(info.serialnum);
1028 free(info.presentation);
1029 free(info.tunercfg);
1030 finish:
1031 htsmsg_destroy(xml);
1032 }
1033
1034 static void
satip_discovery_timerq_cb(void * aux)1035 satip_discovery_timerq_cb(void *aux)
1036 {
1037 satip_discovery_t *d, *next;
1038 int r;
1039
1040 lock_assert(&global_lock);
1041
1042 next = TAILQ_FIRST(&satip_discoveries);
1043 while (next) {
1044 d = next;
1045 next = TAILQ_NEXT(d, disc_link);
1046 if (d->http_client) {
1047 if (mclk() - d->http_start > sec2mono(4))
1048 satip_discovery_destroy(d, 1);
1049 continue;
1050 }
1051
1052 d->http_client = http_client_connect(d, HTTP_VERSION_1_1, d->url.scheme,
1053 d->url.host, d->url.port, NULL);
1054 if (d->http_client == NULL)
1055 satip_discovery_destroy(d, 1);
1056 else {
1057 d->http_start = mclk();
1058 d->http_client->hc_conn_closed = satip_discovery_http_closed;
1059 http_client_register(d->http_client);
1060 r = http_client_simple(d->http_client, &d->url);
1061 if (r < 0)
1062 satip_discovery_destroy(d, 1);
1063 }
1064 }
1065 if (TAILQ_FIRST(&satip_discoveries))
1066 mtimer_arm_rel(&satip_discovery_timerq, satip_discovery_timerq_cb, NULL, sec2mono(5));
1067 }
1068
1069 static void
satip_discovery_service_received(uint8_t * data,size_t len,udp_connection_t * conn,struct sockaddr_storage * storage)1070 satip_discovery_service_received
1071 (uint8_t *data, size_t len, udp_connection_t *conn,
1072 struct sockaddr_storage *storage)
1073 {
1074 char *buf, *ptr, *saveptr;
1075 char *argv[10];
1076 char *st = NULL;
1077 char *location = NULL;
1078 char *server = NULL;
1079 char *uuid = NULL;
1080 char *bootid = NULL;
1081 char *configid = NULL;
1082 char *deviceid = NULL;
1083 char sockbuf[128];
1084 satip_discovery_t *d;
1085 int n, i;
1086
1087 if (len > 8191 || atomic_get(&satip_discoveries_count) > 100)
1088 return;
1089 buf = alloca(len+1);
1090 memcpy(buf, data, len);
1091 buf[len] = '\0';
1092 ptr = strtok_r(buf, "\r\n", &saveptr);
1093 /* Request decoder */
1094 if (ptr) {
1095 if (http_tokenize(ptr, argv, 3, -1) != 3)
1096 return;
1097 if (conn->multicast) {
1098 if (strcmp(argv[0], "NOTIFY"))
1099 return;
1100 if (strcmp(argv[1], "*"))
1101 return;
1102 if (strcmp(argv[2], "HTTP/1.1"))
1103 return;
1104 } else {
1105 if (strcmp(argv[0], "HTTP/1.1"))
1106 return;
1107 if (strcmp(argv[1], "200"))
1108 return;
1109 }
1110 ptr = strtok_r(NULL, "\r\n", &saveptr);
1111 }
1112 /* Header decoder */
1113 while (1) {
1114 if (ptr == NULL)
1115 break;
1116 if (http_tokenize(ptr, argv, 2, ':') == 2) {
1117 if (strcmp(argv[0], "ST") == 0)
1118 st = argv[1];
1119 else if (strcmp(argv[0], "LOCATION") == 0)
1120 location = argv[1];
1121 else if (strcmp(argv[0], "SERVER") == 0)
1122 server = argv[1];
1123 else if (strcmp(argv[0], "BOOTID.UPNP.ORG") == 0)
1124 bootid = argv[1];
1125 else if (strcmp(argv[0], "CONFIGID.UPNP.ORG") == 0)
1126 configid = argv[1];
1127 else if (strcmp(argv[0], "DEVICEID.SES.COM") == 0)
1128 deviceid = argv[1];
1129 else if (strcmp(argv[0], "USN") == 0) {
1130 n = http_tokenize(argv[1], argv, ARRAY_SIZE(argv), ':');
1131 for (i = 0; i < n-1; i++)
1132 if (argv[i] && strcmp(argv[i], "uuid") == 0) {
1133 uuid = argv[++i];
1134 break;
1135 }
1136 }
1137 }
1138 ptr = strtok_r(NULL, "\r\n", &saveptr);
1139 }
1140 /* Sanity checks */
1141 if (st == NULL || strcmp(st, "urn:ses-com:device:SatIPServer:1"))
1142 goto add_uuid;
1143 if (uuid == NULL || strlen(uuid) < 16 || satip_server_match_uuid(uuid))
1144 goto add_uuid;
1145 if (location == NULL || strncmp(location, "http://", 7))
1146 goto add_uuid;
1147 if (server == NULL)
1148 goto add_uuid;
1149
1150 /* Forward information to next layer */
1151
1152 d = calloc(1, sizeof(satip_discovery_t));
1153 if (inet_ntop(conn->ip.ss_family, IP_IN_ADDR(conn->ip),
1154 sockbuf, sizeof(sockbuf)) == NULL) {
1155 satip_discovery_destroy(d, 0);
1156 return;
1157 }
1158 d->myaddr = strdup(sockbuf);
1159 d->location = strdup(location);
1160 d->server = strdup(server);
1161 d->uuid = strdup(uuid);
1162 d->bootid = strdup(bootid ?: "");
1163 d->configid = strdup(configid ?: "");
1164 d->deviceid = strdup(deviceid ?: "");
1165 if (urlparse(d->location, &d->url)) {
1166 satip_discovery_destroy(d, 0);
1167 return;
1168 }
1169
1170 pthread_mutex_lock(&global_lock);
1171 i = 1;
1172 if (!satip_discovery_find(d) && !satip_device_find(d->uuid)) {
1173 TAILQ_INSERT_TAIL(&satip_discoveries, d, disc_link);
1174 atomic_add(&satip_discoveries_count, 1);
1175 mtimer_arm_rel(&satip_discovery_timerq, satip_discovery_timerq_cb, NULL, ms2mono(250));
1176 i = 0;
1177 }
1178 pthread_mutex_unlock(&global_lock);
1179 if (i) /* duplicate */
1180 satip_discovery_destroy(d, 0);
1181 return;
1182
1183 add_uuid:
1184 if (deviceid == NULL || uuid == NULL)
1185 return;
1186 /* if new uuid was discovered, retrigger MSEARCH */
1187 pthread_mutex_lock(&global_lock);
1188 if (!satip_device_find(uuid))
1189 mtimer_arm_rel(&satip_discovery_timer, satip_discovery_timer_cb, NULL, sec2mono(5));
1190 pthread_mutex_unlock(&global_lock);
1191 }
1192
1193 static void
satip_discovery_static(const char * descurl)1194 satip_discovery_static(const char *descurl)
1195 {
1196 satip_discovery_t *d;
1197
1198 lock_assert(&global_lock);
1199
1200 if (satip_device_find_by_descurl(descurl))
1201 return;
1202 d = calloc(1, sizeof(satip_discovery_t));
1203 urlinit(&d->url);
1204 if (urlparse(descurl, &d->url)) {
1205 satip_discovery_destroy(d, 0);
1206 return;
1207 }
1208 d->myaddr = strdup("");
1209 d->location = strdup(descurl);
1210 d->server = strdup("");
1211 d->uuid = strdup("");
1212 d->bootid = strdup("");
1213 d->configid = strdup("");
1214 d->deviceid = strdup("");
1215 TAILQ_INSERT_TAIL(&satip_discoveries, d, disc_link);
1216 atomic_add(&satip_discoveries_count, 1);
1217 satip_discovery_timerq_cb(NULL);
1218 }
1219
1220 static void
satip_discovery_service_destroy(upnp_service_t * us)1221 satip_discovery_service_destroy(upnp_service_t *us)
1222 {
1223 satip_discovery_service = NULL;
1224 }
1225
1226 static void
satip_discovery_send_msearch(void * aux)1227 satip_discovery_send_msearch(void *aux)
1228 {
1229 #define MSG "\
1230 M-SEARCH * HTTP/1.1\r\n\
1231 HOST: 239.255.255.250:1900\r\n\
1232 MAN: \"ssdp:discover\"\r\n\
1233 MX: 2\r\n\
1234 ST: urn:ses-com:device:SatIPServer:1\r\n"
1235 int attempt = ((intptr_t)aux) % 10;
1236 htsbuf_queue_t q;
1237
1238 /* UDP is not reliable - send this message three times */
1239 if (attempt < 1 || attempt > 3)
1240 return;
1241 if (satip_discovery_service == NULL)
1242 return;
1243
1244 htsbuf_queue_init(&q, 0);
1245 htsbuf_append(&q, MSG, sizeof(MSG)-1);
1246 htsbuf_qprintf(&q, "USER-AGENT: unix/1.0 UPnP/1.1 TVHeadend/%s\r\n", tvheadend_version);
1247 htsbuf_append(&q, "\r\n", 2);
1248 upnp_send(&q, NULL, 0, 0);
1249 htsbuf_queue_flush(&q);
1250
1251 mtimer_arm_rel(&satip_discovery_msearch_timer, satip_discovery_send_msearch,
1252 (void *)(intptr_t)(attempt + 1), ms2mono(attempt * 11));
1253 #undef MSG
1254 }
1255
1256 static void
satip_discovery_static_timer_cb(void * aux)1257 satip_discovery_static_timer_cb(void *aux)
1258 {
1259 static int next_timeout = 10;
1260 int i;
1261
1262 if (!tvheadend_is_running())
1263 return;
1264 for (i = 0; i < satip_static_clients->num; i++)
1265 satip_discovery_static(satip_static_clients->str[i]);
1266 mtimer_arm_rel(&satip_discovery_static_timer, satip_discovery_static_timer_cb,
1267 NULL, sec2mono(next_timeout));
1268 if (next_timeout < 3600)
1269 next_timeout = next_timeout >= 30 ? 3600 : 30;
1270 }
1271
1272 static void
satip_discovery_timer_cb(void * aux)1273 satip_discovery_timer_cb(void *aux)
1274 {
1275 static int next_timeout = 10;
1276
1277 if (!tvheadend_is_running())
1278 return;
1279 if (!atomic_get(&upnp_running)) {
1280 mtimer_arm_rel(&satip_discovery_timer, satip_discovery_timer_cb,
1281 NULL, sec2mono(1));
1282 return;
1283 }
1284 if (satip_discovery_service == NULL) {
1285 satip_discovery_service = upnp_service_create(upnp_service);
1286 if (satip_discovery_service) {
1287 satip_discovery_service->us_received = satip_discovery_service_received;
1288 satip_discovery_service->us_destroy = satip_discovery_service_destroy;
1289 }
1290 }
1291 if (satip_discovery_service)
1292 satip_discovery_send_msearch((void *)1);
1293 mtimer_arm_rel(&satip_discovery_timer, satip_discovery_timer_cb,
1294 NULL, sec2mono(next_timeout));
1295 if (next_timeout < 3600)
1296 next_timeout = next_timeout >= 30 ? 3600 : 30;
1297 }
1298
1299 void
satip_device_discovery_start(void)1300 satip_device_discovery_start( void )
1301 {
1302 if (!satip_enabled)
1303 return;
1304 mtimer_arm_rel(&satip_discovery_timer, satip_discovery_timer_cb,
1305 NULL, sec2mono(1));
1306 mtimer_arm_rel(&satip_discovery_static_timer, satip_discovery_static_timer_cb,
1307 NULL, sec2mono(1));
1308 }
1309
1310 /*
1311 * Initialization
1312 */
1313
satip_init(int nosatip,str_list_t * clients)1314 void satip_init ( int nosatip, str_list_t *clients )
1315 {
1316 idclass_register(&satip_device_class);
1317
1318 idclass_register(&satip_frontend_class);
1319 idclass_register(&satip_frontend_dvbt_class);
1320 idclass_register(&satip_frontend_dvbs_class);
1321 idclass_register(&satip_frontend_dvbs_slave_class);
1322 idclass_register(&satip_frontend_atsc_t_class);
1323 idclass_register(&satip_frontend_atsc_c_class);
1324
1325 idclass_register(&satip_satconf_class);
1326
1327 satip_enabled = !nosatip;
1328 TAILQ_INIT(&satip_discoveries);
1329 satip_static_clients = clients;
1330 if (satip_enabled) {
1331 dbus_register_rpc_str("satip_addr", NULL, satip_device_addr);
1332 satip_device_discovery_start();
1333 }
1334 }
1335
satip_done(void)1336 void satip_done ( void )
1337 {
1338 tvh_hardware_t *th, *n;
1339 satip_discovery_t *d, *nd;
1340
1341 pthread_mutex_lock(&global_lock);
1342 for (th = LIST_FIRST(&tvh_hardware); th != NULL; th = n) {
1343 n = LIST_NEXT(th, th_link);
1344 if (idnode_is_instance(&th->th_id, &satip_device_class)) {
1345 satip_device_destroy((satip_device_t *)th);
1346 }
1347 }
1348 for (d = TAILQ_FIRST(&satip_discoveries); d != NULL; d = nd) {
1349 nd = TAILQ_NEXT(d, disc_link);
1350 satip_discovery_destroy(d, 1);
1351 }
1352 pthread_mutex_unlock(&global_lock);
1353 }
1354