* Use our own logging mechanism instead of syslog/printf.
This commit is contained in:
parent
69965b876e
commit
45f294b404
28
Makefile
28
Makefile
@ -28,7 +28,8 @@ BASEOBJS = minidlna.o upnphttp.o upnpdescgen.o upnpsoap.o \
|
|||||||
upnpreplyparse.o minixml.o \
|
upnpreplyparse.o minixml.o \
|
||||||
getifaddr.o daemonize.o upnpglobalvars.o \
|
getifaddr.o daemonize.o upnpglobalvars.o \
|
||||||
options.o minissdp.o upnpevents.o \
|
options.o minissdp.o upnpevents.o \
|
||||||
sql.o utils.o metadata.o albumart.o scanner.o inotify.o
|
sql.o utils.o metadata.o albumart.o scanner.o inotify.o \
|
||||||
|
log.o
|
||||||
|
|
||||||
ALLOBJS = $(BASEOBJS) $(LNXOBJS)
|
ALLOBJS = $(BASEOBJS) $(LNXOBJS)
|
||||||
|
|
||||||
@ -78,26 +79,29 @@ depend: config.h
|
|||||||
minidlna.o: config.h upnpglobalvars.h minidlnatypes.h
|
minidlna.o: config.h upnpglobalvars.h minidlnatypes.h
|
||||||
minidlna.o: upnphttp.h upnpdescgen.h minidlnapath.h getifaddr.h upnpsoap.h
|
minidlna.o: upnphttp.h upnpdescgen.h minidlnapath.h getifaddr.h upnpsoap.h
|
||||||
minidlna.o: options.h minissdp.h daemonize.h upnpevents.h
|
minidlna.o: options.h minissdp.h daemonize.h upnpevents.h
|
||||||
minidlna.o: commonrdr.h
|
minidlna.o: commonrdr.h log.h
|
||||||
upnphttp.o: config.h upnphttp.h upnpdescgen.h minidlnapath.h upnpsoap.h
|
upnphttp.o: config.h upnphttp.h upnpdescgen.h minidlnapath.h upnpsoap.h
|
||||||
upnphttp.o: upnpevents.h
|
upnphttp.o: upnpevents.h log.h
|
||||||
upnpdescgen.o: config.h upnpdescgen.h minidlnapath.h upnpglobalvars.h
|
upnpdescgen.o: config.h upnpdescgen.h minidlnapath.h upnpglobalvars.h
|
||||||
upnpdescgen.o: minidlnatypes.h upnpdescstrings.h
|
upnpdescgen.o: minidlnatypes.h upnpdescstrings.h log.h
|
||||||
upnpsoap.o: config.h upnpglobalvars.h minidlnatypes.h
|
upnpsoap.o: config.h upnpglobalvars.h minidlnatypes.h log.h utils.h sql.h
|
||||||
upnpsoap.o: upnphttp.h upnpsoap.h upnpreplyparse.h getifaddr.h
|
upnpsoap.o: upnphttp.h upnpsoap.h upnpreplyparse.h getifaddr.h log.h
|
||||||
upnpreplyparse.o: upnpreplyparse.h minixml.h
|
upnpreplyparse.o: upnpreplyparse.h minixml.h log.h
|
||||||
minixml.o: minixml.h
|
minixml.o: minixml.h
|
||||||
getifaddr.o: getifaddr.h
|
getifaddr.o: getifaddr.h log.h
|
||||||
daemonize.o: daemonize.h config.h
|
daemonize.o: daemonize.h config.h log.h
|
||||||
upnpglobalvars.o: config.h upnpglobalvars.h
|
upnpglobalvars.o: config.h upnpglobalvars.h
|
||||||
upnpglobalvars.o: minidlnatypes.h
|
upnpglobalvars.o: minidlnatypes.h
|
||||||
options.o: options.h config.h upnpglobalvars.h
|
options.o: options.h config.h upnpglobalvars.h
|
||||||
options.o: minidlnatypes.h
|
options.o: minidlnatypes.h
|
||||||
minissdp.o: config.h upnpdescstrings.h minidlnapath.h upnphttp.h
|
minissdp.o: config.h upnpdescstrings.h minidlnapath.h upnphttp.h
|
||||||
minissdp.o: upnpglobalvars.h minidlnatypes.h minissdp.h
|
minissdp.o: upnpglobalvars.h minidlnatypes.h minissdp.h log.h
|
||||||
upnpevents.o: config.h upnpevents.h minidlnapath.h upnpglobalvars.h
|
upnpevents.o: config.h upnpevents.h minidlnapath.h upnpglobalvars.h
|
||||||
upnpevents.o: minidlnatypes.h upnpdescgen.h
|
upnpevents.o: minidlnatypes.h upnpdescgen.h log.h
|
||||||
netfilter/iptcrdr.o: netfilter/iptcrdr.h commonrdr.h config.h
|
|
||||||
testupnpdescgen.o: config.h upnpdescgen.h
|
testupnpdescgen.o: config.h upnpdescgen.h
|
||||||
upnpdescgen.o: config.h upnpdescgen.h minidlnapath.h upnpglobalvars.h
|
upnpdescgen.o: config.h upnpdescgen.h minidlnapath.h upnpglobalvars.h
|
||||||
upnpdescgen.o: minidlnatypes.h upnpdescstrings.h
|
upnpdescgen.o: minidlnatypes.h upnpdescstrings.h
|
||||||
|
scanner.o: upnpglobalvars.h metadata.h utils.h sql.h scanner.h log.h
|
||||||
|
metadata.o: upnpglobalvars.h metadata.h albumart.h utils.h sql.h log.h
|
||||||
|
sql.o: sql.h
|
||||||
|
log.o: log.h
|
||||||
|
11
daemonize.c
11
daemonize.c
@ -11,12 +11,13 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <syslog.h>
|
#include <errno.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
#include "daemonize.h"
|
#include "daemonize.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
#ifndef USE_DAEMON
|
#ifndef USE_DAEMON
|
||||||
|
|
||||||
@ -72,22 +73,22 @@ writepidfile(const char * fname, int pid)
|
|||||||
|
|
||||||
if( (pidfile = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666)) < 0)
|
if( (pidfile = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666)) < 0)
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR, "Unable to open pidfile for writing %s: %m", fname);
|
DPRINTF(E_ERROR, L_GENERAL, "Unable to open pidfile for writing %s: %s\n", fname, strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
pidstringlen = snprintf(pidstring, sizeof(pidstring), "%d\n", pid);
|
pidstringlen = snprintf(pidstring, sizeof(pidstring), "%d\n", pid);
|
||||||
if(pidstringlen <= 0)
|
if(pidstringlen <= 0)
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR,
|
DPRINTF(E_ERROR, L_GENERAL,
|
||||||
"Unable to write to pidfile %s: snprintf(): FAILED", fname);
|
"Unable to write to pidfile %s: snprintf(): FAILED\n", fname);
|
||||||
close(pidfile);
|
close(pidfile);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(write(pidfile, pidstring, pidstringlen) < 0)
|
if(write(pidfile, pidstring, pidstringlen) < 0)
|
||||||
syslog(LOG_ERR, "Unable to write to pidfile %s: %m", fname);
|
DPRINTF(E_ERROR, L_GENERAL, "Unable to write to pidfile %s: %s\n", fname, strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
close(pidfile);
|
close(pidfile);
|
||||||
|
@ -12,8 +12,6 @@ CONFIGMACRO="__CONFIG_H__"
|
|||||||
|
|
||||||
# version reported in XML descriptions
|
# version reported in XML descriptions
|
||||||
UPNP_VERSION=20070827
|
UPNP_VERSION=20070827
|
||||||
# Facility to syslog
|
|
||||||
LOG_MINIDLNA="LOG_DAEMON"
|
|
||||||
# Database path
|
# Database path
|
||||||
DB_PATH="/tmp/minidlna"
|
DB_PATH="/tmp/minidlna"
|
||||||
|
|
||||||
@ -117,10 +115,6 @@ echo "/* full path of the file database */" >> ${CONFIGFILE}
|
|||||||
echo "#define DB_PATH \"${DB_PATH}\"" >> ${CONFIGFILE}
|
echo "#define DB_PATH \"${DB_PATH}\"" >> ${CONFIGFILE}
|
||||||
echo "" >> ${CONFIGFILE}
|
echo "" >> ${CONFIGFILE}
|
||||||
|
|
||||||
echo "/* syslog facility to be used by miniupnpd */" >> ${CONFIGFILE}
|
|
||||||
echo "#define LOG_MINIDLNA ${LOG_MINIDLNA}" >> ${CONFIGFILE}
|
|
||||||
echo "" >> ${CONFIGFILE}
|
|
||||||
|
|
||||||
echo "/* Uncomment the following line to allow miniupnpd to be" >> ${CONFIGFILE}
|
echo "/* Uncomment the following line to allow miniupnpd to be" >> ${CONFIGFILE}
|
||||||
echo " * controlled by miniupnpdctl */" >> ${CONFIGFILE}
|
echo " * controlled by miniupnpdctl */" >> ${CONFIGFILE}
|
||||||
echo "/*#define USE_MINIUPNPDCTL*/" >> ${CONFIGFILE}
|
echo "/*#define USE_MINIUPNPDCTL*/" >> ${CONFIGFILE}
|
||||||
|
15
getifaddr.c
15
getifaddr.c
@ -8,7 +8,6 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <syslog.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
@ -17,11 +16,13 @@
|
|||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
|
#include <errno.h>
|
||||||
#if defined(sun)
|
#if defined(sun)
|
||||||
#include <sys/sockio.h>
|
#include <sys/sockio.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "getifaddr.h"
|
#include "getifaddr.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
int
|
int
|
||||||
getifaddr(const char * ifname, char * buf, int len)
|
getifaddr(const char * ifname, char * buf, int len)
|
||||||
@ -35,20 +36,20 @@ getifaddr(const char * ifname, char * buf, int len)
|
|||||||
s = socket(PF_INET, SOCK_DGRAM, 0);
|
s = socket(PF_INET, SOCK_DGRAM, 0);
|
||||||
if(s < 0)
|
if(s < 0)
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR, "socket(PF_INET, SOCK_DGRAM): %m");
|
DPRINTF(E_ERROR, L_GENERAL, "socket(PF_INET, SOCK_DGRAM): %s\n", strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
|
strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
|
||||||
if(ioctl(s, SIOCGIFADDR, &ifr, &ifrlen) < 0)
|
if(ioctl(s, SIOCGIFADDR, &ifr, &ifrlen) < 0)
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR, "ioctl(s, SIOCGIFADDR, ...): %m");
|
DPRINTF(E_ERROR, L_GENERAL, "ioctl(s, SIOCGIFADDR, ...): %s\n", strerror(errno));
|
||||||
close(s);
|
close(s);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
addr = (struct sockaddr_in *)&ifr.ifr_addr;
|
addr = (struct sockaddr_in *)&ifr.ifr_addr;
|
||||||
if(!inet_ntop(AF_INET, &addr->sin_addr, buf, len))
|
if(!inet_ntop(AF_INET, &addr->sin_addr, buf, len))
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR, "inet_ntop(): %m");
|
DPRINTF(E_ERROR, L_GENERAL, "inet_ntop(): %s\n", strerror(errno));
|
||||||
close(s);
|
close(s);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -76,7 +77,7 @@ getsysaddr(char * buf, int len)
|
|||||||
continue;
|
continue;
|
||||||
if(!inet_ntop(AF_INET, &addr->sin_addr, buf, len))
|
if(!inet_ntop(AF_INET, &addr->sin_addr, buf, len))
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR, "inet_ntop(): %m");
|
DPRINTF(E_ERROR, L_GENERAL, "inet_ntop(): %s\n", strerror(errno));
|
||||||
close(s);
|
close(s);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -105,13 +106,13 @@ getifhwaddr(const char * ifname, char * buf, int len)
|
|||||||
s = socket(AF_INET, SOCK_DGRAM, 0);
|
s = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
if(s < 0)
|
if(s < 0)
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR, "socket(PF_INET, SOCK_DGRAM): %m");
|
DPRINTF(E_ERROR, L_GENERAL, "socket(PF_INET, SOCK_DGRAM): %s\n", strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
|
strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
|
||||||
if(ioctl(s, SIOCGIFHWADDR, &ifr, &ifrlen) < 0)
|
if(ioctl(s, SIOCGIFHWADDR, &ifr, &ifrlen) < 0)
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR, "ioctl(s, SIOCGIFHWADDR, ...): %m");
|
DPRINTF(E_ERROR, L_GENERAL, "ioctl(s, SIOCGIFHWADDR, ...): %s\n", strerror(errno));
|
||||||
close(s);
|
close(s);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
23
inotify.c
23
inotify.c
@ -18,6 +18,7 @@
|
|||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "sql.h"
|
#include "sql.h"
|
||||||
#include "scanner.h"
|
#include "scanner.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
#define EVENT_SIZE ( sizeof (struct inotify_event) )
|
#define EVENT_SIZE ( sizeof (struct inotify_event) )
|
||||||
#define BUF_LEN ( 1024 * ( EVENT_SIZE + 16 ) )
|
#define BUF_LEN ( 1024 * ( EVENT_SIZE + 16 ) )
|
||||||
@ -157,7 +158,7 @@ inotify_create_watches(int fd)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
printf("WARNING: Inotify max_user_watches [%u] is low or close to the number of used watches [%u] "
|
DPRINTF(E_WARN, L_INOTIFY, "WARNING: Inotify max_user_watches [%u] is low or close to the number of used watches [%u] "
|
||||||
"and I do not have permission to increase this limit. Please do so manually by "
|
"and I do not have permission to increase this limit. Please do so manually by "
|
||||||
"writing a higher value into /proc/sys/fs/inotify/max_user_watches.\n", watch_limit, num_watches);
|
"writing a higher value into /proc/sys/fs/inotify/max_user_watches.\n", watch_limit, num_watches);
|
||||||
}
|
}
|
||||||
@ -165,7 +166,7 @@ inotify_create_watches(int fd)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
printf("WARNING: Could not read inotify max_user_watches! "
|
DPRINTF(E_WARN, L_INOTIFY, "WARNING: Could not read inotify max_user_watches! "
|
||||||
"Hopefully it is enough to cover %u current directories plus any new ones added.\n", num_watches);
|
"Hopefully it is enough to cover %u current directories plus any new ones added.\n", num_watches);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,7 +179,7 @@ inotify_create_watches(int fd)
|
|||||||
sql_get_table(db, "SELECT PATH from DETAILS where SIZE is NULL and PATH is not NULL", &result, &rows, NULL);
|
sql_get_table(db, "SELECT PATH from DETAILS where SIZE is NULL and PATH is not NULL", &result, &rows, NULL);
|
||||||
for( i=1; i <= rows; i++ )
|
for( i=1; i <= rows; i++ )
|
||||||
{
|
{
|
||||||
//DEBUG printf("Add watch to %s\n", result[i]);
|
DPRINTF(E_DEBUG, L_INOTIFY, "Add watch to %s\n", result[i]);
|
||||||
add_watch(fd, result[i]);
|
add_watch(fd, result[i]);
|
||||||
}
|
}
|
||||||
sqlite3_free_table(result);
|
sqlite3_free_table(result);
|
||||||
@ -222,7 +223,7 @@ int add_dir_watch(int fd, char * path, char * filename)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
printf("Added watch to %s [%d]\n", buf, wd);
|
DPRINTF(E_INFO, L_INOTIFY, "Added watch to %s [%d]\n", buf, wd);
|
||||||
}
|
}
|
||||||
|
|
||||||
ds = opendir(buf);
|
ds = opendir(buf);
|
||||||
@ -289,7 +290,7 @@ inotify_insert_file(char * name, const char * path)
|
|||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
printf("Checking %s\n", parent_buf);
|
DPRINTF(E_DEBUG, L_INOTIFY, "Checking %s\n", parent_buf);
|
||||||
sql = sqlite3_mprintf("SELECT OBJECT_ID from OBJECTS o left join DETAILS d on (d.ID = o.DETAIL_ID)"
|
sql = sqlite3_mprintf("SELECT OBJECT_ID from OBJECTS o left join DETAILS d on (d.ID = o.DETAIL_ID)"
|
||||||
" where d.PATH = '%q' and REF_ID is NULL", parent_buf);
|
" where d.PATH = '%q' and REF_ID is NULL", parent_buf);
|
||||||
if( (sql_get_table(db, sql, &result, &rows, NULL) == SQLITE_OK) && rows )
|
if( (sql_get_table(db, sql, &result, &rows, NULL) == SQLITE_OK) && rows )
|
||||||
@ -299,7 +300,7 @@ inotify_insert_file(char * name, const char * path)
|
|||||||
sqlite3_free(sql);
|
sqlite3_free(sql);
|
||||||
if( !depth )
|
if( !depth )
|
||||||
break;
|
break;
|
||||||
printf("Found first known parentID: %s\n", id);
|
DPRINTF(E_DEBUG, L_INOTIFY, "Found first known parentID: %s\n", id);
|
||||||
/* Insert newly-found directory */
|
/* Insert newly-found directory */
|
||||||
strcpy(base_name, last_dir);
|
strcpy(base_name, last_dir);
|
||||||
base_copy = basename(base_name);
|
base_copy = basename(base_name);
|
||||||
@ -374,7 +375,7 @@ inotify_insert_directory(int fd, char *name, const char * path)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
printf("Added watch to %s [%d]\n", path, wd);
|
DPRINTF(E_INFO, L_INOTIFY, "Added watch to %s [%d]\n", path, wd);
|
||||||
}
|
}
|
||||||
|
|
||||||
ds = opendir(path);
|
ds = opendir(path);
|
||||||
@ -525,22 +526,22 @@ start_inotify()
|
|||||||
asprintf(&path_buf, "%s/%s", get_path_from_wd(event->wd), event->name);
|
asprintf(&path_buf, "%s/%s", get_path_from_wd(event->wd), event->name);
|
||||||
if ( event->mask & IN_CREATE && event->mask & IN_ISDIR )
|
if ( event->mask & IN_CREATE && event->mask & IN_ISDIR )
|
||||||
{
|
{
|
||||||
//DEBUG printf( "The directory %s was created.\n", path_buf );
|
DPRINTF(E_DEBUG, L_INOTIFY, "The directory %s was created.\n", path_buf );
|
||||||
inotify_insert_directory(fd, esc_name, path_buf);
|
inotify_insert_directory(fd, esc_name, path_buf);
|
||||||
}
|
}
|
||||||
else if ( event->mask & IN_CLOSE_WRITE )
|
else if ( event->mask & IN_CLOSE_WRITE )
|
||||||
{
|
{
|
||||||
//DEBUG printf( "The file %s was changed.\n", path_buf );
|
DPRINTF(E_DEBUG, L_INOTIFY, "The file %s was changed.\n", path_buf );
|
||||||
inotify_insert_file(esc_name, path_buf);
|
inotify_insert_file(esc_name, path_buf);
|
||||||
}
|
}
|
||||||
else if ( event->mask & IN_DELETE )
|
else if ( event->mask & IN_DELETE )
|
||||||
{
|
{
|
||||||
if ( event->mask & IN_ISDIR ) {
|
if ( event->mask & IN_ISDIR ) {
|
||||||
//DEBUG printf("The directory %s was deleted.\n", path_buf);
|
DPRINTF(E_DEBUG, L_INOTIFY, "The directory %s was deleted.\n", path_buf);
|
||||||
inotify_remove_directory(fd, path_buf);
|
inotify_remove_directory(fd, path_buf);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
//DEBUG printf( "The file %s was deleted.\n", path_buf);
|
DPRINTF(E_DEBUG, L_INOTIFY, "The file %s was deleted.\n", path_buf);
|
||||||
inotify_remove_file(path_buf);
|
inotify_remove_file(path_buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
154
log.c
Normal file
154
log.c
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
|
||||||
|
/* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
|
static FILE *log_fp = NULL;
|
||||||
|
static int default_log_level = E_WARN;
|
||||||
|
int log_level[L_MAX];
|
||||||
|
|
||||||
|
char *facility_name[] = {
|
||||||
|
"general",
|
||||||
|
"artwork",
|
||||||
|
"database",
|
||||||
|
"inotify",
|
||||||
|
"scanner",
|
||||||
|
"metadata",
|
||||||
|
"http",
|
||||||
|
"ssdp",
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
char *level_name[] = {
|
||||||
|
"off", // E_OFF
|
||||||
|
"fatal", // E_FATAL
|
||||||
|
"error", // E_ERROR
|
||||||
|
"warn", // E_WARN
|
||||||
|
"info", // E_INFO
|
||||||
|
"debug", // E_DEBUG
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
int
|
||||||
|
log_init(const char *fname, const char *debug)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
FILE *fp;
|
||||||
|
short int log_level_set[L_MAX];
|
||||||
|
|
||||||
|
if (debug)
|
||||||
|
{
|
||||||
|
char *rhs, *lhs, *p;
|
||||||
|
int n;
|
||||||
|
int level, facility;
|
||||||
|
memset(&log_level_set, 0, sizeof(log_level_set));
|
||||||
|
rhs = lhs = (char*) debug;
|
||||||
|
while (rhs && (rhs = strchr(rhs, '='))) {
|
||||||
|
rhs++;
|
||||||
|
p = strchr(rhs, ',');
|
||||||
|
n = p ? p - rhs : strlen(rhs);
|
||||||
|
for (level=0; level_name[level]; level++) {
|
||||||
|
if (!(strncasecmp(level_name[level], rhs, n)))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
rhs = p;
|
||||||
|
if (!(level_name[level])) {
|
||||||
|
// unknown level
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
do {
|
||||||
|
if (*lhs==',') lhs++;
|
||||||
|
p = strpbrk(lhs, ",=");
|
||||||
|
n = p ? p - lhs : strlen(lhs);
|
||||||
|
for (facility=0; facility_name[facility]; facility++) {
|
||||||
|
if (!(strncasecmp(facility_name[facility], lhs, n)))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ((facility_name[facility])) {
|
||||||
|
log_level[facility] = level;
|
||||||
|
log_level_set[facility] = 1;
|
||||||
|
}
|
||||||
|
lhs = p;
|
||||||
|
} while (*lhs && *lhs==',');
|
||||||
|
}
|
||||||
|
for (i=0; i<L_MAX; i++)
|
||||||
|
{
|
||||||
|
if( !log_level_set[i] )
|
||||||
|
{
|
||||||
|
log_level[i] = default_log_level;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (i=0; i<L_MAX; i++)
|
||||||
|
log_level[i] = default_log_level;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fname) // use default i.e. stderr
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!(fp = fopen(fname, "a")))
|
||||||
|
return 1;
|
||||||
|
log_fp = fp;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
log_err(int level, enum _log_facility facility, char *fname, int lineno, char *fmt, ...)
|
||||||
|
{
|
||||||
|
//char errbuf[1024];
|
||||||
|
char * errbuf;
|
||||||
|
va_list ap;
|
||||||
|
time_t t;
|
||||||
|
struct tm *tm;
|
||||||
|
|
||||||
|
if (level && level>log_level[facility])
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!log_fp)
|
||||||
|
log_fp = stderr;
|
||||||
|
|
||||||
|
// user log
|
||||||
|
va_start(ap, fmt);
|
||||||
|
//vsnprintf(errbuf, sizeof(errbuf), fmt, ap);
|
||||||
|
vasprintf(&errbuf, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
// timestamp
|
||||||
|
t = time(0);
|
||||||
|
tm = localtime(&t);
|
||||||
|
fprintf(log_fp, "[%04d/%02d/%02d %02d:%02d:%02d] ",
|
||||||
|
tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
|
||||||
|
tm->tm_hour, tm->tm_min, tm->tm_sec);
|
||||||
|
|
||||||
|
if (level)
|
||||||
|
fprintf(log_fp, "%s:%d: %s: %s", fname, lineno, level_name[level], errbuf);
|
||||||
|
else
|
||||||
|
fprintf(log_fp, "%s:%d: %s", fname, lineno, errbuf);
|
||||||
|
fflush(log_fp);
|
||||||
|
free(errbuf);
|
||||||
|
|
||||||
|
if (level==E_FATAL)
|
||||||
|
exit(-1);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
46
log.h
Normal file
46
log.h
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
/* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ERR_H__
|
||||||
|
#define __ERR_H__
|
||||||
|
|
||||||
|
#define E_OFF 0
|
||||||
|
#define E_FATAL 1
|
||||||
|
#define E_ERROR 2
|
||||||
|
#define E_WARN 3
|
||||||
|
#define E_INFO 4
|
||||||
|
#define E_DEBUG 5
|
||||||
|
|
||||||
|
enum _log_facility
|
||||||
|
{
|
||||||
|
L_GENERAL=0,
|
||||||
|
L_ARTWORK,
|
||||||
|
L_DB_SQL,
|
||||||
|
L_INOTIFY,
|
||||||
|
L_SCANNER,
|
||||||
|
L_METADATA,
|
||||||
|
L_HTTP,
|
||||||
|
L_SSDP,
|
||||||
|
L_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
extern int log_level[L_MAX];
|
||||||
|
extern int log_init(const char *fname, const char *debug);
|
||||||
|
extern void log_err(int level, enum _log_facility facility, char *fname, int lineno, char *fmt, ...);
|
||||||
|
|
||||||
|
#define DPRINTF(level, facility, fmt, arg...) { log_err(level, facility, __FILE__, __LINE__, fmt, ##arg); }
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* __ERR_H__ */
|
73
metadata.c
73
metadata.c
@ -40,6 +40,7 @@
|
|||||||
#include "albumart.h"
|
#include "albumart.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "sql.h"
|
#include "sql.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
#define FLAG_TITLE 0x00000001
|
#define FLAG_TITLE 0x00000001
|
||||||
#define FLAG_ARTIST 0x00000002
|
#define FLAG_ARTIST 0x00000002
|
||||||
@ -285,7 +286,7 @@ GetAudioMetadata(const char * path, char * name)
|
|||||||
if( free_flags & FLAG_COMMENT )
|
if( free_flags & FLAG_COMMENT )
|
||||||
free(comment);
|
free(comment);
|
||||||
|
|
||||||
//DEBUG printf("SQL: %s\n", sql);
|
//DEBUG DPRINTF(E_DEBUG, L_METADATA, "SQL: %s\n", sql);
|
||||||
if( sql_exec(db, sql) != SQLITE_OK )
|
if( sql_exec(db, sql) != SQLITE_OK )
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Error inserting details for '%s'!\n", path);
|
fprintf(stderr, "Error inserting details for '%s'!\n", path);
|
||||||
@ -332,13 +333,13 @@ GetImageMetadata(const char * path, char * name)
|
|||||||
date[0] = '\0';
|
date[0] = '\0';
|
||||||
model[0] = '\0';
|
model[0] = '\0';
|
||||||
|
|
||||||
//DEBUG printf("Parsing %s...\n", path);
|
DPRINTF(E_DEBUG, L_METADATA, "Parsing %s...\n", path);
|
||||||
if ( stat(path, &file) == 0 )
|
if ( stat(path, &file) == 0 )
|
||||||
size = file.st_size;
|
size = file.st_size;
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
strip_ext(name);
|
strip_ext(name);
|
||||||
//DEBUG printf(" * size: %d\n", size);
|
//DEBUG DPRINTF(E_DEBUG, L_METADATA, " * size: %d\n", size);
|
||||||
|
|
||||||
/* MIME hard-coded to JPEG for now, until we add PNG support */
|
/* MIME hard-coded to JPEG for now, until we add PNG support */
|
||||||
asprintf(&m.mime, "image/jpeg");
|
asprintf(&m.mime, "image/jpeg");
|
||||||
@ -357,7 +358,7 @@ GetImageMetadata(const char * path, char * name)
|
|||||||
e = exif_content_get_entry (ed->ifd[EXIF_IFD_EXIF], tag);
|
e = exif_content_get_entry (ed->ifd[EXIF_IFD_EXIF], tag);
|
||||||
if( e )
|
if( e )
|
||||||
height = atoi( exif_entry_get_value(e, b, sizeof(b)) );
|
height = atoi( exif_entry_get_value(e, b, sizeof(b)) );
|
||||||
//DEBUG printf(" * resolution: %dx%d\n", width, height);
|
//DEBUG DPRINTF(E_DEBUG, L_METADATA, " * resolution: %dx%d\n", width, height);
|
||||||
|
|
||||||
tag = EXIF_TAG_DATE_TIME_ORIGINAL;
|
tag = EXIF_TAG_DATE_TIME_ORIGINAL;
|
||||||
e = exif_content_get_entry (ed->ifd[EXIF_IFD_EXIF], tag);
|
e = exif_content_get_entry (ed->ifd[EXIF_IFD_EXIF], tag);
|
||||||
@ -376,7 +377,7 @@ GetImageMetadata(const char * path, char * name)
|
|||||||
else {
|
else {
|
||||||
strcpy(date, "0000-00-00");
|
strcpy(date, "0000-00-00");
|
||||||
}
|
}
|
||||||
//DEBUG printf(" * date: %s\n", date);
|
//DEBUG DPRINTF(E_DEBUG, L_METADATA, " * date: %s\n", date);
|
||||||
|
|
||||||
model[0] = '\0';
|
model[0] = '\0';
|
||||||
tag = EXIF_TAG_MAKE;
|
tag = EXIF_TAG_MAKE;
|
||||||
@ -395,13 +396,13 @@ GetImageMetadata(const char * path, char * name)
|
|||||||
}
|
}
|
||||||
if( !strlen(model) )
|
if( !strlen(model) )
|
||||||
strcpy(model, "Unknown");
|
strcpy(model, "Unknown");
|
||||||
//DEBUG printf(" * model: %s\n", model);
|
//DEBUG DPRINTF(E_DEBUG, L_METADATA, " * model: %s\n", model);
|
||||||
|
|
||||||
if( ed->size )
|
if( ed->size )
|
||||||
thumb = 1;
|
thumb = 1;
|
||||||
else
|
else
|
||||||
thumb = 0;
|
thumb = 0;
|
||||||
//DEBUG printf(" * thumbnail: %d\n", thumb);
|
//DEBUG DPRINTF(E_DEBUG, L_METADATA, " * thumbnail: %d\n", thumb);
|
||||||
|
|
||||||
exif_data_unref(ed);
|
exif_data_unref(ed);
|
||||||
|
|
||||||
@ -439,7 +440,7 @@ GetImageMetadata(const char * path, char * name)
|
|||||||
"VALUES"
|
"VALUES"
|
||||||
" (%Q, '%q', %llu, '%s', %Q, %d, '%q', %Q, %Q);",
|
" (%Q, '%q', %llu, '%s', %Q, %d, '%q', %Q, %Q);",
|
||||||
path, name, size, date, m.resolution, thumb, model, m.dlna_pn, m.mime);
|
path, name, size, date, m.resolution, thumb, model, m.dlna_pn, m.mime);
|
||||||
//DEBUG printf("SQL: %s\n", sql);
|
//DEBUG DPRINTF(E_DEBUG, L_METADATA, "SQL: %s\n", sql);
|
||||||
if( sql_exec(db, sql) != SQLITE_OK )
|
if( sql_exec(db, sql) != SQLITE_OK )
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Error inserting details for '%s'!\n", path);
|
fprintf(stderr, "Error inserting details for '%s'!\n", path);
|
||||||
@ -508,7 +509,7 @@ GetVideoMetadata(const char * path, char * name)
|
|||||||
memset(&m, '\0', sizeof(m));
|
memset(&m, '\0', sizeof(m));
|
||||||
date[0] = '\0';
|
date[0] = '\0';
|
||||||
|
|
||||||
//DEBUG printf("Parsing %s...\n", path);
|
DPRINTF(E_DEBUG, L_METADATA, "Parsing %s...\n", path);
|
||||||
if ( stat(path, &file) == 0 )
|
if ( stat(path, &file) == 0 )
|
||||||
{
|
{
|
||||||
modtime = localtime(&file.st_mtime);
|
modtime = localtime(&file.st_mtime);
|
||||||
@ -516,7 +517,7 @@ GetVideoMetadata(const char * path, char * name)
|
|||||||
size = file.st_size;
|
size = file.st_size;
|
||||||
}
|
}
|
||||||
strip_ext(name);
|
strip_ext(name);
|
||||||
//DEBUG printf(" * size: %d\n", size);
|
//DEBUG DPRINTF(E_DEBUG, L_METADATA, " * size: %d\n", size);
|
||||||
|
|
||||||
av_register_all();
|
av_register_all();
|
||||||
if( av_open_input_file(&ctx, path, NULL, 0, NULL) == 0 )
|
if( av_open_input_file(&ctx, path, NULL, 0, NULL) == 0 )
|
||||||
@ -549,7 +550,7 @@ GetVideoMetadata(const char * path, char * name)
|
|||||||
if( !ctx->streams[audio_stream]->codec->extradata_size ||
|
if( !ctx->streams[audio_stream]->codec->extradata_size ||
|
||||||
!ctx->streams[audio_stream]->codec->extradata )
|
!ctx->streams[audio_stream]->codec->extradata )
|
||||||
{
|
{
|
||||||
printf("No AAC type\n");
|
DPRINTF(E_DEBUG, L_METADATA, "No AAC type\n");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -565,7 +566,7 @@ GetVideoMetadata(const char * path, char * name)
|
|||||||
if( ctx->streams[audio_stream]->codec->sample_rate < 8000 ||
|
if( ctx->streams[audio_stream]->codec->sample_rate < 8000 ||
|
||||||
ctx->streams[audio_stream]->codec->sample_rate > 48000 )
|
ctx->streams[audio_stream]->codec->sample_rate > 48000 )
|
||||||
{
|
{
|
||||||
printf("Unsupported AAC: sample rate is not 8000 < %d < 48000\n",
|
DPRINTF(E_DEBUG, L_METADATA, "Unsupported AAC: sample rate is not 8000 < %d < 48000\n",
|
||||||
ctx->streams[audio_stream]->codec->sample_rate);
|
ctx->streams[audio_stream]->codec->sample_rate);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -577,12 +578,12 @@ GetVideoMetadata(const char * path, char * name)
|
|||||||
ctx->streams[audio_stream]->codec->bit_rate <= 1440000 )
|
ctx->streams[audio_stream]->codec->bit_rate <= 1440000 )
|
||||||
audio_profile = AAC_MULT5;
|
audio_profile = AAC_MULT5;
|
||||||
else
|
else
|
||||||
printf("Unhandled AAC: %d channels, %d bitrate\n",
|
DPRINTF(E_DEBUG, L_METADATA, "Unhandled AAC: %d channels, %d bitrate\n",
|
||||||
ctx->streams[audio_stream]->codec->channels,
|
ctx->streams[audio_stream]->codec->channels,
|
||||||
ctx->streams[audio_stream]->codec->bit_rate);
|
ctx->streams[audio_stream]->codec->bit_rate);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printf("Unhandled AAC type [%d]\n", aac_type);
|
DPRINTF(E_DEBUG, L_METADATA, "Unhandled AAC type [%d]\n", aac_type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -612,7 +613,7 @@ GetVideoMetadata(const char * path, char * name)
|
|||||||
(ctx->streams[audio_stream]->codec->codec_id < CODEC_ID_ADPCM_IMA_QT) )
|
(ctx->streams[audio_stream]->codec->codec_id < CODEC_ID_ADPCM_IMA_QT) )
|
||||||
audio_profile = PCM;
|
audio_profile = PCM;
|
||||||
else
|
else
|
||||||
printf("Unhandled audio codec [%X]\n", ctx->streams[audio_stream]->codec->codec_id);
|
DPRINTF(E_DEBUG, L_METADATA, "Unhandled audio codec [%X]\n", ctx->streams[audio_stream]->codec->codec_id);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
asprintf(&m.frequency, "%u", ctx->streams[audio_stream]->codec->sample_rate);
|
asprintf(&m.frequency, "%u", ctx->streams[audio_stream]->codec->sample_rate);
|
||||||
@ -625,7 +626,7 @@ GetVideoMetadata(const char * path, char * name)
|
|||||||
}
|
}
|
||||||
if( video_stream >= 0 )
|
if( video_stream >= 0 )
|
||||||
{
|
{
|
||||||
//DEBUG printf("Container: '%s' [%s]\n", ctx->iformat->name, path);
|
DPRINTF(E_DEBUG, L_METADATA, "Container: '%s' [%s]\n", ctx->iformat->name, path);
|
||||||
asprintf(&m.resolution, "%dx%d", ctx->streams[video_stream]->codec->width, ctx->streams[video_stream]->codec->height);
|
asprintf(&m.resolution, "%dx%d", ctx->streams[video_stream]->codec->width, ctx->streams[video_stream]->codec->height);
|
||||||
asprintf(&m.bitrate, "%u", ctx->bit_rate / 8);
|
asprintf(&m.bitrate, "%u", ctx->bit_rate / 8);
|
||||||
if( ctx->duration > 0 ) {
|
if( ctx->duration > 0 ) {
|
||||||
@ -649,7 +650,7 @@ GetVideoMetadata(const char * path, char * name)
|
|||||||
case CODEC_ID_MPEG2VIDEO:
|
case CODEC_ID_MPEG2VIDEO:
|
||||||
if( strcmp(ctx->iformat->name, "mpegts") == 0 )
|
if( strcmp(ctx->iformat->name, "mpegts") == 0 )
|
||||||
{
|
{
|
||||||
printf("Stream %d of %s is %s MPEG2 TS\n", video_stream, path, m.resolution);
|
DPRINTF(E_DEBUG, L_METADATA, "Stream %d of %s is %s MPEG2 TS\n", video_stream, path, m.resolution);
|
||||||
char res;
|
char res;
|
||||||
tsinfo_t * ts = ctx->priv_data;
|
tsinfo_t * ts = ctx->priv_data;
|
||||||
if( ts->packet_size == 192 )
|
if( ts->packet_size == 192 )
|
||||||
@ -670,7 +671,7 @@ GetVideoMetadata(const char * path, char * name)
|
|||||||
}
|
}
|
||||||
else if( strcmp(ctx->iformat->name, "mpeg") == 0 )
|
else if( strcmp(ctx->iformat->name, "mpeg") == 0 )
|
||||||
{
|
{
|
||||||
printf("Stream %d of %s is %s MPEG2 PS\n", video_stream, path, m.resolution);
|
DPRINTF(E_DEBUG, L_METADATA, "Stream %d of %s is %s MPEG2 PS\n", video_stream, path, m.resolution);
|
||||||
char region[5];
|
char region[5];
|
||||||
if( (ctx->streams[video_stream]->codec->height == 576) ||
|
if( (ctx->streams[video_stream]->codec->height == 576) ||
|
||||||
(ctx->streams[video_stream]->codec->height == 288) )
|
(ctx->streams[video_stream]->codec->height == 288) )
|
||||||
@ -682,7 +683,7 @@ GetVideoMetadata(const char * path, char * name)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
printf("Stream %d of %s [UNKNOWN CONTAINER] is %s MPEG2\n", video_stream, path, m.resolution);
|
DPRINTF(E_DEBUG, L_METADATA, "Stream %d of %s [UNKNOWN CONTAINER] is %s MPEG2\n", video_stream, path, m.resolution);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CODEC_ID_H264:
|
case CODEC_ID_H264:
|
||||||
@ -722,7 +723,7 @@ GetVideoMetadata(const char * path, char * name)
|
|||||||
ts_timestamp==NONE?"_ISO" : ts_timestamp==VALID?"_T":"");
|
ts_timestamp==NONE?"_ISO" : ts_timestamp==VALID?"_T":"");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printf("No DLNA profile found for TS/AVC/%cD file %s\n", res, path);
|
DPRINTF(E_DEBUG, L_METADATA, "No DLNA profile found for TS/AVC/%cD file %s\n", res, path);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if( m.dlna_pn && (ts_timestamp != NONE) )
|
if( m.dlna_pn && (ts_timestamp != NONE) )
|
||||||
@ -730,7 +731,7 @@ GetVideoMetadata(const char * path, char * name)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
printf("Unsupported h.264 video profile! [%dx%d, %dbps]\n",
|
DPRINTF(E_DEBUG, L_METADATA, "Unsupported h.264 video profile! [%dx%d, %dbps]\n",
|
||||||
ctx->streams[video_stream]->codec->width,
|
ctx->streams[video_stream]->codec->width,
|
||||||
ctx->streams[video_stream]->codec->height,
|
ctx->streams[video_stream]->codec->height,
|
||||||
ctx->streams[video_stream]->codec->bit_rate);
|
ctx->streams[video_stream]->codec->bit_rate);
|
||||||
@ -752,37 +753,37 @@ GetVideoMetadata(const char * path, char * name)
|
|||||||
asprintf(&m.dlna_pn, "AVC_MP4_MP_SD_AAC_MULT5;DLNA.ORG_OP=01;DLNA.ORG_CI=0");
|
asprintf(&m.dlna_pn, "AVC_MP4_MP_SD_AAC_MULT5;DLNA.ORG_OP=01;DLNA.ORG_CI=0");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printf("No DLNA profile found for MP4/AVC/SD file %s\n", path);
|
DPRINTF(E_DEBUG, L_METADATA, "No DLNA profile found for MP4/AVC/SD file %s\n", path);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf("Stream %d of %s is h.264\n", video_stream, path);
|
DPRINTF(E_DEBUG, L_METADATA, "Stream %d of %s is h.264\n", video_stream, path);
|
||||||
break;
|
break;
|
||||||
case CODEC_ID_MPEG4:
|
case CODEC_ID_MPEG4:
|
||||||
if( ctx->streams[video_stream]->codec->codec_tag == get_fourcc("XVID") )
|
if( ctx->streams[video_stream]->codec->codec_tag == get_fourcc("XVID") )
|
||||||
{
|
{
|
||||||
printf("Stream %d of %s is %s XViD\n", video_stream, path, m.resolution);
|
DPRINTF(E_DEBUG, L_METADATA, "Stream %d of %s is %s XViD\n", video_stream, path, m.resolution);
|
||||||
asprintf(&m.mime, "video/divx");
|
asprintf(&m.mime, "video/divx");
|
||||||
}
|
}
|
||||||
else if( ctx->streams[video_stream]->codec->codec_tag == get_fourcc("DX50") )
|
else if( ctx->streams[video_stream]->codec->codec_tag == get_fourcc("DX50") )
|
||||||
{
|
{
|
||||||
printf("Stream %d of %s is %s DiVX5\n", video_stream, path, m.resolution);
|
DPRINTF(E_DEBUG, L_METADATA, "Stream %d of %s is %s DiVX5\n", video_stream, path, m.resolution);
|
||||||
asprintf(&m.mime, "video/divx");
|
asprintf(&m.mime, "video/divx");
|
||||||
}
|
}
|
||||||
else if( ctx->streams[video_stream]->codec->codec_tag == get_fourcc("DIVX") )
|
else if( ctx->streams[video_stream]->codec->codec_tag == get_fourcc("DIVX") )
|
||||||
{
|
{
|
||||||
printf("Stream %d of %s is DiVX\n", video_stream, path);
|
DPRINTF(E_DEBUG, L_METADATA, "Stream %d of %s is DiVX\n", video_stream, path);
|
||||||
asprintf(&m.mime, "video/divx");
|
asprintf(&m.mime, "video/divx");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
printf("Stream %d of %s is MPEG4 [%X]\n", video_stream, path, ctx->streams[video_stream]->codec->codec_tag);
|
DPRINTF(E_DEBUG, L_METADATA, "Stream %d of %s is MPEG4 [%X]\n", video_stream, path, ctx->streams[video_stream]->codec->codec_tag);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CODEC_ID_WMV3:
|
case CODEC_ID_WMV3:
|
||||||
case CODEC_ID_VC1:
|
case CODEC_ID_VC1:
|
||||||
printf("Stream %d of %s is VC1\n", video_stream, path);
|
DPRINTF(E_DEBUG, L_METADATA, "Stream %d of %s is VC1\n", video_stream, path);
|
||||||
char profile[5]; profile[0] = '\0';
|
char profile[5]; profile[0] = '\0';
|
||||||
asprintf(&m.mime, "video/x-ms-wmv");
|
asprintf(&m.mime, "video/x-ms-wmv");
|
||||||
if( (ctx->streams[video_stream]->codec->width <= 352) &&
|
if( (ctx->streams[video_stream]->codec->width <= 352) &&
|
||||||
@ -819,22 +820,22 @@ GetVideoMetadata(const char * path, char * name)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CODEC_ID_XVID:
|
case CODEC_ID_XVID:
|
||||||
printf("Stream %d of %s is %s UNKNOWN XVID\n", video_stream, path, m.resolution);
|
DPRINTF(E_DEBUG, L_METADATA, "Stream %d of %s is %s UNKNOWN XVID\n", video_stream, path, m.resolution);
|
||||||
break;
|
break;
|
||||||
case CODEC_ID_MSMPEG4V1:
|
case CODEC_ID_MSMPEG4V1:
|
||||||
printf("Stream %d of %s is %s MS MPEG4 v1\n", video_stream, path, m.resolution);
|
DPRINTF(E_DEBUG, L_METADATA, "Stream %d of %s is %s MS MPEG4 v1\n", video_stream, path, m.resolution);
|
||||||
case CODEC_ID_MSMPEG4V3:
|
case CODEC_ID_MSMPEG4V3:
|
||||||
printf("Stream %d of %s is %s MS MPEG4 v3\n", video_stream, path, m.resolution);
|
DPRINTF(E_DEBUG, L_METADATA, "Stream %d of %s is %s MS MPEG4 v3\n", video_stream, path, m.resolution);
|
||||||
asprintf(&m.mime, "video/avi");
|
asprintf(&m.mime, "video/avi");
|
||||||
break;
|
break;
|
||||||
case CODEC_ID_H263I:
|
case CODEC_ID_H263I:
|
||||||
printf("Stream %d of %s is h.263i\n", video_stream, path);
|
DPRINTF(E_DEBUG, L_METADATA, "Stream %d of %s is h.263i\n", video_stream, path);
|
||||||
break;
|
break;
|
||||||
case CODEC_ID_MJPEG:
|
case CODEC_ID_MJPEG:
|
||||||
printf("Stream %d of %s is MJPEG\n", video_stream, path);
|
DPRINTF(E_DEBUG, L_METADATA, "Stream %d of %s is MJPEG\n", video_stream, path);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printf("Stream %d of %s is %d\n", video_stream, path, ctx->streams[video_stream]->codec->codec_id);
|
DPRINTF(E_DEBUG, L_METADATA, "Stream %d of %s is %d\n", video_stream, path, ctx->streams[video_stream]->codec->codec_id);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -855,7 +856,7 @@ GetVideoMetadata(const char * path, char * name)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
printf("Opening %s failed!\n", path);
|
DPRINTF(E_WARN, L_METADATA, "Opening %s failed!\n", path);
|
||||||
}
|
}
|
||||||
|
|
||||||
sql = sqlite3_mprintf( "INSERT into DETAILS"
|
sql = sqlite3_mprintf( "INSERT into DETAILS"
|
||||||
@ -870,7 +871,7 @@ GetVideoMetadata(const char * path, char * name)
|
|||||||
m.frequency,
|
m.frequency,
|
||||||
m.resolution,
|
m.resolution,
|
||||||
name, m.dlna_pn, m.mime);
|
name, m.dlna_pn, m.mime);
|
||||||
//DEBUG printf("SQL: %s\n", sql);
|
//DEBUG DPRINTF(E_DEBUG, L_METADATA, "SQL: %s\n", sql);
|
||||||
if( sql_exec(db, sql) != SQLITE_OK )
|
if( sql_exec(db, sql) != SQLITE_OK )
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Error inserting details for '%s'!\n", path);
|
fprintf(stderr, "Error inserting details for '%s'!\n", path);
|
||||||
|
90
minidlna.c
90
minidlna.c
@ -19,11 +19,11 @@
|
|||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <sys/file.h>
|
#include <sys/file.h>
|
||||||
#include <syslog.h>
|
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
|
#include <errno.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
|
||||||
/* unix sockets */
|
/* unix sockets */
|
||||||
@ -45,6 +45,7 @@
|
|||||||
#include "scanner.h"
|
#include "scanner.h"
|
||||||
#include "inotify.h"
|
#include "inotify.h"
|
||||||
#include "commonrdr.h"
|
#include "commonrdr.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
/* MAX_LAN_ADDR : maximum number of interfaces
|
/* MAX_LAN_ADDR : maximum number of interfaces
|
||||||
* to listen to SSDP traffic */
|
* to listen to SSDP traffic */
|
||||||
@ -63,13 +64,13 @@ OpenAndConfHTTPSocket(unsigned short port)
|
|||||||
|
|
||||||
if( (s = socket(PF_INET, SOCK_STREAM, 0)) < 0)
|
if( (s = socket(PF_INET, SOCK_STREAM, 0)) < 0)
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR, "socket(http): %m");
|
DPRINTF(E_ERROR, L_GENERAL, "socket(http): %s\n", strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)) < 0)
|
if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)) < 0)
|
||||||
{
|
{
|
||||||
syslog(LOG_WARNING, "setsockopt(http, SO_REUSEADDR): %m");
|
DPRINTF(E_WARN, L_GENERAL, "setsockopt(http, SO_REUSEADDR): %s\n", strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&listenname, 0, sizeof(struct sockaddr_in));
|
memset(&listenname, 0, sizeof(struct sockaddr_in));
|
||||||
@ -79,14 +80,14 @@ OpenAndConfHTTPSocket(unsigned short port)
|
|||||||
|
|
||||||
if(bind(s, (struct sockaddr *)&listenname, sizeof(struct sockaddr_in)) < 0)
|
if(bind(s, (struct sockaddr *)&listenname, sizeof(struct sockaddr_in)) < 0)
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR, "bind(http): %m");
|
DPRINTF(E_ERROR, L_GENERAL, "bind(http): %s\n", strerror(errno));
|
||||||
close(s);
|
close(s);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(listen(s, 6) < 0)
|
if(listen(s, 6) < 0)
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR, "listen(http): %m");
|
DPRINTF(E_ERROR, L_GENERAL, "listen(http): %s\n", strerror(errno));
|
||||||
close(s);
|
close(s);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -102,7 +103,7 @@ sigterm(int sig)
|
|||||||
/*int save_errno = errno;*/
|
/*int save_errno = errno;*/
|
||||||
signal(sig, SIG_IGN); /* Ignore this signal while we are quitting */
|
signal(sig, SIG_IGN); /* Ignore this signal while we are quitting */
|
||||||
|
|
||||||
syslog(LOG_NOTICE, "received signal %d, good-bye", sig);
|
DPRINTF(E_WARN, L_GENERAL, "received signal %d, good-bye\n", sig);
|
||||||
|
|
||||||
quitting = 1;
|
quitting = 1;
|
||||||
/*errno = save_errno;*/
|
/*errno = save_errno;*/
|
||||||
@ -121,14 +122,14 @@ set_startup_time(int sysuptime)
|
|||||||
fd = open("/proc/uptime", O_RDONLY);
|
fd = open("/proc/uptime", O_RDONLY);
|
||||||
if(fd < 0)
|
if(fd < 0)
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR, "open(\"/proc/uptime\" : %m");
|
DPRINTF(E_ERROR, L_GENERAL, "Error opening /proc/uptime: %s\n", strerror(errno));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
memset(buff, 0, sizeof(buff));
|
memset(buff, 0, sizeof(buff));
|
||||||
read(fd, buff, sizeof(buff) - 1);
|
read(fd, buff, sizeof(buff) - 1);
|
||||||
uptime = atoi(buff);
|
uptime = atoi(buff);
|
||||||
syslog(LOG_INFO, "system uptime is %d seconds", uptime);
|
DPRINTF(E_DEBUG, L_GENERAL, "system uptime is %d seconds\n", uptime);
|
||||||
close(fd);
|
close(fd);
|
||||||
startup_time -= uptime;
|
startup_time -= uptime;
|
||||||
}
|
}
|
||||||
@ -203,11 +204,10 @@ getfriendlyname(char * buf, int len)
|
|||||||
* 1) read configuration file
|
* 1) read configuration file
|
||||||
* 2) read command line arguments
|
* 2) read command line arguments
|
||||||
* 3) daemonize
|
* 3) daemonize
|
||||||
* 4) open syslog
|
* 4) check and write pid file
|
||||||
* 5) check and write pid file
|
* 5) set startup time stamp
|
||||||
* 6) set startup time stamp
|
* 6) compute presentation URL
|
||||||
* 7) compute presentation URL
|
* 7) set signal handlers */
|
||||||
* 8) set signal handlers */
|
|
||||||
static int
|
static int
|
||||||
init(int argc, char * * argv)
|
init(int argc, char * * argv)
|
||||||
{
|
{
|
||||||
@ -215,7 +215,6 @@ init(int argc, char * * argv)
|
|||||||
int pid;
|
int pid;
|
||||||
int debug_flag = 0;
|
int debug_flag = 0;
|
||||||
int options_flag = 0;
|
int options_flag = 0;
|
||||||
int openlog_option;
|
|
||||||
struct sigaction sa;
|
struct sigaction sa;
|
||||||
/*const char * logfilename = 0;*/
|
/*const char * logfilename = 0;*/
|
||||||
const char * presurl = 0;
|
const char * presurl = 0;
|
||||||
@ -510,6 +509,7 @@ init(int argc, char * * argv)
|
|||||||
if(debug_flag)
|
if(debug_flag)
|
||||||
{
|
{
|
||||||
pid = getpid();
|
pid = getpid();
|
||||||
|
log_init(NULL, "general,artwork,database,inotify,scanner,metadata,http,ssdp=debug");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -521,25 +521,13 @@ init(int argc, char * * argv)
|
|||||||
#else
|
#else
|
||||||
pid = daemonize();
|
pid = daemonize();
|
||||||
#endif
|
#endif
|
||||||
}
|
log_init(DB_PATH "/minidlna.log", NULL);
|
||||||
|
|
||||||
openlog_option = LOG_PID|LOG_CONS;
|
|
||||||
if(debug_flag)
|
|
||||||
{
|
|
||||||
openlog_option |= LOG_PERROR; /* also log on stderr */
|
|
||||||
}
|
|
||||||
|
|
||||||
openlog("minidlna", openlog_option, LOG_MINIDLNA);
|
|
||||||
|
|
||||||
if(!debug_flag)
|
|
||||||
{
|
|
||||||
/* speed things up and ignore LOG_INFO and LOG_DEBUG */
|
|
||||||
setlogmask(LOG_UPTO(LOG_NOTICE));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(checkforrunning(pidfilename) < 0)
|
if(checkforrunning(pidfilename) < 0)
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR, "MiniDLNA is already running. EXITING");
|
DPRINTF(E_ERROR, L_GENERAL, "MiniDLNA is already running. EXITING.\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -563,17 +551,15 @@ init(int argc, char * * argv)
|
|||||||
sa.sa_handler = sigterm;
|
sa.sa_handler = sigterm;
|
||||||
if (sigaction(SIGTERM, &sa, NULL))
|
if (sigaction(SIGTERM, &sa, NULL))
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR, "Failed to set %s handler. EXITING", "SIGTERM");
|
DPRINTF(E_FATAL, L_GENERAL, "Failed to set SIGTERM handler. EXITING.\n");
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
if (sigaction(SIGINT, &sa, NULL))
|
if (sigaction(SIGINT, &sa, NULL))
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR, "Failed to set %s handler. EXITING", "SIGINT");
|
DPRINTF(E_FATAL, L_GENERAL, "Failed to set SIGINT handler. EXITING.\n");
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
|
if(signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
|
||||||
syslog(LOG_ERR, "Failed to ignore SIGPIPE signals");
|
DPRINTF(E_FATAL, L_GENERAL, "Failed to ignore SIGPIPE signals. EXITING.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
writepidfile(pidfilename, pid);
|
writepidfile(pidfilename, pid);
|
||||||
@ -605,6 +591,7 @@ main(int argc, char * * argv)
|
|||||||
if(init(argc, argv) != 0)
|
if(init(argc, argv) != 0)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
DPRINTF(E_ERROR, L_GENERAL, "Starting MiniDLNA...\n");
|
||||||
LIST_INIT(&upnphttphead);
|
LIST_INIT(&upnphttphead);
|
||||||
|
|
||||||
if( access(DB_PATH, F_OK) != 0 )
|
if( access(DB_PATH, F_OK) != 0 )
|
||||||
@ -654,24 +641,21 @@ main(int argc, char * * argv)
|
|||||||
sudp = OpenAndConfSSDPReceiveSocket(n_lan_addr, lan_addr);
|
sudp = OpenAndConfSSDPReceiveSocket(n_lan_addr, lan_addr);
|
||||||
if(sudp < 0)
|
if(sudp < 0)
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR, "Failed to open socket for receiving SSDP. EXITING");
|
DPRINTF(E_FATAL, L_GENERAL, "Failed to open socket for receiving SSDP. EXITING\n");
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
/* open socket for HTTP connections. Listen on the 1st LAN address */
|
/* open socket for HTTP connections. Listen on the 1st LAN address */
|
||||||
shttpl = OpenAndConfHTTPSocket(runtime_vars.port);
|
shttpl = OpenAndConfHTTPSocket(runtime_vars.port);
|
||||||
if(shttpl < 0)
|
if(shttpl < 0)
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR, "Failed to open socket for HTTP. EXITING");
|
DPRINTF(E_FATAL, L_GENERAL, "Failed to open socket for HTTP. EXITING\n");
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
syslog(LOG_NOTICE, "HTTP listening on port %d", runtime_vars.port);
|
DPRINTF(E_WARN, L_GENERAL, "HTTP listening on port %d\n", runtime_vars.port);
|
||||||
|
|
||||||
/* open socket for sending notifications */
|
/* open socket for sending notifications */
|
||||||
if(OpenAndConfSSDPNotifySockets(snotify) < 0)
|
if(OpenAndConfSSDPNotifySockets(snotify) < 0)
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR, "Failed to open sockets for sending SSDP notify "
|
DPRINTF(E_FATAL, L_GENERAL, "Failed to open sockets for sending SSDP notify "
|
||||||
"messages. EXITING");
|
"messages. EXITING\n");
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SendSSDPGoodbye(snotify, n_lan_addr);
|
SendSSDPGoodbye(snotify, n_lan_addr);
|
||||||
@ -685,7 +669,7 @@ main(int argc, char * * argv)
|
|||||||
* at most once every 2 seconds */
|
* at most once every 2 seconds */
|
||||||
if(gettimeofday(&timeofday, 0) < 0)
|
if(gettimeofday(&timeofday, 0) < 0)
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR, "gettimeofday(): %m");
|
DPRINTF(E_ERROR, L_GENERAL, "gettimeofday(): %s\n", strerror(errno));
|
||||||
timeout.tv_sec = runtime_vars.notify_interval;
|
timeout.tv_sec = runtime_vars.notify_interval;
|
||||||
timeout.tv_usec = 0;
|
timeout.tv_usec = 0;
|
||||||
}
|
}
|
||||||
@ -756,7 +740,7 @@ main(int argc, char * * argv)
|
|||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if(i > 1)
|
if(i > 1)
|
||||||
{
|
{
|
||||||
syslog(LOG_DEBUG, "%d active incoming HTTP connections", i);
|
DPRINTF(E_DEBUG, L_GENERAL, "%d active incoming HTTP connections\n", i);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -772,9 +756,8 @@ main(int argc, char * * argv)
|
|||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
if(quitting) goto shutdown;
|
if(quitting) goto shutdown;
|
||||||
syslog(LOG_ERR, "select(all): %m");
|
DPRINTF(E_ERROR, L_GENERAL, "select(all): %s\n", strerror(errno));
|
||||||
syslog(LOG_ERR, "Failed to select open sockets. EXITING");
|
DPRINTF(E_FATAL, L_GENERAL, "Failed to select open sockets. EXITING\n");
|
||||||
return 1; /* very serious cause of error */
|
|
||||||
}
|
}
|
||||||
#ifdef ENABLE_EVENTS
|
#ifdef ENABLE_EVENTS
|
||||||
upnpevents_processfds(&readset, &writeset);
|
upnpevents_processfds(&readset, &writeset);
|
||||||
@ -782,7 +765,7 @@ main(int argc, char * * argv)
|
|||||||
/* process SSDP packets */
|
/* process SSDP packets */
|
||||||
if(sudp >= 0 && FD_ISSET(sudp, &readset))
|
if(sudp >= 0 && FD_ISSET(sudp, &readset))
|
||||||
{
|
{
|
||||||
/*syslog(LOG_INFO, "Received UDP Packet");*/
|
/*DPRINTF(E_DEBUG, L_GENERAL, "Received UDP Packet\n");*/
|
||||||
ProcessSSDPRequest(sudp, (unsigned short)runtime_vars.port);
|
ProcessSSDPRequest(sudp, (unsigned short)runtime_vars.port);
|
||||||
}
|
}
|
||||||
/* process active HTTP connections */
|
/* process active HTTP connections */
|
||||||
@ -805,16 +788,16 @@ main(int argc, char * * argv)
|
|||||||
shttp = accept(shttpl, (struct sockaddr *)&clientname, &clientnamelen);
|
shttp = accept(shttpl, (struct sockaddr *)&clientname, &clientnamelen);
|
||||||
if(shttp<0)
|
if(shttp<0)
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR, "accept(http): %m");
|
DPRINTF(E_ERROR, L_GENERAL, "accept(http): %s\n", strerror(errno));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
struct upnphttp * tmp = 0;
|
struct upnphttp * tmp = 0;
|
||||||
syslog(LOG_INFO, "HTTP connection from %s:%d",
|
DPRINTF(E_DEBUG, L_GENERAL, "HTTP connection from %s:%d\n",
|
||||||
inet_ntoa(clientname.sin_addr),
|
inet_ntoa(clientname.sin_addr),
|
||||||
ntohs(clientname.sin_port) );
|
ntohs(clientname.sin_port) );
|
||||||
/*if (fcntl(shttp, F_SETFL, O_NONBLOCK) < 0) {
|
/*if (fcntl(shttp, F_SETFL, O_NONBLOCK) < 0) {
|
||||||
syslog(LOG_ERR, "fcntl F_SETFL, O_NONBLOCK");
|
DPRINTF(E_ERROR, L_GENERAL, "fcntl F_SETFL, O_NONBLOCK");
|
||||||
}*/
|
}*/
|
||||||
/* Create a new upnphttp object and add it to
|
/* Create a new upnphttp object and add it to
|
||||||
* the active upnphttp object list */
|
* the active upnphttp object list */
|
||||||
@ -826,7 +809,7 @@ main(int argc, char * * argv)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR, "New_upnphttp() failed");
|
DPRINTF(E_ERROR, L_GENERAL, "New_upnphttp() failed\n");
|
||||||
close(shttp);
|
close(shttp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -858,7 +841,7 @@ shutdown:
|
|||||||
|
|
||||||
if(SendSSDPGoodbye(snotify, n_lan_addr) < 0)
|
if(SendSSDPGoodbye(snotify, n_lan_addr) < 0)
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR, "Failed to broadcast good-bye notifications");
|
DPRINTF(E_ERROR, L_GENERAL, "Failed to broadcast good-bye notifications\n");
|
||||||
}
|
}
|
||||||
for(i=0; i<n_lan_addr; i++)
|
for(i=0; i<n_lan_addr; i++)
|
||||||
close(snotify[i]);
|
close(snotify[i]);
|
||||||
@ -870,10 +853,9 @@ shutdown:
|
|||||||
|
|
||||||
if(unlink(pidfilename) < 0)
|
if(unlink(pidfilename) < 0)
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR, "Failed to remove pidfile %s: %m", pidfilename);
|
DPRINTF(E_ERROR, L_GENERAL, "Failed to remove pidfile %s: %s\n", pidfilename, strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
closelog();
|
|
||||||
freeoptions();
|
freeoptions();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
54
minissdp.c
54
minissdp.c
@ -11,13 +11,15 @@
|
|||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <syslog.h>
|
#include <errno.h>
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "upnpdescstrings.h"
|
#include "upnpdescstrings.h"
|
||||||
#include "minidlnapath.h"
|
#include "minidlnapath.h"
|
||||||
#include "upnphttp.h"
|
#include "upnphttp.h"
|
||||||
#include "upnpglobalvars.h"
|
#include "upnpglobalvars.h"
|
||||||
#include "minissdp.h"
|
#include "minissdp.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
/* SSDP ip/port */
|
/* SSDP ip/port */
|
||||||
#define SSDP_PORT (1900)
|
#define SSDP_PORT (1900)
|
||||||
@ -35,7 +37,7 @@ AddMulticastMembership(int s, in_addr_t ifaddr/*const char * ifaddr*/)
|
|||||||
|
|
||||||
if (setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void *)&imr, sizeof(struct ip_mreq)) < 0)
|
if (setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void *)&imr, sizeof(struct ip_mreq)) < 0)
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR, "setsockopt(udp, IP_ADD_MEMBERSHIP): %m");
|
DPRINTF(E_ERROR, L_SSDP, "setsockopt(udp, IP_ADD_MEMBERSHIP): %s\n", strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,8 +46,6 @@ AddMulticastMembership(int s, in_addr_t ifaddr/*const char * ifaddr*/)
|
|||||||
|
|
||||||
int
|
int
|
||||||
OpenAndConfSSDPReceiveSocket()
|
OpenAndConfSSDPReceiveSocket()
|
||||||
/*OpenAndConfSSDPReceiveSocket(int n_lan_addr,
|
|
||||||
struct lan_addr_s * lan_addr)*/
|
|
||||||
{
|
{
|
||||||
int s;
|
int s;
|
||||||
int i = 1;
|
int i = 1;
|
||||||
@ -53,13 +53,13 @@ OpenAndConfSSDPReceiveSocket()
|
|||||||
|
|
||||||
if( (s = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
|
if( (s = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR, "socket(udp): %m");
|
DPRINTF(E_ERROR, L_SSDP, "socket(udp): %s\n", strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)) < 0)
|
if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)) < 0)
|
||||||
{
|
{
|
||||||
syslog(LOG_WARNING, "setsockopt(udp, SO_REUSEADDR): %m");
|
DPRINTF(E_WARN, L_SSDP, "setsockopt(udp, SO_REUSEADDR): %s\n", strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&sockname, 0, sizeof(struct sockaddr_in));
|
memset(&sockname, 0, sizeof(struct sockaddr_in));
|
||||||
@ -72,7 +72,7 @@ OpenAndConfSSDPReceiveSocket()
|
|||||||
|
|
||||||
if(bind(s, (struct sockaddr *)&sockname, sizeof(struct sockaddr_in)) < 0)
|
if(bind(s, (struct sockaddr *)&sockname, sizeof(struct sockaddr_in)) < 0)
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR, "bind(udp): %m");
|
DPRINTF(E_ERROR, L_SSDP, "bind(udp): %s\n", strerror(errno));
|
||||||
close(s);
|
close(s);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -83,8 +83,8 @@ OpenAndConfSSDPReceiveSocket()
|
|||||||
i--;
|
i--;
|
||||||
if(AddMulticastMembership(s, lan_addr[i].addr.s_addr) < 0)
|
if(AddMulticastMembership(s, lan_addr[i].addr.s_addr) < 0)
|
||||||
{
|
{
|
||||||
syslog(LOG_WARNING,
|
DPRINTF(E_WARN, L_SSDP,
|
||||||
"Failed to add multicast membership for address %s",
|
"Failed to add multicast membership for address %s\n",
|
||||||
lan_addr[i].str );
|
lan_addr[i].str );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -105,7 +105,7 @@ OpenAndConfSSDPNotifySocket(in_addr_t addr)
|
|||||||
|
|
||||||
if( (s = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
|
if( (s = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR, "socket(udp_notify): %m");
|
DPRINTF(E_ERROR, L_SSDP, "socket(udp_notify): %s\n", strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,21 +113,21 @@ OpenAndConfSSDPNotifySocket(in_addr_t addr)
|
|||||||
|
|
||||||
if(setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP, (char *)&loopchar, sizeof(loopchar)) < 0)
|
if(setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP, (char *)&loopchar, sizeof(loopchar)) < 0)
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR, "setsockopt(udp_notify, IP_MULTICAST_LOOP): %m");
|
DPRINTF(E_ERROR, L_SSDP, "setsockopt(udp_notify, IP_MULTICAST_LOOP): %s\n", strerror(errno));
|
||||||
close(s);
|
close(s);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, (char *)&mc_if, sizeof(mc_if)) < 0)
|
if(setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, (char *)&mc_if, sizeof(mc_if)) < 0)
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR, "setsockopt(udp_notify, IP_MULTICAST_IF): %m");
|
DPRINTF(E_ERROR, L_SSDP, "setsockopt(udp_notify, IP_MULTICAST_IF): %s\n", strerror(errno));
|
||||||
close(s);
|
close(s);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(setsockopt(s, SOL_SOCKET, SO_BROADCAST, &bcast, sizeof(bcast)) < 0)
|
if(setsockopt(s, SOL_SOCKET, SO_BROADCAST, &bcast, sizeof(bcast)) < 0)
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR, "setsockopt(udp_notify, SO_BROADCAST): %m");
|
DPRINTF(E_ERROR, L_SSDP, "setsockopt(udp_notify, SO_BROADCAST): %s\n", strerror(errno));
|
||||||
close(s);
|
close(s);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -138,7 +138,7 @@ OpenAndConfSSDPNotifySocket(in_addr_t addr)
|
|||||||
|
|
||||||
if (bind(s, (struct sockaddr *)&sockname, sizeof(struct sockaddr_in)) < 0)
|
if (bind(s, (struct sockaddr *)&sockname, sizeof(struct sockaddr_in)) < 0)
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR, "bind(udp_notify): %m");
|
DPRINTF(E_ERROR, L_SSDP, "bind(udp_notify): %s\n", strerror(errno));
|
||||||
close(s);
|
close(s);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -148,8 +148,6 @@ OpenAndConfSSDPNotifySocket(in_addr_t addr)
|
|||||||
|
|
||||||
int
|
int
|
||||||
OpenAndConfSSDPNotifySockets(int * sockets)
|
OpenAndConfSSDPNotifySockets(int * sockets)
|
||||||
/*OpenAndConfSSDPNotifySockets(int * sockets,
|
|
||||||
struct lan_addr_s * lan_addr, int n_lan_addr)*/
|
|
||||||
{
|
{
|
||||||
int i, j;
|
int i, j;
|
||||||
for(i=0; i<n_lan_addr; i++)
|
for(i=0; i<n_lan_addr; i++)
|
||||||
@ -228,7 +226,7 @@ SendSSDPAnnounce2(int s, struct sockaddr_in sockname,
|
|||||||
(struct sockaddr *)&sockname, sizeof(struct sockaddr_in) );
|
(struct sockaddr *)&sockname, sizeof(struct sockaddr_in) );
|
||||||
if(n < 0)
|
if(n < 0)
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR, "sendto(udp): %m");
|
DPRINTF(E_ERROR, L_SSDP, "sendto(udp): %s\n", strerror(errno));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -280,7 +278,7 @@ SendSSDPNotifies(int s, const char * host, unsigned short port,
|
|||||||
uuidvalue, known_service_types[i], (i==0?"":"1") );
|
uuidvalue, known_service_types[i], (i==0?"":"1") );
|
||||||
if(l>=sizeof(bufr))
|
if(l>=sizeof(bufr))
|
||||||
{
|
{
|
||||||
syslog(LOG_WARNING, "SendSSDPNotifies(): truncated output");
|
DPRINTF(E_WARN, L_SSDP, "SendSSDPNotifies(): truncated output\n");
|
||||||
l = sizeof(bufr);
|
l = sizeof(bufr);
|
||||||
}
|
}
|
||||||
//DEBUG printf("Sending NOTIFY:\n%s", bufr);
|
//DEBUG printf("Sending NOTIFY:\n%s", bufr);
|
||||||
@ -288,7 +286,7 @@ SendSSDPNotifies(int s, const char * host, unsigned short port,
|
|||||||
(struct sockaddr *)&sockname, sizeof(struct sockaddr_in) );
|
(struct sockaddr *)&sockname, sizeof(struct sockaddr_in) );
|
||||||
if(n < 0)
|
if(n < 0)
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR, "sendto(udp_notify=%d, %s): %m", s, host);
|
DPRINTF(E_ERROR, L_SSDP, "sendto(udp_notify=%d, %s): %s", s, host, strerror(errno));
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
@ -331,7 +329,7 @@ ProcessSSDPRequest(int s, unsigned short port)
|
|||||||
(struct sockaddr *)&sendername, &len_r);
|
(struct sockaddr *)&sendername, &len_r);
|
||||||
if(n < 0)
|
if(n < 0)
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR, "recvfrom(udp): %m");
|
DPRINTF(E_ERROR, L_SSDP, "recvfrom(udp): %s\n", strerror(errno));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -354,24 +352,24 @@ ProcessSSDPRequest(int s, unsigned short port)
|
|||||||
st_len = 0;
|
st_len = 0;
|
||||||
while(*st == ' ' || *st == '\t') st++;
|
while(*st == ' ' || *st == '\t') st++;
|
||||||
while(st[st_len]!='\r' && st[st_len]!='\n') st_len++;
|
while(st[st_len]!='\r' && st[st_len]!='\n') st_len++;
|
||||||
/*syslog(LOG_INFO, "ST: %.*s", st_len, st);*/
|
/*DPRINTF(E_INFO, L_SSDP, "ST: %.*s", st_len, st);*/
|
||||||
/*j = 0;*/
|
/*j = 0;*/
|
||||||
/*while(bufr[i+j]!='\r') j++;*/
|
/*while(bufr[i+j]!='\r') j++;*/
|
||||||
/*syslog(LOG_INFO, "%.*s", j, bufr+i);*/
|
/*DPRINTF(E_INFO, L_SSDP, "%.*s", j, bufr+i);*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*syslog(LOG_INFO, "SSDP M-SEARCH packet received from %s:%d",
|
/*DPRINTF(E_INFO, L_SSDP, "SSDP M-SEARCH packet received from %s:%d\n",
|
||||||
inet_ntoa(sendername.sin_addr),
|
inet_ntoa(sendername.sin_addr),
|
||||||
ntohs(sendername.sin_port) );*/
|
ntohs(sendername.sin_port) );*/
|
||||||
if( ntohs(sendername.sin_port) <= 1024 || ntohs(sendername.sin_port) == 1900 )
|
if( ntohs(sendername.sin_port) <= 1024 || ntohs(sendername.sin_port) == 1900 )
|
||||||
{
|
{
|
||||||
syslog(LOG_INFO, "WARNING: Ignoring invalid SSDP M-SEARCH from %s [bad source port %d]",
|
DPRINTF(E_INFO, L_SSDP, "WARNING: Ignoring invalid SSDP M-SEARCH from %s [bad source port %d]\n",
|
||||||
inet_ntoa(sendername.sin_addr), ntohs(sendername.sin_port));
|
inet_ntoa(sendername.sin_addr), ntohs(sendername.sin_port));
|
||||||
}
|
}
|
||||||
else if(st)
|
else if(st)
|
||||||
{
|
{
|
||||||
/* TODO : doesnt answer at once but wait for a random time */
|
/* TODO : doesnt answer at once but wait for a random time */
|
||||||
syslog(LOG_INFO, "SSDP M-SEARCH from %s:%d ST: %.*s",
|
DPRINTF(E_INFO, L_SSDP, "SSDP M-SEARCH from %s:%d ST: %.*s\n",
|
||||||
inet_ntoa(sendername.sin_addr),
|
inet_ntoa(sendername.sin_addr),
|
||||||
ntohs(sendername.sin_port),
|
ntohs(sendername.sin_port),
|
||||||
st_len, st);
|
st_len, st);
|
||||||
@ -419,13 +417,13 @@ ProcessSSDPRequest(int s, unsigned short port)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
syslog(LOG_INFO, "Invalid SSDP M-SEARCH from %s:%d",
|
DPRINTF(E_INFO, L_SSDP, "Invalid SSDP M-SEARCH from %s:%d\n",
|
||||||
inet_ntoa(sendername.sin_addr), ntohs(sendername.sin_port));
|
inet_ntoa(sendername.sin_addr), ntohs(sendername.sin_port));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
syslog(LOG_NOTICE, "Unknown udp packet received from %s:%d",
|
DPRINTF(E_WARN, L_SSDP, "Unknown udp packet received from %s:%d\n",
|
||||||
inet_ntoa(sendername.sin_addr), ntohs(sendername.sin_port));
|
inet_ntoa(sendername.sin_addr), ntohs(sendername.sin_port));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -463,7 +461,7 @@ SendSSDPGoodbye(int * sockets, int n_sockets)
|
|||||||
(struct sockaddr *)&sockname, sizeof(struct sockaddr_in) );
|
(struct sockaddr *)&sockname, sizeof(struct sockaddr_in) );
|
||||||
if(n < 0)
|
if(n < 0)
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR, "sendto(udp_shutdown=%d): %m", sockets[j]);
|
DPRINTF(E_ERROR, L_SSDP, "sendto(udp_shutdown=%d): %s\n", sockets[j], strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,6 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <syslog.h>
|
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
#include "upnpglobalvars.h"
|
#include "upnpglobalvars.h"
|
||||||
|
|
||||||
|
40
scanner.c
40
scanner.c
@ -31,6 +31,7 @@
|
|||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "sql.h"
|
#include "sql.h"
|
||||||
#include "scanner.h"
|
#include "scanner.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
struct virtual_item
|
struct virtual_item
|
||||||
{
|
{
|
||||||
@ -155,7 +156,7 @@ insert_containers(const char * name, const char *path, const char * refID, const
|
|||||||
if( strcmp(last_date.name, date_taken) == 0 )
|
if( strcmp(last_date.name, date_taken) == 0 )
|
||||||
{
|
{
|
||||||
last_date.objectID++;
|
last_date.objectID++;
|
||||||
//DEBUG printf("Using last date item: %s/%s/%X\n", last_date.name, last_date.parentID, last_date.objectID);
|
DPRINTF(E_DEBUG, L_SCANNER, "Using last date item: %s/%s/%X\n", last_date.name, last_date.parentID, last_date.objectID);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -163,7 +164,7 @@ insert_containers(const char * name, const char *path, const char * refID, const
|
|||||||
sprintf(last_date.parentID, "3$12$%llX", container>>32);
|
sprintf(last_date.parentID, "3$12$%llX", container>>32);
|
||||||
last_date.objectID = (int)container;
|
last_date.objectID = (int)container;
|
||||||
strcpy(last_date.name, date_taken);
|
strcpy(last_date.name, date_taken);
|
||||||
//DEBUG printf("Creating cached date item: %s/%s/%X\n", last_date.name, last_date.parentID, last_date.objectID);
|
DPRINTF(E_DEBUG, L_SCANNER, "Creating cached date item: %s/%s/%X\n", last_date.name, last_date.parentID, last_date.objectID);
|
||||||
}
|
}
|
||||||
sql = sqlite3_mprintf( "INSERT into OBJECTS"
|
sql = sqlite3_mprintf( "INSERT into OBJECTS"
|
||||||
" (OBJECT_ID, PARENT_ID, REF_ID, CLASS, DETAIL_ID, NAME) "
|
" (OBJECT_ID, PARENT_ID, REF_ID, CLASS, DETAIL_ID, NAME) "
|
||||||
@ -185,7 +186,7 @@ insert_containers(const char * name, const char *path, const char * refID, const
|
|||||||
if( strcmp(last_camdate.name, date_taken) == 0 )
|
if( strcmp(last_camdate.name, date_taken) == 0 )
|
||||||
{
|
{
|
||||||
last_camdate.objectID++;
|
last_camdate.objectID++;
|
||||||
//DEBUG printf("Using last camdate item: %s/%s/%s/%X\n", cam, last_camdate.name, last_camdate.parentID, last_camdate.objectID);
|
DPRINTF(E_DEBUG, L_SCANNER, "Using last camdate item: %s/%s/%s/%X\n", cam, last_camdate.name, last_camdate.parentID, last_camdate.objectID);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -193,7 +194,7 @@ insert_containers(const char * name, const char *path, const char * refID, const
|
|||||||
sprintf(last_camdate.parentID, "%s$%llX", last_cam.parentID, container>>32);
|
sprintf(last_camdate.parentID, "%s$%llX", last_cam.parentID, container>>32);
|
||||||
last_camdate.objectID = (int)container;
|
last_camdate.objectID = (int)container;
|
||||||
strcpy(last_camdate.name, date_taken);
|
strcpy(last_camdate.name, date_taken);
|
||||||
//DEBUG printf("Creating cached camdate item: %s/%s/%s/%X\n", cam, last_camdate.name, last_camdate.parentID, last_camdate.objectID);
|
DPRINTF(E_DEBUG, L_SCANNER, "Creating cached camdate item: %s/%s/%s/%X\n", cam, last_camdate.name, last_camdate.parentID, last_camdate.objectID);
|
||||||
}
|
}
|
||||||
sql = sqlite3_mprintf( "INSERT into OBJECTS"
|
sql = sqlite3_mprintf( "INSERT into OBJECTS"
|
||||||
" (OBJECT_ID, PARENT_ID, REF_ID, CLASS, DETAIL_ID, NAME) "
|
" (OBJECT_ID, PARENT_ID, REF_ID, CLASS, DETAIL_ID, NAME) "
|
||||||
@ -232,7 +233,7 @@ insert_containers(const char * name, const char *path, const char * refID, const
|
|||||||
if( strcmp(album, last_album.name) == 0 )
|
if( strcmp(album, last_album.name) == 0 )
|
||||||
{
|
{
|
||||||
last_album.objectID++;
|
last_album.objectID++;
|
||||||
//DEBUG printf("Using last album item: %s/%s/%X\n", last_album.name, last_album.parentID, last_album.objectID);
|
DPRINTF(E_DEBUG, L_SCANNER, "Using last album item: %s/%s/%X\n", last_album.name, last_album.parentID, last_album.objectID);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -240,7 +241,7 @@ insert_containers(const char * name, const char *path, const char * refID, const
|
|||||||
container = insert_container(album, "1$7", NULL, "album.musicAlbum", artist, genre, album_art, art_dlna_pn);
|
container = insert_container(album, "1$7", NULL, "album.musicAlbum", artist, genre, album_art, art_dlna_pn);
|
||||||
sprintf(last_album.parentID, "1$7$%llX", container>>32);
|
sprintf(last_album.parentID, "1$7$%llX", container>>32);
|
||||||
last_album.objectID = (int)container;
|
last_album.objectID = (int)container;
|
||||||
//DEBUG printf("Creating cached album item: %s/%s/%X\n", last_album.name, last_album.parentID, last_album.objectID);
|
DPRINTF(E_DEBUG, L_SCANNER, "Creating cached album item: %s/%s/%X\n", last_album.name, last_album.parentID, last_album.objectID);
|
||||||
}
|
}
|
||||||
sql = sqlite3_mprintf( "INSERT into OBJECTS"
|
sql = sqlite3_mprintf( "INSERT into OBJECTS"
|
||||||
" (OBJECT_ID, PARENT_ID, REF_ID, CLASS, DETAIL_ID, NAME) "
|
" (OBJECT_ID, PARENT_ID, REF_ID, CLASS, DETAIL_ID, NAME) "
|
||||||
@ -262,7 +263,7 @@ insert_containers(const char * name, const char *path, const char * refID, const
|
|||||||
if( strcmp(album?album:"Unknown", last_artistalbum.name) == 0 )
|
if( strcmp(album?album:"Unknown", last_artistalbum.name) == 0 )
|
||||||
{
|
{
|
||||||
last_artistalbum.objectID++;
|
last_artistalbum.objectID++;
|
||||||
//DEBUG printf("Using last artist/album item: %s/%s/%X\n", last_artist.name, last_artist.parentID, last_artist.objectID);
|
DPRINTF(E_DEBUG, L_SCANNER, "Using last artist/album item: %s/%s/%X\n", last_artist.name, last_artist.parentID, last_artist.objectID);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -270,7 +271,7 @@ insert_containers(const char * name, const char *path, const char * refID, const
|
|||||||
sprintf(last_artistalbum.parentID, "%s$%llX", last_artist.parentID, container>>32);
|
sprintf(last_artistalbum.parentID, "%s$%llX", last_artist.parentID, container>>32);
|
||||||
last_artistalbum.objectID = (int)container;
|
last_artistalbum.objectID = (int)container;
|
||||||
strcpy(last_artistalbum.name, album?album:"Unknown");
|
strcpy(last_artistalbum.name, album?album:"Unknown");
|
||||||
//DEBUG printf("Creating cached artist/album item: %s/%s/%X\n", last_artist.name, last_artist.parentID, last_artist.objectID);
|
DPRINTF(E_DEBUG, L_SCANNER, "Creating cached artist/album item: %s/%s/%X\n", last_artist.name, last_artist.parentID, last_artist.objectID);
|
||||||
}
|
}
|
||||||
sql = sqlite3_mprintf( "INSERT into OBJECTS"
|
sql = sqlite3_mprintf( "INSERT into OBJECTS"
|
||||||
" (OBJECT_ID, PARENT_ID, REF_ID, CLASS, DETAIL_ID, NAME) "
|
" (OBJECT_ID, PARENT_ID, REF_ID, CLASS, DETAIL_ID, NAME) "
|
||||||
@ -285,7 +286,7 @@ insert_containers(const char * name, const char *path, const char * refID, const
|
|||||||
if( strcmp(genre, last_genre.name) == 0 )
|
if( strcmp(genre, last_genre.name) == 0 )
|
||||||
{
|
{
|
||||||
last_genre.objectID++;
|
last_genre.objectID++;
|
||||||
//DEBUG printf("Using last genre item: %s/%s/%X\n", last_genre.name, last_genre.parentID, last_genre.objectID);
|
DPRINTF(E_DEBUG, L_SCANNER, "Using last genre item: %s/%s/%X\n", last_genre.name, last_genre.parentID, last_genre.objectID);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -293,7 +294,7 @@ insert_containers(const char * name, const char *path, const char * refID, const
|
|||||||
container = insert_container(genre, "1$5", NULL, "genre.musicGenre", NULL, NULL, NULL, NULL);
|
container = insert_container(genre, "1$5", NULL, "genre.musicGenre", NULL, NULL, NULL, NULL);
|
||||||
sprintf(last_genre.parentID, "1$5$%llX", container>>32);
|
sprintf(last_genre.parentID, "1$5$%llX", container>>32);
|
||||||
last_genre.objectID = (int)container;
|
last_genre.objectID = (int)container;
|
||||||
//DEBUG printf("Creating cached genre item: %s/%s/%X\n", last_genre.name, last_genre.parentID, last_genre.objectID);
|
DPRINTF(E_DEBUG, L_SCANNER, "Creating cached genre item: %s/%s/%X\n", last_genre.name, last_genre.parentID, last_genre.objectID);
|
||||||
}
|
}
|
||||||
sql = sqlite3_mprintf( "INSERT into OBJECTS"
|
sql = sqlite3_mprintf( "INSERT into OBJECTS"
|
||||||
" (OBJECT_ID, PARENT_ID, REF_ID, CLASS, DETAIL_ID, NAME) "
|
" (OBJECT_ID, PARENT_ID, REF_ID, CLASS, DETAIL_ID, NAME) "
|
||||||
@ -409,7 +410,7 @@ insert_directory(const char * name, const char * path, const char * base, const
|
|||||||
"VALUES"
|
"VALUES"
|
||||||
" ('%s%s$%X', '%s%s', %Q, '%lld', '%s', '%q')",
|
" ('%s%s$%X', '%s%s', %Q, '%lld', '%s', '%q')",
|
||||||
base, parentID, objectID, base, parentID, refID, detailID, class, name);
|
base, parentID, objectID, base, parentID, refID, detailID, class, name);
|
||||||
//DEBUG printf("SQL: %s\n", sql);
|
DPRINTF(E_DEBUG, L_SCANNER, "SQL: %s\n", sql);
|
||||||
ret = sql_exec(db, sql);
|
ret = sql_exec(db, sql);
|
||||||
sqlite3_free(sql);
|
sqlite3_free(sql);
|
||||||
if( refID )
|
if( refID )
|
||||||
@ -430,9 +431,6 @@ insert_file(char * name, const char * path, const char * parentID, int object)
|
|||||||
int typedir_objectID;
|
int typedir_objectID;
|
||||||
char * baseid;
|
char * baseid;
|
||||||
|
|
||||||
static long unsigned int fileno = 0;
|
|
||||||
printf("Scanned %lu files...\r", fileno++); fflush(stdout);
|
|
||||||
|
|
||||||
if( is_image(name) )
|
if( is_image(name) )
|
||||||
{
|
{
|
||||||
strcpy(base, IMAGE_DIR_ID);
|
strcpy(base, IMAGE_DIR_ID);
|
||||||
@ -451,7 +449,7 @@ insert_file(char * name, const char * path, const char * parentID, int object)
|
|||||||
strcpy(class, "item.videoItem");
|
strcpy(class, "item.videoItem");
|
||||||
detailID = GetVideoMetadata(path, name);
|
detailID = GetVideoMetadata(path, name);
|
||||||
}
|
}
|
||||||
//DEBUG printf("Got DetailID %lu!\n", detailID);
|
DPRINTF(E_DEBUG, L_SCANNER, "Got DetailID %lu!\n", detailID);
|
||||||
if( !detailID )
|
if( !detailID )
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@ -462,7 +460,7 @@ insert_file(char * name, const char * path, const char * parentID, int object)
|
|||||||
"VALUES"
|
"VALUES"
|
||||||
" ('%s', '%s%s', '%s', %lu, '%q')",
|
" ('%s', '%s%s', '%s', %lu, '%q')",
|
||||||
objectID, BROWSEDIR_ID, parentID, class, detailID, name);
|
objectID, BROWSEDIR_ID, parentID, class, detailID, name);
|
||||||
//DEBUG printf("SQL: %s\n", sql);
|
DPRINTF(E_DEBUG, L_SCANNER, "SQL: %s\n", sql);
|
||||||
sql_exec(db, sql);
|
sql_exec(db, sql);
|
||||||
sqlite3_free(sql);
|
sqlite3_free(sql);
|
||||||
|
|
||||||
@ -484,7 +482,7 @@ insert_file(char * name, const char * path, const char * parentID, int object)
|
|||||||
"VALUES"
|
"VALUES"
|
||||||
" ('%s%s$%X', '%s%s', '%s', '%s', %lu, '%q')",
|
" ('%s%s$%X', '%s%s', '%s', '%s', %lu, '%q')",
|
||||||
base, parentID, object, base, parentID, objectID, class, detailID, name);
|
base, parentID, object, base, parentID, objectID, class, detailID, name);
|
||||||
//DEBUG printf("SQL: %s\n", sql);
|
DPRINTF(E_DEBUG, L_SCANNER, "SQL: %s\n", sql);
|
||||||
sql_exec(db, sql);
|
sql_exec(db, sql);
|
||||||
sqlite3_free(sql);
|
sqlite3_free(sql);
|
||||||
|
|
||||||
@ -652,12 +650,13 @@ ScanDirectory(const char * dir, const char * parent, enum media_types type)
|
|||||||
char parent_id[PATH_MAX];
|
char parent_id[PATH_MAX];
|
||||||
char full_path[PATH_MAX];
|
char full_path[PATH_MAX];
|
||||||
char * name = NULL;
|
char * name = NULL;
|
||||||
|
static long long unsigned int fileno = 0;
|
||||||
|
|
||||||
setlocale(LC_COLLATE, "");
|
setlocale(LC_COLLATE, "");
|
||||||
if( chdir(dir) != 0 )
|
if( chdir(dir) != 0 )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
printf("\nScanning %s\n", dir);
|
DPRINTF(E_INFO, L_SCANNER, "Scanning %s\n", dir);
|
||||||
switch( type )
|
switch( type )
|
||||||
{
|
{
|
||||||
case ALL_MEDIA:
|
case ALL_MEDIA:
|
||||||
@ -697,7 +696,8 @@ ScanDirectory(const char * dir, const char * parent, enum media_types type)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
insert_file(name?name:namelist[i]->d_name, full_path, (parent ? parent:""), i+startID);
|
if( insert_file(name?name:namelist[i]->d_name, full_path, (parent ? parent:""), i+startID) == 0 )
|
||||||
|
fileno++;
|
||||||
}
|
}
|
||||||
if( name )
|
if( name )
|
||||||
{
|
{
|
||||||
@ -713,7 +713,7 @@ ScanDirectory(const char * dir, const char * parent, enum media_types type)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
printf("Scanning %s finished!\n", dir);
|
DPRINTF(E_INFO, L_SCANNER, "Scanning %s finished (%llu files)!\n", dir, fileno);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,12 +9,8 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <syslog.h>
|
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#ifdef ENABLE_EVENTS
|
|
||||||
#include "getifaddr.h"
|
#include "getifaddr.h"
|
||||||
#endif
|
|
||||||
#include "upnpdescgen.h"
|
#include "upnpdescgen.h"
|
||||||
#include "minidlnapath.h"
|
#include "minidlnapath.h"
|
||||||
#include "upnpglobalvars.h"
|
#include "upnpglobalvars.h"
|
||||||
|
36
upnpevents.c
36
upnpevents.c
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <syslog.h>
|
#include <errno.h>
|
||||||
#include <sys/queue.h>
|
#include <sys/queue.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@ -18,11 +18,13 @@
|
|||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "upnpevents.h"
|
#include "upnpevents.h"
|
||||||
#include "minidlnapath.h"
|
#include "minidlnapath.h"
|
||||||
#include "upnpglobalvars.h"
|
#include "upnpglobalvars.h"
|
||||||
#include "upnpdescgen.h"
|
#include "upnpdescgen.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
#define HAVE_UUID 1
|
#define HAVE_UUID 1
|
||||||
|
|
||||||
@ -121,7 +123,7 @@ upnpevents_addSubscriber(const char * eventurl,
|
|||||||
struct subscriber * tmp;
|
struct subscriber * tmp;
|
||||||
/*static char uuid[42];*/
|
/*static char uuid[42];*/
|
||||||
/* "uuid:00000000-0000-0000-0000-000000000000"; 5+36+1=42bytes */
|
/* "uuid:00000000-0000-0000-0000-000000000000"; 5+36+1=42bytes */
|
||||||
syslog(LOG_DEBUG, "addSubscriber(%s, %.*s, %d)",
|
DPRINTF(E_DEBUG, L_HTTP, "addSubscriber(%s, %.*s, %d)\n",
|
||||||
eventurl, callbacklen, callback, timeout);
|
eventurl, callbacklen, callback, timeout);
|
||||||
/*strncpy(uuid, uuidvalue, sizeof(uuid));
|
/*strncpy(uuid, uuidvalue, sizeof(uuid));
|
||||||
uuid[sizeof(uuid)-1] = '\0';*/
|
uuid[sizeof(uuid)-1] = '\0';*/
|
||||||
@ -188,24 +190,24 @@ upnp_event_create_notify(struct subscriber * sub)
|
|||||||
int flags;
|
int flags;
|
||||||
obj = calloc(1, sizeof(struct upnp_event_notify));
|
obj = calloc(1, sizeof(struct upnp_event_notify));
|
||||||
if(!obj) {
|
if(!obj) {
|
||||||
syslog(LOG_ERR, "%s: calloc(): %m", "upnp_event_create_notify");
|
DPRINTF(E_ERROR, L_HTTP, "%s: calloc(): %s\n", "upnp_event_create_notify", strerror(errno));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
obj->sub = sub;
|
obj->sub = sub;
|
||||||
obj->state = ECreated;
|
obj->state = ECreated;
|
||||||
obj->s = socket(PF_INET, SOCK_STREAM, 0);
|
obj->s = socket(PF_INET, SOCK_STREAM, 0);
|
||||||
if(obj->s<0) {
|
if(obj->s<0) {
|
||||||
syslog(LOG_ERR, "%s: socket(): %m", "upnp_event_create_notify");
|
DPRINTF(E_ERROR, L_HTTP, "%s: socket(): %s\n", "upnp_event_create_notify", strerror(errno));
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if((flags = fcntl(obj->s, F_GETFL, 0)) < 0) {
|
if((flags = fcntl(obj->s, F_GETFL, 0)) < 0) {
|
||||||
syslog(LOG_ERR, "%s: fcntl(..F_GETFL..): %m",
|
DPRINTF(E_ERROR, L_HTTP, "%s: fcntl(..F_GETFL..): %s\n",
|
||||||
"upnp_event_create_notify");
|
"upnp_event_create_notify", strerror(errno));
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if(fcntl(obj->s, F_SETFL, flags | O_NONBLOCK) < 0) {
|
if(fcntl(obj->s, F_SETFL, flags | O_NONBLOCK) < 0) {
|
||||||
syslog(LOG_ERR, "%s: fcntl(..F_SETFL..): %m",
|
DPRINTF(E_ERROR, L_HTTP, "%s: fcntl(..F_SETFL..): %s\n",
|
||||||
"upnp_event_create_notify");
|
"upnp_event_create_notify", strerror(errno));
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if(sub)
|
if(sub)
|
||||||
@ -256,12 +258,12 @@ upnp_event_notify_connect(struct upnp_event_notify * obj)
|
|||||||
addr.sin_family = AF_INET;
|
addr.sin_family = AF_INET;
|
||||||
inet_aton(obj->addrstr, &addr.sin_addr);
|
inet_aton(obj->addrstr, &addr.sin_addr);
|
||||||
addr.sin_port = htons(port);
|
addr.sin_port = htons(port);
|
||||||
syslog(LOG_DEBUG, "%s: '%s' %hu '%s'", "upnp_event_notify_connect",
|
DPRINTF(E_DEBUG, L_HTTP, "%s: '%s' %hu '%s'\n", "upnp_event_notify_connect",
|
||||||
obj->addrstr, port, obj->path);
|
obj->addrstr, port, obj->path);
|
||||||
obj->state = EConnecting;
|
obj->state = EConnecting;
|
||||||
if(connect(obj->s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
if(connect(obj->s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
||||||
if(errno != EINPROGRESS && errno != EWOULDBLOCK) {
|
if(errno != EINPROGRESS && errno != EWOULDBLOCK) {
|
||||||
syslog(LOG_ERR, "%s: connect(): %m", "upnp_event_notify_connect");
|
DPRINTF(E_ERROR, L_HTTP, "%s: connect(): %s\n", "upnp_event_notify_connect", strerror(errno));
|
||||||
obj->state = EError;
|
obj->state = EError;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -323,12 +325,12 @@ static void upnp_event_send(struct upnp_event_notify * obj)
|
|||||||
int i;
|
int i;
|
||||||
i = send(obj->s, obj->buffer + obj->sent, obj->tosend - obj->sent, 0);
|
i = send(obj->s, obj->buffer + obj->sent, obj->tosend - obj->sent, 0);
|
||||||
if(i<0) {
|
if(i<0) {
|
||||||
syslog(LOG_NOTICE, "%s: send(): %m", "upnp_event_send");
|
DPRINTF(E_WARN, L_HTTP, "%s: send(): %s\n", "upnp_event_send", strerror(errno));
|
||||||
obj->state = EError;
|
obj->state = EError;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if(i != (obj->tosend - obj->sent))
|
else if(i != (obj->tosend - obj->sent))
|
||||||
syslog(LOG_NOTICE, "%s: %d bytes send out of %d",
|
DPRINTF(E_WARN, L_HTTP, "%s: %d bytes send out of %d\n",
|
||||||
"upnp_event_send", i, obj->tosend - obj->sent);
|
"upnp_event_send", i, obj->tosend - obj->sent);
|
||||||
obj->sent += i;
|
obj->sent += i;
|
||||||
if(obj->sent == obj->tosend)
|
if(obj->sent == obj->tosend)
|
||||||
@ -340,11 +342,11 @@ static void upnp_event_recv(struct upnp_event_notify * obj)
|
|||||||
int n;
|
int n;
|
||||||
n = recv(obj->s, obj->buffer, obj->buffersize, 0);
|
n = recv(obj->s, obj->buffer, obj->buffersize, 0);
|
||||||
if(n<0) {
|
if(n<0) {
|
||||||
syslog(LOG_ERR, "%s: recv(): %m", "upnp_event_recv");
|
DPRINTF(E_ERROR, L_HTTP, "%s: recv(): %s\n", "upnp_event_recv", strerror(errno));
|
||||||
obj->state = EError;
|
obj->state = EError;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
syslog(LOG_DEBUG, "%s: (%dbytes) %.*s", "upnp_event_recv",
|
DPRINTF(E_DEBUG, L_HTTP, "%s: (%dbytes) %.*s\n", "upnp_event_recv",
|
||||||
n, n, obj->buffer);
|
n, n, obj->buffer);
|
||||||
obj->state = EFinished;
|
obj->state = EFinished;
|
||||||
if(obj->sub)
|
if(obj->sub)
|
||||||
@ -371,7 +373,7 @@ upnp_event_process_notify(struct upnp_event_notify * obj)
|
|||||||
obj->s = -1;
|
obj->s = -1;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
syslog(LOG_ERR, "upnp_event_process_notify: unknown state");
|
DPRINTF(E_ERROR, L_HTTP, "upnp_event_process_notify: unknown state\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -379,7 +381,7 @@ void upnpevents_selectfds(fd_set *readset, fd_set *writeset, int * max_fd)
|
|||||||
{
|
{
|
||||||
struct upnp_event_notify * obj;
|
struct upnp_event_notify * obj;
|
||||||
for(obj = notifylist.lh_first; obj != NULL; obj = obj->entries.le_next) {
|
for(obj = notifylist.lh_first; obj != NULL; obj = obj->entries.le_next) {
|
||||||
syslog(LOG_DEBUG, "upnpevents_selectfds: %p %d %d",
|
DPRINTF(E_DEBUG, L_HTTP, "upnpevents_selectfds: %p %d %d\n",
|
||||||
obj, obj->state, obj->s);
|
obj, obj->state, obj->s);
|
||||||
if(obj->s >= 0) {
|
if(obj->s >= 0) {
|
||||||
switch(obj->state) {
|
switch(obj->state) {
|
||||||
@ -413,7 +415,7 @@ void upnpevents_processfds(fd_set *readset, fd_set *writeset)
|
|||||||
struct subscriber * subnext;
|
struct subscriber * subnext;
|
||||||
time_t curtime;
|
time_t curtime;
|
||||||
for(obj = notifylist.lh_first; obj != NULL; obj = obj->entries.le_next) {
|
for(obj = notifylist.lh_first; obj != NULL; obj = obj->entries.le_next) {
|
||||||
syslog(LOG_DEBUG, "%s: %p %d %d %d %d",
|
DPRINTF(E_DEBUG, L_HTTP, "%s: %p %d %d %d %d\n",
|
||||||
"upnpevents_processfds", obj, obj->state, obj->s,
|
"upnpevents_processfds", obj, obj->state, obj->s,
|
||||||
FD_ISSET(obj->s, readset), FD_ISSET(obj->s, writeset));
|
FD_ISSET(obj->s, readset), FD_ISSET(obj->s, writeset));
|
||||||
if(obj->s >= 0) {
|
if(obj->s >= 0) {
|
||||||
|
151
upnphttp.c
151
upnphttp.c
@ -17,7 +17,6 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <syslog.h>
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "upnphttp.h"
|
#include "upnphttp.h"
|
||||||
@ -34,6 +33,7 @@
|
|||||||
|
|
||||||
#include "upnpglobalvars.h"
|
#include "upnpglobalvars.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
#include "log.h"
|
||||||
#include <sqlite3.h>
|
#include <sqlite3.h>
|
||||||
#include <libexif/exif-loader.h>
|
#include <libexif/exif-loader.h>
|
||||||
#if 0 //JPEG_RESIZE
|
#if 0 //JPEG_RESIZE
|
||||||
@ -61,7 +61,7 @@ CloseSocket_upnphttp(struct upnphttp * h)
|
|||||||
{
|
{
|
||||||
if(close(h->socket) < 0)
|
if(close(h->socket) < 0)
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR, "CloseSocket_upnphttp: close(%d): %m", h->socket);
|
DPRINTF(E_ERROR, L_HTTP, "CloseSocket_upnphttp: close(%d): %s\n", h->socket, strerror(errno));
|
||||||
}
|
}
|
||||||
h->socket = -1;
|
h->socket = -1;
|
||||||
h->state = 100;
|
h->state = 100;
|
||||||
@ -103,9 +103,6 @@ ParseHttpHeaders(struct upnphttp * h)
|
|||||||
while(*p < '0' || *p > '9')
|
while(*p < '0' || *p > '9')
|
||||||
p++;
|
p++;
|
||||||
h->req_contentlen = atoi(p);
|
h->req_contentlen = atoi(p);
|
||||||
/*printf("*** Content-Lenght = %d ***\n", h->req_contentlen);
|
|
||||||
printf(" readbufflen=%d contentoff = %d\n",
|
|
||||||
h->req_buflen, h->req_contentoff);*/
|
|
||||||
}
|
}
|
||||||
else if(strncasecmp(line, "SOAPAction", 10)==0)
|
else if(strncasecmp(line, "SOAPAction", 10)==0)
|
||||||
{
|
{
|
||||||
@ -176,7 +173,7 @@ intervening space) by either an integer or the keyword "infinite". */
|
|||||||
h->reqflags |= FLAG_RANGE;
|
h->reqflags |= FLAG_RANGE;
|
||||||
h->req_RangeEnd = atoll(index(p+6, '-')+1);
|
h->req_RangeEnd = atoll(index(p+6, '-')+1);
|
||||||
h->req_RangeStart = atoll(p+6);
|
h->req_RangeStart = atoll(p+6);
|
||||||
printf("Range Start-End: %lld - %lld\n",
|
DPRINTF(E_DEBUG, L_HTTP, "Range Start-End: %lld - %lld\n",
|
||||||
h->req_RangeStart, h->req_RangeEnd?h->req_RangeEnd:-1);
|
h->req_RangeStart, h->req_RangeEnd?h->req_RangeEnd:-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -282,20 +279,6 @@ Send400(struct upnphttp * h)
|
|||||||
static void
|
static void
|
||||||
Send404(struct upnphttp * h)
|
Send404(struct upnphttp * h)
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
static const char error404[] = "HTTP/1.1 404 Not found\r\n"
|
|
||||||
"Connection: close\r\n"
|
|
||||||
"Content-type: text/html\r\n"
|
|
||||||
"\r\n"
|
|
||||||
"<HTML><HEAD><TITLE>404 Not Found</TITLE></HEAD>"
|
|
||||||
"<BODY><H1>Not Found</H1>The requested URL was not found"
|
|
||||||
" on this server.</BODY></HTML>\r\n";
|
|
||||||
int n;
|
|
||||||
n = send(h->socket, error404, sizeof(error404) - 1, 0);
|
|
||||||
if(n < 0)
|
|
||||||
{
|
|
||||||
syslog(LOG_ERR, "Send404: send(http): %m");
|
|
||||||
}*/
|
|
||||||
static const char body404[] =
|
static const char body404[] =
|
||||||
"<HTML><HEAD><TITLE>404 Not Found</TITLE></HEAD>"
|
"<HTML><HEAD><TITLE>404 Not Found</TITLE></HEAD>"
|
||||||
"<BODY><H1>Not Found</H1>The requested URL was not found"
|
"<BODY><H1>Not Found</H1>The requested URL was not found"
|
||||||
@ -307,7 +290,7 @@ Send404(struct upnphttp * h)
|
|||||||
CloseSocket_upnphttp(h);
|
CloseSocket_upnphttp(h);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* very minimalistic 404 error message */
|
/* very minimalistic 406 error message */
|
||||||
static void
|
static void
|
||||||
Send406(struct upnphttp * h)
|
Send406(struct upnphttp * h)
|
||||||
{
|
{
|
||||||
@ -322,7 +305,7 @@ Send406(struct upnphttp * h)
|
|||||||
CloseSocket_upnphttp(h);
|
CloseSocket_upnphttp(h);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* very minimalistic 404 error message */
|
/* very minimalistic 416 error message */
|
||||||
static void
|
static void
|
||||||
Send416(struct upnphttp * h)
|
Send416(struct upnphttp * h)
|
||||||
{
|
{
|
||||||
@ -341,21 +324,6 @@ Send416(struct upnphttp * h)
|
|||||||
static void
|
static void
|
||||||
Send501(struct upnphttp * h)
|
Send501(struct upnphttp * h)
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
static const char error501[] = "HTTP/1.1 501 Not Implemented\r\n"
|
|
||||||
"Connection: close\r\n"
|
|
||||||
"Content-type: text/html\r\n"
|
|
||||||
"\r\n"
|
|
||||||
"<HTML><HEAD><TITLE>501 Not Implemented</TITLE></HEAD>"
|
|
||||||
"<BODY><H1>Not Implemented</H1>The HTTP Method "
|
|
||||||
"is not implemented by this server.</BODY></HTML>\r\n";
|
|
||||||
int n;
|
|
||||||
n = send(h->socket, error501, sizeof(error501) - 1, 0);
|
|
||||||
if(n < 0)
|
|
||||||
{
|
|
||||||
syslog(LOG_ERR, "Send501: send(http): %m");
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
static const char body501[] =
|
static const char body501[] =
|
||||||
"<HTML><HEAD><TITLE>501 Not Implemented</TITLE></HEAD>"
|
"<HTML><HEAD><TITLE>501 Not Implemented</TITLE></HEAD>"
|
||||||
"<BODY><H1>Not Implemented</H1>The HTTP Method "
|
"<BODY><H1>Not Implemented</H1>The HTTP Method "
|
||||||
@ -390,7 +358,7 @@ sendXMLdesc(struct upnphttp * h, char * (f)(int *))
|
|||||||
{
|
{
|
||||||
static const char error500[] = "<HTML><HEAD><TITLE>Error 500</TITLE>"
|
static const char error500[] = "<HTML><HEAD><TITLE>Error 500</TITLE>"
|
||||||
"</HEAD><BODY>Internal Server Error</BODY></HTML>\r\n";
|
"</HEAD><BODY>Internal Server Error</BODY></HTML>\r\n";
|
||||||
syslog(LOG_ERR, "Failed to generate XML description");
|
DPRINTF(E_ERROR, L_HTTP, "Failed to generate XML description\n");
|
||||||
h->respflags = FLAG_HTML;
|
h->respflags = FLAG_HTML;
|
||||||
BuildResp2_upnphttp(h, 500, "Internal Server Error",
|
BuildResp2_upnphttp(h, 500, "Internal Server Error",
|
||||||
error500, sizeof(error500)-1);
|
error500, sizeof(error500)-1);
|
||||||
@ -414,10 +382,7 @@ ProcessHTTPPOST_upnphttp(struct upnphttp * h)
|
|||||||
if(h->req_soapAction)
|
if(h->req_soapAction)
|
||||||
{
|
{
|
||||||
/* we can process the request */
|
/* we can process the request */
|
||||||
//printf("__LINE %d__ SOAPAction: %s [%d]\n", __LINE__, h->req_soapAction, h->req_soapActionLen);
|
DPRINTF(E_DEBUG, L_HTTP, "SOAPAction: %.*s\n", h->req_soapActionLen, h->req_soapAction);
|
||||||
// syslog(LOG_INFO, "SOAPAction: %.*s",
|
|
||||||
// h->req_soapActionLen, h->req_soapAction);
|
|
||||||
//printf("__LINE %d__ SOAPAction: %.*s\n", __LINE__, h->req_soapActionLen, h->req_soapAction);
|
|
||||||
ExecuteSoapAction(h,
|
ExecuteSoapAction(h,
|
||||||
h->req_soapAction,
|
h->req_soapAction,
|
||||||
h->req_soapActionLen);
|
h->req_soapActionLen);
|
||||||
@ -426,7 +391,7 @@ ProcessHTTPPOST_upnphttp(struct upnphttp * h)
|
|||||||
{
|
{
|
||||||
static const char err400str[] =
|
static const char err400str[] =
|
||||||
"<html><body>Bad request</body></html>";
|
"<html><body>Bad request</body></html>";
|
||||||
syslog(LOG_INFO, "No SOAPAction in HTTP headers");
|
DPRINTF(E_WARN, L_HTTP, "No SOAPAction in HTTP headers");
|
||||||
h->respflags = FLAG_HTML;
|
h->respflags = FLAG_HTML;
|
||||||
BuildResp2_upnphttp(h, 400, "Bad Request",
|
BuildResp2_upnphttp(h, 400, "Bad Request",
|
||||||
err400str, sizeof(err400str) - 1);
|
err400str, sizeof(err400str) - 1);
|
||||||
@ -446,10 +411,10 @@ static void
|
|||||||
ProcessHTTPSubscribe_upnphttp(struct upnphttp * h, const char * path)
|
ProcessHTTPSubscribe_upnphttp(struct upnphttp * h, const char * path)
|
||||||
{
|
{
|
||||||
const char * sid;
|
const char * sid;
|
||||||
syslog(LOG_DEBUG, "ProcessHTTPSubscribe %s", path);
|
DPRINTF(E_DEBUG, L_HTTP, "ProcessHTTPSubscribe %s\n", path);
|
||||||
syslog(LOG_DEBUG, "Callback '%.*s' Timeout=%d",
|
DPRINTF(E_DEBUG, L_HTTP, "Callback '%.*s' Timeout=%d\n",
|
||||||
h->req_CallbackLen, h->req_Callback, h->req_Timeout);
|
h->req_CallbackLen, h->req_Callback, h->req_Timeout);
|
||||||
syslog(LOG_DEBUG, "SID '%.*s'", h->req_SIDLen, h->req_SID);
|
DPRINTF(E_DEBUG, L_HTTP, "SID '%.*s'\n", h->req_SIDLen, h->req_SID);
|
||||||
if(!h->req_Callback && !h->req_SID) {
|
if(!h->req_Callback && !h->req_SID) {
|
||||||
/* Missing or invalid CALLBACK : 412 Precondition Failed.
|
/* Missing or invalid CALLBACK : 412 Precondition Failed.
|
||||||
* If CALLBACK header is missing or does not contain a valid HTTP URL,
|
* If CALLBACK header is missing or does not contain a valid HTTP URL,
|
||||||
@ -467,7 +432,7 @@ ProcessHTTPSubscribe_upnphttp(struct upnphttp * h, const char * path)
|
|||||||
h->req_CallbackLen, h->req_Timeout);
|
h->req_CallbackLen, h->req_Timeout);
|
||||||
h->respflags = FLAG_TIMEOUT;
|
h->respflags = FLAG_TIMEOUT;
|
||||||
if(sid) {
|
if(sid) {
|
||||||
syslog(LOG_DEBUG, "generated sid=%s", sid);
|
DPRINTF(E_DEBUG, L_HTTP, "generated sid=%s\n", sid);
|
||||||
h->respflags |= FLAG_SID;
|
h->respflags |= FLAG_SID;
|
||||||
h->req_SID = sid;
|
h->req_SID = sid;
|
||||||
h->req_SIDLen = strlen(sid);
|
h->req_SIDLen = strlen(sid);
|
||||||
@ -496,8 +461,8 @@ with HTTP error 412 Precondition Failed. */
|
|||||||
static void
|
static void
|
||||||
ProcessHTTPUnSubscribe_upnphttp(struct upnphttp * h, const char * path)
|
ProcessHTTPUnSubscribe_upnphttp(struct upnphttp * h, const char * path)
|
||||||
{
|
{
|
||||||
syslog(LOG_DEBUG, "ProcessHTTPUnSubscribe %s", path);
|
DPRINTF(E_DEBUG, L_HTTP, "ProcessHTTPUnSubscribe %s\n", path);
|
||||||
syslog(LOG_DEBUG, "SID '%.*s'", h->req_SIDLen, h->req_SID);
|
DPRINTF(E_DEBUG, L_HTTP, "SID '%.*s'\n", h->req_SIDLen, h->req_SID);
|
||||||
/* Remove from the list */
|
/* Remove from the list */
|
||||||
if(upnpevents_removeSubscriber(h->req_SID, h->req_SIDLen) < 0) {
|
if(upnpevents_removeSubscriber(h->req_SID, h->req_SIDLen) < 0) {
|
||||||
BuildResp2_upnphttp(h, 412, "Precondition Failed", 0, 0);
|
BuildResp2_upnphttp(h, 412, "Precondition Failed", 0, 0);
|
||||||
@ -542,9 +507,9 @@ ProcessHttpQuery_upnphttp(struct upnphttp * h)
|
|||||||
for(i = 0; i<15 && *p != '\r'; i++)
|
for(i = 0; i<15 && *p != '\r'; i++)
|
||||||
HttpVer[i] = *(p++);
|
HttpVer[i] = *(p++);
|
||||||
HttpVer[i] = '\0';
|
HttpVer[i] = '\0';
|
||||||
syslog(LOG_INFO, "HTTP REQUEST : %s %s (%s)",
|
DPRINTF(E_INFO, L_HTTP, "HTTP REQUEST : %s %s (%s)\n",
|
||||||
HttpCommand, HttpUrl, HttpVer);
|
HttpCommand, HttpUrl, HttpVer);
|
||||||
printf("HTTP REQUEST:\n%.*s\n", h->req_buflen, h->req_buf);
|
DPRINTF(E_DEBUG, L_HTTP, "HTTP REQUEST:\n%.*s\n", h->req_buflen, h->req_buf);
|
||||||
ParseHttpHeaders(h);
|
ParseHttpHeaders(h);
|
||||||
|
|
||||||
/* see if we need to wait for remaining data */
|
/* see if we need to wait for remaining data */
|
||||||
@ -561,7 +526,7 @@ ProcessHttpQuery_upnphttp(struct upnphttp * h)
|
|||||||
h->req_chunklen = strtol(numstart, &chunkstart, 16);
|
h->req_chunklen = strtol(numstart, &chunkstart, 16);
|
||||||
if( !h->req_chunklen && (chunkstart == numstart) )
|
if( !h->req_chunklen && (chunkstart == numstart) )
|
||||||
{
|
{
|
||||||
printf("Chunked request needs more input.\n");
|
DPRINTF(E_DEBUG, L_HTTP, "Chunked request needs more input.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
chunkstart = chunkstart+2;
|
chunkstart = chunkstart+2;
|
||||||
@ -577,12 +542,12 @@ ProcessHttpQuery_upnphttp(struct upnphttp * h)
|
|||||||
{
|
{
|
||||||
if( ((strcmp(h->HttpVer, "HTTP/1.1")==0) && !(h->reqflags & FLAG_HOST)) || (h->reqflags & FLAG_INVALID_REQ) )
|
if( ((strcmp(h->HttpVer, "HTTP/1.1")==0) && !(h->reqflags & FLAG_HOST)) || (h->reqflags & FLAG_INVALID_REQ) )
|
||||||
{
|
{
|
||||||
syslog(LOG_NOTICE, "Invalid request, responding ERROR 400. (No Host specified in HTTP headers?)");
|
DPRINTF(E_WARN, L_HTTP, "Invalid request, responding ERROR 400. (No Host specified in HTTP headers?)\n");
|
||||||
Send400(h);
|
Send400(h);
|
||||||
}
|
}
|
||||||
else if( h->reqflags & FLAG_TIMESEEK )
|
else if( h->reqflags & FLAG_TIMESEEK )
|
||||||
{
|
{
|
||||||
syslog(LOG_NOTICE, "DLNA TimeSeek requested, responding ERROR 406");
|
DPRINTF(E_WARN, L_HTTP, "DLNA TimeSeek requested, responding ERROR 406\n");
|
||||||
Send406(h);
|
Send406(h);
|
||||||
}
|
}
|
||||||
else if(strcmp("GET", HttpCommand) == 0)
|
else if(strcmp("GET", HttpCommand) == 0)
|
||||||
@ -633,11 +598,10 @@ ProcessHttpQuery_upnphttp(struct upnphttp * h)
|
|||||||
#endif
|
#endif
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
syslog(LOG_NOTICE, "%s not found, responding ERROR 404", HttpUrl);
|
DPRINTF(E_WARN, L_HTTP, "%s not found, responding ERROR 404\n", HttpUrl);
|
||||||
Send404(h);
|
Send404(h);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef ENABLE_EVENTS
|
|
||||||
else if(strcmp("SUBSCRIBE", HttpCommand) == 0)
|
else if(strcmp("SUBSCRIBE", HttpCommand) == 0)
|
||||||
{
|
{
|
||||||
h->req_command = ESubscribe;
|
h->req_command = ESubscribe;
|
||||||
@ -648,16 +612,9 @@ ProcessHttpQuery_upnphttp(struct upnphttp * h)
|
|||||||
h->req_command = EUnSubscribe;
|
h->req_command = EUnSubscribe;
|
||||||
ProcessHTTPUnSubscribe_upnphttp(h, HttpUrl);
|
ProcessHTTPUnSubscribe_upnphttp(h, HttpUrl);
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
else if(strcmp("SUBSCRIBE", HttpCommand) == 0)
|
|
||||||
{
|
|
||||||
syslog(LOG_NOTICE, "SUBSCRIBE not implemented. ENABLE_EVENTS compile option disabled");
|
|
||||||
Send501(h);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
syslog(LOG_NOTICE, "Unsupported HTTP Command %s", HttpCommand);
|
DPRINTF(E_WARN, L_HTTP, "Unsupported HTTP Command %s\n", HttpCommand);
|
||||||
Send501(h);
|
Send501(h);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -676,12 +633,12 @@ Process_upnphttp(struct upnphttp * h)
|
|||||||
n = recv(h->socket, buf, 2048, 0);
|
n = recv(h->socket, buf, 2048, 0);
|
||||||
if(n<0)
|
if(n<0)
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR, "recv (state0): %m");
|
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)
|
||||||
{
|
{
|
||||||
syslog(LOG_WARNING, "HTTP Connection closed inexpectedly");
|
DPRINTF(E_WARN, L_HTTP, "HTTP Connection closed inexpectedly\n");
|
||||||
h->state = 100;
|
h->state = 100;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -707,12 +664,12 @@ Process_upnphttp(struct upnphttp * h)
|
|||||||
n = recv(h->socket, buf, 2048, 0);
|
n = recv(h->socket, buf, 2048, 0);
|
||||||
if(n<0)
|
if(n<0)
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR, "recv (state1): %m");
|
DPRINTF(E_ERROR, L_HTTP, "recv (state1): %s\n", strerror(errno));
|
||||||
h->state = 100;
|
h->state = 100;
|
||||||
}
|
}
|
||||||
else if(n==0)
|
else if(n==0)
|
||||||
{
|
{
|
||||||
syslog(LOG_WARNING, "HTTP Connection closed inexpectedly");
|
DPRINTF(E_WARN, L_HTTP, "HTTP Connection closed inexpectedly\n");
|
||||||
h->state = 100;
|
h->state = 100;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -731,7 +688,7 @@ Process_upnphttp(struct upnphttp * h)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
syslog(LOG_WARNING, "Unexpected state: %d", h->state);
|
DPRINTF(E_WARN, L_HTTP, "Unexpected state: %d\n", h->state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -850,16 +807,16 @@ void
|
|||||||
SendResp_upnphttp(struct upnphttp * h)
|
SendResp_upnphttp(struct upnphttp * h)
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
printf("HTTP RESPONSE:\n%.*s\n", h->res_buflen, h->res_buf);
|
DPRINTF(E_DEBUG, L_HTTP, "HTTP RESPONSE:\n%.*s\n", h->res_buflen, h->res_buf);
|
||||||
n = send(h->socket, h->res_buf, h->res_buflen, 0);
|
n = send(h->socket, h->res_buf, h->res_buflen, 0);
|
||||||
if(n<0)
|
if(n<0)
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR, "send(res_buf): %m");
|
DPRINTF(E_ERROR, L_HTTP, "send(res_buf): %s", strerror(errno));
|
||||||
}
|
}
|
||||||
else if(n < h->res_buflen)
|
else if(n < h->res_buflen)
|
||||||
{
|
{
|
||||||
/* TODO : handle correctly this case */
|
/* TODO : handle correctly this case */
|
||||||
syslog(LOG_ERR, "send(res_buf): %d bytes sent (out of %d)",
|
DPRINTF(E_ERROR, L_HTTP, "send(res_buf): %d bytes sent (out of %d)\n",
|
||||||
n, h->res_buflen);
|
n, h->res_buflen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -872,12 +829,12 @@ send_data(struct upnphttp * h, char * header, size_t size)
|
|||||||
n = send(h->socket, header, size, 0);
|
n = send(h->socket, header, size, 0);
|
||||||
if(n<0)
|
if(n<0)
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR, "send(res_buf): %m");
|
DPRINTF(E_ERROR, L_HTTP, "send(res_buf): %s", strerror(errno));
|
||||||
}
|
}
|
||||||
else if(n < h->res_buflen)
|
else if(n < h->res_buflen)
|
||||||
{
|
{
|
||||||
/* TODO : handle correctly this case */
|
/* TODO : handle correctly this case */
|
||||||
syslog(LOG_ERR, "send(res_buf): %d bytes sent (out of %d)",
|
DPRINTF(E_ERROR, L_HTTP, "send(res_buf): %d bytes sent (out of %d)\n",
|
||||||
n, h->res_buflen);
|
n, h->res_buflen);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -898,13 +855,13 @@ send_file(struct upnphttp * h, int sendfd, off_t offset, off_t end_offset)
|
|||||||
off_t ret = sendfile(h->socket, sendfd, &offset, send_size);
|
off_t ret = sendfile(h->socket, sendfd, &offset, send_size);
|
||||||
if( ret == -1 )
|
if( ret == -1 )
|
||||||
{
|
{
|
||||||
printf("sendfile error :: error no. %d [%s]\n", errno, strerror(errno));
|
DPRINTF(E_WARN, L_HTTP, "sendfile error :: error no. %d [%s]\n", errno, strerror(errno));
|
||||||
if( errno == 32 || errno == 9 || errno == 54 || errno == 104 )
|
if( errno == 32 || errno == 9 || errno == 54 || errno == 104 )
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/*else
|
/*else
|
||||||
{
|
{
|
||||||
printf("sent %lld bytes to %d. offset is now %lld.\n", ret, h->socket, offset);
|
DPRINTF(E_DEBUG, L_HTTP, "sent %lld bytes to %d. offset is now %lld.\n", ret, h->socket, offset);
|
||||||
}*/
|
}*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -926,7 +883,7 @@ SendResp_albumArt(struct upnphttp * h, char * object)
|
|||||||
|
|
||||||
if( h->reqflags & FLAG_XFERSTREAMING || h->reqflags & FLAG_RANGE )
|
if( h->reqflags & FLAG_XFERSTREAMING || h->reqflags & FLAG_RANGE )
|
||||||
{
|
{
|
||||||
syslog(LOG_NOTICE, "Hey, you can't specify transferMode as Streaming with an image!");
|
DPRINTF(E_WARN, L_HTTP, "Client tried to specify transferMode as Streaming with an image!\n");
|
||||||
Send406(h);
|
Send406(h);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -936,12 +893,12 @@ SendResp_albumArt(struct upnphttp * h, char * object)
|
|||||||
sqlite3_get_table(db, sql_buf, &result, &rows, 0, 0);
|
sqlite3_get_table(db, sql_buf, &result, &rows, 0, 0);
|
||||||
if( !rows )
|
if( !rows )
|
||||||
{
|
{
|
||||||
syslog(LOG_NOTICE, "ALBUM_ART ID %s not found, responding ERROR 404", object);
|
DPRINTF(E_WARN, L_HTTP, "ALBUM_ART ID %s not found, responding ERROR 404\n", object);
|
||||||
Send404(h);
|
Send404(h);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
path = result[1];
|
path = result[1];
|
||||||
printf("Serving album art ID: %s [%s]\n", object, path);
|
DPRINTF(E_INFO, L_HTTP, "Serving album art ID: %s [%s]\n", object, path);
|
||||||
|
|
||||||
if( access(path, F_OK) == 0 )
|
if( access(path, F_OK) == 0 )
|
||||||
{
|
{
|
||||||
@ -949,7 +906,7 @@ SendResp_albumArt(struct upnphttp * h, char * object)
|
|||||||
|
|
||||||
sendfh = open(path, O_RDONLY);
|
sendfh = open(path, O_RDONLY);
|
||||||
if( sendfh < 0 ) {
|
if( sendfh < 0 ) {
|
||||||
printf("Error opening %s\n", path);
|
DPRINTF(E_ERROR, L_HTTP, "Error opening %s\n", path);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
size = lseek(sendfh, 0, SEEK_END);
|
size = lseek(sendfh, 0, SEEK_END);
|
||||||
@ -1002,7 +959,7 @@ SendResp_thumbnail(struct upnphttp * h, char * object)
|
|||||||
|
|
||||||
if( h->reqflags & FLAG_XFERSTREAMING || h->reqflags & FLAG_RANGE )
|
if( h->reqflags & FLAG_XFERSTREAMING || h->reqflags & FLAG_RANGE )
|
||||||
{
|
{
|
||||||
syslog(LOG_NOTICE, "Hey, you can't specify transferMode as Streaming with an image!");
|
DPRINTF(E_WARN, L_HTTP, "Client tried to specify transferMode as Streaming with an image!\n");
|
||||||
Send406(h);
|
Send406(h);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1012,12 +969,12 @@ SendResp_thumbnail(struct upnphttp * h, char * object)
|
|||||||
sqlite3_get_table(db, sql_buf, &result, &rows, 0, 0);
|
sqlite3_get_table(db, sql_buf, &result, &rows, 0, 0);
|
||||||
if( !rows )
|
if( !rows )
|
||||||
{
|
{
|
||||||
syslog(LOG_NOTICE, "%s not found, responding ERROR 404", object);
|
DPRINTF(E_WARN, L_HTTP, "%s not found, responding ERROR 404\n", object);
|
||||||
Send404(h);
|
Send404(h);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
path = result[1];
|
path = result[1];
|
||||||
printf("Serving thumbnail for ObjectId: %s [%s]\n", object, path);
|
DPRINTF(E_INFO, L_HTTP, "Serving thumbnail for ObjectId: %s [%s]\n", object, path);
|
||||||
|
|
||||||
if( access(path, F_OK) == 0 )
|
if( access(path, F_OK) == 0 )
|
||||||
{
|
{
|
||||||
@ -1083,14 +1040,14 @@ SendResp_resizedimg(struct upnphttp * h, char * object)
|
|||||||
|
|
||||||
if( h->reqflags & FLAG_XFERSTREAMING || h->reqflags & FLAG_RANGE )
|
if( h->reqflags & FLAG_XFERSTREAMING || h->reqflags & FLAG_RANGE )
|
||||||
{
|
{
|
||||||
syslog(LOG_NOTICE, "You can't specify transferMode as Streaming with a resized image!");
|
DPRINTF(E_WARN, L_HTTP, "Client tried to specify transferMode as Streaming with a resized image!\n");
|
||||||
Send406(h);
|
Send406(h);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
sprintf(sql_buf, "SELECT d.PATH, d.WIDTH, d.HEIGHT from OBJECTS o left join DETAILS d on (d.ID = o.DETAIL_ID) where OBJECT_ID = '%s'", object);
|
sprintf(sql_buf, "SELECT d.PATH, d.WIDTH, d.HEIGHT from OBJECTS o left join DETAILS d on (d.ID = o.DETAIL_ID) where OBJECT_ID = '%s'", object);
|
||||||
sqlite3_get_table(db, sql_buf, &result, 0, 0, 0);
|
sqlite3_get_table(db, sql_buf, &result, 0, 0, 0);
|
||||||
printf("Serving up resized image for ObjectId: %s [%s]\n", object, result[1]);
|
DPRINTF(E_INFO, L_HTTP, "Serving up resized image for ObjectId: %s [%s]\n", object, result[1]);
|
||||||
|
|
||||||
if( access(result[3], F_OK) == 0 )
|
if( access(result[3], F_OK) == 0 )
|
||||||
{
|
{
|
||||||
@ -1139,12 +1096,12 @@ SendResp_resizedimg(struct upnphttp * h, char * object)
|
|||||||
n = send(h->socket, header, strlen(header), 0);
|
n = send(h->socket, header, strlen(header), 0);
|
||||||
if(n<0)
|
if(n<0)
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR, "send(res_buf): %m");
|
DPRINTF(E_ERROR, L_HTTP, "send(res_buf): %s", strerror(errno));
|
||||||
}
|
}
|
||||||
else if(n < h->res_buflen)
|
else if(n < h->res_buflen)
|
||||||
{
|
{
|
||||||
/* TODO : handle correctly this case */
|
/* TODO : handle correctly this case */
|
||||||
syslog(LOG_ERR, "send(res_buf): %d bytes sent (out of %d)",
|
DPRINTF(E_ERROR, L_HTTP, "send(res_buf): %d bytes sent (out of %d)\n",
|
||||||
n, h->res_buflen);
|
n, h->res_buflen);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1156,12 +1113,12 @@ SendResp_resizedimg(struct upnphttp * h, char * object)
|
|||||||
n = send(h->socket, data, size, 0);
|
n = send(h->socket, data, size, 0);
|
||||||
if(n<0)
|
if(n<0)
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR, "send(res_buf): %m");
|
DPRINTF(E_ERROR, L_HTTP, "send(res_buf): %s", strerror(errno));
|
||||||
}
|
}
|
||||||
else if(n < h->res_buflen)
|
else if(n < h->res_buflen)
|
||||||
{
|
{
|
||||||
/* TODO : handle correctly this case */
|
/* TODO : handle correctly this case */
|
||||||
syslog(LOG_ERR, "send(res_buf): %d bytes sent (out of %d)",
|
DPRINTF(E_ERROR, L_HTTP, "send(res_buf): %d bytes sent (out of %d)\n",
|
||||||
n, h->res_buflen);
|
n, h->res_buflen);
|
||||||
}
|
}
|
||||||
gdFree(data);
|
gdFree(data);
|
||||||
@ -1200,7 +1157,7 @@ SendResp_dlnafile(struct upnphttp * h, char * object)
|
|||||||
sqlite3_get_table(db, sql_buf, &result, &rows, 0, 0);
|
sqlite3_get_table(db, sql_buf, &result, &rows, 0, 0);
|
||||||
if( !rows )
|
if( !rows )
|
||||||
{
|
{
|
||||||
syslog(LOG_NOTICE, "%s not found, responding ERROR 404", object);
|
DPRINTF(E_WARN, L_HTTP, "%s not found, responding ERROR 404\n", object);
|
||||||
Send404(h);
|
Send404(h);
|
||||||
sqlite3_free_table(result);
|
sqlite3_free_table(result);
|
||||||
return;
|
return;
|
||||||
@ -1209,13 +1166,13 @@ SendResp_dlnafile(struct upnphttp * h, char * object)
|
|||||||
mime = result[4];
|
mime = result[4];
|
||||||
dlna = result[5];
|
dlna = result[5];
|
||||||
|
|
||||||
printf("Serving DetailID: %s [%s]\n", object, path);
|
DPRINTF(E_INFO, L_HTTP, "Serving DetailID: %s [%s]\n", object, path);
|
||||||
|
|
||||||
if( h->reqflags & FLAG_XFERSTREAMING )
|
if( h->reqflags & FLAG_XFERSTREAMING )
|
||||||
{
|
{
|
||||||
if( strncmp(mime, "image", 5) == 0 )
|
if( strncmp(mime, "image", 5) == 0 )
|
||||||
{
|
{
|
||||||
syslog(LOG_NOTICE, "Hey, you can't specify transferMode as Streaming with an image!");
|
DPRINTF(E_WARN, L_HTTP, "Client tried to specify transferMode as Streaming with an image!\n");
|
||||||
Send406(h);
|
Send406(h);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
@ -1224,13 +1181,13 @@ SendResp_dlnafile(struct upnphttp * h, char * object)
|
|||||||
{
|
{
|
||||||
if( h->reqflags & FLAG_REALTIMEINFO )
|
if( h->reqflags & FLAG_REALTIMEINFO )
|
||||||
{
|
{
|
||||||
syslog(LOG_NOTICE, "Bad realTimeInfo flag with Interactive request!");
|
DPRINTF(E_WARN, L_HTTP, "Bad realTimeInfo flag with Interactive request!\n");
|
||||||
Send400(h);
|
Send400(h);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if( strncmp(mime, "image", 5) != 0 )
|
if( strncmp(mime, "image", 5) != 0 )
|
||||||
{
|
{
|
||||||
syslog(LOG_NOTICE, "Hey, you can't specify transferMode as Interactive without an image!");
|
DPRINTF(E_WARN, L_HTTP, "Client tried to specify transferMode as Interactive without an image!\n");
|
||||||
Send406(h);
|
Send406(h);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
@ -1240,7 +1197,7 @@ SendResp_dlnafile(struct upnphttp * h, char * object)
|
|||||||
offset = h->req_RangeStart;
|
offset = h->req_RangeStart;
|
||||||
sendfh = open(path, O_RDONLY);
|
sendfh = open(path, O_RDONLY);
|
||||||
if( sendfh < 0 ) {
|
if( sendfh < 0 ) {
|
||||||
printf("Error opening %s\n", path);
|
DPRINTF(E_ERROR, L_HTTP, "Error opening %s\n", path);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
size = lseek(sendfh, 0, SEEK_END);
|
size = lseek(sendfh, 0, SEEK_END);
|
||||||
@ -1254,14 +1211,14 @@ SendResp_dlnafile(struct upnphttp * h, char * object)
|
|||||||
h->req_RangeEnd = size;
|
h->req_RangeEnd = size;
|
||||||
if( (h->req_RangeStart > h->req_RangeEnd) || (h->req_RangeStart < 0) )
|
if( (h->req_RangeStart > h->req_RangeEnd) || (h->req_RangeStart < 0) )
|
||||||
{
|
{
|
||||||
syslog(LOG_NOTICE, "Specified range was invalid!");
|
DPRINTF(E_WARN, L_HTTP, "Specified range was invalid!\n");
|
||||||
Send400(h);
|
Send400(h);
|
||||||
close(sendfh);
|
close(sendfh);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if( h->req_RangeEnd > size )
|
if( h->req_RangeEnd > size )
|
||||||
{
|
{
|
||||||
syslog(LOG_NOTICE, "Specified range was outside file boundaries!");
|
DPRINTF(E_WARN, L_HTTP, "Specified range was outside file boundaries!\n");
|
||||||
Send416(h);
|
Send416(h);
|
||||||
close(sendfh);
|
close(sendfh);
|
||||||
goto error;
|
goto error;
|
||||||
|
58
upnpsoap.c
58
upnpsoap.c
@ -17,7 +17,6 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <syslog.h>
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
@ -31,8 +30,9 @@
|
|||||||
#include "upnpreplyparse.h"
|
#include "upnpreplyparse.h"
|
||||||
#include "getifaddr.h"
|
#include "getifaddr.h"
|
||||||
|
|
||||||
#include "metadata.h"
|
#include "utils.h"
|
||||||
#include "sql.h"
|
#include "sql.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
static void
|
static void
|
||||||
BuildSendAndCloseSoapResp(struct upnphttp * h,
|
BuildSendAndCloseSoapResp(struct upnphttp * h,
|
||||||
@ -450,12 +450,15 @@ BrowseContentDirectory(struct upnphttp * h, const char * action)
|
|||||||
else
|
else
|
||||||
ObjectId = strdup(ObjectId);
|
ObjectId = strdup(ObjectId);
|
||||||
}
|
}
|
||||||
printf("Asked for ObjectID: %s\n", ObjectId);
|
DPRINTF(E_DEBUG, L_HTTP, "Browsing ContentDirectory:\n"
|
||||||
printf("Asked for Count: %d\n", RequestedCount);
|
" * ObjectID: %s\n"
|
||||||
printf("Asked for StartingIndex: %d\n", StartingIndex);
|
" * Count: %d\n"
|
||||||
printf("Asked for BrowseFlag: %s\n", BrowseFlag);
|
" * StartingIndex: %d\n"
|
||||||
printf("Asked for Filter: %s\n", Filter);
|
" * BrowseFlag: %s\n"
|
||||||
if( SortCriteria ) printf("Asked for SortCriteria: %s\n", SortCriteria);
|
" * Filter: %s\n"
|
||||||
|
" * SortCriteria: %s\n",
|
||||||
|
ObjectId, RequestedCount, StartingIndex,
|
||||||
|
BrowseFlag, Filter, SortCriteria);
|
||||||
|
|
||||||
if( !Filter )
|
if( !Filter )
|
||||||
{
|
{
|
||||||
@ -481,8 +484,9 @@ BrowseContentDirectory(struct upnphttp * h, const char * action)
|
|||||||
ret = sqlite3_exec(db, sql, callback, (void *) &args, &zErrMsg);
|
ret = sqlite3_exec(db, sql, callback, (void *) &args, &zErrMsg);
|
||||||
}
|
}
|
||||||
sqlite3_free(sql);
|
sqlite3_free(sql);
|
||||||
if( ret != SQLITE_OK ){
|
if( ret != SQLITE_OK )
|
||||||
printf("SQL error: %s\n", zErrMsg);
|
{
|
||||||
|
DPRINTF(E_ERROR, L_HTTP, "SQL error: %s\n", zErrMsg);
|
||||||
sqlite3_free(zErrMsg);
|
sqlite3_free(zErrMsg);
|
||||||
}
|
}
|
||||||
strcat(resp, resp1);
|
strcat(resp, resp1);
|
||||||
@ -550,12 +554,15 @@ SearchContentDirectory(struct upnphttp * h, const char * action)
|
|||||||
else
|
else
|
||||||
ContainerID = strdup(ContainerID);
|
ContainerID = strdup(ContainerID);
|
||||||
}
|
}
|
||||||
printf("Asked for ContainerID: %s\n", ContainerID);
|
DPRINTF(E_DEBUG, L_HTTP, "Browsing ContentDirectory:\n"
|
||||||
printf("Asked for Count: %d\n", RequestedCount);
|
" * ObjectID: %s\n"
|
||||||
printf("Asked for StartingIndex: %d\n", StartingIndex);
|
" * Count: %d\n"
|
||||||
printf("Asked for SearchCriteria: %s\n", SearchCriteria);
|
" * StartingIndex: %d\n"
|
||||||
printf("Asked for Filter: %s\n", Filter);
|
" * SearchCriteria: %s\n"
|
||||||
if( SortCriteria ) printf("Asked for SortCriteria: %s\n", SortCriteria);
|
" * Filter: %s\n"
|
||||||
|
" * SortCriteria: %s\n",
|
||||||
|
ContainerID, RequestedCount, StartingIndex,
|
||||||
|
SearchCriteria, Filter, SortCriteria);
|
||||||
|
|
||||||
strcpy(resp, resp0);
|
strcpy(resp, resp0);
|
||||||
/* See if we need to include DLNA namespace reference */
|
/* See if we need to include DLNA namespace reference */
|
||||||
@ -601,7 +608,7 @@ SearchContentDirectory(struct upnphttp * h, const char * action)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
printf("Translated SearchCriteria: %s\n", SearchCriteria);
|
DPRINTF(E_DEBUG, L_HTTP, "Translated SearchCriteria: %s\n", SearchCriteria);
|
||||||
|
|
||||||
args.resp = resp;
|
args.resp = resp;
|
||||||
sql = sqlite3_mprintf("SELECT * from OBJECTS o left join DETAILS d on (d.ID = o.DETAIL_ID)"
|
sql = sqlite3_mprintf("SELECT * from OBJECTS o left join DETAILS d on (d.ID = o.DETAIL_ID)"
|
||||||
@ -613,10 +620,11 @@ SearchContentDirectory(struct upnphttp * h, const char * action)
|
|||||||
sqlite3_mprintf("UNION ALL SELECT * from OBJECTS o left join DETAILS d on (d.ID = o.DETAIL_ID)"
|
sqlite3_mprintf("UNION ALL SELECT * from OBJECTS o left join DETAILS d on (d.ID = o.DETAIL_ID)"
|
||||||
" where OBJECT_ID = '%s' and (%s) ", ContainerID, SearchCriteria),
|
" where OBJECT_ID = '%s' and (%s) ", ContainerID, SearchCriteria),
|
||||||
StartingIndex);
|
StartingIndex);
|
||||||
printf("Search SQL: %s\n", sql);
|
DPRINTF(E_DEBUG, L_HTTP, "Search SQL: %s\n", sql);
|
||||||
ret = sqlite3_exec(db, sql, callback, (void *) &args, &zErrMsg);
|
ret = sqlite3_exec(db, sql, callback, (void *) &args, &zErrMsg);
|
||||||
if( ret != SQLITE_OK ){
|
if( ret != SQLITE_OK )
|
||||||
printf("SQL error: %s\nBAD SQL: %s\n", zErrMsg, sql);
|
{
|
||||||
|
DPRINTF(E_WARN, L_HTTP, "SQL error: %s\nBAD SQL: %s\n", zErrMsg, sql);
|
||||||
sqlite3_free(zErrMsg);
|
sqlite3_free(zErrMsg);
|
||||||
}
|
}
|
||||||
sqlite3_free(sql);
|
sqlite3_free(sql);
|
||||||
@ -665,7 +673,7 @@ QueryStateVariable(struct upnphttp * h, const char * action)
|
|||||||
/*var_name = GetValueFromNameValueListIgnoreNS(&data, "varName");*/
|
/*var_name = GetValueFromNameValueListIgnoreNS(&data, "varName");*/
|
||||||
var_name = GetValueFromNameValueList(&data, "varName");
|
var_name = GetValueFromNameValueList(&data, "varName");
|
||||||
|
|
||||||
/*syslog(LOG_INFO, "QueryStateVariable(%.40s)", var_name); */
|
DPRINTF(E_INFO, L_HTTP, "QueryStateVariable(%.40s)\n", var_name);
|
||||||
|
|
||||||
if(!var_name)
|
if(!var_name)
|
||||||
{
|
{
|
||||||
@ -693,7 +701,7 @@ QueryStateVariable(struct upnphttp * h, const char * action)
|
|||||||
#endif
|
#endif
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
syslog(LOG_NOTICE, "%s: Unknown: %s", action, var_name?var_name:"");
|
DPRINTF(E_WARN, L_HTTP, "%s: Unknown: %s\n", action, var_name?var_name:"");
|
||||||
SoapError(h, 404, "Invalid Var");
|
SoapError(h, 404, "Invalid Var");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -739,7 +747,7 @@ ExecuteSoapAction(struct upnphttp * h, const char * action, int n)
|
|||||||
methodlen = p2 - p;
|
methodlen = p2 - p;
|
||||||
else
|
else
|
||||||
methodlen = n - (p - action);
|
methodlen = n - (p - action);
|
||||||
/*syslog(LOG_DEBUG, "SoapMethod: %.*s", methodlen, p);*/
|
DPRINTF(E_DEBUG, L_HTTP, "SoapMethod: %.*s\n", methodlen, p);
|
||||||
while(soapMethods[i].methodName)
|
while(soapMethods[i].methodName)
|
||||||
{
|
{
|
||||||
len = strlen(soapMethods[i].methodName);
|
len = strlen(soapMethods[i].methodName);
|
||||||
@ -751,7 +759,7 @@ ExecuteSoapAction(struct upnphttp * h, const char * action, int n)
|
|||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
syslog(LOG_NOTICE, "SoapMethod: Unknown: %.*s", methodlen, p);
|
DPRINTF(E_WARN, L_HTTP, "SoapMethod: Unknown: %.*s\n", methodlen, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
SoapError(h, 401, "Invalid Action");
|
SoapError(h, 401, "Invalid Action");
|
||||||
@ -799,7 +807,7 @@ SoapError(struct upnphttp * h, int errCode, const char * errDesc)
|
|||||||
char body[2048];
|
char body[2048];
|
||||||
int bodylen;
|
int bodylen;
|
||||||
|
|
||||||
syslog(LOG_INFO, "Returning UPnPError %d: %s", errCode, errDesc);
|
DPRINTF(E_WARN, L_HTTP, "Returning UPnPError %d: %s\n", errCode, errDesc);
|
||||||
bodylen = snprintf(body, sizeof(body), resp, errCode, errDesc);
|
bodylen = snprintf(body, sizeof(body), resp, errCode, errDesc);
|
||||||
BuildResp2_upnphttp(h, 500, "Internal Server Error", body, bodylen);
|
BuildResp2_upnphttp(h, 500, "Internal Server Error", body, bodylen);
|
||||||
SendResp_upnphttp(h);
|
SendResp_upnphttp(h);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user