libsodium: Needed for Dnscrypto-proxy Release 1.3.0
[tomato.git] / release / src / router / minidlna / minidlna.c
blobc8ed07e34b5cd2a96b73f553c82a1f013099f2e3
1 /* MiniDLNA project
3 * http://sourceforge.net/projects/minidlna/
5 * MiniDLNA media server
6 * Copyright (C) 2008-2009 Justin Maggard
8 * This file is part of MiniDLNA.
10 * MiniDLNA is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
14 * MiniDLNA is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with MiniDLNA. If not, see <http://www.gnu.org/licenses/>.
22 * Portions of the code from the MiniUPnP project:
24 * Copyright (c) 2006-2007, Thomas Bernard
25 * All rights reserved.
27 * Redistribution and use in source and binary forms, with or without
28 * modification, are permitted provided that the following conditions are met:
29 * * Redistributions of source code must retain the above copyright
30 * notice, this list of conditions and the following disclaimer.
31 * * Redistributions in binary form must reproduce the above copyright
32 * notice, this list of conditions and the following disclaimer in the
33 * documentation and/or other materials provided with the distribution.
34 * * The name of the author may not be used to endorse or promote products
35 * derived from this software without specific prior written permission.
37 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
38 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
39 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
40 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
41 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
43 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
44 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
45 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
46 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
47 * POSSIBILITY OF SUCH DAMAGE.
49 #include <stdlib.h>
50 #include <unistd.h>
51 #include <string.h>
52 #include <stdio.h>
53 #include <ctype.h>
54 #include <sys/types.h>
55 #include <sys/socket.h>
56 #include <netinet/in.h>
57 #include <arpa/inet.h>
58 #include <fcntl.h>
59 #include <sys/file.h>
60 #include <sys/time.h>
61 #include <time.h>
62 #include <signal.h>
63 #include <sys/param.h>
64 #include <errno.h>
65 #include <pthread.h>
66 #include <pwd.h>
68 #include "config.h"
70 #ifdef ENABLE_NLS
71 #include <libintl.h>
72 #endif
74 #include "upnpglobalvars.h"
75 #include "sql.h"
76 #include "upnphttp.h"
77 #include "upnpdescgen.h"
78 #include "minidlnapath.h"
79 #include "getifaddr.h"
80 #include "upnpsoap.h"
81 #include "options.h"
82 #include "utils.h"
83 #include "minissdp.h"
84 #include "minidlnatypes.h"
85 #include "daemonize.h"
86 #include "upnpevents.h"
87 #include "scanner.h"
88 #include "inotify.h"
89 #include "log.h"
90 #ifdef TIVO_SUPPORT
91 #include "tivo_beacon.h"
92 #include "tivo_utils.h"
93 #endif
95 #if SQLITE_VERSION_NUMBER < 3005001
96 # warning "Your SQLite3 library appears to be too old! Please use 3.5.1 or newer."
97 # define sqlite3_threadsafe() 0
98 #endif
100 /* OpenAndConfHTTPSocket() :
101 * setup the socket used to handle incoming HTTP connections. */
102 static int
103 OpenAndConfHTTPSocket(unsigned short port)
105 int s;
106 int i = 1;
107 struct sockaddr_in listenname;
109 /* Initialize client type cache */
110 memset(&clients, 0, sizeof(struct client_cache_s));
112 if( (s = socket(PF_INET, SOCK_STREAM, 0)) < 0)
114 DPRINTF(E_ERROR, L_GENERAL, "socket(http): %s\n", strerror(errno));
115 return -1;
118 if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)) < 0)
120 DPRINTF(E_WARN, L_GENERAL, "setsockopt(http, SO_REUSEADDR): %s\n", strerror(errno));
123 memset(&listenname, 0, sizeof(struct sockaddr_in));
124 listenname.sin_family = AF_INET;
125 listenname.sin_port = htons(port);
126 listenname.sin_addr.s_addr = htonl(INADDR_ANY);
128 if(bind(s, (struct sockaddr *)&listenname, sizeof(struct sockaddr_in)) < 0)
130 DPRINTF(E_ERROR, L_GENERAL, "bind(http): %s\n", strerror(errno));
131 close(s);
132 return -1;
135 if(listen(s, 6) < 0)
137 DPRINTF(E_ERROR, L_GENERAL, "listen(http): %s\n", strerror(errno));
138 close(s);
139 return -1;
142 return s;
145 /* Handler for the SIGTERM signal (kill)
146 * SIGINT is also handled */
147 static void
148 sigterm(int sig)
150 /*int save_errno = errno;*/
151 signal(sig, SIG_IGN); /* Ignore this signal while we are quitting */
153 DPRINTF(E_WARN, L_GENERAL, "received signal %d, good-bye\n", sig);
155 quitting = 1;
156 /*errno = save_errno;*/
159 /* record the startup time, for returning uptime */
160 static void
161 set_startup_time(void)
163 startup_time = time(NULL);
166 /* parselanaddr()
167 * parse address with mask
168 * ex: 192.168.1.1/24
169 * return value :
170 * 0 : ok
171 * -1 : error */
172 static int
173 parselanaddr(struct lan_addr_s * lan_addr, const char * str)
175 const char * p;
176 int nbits = 24;
177 int n;
178 p = str;
179 while(*p && *p != '/' && !isspace(*p))
180 p++;
181 n = p - str;
182 if(*p == '/')
184 nbits = atoi(++p);
185 while(*p && !isspace(*p))
186 p++;
188 if(n>15)
190 DPRINTF(E_OFF, L_GENERAL, "Error parsing address/mask: %s\n", str);
191 return -1;
193 memcpy(lan_addr->str, str, n);
194 lan_addr->str[n] = '\0';
195 if(!inet_aton(lan_addr->str, &lan_addr->addr))
197 DPRINTF(E_OFF, L_GENERAL, "Error parsing address: %s\n", str);
198 return -1;
200 lan_addr->mask.s_addr = htonl(nbits ? (0xffffffff << (32 - nbits)) : 0);
201 return 0;
204 static void
205 getfriendlyname(char * buf, int len)
207 char * dot = NULL;
208 char * hn = calloc(1, 256);
209 int off;
211 if( gethostname(hn, 256) == 0 )
213 strncpyt(buf, hn, len);
214 dot = strchr(buf, '.');
215 if( dot )
216 *dot = '\0';
218 else
220 strcpy(buf, "Unknown");
222 free(hn);
224 off = strlen(buf);
225 off += snprintf(buf+off, len-off, ": ");
226 #ifdef READYNAS
227 FILE * info;
228 char ibuf[64], *key, *val;
229 snprintf(buf+off, len-off, "ReadyNAS");
230 info = fopen("/proc/sys/dev/boot/info", "r");
231 if( !info )
232 return;
233 while( (val = fgets(ibuf, 64, info)) != NULL )
235 key = strsep(&val, ": \t");
236 val = trim(val);
237 if( strcmp(key, "model") == 0 )
239 snprintf(buf+off, len-off, "%s", val);
240 key = strchr(val, ' ');
241 if( key )
243 strncpyt(modelnumber, key+1, MODELNUMBER_MAX_LEN);
244 *key = '\0';
246 snprintf(modelname, MODELNAME_MAX_LEN,
247 "Windows Media Connect compatible (%s)", val);
249 else if( strcmp(key, "serial") == 0 )
251 strncpyt(serialnumber, val, SERIALNUMBER_MAX_LEN);
252 if( serialnumber[0] == '\0' )
254 char mac_str[13];
255 if( getsyshwaddr(mac_str, sizeof(mac_str)) == 0 )
256 strcpy(serialnumber, mac_str);
257 else
258 strcpy(serialnumber, "0");
260 break;
263 fclose(info);
264 memcpy(pnpx_hwid+4, "01F2", 4);
265 if( strcmp(modelnumber, "NVX") == 0 )
266 memcpy(pnpx_hwid+17, "0101", 4);
267 else if( strcmp(modelnumber, "Pro") == 0 ||
268 strcmp(modelnumber, "Pro 6") == 0 ||
269 strncmp(modelnumber, "Ultra 6", 7) == 0 )
270 memcpy(pnpx_hwid+17, "0102", 4);
271 else if( strcmp(modelnumber, "Pro 2") == 0 ||
272 strncmp(modelnumber, "Ultra 2", 7) == 0 )
273 memcpy(pnpx_hwid+17, "0103", 4);
274 else if( strcmp(modelnumber, "Pro 4") == 0 ||
275 strncmp(modelnumber, "Ultra 4", 7) == 0 )
276 memcpy(pnpx_hwid+17, "0104", 4);
277 else if( strcmp(modelnumber+1, "100") == 0 )
278 memcpy(pnpx_hwid+17, "0105", 4);
279 else if( strcmp(modelnumber+1, "200") == 0 )
280 memcpy(pnpx_hwid+17, "0106", 4);
281 /* 0107 = Stora */
282 else if( strcmp(modelnumber, "Duo v2") == 0 )
283 memcpy(pnpx_hwid+17, "0108", 4);
284 else if( strcmp(modelnumber, "NV+ v2") == 0 )
285 memcpy(pnpx_hwid+17, "0109", 4);
286 #else
287 char * logname;
288 logname = getenv("LOGNAME");
289 #ifndef STATIC // Disable for static linking
290 if( !logname )
292 struct passwd * pwent;
293 pwent = getpwuid(getuid());
294 if( pwent )
295 logname = pwent->pw_name;
297 #endif
298 snprintf(buf+off, len-off, "%s", logname?logname:"Unknown");
299 #endif
302 static int
303 open_db(void)
305 char path[PATH_MAX];
306 int new_db = 0;
308 snprintf(path, sizeof(path), "%s/files.db", db_path);
309 if( access(path, F_OK) != 0 )
311 new_db = 1;
312 make_dir(db_path, S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO);
314 if( sqlite3_open(path, &db) != SQLITE_OK )
316 DPRINTF(E_FATAL, L_GENERAL, "ERROR: Failed to open sqlite database! Exiting...\n");
318 sqlite3_busy_timeout(db, 5000);
319 sql_exec(db, "pragma page_size = 4096");
320 sql_exec(db, "pragma journal_mode = OFF");
321 sql_exec(db, "pragma synchronous = OFF;");
323 // this sets the sqlite database cache size
324 // original code had 8192 = 32MB - reduce it to 4MB
325 sql_exec(db, "pragma default_cache_size = 1024;");
326 return new_db;
329 /* init phase :
330 * 1) read configuration file
331 * 2) read command line arguments
332 * 3) daemonize
333 * 4) check and write pid file
334 * 5) set startup time stamp
335 * 6) compute presentation URL
336 * 7) set signal handlers */
337 static int
338 init(int argc, char * * argv)
340 int i;
341 int pid;
342 int debug_flag = 0;
343 int verbose_flag = 0;
344 int options_flag = 0;
345 struct sigaction sa;
346 const char * presurl = NULL;
347 const char * optionsfile = "/etc/minidlna.conf";
348 char mac_str[13];
349 char * string, * word;
350 enum media_types type;
351 char * path;
352 char buf[PATH_MAX];
353 char ip_addr[INET_ADDRSTRLEN + 3] = {'\0'};
354 char log_str[72] = "general,artwork,database,inotify,scanner,metadata,http,ssdp,tivo=warn";
355 char *log_level = NULL;
357 /* first check if "-f" option is used */
358 for(i=2; i<argc; i++)
360 if(0 == strcmp(argv[i-1], "-f"))
362 optionsfile = argv[i];
363 options_flag = 1;
364 break;
368 /* set up uuid based on mac address */
369 if( getsyshwaddr(mac_str, sizeof(mac_str)) < 0 )
371 DPRINTF(E_OFF, L_GENERAL, "No MAC address found. Falling back to generic UUID.\n");
372 strcpy(mac_str, "554e4b4e4f57");
374 strcpy(uuidvalue+5, "4d696e69-444c-164e-9d41-");
375 strncat(uuidvalue, mac_str, 12);
377 getfriendlyname(friendly_name, FRIENDLYNAME_MAX_LEN);
379 runtime_vars.port = -1;
380 runtime_vars.notify_interval = 895; /* seconds between SSDP announces */
381 runtime_vars.root_container = NULL;
383 /* read options file first since
384 * command line arguments have final say */
385 if(readoptionsfile(optionsfile) < 0)
387 /* only error if file exists or using -f */
388 if(access(optionsfile, F_OK) == 0 || options_flag)
389 DPRINTF(E_ERROR, L_GENERAL, "Error reading configuration file %s\n", optionsfile);
391 else
393 for(i=0; i<num_options; i++)
395 switch(ary_options[i].id)
397 case UPNPIFNAME:
398 for( string = ary_options[i].value; (word = strtok(string, ",")); string = NULL )
400 if(n_lan_addr < MAX_LAN_ADDR)
402 if(getifaddr(word, ip_addr, sizeof(ip_addr)) >= 0)
404 if( *ip_addr && parselanaddr(&lan_addr[n_lan_addr], ip_addr) == 0 )
405 if(n_lan_addr < MAX_LAN_ADDR)
406 n_lan_addr++;
409 else
411 DPRINTF(E_ERROR, L_GENERAL, "Too many listening ips (max: %d), ignoring %s\n",
412 MAX_LAN_ADDR, word);
415 break;
416 case UPNPLISTENING_IP:
417 if(n_lan_addr < MAX_LAN_ADDR)
419 if(parselanaddr(&lan_addr[n_lan_addr],
420 ary_options[i].value) == 0)
421 n_lan_addr++;
423 else
425 DPRINTF(E_ERROR, L_GENERAL, "Too many listening ips (max: %d), ignoring %s\n",
426 MAX_LAN_ADDR, ary_options[i].value);
428 break;
429 case UPNPPORT:
430 runtime_vars.port = atoi(ary_options[i].value);
431 break;
432 case UPNPPRESENTATIONURL:
433 presurl = ary_options[i].value;
434 break;
435 case UPNPNOTIFY_INTERVAL:
436 runtime_vars.notify_interval = atoi(ary_options[i].value);
437 break;
438 case UPNPSERIAL:
439 strncpyt(serialnumber, ary_options[i].value, SERIALNUMBER_MAX_LEN);
440 break;
441 case UPNPMODEL_NAME:
442 strncpyt(modelname, ary_options[i].value, MODELNAME_MAX_LEN);
443 break;
444 case UPNPMODEL_NUMBER:
445 strncpyt(modelnumber, ary_options[i].value, MODELNUMBER_MAX_LEN);
446 break;
447 case UPNPFRIENDLYNAME:
448 strncpyt(friendly_name, ary_options[i].value, FRIENDLYNAME_MAX_LEN);
449 break;
450 case UPNPMEDIADIR:
451 type = ALL_MEDIA;
452 char * myval = NULL;
453 switch( ary_options[i].value[0] )
455 case 'A':
456 case 'a':
457 if( ary_options[i].value[0] == 'A' || ary_options[i].value[0] == 'a' )
458 type = AUDIO_ONLY;
459 case 'V':
460 case 'v':
461 if( ary_options[i].value[0] == 'V' || ary_options[i].value[0] == 'v' )
462 type = VIDEO_ONLY;
463 case 'P':
464 case 'p':
465 if( ary_options[i].value[0] == 'P' || ary_options[i].value[0] == 'p' )
466 type = IMAGES_ONLY;
467 myval = index(ary_options[i].value, '/');
468 case '/':
469 path = realpath(myval ? myval:ary_options[i].value, buf);
470 if( !path )
471 path = (myval ? myval:ary_options[i].value);
472 if( access(path, F_OK) != 0 )
474 DPRINTF(E_ERROR, L_GENERAL, "Media directory \"%s\" not accessible! [%s]\n",
475 path, strerror(errno));
476 break;
478 struct media_dir_s * this_dir = calloc(1, sizeof(struct media_dir_s));
479 this_dir->path = strdup(path);
480 this_dir->type = type;
481 if( !media_dirs )
483 media_dirs = this_dir;
485 else
487 struct media_dir_s * all_dirs = media_dirs;
488 while( all_dirs->next )
489 all_dirs = all_dirs->next;
490 all_dirs->next = this_dir;
492 break;
493 default:
494 DPRINTF(E_ERROR, L_GENERAL, "Media directory entry not understood! [%s]\n",
495 ary_options[i].value);
496 break;
498 break;
499 case UPNPALBUMART_NAMES:
500 for( string = ary_options[i].value; (word = strtok(string, "/")); string = NULL )
502 struct album_art_name_s * this_name = calloc(1, sizeof(struct album_art_name_s));
503 int len = strlen(word);
504 if( word[len-1] == '*' )
506 word[len-1] = '\0';
507 this_name->wildcard = 1;
509 this_name->name = strdup(word);
510 if( !album_art_names )
512 album_art_names = this_name;
514 else
516 struct album_art_name_s * all_names = album_art_names;
517 while( all_names->next )
518 all_names = all_names->next;
519 all_names->next = this_name;
522 break;
523 case UPNPDBDIR:
524 path = realpath(ary_options[i].value, buf);
525 if( !path )
526 path = (ary_options[i].value);
527 make_dir(path, S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO);
528 if( access(path, F_OK) != 0 )
530 DPRINTF(E_FATAL, L_GENERAL, "Database path not accessible! [%s]\n", path);
531 break;
533 strncpyt(db_path, path, PATH_MAX);
534 break;
535 case UPNPLOGDIR:
536 path = realpath(ary_options[i].value, buf);
537 if( !path )
538 path = (ary_options[i].value);
539 make_dir(path, S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO);
540 if( access(path, F_OK) != 0 )
542 DPRINTF(E_FATAL, L_GENERAL, "Log path not accessible! [%s]\n", path);
543 break;
545 strncpyt(log_path, path, PATH_MAX);
546 break;
547 case UPNPLOGLEVEL:
548 log_level = ary_options[i].value;
549 break;
550 case UPNPINOTIFY:
551 if( (strcmp(ary_options[i].value, "yes") != 0) && !atoi(ary_options[i].value) )
552 CLEARFLAG(INOTIFY_MASK);
553 break;
554 case ENABLE_TIVO:
555 if( (strcmp(ary_options[i].value, "yes") == 0) || atoi(ary_options[i].value) )
556 SETFLAG(TIVO_MASK);
557 break;
558 case ENABLE_DLNA_STRICT:
559 if( (strcmp(ary_options[i].value, "yes") == 0) || atoi(ary_options[i].value) )
560 SETFLAG(DLNA_STRICT_MASK);
561 break;
562 case ROOT_CONTAINER:
563 switch( ary_options[i].value[0] )
565 case '.':
566 runtime_vars.root_container = NULL;
567 break;
568 case 'B':
569 case 'b':
570 runtime_vars.root_container = BROWSEDIR_ID;
571 break;
572 case 'M':
573 case 'm':
574 runtime_vars.root_container = MUSIC_ID;
575 break;
576 case 'V':
577 case 'v':
578 runtime_vars.root_container = VIDEO_ID;
579 break;
580 case 'P':
581 case 'p':
582 runtime_vars.root_container = IMAGE_ID;
583 break;
584 default:
585 DPRINTF(E_ERROR, L_GENERAL, "Invalid root container! [%s]\n",
586 ary_options[i].value);
587 break;
589 break;
590 case UPNPMINISSDPDSOCKET:
591 minissdpdsocketpath = ary_options[i].value;
592 break;
593 default:
594 DPRINTF(E_ERROR, L_GENERAL, "Unknown option in file %s\n",
595 optionsfile);
599 if( log_path[0] == '\0' )
601 if( db_path[0] == '\0' )
602 strncpyt(log_path, DEFAULT_LOG_PATH, PATH_MAX);
603 else
604 strncpyt(log_path, db_path, PATH_MAX);
606 if( db_path[0] == '\0' )
607 strncpyt(db_path, DEFAULT_DB_PATH, PATH_MAX);
609 /* command line arguments processing */
610 for(i=1; i<argc; i++)
612 if(argv[i][0]!='-')
614 DPRINTF(E_ERROR, L_GENERAL, "Unknown option: %s\n", argv[i]);
616 else if(strcmp(argv[i], "--help")==0)
618 runtime_vars.port = -1;
619 break;
621 else switch(argv[i][1])
623 case 't':
624 if(i+1 < argc)
625 runtime_vars.notify_interval = atoi(argv[++i]);
626 else
627 DPRINTF(E_ERROR, L_GENERAL, "Option -%c takes one argument.\n", argv[i][1]);
628 break;
629 case 's':
630 if(i+1 < argc)
631 strncpyt(serialnumber, argv[++i], SERIALNUMBER_MAX_LEN);
632 else
633 DPRINTF(E_ERROR, L_GENERAL, "Option -%c takes one argument.\n", argv[i][1]);
634 break;
635 case 'm':
636 if(i+1 < argc)
637 strncpyt(modelnumber, argv[++i], MODELNUMBER_MAX_LEN);
638 else
639 DPRINTF(E_ERROR, L_GENERAL, "Option -%c takes one argument.\n", argv[i][1]);
640 break;
641 case 'p':
642 if(i+1 < argc)
643 runtime_vars.port = atoi(argv[++i]);
644 else
645 DPRINTF(E_ERROR, L_GENERAL, "Option -%c takes one argument.\n", argv[i][1]);
646 break;
647 case 'P':
648 if(i+1 < argc)
649 pidfilename = argv[++i];
650 else
651 DPRINTF(E_ERROR, L_GENERAL, "Option -%c takes one argument.\n", argv[i][1]);
652 break;
653 case 'd':
654 debug_flag = 1;
655 case 'v':
656 verbose_flag = 1;
657 break;
658 case 'L':
659 SETFLAG(NO_PLAYLIST_MASK);
660 break;
661 case 'w':
662 if(i+1 < argc)
663 presurl = argv[++i];
664 else
665 DPRINTF(E_ERROR, L_GENERAL, "Option -%c takes one argument.\n", argv[i][1]);
666 break;
667 case 'a':
668 if(i+1 < argc)
670 int address_already_there = 0;
671 int j;
672 i++;
673 for(j=0; j<n_lan_addr; j++)
675 struct lan_addr_s tmpaddr;
676 parselanaddr(&tmpaddr, argv[i]);
677 if(0 == strcmp(lan_addr[j].str, tmpaddr.str))
678 address_already_there = 1;
680 if(address_already_there)
681 break;
682 if(n_lan_addr < MAX_LAN_ADDR)
684 if(parselanaddr(&lan_addr[n_lan_addr], argv[i]) == 0)
685 n_lan_addr++;
687 else
689 DPRINTF(E_ERROR, L_GENERAL, "Too many listening ips (max: %d), ignoring %s\n",
690 MAX_LAN_ADDR, argv[i]);
693 else
694 DPRINTF(E_ERROR, L_GENERAL, "Option -%c takes one argument.\n", argv[i][1]);
695 break;
696 case 'i':
697 if(i+1 < argc)
699 int address_already_there = 0;
700 int j;
701 i++;
702 if( getifaddr(argv[i], ip_addr, sizeof(ip_addr)) < 0 )
704 DPRINTF(E_FATAL, L_GENERAL, "Required network interface '%s' not found.\n",
705 argv[i]);
707 for(j=0; j<n_lan_addr; j++)
709 struct lan_addr_s tmpaddr;
710 parselanaddr(&tmpaddr, ip_addr);
711 if(0 == strcmp(lan_addr[j].str, tmpaddr.str))
712 address_already_there = 1;
714 if(address_already_there)
715 break;
716 if(n_lan_addr < MAX_LAN_ADDR)
718 if(parselanaddr(&lan_addr[n_lan_addr], ip_addr) == 0)
719 n_lan_addr++;
721 else
723 DPRINTF(E_ERROR, L_GENERAL, "Too many listening ips (max: %d), ignoring %s\n",
724 MAX_LAN_ADDR, argv[i]);
727 else
728 DPRINTF(E_ERROR, L_GENERAL, "Option -%c takes one argument.\n", argv[i][1]);
729 break;
730 case 'f':
731 i++; /* discarding, the config file is already read */
732 break;
733 case 'h':
734 runtime_vars.port = -1; // triggers help display
735 break;
736 case 'R':
737 snprintf(buf, sizeof(buf), "rm -rf %s/files.db %s/art_cache", db_path, db_path);
738 if( system(buf) != 0 )
739 DPRINTF(E_WARN, L_GENERAL, "Failed to clean old file cache.\n");
740 break;
741 case 'V':
742 printf("Version " MINIDLNA_VERSION "\n");
743 exit(0);
744 break;
745 default:
746 DPRINTF(E_ERROR, L_GENERAL, "Unknown option: %s\n", argv[i]);
749 /* If no IP was specified, try to detect one */
750 if( n_lan_addr < 1 )
752 if( (getsysaddr(ip_addr, sizeof(ip_addr)) < 0) &&
753 (getifaddr("eth0", ip_addr, sizeof(ip_addr)) < 0) &&
754 (getifaddr("eth1", ip_addr, sizeof(ip_addr)) < 0) )
756 DPRINTF(E_OFF, L_GENERAL, "No IP address automatically detected!\n");
758 if( *ip_addr && parselanaddr(&lan_addr[n_lan_addr], ip_addr) == 0 )
760 n_lan_addr++;
764 if( (n_lan_addr==0) || (runtime_vars.port<0) )
766 DPRINTF(E_ERROR, L_GENERAL, "Usage:\n\t"
767 "%s [-d] [-v] [-f config_file]\n"
768 "\t\t[-a listening_ip] [-p port]\n"
769 /*"[-l logfile] " not functionnal */
770 "\t\t[-s serial] [-m model_number] \n"
771 "\t\t[-t notify_interval] [-P pid_filename]\n"
772 "\t\t[-w url] [-R] [-V] [-h]\n"
773 "\nNotes:\n\tNotify interval is in seconds. Default is 895 seconds.\n"
774 "\tDefault pid file is %s.\n"
775 "\tWith -d minidlna will run in debug mode (not daemonize).\n"
776 "\t-w sets the presentation url. Default is http address on port 80\n"
777 "\t-h displays this text\n"
778 "\t-R forces a full rescan\n"
779 "\t-L do note create playlists\n"
780 "\t-V print the version number\n",
781 argv[0], pidfilename);
782 return 1;
785 if( verbose_flag )
787 strcpy(log_str+65, "debug");
788 log_level = log_str;
790 else if( !log_level )
792 log_level = log_str;
794 if(debug_flag)
796 pid = getpid();
797 log_init(NULL, log_level);
799 else
801 pid = daemonize();
802 #ifdef READYNAS
803 log_init("/var/log/upnp-av.log", log_level);
804 #else
805 if( access(db_path, F_OK) != 0 )
806 make_dir(db_path, S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO);
807 sprintf(buf, "%s/minidlna.log", log_path);
808 log_init(buf, log_level);
809 #endif
812 if(checkforrunning(pidfilename) < 0)
814 DPRINTF(E_ERROR, L_GENERAL, "MiniDLNA is already running. EXITING.\n");
815 return 1;
818 set_startup_time();
820 /* presentation url */
821 if(presurl)
822 strncpyt(presentationurl, presurl, PRESENTATIONURL_MAX_LEN);
823 else
824 strcpy(presentationurl, "/");
826 /* set signal handler */
827 memset(&sa, 0, sizeof(struct sigaction));
828 sa.sa_handler = sigterm;
829 if (sigaction(SIGTERM, &sa, NULL))
831 DPRINTF(E_FATAL, L_GENERAL, "Failed to set SIGTERM handler. EXITING.\n");
833 if (sigaction(SIGINT, &sa, NULL))
835 DPRINTF(E_FATAL, L_GENERAL, "Failed to set SIGINT handler. EXITING.\n");
838 if(signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
839 DPRINTF(E_FATAL, L_GENERAL, "Failed to ignore SIGPIPE signals. EXITING.\n");
842 writepidfile(pidfilename, pid);
844 return 0;
847 /* === main === */
848 /* process HTTP or SSDP requests */
850 main(int argc, char * * argv)
852 int i;
853 int sudp = -1, shttpl = -1;
854 int snotify[MAX_LAN_ADDR];
855 LIST_HEAD(httplisthead, upnphttp) upnphttphead;
856 struct upnphttp * e = 0;
857 struct upnphttp * next;
858 fd_set readset; /* for select() */
859 fd_set writeset;
860 struct timeval timeout, timeofday, lastnotifytime = {0, 0};
861 time_t lastupdatetime = 0;
862 int max_fd = -1;
863 int last_changecnt = 0;
864 pid_t scanner_pid = 0;
865 pthread_t inotify_thread = 0;
866 struct media_dir_s *media_path, *last_path;
867 struct album_art_name_s *art_names, *last_name;
868 #ifdef TIVO_SUPPORT
869 unsigned short int beacon_interval = 5;
870 int sbeacon = -1;
871 struct sockaddr_in tivo_bcast;
872 struct timeval lastbeacontime = {0, 0};
873 #endif
875 for (i = 0; i < L_MAX; i++)
876 log_level[i] = E_WARN;
877 #ifdef ENABLE_NLS
878 setlocale(LC_MESSAGES, "");
879 setlocale(LC_CTYPE, "en_US.utf8");
880 DPRINTF(E_DEBUG, L_GENERAL, "Using locale dir %s\n", bindtextdomain("minidlna", getenv("TEXTDOMAINDIR")));
881 textdomain("minidlna");
882 #endif
884 if (init(argc, argv) != 0)
885 return 1;
887 #ifdef READYNAS
888 DPRINTF(E_WARN, L_GENERAL, "Starting " SERVER_NAME " version " MINIDLNA_VERSION ".\n");
889 unlink("/ramfs/.upnp-av_scan");
890 #else
891 DPRINTF(E_WARN, L_GENERAL, "Starting " SERVER_NAME " version " MINIDLNA_VERSION " [SQLite %s].\n", sqlite3_libversion());
892 unlink("/var/notice/dlna");
893 if( !sqlite3_threadsafe() )
895 DPRINTF(E_ERROR, L_GENERAL, "SQLite library is not threadsafe! "
896 "Scanning must be finished before file serving can begin, "
897 "and inotify will be disabled.\n");
899 if( sqlite3_libversion_number() < 3005001 )
901 DPRINTF(E_WARN, L_GENERAL, "SQLite library is old. Please use version 3.5.1 or newer.\n");
903 #endif
904 LIST_INIT(&upnphttphead);
906 if( open_db() == 0 )
908 updateID = sql_get_int_field(db, "SELECT UPDATE_ID from SETTINGS");
910 i = db_upgrade(db);
911 if( i != 0 )
913 if( i < 0 )
915 DPRINTF(E_WARN, L_GENERAL, "Creating new database...\n");
917 else
919 DPRINTF(E_WARN, L_GENERAL, "Database version mismatch; need to recreate...\n");
921 sqlite3_close(db);
922 char *cmd;
923 i = asprintf(&cmd, "rm -rf %s/files.db %s/art_cache", db_path, db_path);
924 if( i > 0 )
925 i = system(cmd);
926 else
927 cmd = NULL;
928 if( i != 0 )
930 DPRINTF(E_WARN, L_GENERAL, "Failed to clean old file cache.\n");
932 free(cmd);
933 open_db();
934 if( CreateDatabase() != 0 )
936 DPRINTF(E_FATAL, L_GENERAL, "ERROR: Failed to create sqlite database! Exiting...\n");
938 #if USE_FORK
939 scanning = 1;
940 sqlite3_close(db);
941 scanner_pid = fork();
942 open_db();
943 if( !scanner_pid ) // child (scanner) process
945 start_scanner();
946 sqlite3_close(db);
947 media_path = media_dirs;
948 art_names = album_art_names;
949 while( media_path )
951 free(media_path->path);
952 last_path = media_path;
953 media_path = media_path->next;
954 free(last_path);
956 while( art_names )
958 free(art_names->name);
959 last_name = art_names;
960 art_names = art_names->next;
961 free(last_name);
963 freeoptions();
964 exit(EXIT_SUCCESS);
966 #else
967 start_scanner();
968 #endif
970 signal(SIGCHLD, SIG_IGN);
971 if( sqlite3_threadsafe() && sqlite3_libversion_number() >= 3005001 &&
972 GETFLAG(INOTIFY_MASK) && pthread_create(&inotify_thread, NULL, start_inotify, NULL) )
974 DPRINTF(E_FATAL, L_GENERAL, "ERROR: pthread_create() failed for start_inotify.\n");
977 sudp = OpenAndConfSSDPReceiveSocket(n_lan_addr, lan_addr);
978 if(sudp < 0)
980 DPRINTF(E_INFO, L_GENERAL, "Failed to open socket for receiving SSDP. Trying to use MiniSSDPd\n");
981 if(SubmitServicesToMiniSSDPD(lan_addr[0].str, runtime_vars.port) < 0) {
982 DPRINTF(E_FATAL, L_GENERAL, "Failed to connect to MiniSSDPd. EXITING");
983 return 1;
986 /* open socket for HTTP connections. Listen on the 1st LAN address */
987 shttpl = OpenAndConfHTTPSocket((runtime_vars.port > 0) ? runtime_vars.port : 0);
988 if(shttpl < 0)
990 DPRINTF(E_FATAL, L_GENERAL, "Failed to open socket for HTTP. EXITING\n");
992 if(runtime_vars.port <= 0)
994 struct sockaddr_in sockinfo;
995 socklen_t len = sizeof(struct sockaddr_in);
996 if (getsockname(shttpl, (struct sockaddr *)&sockinfo, &len) < 0)
998 DPRINTF(E_FATAL, L_GENERAL, "getsockname(): %s. EXITING\n", strerror(errno));
1000 runtime_vars.port = ntohs(sockinfo.sin_port);
1002 DPRINTF(E_WARN, L_GENERAL, "HTTP listening on port %d\n", runtime_vars.port);
1004 /* open socket for sending notifications */
1005 if(OpenAndConfSSDPNotifySockets(snotify) < 0)
1007 DPRINTF(E_FATAL, L_GENERAL, "Failed to open sockets for sending SSDP notify "
1008 "messages. EXITING\n");
1011 #ifdef TIVO_SUPPORT
1012 if( GETFLAG(TIVO_MASK) )
1014 DPRINTF(E_WARN, L_GENERAL, "TiVo support is enabled.\n");
1015 /* Add TiVo-specific randomize function to sqlite */
1016 if( sqlite3_create_function(db, "tivorandom", 1, SQLITE_UTF8, NULL, &TiVoRandomSeedFunc, NULL, NULL) != SQLITE_OK )
1018 DPRINTF(E_ERROR, L_TIVO, "ERROR: Failed to add sqlite randomize function for TiVo!\n");
1020 /* open socket for sending Tivo notifications */
1021 sbeacon = OpenAndConfTivoBeaconSocket();
1022 if(sbeacon < 0)
1024 DPRINTF(E_FATAL, L_GENERAL, "Failed to open sockets for sending Tivo beacon notify "
1025 "messages. EXITING\n");
1027 tivo_bcast.sin_family = AF_INET;
1028 tivo_bcast.sin_addr.s_addr = htonl(getBcastAddress());
1029 tivo_bcast.sin_port = htons(2190);
1031 else
1033 sbeacon = -1;
1035 #endif
1037 SendSSDPGoodbye(snotify, n_lan_addr);
1039 /* main loop */
1040 while(!quitting)
1042 /* Check if we need to send SSDP NOTIFY messages and do it if
1043 * needed */
1044 if(gettimeofday(&timeofday, 0) < 0)
1046 DPRINTF(E_ERROR, L_GENERAL, "gettimeofday(): %s\n", strerror(errno));
1047 timeout.tv_sec = runtime_vars.notify_interval;
1048 timeout.tv_usec = 0;
1050 else
1052 /* the comparaison is not very precise but who cares ? */
1053 if(timeofday.tv_sec >= (lastnotifytime.tv_sec + runtime_vars.notify_interval))
1055 SendSSDPNotifies2(snotify,
1056 (unsigned short)runtime_vars.port,
1057 (runtime_vars.notify_interval << 1)+10);
1058 memcpy(&lastnotifytime, &timeofday, sizeof(struct timeval));
1059 timeout.tv_sec = runtime_vars.notify_interval;
1060 timeout.tv_usec = 0;
1062 else
1064 timeout.tv_sec = lastnotifytime.tv_sec + runtime_vars.notify_interval
1065 - timeofday.tv_sec;
1066 if(timeofday.tv_usec > lastnotifytime.tv_usec)
1068 timeout.tv_usec = 1000000 + lastnotifytime.tv_usec
1069 - timeofday.tv_usec;
1070 timeout.tv_sec--;
1072 else
1074 timeout.tv_usec = lastnotifytime.tv_usec - timeofday.tv_usec;
1077 #ifdef TIVO_SUPPORT
1078 if( GETFLAG(TIVO_MASK) )
1080 if(timeofday.tv_sec >= (lastbeacontime.tv_sec + beacon_interval))
1082 sendBeaconMessage(sbeacon, &tivo_bcast, sizeof(struct sockaddr_in), 1);
1083 memcpy(&lastbeacontime, &timeofday, sizeof(struct timeval));
1084 if( timeout.tv_sec > beacon_interval )
1086 timeout.tv_sec = beacon_interval;
1087 timeout.tv_usec = 0;
1089 /* Beacons should be sent every 5 seconds or so for the first minute,
1090 * then every minute or so thereafter. */
1091 if( beacon_interval == 5 && (timeofday.tv_sec - startup_time) > 60 )
1093 beacon_interval = 60;
1096 else if( timeout.tv_sec > (lastbeacontime.tv_sec + beacon_interval + 1 - timeofday.tv_sec) )
1098 timeout.tv_sec = lastbeacontime.tv_sec + beacon_interval - timeofday.tv_sec;
1101 #endif
1104 if( scanning )
1106 if( !scanner_pid || kill(scanner_pid, 0) )
1108 scanning = 0;
1109 updateID++;
1113 /* select open sockets (SSDP, HTTP listen, and all HTTP soap sockets) */
1114 FD_ZERO(&readset);
1116 if (sudp >= 0)
1118 FD_SET(sudp, &readset);
1119 max_fd = MAX(max_fd, sudp);
1122 if (shttpl >= 0)
1124 FD_SET(shttpl, &readset);
1125 max_fd = MAX(max_fd, shttpl);
1127 #ifdef TIVO_SUPPORT
1128 if (sbeacon >= 0)
1130 FD_SET(sbeacon, &readset);
1131 max_fd = MAX(max_fd, sbeacon);
1133 #endif
1134 i = 0; /* active HTTP connections count */
1135 for(e = upnphttphead.lh_first; e != NULL; e = e->entries.le_next)
1137 if((e->socket >= 0) && (e->state <= 2))
1139 FD_SET(e->socket, &readset);
1140 max_fd = MAX(max_fd, e->socket);
1141 i++;
1144 #ifdef DEBUG
1145 /* for debug */
1146 if(i > 1)
1148 DPRINTF(E_DEBUG, L_GENERAL, "%d active incoming HTTP connections\n", i);
1150 #endif
1151 FD_ZERO(&writeset);
1152 upnpevents_selectfds(&readset, &writeset, &max_fd);
1154 if(select(max_fd+1, &readset, &writeset, 0, &timeout) < 0)
1156 if(quitting) goto shutdown;
1157 DPRINTF(E_ERROR, L_GENERAL, "select(all): %s\n", strerror(errno));
1158 DPRINTF(E_FATAL, L_GENERAL, "Failed to select open sockets. EXITING\n");
1160 upnpevents_processfds(&readset, &writeset);
1161 /* process SSDP packets */
1162 if(sudp >= 0 && FD_ISSET(sudp, &readset))
1164 /*DPRINTF(E_DEBUG, L_GENERAL, "Received UDP Packet\n");*/
1165 ProcessSSDPRequest(sudp, (unsigned short)runtime_vars.port);
1167 #ifdef TIVO_SUPPORT
1168 if(sbeacon >= 0 && FD_ISSET(sbeacon, &readset))
1170 /*DPRINTF(E_DEBUG, L_GENERAL, "Received UDP Packet\n");*/
1171 ProcessTiVoBeacon(sbeacon);
1173 #endif
1174 /* increment SystemUpdateID if the content database has changed,
1175 * and if there is an active HTTP connection, at most once every 2 seconds */
1176 if( i && (timeofday.tv_sec >= (lastupdatetime + 2)) )
1178 if( scanning || sqlite3_total_changes(db) != last_changecnt )
1180 updateID++;
1181 last_changecnt = sqlite3_total_changes(db);
1182 upnp_event_var_change_notify(EContentDirectory);
1183 lastupdatetime = timeofday.tv_sec;
1186 /* process active HTTP connections */
1187 for(e = upnphttphead.lh_first; e != NULL; e = e->entries.le_next)
1189 if( (e->socket >= 0) && (e->state <= 2)
1190 &&(FD_ISSET(e->socket, &readset)) )
1192 Process_upnphttp(e);
1195 /* process incoming HTTP connections */
1196 if(shttpl >= 0 && FD_ISSET(shttpl, &readset))
1198 int shttp;
1199 socklen_t clientnamelen;
1200 struct sockaddr_in clientname;
1201 clientnamelen = sizeof(struct sockaddr_in);
1202 shttp = accept(shttpl, (struct sockaddr *)&clientname, &clientnamelen);
1203 if(shttp<0)
1205 DPRINTF(E_ERROR, L_GENERAL, "accept(http): %s\n", strerror(errno));
1207 else
1209 struct upnphttp * tmp = 0;
1210 DPRINTF(E_DEBUG, L_GENERAL, "HTTP connection from %s:%d\n",
1211 inet_ntoa(clientname.sin_addr),
1212 ntohs(clientname.sin_port) );
1213 /*if (fcntl(shttp, F_SETFL, O_NONBLOCK) < 0) {
1214 DPRINTF(E_ERROR, L_GENERAL, "fcntl F_SETFL, O_NONBLOCK\n");
1216 /* Create a new upnphttp object and add it to
1217 * the active upnphttp object list */
1218 tmp = New_upnphttp(shttp);
1219 if(tmp)
1221 tmp->clientaddr = clientname.sin_addr;
1222 LIST_INSERT_HEAD(&upnphttphead, tmp, entries);
1224 else
1226 DPRINTF(E_ERROR, L_GENERAL, "New_upnphttp() failed\n");
1227 close(shttp);
1231 /* delete finished HTTP connections */
1232 for(e = upnphttphead.lh_first; e != NULL; )
1234 next = e->entries.le_next;
1235 if(e->state >= 100)
1237 LIST_REMOVE(e, entries);
1238 Delete_upnphttp(e);
1240 e = next;
1244 shutdown:
1245 /* kill the scanner */
1246 if( scanning && scanner_pid )
1248 kill(scanner_pid, 9);
1250 /* close out open sockets */
1251 while(upnphttphead.lh_first != NULL)
1253 e = upnphttphead.lh_first;
1254 LIST_REMOVE(e, entries);
1255 Delete_upnphttp(e);
1258 if (sudp >= 0) close(sudp);
1259 if (shttpl >= 0) close(shttpl);
1260 #ifdef TIVO_SUPPORT
1261 if (sbeacon >= 0) close(sbeacon);
1262 #endif
1264 if(SendSSDPGoodbye(snotify, n_lan_addr) < 0)
1266 DPRINTF(E_ERROR, L_GENERAL, "Failed to broadcast good-bye notifications\n");
1268 for(i=0; i<n_lan_addr; i++)
1269 close(snotify[i]);
1271 if( inotify_thread )
1272 pthread_join(inotify_thread, NULL);
1274 sql_exec(db, "UPDATE SETTINGS set UPDATE_ID = %u", updateID);
1275 sqlite3_close(db);
1277 upnpevents_removeSubscribers();
1279 media_path = media_dirs;
1280 art_names = album_art_names;
1281 while( media_path )
1283 free(media_path->path);
1284 last_path = media_path;
1285 media_path = media_path->next;
1286 free(last_path);
1288 while( art_names )
1290 free(art_names->name);
1291 last_name = art_names;
1292 art_names = art_names->next;
1293 free(last_name);
1296 if(unlink(pidfilename) < 0)
1298 DPRINTF(E_ERROR, L_GENERAL, "Failed to remove pidfile %s: %s\n", pidfilename, strerror(errno));
1301 freeoptions();
1303 exit(EXIT_SUCCESS);