clients: restructure client cache

This commit is contained in:
Justin Maggard 2014-06-09 17:10:27 -07:00
parent 173f6a76d7
commit e9a653d6e8
6 changed files with 49 additions and 53 deletions

View File

@ -240,7 +240,7 @@ struct client_type_s client_types[] =
struct client_cache_s clients[CLIENT_CACHE_SLOTS];
int
struct client_cache_s *
SearchClientCache(struct in_addr addr, int quiet)
{
int i;
@ -263,20 +263,20 @@ SearchClientCache(struct in_addr addr, int quiet)
else
{
memset(&clients[i], 0, sizeof(struct client_cache_s));
return -1;
return NULL;
}
}
if (!quiet)
DPRINTF(E_DEBUG, L_HTTP, "Client found in cache. [%s/entry %d]\n",
client_types[clients[i].type].name, i);
return i;
clients[i].type->name, i);
return &clients[i];
}
}
return -1;
return NULL;
}
int
struct client_cache_s *
AddClientCache(struct in_addr addr, int type)
{
int i;
@ -287,15 +287,15 @@ AddClientCache(struct in_addr addr, int type)
continue;
get_remote_mac(addr, clients[i].mac);
clients[i].addr = addr;
clients[i].type = type;
clients[i].type = &client_types[type];
clients[i].age = time(NULL);
DPRINTF(E_DEBUG, L_HTTP, "Added client [%s/%s/%02X:%02X:%02X:%02X:%02X:%02X] to cache slot %d.\n",
client_types[type].name, inet_ntoa(clients[i].addr),
clients[i].mac[0], clients[i].mac[1], clients[i].mac[2],
clients[i].mac[3], clients[i].mac[4], clients[i].mac[5], i);
return 0;
return &clients[i];
}
return -1;
return NULL;
}

View File

