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