diff --git a/clients.c b/clients.c index 2d4143c..8d82ba2 100644 --- a/clients.c +++ b/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; } diff --git a/clients.h b/clients.h index 5b4cb5a..d904ed0 100644 --- a/clients.h +++ b/clients.h @@ -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 diff --git a/minissdp.c b/minissdp.c index 0ab7ab5..ba9a861 100644 --- a/minissdp.c +++ b/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; } } diff --git a/upnphttp.c b/upnphttp.c index 5834b03..d8b6d29 100644 --- a/upnphttp.c +++ b/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, "%d%s%s%02X:%02X:%02X:%02X:%02X:%02X", - 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 ) diff --git a/upnphttp.h b/upnphttp.h index 8de4499..04db13a 100644 --- a/upnphttp.h +++ b/upnphttp.h @@ -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 */ diff --git a/upnpsoap.c b/upnpsoap.c index 0b6ec56..998515c 100644 --- a/upnpsoap.c +++ b/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 ) {