Work at SourceForge, help us to make it a better place! We have an immediate need for a Support Technician in our San Francisco or Denver office.

Close

Diff of /upnphttp.c [bc33a3] .. [1c748c] Maximize Restore

  Switch to side-by-side view

--- a/upnphttp.c
+++ b/upnphttp.c
@@ -77,6 +77,7 @@
 #include <libexif/exif-loader.h>
 #include "tivo_utils.h"
 #include "tivo_commands.h"
+#include "clients.h"
 
 #include "sendfile.h"
 
@@ -128,40 +129,6 @@
 		free(h->res_buf);
 		free(h);
 	}
-}
-
-int
-SearchClientCache(struct in_addr addr, int quiet)
-{
-	int i;
-	for( i=0; i<CLIENT_CACHE_SLOTS; i++ )
-	{
-		if( clients[i].addr.s_addr == addr.s_addr )
-		{
-			/* Invalidate this client cache if it's older than 1 hour */
-			if( (time(NULL) - clients[i].age) > 3600 )
-			{
-				unsigned char mac[6];
-				if( get_remote_mac(addr, mac) == 0 &&
-				    memcmp(mac, clients[i].mac, 6) == 0 )
-				{
-					/* Same MAC as last time when we were able to identify the client,
- 					 * so extend the timeout by another hour. */
-					clients[i].age = time(NULL);
-				}
-				else
-				{
-					memset(&clients[i], 0, sizeof(struct client_cache_s));
-					return -1;
-				}
-			}
-			if( !quiet )
-				DPRINTF(E_DEBUG, L_HTTP, "Client found in cache. [type %d/entry %d]\n",
-					clients[i].type, i);
-			return i;
-		}
-	}
-	return -1;
 }
 
 /* parse HttpHeaders of the REQUEST */
