* Add client type caching code, so we can behave in a customized manner if necessary for certain clients.
This commit is contained in:
parent
a67c054ef7
commit
76ab570ed1
@ -66,6 +66,9 @@ OpenAndConfHTTPSocket(unsigned short port)
|
||||
int i = 1;
|
||||
struct sockaddr_in listenname;
|
||||
|
||||
/* Initialize client type cache */
|
||||
memset(&clients, 0, sizeof(struct client_cache_s));
|
||||
|
||||
if( (s = socket(PF_INET, SOCK_STREAM, 0)) < 0)
|
||||
{
|
||||
DPRINTF(E_ERROR, L_GENERAL, "socket(http): %s\n", strerror(errno));
|
||||
|
@ -28,6 +28,12 @@ enum media_types {
|
||||
IMAGES_ONLY
|
||||
};
|
||||
|
||||
enum client_types {
|
||||
EXbox = 1,
|
||||
EPS3,
|
||||
ESamsungTV
|
||||
};
|
||||
|
||||
struct media_dir_s {
|
||||
char * path; /* Base path */
|
||||
enum media_types type; /* type of files to scan */
|
||||
@ -39,4 +45,10 @@ struct album_art_name_s {
|
||||
struct album_art_name_s * next;
|
||||
};
|
||||
|
||||
struct client_cache_s {
|
||||
struct in_addr addr;
|
||||
enum client_types type;
|
||||
time_t age;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -39,5 +39,6 @@ sqlite3 * db;
|
||||
char friendly_name[FRIENDLYNAME_MAX_LEN];
|
||||
struct media_dir_s * media_dirs = NULL;
|
||||
struct album_art_name_s * album_art_names = NULL;
|
||||
struct client_cache_s clients[CLIENT_CACHE_SLOTS];
|
||||
short int scanning = 0;
|
||||
volatile __u32 updateID = 0;
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include <sqlite3.h>
|
||||
|
||||
#define CLIENT_CACHE_SLOTS 20
|
||||
#define USE_FORK 1
|
||||
#define DB_VERSION 1
|
||||
|
||||
@ -91,6 +92,7 @@ extern sqlite3 *db;
|
||||
extern char friendly_name[];
|
||||
extern struct media_dir_s * media_dirs;
|
||||
extern struct album_art_name_s * album_art_names;
|
||||
extern struct client_cache_s clients[CLIENT_CACHE_SLOTS];
|
||||
extern short int scanning;
|
||||
extern volatile __u32 updateID;
|
||||
|
||||
|
66
upnphttp.c
66
upnphttp.c
@ -86,6 +86,27 @@ Delete_upnphttp(struct upnphttp * h)
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
SearchClientCache(struct in_addr addr)
|
||||
{
|
||||
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 2 hours */
|
||||
if( (time(NULL) - clients[i].age) > 7200 )
|
||||
{
|
||||
memset(&clients[i], 0, sizeof(struct client_cache_s));
|
||||
return -1;
|
||||
}
|
||||
DPRINTF(E_DEBUG, L_HTTP, "Client [%d] found in cache.\n", clients[i].type);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* parse HttpHeaders of the REQUEST */
|
||||
static void
|
||||
ParseHttpHeaders(struct upnphttp * h)
|
||||
@ -191,6 +212,14 @@ intervening space) by either an integer or the keyword "infinite". */
|
||||
{
|
||||
h->req_client = EXbox;
|
||||
}
|
||||
else if(strncmp(p, "PLAYSTATION", 11)==0)
|
||||
{
|
||||
h->req_client = EPS3;
|
||||
}
|
||||
else if(strncmp(p, "SamsungWiselinkPro", 18)==0)
|
||||
{
|
||||
h->req_client = ESamsungTV;
|
||||
}
|
||||
}
|
||||
else if(strncasecmp(line, "Transfer-Encoding", 17)==0)
|
||||
{
|
||||
@ -262,6 +291,32 @@ intervening space) by either an integer or the keyword "infinite". */
|
||||
h->req_chunklen = -1;
|
||||
}
|
||||
}
|
||||
/* 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);
|
||||
if( h->req_client )
|
||||
{
|
||||
/* 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;
|
||||
clients[n].addr = h->clientaddr;
|
||||
clients[n].type = h->req_client;
|
||||
DPRINTF(E_DEBUG, L_HTTP, "Added client [%d/%X] to cache slot %d.\n",
|
||||
clients[n].type, clients[n].addr.s_addr, n);
|
||||
break;
|
||||
}
|
||||
}
|
||||
clients[n].age = time(NULL);
|
||||
}
|
||||
else if( n >= 0 )
|
||||
{
|
||||
h->req_client = clients[n].type;
|
||||
}
|
||||
}
|
||||
|
||||
/* very minimalistic 400 error message */
|
||||
@ -1366,14 +1421,17 @@ SendResp_dlnafile(struct upnphttp * h, char * object)
|
||||
Send400(h);
|
||||
goto error;
|
||||
}
|
||||
#if 1 // Some Samsung TVs do this?
|
||||
if( strncmp(last_file.mime, "image", 5) != 0 )
|
||||
{
|
||||
DPRINTF(E_WARN, L_HTTP, "Client tried to specify transferMode as Interactive without an image!\n");
|
||||
Send406(h);
|
||||
goto error;
|
||||
/* 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->req_client != ESamsungTV )
|
||||
{
|
||||
Send406(h);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
strftime(date, 30,"%a, %d %b %Y %H:%M:%S GMT" , gmtime(&curtime));
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <netinet/in.h>
|
||||
#include <sys/queue.h>
|
||||
|
||||
#include "minidlnatypes.h"
|
||||
#include "config.h"
|
||||
|
||||
/* server: HTTP header returned in all HTTP responses : */
|
||||
@ -31,10 +32,6 @@ enum httpCommands {
|
||||
EUnSubscribe
|
||||
};
|
||||
|
||||
enum clientType {
|
||||
EXbox = 1
|
||||
};
|
||||
|
||||
struct upnphttp {
|
||||
int socket;
|
||||
struct in_addr clientaddr; /* client address */
|
||||
@ -46,7 +43,7 @@ struct upnphttp {
|
||||
int req_contentlen;
|
||||
int req_contentoff; /* header length */
|
||||
enum httpCommands req_command;
|
||||
enum clientType req_client;
|
||||
enum client_types req_client;
|
||||
const char * req_soapAction;
|
||||
int req_soapActionLen;
|
||||
const char * req_Callback; /* For SUBSCRIBE */
|
||||
|
@ -22,7 +22,7 @@ struct Response
|
||||
int requested;
|
||||
int size;
|
||||
u_int32_t filter;
|
||||
enum clientType client;
|
||||
enum client_types client;
|
||||
};
|
||||
|
||||
/* ExecuteSoapAction():
|
||||
|
Loading…
x
Reference in New Issue
Block a user