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