@ -91,14 +91,14 @@ struct client_type_s {
struct client_cache_s {
struct in_addr addr;
unsigned char mac[6];
enum client_types type;
struct client_type_s *type;
time_t age;
};
extern struct client_type_s client_types[];
extern struct client_cache_s clients[CLIENT_CACHE_SLOTS];
int SearchClientCache(struct in_addr addr, int quiet);
int AddClientCache(struct in_addr addr, int type);
struct client_cache_s *SearchClientCache(struct in_addr addr, int quiet);
struct client_cache_s *AddClientCache(struct in_addr addr, int type);
#endif

View File

@ -319,7 +319,7 @@ ParseUPnPClient(char *location)
char *off = NULL, *p;
int content_len = sizeof(buf);
struct NameValueParserData xml;
int client;
struct client_cache_s *client;
int type = 0;
char *model, *serial, *name;
@ -458,14 +458,14 @@ close:
return;
/* Add this client to the cache if it's not there already. */
client = SearchClientCache(dest.sin_addr, 1);
if (client < 0)
if (!client)
{
AddClientCache(dest.sin_addr, type);
}
else
{
clients[client].type = type;
clients[client].age = time(NULL);
client->type = &client_types[type];
client->age = time(NULL);
}
}
@ -546,13 +546,13 @@ ProcessSSDPRequest(int s, unsigned short port)
(strstrc(srv, "DigiOn DiXiM", '\r') != NULL)) /* Marantz Receiver */
{
/* Check if the client is already in cache */
i = SearchClientCache(sendername.sin_addr, 1);
if (i >= 0)
struct client_cache_s *client = SearchClientCache(sendername.sin_addr, 1);
if (client)
{
if (clients[i].type < EStandardDLNA150 &&
clients[i].type != ESamsungSeriesA)
if (client->type->type < EStandardDLNA150 &&
client->type->type != ESamsungSeriesA)
{
clients[i].age = time(NULL);
client->age = time(NULL);
return;
}
}

View File

@ -137,6 +137,7 @@ Delete_upnphttp(struct upnphttp * h)
static void
ParseHttpHeaders(struct upnphttp * h)
{
int client = 0;
char * line;
char * colon;
char * p;
@ -274,7 +275,7 @@ ParseHttpHeaders(struct upnphttp * h)
{
int i;
/* Skip client detection if we already detected it. */
if( h->req_client )
if( client )
goto next_header;
p = colon + 1;
while(isspace(*p))
@ -285,7 +286,7 @@ ParseHttpHeaders(struct upnphttp * h)
continue;
if (strstrc(p, client_types[i].match, '\r') != NULL)
{
h->req_client = i;
client = i;
break;
}
}
@ -294,7 +295,7 @@ ParseHttpHeaders(struct upnphttp * h)
{
int i;
/* Skip client detection if we already detected it. */
if( h->req_client && client_types[h->req_client].type < EStandardDLNA150 )
if( client && client_types[client].type < EStandardDLNA150 )
goto next_header;
p = colon + 1;
while(isspace(*p))
@ -305,7 +306,7 @@ ParseHttpHeaders(struct upnphttp * h)
continue;
if (strstrc(p, client_types[i].match, '\r') != NULL)
{
h->req_client = i;
client = i;
break;
}
}
@ -386,7 +387,7 @@ ParseHttpHeaders(struct upnphttp * h)
continue;
if (strstrc(p, client_types[i].match, '\r') != NULL)
{
h->req_client = i;
client = i;
break;
}
}
@ -432,29 +433,24 @@ next_header:
/* If the client type wasn't found, search the cache.
* This is done because a lot of clients like to send a
* different User-Agent with different types of requests. */
n = SearchClientCache(h->clientaddr, 0);
h->req_client = SearchClientCache(h->clientaddr, 0);
/* Add this client to the cache if it's not there already. */
if( n < 0 )
if (!h->req_client)
{
AddClientCache(h->clientaddr, h->req_client);
h->req_client = AddClientCache(h->clientaddr, client);
}
else if (h->req_client)
else if (client)
{
enum client_types type = client_types[h->req_client].type;
enum client_types ctype = client_types[clients[n].type].type;
enum client_types type = client_types[client].type;
enum client_types ctype = client_types[n].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 */
if ((ctype && ctype < EStandardDLNA150 && type >= EStandardDLNA150) ||
(ctype == ESamsungSeriesB && type == ESamsungSeriesA))
{
h->req_client = clients[n].type;
return;
}
clients[n].type = h->req_client;
clients[n].type = &client_types[client];
clients[n].age = time(NULL);
}
else
h->req_client = clients[n].type;
}
/* very minimalistic 400 error message */
@ -625,7 +621,7 @@ SendResp_presentation(struct upnphttp * h)
if (!clients[i].addr.s_addr)
continue;
strcatf(&str, "<tr><td>%d</td><td>%s</td><td>%s</td><td>%02X:%02X:%02X:%02X:%02X:%02X</td></tr>",
i, client_types[clients[i].type].name, inet_ntoa(clients[i].addr),
i, clients[i].type->name, inet_ntoa(clients[i].addr),
clients[i].mac[0], clients[i].mac[1], clients[i].mac[2],
clients[i].mac[3], clients[i].mac[4], clients[i].mac[5]);
}
@ -907,7 +903,7 @@ ProcessHttpQuery_upnphttp(struct upnphttp * h)
if(strcmp(ROOTDESC_PATH, HttpUrl) == 0)
{
/* If it's a Xbox360, we might need a special friendly_name to be recognized */
if( client_types[h->req_client].type == EXbox )
if( h->req_client && h->req_client->type->type == EXbox )
{
char model_sav[2];
i = 0;
@ -923,7 +919,7 @@ ProcessHttpQuery_upnphttp(struct upnphttp * h)
friendly_name[i] = '\0';
memcpy(modelnumber, model_sav, 2);
}
else if( client_types[h->req_client].flags & FLAG_SAMSUNG_DCM10 )
else if( h->req_client && h->req_client->type->flags & FLAG_SAMSUNG_DCM10 )
{
sendXMLdesc(h, genRootDescSamsung);
}
@ -1800,7 +1796,8 @@ SendResp_dlnafile(struct upnphttp *h, char *object)
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;
uint32_t cflags = h->req_client ? h->req_client->type->flags : 0;
enum client_types ctype = h->req_client ? h->req_client->type->type : 0;
static struct { int64_t id;
enum client_types client;
char path[PATH_MAX];
@ -1828,7 +1825,7 @@ SendResp_dlnafile(struct upnphttp *h, char *object)
return;
}
}
if( id != last_file.id || h->req_client != last_file.client )
if( id != last_file.id || ctype != last_file.client )
{
snprintf(buf, sizeof(buf), "SELECT PATH, MIME, DLNA_PN from DETAILS where ID = '%lld'", (long long)id);
ret = sql_get_table(db, buf, &result, &rows, NULL);
@ -1847,7 +1844,7 @@ SendResp_dlnafile(struct upnphttp *h, char *object)
}
/* Cache the result */
last_file.id = id;
last_file.client = h->req_client;
last_file.client = ctype;
strncpy(last_file.path, result[3], sizeof(last_file.path)-1);
if( result[4] )
{
@ -1860,12 +1857,11 @@ SendResp_dlnafile(struct upnphttp *h, char *object)
/* Samsung TV's such as the A750 can natively support many
Xvid/DivX AVI's however, the DLNA server needs the
mime type to say video/mpeg */
else if( h->req_client == ESamsungSeriesA &&
strcmp(last_file.mime+6, "x-msvideo") == 0 )
else if( ctype == ESamsungSeriesA && strcmp(last_file.mime+6, "x-msvideo") == 0 )
strcpy(last_file.mime+6, "mpeg");
}
/* ... and Sony BDP-S370 won't play MKV unless we pretend it's a DiVX file */
else if( h->req_client == ESonyBDP )
else if( ctype == ESonyBDP )
{
if( strcmp(last_file.mime+6, "x-matroska") == 0 ||
strcmp(last_file.mime+6, "mpeg") == 0 )

View File

@ -86,7 +86,7 @@ struct upnphttp {
int req_contentlen;
int req_contentoff; /* header length */
enum httpCommands req_command;
enum client_types req_client;
struct client_cache_s * req_client;
const char * req_soapAction;
int req_soapActionLen;
const char * req_Callback; /* For SUBSCRIBE */

View File

@ -349,7 +349,7 @@ set_filter_flags(char *filter, struct upnphttp *h)
{
char *item, *saveptr = NULL;
uint32_t flags = 0;
int samsung = client_types[h->req_client].flags & FLAG_SAMSUNG;
int samsung = h->req_client && (h->req_client->type->flags & FLAG_SAMSUNG);
if( !filter || (strlen(filter) <= 1) ) {
/* Not the full 32 bits. Skip vendor-specific stuff by default. */
@ -1166,8 +1166,8 @@ BrowseContentDirectory(struct upnphttp * h, const char * action)
args.returned = 0;
args.requested = RequestedCount;
args.client = client_types[h->req_client].type;
args.flags = client_types[h->req_client].flags;
args.client = h->req_client ? h->req_client->type->type : 0;
args.flags = h->req_client ? h->req_client->type->flags : 0;
args.str = &str;
if( args.flags & FLAG_MS_PFS )
{
@ -1638,8 +1638,8 @@ SearchContentDirectory(struct upnphttp * h, const char * action)
args.returned = 0;
args.requested = RequestedCount;
args.client = client_types[h->req_client].type;
args.flags = client_types[h->req_client].flags;
args.client = h->req_client ? h->req_client->type->type : 0;
args.flags = h->req_client ? h->req_client->type->flags : 0;
args.str = &str;
if( args.flags & FLAG_MS_PFS )
{