* 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;
|
int i = 1;
|
||||||
struct sockaddr_in listenname;
|
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)
|
if( (s = socket(PF_INET, SOCK_STREAM, 0)) < 0)
|
||||||
{
|
{
|
||||||
DPRINTF(E_ERROR, L_GENERAL, "socket(http): %s\n", strerror(errno));
|
DPRINTF(E_ERROR, L_GENERAL, "socket(http): %s\n", strerror(errno));
|
||||||
|
@ -28,6 +28,12 @@ enum media_types {
|
|||||||
IMAGES_ONLY
|
IMAGES_ONLY
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum client_types {
|
||||||
|
EXbox = 1,
|
||||||
|
EPS3,
|
||||||
|
ESamsungTV
|
||||||
|
};
|
||||||
|
|
||||||
struct media_dir_s {
|
struct media_dir_s {
|
||||||
char * path; /* Base path */
|
char * path; /* Base path */
|
||||||
enum media_types type; /* type of files to scan */
|
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 album_art_name_s * next;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct client_cache_s {
|
||||||
|
struct in_addr addr;
|
||||||
|
enum client_types type;
|
||||||
|
time_t age;
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -39,5 +39,6 @@ sqlite3 * db;
|
|||||||
char friendly_name[FRIENDLYNAME_MAX_LEN];
|
char friendly_name[FRIENDLYNAME_MAX_LEN];
|
||||||
struct media_dir_s * media_dirs = NULL;
|
struct media_dir_s * media_dirs = NULL;
|
||||||
struct album_art_name_s * album_art_names = NULL;
|
struct album_art_name_s * album_art_names = NULL;
|
||||||
|
struct client_cache_s clients[CLIENT_CACHE_SLOTS];
|
||||||
short int scanning = 0;
|
short int scanning = 0;
|
||||||
volatile __u32 updateID = 0;
|
volatile __u32 updateID = 0;
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
#include <sqlite3.h>
|
#include <sqlite3.h>
|
||||||
|
|
||||||
|
#define CLIENT_CACHE_SLOTS 20
|
||||||
#define USE_FORK 1
|
#define USE_FORK 1
|
||||||
#define DB_VERSION 1
|
#define DB_VERSION 1
|
||||||
|
|
||||||
@ -91,6 +92,7 @@ extern sqlite3 *db;
|
|||||||
extern char friendly_name[];
|
extern char friendly_name[];
|
||||||
extern struct media_dir_s * media_dirs;
|
extern struct media_dir_s * media_dirs;
|
||||||
extern struct album_art_name_s * album_art_names;
|
extern struct album_art_name_s * album_art_names;
|
||||||
|
extern struct client_cache_s clients[CLIENT_CACHE_SLOTS];
|
||||||
extern short int scanning;
|
extern short int scanning;
|
||||||
extern volatile __u32 updateID;
|
extern volatile __u32 updateID;
|
||||||
|
|
||||||
|
62
upnphttp.c
62
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 */
|
/* parse HttpHeaders of the REQUEST */
|
||||||
static void
|
static void
|
||||||
ParseHttpHeaders(struct upnphttp * h)
|
ParseHttpHeaders(struct upnphttp * h)
|
||||||
@ -191,6 +212,14 @@ intervening space) by either an integer or the keyword "infinite". */
|
|||||||
{
|
{
|
||||||
h->req_client = EXbox;
|
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)
|
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;
|
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 */
|
/* very minimalistic 400 error message */
|
||||||
@ -1366,14 +1421,17 @@ SendResp_dlnafile(struct upnphttp * h, char * object)
|
|||||||
Send400(h);
|
Send400(h);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
#if 1 // Some Samsung TVs do this?
|
|
||||||
if( strncmp(last_file.mime, "image", 5) != 0 )
|
if( strncmp(last_file.mime, "image", 5) != 0 )
|
||||||
{
|
{
|
||||||
DPRINTF(E_WARN, L_HTTP, "Client tried to specify transferMode as Interactive without an image!\n");
|
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->req_client != ESamsungTV )
|
||||||
|
{
|
||||||
Send406(h);
|
Send406(h);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
#endif
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
strftime(date, 30,"%a, %d %b %Y %H:%M:%S GMT" , gmtime(&curtime));
|
strftime(date, 30,"%a, %d %b %Y %H:%M:%S GMT" , gmtime(&curtime));
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <sys/queue.h>
|
#include <sys/queue.h>
|
||||||
|
|
||||||
|
#include "minidlnatypes.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
/* server: HTTP header returned in all HTTP responses : */
|
/* server: HTTP header returned in all HTTP responses : */
|
||||||
@ -31,10 +32,6 @@ enum httpCommands {
|
|||||||
EUnSubscribe
|
EUnSubscribe
|
||||||
};
|
};
|
||||||
|
|
||||||
enum clientType {
|
|
||||||
EXbox = 1
|
|
||||||
};
|
|
||||||
|
|
||||||
struct upnphttp {
|
struct upnphttp {
|
||||||
int socket;
|
int socket;
|
||||||
struct in_addr clientaddr; /* client address */
|
struct in_addr clientaddr; /* client address */
|
||||||
@ -46,7 +43,7 @@ struct upnphttp {
|
|||||||
int req_contentlen;
|
int req_contentlen;
|
||||||
int req_contentoff; /* header length */
|
int req_contentoff; /* header length */
|
||||||
enum httpCommands req_command;
|
enum httpCommands req_command;
|
||||||
enum clientType req_client;
|
enum client_types req_client;
|
||||||
const char * req_soapAction;
|
const char * req_soapAction;
|
||||||
int req_soapActionLen;
|
int req_soapActionLen;
|
||||||
const char * req_Callback; /* For SUBSCRIBE */
|
const char * req_Callback; /* For SUBSCRIBE */
|
||||||
|
@ -22,7 +22,7 @@ struct Response
|
|||||||
int requested;
|
int requested;
|
||||||
int size;
|
int size;
|
||||||
u_int32_t filter;
|
u_int32_t filter;
|
||||||
enum clientType client;
|
enum client_types client;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ExecuteSoapAction():
|
/* ExecuteSoapAction():
|
||||||
|
Loading…
x
Reference in New Issue
Block a user