1/* MiniDLNA project
2 *
3 * http://sourceforge.net/projects/minidlna/
4 *
5 * MiniDLNA media server
6 * Copyright (C) 2008-2009  Justin Maggard
7 *
8 * This file is part of MiniDLNA.
9 *
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.
13 *
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.
18 *
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/>.
21 *
22 * Portions of the code from the MiniUPnP project:
23 *
24 * Copyright (c) 2006-2007, Thomas Bernard
25 * All rights reserved.
26 *
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.
36 *
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.
48 */
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>
67
68#include "config.h"
69
70#ifdef ENABLE_NLS
71#include <libintl.h>
72#endif
73
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
94
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
99
100/* OpenAndConfHTTPSocket() :
101 * setup the socket used to handle incoming HTTP connections. */
102static int
103OpenAndConfHTTPSocket(unsigned short port)
104{
105	int s;
106	int i = 1;
107	struct sockaddr_in listenname;
108
109	/* Initialize client type cache */
110	memset(&clients, 0, sizeof(struct client_cache_s));
111
112	if( (s = socket(PF_INET, SOCK_STREAM, 0)) < 0)
113	{
114		DPRINTF(E_ERROR, L_GENERAL, "socket(http): %s\n", strerror(errno));
115		return -1;
116	}
117
118	if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)) < 0)
119	{
120		DPRINTF(E_WARN, L_GENERAL, "setsockopt(http, SO_REUSEADDR): %s\n", strerror(errno));
121	}
122
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);
127
128	if(bind(s, (struct sockaddr *)&listenname, sizeof(struct sockaddr_in)) < 0)
129	{
130		DPRINTF(E_ERROR, L_GENERAL, "bind(http): %s\n", strerror(errno));
131		close(s);
132		return -1;
133	}
134
135	if(listen(s, 6) < 0)
136	{
137		DPRINTF(E_ERROR, L_GENERAL, "listen(http): %s\n", strerror(errno));
138		close(s);
139		return -1;
140	}
141
142	return s;
143}
144
145/* Handler for the SIGTERM signal (kill)
146 * SIGINT is also handled */
147static void
148sigterm(int sig)
149{
150	/*int save_errno = errno;*/
151	signal(sig, SIG_IGN);	/* Ignore this signal while we are quitting */
152
153	DPRINTF(E_WARN, L_GENERAL, "received signal %d, good-bye\n", sig);
154
155	quitting = 1;
156	/*errno = save_errno;*/
157}
158
159/* record the startup time, for returning uptime */
160static void
161set_startup_time(void)
162{
163	startup_time = time(NULL);
164}
165
166/* parselanaddr()
167 * parse address with mask
168 * ex: 192.168.1.1/24
169 * return value :
170 *    0 : ok
171 *   -1 : error */
172static int
173parselanaddr(struct lan_addr_s * lan_addr, const char * str)
174{
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 == '/')
183	{
184		nbits = atoi(++p);
185		while(*p && !isspace(*p))
186			p++;
187	}
188	if(n>15)
189	{
190		DPRINTF(E_OFF, L_GENERAL, "Error parsing address/mask: %s\n", str);
191		return -1;
192	}
193	memcpy(lan_addr->str, str, n);
194	lan_addr->str[n] = '\0';
195	if(!inet_aton(lan_addr->str, &lan_addr->addr))
196	{
197		DPRINTF(E_OFF, L_GENERAL, "Error parsing address: %s\n", str);
198		return -1;
199	}
200	lan_addr->mask.s_addr = htonl(nbits ? (0xffffffff << (32 - nbits)) : 0);
201	return 0;
202}
203
204static void
205getfriendlyname(char * buf, int len)
206{
207	char * dot = NULL;
208	char * hn = calloc(1, 256);
209	int off;
210
211	if( gethostname(hn, 256) == 0 )
212	{
213		strncpyt(buf, hn, len);
214		dot = strchr(buf, '.');
215		if( dot )
216			*dot = '\0';
217	}
218	else
219	{
220		strcpy(buf, "Unknown");
221	}
222	free(hn);
223
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 )
234	{
235		key = strsep(&val, ": \t");
236		val = trim(val);
237		if( strcmp(key, "model") == 0 )
238		{
239			snprintf(buf+off, len-off, "%s", val);
240			key = strchr(val, ' ');
241			if( key )
242			{
243				strncpyt(modelnumber, key+1, MODELNUMBER_MAX_LEN);
244				*key = '\0';
245			}
246			snprintf(modelname, MODELNAME_MAX_LEN,
247				"Windows Media Connect compatible (%s)", val);
248		}
249		else if( strcmp(key, "serial") == 0 )
250		{
251			strncpyt(serialnumber, val, SERIALNUMBER_MAX_LEN);
252			if( serialnumber[0] == '\0' )
253			{
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");
259			}
260			break;
261		}
262	}
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 )
291	{
292		struct passwd * pwent;
293		pwent = getpwuid(getuid());
294		if( pwent )
295			logname = pwent->pw_name;
296	}
297#endif
298/* Modify by Foxconn Antony start 02/17/2012 set the properly friendly name */
299//	snprintf(buf+off, len-off, "%s", logname?logname:"Unknown");
300	snprintf(buf+off, len-off, "%s", logname?logname:"ReadyShare");
301/* Modify by Foxconn Antony end 02/17/2012 */
302#endif
303}
304
305static int
306open_db(void)
307{
308	char path[PATH_MAX];
309	int new_db = 0;
310
311	snprintf(path, sizeof(path), "%s/files.db", db_path);
312	if( access(path, F_OK) != 0 )
313	{
314		new_db = 1;
315		make_dir(db_path, S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO);
316	}
317	if( sqlite3_open(path, &db) != SQLITE_OK )
318	{
319		DPRINTF(E_FATAL, L_GENERAL, "ERROR: Failed to open sqlite database!  Exiting...\n");
320	}
321	sqlite3_busy_timeout(db, 5000);
322	sql_exec(db, "pragma page_size = 4096");
323	sql_exec(db, "pragma journal_mode = OFF");
324	sql_exec(db, "pragma synchronous = OFF;");
325	sql_exec(db, "pragma default_cache_size = 8192;");
326	return new_db;
327}
328
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 */
337static int
338init(int argc, char * * argv)
339{
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;
356
357	/* first check if "-f" option is used */
358	for(i=2; i<argc; i++)
359	{
360		if(0 == strcmp(argv[i-1], "-f"))
361		{
362			optionsfile = argv[i];
363			options_flag = 1;
364			break;
365		}
366	}
367
368	/* set up uuid based on mac address */
369	if( getsyshwaddr(mac_str, sizeof(mac_str)) < 0 )
370	{
371		DPRINTF(E_OFF, L_GENERAL, "No MAC address found.  Falling back to generic UUID.\n");
372		strcpy(mac_str, "554e4b4e4f57");
373	}
374	strcpy(uuidvalue+5, "4d696e69-444c-164e-9d41-");
375	strncat(uuidvalue, mac_str, 12);
376
377	getfriendlyname(friendly_name, FRIENDLYNAME_MAX_LEN);
378
379	runtime_vars.port = -1;
380	runtime_vars.notify_interval = 895;	/* seconds between SSDP announces */
381	runtime_vars.root_container = NULL;
382
383	/* read options file first since
384	 * command line arguments have final say */
385	if(readoptionsfile(optionsfile) < 0)
386	{
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);
390	}
391	else
392	{
393		for(i=0; i<num_options; i++)
394		{
395			switch(ary_options[i].id)
396			{
397			case UPNPIFNAME:
398				for( string = ary_options[i].value; (word = strtok(string, ",")); string = NULL )
399				{
400					if(n_lan_addr < MAX_LAN_ADDR)
401					{
402						if(getifaddr(word, ip_addr, sizeof(ip_addr)) >= 0)
403						{
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++;
407						}
408					}
409					else
410					{
411						DPRINTF(E_ERROR, L_GENERAL, "Too many listening ips (max: %d), ignoring %s\n",
412				    		    MAX_LAN_ADDR, word);
413					}
414				}
415				break;
416			case UPNPLISTENING_IP:
417				if(n_lan_addr < MAX_LAN_ADDR)
418				{
419					if(parselanaddr(&lan_addr[n_lan_addr],
420					             ary_options[i].value) == 0)
421						n_lan_addr++;
422				}
423				else
424				{
425					DPRINTF(E_ERROR, L_GENERAL, "Too many listening ips (max: %d), ignoring %s\n",
426			    		    MAX_LAN_ADDR, ary_options[i].value);
427				}
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] )
454				{
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 )
473					{
474						DPRINTF(E_ERROR, L_GENERAL, "Media directory \"%s\" not accessible! [%s]\n",
475						        path, strerror(errno));
476						break;
477					}
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 )
482					{
483						media_dirs = this_dir;
484					}
485					else
486					{
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;
491					}
492					break;
493				default:
494					DPRINTF(E_ERROR, L_GENERAL, "Media directory entry not understood! [%s]\n",
495					        ary_options[i].value);
496					break;
497				}
498				break;
499			case UPNPALBUMART_NAMES:
500				for( string = ary_options[i].value; (word = strtok(string, "/")); string = NULL )
501				{
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] == '*' )
505					{
506						word[len-1] = '\0';
507						this_name->wildcard = 1;
508					}
509					this_name->name = strdup(word);
510					if( !album_art_names )
511					{
512						album_art_names = this_name;
513					}
514					else
515					{
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;
520					}
521				}
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 )
529				{
530					DPRINTF(E_FATAL, L_GENERAL, "Database path not accessible! [%s]\n", path);
531					break;
532				}
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 )
541				{
542					DPRINTF(E_FATAL, L_GENERAL, "Log path not accessible! [%s]\n", path);
543					break;
544				}
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] )
564				{
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;
588				}
589				break;
590			case UPNPMINISSDPDSOCKET:
591				minissdpdsocketpath = ary_options[i].value;
592				break;
593			default:
594				DPRINTF(E_DEBUG, L_GENERAL, "Unknown option in file %s\n",
595				        optionsfile);
596			}
597		}
598	}
599	if( log_path[0] == '\0' )
600	{
601		if( db_path[0] == '\0' )
602			strncpyt(log_path, "/tmp/log", PATH_MAX);
603		else
604			strncpyt(log_path, db_path, PATH_MAX);
605	}
606	if( db_path[0] == '\0' )
607		strncpyt(db_path, DEFAULT_DB_PATH, PATH_MAX);
608
609	/* command line arguments processing */
610	for(i=1; i<argc; i++)
611	{
612		if(argv[i][0]!='-')
613		{
614			DPRINTF(E_ERROR, L_GENERAL, "Unknown option: %s\n", argv[i]);
615		}
616		else if(strcmp(argv[i], "--help")==0)
617		{
618			runtime_vars.port = 0;
619			break;
620		}
621		else switch(argv[i][1])
622		{
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)
669			{
670				int address_already_there = 0;
671				int j;
672				i++;
673				for(j=0; j<n_lan_addr; j++)
674				{
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;
679				}
680				if(address_already_there)
681					break;
682				if(n_lan_addr < MAX_LAN_ADDR)
683				{
684					if(parselanaddr(&lan_addr[n_lan_addr], argv[i]) == 0)
685						n_lan_addr++;
686				}
687				else
688				{
689					DPRINTF(E_ERROR, L_GENERAL, "Too many listening ips (max: %d), ignoring %s\n",
690				    	    MAX_LAN_ADDR, argv[i]);
691				}
692			}
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)
698			{
699				int address_already_there = 0;
700				int j;
701				i++;
702				if( getifaddr(argv[i], ip_addr, sizeof(ip_addr)) < 0 )
703				{
704					DPRINTF(E_FATAL, L_GENERAL, "Required network interface '%s' not found.\n",
705						argv[i]);
706				}
707				for(j=0; j<n_lan_addr; j++)
708				{
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;
713				}
714				if(address_already_there)
715					break;
716				if(n_lan_addr < MAX_LAN_ADDR)
717				{
718					if(parselanaddr(&lan_addr[n_lan_addr], ip_addr) == 0)
719						n_lan_addr++;
720				}
721				else
722				{
723					DPRINTF(E_ERROR, L_GENERAL, "Too many listening ips (max: %d), ignoring %s\n",
724				    	    MAX_LAN_ADDR, argv[i]);
725				}
726			}
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 = 0; // 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]);
747		}
748	}
749	/* If no IP was specified, try to detect one */
750
751	if( n_lan_addr < 1 )
752	{
753
754		if( (getsysaddrs() <= 0 ) &&
755		    (getifaddr("eth0", ip_addr, sizeof(ip_addr)) < 0) &&
756		    (getifaddr("eth1", ip_addr, sizeof(ip_addr)) < 0) )
757		{
758			DPRINTF(E_OFF, L_GENERAL, "No IP address automatically detected!\n");
759		}
760		if( *ip_addr && parselanaddr(&lan_addr[n_lan_addr], ip_addr) == 0 )
761		{
762			n_lan_addr++;
763		}
764	}
765
766	if( (n_lan_addr==0) || (runtime_vars.port<=0) )
767	{
768		DPRINTF(E_ERROR, L_GENERAL, "Usage:\n\t"
769		        "%s [-d] [-v] [-f config_file]\n"
770			"\t\t[-a listening_ip] [-p port]\n"
771			/*"[-l logfile] " not functionnal */
772			"\t\t[-s serial] [-m model_number] \n"
773			"\t\t[-t notify_interval] [-P pid_filename]\n"
774			"\t\t[-w url] [-R] [-V] [-h]\n"
775		        "\nNotes:\n\tNotify interval is in seconds. Default is 895 seconds.\n"
776			"\tDefault pid file is %s.\n"
777			"\tWith -d minidlna will run in debug mode (not daemonize).\n"
778			"\t-w sets the presentation url. Default is http address on port 80\n"
779			"\t-h displays this text\n"
780			"\t-R forces a full rescan\n"
781			"\t-L do note create playlists\n"
782			"\t-V print the version number\n",
783		        argv[0], pidfilename);
784		return 1;
785	}
786
787	if( verbose_flag )
788	{
789		strcpy(log_str+65, "debug");
790		log_level = log_str;
791	}
792	else if( !log_level )
793	{
794		log_level = log_str;
795	}
796	if(debug_flag)
797	{
798		pid = getpid();
799		log_init(NULL, log_level);
800	}
801	else
802	{
803		pid = daemonize();
804		#ifdef READYNAS
805		log_init("/var/log/upnp-av.log", log_level);
806		#else
807		if( access(db_path, F_OK) != 0 )
808			make_dir(db_path, S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO);
809		sprintf(buf, "%s/minidlna.log", log_path);
810		log_init(buf, log_level);
811		#endif
812	}
813
814	if(checkforrunning(pidfilename) < 0)
815	{
816		DPRINTF(E_ERROR, L_GENERAL, "MiniDLNA is already running. EXITING.\n");
817		return 1;
818	}
819
820	set_startup_time();
821
822	/* presentation url */
823	if(presurl)
824		strncpyt(presentationurl, presurl, PRESENTATIONURL_MAX_LEN);
825	else
826		strcpy(presentationurl, "/");
827
828	/* set signal handler */
829	memset(&sa, 0, sizeof(struct sigaction));
830	sa.sa_handler = sigterm;
831	if (sigaction(SIGTERM, &sa, NULL))
832	{
833		DPRINTF(E_FATAL, L_GENERAL, "Failed to set SIGTERM handler. EXITING.\n");
834	}
835	if (sigaction(SIGINT, &sa, NULL))
836	{
837		DPRINTF(E_FATAL, L_GENERAL, "Failed to set SIGINT handler. EXITING.\n");
838	}
839
840	if(signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
841		DPRINTF(E_FATAL, L_GENERAL, "Failed to ignore SIGPIPE signals. EXITING.\n");
842	}
843
844	writepidfile(pidfilename, pid);
845
846	return 0;
847}
848
849/* === main === */
850/* process HTTP or SSDP requests */
851int
852main(int argc, char * * argv)
853{
854	int i;
855	int sudp = -1, shttpl = -1;
856	int snotify[MAX_LAN_ADDR];
857	LIST_HEAD(httplisthead, upnphttp) upnphttphead;
858	struct upnphttp * e = 0;
859	struct upnphttp * next;
860	fd_set readset;	/* for select() */
861	fd_set writeset;
862	struct timeval timeout, timeofday, lastnotifytime = {0, 0};
863	time_t lastupdatetime = 0;
864	int max_fd = -1;
865	int last_changecnt = 0;
866	pid_t scanner_pid = 0;
867	pthread_t inotify_thread = 0;
868	struct media_dir_s *media_path, *last_path;
869	struct album_art_name_s *art_names, *last_name;
870#ifdef TIVO_SUPPORT
871	unsigned short int beacon_interval = 5;
872	int sbeacon = -1;
873	struct sockaddr_in tivo_bcast;
874	struct timeval lastbeacontime = {0, 0};
875#endif
876
877	for (i = 0; i < L_MAX; i++)
878		log_level[i] = E_WARN;
879#ifdef ENABLE_NLS
880	setlocale(LC_MESSAGES, "");
881	setlocale(LC_CTYPE, "en_US.utf8");
882	DPRINTF(E_DEBUG, L_GENERAL, "Using locale dir %s\n", bindtextdomain("minidlna", getenv("TEXTDOMAINDIR")));
883	textdomain("minidlna");
884#endif
885
886	if (init(argc, argv) != 0)
887		return 1;
888
889#ifdef READYNAS
890	DPRINTF(E_WARN, L_GENERAL, "Starting " SERVER_NAME " version " MINIDLNA_VERSION ".\n");
891	unlink("/ramfs/.upnp-av_scan");
892#else
893	DPRINTF(E_WARN, L_GENERAL, "Starting " SERVER_NAME " version " MINIDLNA_VERSION " [SQLite %s].\n", sqlite3_libversion());
894	if( !sqlite3_threadsafe() )
895	{
896		DPRINTF(E_ERROR, L_GENERAL, "SQLite library is not threadsafe!  "
897		                            "Scanning must be finished before file serving can begin, "
898		                            "and inotify will be disabled.\n");
899	}
900	if( sqlite3_libversion_number() < 3005001 )
901	{
902		DPRINTF(E_WARN, L_GENERAL, "SQLite library is old.  Please use version 3.5.1 or newer.\n");
903	}
904#endif
905	LIST_INIT(&upnphttphead);
906
907	if( open_db() == 0 )
908	{
909		updateID = sql_get_int_field(db, "SELECT UPDATE_ID from SETTINGS");
910	}
911	i = db_upgrade(db);
912//	if( i != 0 )
913	if(1)
914	{
915		if( i < 0 )
916		{
917			DPRINTF(E_WARN, L_GENERAL, "Creating new database...\n");
918		}
919		else
920		{
921			DPRINTF(E_WARN, L_GENERAL, "Database version mismatch; need to recreate...\n");
922		}
923		sqlite3_close(db);
924		char *cmd;
925		i = asprintf(&cmd, "rm -rf %s/files.db %s/art_cache", db_path, db_path);
926		if( i > 0 )
927			i = system(cmd);
928		else
929			cmd = NULL;
930		if( i != 0 )
931		{
932			DPRINTF(E_WARN, L_GENERAL, "Failed to clean old file cache.\n");
933		}
934		free(cmd);
935		open_db();
936
937		if( CreateDatabase() != 0 )
938		{
939			DPRINTF(E_FATAL, L_GENERAL, "ERROR: Failed to create sqlite database!  Exiting...\n");
940		}
941#if USE_FORK
942		scanning = 1;
943		sqlite3_close(db);
944		scanner_pid = fork();
945		open_db();
946		if( !scanner_pid ) // child (scanner) process
947		{
948			start_scanner();
949			sqlite3_close(db);
950			media_path = media_dirs;
951			art_names = album_art_names;
952			while( media_path )
953			{
954				free(media_path->path);
955				last_path = media_path;
956				media_path = media_path->next;
957				free(last_path);
958			}
959			while( art_names )
960			{
961				free(art_names->name);
962				last_name = art_names;
963				art_names = art_names->next;
964				free(last_name);
965			}
966			freeoptions();
967printf("\n\n\n\nminidlan:scan finished\n\n\n");
968			exit(EXIT_SUCCESS);
969		}
970#else
971		start_scanner();
972#endif
973	}
974	signal(SIGCHLD, SIG_IGN);
975	if( sqlite3_threadsafe() && sqlite3_libversion_number() >= 3005001 &&
976	    GETFLAG(INOTIFY_MASK) && pthread_create(&inotify_thread, NULL, start_inotify, NULL) )
977	{
978		DPRINTF(E_FATAL, L_GENERAL, "ERROR: pthread_create() failed for start_inotify.\n");
979	}
980
981	for( i = 0; i < n_lan_addr; i++ )
982	{
983		DPRINTF(E_INFO, L_GENERAL, "Enabled interface %s/%s\n",
984		        lan_addr[i].str, inet_ntoa(lan_addr[i].mask));
985
986	}
987
988	sudp = OpenAndConfSSDPReceiveSocket(n_lan_addr, lan_addr);
989	if(sudp < 0)
990	{
991		DPRINTF(E_INFO, L_GENERAL, "Failed to open socket for receiving SSDP. Trying to use MiniSSDPd\n");
992		if(SubmitServicesToMiniSSDPD(lan_addr[0].str, runtime_vars.port) < 0) {
993			DPRINTF(E_FATAL, L_GENERAL, "Failed to connect to MiniSSDPd. EXITING");
994			return 1;
995		}
996	}
997	/* open socket for HTTP connections. Listen on the 1st LAN address */
998	shttpl = OpenAndConfHTTPSocket(runtime_vars.port);
999	if(shttpl < 0)
1000	{
1001		DPRINTF(E_FATAL, L_GENERAL, "Failed to open socket for HTTP. EXITING\n");
1002	}
1003	DPRINTF(E_WARN, L_GENERAL, "HTTP listening on port %d\n", runtime_vars.port);
1004
1005	/* open socket for sending notifications */
1006	if(OpenAndConfSSDPNotifySockets(snotify) < 0)
1007	{
1008		DPRINTF(E_FATAL, L_GENERAL, "Failed to open sockets for sending SSDP notify "
1009	                "messages. EXITING\n");
1010	}
1011
1012#ifdef TIVO_SUPPORT
1013	if( GETFLAG(TIVO_MASK) )
1014	{
1015		DPRINTF(E_WARN, L_GENERAL, "TiVo support is enabled.\n");
1016		/* Add TiVo-specific randomize function to sqlite */
1017		if( sqlite3_create_function(db, "tivorandom", 1, SQLITE_UTF8, NULL, &TiVoRandomSeedFunc, NULL, NULL) != SQLITE_OK )
1018		{
1019			DPRINTF(E_ERROR, L_TIVO, "ERROR: Failed to add sqlite randomize function for TiVo!\n");
1020		}
1021		/* open socket for sending Tivo notifications */
1022		sbeacon = OpenAndConfTivoBeaconSocket();
1023		if(sbeacon < 0)
1024		{
1025			DPRINTF(E_FATAL, L_GENERAL, "Failed to open sockets for sending Tivo beacon notify "
1026		                "messages. EXITING\n");
1027		}
1028		tivo_bcast.sin_family = AF_INET;
1029		tivo_bcast.sin_addr.s_addr = htonl(getBcastAddress());
1030		tivo_bcast.sin_port = htons(2190);
1031	}
1032	else
1033	{
1034		sbeacon = -1;
1035	}
1036#endif
1037
1038	SendSSDPGoodbye(snotify, n_lan_addr); //Foxconn modify start, Kent Huang, 09/18/2012 @Fix minidlna TD issue
1039
1040	/* main loop */
1041	while(!quitting)
1042	{
1043		/* Check if we need to send SSDP NOTIFY messages and do it if
1044		 * needed */
1045		if(gettimeofday(&timeofday, 0) < 0)
1046		{
1047			DPRINTF(E_ERROR, L_GENERAL, "gettimeofday(): %s\n", strerror(errno));
1048			timeout.tv_sec = runtime_vars.notify_interval;
1049			timeout.tv_usec = 0;
1050		}
1051		else
1052		{
1053			/* the comparaison is not very precise but who cares ? */
1054			if(timeofday.tv_sec >= (lastnotifytime.tv_sec + runtime_vars.notify_interval))
1055			{
1056				SendSSDPNotifies2(snotify,
1057			                  (unsigned short)runtime_vars.port,
1058			                  (runtime_vars.notify_interval << 1)+10);
1059				memcpy(&lastnotifytime, &timeofday, sizeof(struct timeval));
1060				timeout.tv_sec = runtime_vars.notify_interval;
1061				timeout.tv_usec = 0;
1062			}
1063			else
1064			{
1065				timeout.tv_sec = lastnotifytime.tv_sec + runtime_vars.notify_interval
1066				                 - timeofday.tv_sec;
1067				if(timeofday.tv_usec > lastnotifytime.tv_usec)
1068				{
1069					timeout.tv_usec = 1000000 + lastnotifytime.tv_usec
1070					                  - timeofday.tv_usec;
1071					timeout.tv_sec--;
1072				}
1073				else
1074				{
1075					timeout.tv_usec = lastnotifytime.tv_usec - timeofday.tv_usec;
1076				}
1077			}
1078#ifdef TIVO_SUPPORT
1079			if( GETFLAG(TIVO_MASK) )
1080			{
1081				if(timeofday.tv_sec >= (lastbeacontime.tv_sec + beacon_interval))
1082				{
1083   					sendBeaconMessage(sbeacon, &tivo_bcast, sizeof(struct sockaddr_in), 1);
1084					memcpy(&lastbeacontime, &timeofday, sizeof(struct timeval));
1085					if( timeout.tv_sec > beacon_interval )
1086					{
1087						timeout.tv_sec = beacon_interval;
1088						timeout.tv_usec = 0;
1089					}
1090					/* Beacons should be sent every 5 seconds or so for the first minute,
1091					 * then every minute or so thereafter. */
1092					if( beacon_interval == 5 && (timeofday.tv_sec - startup_time) > 60 )
1093					{
1094						beacon_interval = 60;
1095					}
1096				}
1097				else if( timeout.tv_sec > (lastbeacontime.tv_sec + beacon_interval + 1 - timeofday.tv_sec) )
1098				{
1099					timeout.tv_sec = lastbeacontime.tv_sec + beacon_interval - timeofday.tv_sec;
1100				}
1101			}
1102#endif
1103		}
1104
1105		if( scanning )
1106		{
1107			if( !scanner_pid || kill(scanner_pid, 0) )
1108			{
1109				scanning = 0;
1110				updateID++;
1111			}
1112		}
1113
1114		/* select open sockets (SSDP, HTTP listen, and all HTTP soap sockets) */
1115		FD_ZERO(&readset);
1116
1117		if (sudp >= 0)
1118		{
1119			FD_SET(sudp, &readset);
1120			max_fd = MAX(max_fd, sudp);
1121		}
1122
1123		if (shttpl >= 0)
1124		{
1125			FD_SET(shttpl, &readset);
1126			max_fd = MAX(max_fd, shttpl);
1127		}
1128#ifdef TIVO_SUPPORT
1129		if (sbeacon >= 0)
1130		{
1131			FD_SET(sbeacon, &readset);
1132			max_fd = MAX(max_fd, sbeacon);
1133		}
1134#endif
1135		i = 0;	/* active HTTP connections count */
1136		for(e = upnphttphead.lh_first; e != NULL; e = e->entries.le_next)
1137		{
1138			if((e->socket >= 0) && (e->state <= 2))
1139			{
1140				FD_SET(e->socket, &readset);
1141				max_fd = MAX(max_fd, e->socket);
1142				i++;
1143			}
1144		}
1145#ifdef DEBUG
1146		/* for debug */
1147		if(i > 1)
1148		{
1149			DPRINTF(E_DEBUG, L_GENERAL, "%d active incoming HTTP connections\n", i);
1150		}
1151#endif
1152		FD_ZERO(&writeset);
1153		upnpevents_selectfds(&readset, &writeset, &max_fd);
1154
1155		if(select(max_fd+1, &readset, &writeset, 0, &timeout) < 0)
1156		{
1157			if(quitting) goto shutdown;
1158			DPRINTF(E_ERROR, L_GENERAL, "select(all): %s\n", strerror(errno));
1159			DPRINTF(E_FATAL, L_GENERAL, "Failed to select open sockets. EXITING\n");
1160		}
1161		upnpevents_processfds(&readset, &writeset);
1162		/* process SSDP packets */
1163		if(sudp >= 0 && FD_ISSET(sudp, &readset))
1164		{
1165			/*DPRINTF(E_DEBUG, L_GENERAL, "Received UDP Packet\n");*/
1166			ProcessSSDPRequest(sudp, (unsigned short)runtime_vars.port);
1167		}
1168#ifdef TIVO_SUPPORT
1169		if(sbeacon >= 0 && FD_ISSET(sbeacon, &readset))
1170		{
1171			/*DPRINTF(E_DEBUG, L_GENERAL, "Received UDP Packet\n");*/
1172			ProcessTiVoBeacon(sbeacon);
1173		}
1174#endif
1175		/* increment SystemUpdateID if the content database has changed,
1176		 * and if there is an active HTTP connection, at most once every 2 seconds */
1177		if( i && (timeofday.tv_sec >= (lastupdatetime + 2)) )
1178		{
1179			if( scanning || sqlite3_total_changes(db) != last_changecnt )
1180			{
1181				updateID++;
1182				last_changecnt = sqlite3_total_changes(db);
1183				upnp_event_var_change_notify(EContentDirectory);
1184				lastupdatetime = timeofday.tv_sec;
1185			}
1186		}
1187		/* process active HTTP connections */
1188		for(e = upnphttphead.lh_first; e != NULL; e = e->entries.le_next)
1189		{
1190			if(  (e->socket >= 0) && (e->state <= 2)
1191				&&(FD_ISSET(e->socket, &readset)) )
1192			{
1193				Process_upnphttp(e);
1194			}
1195		}
1196		/* process incoming HTTP connections */
1197		if(shttpl >= 0 && FD_ISSET(shttpl, &readset))
1198		{
1199			int shttp;
1200			socklen_t clientnamelen;
1201			struct sockaddr_in clientname;
1202			clientnamelen = sizeof(struct sockaddr_in);
1203 			shttp = accept(shttpl, (struct sockaddr *)&clientname, &clientnamelen);
1204			if(!is_disk_mounted())
1205			    close(shttp);
1206			else
1207			{
1208    			if(shttp<0)
1209		    	{
1210				    DPRINTF(E_ERROR, L_GENERAL, "accept(http): %s\n", strerror(errno));
1211    			}
1212		    	else
1213    			{
1214		    		struct upnphttp * tmp = 0;
1215				    DPRINTF(E_DEBUG, L_GENERAL, "HTTP connection from %s:%d\n",
1216    				inet_ntoa(clientname.sin_addr),
1217		   			ntohs(clientname.sin_port) );
1218    				/*if (fcntl(shttp, F_SETFL, O_NONBLOCK) < 0) {
1219		    			DPRINTF(E_ERROR, L_GENERAL, "fcntl F_SETFL, O_NONBLOCK\n");
1220    				}*/
1221		    		/* Create a new upnphttp object and add it to
1222    				 * the active upnphttp object list */
1223		   		tmp = New_upnphttp(shttp);
1224				  if(tmp)
1225  				{
1226	  				tmp->clientaddr = clientname.sin_addr;
1227		  			LIST_INSERT_HEAD(&upnphttphead, tmp, entries);
1228			  	}
1229				  else
1230  				{
1231	  				DPRINTF(E_ERROR, L_GENERAL, "New_upnphttp() failed\n");
1232		  			close(shttp);
1233		  		}
1234				}
1235			}
1236		}
1237		/* delete finished HTTP connections */
1238		for(e = upnphttphead.lh_first; e != NULL; )
1239		{
1240			next = e->entries.le_next;
1241			if(e->state >= 100)
1242			{
1243				LIST_REMOVE(e, entries);
1244				Delete_upnphttp(e);
1245			}
1246			e = next;
1247		}
1248	}
1249
1250shutdown:
1251	/* kill the scanner */
1252	if( scanning && scanner_pid )
1253	{
1254		kill(scanner_pid, 9);
1255	}
1256	/* close out open sockets */
1257	while(upnphttphead.lh_first != NULL)
1258	{
1259		e = upnphttphead.lh_first;
1260		LIST_REMOVE(e, entries);
1261		Delete_upnphttp(e);
1262	}
1263
1264	if (sudp >= 0) close(sudp);
1265	if (shttpl >= 0) close(shttpl);
1266	#ifdef TIVO_SUPPORT
1267	if (sbeacon >= 0) close(sbeacon);
1268	#endif
1269
1270	if(SendSSDPGoodbye(snotify, n_lan_addr) < 0)
1271	{
1272		DPRINTF(E_ERROR, L_GENERAL, "Failed to broadcast good-bye notifications\n");
1273	}
1274	for(i=0; i<n_lan_addr; i++)
1275		close(snotify[i]);
1276
1277	if( inotify_thread )
1278		pthread_join(inotify_thread, NULL);
1279
1280	sql_exec(db, "UPDATE SETTINGS set UPDATE_ID = %u", updateID);
1281	sqlite3_close(db);
1282
1283	upnpevents_removeSubscribers();
1284
1285	media_path = media_dirs;
1286	art_names = album_art_names;
1287	while( media_path )
1288	{
1289		free(media_path->path);
1290		last_path = media_path;
1291		media_path = media_path->next;
1292		free(last_path);
1293	}
1294	while( art_names )
1295	{
1296		free(art_names->name);
1297		last_name = art_names;
1298		art_names = art_names->next;
1299		free(last_name);
1300	}
1301
1302	if(unlink(pidfilename) < 0)
1303	{
1304		DPRINTF(E_ERROR, L_GENERAL, "Failed to remove pidfile %s: %s\n", pidfilename, strerror(errno));
1305	}
1306
1307	freeoptions();
1308
1309	exit(EXIT_SUCCESS);
1310}
1311
1312