@@ -302,121 +269,42 @@
 			}
 			else if(strncasecmp(line, "User-Agent", 10)==0)
 			{
-				char *s;
+				int i;
 				/* Skip client detection if we already detected it. */
 				if( h->req_client )
 					goto next_header;
 				p = colon + 1;
 				while(isspace(*p))
 					p++;
-				if(strncasecmp(p, "Xbox/", 5)==0)
+				for (i = 0; client_types[i].name; i++)
 				{
-					h->req_client = EXbox;
-					h->reqflags |= FLAG_MIME_AVI_AVI;
-					h->reqflags |= FLAG_MS_PFS;
+					if (client_types[i].match_type != EUserAgent)
+						continue;
+					if (strstrc(p, client_types[i].match, '\r') != NULL)
+					{
+						h->req_client = i;
+						break;
+					}
 				}
-				else if(strncmp(p, "PLAYSTATION", 11)==0)
-				{
-					h->req_client = EPS3;
-					h->reqflags |= FLAG_DLNA;
-					h->reqflags |= FLAG_MIME_AVI_DIVX;
-				}
-				else if((s=strstrc(p, "SEC_HHP_", '\r')))
-				{
-					h->req_client = ESamsungSeriesC;
-					h->reqflags |= FLAG_SAMSUNG;
-					h->reqflags |= FLAG_DLNA;
-					h->reqflags |= FLAG_NO_RESIZE;
-					if(strstrc(s+8, "TV", '\r'))
-						h->reqflags |= FLAG_SAMSUNG_TV;
-				}
-				else if(strncmp(p, "SamsungWiselinkPro", 18)==0)
-				{
-					h->req_client = ESamsungSeriesA;
-					h->reqflags |= FLAG_SAMSUNG;
-					h->reqflags |= FLAG_DLNA;
-					h->reqflags |= FLAG_NO_RESIZE;
-				}
-				else if(strstrc(p, "bridgeCo-DMP/3", '\r'))
-				{
-					h->req_client = EDenonReceiver;
-					h->reqflags |= FLAG_DLNA;
-				}
-				else if(strstrc(p, "fbxupnpav/", '\r'))
-				{
-					h->req_client = EFreeBox;
-					h->reqflags |= FLAG_RESIZE_THUMBS;
-				}
-				else if(strncmp(p, "SMP8634", 7)==0)
-				{
-					h->req_client = EPopcornHour;
-					h->reqflags |= FLAG_MIME_FLAC_FLAC;
-				}
-				else if(strstrc(p, "Microsoft-IPTV-Client", '\r'))
-				{
-					h->req_client = EMediaRoom;
-					h->reqflags |= FLAG_MS_PFS;
-				}
-				else if(strstrc(p, "LGE_DLNA_SDK", '\r'))
-				{
-					h->req_client = ELGDevice;
-					h->reqflags |= FLAG_DLNA;
-				}
-				else if(strncmp(p, "Verismo,", 8)==0)
-				{
-					h->req_client = ENetgearEVA2000;
-					h->reqflags |= FLAG_MS_PFS;
-					h->reqflags |= FLAG_RESIZE_THUMBS;
-				}
-				else if(strstrc(p, "DIRECTV ", '\r'))
-				{
-					h->req_client = EDirecTV;
-					h->reqflags |= FLAG_RESIZE_THUMBS;
-				}
-				else if(strstrc(p, "UPnP/1.0 DLNADOC/1.50 Intel_SDK_for_UPnP_devices/1.2", '\r'))
-				{
-					h->req_client = EToshibaTV;
-					h->reqflags |= FLAG_DLNA;
-				}
-				else if(strstrc(p, "DLNADOC/1.50", '\r'))
-				{
-					h->req_client = EStandardDLNA150;
-					h->reqflags |= FLAG_DLNA;
-					h->reqflags |= FLAG_MIME_AVI_AVI;
-				}
 			}
 			else if(strncasecmp(line, "X-AV-Client-Info", 16)==0)
 			{
+				int i;
 				/* Skip client detection if we already detected it. */
-				if( h->req_client && h->req_client < EStandardDLNA150 )
+				if( h->req_client && client_types[h->req_client].type < EStandardDLNA150 )
 					goto next_header;
 				p = colon + 1;
 				while(isspace(*p))
 					p++;
-				if(strstrc(p, "PLAYSTATION 3", '\r'))
+				for (i = 0; client_types[i].name; i++)
 				{
-					h->req_client = EPS3;
-					h->reqflags |= FLAG_DLNA;
-					h->reqflags |= FLAG_MIME_AVI_DIVX;
-				}
-				/* X-AV-Client-Info: av=5.0; cn="Sony Corporation"; mn="Blu-ray Disc Player"; mv="2.0" */
-				/* X-AV-Client-Info: av=5.0; cn="Sony Corporation"; mn="BLU-RAY HOME THEATRE SYSTEM"; mv="2.0"; */
-				/* Sony SMP-100 needs the same treatment as their BDP-S370 */
-				/* X-AV-Client-Info: av=5.0; cn="Sony Corporation"; mn="Media Player"; mv="2.0" */
-				else if(strstrc(p, "Blu-ray Disc Player", '\r') ||
-				        strstrc(p, "BLU-RAY HOME THEATRE SYSTEM", '\r') ||
-				        strstrc(p, "Media Player", '\r'))
-				{
-					h->req_client = ESonyBDP;
-					h->reqflags |= FLAG_DLNA;
-				}
-				/* X-AV-Client-Info: av=5.0; cn="Sony Corporation"; mn="BRAVIA KDL-40EX503"; mv="1.7"; */
-				/* X-AV-Client-Info: av=5.0; hn=""; cn="Sony Corporation"; mn="INTERNET TV NSX-40GT 1"; mv="0.1"; */
-				else if(strstrc(p, "BRAVIA", '\r') ||
-				        strstrc(p, "INTERNET TV", '\r'))
-				{
-					h->req_client = ESonyBravia;
-					h->reqflags |= FLAG_DLNA;
+					if (client_types[i].match_type != EXAVClientInfo)
+						continue;
+					if (strstrc(p, client_types[i].match, '\r') != NULL)
+					{
+						h->req_client = i;
+						break;
+					}
 				}
 			}
 			else if(strncasecmp(line, "Transfer-Encoding", 17)==0)
@@ -485,13 +373,19 @@
 			}
 			else if(strncasecmp(line, "FriendlyName", 12)==0)
 			{
+				int i;
 				p = colon + 1;
 				while(isspace(*p))
 					p++;
-				if(strstrc(p, "LIFETAB", '\r'))
+				for (i = 0; client_types[i].name; i++)
 				{
-					h->req_client = ELifeTab;
-					h->reqflags |= FLAG_MS_PFS;
+					if (client_types[i].match_type != EFriendlyName)
+						continue;
+					if (strstrc(p, client_types[i].match, '\r') != NULL)
+					{
+						h->req_client = i;
+						break;
+					}
 				}
 			}
 		}
