Mercurial > pt1.oyama
annotate src/ushare.c @ 126:5dcaf3785ebe
fix process terminate problem.
add dynamic Content-Length header.
author | Naoya OYAMA <naoya.oyama@gmail.com> |
---|---|
date | Sun, 03 Oct 2010 21:55:37 +0900 |
parents | e413158cae13 |
children | 20442921bff5 |
rev | line source |
---|---|
125 | 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 | |
126
5dcaf3785ebe
fix process terminate problem.
Naoya OYAMA <naoya.oyama@gmail.com>
parents:
125
diff
changeset
|
644 //static void |
5dcaf3785ebe
fix process terminate problem.
Naoya OYAMA <naoya.oyama@gmail.com>
parents:
125
diff
changeset
|
645 void |
125 | 646 UPnPBreak (int s __attribute__ ((unused))) |
647 { | |
648 ushare_signal_exit (); | |
649 } | |
650 | |
651 static void | |
652 reload_config (int s __attribute__ ((unused))) | |
653 { | |
654 struct ushare_t *ut2; | |
655 bool reload = false; | |
656 | |
657 log_info (_("Reloading configuration...\n")); | |
658 | |
659 ut2 = ushare_new (); | |
660 if (!ut || !ut2) | |
661 return; | |
662 | |
663 if (parse_config_file (ut2) < 0) | |
664 return; | |
665 | |
666 if (ut->name && strcmp (ut->name, ut2->name)) | |
667 { | |
668 free (ut->name); | |
669 ut->name = ut2->name; | |
670 ut2->name = NULL; | |
671 reload = true; | |
672 } | |
673 | |
674 if (ut->interface && strcmp (ut->interface, ut2->interface)) | |
675 { | |
676 if (!has_iface (ut2->interface)) | |
677 { | |
678 ushare_free (ut2); | |
679 raise (SIGINT); | |
680 } | |
681 else | |
682 { | |
683 free (ut->interface); | |
684 ut->interface = ut2->interface; | |
685 ut2->interface = NULL; | |
686 reload = true; | |
687 } | |
688 } | |
689 | |
690 if (ut->port != ut2->port) | |
691 { | |
692 ut->port = ut2->port; | |
693 reload = true; | |
694 } | |
695 | |
696 if (reload) | |
697 { | |
698 if (restart_upnp (ut) < 0) | |
699 { | |
700 ushare_free (ut2); | |
701 raise (SIGINT); | |
702 } | |
703 } | |
704 | |
705 if (ut->contentlist) | |
706 content_free (ut->contentlist); | |
707 ut->contentlist = ut2->contentlist; | |
708 ut2->contentlist = NULL; | |
709 ushare_free (ut2); | |
710 | |
711 if (ut->contentlist) | |
712 { | |
713 free_metadata_list (ut); | |
714 build_metadata_list (ut); | |
715 } | |
716 else | |
717 { | |
718 log_error (_("Error: no content directory to be shared.\n")); | |
719 raise (SIGINT); | |
720 } | |
721 } | |
722 | |
723 inline void | |
724 display_headers (void) | |
725 { | |
726 printf (_("%s (version %s), a lightweight UPnP A/V and DLNA Media Server.\n"), | |
727 PACKAGE_NAME, VERSION); | |
728 printf (_("Benjamin Zores (C) 2005-2007, for GeeXboX Team.\n")); | |
729 printf (_("See http://ushare.geexbox.org/ for updates.\n")); | |
730 } | |
731 | |
732 inline static void | |
733 setup_i18n(void) | |
734 { | |
735 #ifdef CONFIG_NLS | |
736 #ifdef HAVE_SETLOCALE | |
737 setlocale (LC_ALL, ""); | |
738 #endif | |
739 #if (!defined(BSD) && !defined(__FreeBSD__)) | |
740 bindtextdomain (PACKAGE, LOCALEDIR); | |
741 #endif | |
742 textdomain (PACKAGE); | |
743 #endif | |
744 } | |
745 | |
746 #define SHUTDOWN_MSG _("Server is shutting down: other clients will be notified soon, Bye bye ...\n") | |
747 | |
748 static void | |
749 ushare_kill (ctrl_telnet_client *client, | |
750 int argc __attribute__((unused)), | |
751 char **argv __attribute__((unused))) | |
752 { | |
753 if (ut->use_telnet) | |
754 { | |
755 ctrl_telnet_client_send (client, SHUTDOWN_MSG); | |
756 client->exiting = true; | |
757 } | |
758 ushare_signal_exit (); | |
759 } | |
760 | |
761 //main (int argc, char **argv) | |
762 void * | |
763 dlna_startup (void *p) | |
764 { | |
765 ut = ushare_new (); | |
766 log_verbose ("dlna_startup() start\n"); | |
767 | |
768 if (!ut) | |
769 return NULL; | |
770 | |
771 setup_i18n (); | |
772 setup_iconv (); | |
773 | |
774 #if 0 | |
775 /* Parse args before cfg file, as we may override the default file */ | |
776 if (parse_command_line (ut, argc, argv) < 0) | |
777 { | |
778 ushare_free (ut); | |
779 return NULL; | |
780 } | |
781 #endif | |
782 | |
783 if (parse_config_file (ut) < 0) | |
784 { | |
785 /* fprintf here, because syslog not yet ready */ | |
786 fprintf (stderr, _("Warning: can't parse file \"%s\".\n"), | |
787 ut->cfg_file ? ut->cfg_file : SYSCONFDIR "/" USHARE_CONFIG_FILE); | |
788 } | |
789 ut->verbose = true; | |
790 ut->port = 0; | |
791 ut->use_presentation = false; | |
792 ut->use_telnet = false; | |
793 ut->dlna_enabled = true; | |
794 ut->override_iconv_err = false; | |
795 ut->xbox360 = true; | |
796 ut->daemon = false; | |
797 //ut->interface = "192.168.1.34"; | |
798 ut->contentlist = "/tmp"; | |
799 | |
800 if (ut->xbox360) | |
801 { | |
802 char *name; | |
803 | |
804 name = malloc (strlen (XBOX_MODEL_NAME) + strlen (ut->model_name) + 4); | |
805 sprintf (name, "%s (%s)", XBOX_MODEL_NAME, ut->model_name); | |
806 free (ut->model_name); | |
807 ut->model_name = strdup (name); | |
808 free (name); | |
809 | |
810 ut->starting_id = STARTING_ENTRY_ID_XBOX360; | |
811 } | |
812 | |
813 if (ut->daemon) | |
814 { | |
815 /* starting syslog feature as soon as possible */ | |
816 start_log (); | |
817 } | |
818 | |
819 if (!ut->contentlist) | |
820 { | |
821 log_error (_("Error: no content directory to be shared.\n")); | |
822 ushare_free (ut); | |
823 return NULL; | |
824 } | |
825 | |
826 if (!has_iface (ut->interface)) | |
827 { | |
828 ushare_free (ut); | |
829 return NULL; | |
830 } | |
831 | |
832 ut->udn = create_udn (ut->interface); | |
833 if (!ut->udn) | |
834 { | |
835 ushare_free (ut); | |
836 return NULL; | |
837 } | |
838 | |
839 ut->ip = get_iface_address (ut->interface); | |
840 if (!ut->ip) | |
841 { | |
842 ushare_free (ut); | |
843 return NULL; | |
844 } | |
845 | |
846 if (ut->daemon) | |
847 { | |
848 int err; | |
849 err = daemon (0, 0); | |
850 if (err == -1) | |
851 { | |
852 log_error (_("Error: failed to daemonize program : %s\n"), | |
853 strerror (err)); | |
854 ushare_free (ut); | |
855 return NULL; | |
856 } | |
857 } | |
858 else | |
859 { | |
860 display_headers (); | |
861 } | |
862 | |
863 #if 0 | |
864 signal (SIGINT, UPnPBreak); | |
865 signal (SIGTERM, UPnPBreak); | |
866 signal (SIGUSR1, UPnPBreak); | |
867 signal (SIGUSR2, UPnPBreak); | |
868 signal (SIGPIPE, UPnPBreak); | |
869 signal (SIGHUP, reload_config); | |
870 #endif | |
871 | |
872 if (ut->use_telnet) | |
873 { | |
874 if (ctrl_telnet_start (ut->telnet_port) < 0) | |
875 { | |
876 ushare_free (ut); | |
877 return NULL; | |
878 } | |
879 | |
880 ctrl_telnet_register ("kill", ushare_kill, | |
881 _("Terminates the uShare server")); | |
882 } | |
883 log_verbose ("init_upnp() start\n"); | |
884 | |
885 if (init_upnp (ut) < 0) | |
886 { | |
887 finish_upnp (ut); | |
888 ushare_free (ut); | |
889 return NULL; | |
890 } | |
891 | |
892 build_metadata_list (ut); | |
893 | |
894 /* Let main sleep until it's time to die... */ | |
895 pthread_mutex_lock (&ut->termination_mutex); | |
896 pthread_cond_wait (&ut->termination_cond, &ut->termination_mutex); | |
897 pthread_mutex_unlock (&ut->termination_mutex); | |
898 | |
899 if (ut->use_telnet) | |
900 ctrl_telnet_stop (); | |
901 finish_upnp (ut); | |
902 free_metadata_list (ut); | |
903 ushare_free (ut); | |
904 finish_iconv (); | |
905 | |
906 /* it should never be executed */ | |
907 return NULL; | |
908 } | |
126
5dcaf3785ebe
fix process terminate problem.
Naoya OYAMA <naoya.oyama@gmail.com>
parents:
125
diff
changeset
|
909 |