comparison src/ushare.c @ 125:e413158cae13

Add ushare project files.
author naoyan@johnstown.minaminoshima.org
date Sun, 03 Oct 2010 11:35:19 +0900
parents
children 5dcaf3785ebe
comparison
equal deleted inserted replaced
124:9c7bc6c0327e 125:e413158cae13
1 /*
2 * ushare.c : GeeXboX uShare UPnP Media Server.
3 * Originally developped for the GeeXboX project.
4 * Parts of the code are originated from GMediaServer from Oskar Liljeblad.
5 * Copyright (C) 2005-2007 Benjamin Zores <ben@geexbox.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 */
21
22 #include <stdio.h>
23 #include <signal.h>
24 #include <string.h>
25 #include <stdlib.h>
26 #include <stdarg.h>
27 #include <unistd.h>
28 #include <errno.h>
29 #include <getopt.h>
30
31 #if (defined(BSD) || defined(__FreeBSD__) || defined(__APPLE__))
32 #include <sys/socket.h>
33 #include <sys/sysctl.h>
34 #include <net/if_dl.h>
35 #endif
36
37 #if (defined(__APPLE__))
38 #include <net/route.h>
39 #endif
40
41 #include <net/if.h>
42 #include <sys/ioctl.h>
43 #include <sys/types.h>
44 #include <sys/stat.h>
45 #include <stdbool.h>
46 #include <fcntl.h>
47
48 #ifdef HAVE_IFADDRS_H
49 #include <ifaddrs.h>
50 #endif
51
52 #if (defined(__unix__) || defined(unix)) && !defined(USG)
53 #include <sys/param.h>
54 #endif
55
56 #include <upnp/upnp.h>
57 #include <upnp/upnptools.h>
58
59 #if (defined(HAVE_SETLOCALE) && defined(CONFIG_NLS))
60 # include <locale.h>
61 #endif
62
63 #include "config.h"
64 #include "ushare.h"
65 #include "services.h"
66 #include "http.h"
67 #include "metadata.h"
68 #include "util_iconv.h"
69 #include "content.h"
70 #include "cfgparser.h"
71 #include "gettext.h"
72 #include "trace.h"
73 #include "buffer.h"
74 #include "ctrl_telnet.h"
75 #include "recpt1.h"
76
77 struct ushare_t *ut = NULL;
78
79 static struct ushare_t * ushare_new (void)
80 __attribute__ ((malloc));
81
82 static struct ushare_t *
83 ushare_new (void)
84 {
85 struct ushare_t *ut = (struct ushare_t *) malloc (sizeof (struct ushare_t));
86 if (!ut)
87 return NULL;
88
89 ut->name = strdup (DEFAULT_USHARE_NAME);
90 ut->interface = strdup (DEFAULT_USHARE_IFACE);
91 ut->model_name = strdup (DEFAULT_USHARE_NAME);
92 ut->contentlist = NULL;
93 ut->rb = rbinit (rb_compare, NULL);
94 ut->root_entry = NULL;
95 ut->nr_entries = 0;
96 ut->starting_id = STARTING_ENTRY_ID_DEFAULT;
97 ut->init = 0;
98 ut->dev = 0;
99 ut->udn = NULL;
100 ut->ip = NULL;
101 ut->port = 0; /* Randomly attributed by libupnp */
102 ut->telnet_port = CTRL_TELNET_PORT;
103 ut->presentation = NULL;
104 ut->use_presentation = true;
105 ut->use_telnet = true;
106 #ifdef HAVE_DLNA
107 ut->dlna_enabled = false;
108 ut->dlna = NULL;
109 ut->dlna_flags = DLNA_ORG_FLAG_STREAMING_TRANSFER_MODE |
110 DLNA_ORG_FLAG_BACKGROUND_TRANSFERT_MODE |
111 DLNA_ORG_FLAG_CONNECTION_STALL |
112 DLNA_ORG_FLAG_DLNA_V15;
113 #endif /* HAVE_DLNA */
114 ut->xbox360 = false;
115 ut->verbose = false;
116 ut->daemon = false;
117 ut->override_iconv_err = false;
118 ut->cfg_file = NULL;
119
120 pthread_mutex_init (&ut->termination_mutex, NULL);
121 pthread_cond_init (&ut->termination_cond, NULL);
122
123 return ut;
124 }
125
126 static void
127 ushare_free (struct ushare_t *ut)
128 {
129 if (!ut)
130 return;
131
132 if (ut->name)
133 free (ut->name);
134 if (ut->interface)
135 free (ut->interface);
136 if (ut->model_name)
137 free (ut->model_name);
138 if (ut->contentlist)
139 content_free (ut->contentlist);
140 if (ut->rb)
141 rbdestroy (ut->rb);
142 if (ut->root_entry)
143 upnp_entry_free (ut, ut->root_entry);
144 if (ut->udn)
145 free (ut->udn);
146 if (ut->ip)
147 free (ut->ip);
148 if (ut->presentation)
149 buffer_free (ut->presentation);
150 #ifdef HAVE_DLNA
151 if (ut->dlna_enabled)
152 {
153 if (ut->dlna)
154 dlna_uninit (ut->dlna);
155 ut->dlna = NULL;
156 }
157 #endif /* HAVE_DLNA */
158 if (ut->cfg_file)
159 free (ut->cfg_file);
160
161 pthread_cond_destroy (&ut->termination_cond);
162 pthread_mutex_destroy (&ut->termination_mutex);
163
164 free (ut);
165 }
166
167 static void
168 ushare_signal_exit (void)
169 {
170 pthread_mutex_lock (&ut->termination_mutex);
171 pthread_cond_signal (&ut->termination_cond);
172 pthread_mutex_unlock (&ut->termination_mutex);
173 }
174
175 static void
176 handle_action_request (struct Upnp_Action_Request *request)
177 {
178 struct service_t *service;
179 struct service_action_t *action;
180 char val[256];
181 uint32_t ip;
182
183 if (!request || !ut)
184 return;
185
186 if (request->ErrCode != UPNP_E_SUCCESS)
187 return;
188
189 if (strcmp (request->DevUDN + 5, ut->udn))
190 return;
191
192 ip = request->CtrlPtIPAddr.s_addr;
193 ip = ntohl (ip);
194 sprintf (val, "%d.%d.%d.%d",
195 (ip >> 24) & 0xFF, (ip >> 16) & 0xFF, (ip >> 8) & 0xFF, ip & 0xFF);
196
197 if (ut->verbose)
198 {
199 DOMString str = ixmlPrintDocument (request->ActionRequest);
200 log_verbose ("***************************************************\n");
201 log_verbose ("** New Action Request **\n");
202 log_verbose ("***************************************************\n");
203 log_verbose ("ServiceID: %s\n", request->ServiceID);
204 log_verbose ("ActionName: %s\n", request->ActionName);
205 log_verbose ("CtrlPtIP: %s\n", val);
206 log_verbose ("Action Request:\n%s\n", str);
207 ixmlFreeDOMString (str);
208 }
209
210 if (find_service_action (request, &service, &action))
211 {
212 struct action_event_t event;
213
214 event.request = request;
215 event.status = true;
216 event.service = service;
217
218 if (action->function (&event) && event.status)
219 request->ErrCode = UPNP_E_SUCCESS;
220
221 if (ut->verbose)
222 {
223 DOMString str = ixmlPrintDocument (request->ActionResult);
224 log_verbose ("Action Result:\n%s", str);
225 log_verbose ("***************************************************\n");
226 log_verbose ("\n");
227 ixmlFreeDOMString (str);
228 }
229
230 return;
231 }
232
233 if (service) /* Invalid Action name */
234 strcpy (request->ErrStr, "Unknown Service Action");
235 else /* Invalid Service name */
236 strcpy (request->ErrStr, "Unknown Service ID");
237
238 request->ActionResult = NULL;
239 request->ErrCode = UPNP_SOAP_E_INVALID_ACTION;
240 }
241
242 static int
243 device_callback_event_handler (Upnp_EventType type, void *event,
244 void *cookie __attribute__((unused)))
245 {
246 switch (type)
247 {
248 case UPNP_CONTROL_ACTION_REQUEST:
249 handle_action_request ((struct Upnp_Action_Request *) event);
250 break;
251 case UPNP_CONTROL_ACTION_COMPLETE:
252 case UPNP_EVENT_SUBSCRIPTION_REQUEST:
253 case UPNP_CONTROL_GET_VAR_REQUEST:
254 break;
255 default:
256 break;
257 }
258
259 return 0;
260 }
261
262 static int
263 finish_upnp (struct ushare_t *ut)
264 {
265 if (!ut)
266 return -1;
267
268 log_info (_("Stopping UPnP Service ...\n"));
269 UpnpUnRegisterRootDevice (ut->dev);
270 UpnpFinish ();
271
272 return UPNP_E_SUCCESS;
273 }
274
275 static int
276 init_upnp (struct ushare_t *ut)
277 {
278 char *description = NULL;
279 int res;
280 size_t len;
281
282 if (!ut || !ut->name || !ut->udn || !ut->ip)
283 return -1;
284
285 #ifdef HAVE_DLNA
286 if (ut->dlna_enabled)
287 {
288 len = 0;
289 description =
290 dlna_dms_description_get (ut->name,
291 "GeeXboX Team",
292 "http://ushare.geexbox.org/",
293 "uShare : DLNA Media Server",
294 ut->model_name,
295 "001",
296 "http://ushare.geexbox.org/",
297 "USHARE-01",
298 ut->udn,
299 "/web/ushare.html",
300 "/web/cms.xml",
301 "/web/cms_control",
302 "/web/cms_event",
303 "/web/cds.xml",
304 "/web/cds_control",
305 "/web/cds_event");
306 if (!description)
307 return -1;
308 }
309 else
310 {
311 #endif /* HAVE_DLNA */
312 len = strlen (UPNP_DESCRIPTION) + strlen (ut->name)
313 + strlen (ut->model_name) + strlen (ut->udn) + 1;
314 description = (char *) malloc (len * sizeof (char));
315 memset (description, 0, len);
316 sprintf (description, UPNP_DESCRIPTION, ut->name, ut->model_name, ut->udn);
317 #ifdef HAVE_DLNA
318 }
319 #endif /* HAVE_DLNA */
320
321 log_info (_("Initializing UPnP subsystem ...\n"));
322 res = UpnpInit (ut->ip, ut->port);
323 if (res != UPNP_E_SUCCESS)
324 {
325 log_error (_("Cannot initialize UPnP subsystem\n"));
326 return -1;
327 }
328
329 if (UpnpSetMaxContentLength (UPNP_MAX_CONTENT_LENGTH) != UPNP_E_SUCCESS)
330 log_info (_("Could not set Max content UPnP\n"));
331
332 if (ut->xbox360)
333 log_info (_("Starting in XboX 360 compliant profile ...\n"));
334
335 #ifdef HAVE_DLNA
336 if (ut->dlna_enabled)
337 {
338 log_info (_("Starting in DLNA compliant profile ...\n"));
339 ut->dlna = dlna_init ();
340 dlna_set_verbosity (ut->dlna, ut->verbose ? 1 : 0);
341 dlna_set_extension_check (ut->dlna, 1);
342 dlna_register_all_media_profiles (ut->dlna);
343 }
344 #endif /* HAVE_DLNA */
345
346 ut->port = UpnpGetServerPort();
347 log_info (_("UPnP MediaServer listening on %s:%d\n"),
348 UpnpGetServerIpAddress (), ut->port);
349
350 UpnpEnableWebserver (TRUE);
351
352 res = UpnpSetVirtualDirCallbacks (&virtual_dir_callbacks);
353 if (res != UPNP_E_SUCCESS)
354 {
355 log_error (_("Cannot set virtual directory callbacks\n"));
356 free (description);
357 return -1;
358 }
359
360 res = UpnpAddVirtualDir (VIRTUAL_DIR);
361 if (res != UPNP_E_SUCCESS)
362 {
363 log_error (_("Cannot add virtual directory for web server\n"));
364 free (description);
365 return -1;
366 }
367
368 res = UpnpRegisterRootDevice2 (UPNPREG_BUF_DESC, description, 0, 1,
369 device_callback_event_handler,
370 NULL, &(ut->dev));
371 if (res != UPNP_E_SUCCESS)
372 {
373 log_error (_("Cannot register UPnP device\n"));
374 free (description);
375 return -1;
376 }
377
378 res = UpnpUnRegisterRootDevice (ut->dev);
379 if (res != UPNP_E_SUCCESS)
380 {
381 log_error (_("Cannot unregister UPnP device\n"));
382 free (description);
383 return -1;
384 }
385
386 res = UpnpRegisterRootDevice2 (UPNPREG_BUF_DESC, description, 0, 1,
387 device_callback_event_handler,
388 NULL, &(ut->dev));
389 if (res != UPNP_E_SUCCESS)
390 {
391 log_error (_("Cannot register UPnP device\n"));
392 free (description);
393 return -1;
394 }
395
396 log_info (_("Sending UPnP advertisement for device ...\n"));
397 UpnpSendAdvertisement (ut->dev, 1800);
398
399 log_info (_("Listening for control point connections ...\n"));
400
401 if (description)
402 free (description);
403
404 return 0;
405 }
406
407 static bool
408 has_iface (char *interface)
409 {
410 #ifdef HAVE_IFADDRS_H
411 struct ifaddrs *itflist, *itf;
412
413 if (!interface)
414 return false;
415
416 if (getifaddrs (&itflist) < 0)
417 {
418 perror ("getifaddrs");
419 return false;
420 }
421
422 itf = itflist;
423 while (itf)
424 {
425 if ((itf->ifa_flags & IFF_UP)
426 && !strncmp (itf->ifa_name, interface, IFNAMSIZ))
427 {
428 log_error (_("Interface %s is down.\n"), interface);
429 log_error (_("Recheck uShare's configuration and try again !\n"));
430 freeifaddrs (itflist);
431 return true;
432 }
433 itf = itf->ifa_next;
434 }
435
436 freeifaddrs (itf);
437 #else
438 int sock, i, n;
439 struct ifconf ifc;
440 struct ifreq ifr;
441 char buff[8192];
442
443 if (!interface)
444 return false;
445
446 /* determine UDN according to MAC address */
447 sock = socket (AF_INET, SOCK_STREAM, 0);
448 if (sock < 0)
449 {
450 perror ("socket");
451 return false;
452 }
453
454 /* get list of available interfaces */
455 ifc.ifc_len = sizeof (buff);
456 ifc.ifc_buf = buff;
457
458 if (ioctl (sock, SIOCGIFCONF, &ifc) < 0)
459 {
460 perror ("ioctl");
461 close (sock);
462 return false;
463 }
464
465 n = ifc.ifc_len / sizeof (struct ifreq);
466 for (i = n - 1 ; i >= 0 ; i--)
467 {
468 ifr = ifc.ifc_req[i];
469
470 if (strncmp (ifr.ifr_name, interface, IFNAMSIZ))
471 continue;
472
473 if (ioctl (sock, SIOCGIFFLAGS, &ifr) < 0)
474 {
475 perror ("ioctl");
476 close (sock);
477 return false;
478 }
479
480 if (!(ifr.ifr_flags & IFF_UP))
481 {
482 /* interface is down */
483 log_error (_("Interface %s is down.\n"), interface);
484 log_error (_("Recheck uShare's configuration and try again !\n"));
485 close (sock);
486 return false;
487 }
488
489 /* found right interface */
490 close (sock);
491 return true;
492 }
493 close (sock);
494 #endif
495
496 log_error (_("Can't find interface %s.\n"),interface);
497 log_error (_("Recheck uShare's configuration and try again !\n"));
498
499 return false;
500 }
501
502 static char *
503 create_udn (char *interface)
504 {
505 int sock = -1;
506 char *buf;
507 unsigned char *ptr;
508
509 #if (defined(BSD) || defined(__FreeBSD__) || defined(__APPLE__))
510 int mib[6];
511 size_t len;
512 struct if_msghdr *ifm;
513 struct sockaddr_dl *sdl;
514 #else /* Linux */
515 struct ifreq ifr;
516 #endif
517
518 if (!interface)
519 return NULL;
520
521 #if (defined(BSD) || defined(__FreeBSD__) || defined(__APPLE__))
522 mib[0] = CTL_NET;
523 mib[1] = AF_ROUTE;
524 mib[2] = 0;
525 mib[3] = AF_LINK;
526 mib[4] = NET_RT_IFLIST;
527
528 mib[5] = if_nametoindex (interface);
529 if (mib[5] == 0)
530 {
531 perror ("if_nametoindex");
532 return NULL;
533 }
534
535 if (sysctl (mib, 6, NULL, &len, NULL, 0) < 0)
536 {
537 perror ("sysctl");
538 return NULL;
539 }
540
541 buf = malloc (len);
542 if (sysctl (mib, 6, buf, &len, NULL, 0) < 0)
543 {
544 perror ("sysctl");
545 return NULL;
546 }
547
548 ifm = (struct if_msghdr *) buf;
549 sdl = (struct sockaddr_dl*) (ifm + 1);
550 ptr = (unsigned char *) LLADDR (sdl);
551 #else /* Linux */
552 /* determine UDN according to MAC address */
553 sock = socket (AF_INET, SOCK_STREAM, 0);
554 if (sock < 0)
555 {
556 perror ("socket");
557 return NULL;
558 }
559
560 strcpy (ifr.ifr_name, interface);
561 strcpy (ifr.ifr_hwaddr.sa_data, "");
562
563 if (ioctl (sock, SIOCGIFHWADDR, &ifr) < 0)
564 {
565 perror ("ioctl");
566 return NULL;
567 }
568
569 buf = (char *) malloc (64 * sizeof (char));
570 memset (buf, 0, 64);
571 ptr = (unsigned char *) ifr.ifr_hwaddr.sa_data;
572 #endif /* (defined(BSD) || defined(__FreeBSD__)) */
573
574 snprintf (buf, 64, "%s-%02x%02x%02x%02x%02x%02x", DEFAULT_UUID,
575 (ptr[0] & 0377), (ptr[1] & 0377), (ptr[2] & 0377),
576 (ptr[3] & 0377), (ptr[4] & 0377), (ptr[5] & 0377));
577
578 if (sock)
579 close (sock);
580
581 return buf;
582 }
583
584 static char *
585 get_iface_address (char *interface)
586 {
587 int sock;
588 uint32_t ip;
589 struct ifreq ifr;
590 char *val;
591
592 if (!interface)
593 return NULL;
594
595 /* determine UDN according to MAC address */
596 sock = socket (AF_INET, SOCK_STREAM, 0);
597 if (sock < 0)
598 {
599 perror ("socket");
600 return NULL;
601 }
602
603 strcpy (ifr.ifr_name, interface);
604 ifr.ifr_addr.sa_family = AF_INET;
605
606 if (ioctl (sock, SIOCGIFADDR, &ifr) < 0)
607 {
608 perror ("ioctl");
609 close (sock);
610 return NULL;
611 }
612
613 val = (char *) malloc (16 * sizeof (char));
614 ip = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr;
615 ip = ntohl (ip);
616 sprintf (val, "%d.%d.%d.%d",
617 (ip >> 24) & 0xFF, (ip >> 16) & 0xFF, (ip >> 8) & 0xFF, ip & 0xFF);
618
619 close (sock);
620
621 return val;
622 }
623
624 static int
625 restart_upnp (struct ushare_t *ut)
626 {
627 finish_upnp (ut);
628
629 if (ut->udn)
630 free (ut->udn);
631 ut->udn = create_udn (ut->interface);
632 if (!ut->udn)
633 return -1;
634
635 if (ut->ip)
636 free (ut->ip);
637 ut->ip = get_iface_address (ut->interface);
638 if (!ut->ip)
639 return -1;
640
641 return (init_upnp (ut));
642 }
643
644 static void
645 UPnPBreak (int s __attribute__ ((unused)))
646 {
647 ushare_signal_exit ();
648 }
649
650 static void
651 reload_config (int s __attribute__ ((unused)))
652 {
653 struct ushare_t *ut2;
654 bool reload = false;
655
656 log_info (_("Reloading configuration...\n"));
657
658 ut2 = ushare_new ();
659 if (!ut || !ut2)
660 return;
661
662 if (parse_config_file (ut2) < 0)
663 return;
664
665 if (ut->name && strcmp (ut->name, ut2->name))
666 {
667 free (ut->name);
668 ut->name = ut2->name;
669 ut2->name = NULL;
670 reload = true;
671 }
672
673 if (ut->interface && strcmp (ut->interface, ut2->interface))
674 {
675 if (!has_iface (ut2->interface))
676 {
677 ushare_free (ut2);
678 raise (SIGINT);
679 }
680 else
681 {
682 free (ut->interface);
683 ut->interface = ut2->interface;
684 ut2->interface = NULL;
685 reload = true;
686 }
687 }
688
689 if (ut->port != ut2->port)
690 {
691 ut->port = ut2->port;
692 reload = true;
693 }
694
695 if (reload)
696 {
697 if (restart_upnp (ut) < 0)
698 {
699 ushare_free (ut2);
700 raise (SIGINT);
701 }
702 }
703
704 if (ut->contentlist)
705 content_free (ut->contentlist);
706 ut->contentlist = ut2->contentlist;
707 ut2->contentlist = NULL;
708 ushare_free (ut2);
709
710 if (ut->contentlist)
711 {
712 free_metadata_list (ut);
713 build_metadata_list (ut);
714 }
715 else
716 {
717 log_error (_("Error: no content directory to be shared.\n"));
718 raise (SIGINT);
719 }
720 }
721
722 inline void
723 display_headers (void)
724 {
725 printf (_("%s (version %s), a lightweight UPnP A/V and DLNA Media Server.\n"),
726 PACKAGE_NAME, VERSION);
727 printf (_("Benjamin Zores (C) 2005-2007, for GeeXboX Team.\n"));
728 printf (_("See http://ushare.geexbox.org/ for updates.\n"));
729 }
730
731 inline static void
732 setup_i18n(void)
733 {
734 #ifdef CONFIG_NLS
735 #ifdef HAVE_SETLOCALE
736 setlocale (LC_ALL, "");
737 #endif
738 #if (!defined(BSD) && !defined(__FreeBSD__))
739 bindtextdomain (PACKAGE, LOCALEDIR);
740 #endif
741 textdomain (PACKAGE);
742 #endif
743 }
744
745 #define SHUTDOWN_MSG _("Server is shutting down: other clients will be notified soon, Bye bye ...\n")
746
747 static void
748 ushare_kill (ctrl_telnet_client *client,
749 int argc __attribute__((unused)),
750 char **argv __attribute__((unused)))
751 {
752 if (ut->use_telnet)
753 {
754 ctrl_telnet_client_send (client, SHUTDOWN_MSG);
755 client->exiting = true;
756 }
757 ushare_signal_exit ();
758 }
759
760 //main (int argc, char **argv)
761 void *
762 dlna_startup (void *p)
763 {
764 ut = ushare_new ();
765 log_verbose ("dlna_startup() start\n");
766
767 if (!ut)
768 return NULL;
769
770 setup_i18n ();
771 setup_iconv ();
772
773 #if 0
774 /* Parse args before cfg file, as we may override the default file */
775 if (parse_command_line (ut, argc, argv) < 0)
776 {
777 ushare_free (ut);
778 return NULL;
779 }
780 #endif
781
782 if (parse_config_file (ut) < 0)
783 {
784 /* fprintf here, because syslog not yet ready */
785 fprintf (stderr, _("Warning: can't parse file \"%s\".\n"),
786 ut->cfg_file ? ut->cfg_file : SYSCONFDIR "/" USHARE_CONFIG_FILE);
787 }
788 ut->verbose = true;
789 ut->port = 0;
790 ut->use_presentation = false;
791 ut->use_telnet = false;
792 ut->dlna_enabled = true;
793 ut->override_iconv_err = false;
794 ut->xbox360 = true;
795 ut->daemon = false;
796 //ut->interface = "192.168.1.34";
797 ut->contentlist = "/tmp";
798
799 if (ut->xbox360)
800 {
801 char *name;
802
803 name = malloc (strlen (XBOX_MODEL_NAME) + strlen (ut->model_name) + 4);
804 sprintf (name, "%s (%s)", XBOX_MODEL_NAME, ut->model_name);
805 free (ut->model_name);
806 ut->model_name = strdup (name);
807 free (name);
808
809 ut->starting_id = STARTING_ENTRY_ID_XBOX360;
810 }
811
812 if (ut->daemon)
813 {
814 /* starting syslog feature as soon as possible */
815 start_log ();
816 }
817
818 if (!ut->contentlist)
819 {
820 log_error (_("Error: no content directory to be shared.\n"));
821 ushare_free (ut);
822 return NULL;
823 }
824
825 if (!has_iface (ut->interface))
826 {
827 ushare_free (ut);
828 return NULL;
829 }
830
831 ut->udn = create_udn (ut->interface);
832 if (!ut->udn)
833 {
834 ushare_free (ut);
835 return NULL;
836 }
837
838 ut->ip = get_iface_address (ut->interface);
839 if (!ut->ip)
840 {
841 ushare_free (ut);
842 return NULL;
843 }
844
845 if (ut->daemon)
846 {
847 int err;
848 err = daemon (0, 0);
849 if (err == -1)
850 {
851 log_error (_("Error: failed to daemonize program : %s\n"),
852 strerror (err));
853 ushare_free (ut);
854 return NULL;
855 }
856 }
857 else
858 {
859 display_headers ();
860 }
861
862 #if 0
863 signal (SIGINT, UPnPBreak);
864 signal (SIGTERM, UPnPBreak);
865 signal (SIGUSR1, UPnPBreak);
866 signal (SIGUSR2, UPnPBreak);
867 signal (SIGPIPE, UPnPBreak);
868 signal (SIGHUP, reload_config);
869 #endif
870
871 if (ut->use_telnet)
872 {
873 if (ctrl_telnet_start (ut->telnet_port) < 0)
874 {
875 ushare_free (ut);
876 return NULL;
877 }
878
879 ctrl_telnet_register ("kill", ushare_kill,
880 _("Terminates the uShare server"));
881 }
882 log_verbose ("init_upnp() start\n");
883
884 if (init_upnp (ut) < 0)
885 {
886 finish_upnp (ut);
887 ushare_free (ut);
888 return NULL;
889 }
890
891 build_metadata_list (ut);
892
893 log_verbose ("uShare mutex lock.\n");
894 /* Let main sleep until it's time to die... */
895 pthread_mutex_lock (&ut->termination_mutex);
896 log_verbose ("uShare cond wait.\n");
897 pthread_cond_wait (&ut->termination_cond, &ut->termination_mutex);
898 pthread_mutex_unlock (&ut->termination_mutex);
899 log_verbose ("uShare finish.\n");
900
901 if (ut->use_telnet)
902 ctrl_telnet_stop ();
903 finish_upnp (ut);
904 free_metadata_list (ut);
905 ushare_free (ut);
906 finish_iconv ();
907
908 log_verbose ("dlna_start() finish\n");
909 /* it should never be executed */
910 return NULL;
911 }