clients: restructure client cache
This commit is contained in:
parent
173f6a76d7
commit
e9a653d6e8
18
clients.c
18
clients.c
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
18
minissdp.c
18
minissdp.c
@ -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;
|
||||
}
|
||||
}
|
||||
|
48
upnphttp.c
48
upnphttp.c
@ -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 )
|
||||
|
@ -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 */
|
||||
|
10
upnpsoap.c
10
upnpsoap.c
@ -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 )
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user