Wrap up version 1.3.3.
[minidlna.git] / clients.c
blob2e296443805d580d0f36608bf707c13e4c6110f9
1 /* MiniDLNA media server
2 * Copyright (C) 2013-2017 NETGEAR
4 * This file is part of MiniDLNA.
6 * MiniDLNA is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
10 * MiniDLNA is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with MiniDLNA. If not, see <http://www.gnu.org/licenses/>.
18 #include <stdio.h>
19 #include <string.h>
20 #include <time.h>
22 #include "clients.h"
23 #include "event.h"
24 #include "getifaddr.h"
25 #include "log.h"
27 struct client_type_s client_types[] =
29 { 0,
31 "Unknown",
32 NULL,
33 EMatchNone
36 { EXbox,
37 FLAG_MIME_AVI_AVI | FLAG_MS_PFS,
38 "Xbox 360",
39 "Xbox/",
40 EUserAgent
43 { EPS3,
44 FLAG_DLNA | FLAG_MIME_AVI_DIVX,
45 "PLAYSTATION 3",
46 "PLAYSTATION",
47 EUserAgent
50 { EPS3,
51 FLAG_DLNA | FLAG_MIME_AVI_DIVX,
52 "PLAYSTATION 3",
53 "PLAYSTATION 3",
54 EXAVClientInfo
57 { ECling,
58 FLAG_MS_PFS,
59 "Cling",
60 "Cling/",
61 EUserAgent
64 /* User-Agent: DLNADOC/1.50 SEC_HHP_[PC]LPC001/1.0 MS-DeviceCaps/1024 */
65 /* This is AllShare running on a PC. We don't want to respond with Samsung
66 * capabilities, or Windows (and AllShare) might get grumpy. */
67 { 0,
68 FLAG_DLNA,
69 "AllShare",
70 "SEC_HHP_[PC]",
71 EUserAgent
74 { ESamsungBDJ5500,
75 FLAG_SAMSUNG | FLAG_DLNA | FLAG_NO_RESIZE | FLAG_CAPTION_RES | FLAG_SKIP_DLNA_PN,
76 "Samsung BD J5500",
77 "[BD]J5500",
78 EUserAgent
81 /* Samsung Series [CDE] BDPs and TVs must be separated, or some of our
82 * advertised extra features trigger a folder browsing bug on BDPs. */
83 /* User-Agent: DLNADOC/1.50 SEC_HHP_BD-D5100/1.0 */
84 { ESamsungSeriesCDEBDP,
85 FLAG_SAMSUNG | FLAG_DLNA | FLAG_NO_RESIZE,
86 "Samsung Series [CDEF] BDP",
87 "SEC_HHP_BD",
88 EUserAgent
91 /* Samsung Series [Q] TVs work with milliseconds for bookmarks */
92 /* User-Agent: DLNADOC/1.50 SEC_HHP_[TV] Samsung Q7 Series (49)/1.0 */
93 { ESamsungSeriesQ,
94 FLAG_SAMSUNG | FLAG_DLNA | FLAG_NO_RESIZE | FLAG_SAMSUNG_DCM10 | FLAG_CAPTION_RES | FLAG_CONVERT_MS,
95 "Samsung Series [Q]",
96 "SEC_HHP_[TV] Samsung Q",
97 EUserAgent
100 /* Samsung Series [QN] TVs work with milliseconds for bookmarks */
101 /* User-Agent: DLNADOC/1.50 SEC_HHP_Samsung QN90AA 50 TV/1.0 */
102 { ESamsungSeriesQ,
103 FLAG_SAMSUNG | FLAG_DLNA | FLAG_NO_RESIZE | FLAG_SAMSUNG_DCM10 | FLAG_CAPTION_RES | FLAG_CONVERT_MS,
104 "Samsung Series [QN]",
105 "SEC_HHP_Samsung QN",
106 EUserAgent
109 /* User-Agent: DLNADOC/1.50 SEC_HHP_[TV]UE40D7000/1.0 */
110 /* User-Agent: DLNADOC/1.50 SEC_HHP_ Family TV/1.0 */
111 /* USER-AGENT: DLNADOC/1.50 SEC_HHP_[TV] UE65JU7000/1.0 UPnP/1.0 */
112 { ESamsungSeriesCDE,
113 FLAG_SAMSUNG | FLAG_DLNA | FLAG_NO_RESIZE | FLAG_SAMSUNG_DCM10 | FLAG_CAPTION_RES,
114 "Samsung Series [CDEFJ]",
115 "SEC_HHP_",
116 EUserAgent
119 { ESamsungSeriesA,
120 FLAG_SAMSUNG | FLAG_DLNA | FLAG_NO_RESIZE,
121 "Samsung Series A",
122 "SamsungWiselinkPro",
123 EUserAgent
126 { ESamsungSeriesB,
127 FLAG_SAMSUNG | FLAG_DLNA | FLAG_NO_RESIZE,
128 "Samsung Series B",
129 "Samsung DTV DMR",
130 EModelName
133 /* User-Agent: Panasonic MIL DLNA CP UPnP/1.0 DLNADOC/1.50 */
134 { EPanasonic,
135 FLAG_DLNA | FLAG_FORCE_SORT,
136 "Panasonic",
137 "Panasonic",
138 EUserAgent
141 /* User-Agent: IPI/1.0 UPnP/1.0 DLNADOC/1.50 */
142 { ENetFrontLivingConnect,
143 FLAG_DLNA | FLAG_FORCE_SORT | FLAG_CAPTION_RES,
144 "NetFront Living Connect",
145 "IPI/1",
146 EUserAgent
149 { EDenonReceiver,
150 FLAG_DLNA,
151 "Denon Receiver",
152 "bridgeCo-DMP/3",
153 EUserAgent
156 { EFreeBox,
157 FLAG_RESIZE_THUMBS,
158 "FreeBox",
159 "fbxupnpav/",
160 EUserAgent
163 { EPopcornHour,
164 FLAG_MIME_FLAC_FLAC,
165 "Popcorn Hour",
166 "SMP8634",
167 EUserAgent
170 /* X-AV-Client-Info: av=5.0; cn="Sony Corporation"; mn="Blu-ray Disc Player"; mv="2.0" */
171 /* X-AV-Client-Info: av=5.0; cn="Sony Corporation"; mn="BLU-RAY HOME THEATRE SYSTEM"; mv="2.0"; */
172 /* Sony SMP-100 needs the same treatment as their BDP-S370 */
173 /* X-AV-Client-Info: av=5.0; cn="Sony Corporation"; mn="Media Player"; mv="2.0" */
174 { ESonyBDP,
175 FLAG_DLNA,
176 "Sony BDP",
177 "mv=\"2.0\"",
178 EXAVClientInfo
181 /* USER-AGENT: Linux/2.6.35 UPnP/1.0 DLNADOC/1.50 INTEL_NMPR/2.0 LGE_DLNA_SDK/1.6.0 */
182 { ELGNetCastDevice,
183 FLAG_DLNA | FLAG_CAPTION_RES | FLAG_MIME_FLAC_FLAC,
184 "LG",
185 "LGE_DLNA_SDK/1.6.0",
186 EUserAgent
189 /* User-Agent: Linux/2.6.31-1.0 UPnP/1.0 DLNADOC/1.50 INTEL_NMPR/2.0 LGE_DLNA_SDK/1.5.0 */
190 { ELGDevice,
191 FLAG_DLNA | FLAG_CAPTION_RES | FLAG_MIME_FLAC_FLAC,
192 "LG",
193 "LGE_DLNA_SDK",
194 EUserAgent
197 /* X-AV-Client-Info: av=5.0; cn="Sony Corporation"; mn="BRAVIA KDL-40EX503"; mv="1.7"; */
198 { ESonyBravia,
199 FLAG_DLNA,
200 "Sony Bravia",
201 "BRAVIA",
202 EXAVClientInfo
205 /* X-AV-Client-Info: av=5.0; hn=""; cn="Sony Corporation"; mn="INTERNET TV NSX-40GT 1"; mv="0.1"; */
206 { ESonyInternetTV,
207 FLAG_DLNA,
208 "Sony Internet TV",
209 "INTERNET TV",
210 EXAVClientInfo
213 { ENetgearEVA2000,
214 FLAG_MS_PFS | FLAG_RESIZE_THUMBS,
215 "EVA2000",
216 "Verismo,",
217 EUserAgent
220 { EDirecTV,
221 FLAG_RESIZE_THUMBS,
222 "DirecTV",
223 "DIRECTV ",
224 EUserAgent
227 { EToshibaTV,
228 FLAG_DLNA,
229 "Toshiba TV",
230 "UPnP/1.0 DLNADOC/1.50 Intel_SDK_for_UPnP_devices/1.2",
231 EUserAgent
234 { EHyundaiTV,
235 FLAG_DLNA,
236 "Hyundai TV",
237 "HYUNDAITV",
238 EFriendlyName
241 { ERokuSoundBridge,
242 FLAG_MS_PFS | FLAG_AUDIO_ONLY | FLAG_MIME_WAV_WAV | FLAG_FORCE_SORT,
243 "Roku SoundBridge",
244 "Roku SoundBridge",
245 EModelName
248 { EMarantzDMP,
249 FLAG_DLNA | FLAG_MIME_WAV_WAV,
250 "marantz DMP",
251 "marantz DMP",
252 EFriendlyNameSSDP
255 { EMediaRoom,
256 FLAG_MS_PFS,
257 "MS MediaRoom",
258 "Microsoft-IPTV-Client",
259 EUserAgent
262 { ELifeTab,
263 FLAG_MS_PFS,
264 "LIFETAB",
265 "LIFETAB",
266 EFriendlyName
269 { EAsusOPlay,
270 FLAG_DLNA | FLAG_MIME_AVI_AVI | FLAG_CAPTION_RES,
271 "Asus OPlay Mini/Mini+",
272 "O!Play",
273 EUserAgent
276 { EBubbleUPnP,
277 FLAG_CAPTION_RES,
278 "BubbleUPnP",
279 "BubbleUPnP",
280 EUserAgent
283 { EMovian,
284 FLAG_CAPTION_RES,
285 "Movian",
286 "Movian",
287 EUserAgent
290 { EKodi,
291 FLAG_DLNA | FLAG_MIME_AVI_AVI | FLAG_CAPTION_RES,
292 "Kodi",
293 "Kodi",
294 EUserAgent
297 { 0,
298 FLAG_DLNA | FLAG_MIME_AVI_AVI,
299 "Windows",
300 "FDSSDP",
301 EUserAgent
304 { 0,
306 "TiVo",
307 "TvHttpClient",
308 EUserAgent
311 { EStandardDLNA150,
312 FLAG_DLNA | FLAG_MIME_AVI_AVI,
313 "Generic DLNA 1.5",
314 "DLNADOC/1.50",
315 EUserAgent
318 { EStandardUPnP,
320 "Generic UPnP 1.0",
321 "UPnP/1.0",
322 EUserAgent
325 { 0, 0, NULL, 0 }
328 struct client_cache_s clients[CLIENT_CACHE_SLOTS];
330 struct client_cache_s *
331 SearchClientCache(struct in_addr addr, int quiet)
333 int i;
335 for (i = 0; i < CLIENT_CACHE_SLOTS; i++)
337 if (clients[i].addr.s_addr == addr.s_addr)
339 /* Invalidate this client cache if it's older than 1 hour */
340 if ((time(NULL) - clients[i].age) > 3600)
342 unsigned char mac[6];
343 if (get_remote_mac(addr, mac) == 0 &&
344 memcmp(mac, clients[i].mac, 6) == 0)
346 /* Same MAC as last time when we were able to identify the client,
347 * so extend the timeout by another hour. */
348 clients[i].age = time(NULL);
350 else
352 memset(&clients[i], 0, sizeof(struct client_cache_s));
353 return NULL;
356 if (!quiet)
357 DPRINTF(E_DEBUG, L_HTTP, "Client found in cache. [%s/entry %d]\n",
358 clients[i].type->name, i);
359 return &clients[i];
363 return NULL;
366 struct client_cache_s *
367 AddClientCache(struct in_addr addr, int type)
369 int i;
371 for (i = 0; i < CLIENT_CACHE_SLOTS; i++)
373 if (clients[i].addr.s_addr)
374 continue;
375 get_remote_mac(addr, clients[i].mac);
376 clients[i].addr = addr;
377 clients[i].type = &client_types[type];
378 clients[i].age = time(NULL);
379 DPRINTF(E_DEBUG, L_HTTP, "Added client [%s/%s/%02X:%02X:%02X:%02X:%02X:%02X] to cache slot %d.\n",
380 client_types[type].name, inet_ntoa(clients[i].addr),
381 clients[i].mac[0], clients[i].mac[1], clients[i].mac[2],
382 clients[i].mac[3], clients[i].mac[4], clients[i].mac[5], i);
383 return &clients[i];
386 return NULL;