* Add client type caching code, so we can behave in a customized manner if necessary for certain clients.

This commit is contained in:
Justin Maggard 2009-05-01 00:01:03 +00:00
parent a67c054ef7
commit 76ab570ed1
7 changed files with 83 additions and 10 deletions

View File

@ -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));

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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));

View File

@ -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 */

View File

@ -22,7 +22,7 @@ struct Response
int requested;
int size;
u_int32_t filter;
enum clientType client;
enum client_types client;
};
/* ExecuteSoapAction():