upnpttp: factor out basic header generation

This commit is contained in:
Justin Maggard 2014-07-25 18:26:02 -07:00
parent 04c8730dae
commit 75a697a671

View File

@ -80,12 +80,13 @@
#include "tivo_commands.h"
#include "clients.h"
#include "process.h"
#include "sendfile.h"
#define MAX_BUFFER_SIZE 2147483647
#define MIN_BUFFER_SIZE 65536
#define INIT_STR(s, d) { s.data = d; s.size = sizeof(d); s.off = 0; }
#include "icons.c"
enum event_type {
@ -592,9 +593,7 @@ SendResp_presentation(struct upnphttp * h)
char body[4096];
int a, v, p, i;
str.data = body;
str.size = sizeof(body);
str.off = 0;
INIT_STR(str, body);
h->respflags = FLAG_HTML;
@ -1181,9 +1180,6 @@ BuildHeader_upnphttp(struct upnphttp * h, int respcode,
strftime(date, 30,"%a, %d %b %Y %H:%M:%S GMT" , gmtime(&curtime));
strcatf(&res, "Date: %s\r\n", date);
strcatf(&res, "EXT:\r\n");
#if 0 // DLNA
strcatf(&res, "contentFeatures.dlna.org: \r\n");
#endif
strcatf(&res, "\r\n");
h->res_buflen = res.off;
if(h->res_buf_alloclen < (h->res_buflen + bodylen))
@ -1313,15 +1309,33 @@ send_file(struct upnphttp * h, int sendfd, off_t offset, off_t end_offset)
free(buf);
}
static void
start_dlna_header(struct string_s *str, int respcode, const char *tmode, const char *mime)
{
char date[30];
time_t now;
now = time(NULL);
strftime(date, sizeof(date),"%a, %d %b %Y %H:%M:%S GMT" , gmtime(&now));
strcatf(str, "HTTP/1.1 %d OK\r\n"
"Connection: close\r\n"
"Date: %s\r\n"
"Server: " MINIDLNA_SERVER_STRING "\r\n"
"EXT:\r\n"
"realTimeInfo.dlna.org: DLNA.ORG_TLAG=*\r\n"
"transferMode.dlna.org: %s\r\n"
"Content-Type: %s\r\n",
respcode, date, tmode, mime);
}
static void
SendResp_icon(struct upnphttp * h, char * icon)
{
char header[512];
char mime[12] = "image/";
char date[30];
char *data;
int size, ret;
time_t curtime = time(NULL);
int size;
struct string_s str;
if( strcmp(icon, "sm.png") == 0 )
{
@ -1358,16 +1372,12 @@ SendResp_icon(struct upnphttp * h, char * icon)
return;
}
strftime(date, 30,"%a, %d %b %Y %H:%M:%S GMT" , gmtime(&curtime));
ret = snprintf(header, sizeof(header), "HTTP/1.1 200 OK\r\n"
"Content-Type: %s\r\n"
"Content-Length: %d\r\n"
"Connection: close\r\n"
"Date: %s\r\n"
"Server: " MINIDLNA_SERVER_STRING "\r\n\r\n",
mime, size, date);
INIT_STR(str, header);
if( send_data(h, header, ret, MSG_MORE) == 0 )
start_dlna_header(&str, 200, "Interactive", mime);
strcatf(&str, "Content-Length: %d\r\n\r\n", size);
if( send_data(h, str.data, str.off, MSG_MORE) == 0 )
{
if( h->req_command != EHead )
send_data(h, data, size, 0);
@ -1380,11 +1390,10 @@ SendResp_albumArt(struct upnphttp * h, char * object)
{
char header[512];
char *path;
char date[30];
time_t curtime = time(NULL);
off_t size;
long long id;
int fd, ret;
int fd;
struct string_s str;
if( h->reqflags & (FLAG_XFERSTREAMING|FLAG_RANGE) )
{
@ -1415,20 +1424,14 @@ SendResp_albumArt(struct upnphttp * h, char * object)
size = lseek(fd, 0, SEEK_END);
lseek(fd, 0, SEEK_SET);
strftime(date, 30,"%a, %d %b %Y %H:%M:%S GMT" , gmtime(&curtime));
ret = snprintf(header, sizeof(header), "HTTP/1.1 200 OK\r\n"
"Content-Type: image/jpeg\r\n"
"Content-Length: %jd\r\n"
"Connection: close\r\n"
"Date: %s\r\n"
"EXT:\r\n"
"realTimeInfo.dlna.org: DLNA.ORG_TLAG=*\r\n"
"contentFeatures.dlna.org: DLNA.ORG_PN=JPEG_TN\r\n"
"Server: " MINIDLNA_SERVER_STRING "\r\n"
"transferMode.dlna.org: Interactive\r\n\r\n",
(intmax_t)size, date);
INIT_STR(str, header);
if( send_data(h, header, ret, MSG_MORE) == 0 )
start_dlna_header(&str, 200, "Interactive", "image/jpeg");
strcatf(&str, "Content-Length: %jd\r\n"
"contentFeatures.dlna.org: DLNA.ORG_PN=JPEG_TN\r\n\r\n",
(intmax_t)size);
if( send_data(h, str.data, str.off, MSG_MORE) == 0 )
{
if( h->req_command != EHead )
send_file(h, fd, 0, size-1);
@ -1442,11 +1445,10 @@ SendResp_caption(struct upnphttp * h, char * object)
{
char header[512];
char *path;
char date[30];
time_t curtime = time(NULL);
off_t size;
long long id;
int fd, ret;
int fd;
struct string_s str;
id = strtoll(object, NULL, 10);
@ -1470,17 +1472,12 @@ SendResp_caption(struct upnphttp * h, char * object)
size = lseek(fd, 0, SEEK_END);
lseek(fd, 0, SEEK_SET);
strftime(date, 30,"%a, %d %b %Y %H:%M:%S GMT" , gmtime(&curtime));
ret = snprintf(header, sizeof(header), "HTTP/1.1 200 OK\r\n"
"Content-Type: smi/caption\r\n"
"Content-Length: %jd\r\n"
"Connection: close\r\n"
"Date: %s\r\n"
"EXT:\r\n"
"Server: " MINIDLNA_SERVER_STRING "\r\n\r\n",
(intmax_t)size, date);
INIT_STR(str, header);
if( send_data(h, header, ret, MSG_MORE) == 0 )
start_dlna_header(&str, 200, "Interactive", "smi/caption");
strcatf(&str, "Content-Length: %jd\r\n\r\n", (intmax_t)size);
if( send_data(h, str.data, str.off, MSG_MORE) == 0 )
{
if( h->req_command != EHead )
send_file(h, fd, 0, size-1);
@ -1494,12 +1491,10 @@ SendResp_thumbnail(struct upnphttp * h, char * object)
{
char header[512];
char *path;
char date[30];
time_t curtime = time(NULL);
long long id;
int ret;
ExifData *ed;
ExifLoader *l;
struct string_s str;
if( h->reqflags & (FLAG_XFERSTREAMING|FLAG_RANGE) )
{
@ -1539,20 +1534,15 @@ SendResp_thumbnail(struct upnphttp * h, char * object)
exif_data_unref(ed);
return;
}
strftime(date, 30,"%a, %d %b %Y %H:%M:%S GMT" , gmtime(&curtime));
ret = snprintf(header, sizeof(header), "HTTP/1.1 200 OK\r\n"
"Content-Type: image/jpeg\r\n"
"Content-Length: %jd\r\n"
"Connection: close\r\n"
"Date: %s\r\n"
"EXT:\r\n"
"realTimeInfo.dlna.org: DLNA.ORG_TLAG=*\r\n"
"contentFeatures.dlna.org: DLNA.ORG_PN=JPEG_TN;DLNA.ORG_CI=1\r\n"
"Server: " MINIDLNA_SERVER_STRING "\r\n"
"transferMode.dlna.org: Interactive\r\n\r\n",
(intmax_t)ed->size, date);
if( send_data(h, header, ret, MSG_MORE) == 0 )
INIT_STR(str, header);
start_dlna_header(&str, 200, "Interactive", "image/jpeg");
strcatf(&str, "Content-Length: %jd\r\n"
"contentFeatures.dlna.org: DLNA.ORG_PN=JPEG_TN;DLNA.ORG_CI=1\r\n\r\n",
(intmax_t)ed->size);
if( send_data(h, str.data, str.off, MSG_MORE) == 0 )
{
if( h->req_command != EHead )
send_data(h, (char *)ed->data, ed->size, 0);
@ -1568,10 +1558,8 @@ SendResp_resizedimg(struct upnphttp * h, char * object)
char buf[128];
struct string_s str;
char **result;
char date[30];
char dlna_pn[22];
uint32_t dlna_flags = DLNA_FLAG_DLNA_V1_5|DLNA_FLAG_HTTP_STALLING|DLNA_FLAG_TM_B|DLNA_FLAG_TM_I;
time_t curtime = time(NULL);
int width=640, height=480, dstw, dsth, size;
int srcw, srch;
unsigned char * data = NULL;
@ -1586,6 +1574,7 @@ SendResp_resizedimg(struct upnphttp * h, char * object)
int rows=0, chunked, ret;
image_s *imsrc = NULL, *imdst = NULL;
int scale = 1;
const char *tmode;
id = strtoll(object, &saveptr, 10);
snprintf(buf, sizeof(buf), "SELECT PATH, RESOLUTION, ROTATION from DETAILS where ID = '%lld'", (long long)id);
@ -1706,26 +1695,17 @@ SendResp_resizedimg(struct upnphttp * h, char * object)
else if( srcw>>2 >= dstw && srch>>2 >= dsth )
scale = 2;
str.data = header;
str.size = sizeof(header);
str.off = 0;
INIT_STR(str, header);
strftime(date, 30,"%a, %d %b %Y %H:%M:%S GMT" , gmtime(&curtime));
strcatf(&str, "HTTP/1.1 200 OK\r\n"
"Content-Type: image/jpeg\r\n"
"Connection: close\r\n"
"Date: %s\r\n"
"EXT:\r\n"
"realTimeInfo.dlna.org: DLNA.ORG_TLAG=*\r\n"
"contentFeatures.dlna.org: %sDLNA.ORG_CI=%X;DLNA.ORG_FLAGS=%08X%024X\r\n"
"Server: " MINIDLNA_SERVER_STRING "\r\n",
date, dlna_pn, 1, dlna_flags, 0);
#if USE_FORK
if( (h->reqflags & FLAG_XFERBACKGROUND) && (setpriority(PRIO_PROCESS, 0, 19) == 0) )
strcatf(&str, "transferMode.dlna.org: Background\r\n");
tmode = "Background";
else
#endif
strcatf(&str, "transferMode.dlna.org: Interactive\r\n");
tmode = "Interactive";
start_dlna_header(&str, 200, tmode, "image/jpeg");
strcatf(&str, "contentFeatures.dlna.org: %sDLNA.ORG_CI=1;DLNA.ORG_FLAGS=%08X%024X\r\n",
dlna_pn, dlna_flags, 0);
if( strcmp(h->HttpVer, "HTTP/1.0") == 0 )
{
@ -1799,13 +1779,12 @@ SendResp_dlnafile(struct upnphttp *h, char *object)
char buf[128];
char **result;
int rows, ret;
char date[30];
time_t curtime = time(NULL);
off_t total, offset, size;
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 = h->req_client ? h->req_client->type->flags : 0;
const char *tmode;
enum client_types ctype = h->req_client ? h->req_client->type->type : 0;
static struct { int64_t id;
enum client_types client;
@ -1934,14 +1913,20 @@ SendResp_dlnafile(struct upnphttp *h, char *object)
size = lseek(sendfh, 0, SEEK_END);
lseek(sendfh, 0, SEEK_SET);
str.data = header;
str.size = sizeof(header);
str.off = 0;
INIT_STR(str, header);
#if USE_FORK
if( (h->reqflags & FLAG_XFERBACKGROUND) && (setpriority(PRIO_PROCESS, 0, 19) == 0) )
tmode = "Background";
else
#endif
if( strncmp(last_file.mime, "image", 5) == 0 )
tmode = "Interactive";
else
tmode = "Streaming";
start_dlna_header(&str, (h->reqflags & FLAG_RANGE ? 206 : 200), tmode, last_file.mime);
strcatf(&str, "HTTP/1.1 20%c OK\r\n"
"Content-Type: %s\r\n",
(h->reqflags & FLAG_RANGE ? '6' : '0'),
last_file.mime);
if( h->reqflags & FLAG_RANGE )
{
if( !h->req_RangeEnd || h->req_RangeEnd == size )
@ -1976,16 +1961,6 @@ SendResp_dlnafile(struct upnphttp *h, char *object)
strcatf(&str, "Content-Length: %jd\r\n", (intmax_t)total);
}
#if USE_FORK
if( (h->reqflags & FLAG_XFERBACKGROUND) && (setpriority(PRIO_PROCESS, 0, 19) == 0) )
strcatf(&str, "transferMode.dlna.org: Background\r\n");
else
#endif
if( strncmp(last_file.mime, "image", 5) == 0 )
strcatf(&str, "transferMode.dlna.org: Interactive\r\n");
else
strcatf(&str, "transferMode.dlna.org: Streaming\r\n");
switch( *last_file.mime )
{
case 'i':
@ -2005,15 +1980,9 @@ SendResp_dlnafile(struct upnphttp *h, char *object)
lan_addr[h->iface].str, runtime_vars.port, (long long)id);
}
strftime(date, 30,"%a, %d %b %Y %H:%M:%S GMT" , gmtime(&curtime));
strcatf(&str, "Accept-Ranges: bytes\r\n"
"Connection: close\r\n"
"Date: %s\r\n"
"EXT:\r\n"
"realTimeInfo.dlna.org: DLNA.ORG_TLAG=*\r\n"
"contentFeatures.dlna.org: %sDLNA.ORG_OP=%02X;DLNA.ORG_CI=%X;DLNA.ORG_FLAGS=%08X%024X\r\n"
"Server: " MINIDLNA_SERVER_STRING "\r\n\r\n",
date, last_file.dlna, 1, 0, dlna_flags, 0);
"contentFeatures.dlna.org: %sDLNA.ORG_OP=%02X;DLNA.ORG_CI=%X;DLNA.ORG_FLAGS=%08X%024X\r\n\r\n",
last_file.dlna, 1, 0, dlna_flags, 0);
//DEBUG DPRINTF(E_DEBUG, L_HTTP, "RESPONSE: %s\n", str.data);
if( send_data(h, str.data, str.off, MSG_MORE) == 0 )