"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "upnphttp.c" between
minidlna-1.2.1.tar.gz and minidlna-1.3.0.tar.gz

About: ReadyMedia (formerly known as MiniDLNA) is a simple media server software, with the aim of being fully compliant with DLNA/UPnP-AV clients.

upnphttp.c  (minidlna-1.2.1):upnphttp.c  (minidlna-1.3.0)
skipping to change at line 67 skipping to change at line 67
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <fcntl.h> #include <fcntl.h>
#include <errno.h> #include <errno.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/resource.h> #include <sys/resource.h>
#include <limits.h> #include <limits.h>
#include "config.h" #include "config.h"
#include "event.h"
#include "upnpglobalvars.h" #include "upnpglobalvars.h"
#include "upnphttp.h" #include "upnphttp.h"
#include "upnpdescgen.h" #include "upnpdescgen.h"
#include "minidlnapath.h" #include "minidlnapath.h"
#include "upnpsoap.h" #include "upnpsoap.h"
#include "upnpevents.h" #include "upnpevents.h"
#include "utils.h" #include "utils.h"
#include "getifaddr.h" #include "getifaddr.h"
#include "image_utils.h" #include "image_utils.h"
#include "log.h" #include "log.h"
skipping to change at line 104 skipping to change at line 105
E_SUBSCRIBE, E_SUBSCRIBE,
E_RENEW E_RENEW
}; };
static void SendResp_icon(struct upnphttp *, char * url); static void SendResp_icon(struct upnphttp *, char * url);
static void SendResp_albumArt(struct upnphttp *, char * url); static void SendResp_albumArt(struct upnphttp *, char * url);
static void SendResp_caption(struct upnphttp *, char * url); static void SendResp_caption(struct upnphttp *, char * url);
static void SendResp_resizedimg(struct upnphttp *, char * url); static void SendResp_resizedimg(struct upnphttp *, char * url);
static void SendResp_thumbnail(struct upnphttp *, char * url); static void SendResp_thumbnail(struct upnphttp *, char * url);
static void SendResp_dlnafile(struct upnphttp *, char * url); static void SendResp_dlnafile(struct upnphttp *, char * url);
static void Process_upnphttp(struct event *ev);
struct upnphttp * struct upnphttp *
New_upnphttp(int s) New_upnphttp(int s)
{ {
struct upnphttp * ret; struct upnphttp * ret;
if(s<0) if(s<0)
return NULL; return NULL;
ret = (struct upnphttp *)malloc(sizeof(struct upnphttp)); ret = (struct upnphttp *)malloc(sizeof(struct upnphttp));
if(ret == NULL) if(ret == NULL)
return NULL; return NULL;
memset(ret, 0, sizeof(struct upnphttp)); memset(ret, 0, sizeof(struct upnphttp));
ret->socket = s; ret->ev = (struct event ){ .fd = s, .rdwr = EVENT_READ, .process = Proces
s_upnphttp, .data = ret };
event_module.add(&ret->ev);
return ret; return ret;
} }
void void
CloseSocket_upnphttp(struct upnphttp * h) CloseSocket_upnphttp(struct upnphttp * h)
{ {
if(close(h->socket) < 0)
event_module.del(&h->ev, EV_FLAG_CLOSING);
if(close(h->ev.fd) < 0)
{ {
DPRINTF(E_ERROR, L_HTTP, "CloseSocket_upnphttp: close(%d): %s\n", h->socket, strerror(errno)); DPRINTF(E_ERROR, L_HTTP, "CloseSocket_upnphttp: close(%d): %s\n", h->ev.fd, strerror(errno));
} }
h->socket = -1; h->ev.fd = -1;
h->state = 100; h->state = 100;
} }
void void
Delete_upnphttp(struct upnphttp * h) Delete_upnphttp(struct upnphttp * h)
{ {
if(h) if(h)
{ {
if(h->socket >= 0) if(h->ev.fd >= 0)
CloseSocket_upnphttp(h); CloseSocket_upnphttp(h);
free(h->req_buf); free(h->req_buf);
free(h->res_buf); free(h->res_buf);
free(h); free(h);
} }
} }
/* parse HttpHeaders of the REQUEST */ /* parse HttpHeaders of the REQUEST */
static void static void
ParseHttpHeaders(struct upnphttp * h) ParseHttpHeaders(struct upnphttp * h)
skipping to change at line 271 skipping to change at line 276
h->req_RangeEnd ? (long long)h->r eq_RangeEnd : -1); h->req_RangeEnd ? (long long)h->r eq_RangeEnd : -1);
} }
} }
else if(strncasecmp(line, "Host", 4)==0) else if(strncasecmp(line, "Host", 4)==0)
{ {
int i; int i;
h->reqflags |= FLAG_HOST; h->reqflags |= FLAG_HOST;
p = colon + 1; p = colon + 1;
while(isspace(*p)) while(isspace(*p))
p++; p++;
for(n = 0; n<n_lan_addr; n++) for(n = 0; n < n_lan_addr; n++)
{ {
for(i=0; lan_addr[n].str[i]; i++) for(i = 0; lan_addr[n].str[i]; i++)
{ {
if(lan_addr[n].str[i] != p[i]) if(lan_addr[n].str[i] != p[i])
break; break;
} }
if(!lan_addr[n].str[i]) if(i && !lan_addr[n].str[i])
{ {
h->iface = n; h->iface = n;
break; break;
} }
} }
} }
else if(strncasecmp(line, "User-Agent", 10)==0) else if(strncasecmp(line, "User-Agent", 10)==0)
{ {
int i; int i;
/* Skip client detection if we already detected i t. */ /* Skip client detection if we already detected i t. */
skipping to change at line 418 skipping to change at line 423
/* Conformance testing */ /* Conformance testing */
SETFLAG(DLNA_STRICT_MASK); SETFLAG(DLNA_STRICT_MASK);
} }
} }
next_header: next_header:
line = strstr(line, "\r\n"); line = strstr(line, "\r\n");
if (!line) if (!line)
return; return;
line += 2; line += 2;
} }
if( h->reqflags & FLAG_CHUNKED ) if (h->reqflags & FLAG_CHUNKED)
{ {
char *endptr; char *endptr;
h->req_chunklen = -1; h->req_chunklen = -1;
if( h->req_buflen <= h->req_contentoff ) if (h->req_buflen <= h->req_contentoff)
return; return;
while( (line < (h->req_buf + h->req_buflen)) && while( (line < (h->req_buf + h->req_buflen)) &&
(h->req_chunklen = strtol(line, &endptr, 16)) && (h->req_chunklen = strtol(line, &endptr, 16) > 0) &&
(endptr != line) ) (endptr != line) )
{ {
endptr = strstr(endptr, "\r\n"); endptr = strstr(endptr, "\r\n");
if (!endptr) if (!endptr)
{ {
return; return;
} }
line = endptr+h->req_chunklen+2; line = endptr+h->req_chunklen+2;
} }
skipping to change at line 697 skipping to change at line 702
else else
{ {
/* waiting for remaining data */ /* waiting for remaining data */
h->state = 1; h->state = 1;
} }
} }
static int static int
check_event(struct upnphttp *h) check_event(struct upnphttp *h)
{ {
enum event_type type; enum event_type type = E_INVALID;
if (h->req_Callback) if (h->req_Callback)
{ {
if (h->req_SID || !h->req_NT) if (h->req_SID || !h->req_NT)
{ {
BuildResp2_upnphttp(h, 400, "Bad Request", BuildResp2_upnphttp(h, 400, "Bad Request",
"<html><body>Bad request</body></html >", 37); "<html><body>Bad request</body></html >", 37);
type = E_INVALID;
} }
else if (strncmp(h->req_Callback, "http://", 7) != 0 || else if (strncmp(h->req_Callback, "http://", 7) != 0 ||
strncmp(h->req_NT, "upnp:event", h->req_NTLen) != 0) strncmp(h->req_NT, "upnp:event", h->req_NTLen) != 0)
{ {
/* Missing or invalid CALLBACK : 412 Precondition Failed. /* Missing or invalid CALLBACK : 412 Precondition Failed.
* If CALLBACK header is missing or does not contain a va lid HTTP URL, * If CALLBACK header is missing or does not contain a va lid HTTP URL,
* the publisher must respond with HTTP error 412 Precond ition Failed*/ * the publisher must respond with HTTP error 412 Precond ition Failed*/
BuildResp2_upnphttp(h, 412, "Precondition Failed", 0, 0); BuildResp2_upnphttp(h, 412, "Precondition Failed", 0, 0);
type = E_INVALID;
} }
else else
type = E_SUBSCRIBE; {
/* Make sure callback URL points to the originating IP */
struct in_addr addr;
char addrstr[16];
int i = 0;
const char *p = h->req_Callback + 7;
while (!strchr("/:>", *p) && i < sizeof(addrstr) - 1 &&
p < (h->req_Callback + h->req_CallbackLen))
{
addrstr[i++] = *(p++);
}
addrstr[i] = '\0';
if (inet_pton(AF_INET, addrstr, &addr) <= 0 ||
memcmp(&addr, &h->clientaddr, sizeof(struct in_addr))
)
{
DPRINTF(E_ERROR, L_HTTP, "Bad callback IP (%s)\n"
, addrstr);
BuildResp2_upnphttp(h, 412, "Precondition Failed"
, 0, 0);
}
else
type = E_SUBSCRIBE;
}
} }
else if (h->req_SID) else if (h->req_SID)
{ {
/* subscription renew */ /* subscription renew */
if (h->req_NT) if (h->req_NT)
{ {
BuildResp2_upnphttp(h, 400, "Bad Request", BuildResp2_upnphttp(h, 400, "Bad Request",
"<html><body>Bad request</body></html >", 37); "<html><body>Bad request</body></html >", 37);
type = E_INVALID;
} }
else else
type = E_RENEW; type = E_RENEW;
} }
else else
{ {
BuildResp2_upnphttp(h, 412, "Precondition Failed", 0, 0); BuildResp2_upnphttp(h, 412, "Precondition Failed", 0, 0);
type = E_INVALID;
} }
return type; return type;
} }
static void static void
ProcessHTTPSubscribe_upnphttp(struct upnphttp * h, const char * path) ProcessHTTPSubscribe_upnphttp(struct upnphttp * h, const char * path)
{ {
const char * sid; const char * sid;
enum event_type type; enum event_type type;
skipping to change at line 869 skipping to change at line 891
return; return;
} }
if( h->req_chunklen ) if( h->req_chunklen )
{ {
h->state = 2; h->state = 2;
return; return;
} }
char *chunkstart, *chunk, *endptr, *endbuf; char *chunkstart, *chunk, *endptr, *endbuf;
chunk = endbuf = chunkstart = h->req_buf + h->req_contentoff; chunk = endbuf = chunkstart = h->req_buf + h->req_contentoff;
while( (h->req_chunklen = strtol(chunk, &endptr, 16)) && (endptr != chunk) ) while ((h->req_chunklen = strtol(chunk, &endptr, 16)) > 0 && (end ptr != chunk) )
{ {
endptr = strstr(endptr, "\r\n"); endptr = strstr(endptr, "\r\n");
if (!endptr) if (!endptr)
{ {
Send400(h); Send400(h);
return; return;
} }
endptr += 2; endptr += 2;
memmove(endbuf, endptr, h->req_chunklen); memmove(endbuf, endptr, h->req_chunklen);
skipping to change at line 1042 skipping to change at line 1064
h->req_command = EUnSubscribe; h->req_command = EUnSubscribe;
ProcessHTTPUnSubscribe_upnphttp(h, HttpUrl); ProcessHTTPUnSubscribe_upnphttp(h, HttpUrl);
} }
else else
{ {
DPRINTF(E_WARN, L_HTTP, "Unsupported HTTP Command %s\n", HttpComm and); DPRINTF(E_WARN, L_HTTP, "Unsupported HTTP Command %s\n", HttpComm and);
Send501(h); Send501(h);
} }
} }
void static void
Process_upnphttp(struct upnphttp * h) Process_upnphttp(struct event *ev)
{ {
char buf[2048]; char buf[2048];
struct upnphttp *h = ev->data;
int n; int n;
if(!h)
return;
switch(h->state) switch(h->state)
{ {
case 0: case 0:
n = recv(h->socket, buf, 2048, 0); n = recv(h->ev.fd, buf, 2048, 0);
if(n<0) if(n<0)
{ {
DPRINTF(E_ERROR, L_HTTP, "recv (state0): %s\n", strerror( errno)); DPRINTF(E_ERROR, L_HTTP, "recv (state0): %s\n", strerror( errno));
h->state = 100; h->state = 100;
} }
else if(n==0) else if(n==0)
{ {
DPRINTF(E_WARN, L_HTTP, "HTTP Connection closed unexpecte dly\n"); DPRINTF(E_DEBUG, L_HTTP, "HTTP Connection closed unexpect edly\n");
h->state = 100; h->state = 100;
} }
else else
{ {
int new_req_buflen; int new_req_buflen;
const char * endheaders; const char * endheaders;
/* if 1st arg of realloc() is null, /* if 1st arg of realloc() is null,
* realloc behaves the same as malloc() */ * realloc behaves the same as malloc() */
new_req_buflen = n + h->req_buflen + 1; new_req_buflen = n + h->req_buflen + 1;
if (new_req_buflen >= 1024 * 1024) if (new_req_buflen >= 1024 * 1024)
skipping to change at line 1098 skipping to change at line 1120
if(endheaders) if(endheaders)
{ {
h->req_contentoff = endheaders - h->req_buf + 4; h->req_contentoff = endheaders - h->req_buf + 4;
h->req_contentlen = h->req_buflen - h->req_conten toff; h->req_contentlen = h->req_buflen - h->req_conten toff;
ProcessHttpQuery_upnphttp(h); ProcessHttpQuery_upnphttp(h);
} }
} }
break; break;
case 1: case 1:
case 2: case 2:
n = recv(h->socket, buf, sizeof(buf), 0); n = recv(h->ev.fd, buf, sizeof(buf), 0);
if(n < 0) if(n < 0)
{ {
DPRINTF(E_ERROR, L_HTTP, "recv (state%d): %s\n", h->state , strerror(errno)); DPRINTF(E_ERROR, L_HTTP, "recv (state%d): %s\n", h->state , strerror(errno));
h->state = 100; h->state = 100;
} }
else if(n == 0) else if(n == 0)
{ {
DPRINTF(E_WARN, L_HTTP, "HTTP Connection closed unexpecte dly\n"); DPRINTF(E_DEBUG, L_HTTP, "HTTP Connection closed unexpect edly\n");
h->state = 100; h->state = 100;
} }
else else
{ {
buf[sizeof(buf)-1] = '\0'; buf[sizeof(buf)-1] = '\0';
/*fwrite(buf, 1, n, stdout);*/ /* debug */ /*fwrite(buf, 1, n, stdout);*/ /* debug */
h->req_buf = (char *)realloc(h->req_buf, n + h->req_bufle n); h->req_buf = (char *)realloc(h->req_buf, n + h->req_bufle n);
if (!h->req_buf) if (!h->req_buf)
{ {
DPRINTF(E_ERROR, L_HTTP, "Receive request body: % s\n", strerror(errno)); DPRINTF(E_ERROR, L_HTTP, "Receive request body: % s\n", strerror(errno));
skipping to change at line 1225 skipping to change at line 1247
BuildResp_upnphttp(struct upnphttp *h, const char *body, int bodylen) BuildResp_upnphttp(struct upnphttp *h, const char *body, int bodylen)
{ {
BuildResp2_upnphttp(h, 200, "OK", body, bodylen); BuildResp2_upnphttp(h, 200, "OK", body, bodylen);
} }
void void
SendResp_upnphttp(struct upnphttp * h) SendResp_upnphttp(struct upnphttp * h)
{ {
int n; int n;
DPRINTF(E_DEBUG, L_HTTP, "HTTP RESPONSE: %.*s\n", h->res_buflen, h->res_b uf); DPRINTF(E_DEBUG, L_HTTP, "HTTP RESPONSE: %.*s\n", h->res_buflen, h->res_b uf);
n = send(h->socket, h->res_buf, h->res_buflen, 0); n = send(h->ev.fd, h->res_buf, h->res_buflen, 0);
if(n<0) if(n<0)
{ {
DPRINTF(E_ERROR, L_HTTP, "send(res_buf): %s\n", strerror(errno)); DPRINTF(E_ERROR, L_HTTP, "send(res_buf): %s\n", strerror(errno));
} }
else if(n < h->res_buflen) else if(n < h->res_buflen)
{ {
/* TODO : handle correctly this case */ /* TODO : handle correctly this case */
DPRINTF(E_ERROR, L_HTTP, "send(res_buf): %d bytes sent (out of %d )\n", DPRINTF(E_ERROR, L_HTTP, "send(res_buf): %d bytes sent (out of %d )\n",
n, h->res_buflen); n, h->res_buflen);
} }
} }
static int static int
send_data(struct upnphttp * h, char * header, size_t size, int flags) send_data(struct upnphttp * h, char * header, size_t size, int flags)
{ {
int n; int n;
n = send(h->socket, header, size, flags); n = send(h->ev.fd, header, size, flags);
if(n<0) if(n<0)
{ {
DPRINTF(E_ERROR, L_HTTP, "send(res_buf): %s\n", strerror(errno)); DPRINTF(E_ERROR, L_HTTP, "send(res_buf): %s\n", strerror(errno));
} }
else if(n < h->res_buflen) else if(n < h->res_buflen)
{ {
/* TODO : handle correctly this case */ /* TODO : handle correctly this case */
DPRINTF(E_ERROR, L_HTTP, "send(res_buf): %d bytes sent (out of %d )\n", DPRINTF(E_ERROR, L_HTTP, "send(res_buf): %d bytes sent (out of %d )\n",
n, h->res_buflen); n, h->res_buflen);
} }
skipping to change at line 1277 skipping to change at line 1299
#if HAVE_SENDFILE #if HAVE_SENDFILE
int try_sendfile = 1; int try_sendfile = 1;
#endif #endif
while( offset <= end_offset ) while( offset <= end_offset )
{ {
#if HAVE_SENDFILE #if HAVE_SENDFILE
if( try_sendfile ) if( try_sendfile )
{ {
send_size = ( ((end_offset - offset) < MAX_BUFFER_SIZE) ? (end_offset - offset + 1) : MAX_BUFFER_SIZE); send_size = ( ((end_offset - offset) < MAX_BUFFER_SIZE) ? (end_offset - offset + 1) : MAX_BUFFER_SIZE);
ret = sys_sendfile(h->socket, sendfd, &offset, send_size) ; ret = sys_sendfile(h->ev.fd, sendfd, &offset, send_size);
if( ret == -1 ) if( ret == -1 )
{ {
DPRINTF(E_DEBUG, L_HTTP, "sendfile error :: error no. %d [%s]\n", errno, strerror(errno)); DPRINTF(E_DEBUG, L_HTTP, "sendfile error :: error no. %d [%s]\n", errno, strerror(errno));
/* If sendfile isn't supported on the filesystem, don't bother trying to use it again. */ /* If sendfile isn't supported on the filesystem, don't bother trying to use it again. */
if( errno == EOVERFLOW || errno == EINVAL ) if( errno == EOVERFLOW || errno == EINVAL )
try_sendfile = 0; try_sendfile = 0;
else if( errno != EAGAIN ) else if( errno != EAGAIN )
break; break;
} }
else else
skipping to change at line 1307 skipping to change at line 1329
send_size = (((end_offset - offset) < MIN_BUFFER_SIZE) ? (end_off set - offset + 1) : MIN_BUFFER_SIZE); send_size = (((end_offset - offset) < MIN_BUFFER_SIZE) ? (end_off set - offset + 1) : MIN_BUFFER_SIZE);
lseek(sendfd, offset, SEEK_SET); lseek(sendfd, offset, SEEK_SET);
ret = read(sendfd, buf, send_size); ret = read(sendfd, buf, send_size);
if( ret == -1 ) { if( ret == -1 ) {
DPRINTF(E_DEBUG, L_HTTP, "read error :: error no. %d [%s] \n", errno, strerror(errno)); DPRINTF(E_DEBUG, L_HTTP, "read error :: error no. %d [%s] \n", errno, strerror(errno));
if( errno == EAGAIN ) if( errno == EAGAIN )
continue; continue;
else else
break; break;
} }
ret = write(h->socket, buf, ret); ret = write(h->ev.fd, buf, ret);
if( ret == -1 ) { if( ret == -1 ) {
DPRINTF(E_DEBUG, L_HTTP, "write error :: error no. %d [%s ]\n", errno, strerror(errno)); DPRINTF(E_DEBUG, L_HTTP, "write error :: error no. %d [%s ]\n", errno, strerror(errno));
if( errno == EAGAIN ) if( errno == EAGAIN )
continue; continue;
else else
break; break;
} }
offset += ret; offset += ret;
} }
free(buf); free(buf);
skipping to change at line 1622 skipping to change at line 1644
char **result; char **result;
char dlna_pn[22]; char dlna_pn[22];
uint32_t dlna_flags = DLNA_FLAG_DLNA_V1_5|DLNA_FLAG_HTTP_STALLING|DLNA_FL AG_TM_B|DLNA_FLAG_TM_I; uint32_t dlna_flags = DLNA_FLAG_DLNA_V1_5|DLNA_FLAG_HTTP_STALLING|DLNA_FL AG_TM_B|DLNA_FLAG_TM_I;
int width=640, height=480, dstw, dsth, size; int width=640, height=480, dstw, dsth, size;
int srcw, srch; int srcw, srch;
unsigned char * data = NULL; unsigned char * data = NULL;
char *path, *file_path = NULL; char *path, *file_path = NULL;
char *resolution = NULL; char *resolution = NULL;
char *key, *val; char *key, *val;
char *saveptr, *item = NULL; char *saveptr, *item = NULL;
int rotate; int rotate = 0;
int pixw = 0, pixh = 0; int pixw = 0, pixh = 0;
long long id; long long id;
int rows=0, chunked, ret; int rows=0, chunked, ret;
image_s *imsrc = NULL, *imdst = NULL; image_s *imsrc = NULL, *imdst = NULL;
int scale = 1; int scale = 1;
const char *tmode; const char *tmode;
id = strtoll(object, &saveptr, 10); id = strtoll(object, &saveptr, 10);
snprintf(buf, sizeof(buf), "SELECT PATH, RESOLUTION, ROTATION from DETAIL S where ID = '%lld'", (long long)id); snprintf(buf, sizeof(buf), "SELECT PATH, RESOLUTION, ROTATION from DETAIL S where ID = '%lld'", (long long)id);
ret = sql_get_table(db, buf, &result, &rows, NULL); ret = sql_get_table(db, buf, &result, &rows, NULL);
if( ret != SQLITE_OK ) if( ret != SQLITE_OK )
{ {
Send500(h); Send500(h);
return; return;
} }
if( rows ) if( rows )
{ {
file_path = result[3]; file_path = result[3];
resolution = result[4]; resolution = result[4];
rotate = result[5] ? atoi(result[5]) : 0; if (result[5])
rotate = atoi(result[5]);
} }
if( !file_path || !resolution || (access(file_path, F_OK) != 0) ) if( !file_path || !resolution || (access(file_path, F_OK) != 0) )
{ {
DPRINTF(E_WARN, L_HTTP, "%s not found, responding ERROR 404\n", o bject); DPRINTF(E_WARN, L_HTTP, "%s not found, responding ERROR 404\n", o bject);
sqlite3_free_table(result); sqlite3_free_table(result);
Send404(h); Send404(h);
return; return;
} }
if( saveptr ) if( saveptr )
 End of changes. 33 change blocks. 
32 lines changed or deleted 59 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)