@@ -532,35 +426,26 @@
 		/* Add this client to the cache if it's not there already. */
 		if( n < 0 )
 		{
-			for( n=0; n<CLIENT_CACHE_SLOTS; n++ )
-			{
-				if( clients[n].addr.s_addr )
-					continue;
-				get_remote_mac(h->clientaddr, clients[n].mac);
-				clients[n].addr = h->clientaddr;
-				DPRINTF(E_DEBUG, L_HTTP, "Added client [%d/%s/%02X:%02X:%02X:%02X:%02X:%02X] to cache slot %d.\n",
-				                         h->req_client, inet_ntoa(clients[n].addr),
-				                         clients[n].mac[0], clients[n].mac[1], clients[n].mac[2],
-				                         clients[n].mac[3], clients[n].mac[4], clients[n].mac[5], n);
-				break;
-			}
-		}
-		else if( (clients[n].type < EStandardDLNA150 && h->req_client == EStandardDLNA150) ||
-		         (clients[n].type == ESamsungSeriesB && h->req_client == ESamsungSeriesA) )
-		{
+			AddClientCache(h->clientaddr, h->req_client);
+		}
+		else
+		{
+			enum client_types type = client_types[h->req_client].type;
+			enum client_types ctype = client_types[clients[n].type].type;
 			/* If we know the client and our new detection is generic, use our cached info */
 			/* If we detected a Samsung Series B earlier, don't overwrite it with Series A info */
-			h->reqflags |= clients[n].flags;
-			h->req_client = clients[n].type;
-			return;
-		}
-		clients[n].type = h->req_client;
-		clients[n].flags = h->reqflags & 0xFFF00000;
-		clients[n].age = time(NULL);
+			if ((ctype < EStandardDLNA150 && type == EStandardDLNA150) ||
+			    (ctype == ESamsungSeriesB && type == ESamsungSeriesA))
+			{
+				h->req_client = clients[n].type;
+				return;
+			}
+			clients[n].type = h->req_client;
+			clients[n].age = time(NULL);
+		}
 	}
 	else if( n >= 0 )
 	{
-		h->reqflags |= clients[n].flags;
 		h->req_client = clients[n].type;
 	}
 }
@@ -979,7 +864,7 @@
 		if(strcmp(ROOTDESC_PATH, HttpUrl) == 0)
 		{
 			/* If it's a Xbox360, we might need a special friendly_name to be recognized */
-			if( h->req_client == EXbox )
+			if( client_types[h->req_client].type == EXbox )
 			{
 				char model_sav[2];
 				i = 0;
@@ -995,7 +880,7 @@
 					friendly_name[i] = '\0';
 				memcpy(modelnumber, model_sav, 2);
 			}
-			else if( h->reqflags & FLAG_SAMSUNG_TV )
+			else if( client_types[h->req_client].flags & FLAG_SAMSUNG_TV )
 			{
 				sendXMLdesc(h, genRootDescSamsung);
 			}
@@ -1837,7 +1722,7 @@
 }
 
 void
-SendResp_dlnafile(struct upnphttp * h, char * object)
+SendResp_dlnafile(struct upnphttp *h, char *object)
 {
 	char header[1024];
 	struct string_s str;
@@ -1850,6 +1735,7 @@
 	int64_t id;
 	int sendfh;
 	uint32_t dlna_flags = DLNA_FLAG_DLNA_V1_5|DLNA_FLAG_HTTP_STALLING|DLNA_FLAG_TM_B;
+	uint32_t cflags = client_types[h->req_client].flags;
 	static struct { int64_t id;
 	                enum client_types client;
 	                char path[PATH_MAX];
@@ -1861,7 +1747,7 @@
 #endif
 
 	id = strtoll(object, NULL, 10);
-	if( h->reqflags & FLAG_MS_PFS )
+	if( cflags & FLAG_MS_PFS )
 	{
 		if( strstr(object, "?albumArt=true") )
 		{
@@ -1897,7 +1783,7 @@
 		{
 			strncpy(last_file.mime, result[4], sizeof(last_file.mime)-1);
 			/* From what I read, Samsung TV's expect a [wrong] MIME type of x-mkv. */
-			if( h->reqflags & FLAG_SAMSUNG )
+			if( cflags & FLAG_SAMSUNG )
 			{
 				if( strcmp(last_file.mime+6, "x-matroska") == 0 )
 					strcpy(last_file.mime+8, "mkv");
@@ -1955,7 +1841,7 @@
 			DPRINTF(E_WARN, L_HTTP, "Client tried to specify transferMode as Interactive without an image!\n");
 			/* Samsung TVs (well, at least the A950) do this for some reason,
 			 * and I don't see them fixing this bug any time soon. */
-			if( !(h->reqflags & FLAG_SAMSUNG) || GETFLAG(DLNA_STRICT_MASK) )
+			if( !(cflags & FLAG_SAMSUNG) || GETFLAG(DLNA_STRICT_MASK) )
 			{
 				Send406(h);
 				goto error;