Merge of trunk into branch-1.4.x.

git-svn-id: https://pupnp.svn.sourceforge.net/svnroot/pupnp/branches/branch-1.4.x@127 119443c7-1b9e-41f8-b6fc-b9c35fce742c
This commit is contained in:
Marcelo Roberto Jimenez 2007-02-03 19:30:31 +00:00
parent 9e775e662e
commit 8cfa0e488c
29 changed files with 874 additions and 443 deletions

105
ChangeLog
View File

@ -2,30 +2,100 @@
Version 1.4.2 Version 1.4.2
************************************************************************* *************************************************************************
2007-02-02 Marcelo Jimenez <mroberto(at)users.sourceforge.net>
* Bumped the program version to 1.4.2 in config.ac.
* Now requires autoconf 2.60.
* Fixed docdir use.
* Does not install the documentation by default.
* Use dist-bzip2 to create a .bz2 distribution file.
2007-01-23 Marcelo Jimenez <mroberto(at)users.sourceforge.net>
* SF Tracker [ 1634922 ] Support for large files (>= 2 GiB), part 2
Submitted By: Jonathan - no_dice
Summary: This patch hopefully fixes the remaining types and related
code to enable files >= 2 GiB to be streamed. Jonathan claims to have
tested this with a patched version of ushare-0.9.8 and a D-Link DSM-520.
2007-01-09 Marcelo Jimenez <mroberto(at)users.sourceforge.net>
* SF Tracker [ 1628629 ] Multicast interface patch
Submitted By: Fredrik Svensson - svefredrik
This patch fixes two problems:
1) Specify the IP address for the interface when we do
setsockopt IP_ADD_MEMBERSHIP. This makes it possible to run
when no default router has been configured.
2) Explicitly set the multicast interface through setsockopt
IP_MULTICAST_IF. Avoids socket error -207 in some cases.
* SF Tracker [ 1628590 ] XML parsing segfault patch
Submitted By: Fredrik Svensson - svefredrik
This patch fixes a segmentation fault problem that occurrs
when parsing XML code than some routers produce.
2007-01-06 Marcelo Jimenez <mroberto(at)users.sourceforge.net>
* SF Tracker [ 1628552 ] XML white space patch
Submitted By: Fredrik Svensson - svefredrik
* SF Tracker [ 1628562 ] Maximum total jobs patch
Submitted By: Fredrik Svensson - svefredrik
Also, I incremented the libray versions and included some
comments in the file configure.ac so that we do not bump
the library version excessively, only the necessary numbers
on the next release.
* SF Tracker [ 1628575 ] Linksys WRT54G patch
Submitted By: Fredrik Svensson - svefredrik
* SF Tracker [ 1628636 ] SSDP packet copy patch
Submitted By: Fredrik Svensson - svefredrik
Changed NUM_COPY to 1 since, according to section 9.2 of the
HTTPU/MU spec, we should never send more than one copy of a
reply to an SSDP request. Ref. section 9.2 of
http://www.upnp.org/download/draft-goland-http-udp-04.txt
2006-12-23 Marcelo Jimenez <mroberto(at)users.sourceforge.net> 2006-12-23 Marcelo Jimenez <mroberto(at)users.sourceforge.net>
* Thorough revision of every call of http_MakeMessage() due to a
bug introduced in rev.79 "largefile patch added".
http_MakeMessage() has a worst than brain damaged "printf" like
interface. In rev.79, the "N" format parameter must be an off_t.
Every call of this function with an "N" format parameter and an
int passed on the stack would fail terribly.
* SF Bug tracker [ 1590469 ]
Typo in ixmlparser.c
Submitted By: Erik Johansson - erijo
* SF Bug Tracker [ 1590466 ] Invalid xml output
Submitted By: Erik Johansson - erijo
* SF Patch tracker [ 1581161 ] VStudio2005 patch
Submitted By: David Maass - darkservant
* SF Patch tracker [ 1587272 ] const-ified ixml
Submitted By: Erik Johansson
* Finished const-ifications as suggested by Erik Johansson in * Finished const-ifications as suggested by Erik Johansson in
SF Patch tracker [ 1587272 ]. SF Patch tracker [ 1587272 ].
2006-12-23 Marcelo Jimenez <mroberto(at)users.sourceforge.net> 2006-07-05 Nektarios K. Papadopoulos <npapadop(at)inaccessnetworks.com>
* [bug-id] 1580440
[submitted-by] Erik Johansson - erijo
[patched-by] Erik Johansson - erijo
The SOAP HTTP message that's generated on upnp errors
is missing a \r\n\ between header and body.
* Erik Johansson's patch for const-ified ixml 2006-07-07 Oxy <virtual_worlds(at)gmx.de>
SF Patch tracker [ 1587272 ].
2006-12-23 Marcelo Jimenez <mroberto(at)users.sourceforge.net> * support for large files (>2 GBytes) added
* David Maass's patch for VStudio2005 compilation failure.
SF Patch tracker [ 1581161 ].
2006-12-23 Marcelo Jimenez <mroberto(at)users.sourceforge.net>
* Erik Johansson's patch for invalid xml output.
SF Bug Tracker [ 1590466 ].
2006-12-23 Marcelo Jimenez <mroberto(at)users.sourceforge.net>
* Erik Johansson's patch for typo in ixmlparser.c.
SF Bug tracker [ 1590469 ].
************************************************************************* *************************************************************************
Version 1.4.1 Version 1.4.1
@ -79,10 +149,13 @@ Version 1.4.0
2006-05-18 Oxy <virtual_worlds(at)gmx.de> 2006-05-18 Oxy <virtual_worlds(at)gmx.de>
* DSM-320 patch added (fetched from project MediaTomb) * DSM-320 patch added (fetched from project MediaTomb)
* httpGet additons atch added, Added proxy support by introducing * httpGet additons atch added, Added proxy support by introducing
UpnpOpenHttpGetProxy. UpnpOpenHttpGet now just calls UpnpOpenHttpGetProxy. UpnpOpenHttpGet now just calls
UpnpOpenHttpGetProxy with the proxy url set to NULL. UpnpOpenHttpGetProxy with the proxy url set to NULL.
* Bugfix for typo ("\0" / "0") in ixmlparser.c * Bugfix for typo ("\0" / "0") in ixmlparser.c
* Bugfix for M-Search packet * Bugfix for M-Search packet
************************************************************************* *************************************************************************

View File

@ -5,40 +5,39 @@
# Copyright (C) 2005 Rémi Turboult <r3mi@users.sourceforge.net> # Copyright (C) 2005 Rémi Turboult <r3mi@users.sourceforge.net>
# #
ACLOCAL_AMFLAGS = -I m4 ACLOCAL_AMFLAGS = -I m4
DISTCHECK_CONFIGURE_FLAGS = --enable-debug --enable-samples DISTCHECK_CONFIGURE_FLAGS = --enable-debug --enable-samples
SUBDIRS = ixml threadutil upnp docs/dist SUBDIRS = ixml threadutil upnp docs/dist
EXTRA_DIST = libupnp.pc.in LICENSE THANKS libupnp.spec \ EXTRA_DIST = \
build/libupnp.bpf \ libupnp.pc.in \
build/libupnp.bpr \ LICENSE \
build/libupnp.dsp \ THANKS \
build/libupnp.dsw \ libupnp.spec \
build/inc/autoconfig.h \ build/libupnp.bpf \
build/inc/config.h \ build/libupnp.bpr \
build/inc/upnpconfig.h build/libupnp.dsp \
build/libupnp.dsw \
build/inc/autoconfig.h \
build/inc/config.h \
build/inc/upnpconfig.h
# This variable must have 'exec' in its name, in order to be installed # This variable must have 'exec' in its name, in order to be installed
# by 'install-exec' target (instead of default 'install-data') # by 'install-exec' target (instead of default 'install-data')
pkgconfigexecdir = $(libdir)/pkgconfig pkgconfigexecdir = $(libdir)/pkgconfig
pkgconfigexec_DATA = libupnp.pc pkgconfigexec_DATA = libupnp.pc
$(pkgconfigexec_DATA): config.status $(pkgconfigexec_DATA): config.status
if WITH_DOCDIR if WITH_DOCUMENTATION
docdir = @DOCDIR@ doc_DATA = LICENSE README NEWS TODO THANKS
doc_DATA = LICENSE README NEWS TODO THANKS
endif endif
CLEANFILES = IUpnpErrFile.txt IUpnpInfoFile.txt CLEANFILES = IUpnpErrFile.txt IUpnpInfoFile.txt

4
THANKS
View File

@ -12,15 +12,17 @@ exempt of errors.
- Erik Johansson - Erik Johansson
- Eric Tanguy - Eric Tanguy
- Erwan Velu - Erwan Velu
- Fredrik Svensson
- Jiri Zouhar - Jiri Zouhar
- John Dennis - John Dennis
- Jonathan (no_dice)
- Leuk_He - Leuk_He
- Loigu - Loigu
- Marcelo Roberto Jimenez - Marcelo Roberto Jimenez
- Markus Strobl - Markus Strobl
- Nektarios K. Papadopoulos - Nektarios K. Papadopoulos
- Oskar Liljeblad - Oskar Liljeblad
- Oxy - Michael (Oxy)
- Paul Vixie - Paul Vixie
- Siva Chandran - Siva Chandran

View File

@ -43,7 +43,7 @@ RSC=rc.exe
# PROP Ignore_Export_Lib 0 # PROP Ignore_Export_Lib 0
# PROP Target_Dir "" # PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBUPNP_EXPORTS" /YX /FD /c # ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBUPNP_EXPORTS" /YX /FD /c
# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\pthreads\include" /I "..\ixml\src\inc" /I "..\ixml\inc" /I "..\threadutil\inc" /I "..\upnp\inc" /I "..\upnp\src\inc" /I ".\inc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBUPNP_EXPORTS" /FR /YX /FD /c # ADD CPP /nologo /MT /W3 /GX /O2 /I "..\pthreads\include" /I "..\ixml\src\inc" /I "..\ixml\inc" /I "..\threadutil\inc" /I "..\upnp\inc" /I "..\upnp\src\inc" /I ".\inc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBUPNP_EXPORTS" /D "PTW32_STATIC_LIB" /D "UPNP_STATIC_LIB" /FR /YX /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x407 /d "NDEBUG" # ADD BASE RSC /l 0x407 /d "NDEBUG"
@ -53,7 +53,8 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo # ADD BSC32 /nologo
LINK32=link.exe LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
# ADD LINK32 kernel32.lib user32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ..\pthreads\lib\pthreadvc2.lib ws2_32.lib /nologo /dll /machine:I386 # ADD LINK32 kernel32.lib user32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib pthreads\lib\pthreadvc2.lib ws2_32.lib /nologo /dll /machine:I386
# SUBTRACT LINK32 /pdb:none
!ELSEIF "$(CFG)" == "libupnp - Win32 Debug" !ELSEIF "$(CFG)" == "libupnp - Win32 Debug"
@ -274,6 +275,146 @@ SOURCE=..\upnp\src\win_dll.c
# Begin Group "Header-Dateien" # Begin Group "Header-Dateien"
# PROP Default_Filter "h;hpp;hxx;hm;inl" # PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=..\upnp\src\inc\client_table.h
# End Source File
# Begin Source File
SOURCE=..\upnp\src\inc\config.h
# End Source File
# Begin Source File
SOURCE=..\upnp\src\inc\gena.h
# End Source File
# Begin Source File
SOURCE=..\upnp\src\inc\gena_ctrlpt.h
# End Source File
# Begin Source File
SOURCE=..\upnp\src\inc\gena_device.h
# End Source File
# Begin Source File
SOURCE=..\upnp\src\inc\global.h
# End Source File
# Begin Source File
SOURCE=..\upnp\src\inc\gmtdate.h
# End Source File
# Begin Source File
SOURCE=..\upnp\src\inc\http_client.h
# End Source File
# Begin Source File
SOURCE=..\upnp\src\inc\httpparser.h
# End Source File
# Begin Source File
SOURCE=..\upnp\src\inc\httpreadwrite.h
# End Source File
# Begin Source File
SOURCE=..\upnp\src\inc\inet_pton.h
# End Source File
# Begin Source File
SOURCE=..\upnp\src\inc\md5.h
# End Source File
# Begin Source File
SOURCE=..\upnp\src\inc\membuffer.h
# End Source File
# Begin Source File
SOURCE=..\upnp\src\inc\miniserver.h
# End Source File
# Begin Source File
SOURCE=..\upnp\src\inc\netall.h
# End Source File
# Begin Source File
SOURCE=..\upnp\src\inc\parsetools.h
# End Source File
# Begin Source File
SOURCE=..\upnp\src\inc\server.h
# End Source File
# Begin Source File
SOURCE=..\upnp\src\inc\service_table.h
# End Source File
# Begin Source File
SOURCE=..\upnp\src\inc\soaplib.h
# End Source File
# Begin Source File
SOURCE=..\upnp\src\inc\sock.h
# End Source File
# Begin Source File
SOURCE=..\upnp\src\inc\ssdplib.h
# End Source File
# Begin Source File
SOURCE=..\upnp\src\inc\statcodes.h
# End Source File
# Begin Source File
SOURCE=..\upnp\src\inc\statuscodes.h
# End Source File
# Begin Source File
SOURCE=..\upnp\src\inc\strintmap.h
# End Source File
# Begin Source File
SOURCE=..\upnp\src\inc\sysdep.h
# End Source File
# Begin Source File
SOURCE=..\upnp\src\inc\unixutil.h
# End Source File
# Begin Source File
SOURCE=..\upnp\src\inc\upnp_timeout.h
# End Source File
# Begin Source File
SOURCE=..\upnp\src\inc\upnpapi.h
# End Source File
# Begin Source File
SOURCE=..\upnp\src\inc\upnpclosesocket.h
# End Source File
# Begin Source File
SOURCE=..\upnp\src\inc\uri.h
# End Source File
# Begin Source File
SOURCE=..\upnp\src\inc\urlconfig.h
# End Source File
# Begin Source File
SOURCE=..\upnp\src\inc\util.h
# End Source File
# Begin Source File
SOURCE=..\upnp\src\inc\utilall.h
# End Source File
# Begin Source File
SOURCE=..\upnp\src\inc\uuid.h
# End Source File
# Begin Source File
SOURCE=..\upnp\src\inc\webserver.h
# End Source File
# End Group # End Group
# Begin Group "Ressourcendateien" # Begin Group "Ressourcendateien"

View File

@ -8,9 +8,9 @@
# (C) Copyright 2005-2006 Rémi Turboult <r3mi@users.sourceforge.net> # (C) Copyright 2005-2006 Rémi Turboult <r3mi@users.sourceforge.net>
# #
AC_PREREQ(2.59) AC_PREREQ(2.60)
AC_INIT([libupnp], [1.4.1], [virtual_worlds@gmx.de]) AC_INIT([libupnp], [1.4.2], [mroberto@users.sourceforge.net])
# *Independently* of the above libupnp package version, the libtool version # *Independently* of the above libupnp package version, the libtool version
# of the 3 libraries need to be updated whenever there is a change released : # of the 3 libraries need to be updated whenever there is a change released :
# "current:revision:age" (this is NOT the same as the package version), where: # "current:revision:age" (this is NOT the same as the package version), where:
@ -19,16 +19,34 @@ AC_INIT([libupnp], [1.4.1], [virtual_worlds@gmx.de])
# - interfaces added: age++ # - interfaces added: age++
# - interfaces removed: age=0 # - interfaces removed: age=0
# *please update only once, before a formal release, not for each change* # *please update only once, before a formal release, not for each change*
AC_SUBST([LT_VERSION_IXML], [2:2:0]) #
AC_SUBST([LT_VERSION_THREADUTIL], [2:2:0]) # For release 1.4.1, we had:
AC_SUBST([LT_VERSION_UPNP], [2:2:0]) #AC_SUBST([LT_VERSION_IXML], [2:2:0])
#AC_SUBST([LT_VERSION_THREADUTIL], [2:2:0])
#AC_SUBST([LT_VERSION_UPNP], [2:2:0])
#
# "current:revision:age"
#
# - Code has changed in ixml
# revision: 2 -> 3
# - Code has changed in threadutil
# revision: 2 -> 3
# - Interface added in threadutil
# current: 2 -> 3
# revisiion: 3 -> 0
# age: 0 -> 1
# - Code has changed in upnp (revision 2 -> 3)
# revision: 2 -> 3
AC_SUBST([LT_VERSION_IXML], [2:3:0])
AC_SUBST([LT_VERSION_THREADUTIL], [3:0:1])
AC_SUBST([LT_VERSION_UPNP], [2:3:0])
AC_CONFIG_AUX_DIR(config.aux) AC_CONFIG_AUX_DIR(config.aux)
AC_CONFIG_MACRO_DIR(m4) AC_CONFIG_MACRO_DIR(m4)
AC_CONFIG_SRCDIR(upnp/inc/upnp.h) AC_CONFIG_SRCDIR(upnp/inc/upnp.h)
AM_INIT_AUTOMAKE([1.8 -Wall foreign subdir-objects]) AM_INIT_AUTOMAKE([1.8 -Wall foreign subdir-objects dist-bzip2])
# #
# There are 3 configuration files : # There are 3 configuration files :
@ -42,6 +60,7 @@ AM_INIT_AUTOMAKE([1.8 -Wall foreign subdir-objects])
# installed libraries. # installed libraries.
# #
AC_CONFIG_HEADERS([autoconfig.h upnp/inc/upnpconfig.h]) AC_CONFIG_HEADERS([autoconfig.h upnp/inc/upnpconfig.h])
#AC_SYS_LARGEFILE_SENSITIVE
AC_REVISION([$Revision: 1.11 $]) AC_REVISION([$Revision: 1.11 $])
@ -106,19 +125,28 @@ RT_BOOL_ARG_ENABLE([samples], [yes], [compilation of upnp/sample/ code])
# doc installation # doc installation
AC_MSG_CHECKING([documentation installation]) # autoconf >= 2.60 already defines ${docdir}, but we will not use its
AC_ARG_WITH([docdir], # default value, which is ${datarootdir}/doc/${PACKAGE_TARNAME}.
AC_HELP_STRING([--with-docdir=DIR], # That would give us ${datarootdir}/doc/libupnp, and we want the package
[where documentation is installed # version on that.
@<:@[DATADIR/doc/]AC_PACKAGE_NAME[-]AC_PACKAGE_VERSION@:>@]) docdir="${datadir}/doc/${PACKAGE_NAME}-${PACKAGE_VERSION}"
AC_HELP_STRING([--without-docdir], AC_MSG_CHECKING([for documentation directory])
[do not install the documentation]), AC_ARG_WITH([documentation],
[DOCDIR="$with_docdir"], AS_HELP_STRING([--with-documentation=directory_name],
[DOCDIR="${datadir}/doc/${PACKAGE_NAME}-${PACKAGE_VERSION}"]) [where documentation is installed
@<:@[DATADIR/doc/]AC_PACKAGE_NAME[-]AC_PACKAGE_VERSION@:>@])
AS_HELP_STRING([--without-documentation],
[do not install the documentation]),
[],
[with_documentation=no])
AM_CONDITIONAL(WITH_DOCDIR, test x"$with_docdir" != xno) # If something has been entered after an equal sign, assume it is the directory
AC_SUBST(DOCDIR) if test x"$with_documentation" != xyes -a x"$with_documentation" != xno; then
AC_MSG_RESULT($DOCDIR) docdir="$with_documentation"
fi
AM_CONDITIONAL(WITH_DOCUMENTATION, test x"$with_documentation" != xno)
AC_SUBST(docdir)
AC_MSG_RESULT($docdir)
# #
@ -144,9 +172,12 @@ else
fi fi
AX_CFLAGS_WARN_ALL AX_CFLAGS_WARN_ALL
# Arrange for large-file support (can be disabled with --disable-largefile). #
# Define _FILE_OFFSET_BITS and _LARGE_FILES if necessary # Lot's of stuff to ensure large file support
AC_SYS_LARGEFILE #
AC_TYPE_OFF_T
AC_DEFINE(_LARGE_FILE_SOURCE, [], [Large files support])
AC_DEFINE(_FILE_OFFSET_BITS, [64], [File Offset size])
# #

13
docs/dist/Makefile.am vendored
View File

@ -1,4 +1,7 @@
EXTRA_DIST = ./UPnP_Programming_Guide.pdf \
EXTRA_DIST = \
./UPnP_Programming_Guide.pdf \
./IXML_Programming_Guide.pdf \ ./IXML_Programming_Guide.pdf \
./html/upnp/icon1.gif \ ./html/upnp/icon1.gif \
./html/upnp/icon2.gif \ ./html/upnp/icon2.gif \
@ -251,9 +254,10 @@ EXTRA_DIST = ./UPnP_Programming_Guide.pdf \
./html/ixml/ixmlCloneDOMString.html \ ./html/ixml/ixmlCloneDOMString.html \
./html/ixml/ixmlFreeDOMString.html ./html/ixml/ixmlFreeDOMString.html
if WITH_DOCDIR if WITH_DOCUMENTATION
docsdir = @DOCDIR@ docsdir = @docdir@
nobase_docs_DATA = ./UPnP_Programming_Guide.pdf \ nobase_docs_DATA = \
./UPnP_Programming_Guide.pdf \
./IXML_Programming_Guide.pdf \ ./IXML_Programming_Guide.pdf \
./html/upnp/icon1.gif \ ./html/upnp/icon1.gif \
./html/upnp/icon2.gif \ ./html/upnp/icon2.gif \
@ -506,3 +510,4 @@ if WITH_DOCDIR
./html/ixml/ixmlCloneDOMString.html \ ./html/ixml/ixmlCloneDOMString.html \
./html/ixml/ixmlFreeDOMString.html ./html/ixml/ixmlFreeDOMString.html
endif endif

View File

@ -146,7 +146,7 @@ ixmlPrintDomTreeRecursive( IN IXML_Node * nodeptr,
if( ( child != NULL ) if( ( child != NULL )
&& ( ixmlNode_getNodeType( child ) == && ( ixmlNode_getNodeType( child ) ==
eELEMENT_NODE ) ) { eELEMENT_NODE ) ) {
ixml_membuf_append_str( buf, ">\n" ); ixml_membuf_append_str( buf, ">\r\n" );
} else { } else {
ixml_membuf_append_str( buf, ">" ); ixml_membuf_append_str( buf, ">" );
} }
@ -164,7 +164,7 @@ ixmlPrintDomTreeRecursive( IN IXML_Node * nodeptr,
&& ixmlNode_getNodeType( sibling ) == eTEXT_NODE ) { && ixmlNode_getNodeType( sibling ) == eTEXT_NODE ) {
ixml_membuf_append_str( buf, ">" ); ixml_membuf_append_str( buf, ">" );
} else { } else {
ixml_membuf_append_str( buf, ">\n" ); ixml_membuf_append_str( buf, ">\r\n" );
} }
ixmlPrintDomTreeRecursive( ixmlNode_getNextSibling ixmlPrintDomTreeRecursive( ixmlNode_getNextSibling
( nodeptr ), buf ); ( nodeptr ), buf );
@ -227,7 +227,7 @@ ixmlPrintDomTree( IN IXML_Node * nodeptr,
child = ixmlNode_getFirstChild( nodeptr ); child = ixmlNode_getFirstChild( nodeptr );
if( ( child != NULL ) if( ( child != NULL )
&& ( ixmlNode_getNodeType( child ) == eELEMENT_NODE ) ) { && ( ixmlNode_getNodeType( child ) == eELEMENT_NODE ) ) {
ixml_membuf_append_str( buf, ">\n" ); ixml_membuf_append_str( buf, ">\r\n" );
} else { } else {
ixml_membuf_append_str( buf, ">" ); ixml_membuf_append_str( buf, ">" );
} }
@ -239,7 +239,7 @@ ixmlPrintDomTree( IN IXML_Node * nodeptr,
// Done with children. Output the end tag. // Done with children. Output the end tag.
ixml_membuf_append_str( buf, "</" ); ixml_membuf_append_str( buf, "</" );
ixml_membuf_append_str( buf, nodeName ); ixml_membuf_append_str( buf, nodeName );
ixml_membuf_append_str( buf, ">\n" ); ixml_membuf_append_str( buf, ">\r\n" );
break; break;
default: default:
@ -372,7 +372,7 @@ ixmlPrintDocument(IXML_Document *doc)
} }
ixml_membuf_init( buf ); ixml_membuf_init( buf );
ixml_membuf_append_str( buf, "<?xml version=\"1.0\"?>\n" ); ixml_membuf_append_str( buf, "<?xml version=\"1.0\"?>\r\n" );
ixmlPrintDomTree( rootNode, buf ); ixmlPrintDomTree( rootNode, buf );
return buf->buf; return buf->buf;
@ -421,7 +421,7 @@ ixmlDocumenttoString(IXML_Document *doc)
} }
ixml_membuf_init( buf ); ixml_membuf_init( buf );
ixml_membuf_append_str( buf, "<?xml version=\"1.0\"?>\n" ); ixml_membuf_append_str( buf, "<?xml version=\"1.0\"?>\r\n" );
ixmlDomTreetoString( rootNode, buf ); ixmlDomTreetoString( rootNode, buf );
return buf->buf; return buf->buf;

View File

@ -241,6 +241,21 @@ static BOOL Parser_hasDefaultNamespace( Parser * xmlParser,
static int Parser_getChar( IN const char *src, static int Parser_getChar( IN const char *src,
INOUT int *cLen ); INOUT int *cLen );
/*==============================================================================*
* safe_strdup
* strdup that handles NULL input.
*
*===============================================================================*/
static char *
safe_strdup(const char *s)
{
assert(s != NULL);
if (s == NULL) {
return strdup("");
}
return strdup(s);
}
/*==============================================================================* /*==============================================================================*
* Parser_isCharInTable * Parser_isCharInTable
* will determine whether character c is in the table of tbl * will determine whether character c is in the table of tbl
@ -525,14 +540,14 @@ Parser_pushElement( IN Parser * xmlParser,
memset( pNewStackElement, 0, sizeof( IXML_ElementStack ) ); memset( pNewStackElement, 0, sizeof( IXML_ElementStack ) );
// the element member includes both prefix and name // the element member includes both prefix and name
pNewStackElement->element = strdup( newElement->nodeName ); pNewStackElement->element = safe_strdup( newElement->nodeName );
if( pNewStackElement->element == NULL ) { if( pNewStackElement->element == NULL ) {
free( pNewStackElement ); free( pNewStackElement );
return IXML_INSUFFICIENT_MEMORY; return IXML_INSUFFICIENT_MEMORY;
} }
if( newElement->prefix != 0 ) { if( newElement->prefix != 0 ) {
pNewStackElement->prefix = strdup( newElement->prefix ); pNewStackElement->prefix = safe_strdup( newElement->prefix );
if( pNewStackElement->prefix == NULL ) { if( pNewStackElement->prefix == NULL ) {
Parser_freeElementStackItem( pNewStackElement ); Parser_freeElementStackItem( pNewStackElement );
free( pNewStackElement ); free( pNewStackElement );
@ -542,7 +557,7 @@ Parser_pushElement( IN Parser * xmlParser,
if( newElement->namespaceURI != 0 ) { if( newElement->namespaceURI != 0 ) {
pNewStackElement->namespaceUri = pNewStackElement->namespaceUri =
strdup( newElement->namespaceURI ); safe_strdup( newElement->namespaceURI );
if( pNewStackElement->namespaceUri == NULL ) { if( pNewStackElement->namespaceUri == NULL ) {
Parser_freeElementStackItem( pNewStackElement ); Parser_freeElementStackItem( pNewStackElement );
free( pNewStackElement ); free( pNewStackElement );
@ -634,7 +649,7 @@ Parser_readFileOrBuffer( IN Parser * xmlParser,
fclose( xmlFilePtr ); fclose( xmlFilePtr );
} }
} else { } else {
xmlParser->dataBuffer = strdup( xmlFileName ); xmlParser->dataBuffer = safe_strdup( xmlFileName );
if( xmlParser->dataBuffer == NULL ) { if( xmlParser->dataBuffer == NULL ) {
return IXML_INSUFFICIENT_MEMORY; return IXML_INSUFFICIENT_MEMORY;
} }
@ -1610,7 +1625,7 @@ Parser_addNamespace( IN Parser * xmlParser )
// it would be wrong that pNode->namespace != NULL. // it would be wrong that pNode->namespace != NULL.
assert( pNode->namespaceURI == NULL ); assert( pNode->namespaceURI == NULL );
pNode->namespaceURI = strdup( pCur->namespaceUri ); pNode->namespaceURI = safe_strdup( pCur->namespaceUri );
if( pNode->namespaceURI == NULL ) { if( pNode->namespaceURI == NULL ) {
return IXML_INSUFFICIENT_MEMORY; return IXML_INSUFFICIENT_MEMORY;
} }
@ -1626,7 +1641,7 @@ Parser_addNamespace( IN Parser * xmlParser )
namespaceUri = Parser_getNameSpace( xmlParser, pCur->prefix ); namespaceUri = Parser_getNameSpace( xmlParser, pCur->prefix );
if( namespaceUri != NULL ) { if( namespaceUri != NULL ) {
pNode->namespaceURI = strdup( namespaceUri ); pNode->namespaceURI = safe_strdup( namespaceUri );
if( pNode->namespaceURI == NULL ) { if( pNode->namespaceURI == NULL ) {
return IXML_INSUFFICIENT_MEMORY; return IXML_INSUFFICIENT_MEMORY;
} }
@ -1661,7 +1676,7 @@ Parser_setNodePrefixAndLocalName( IN IXML_Node * node )
pStrPrefix = strchr( node->nodeName, ':' ); pStrPrefix = strchr( node->nodeName, ':' );
if( pStrPrefix == NULL ) { if( pStrPrefix == NULL ) {
node->prefix = NULL; node->prefix = NULL;
node->localName = strdup( node->nodeName ); node->localName = safe_strdup( node->nodeName );
if( node->localName == NULL ) { if( node->localName == NULL ) {
return IXML_INSUFFICIENT_MEMORY; return IXML_INSUFFICIENT_MEMORY;
} }
@ -1678,7 +1693,7 @@ Parser_setNodePrefixAndLocalName( IN IXML_Node * node )
memset( node->prefix, 0, nPrefix + 1 ); memset( node->prefix, 0, nPrefix + 1 );
strncpy( node->prefix, node->nodeName, nPrefix ); strncpy( node->prefix, node->nodeName, nPrefix );
node->localName = strdup( pLocalName ); node->localName = safe_strdup( pLocalName );
if( node->localName == NULL ) { if( node->localName == NULL ) {
free( node->prefix ); free( node->prefix );
node->prefix = NULL; //no need to free really, main loop will frees it node->prefix = NULL; //no need to free really, main loop will frees it
@ -1718,7 +1733,7 @@ Parser_xmlNamespace( IN Parser * xmlParser,
} }
///here it goes to segfault on "" when not copying ///here it goes to segfault on "" when not copying
if(newNode->nodeValue){ if(newNode->nodeValue){
pCur->namespaceUri = strdup( newNode->nodeValue ); pCur->namespaceUri = safe_strdup( newNode->nodeValue );
if( pCur->namespaceUri == NULL ) { if( pCur->namespaceUri == NULL ) {
return IXML_INSUFFICIENT_MEMORY; return IXML_INSUFFICIENT_MEMORY;
} }
@ -1738,7 +1753,7 @@ Parser_xmlNamespace( IN Parser * xmlParser,
if( ( pCur->prefix != NULL ) if( ( pCur->prefix != NULL )
&& ( strcmp( pCur->prefix, newNode->localName ) == 0 ) ) { && ( strcmp( pCur->prefix, newNode->localName ) == 0 ) ) {
pCur->namespaceUri = strdup( newNode->nodeValue ); pCur->namespaceUri = safe_strdup( newNode->nodeValue );
if( pCur->namespaceUri == NULL ) { if( pCur->namespaceUri == NULL ) {
return IXML_INSUFFICIENT_MEMORY; return IXML_INSUFFICIENT_MEMORY;
} }
@ -1765,13 +1780,13 @@ Parser_xmlNamespace( IN Parser * xmlParser,
} }
memset( pNewNs, 0, sizeof( IXML_NamespaceURI ) ); memset( pNewNs, 0, sizeof( IXML_NamespaceURI ) );
pNewNs->prefix = strdup( newNode->localName ); pNewNs->prefix = safe_strdup( newNode->localName );
if( pNewNs->prefix == NULL ) { if( pNewNs->prefix == NULL ) {
free( pNewNs ); free( pNewNs );
return IXML_INSUFFICIENT_MEMORY; return IXML_INSUFFICIENT_MEMORY;
} }
pNewNs->nsURI = strdup( newNode->nodeValue ); pNewNs->nsURI = safe_strdup( newNode->nodeValue );
if( pNewNs->nsURI == NULL ) { if( pNewNs->nsURI == NULL ) {
Parser_freeNsURI( pNewNs ); Parser_freeNsURI( pNewNs );
free( pNewNs ); free( pNewNs );
@ -1789,7 +1804,7 @@ Parser_xmlNamespace( IN Parser * xmlParser,
free( pNs->nsURI ); free( pNs->nsURI );
} }
pNs->nsURI = strdup( newNode->nodeValue ); pNs->nsURI = safe_strdup( newNode->nodeValue );
if( pNs->nsURI == NULL ) { if( pNs->nsURI == NULL ) {
return IXML_INSUFFICIENT_MEMORY; return IXML_INSUFFICIENT_MEMORY;
} }
@ -1826,7 +1841,7 @@ Parser_processSTag( IN Parser * xmlParser,
pCurToken = ( xmlParser->tokenBuf ).buf; pCurToken = ( xmlParser->tokenBuf ).buf;
if( pCurToken != NULL ) { if( pCurToken != NULL ) {
node->nodeName = strdup( pCurToken ); node->nodeName = safe_strdup( pCurToken );
if( node->nodeName == NULL ) { if( node->nodeName == NULL ) {
return IXML_INSUFFICIENT_MEMORY; return IXML_INSUFFICIENT_MEMORY;
} }
@ -1977,7 +1992,7 @@ Parser_processCDSect( IN char **pSrc,
strncpy( node->nodeValue, pCDataStart, tokenLength ); strncpy( node->nodeValue, pCDataStart, tokenLength );
node->nodeValue[tokenLength] = '\0'; node->nodeValue[tokenLength] = '\0';
node->nodeName = strdup( CDATANODENAME ); node->nodeName = safe_strdup( CDATANODENAME );
if( node->nodeName == NULL ) { if( node->nodeName == NULL ) {
// no need to free node->nodeValue at all, bacause node contents // no need to free node->nodeValue at all, bacause node contents
// will be freed by the main loop. // will be freed by the main loop.
@ -2008,7 +2023,7 @@ Parser_setElementNamespace( IN IXML_Element * newElement,
if( newElement->n.namespaceURI != NULL ) { if( newElement->n.namespaceURI != NULL ) {
return IXML_SYNTAX_ERR; return IXML_SYNTAX_ERR;
} else { } else {
( newElement->n ).namespaceURI = strdup( nsURI ); ( newElement->n ).namespaceURI = safe_strdup( nsURI );
if( ( newElement->n ).namespaceURI == NULL ) { if( ( newElement->n ).namespaceURI == NULL ) {
return IXML_INSUFFICIENT_MEMORY; return IXML_INSUFFICIENT_MEMORY;
} }
@ -2107,7 +2122,7 @@ Parser_processContent( IN Parser * xmlParser,
pCurToken = ( xmlParser->tokenBuf ).buf; pCurToken = ( xmlParser->tokenBuf ).buf;
if( pCurToken != NULL ) { if( pCurToken != NULL ) {
node->nodeValue = strdup( pCurToken ); node->nodeValue = safe_strdup( pCurToken );
if( node->nodeValue == NULL ) { if( node->nodeValue == NULL ) {
return IXML_INSUFFICIENT_MEMORY; return IXML_INSUFFICIENT_MEMORY;
} }
@ -2115,7 +2130,7 @@ Parser_processContent( IN Parser * xmlParser,
return IXML_SYNTAX_ERR; return IXML_SYNTAX_ERR;
} }
node->nodeName = strdup( TEXTNODENAME ); node->nodeName = safe_strdup( TEXTNODENAME );
if( node->nodeName == NULL ) { if( node->nodeName == NULL ) {
return IXML_SYNTAX_ERR; return IXML_SYNTAX_ERR;
} }
@ -2152,7 +2167,7 @@ Parser_processETag( IN Parser * xmlParser,
if( pCurToken == NULL ) { if( pCurToken == NULL ) {
return IXML_SYNTAX_ERR; return IXML_SYNTAX_ERR;
} }
node->nodeName = strdup( pCurToken ); node->nodeName = safe_strdup( pCurToken );
if( node->nodeName == NULL ) { if( node->nodeName == NULL ) {
return IXML_INSUFFICIENT_MEMORY; return IXML_INSUFFICIENT_MEMORY;
} }
@ -2320,7 +2335,7 @@ Parser_processAttribute( IN Parser * xmlParser,
return IXML_SYNTAX_ERR; return IXML_SYNTAX_ERR;
} }
// copy in the attribute name // copy in the attribute name
node->nodeName = strdup( pCurToken ); node->nodeName = safe_strdup( pCurToken );
if( node->nodeName == NULL ) { if( node->nodeName == NULL ) {
return IXML_INSUFFICIENT_MEMORY; return IXML_INSUFFICIENT_MEMORY;
} }
@ -2373,7 +2388,7 @@ Parser_processAttribute( IN Parser * xmlParser,
pCurToken = ( xmlParser->tokenBuf ).buf; pCurToken = ( xmlParser->tokenBuf ).buf;
if( pCurToken != NULL ) { // attribute has value, like a="c" if( pCurToken != NULL ) { // attribute has value, like a="c"
node->nodeValue = strdup( pCurToken ); node->nodeValue = safe_strdup( pCurToken );
if( node->nodeValue == NULL ) { if( node->nodeValue == NULL ) {
return IXML_INSUFFICIENT_MEMORY; return IXML_INSUFFICIENT_MEMORY;
} }
@ -2456,7 +2471,7 @@ Parser_getNextNode( IN Parser * xmlParser,
goto ErrorHandler; goto ErrorHandler;
} }
node->nodeName = strdup( lastElement ); node->nodeName = safe_strdup( lastElement );
if( node->nodeName == NULL ) { if( node->nodeName == NULL ) {
return IXML_INSUFFICIENT_MEMORY; return IXML_INSUFFICIENT_MEMORY;
} }

View File

@ -1,15 +1,14 @@
Version: 1.4.1 Version: 1.4.2
Summary: Universal Plug and Play (UPnP) SDK Summary: Universal Plug and Play (UPnP) SDK
Name: libupnp Name: libupnp
Release: 1%{?dist} Release: 1%{?dist}
License: BSD License: BSD
Group: System Environment/Libraries Group: System Environment/Libraries
URL: http://www.libupnp.org/ URL: http://www.libupnp.org/
Source: http://puzzle.dl.sourceforge.net/sourceforge/pupnp/%{name}-%{version}.tar.gz Source: http://puzzle.dl.sourceforge.net/sourceforge/pupnp/%{name}-%{version}.tar.bz2
Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
%define docdir %{_docdir}/%{name}-%{version}-%{release} %define docdeveldir %{_docdir}/%{name}-devel-%{version}
%define docdeveldir %{_docdir}/%{name}-devel-%{version}-%{release}
%description %description
The Universal Plug and Play (UPnP) SDK for Linux provides The Universal Plug and Play (UPnP) SDK for Linux provides
@ -29,7 +28,7 @@ the UPnP SDK libraries.
%setup -q %setup -q
%build %build
%configure --with-docdir=%{docdir}/ %configure --with-documentation
make %{?_smp_mflags} make %{?_smp_mflags}
%install %install
@ -78,6 +77,9 @@ make install DESTDIR=$RPM_BUILD_ROOT
rm -rf %{buildroot} rm -rf %{buildroot}
%changelog %changelog
* Fri Feb 02 2007 Eric Tanguy <eric.tanguy@univ-nantes.fr> - 1.4.2-1
- Update to version 1.4.2
* Wed Jul 05 2006 Eric Tanguy <eric.tanguy@univ-nantes.fr> - 1.4.1-1 * Wed Jul 05 2006 Eric Tanguy <eric.tanguy@univ-nantes.fr> - 1.4.1-1
- Update to version 1.4.1 - Update to version 1.4.1
@ -117,3 +119,4 @@ rm -rf %{buildroot}
* Thu Dec 22 2005 Eric Tanguy 1.2.1a-1 * Thu Dec 22 2005 Eric Tanguy 1.2.1a-1
- Modify spec file from - Modify spec file from
http://rpm.pbone.net/index.php3/stat/4/idpl/2378737/com/libupnp-1.2.1a_DSM320-3.i386.rpm.html http://rpm.pbone.net/index.php3/stat/4/idpl/2378737/com/libupnp-1.2.1a_DSM320-3.i386.rpm.html

View File

@ -61,32 +61,33 @@ typedef enum priority {LOW_PRIORITY,
#define DEFAULT_JOBS_PER_THREAD 10 //default jobs per thread used by TPAttrInit #define DEFAULT_JOBS_PER_THREAD 10 //default jobs per thread used by TPAttrInit
#define DEFAULT_STARVATION_TIME 500 //default starvation time used by TPAttrInit #define DEFAULT_STARVATION_TIME 500 //default starvation time used by TPAttrInit
#define DEFAULT_IDLE_TIME 10 * 1000 //default idle time used by TPAttrInit #define DEFAULT_IDLE_TIME 10 * 1000 //default idle time used by TPAttrInit
#define DEFAULT_FREE_ROUTINE NULL //default free routine used TPJobInit #define DEFAULT_FREE_ROUTINE NULL //default free routine used TPJobInit
#define DEFAULT_MAX_JOBS_TOTAL 100 //default max jobs used TPAttrInit
#define STATS 1 //always include stats because code change is minimal #define STATS 1 //always include stats because code change is minimal
//Statistics //Statistics
#ifdef WIN32 // todo: check why STATSONLY fails during compilation #ifdef WIN32 // todo: check why STATSONLY fails during compilation
#undef STATS #undef STATS
#endif #endif
#ifdef STATS #ifdef STATS
#define STATSONLY(x) x #define STATSONLY(x) x
#else #else
#define STATSONLY(x) #define STATSONLY(x)
#endif #endif
#ifdef _DEBUG #ifdef _DEBUG
#define DEBUG 1 #define DEBUG 1
#endif #endif
//DEBUGGING //DEBUGGING
#ifndef WIN32 #ifndef WIN32
#ifdef DEBUG #ifdef DEBUG
#define DBGONLY(x) x #define DBGONLY(x) x
#else #else
#define DBGONLY(x) #define DBGONLY(x)
#endif #endif
#endif #endif
@ -97,7 +98,7 @@ typedef enum priority {LOW_PRIORITY,
#include "ithread.h" #include "ithread.h"
#include <errno.h> #include <errno.h>
#include <sys/timeb.h> #include <sys/timeb.h>
#define EXPORT #define EXPORT
typedef int PolicyType; typedef int PolicyType;
#define DEFAULT_POLICY SCHED_OTHER #define DEFAULT_POLICY SCHED_OTHER
#define DEFAULT_SCHED_PARAM 0 //default priority #define DEFAULT_SCHED_PARAM 0 //default priority
@ -114,28 +115,30 @@ typedef void (*free_routine)(void *arg);
* Name: ThreadPoolAttr * Name: ThreadPoolAttr
* *
* Description: * Description:
* Attributes for thread pool. Used to set and change parameters of * Attributes for thread pool. Used to set and change parameters of
* thread pool * thread pool
*****************************************************************************/ *****************************************************************************/
typedef struct THREADPOOLATTR typedef struct THREADPOOLATTR
{ {
int minThreads; //minThreads, ThreadPool will always maintain at least int minThreads; // minThreads, ThreadPool will always maintain at least
//this many threads // this many threads
int maxThreads; //maxThreads, ThreadPool will never have more than this
//number of threads
int maxIdleTime; //maxIdleTime (in milliseconds)
// this is the maximum time a thread will remain idle
// before dying
int jobsPerThread; //jobs per thread to maintain int maxThreads; // maxThreads, ThreadPool will never have more than this
// number of threads
int starvationTime; //the time a low priority or med priority
//job waits before getting bumped int maxIdleTime; // maxIdleTime (in milliseconds)
//up a priority (in milliseconds) // this is the maximum time a thread will remain idle
// before dying
PolicyType schedPolicy; //scheduling policy to use
int jobsPerThread; // jobs per thread to maintain
int maxJobsTotal; // maximum number of jobs that can be queued totally.
int starvationTime; // the time a low priority or med priority
// job waits before getting bumped
// up a priority (in milliseconds)
PolicyType schedPolicy; // scheduling policy to use
} ThreadPoolAttr; } ThreadPoolAttr;
@ -152,7 +155,7 @@ typedef struct THREADPOOLJOB
free_routine free_func; //free function free_routine free_func; //free function
struct timeb requestTime; //time of request struct timeb requestTime; //time of request
int priority; //priority of request int priority; //priority of request
int jobId; //id int jobId; //id
} ThreadPoolJob; } ThreadPoolJob;
/**************************************************************************** /****************************************************************************
@ -168,20 +171,20 @@ typedef struct TPOOLSTATS
{ {
double totalTimeHQ; //total time spent by all jobs in high priority Q double totalTimeHQ; //total time spent by all jobs in high priority Q
int totalJobsHQ; //total jobs in HQ run so far int totalJobsHQ; //total jobs in HQ run so far
double avgWaitHQ; //average wait in HQ double avgWaitHQ; //average wait in HQ
double totalTimeMQ; //total time spent by all jobs in med priority Q double totalTimeMQ; //total time spent by all jobs in med priority Q
int totalJobsMQ; //total jobs in MQ run so far int totalJobsMQ; //total jobs in MQ run so far
double avgWaitMQ; //average wait in MQ double avgWaitMQ; //average wait in MQ
double totalTimeLQ; //total time spent by all jobs in low priority Q double totalTimeLQ; //total time spent by all jobs in low priority Q
int totalJobsLQ; //total jobs in LQ run so far int totalJobsLQ; //total jobs in LQ run so far
double avgWaitLQ; //average wait in LQ double avgWaitLQ; //average wait in LQ
double totalWorkTime; //total time spent working for all threads double totalWorkTime; //total time spent working for all threads
double totalIdleTime; //total time spent idle for all threads double totalIdleTime; //total time spent idle for all threads
int workerThreads; //number of current workerThreads int workerThreads; //number of current workerThreads
int idleThreads; //number of current idle threads int idleThreads; //number of current idle threads
int persistentThreads; //number of persistent threads int persistentThreads; //number of persistent threads
int totalThreads; //total number of current threads int totalThreads; //total number of current threads
int maxThreads; //max threads so far int maxThreads; //max threads so far
int currentJobsHQ; // current jobs in Q int currentJobsHQ; // current jobs in Q
int currentJobsLQ; //current jobs in Q int currentJobsLQ; //current jobs in Q
int currentJobsMQ; //current jobs in Q int currentJobsMQ; //current jobs in Q
@ -521,6 +524,19 @@ int TPAttrSetStarvationTime(ThreadPoolAttr *attr, int starvationTime);
int TPAttrSetSchedPolicy(ThreadPoolAttr *attr, PolicyType schedPolicy); int TPAttrSetSchedPolicy(ThreadPoolAttr *attr, PolicyType schedPolicy);
/****************************************************************************
* Function: TPAttrSetMaxJobsTotal
*
* Description:
* Sets the maximum number jobs that can be qeued totally.
* Parameters:
* attr - must be valid thread pool attributes.
* maxJobsTotal - maximum number of jobs
* Returns:
* Always returns 0.
*****************************************************************************/
int TPAttrSetMaxJobsTotal(ThreadPoolAttr *attr, int maxJobsTotal);
/**************************************************************************** /****************************************************************************
* Function: ThreadPoolGetStats * Function: ThreadPoolGetStats
* *

View File

@ -906,6 +906,7 @@ tp->stats.totalJobsLQ++; tp->stats.totalTimeLQ += diff; break; default:
int rc = EOUTOFMEM; int rc = EOUTOFMEM;
int tempId = -1; int tempId = -1;
int totalJobs;
ThreadPoolJob *temp = NULL; ThreadPoolJob *temp = NULL;
@ -922,6 +923,13 @@ tp->stats.totalJobsLQ++; tp->stats.totalTimeLQ += diff; break; default:
|| ( job->priority == MED_PRIORITY ) || ( job->priority == MED_PRIORITY )
|| ( job->priority == HIGH_PRIORITY ) ); || ( job->priority == HIGH_PRIORITY ) );
totalJobs = tp->highJobQ.size + tp->lowJobQ.size + tp->medJobQ.size;
if (totalJobs >= tp->attr.maxJobsTotal) {
fprintf(stderr, "total jobs = %d, too many jobs", totalJobs);
ithread_mutex_unlock( &tp->mutex );
return rc;
}
if( jobId == NULL ) if( jobId == NULL )
jobId = &tempId; jobId = &tempId;
@ -1267,6 +1275,7 @@ tp->stats.totalJobsLQ++; tp->stats.totalTimeLQ += diff; break; default:
attr->minThreads = DEFAULT_MIN_THREADS; attr->minThreads = DEFAULT_MIN_THREADS;
attr->schedPolicy = DEFAULT_POLICY; attr->schedPolicy = DEFAULT_POLICY;
attr->starvationTime = DEFAULT_STARVATION_TIME; attr->starvationTime = DEFAULT_STARVATION_TIME;
attr->maxJobsTotal = DEFAULT_MAX_JOBS_TOTAL;
return 0; return 0;
} }
@ -1518,6 +1527,29 @@ tp->stats.totalJobsLQ++; tp->stats.totalTimeLQ += diff; break; default:
stats->totalIdleTime );} stats->totalIdleTime );}
#endif #endif
/****************************************************************************
* Function: TPAttrSetMaxJobsTotal
*
* Description:
* Sets the maximum number jobs that can be qeued totally.
* Parameters:
* attr - must be valid thread pool attributes.
* maxJobsTotal - maximum number of jobs
* Returns:
* Always returns 0.
*****************************************************************************/
int TPAttrSetMaxJobsTotal( ThreadPoolAttr * attr,
int maxJobsTotal ) {
assert( attr != NULL );
if( attr == NULL ) {
return EINVAL;
}
attr->maxJobsTotal = maxJobsTotal;
return 0;
}
/**************************************************************************** /****************************************************************************
* Function: ThreadPoolGetStats * Function: ThreadPoolGetStats
* *

View File

@ -132,8 +132,7 @@ upnp_tv_ctrlpt_SOURCES = \
sample/tvctrlpt/upnp_tv_ctrlpt.h \ sample/tvctrlpt/upnp_tv_ctrlpt.h \
sample/tvctrlpt/linux/upnp_tv_ctrlpt_main.c sample/tvctrlpt/linux/upnp_tv_ctrlpt_main.c
if WITH_DOCDIR if WITH_DOCUMENTATION
docdir = @DOCDIR@
examplesdir = $(docdir)/examples examplesdir = $(docdir)/examples
examples_DATA = $(upnp_tv_ctrlpt_SOURCES) $(upnp_tv_device_SOURCES) examples_DATA = $(upnp_tv_ctrlpt_SOURCES) $(upnp_tv_device_SOURCES)
endif endif

View File

@ -36,6 +36,14 @@
//@{ //@{
#if defined MYLIB_LARGEFILE_SENSITIVE && _FILE_OFFSET_BITS+0 != 64
#if defined __GNUC__
#warning libupnp requires largefile mode - use AC_SYS_LARGEFILE
#else
#error libupnp requires largefile mode - use AC_SYS_LARGEFILE
#endif
#endif
#include <stdio.h> #include <stdio.h>
#ifdef __FreeBSD__ #ifdef __FreeBSD__
#include <time.h> #include <time.h>
@ -65,6 +73,7 @@
#define UpnpCloseSocket close #define UpnpCloseSocket close
#else #else
#define UpnpCloseSocket closesocket #define UpnpCloseSocket closesocket
#define fseeko fseek
#endif #endif
#define UPNP_SOCKETERROR -1 #define UPNP_SOCKETERROR -1
#define UPNP_INVALID_SOCKET -1 #define UPNP_INVALID_SOCKET -1
@ -79,6 +88,8 @@
#include <time.h> #include <time.h>
#endif #endif
#include <sys/types.h>
#define NUM_HANDLE 200 #define NUM_HANDLE 200
#define LINE_SIZE 180 #define LINE_SIZE 180
#define NAME_SIZE 256 #define NAME_SIZE 256
@ -875,7 +886,7 @@ struct File_Info
/** The length of the file. A length less than 0 indicates the size /** The length of the file. A length less than 0 indicates the size
* is unknown, and data will be sent until 0 bytes are returned from * is unknown, and data will be sent until 0 bytes are returned from
* a read call. */ * a read call. */
int file_length; off_t file_length;
/** The time at which the contents of the file was modified; /** The time at which the contents of the file was modified;
* The time system is always local (not GMT). */ * The time system is always local (not GMT). */
@ -969,7 +980,7 @@ struct UpnpVirtualDirCallbacks
int (*seek) ( int (*seek) (
IN UpnpWebFileHandle fileHnd, /** The handle of the file to move the IN UpnpWebFileHandle fileHnd, /** The handle of the file to move the
file pointer. */ file pointer. */
IN long offset, /** The number of bytes to move in the IN off_t offset, /** The number of bytes to move in the
file. Positive values move foward and file. Positive values move foward and
negative values move backward. Note negative values move backward. Note
that this must be positive if the that this must be positive if the
@ -2707,4 +2718,3 @@ EXPORT_SPEC void UpnpFree(
//@} The API //@} The API
#endif #endif

View File

@ -1974,9 +1974,7 @@ TvDeviceStart( char *ip_address,
ip_address = UpnpGetServerIpAddress( ); ip_address = UpnpGetServerIpAddress( );
} }
if( port == 0 ) {
port = UpnpGetServerPort( ); port = UpnpGetServerPort( );
}
SampleUtil_Print( "UPnP Initialized\n \t ipaddress= %s port = %d\n", SampleUtil_Print( "UPnP Initialized\n \t ipaddress= %s port = %d\n",
ip_address, port ); ip_address, port );

View File

@ -244,6 +244,7 @@ int UpnpInit( IN const char *HostIP,
TPAttrSetMinThreads( &attr, MIN_THREADS ); TPAttrSetMinThreads( &attr, MIN_THREADS );
TPAttrSetJobsPerThread( &attr, JOBS_PER_THREAD ); TPAttrSetJobsPerThread( &attr, JOBS_PER_THREAD );
TPAttrSetIdleTime( &attr, THREAD_IDLE_TIME ); TPAttrSetIdleTime( &attr, THREAD_IDLE_TIME );
TPAttrSetMaxJobsTotal( &attr, MAX_JOBS_TOTAL );
if( ThreadPoolInit( &gSendThreadPool, &attr ) != UPNP_E_SUCCESS ) { if( ThreadPoolInit( &gSendThreadPool, &attr ) != UPNP_E_SUCCESS ) {
UpnpSdkInit = 0; UpnpSdkInit = 0;
@ -955,7 +956,7 @@ GetDescDocumentAndURL( IN Upnp_DescType descriptionType,
char aliasStr[LINE_SIZE]; char aliasStr[LINE_SIZE];
char *temp_str = NULL; char *temp_str = NULL;
FILE *fp = NULL; FILE *fp = NULL;
unsigned fileLen; off_t fileLen;
unsigned num_read; unsigned num_read;
time_t last_modified; time_t last_modified;
struct stat file_info; struct stat file_info;
@ -3339,19 +3340,20 @@ UpnpDownloadXmlDoc( const char *url,
return ret_code; return ret_code;
} }
/* TODO: MoNKi: Do not check this?? Some routers (Linksys WRT54GS) sends
"CONTENT-TYPE: application/octet-stream". If the data sended is not
an xml file, ixmlParseBufferEx will fail and the function will return
UPNP_E_INVALID_DESC too.*/
if( strncasecmp( content_type, "text/xml", strlen( "text/xml" ) ) ) { if( strncasecmp( content_type, "text/xml", strlen( "text/xml" ) ) ) {
DBGONLY(
UpnpPrintf( UPNP_INFO, API, __FILE__, __LINE__, "Not text/xml\n" );
)
// Linksys WRT54G router returns
// "CONTENT-TYPE: application/octet-stream".
// Let's be nice to Linksys and try to parse document anyway.
// If the data sended is not a xml file, ixmlParseBufferEx
// will fail and the function will return UPNP_E_INVALID_DESC too.
#if 0
free( xml_buf ); free( xml_buf );
DBGONLY( UpnpPrintf( UPNP_CRITICAL, API, __FILE__, __LINE__, return UPNP_E_INVALID_DESC;
"Not text/xml\n" ); #endif
)
return UPNP_E_INVALID_DESC;
} }
// end of TODO Do not check this
ret_code = ixmlParseBufferEx( xml_buf, xmlDoc ); ret_code = ixmlParseBufferEx( xml_buf, xmlDoc );
free( xml_buf ); free( xml_buf );

View File

@ -196,11 +196,12 @@ addToAction( IN int response,
if( response ) { if( response ) {
sprintf( ActBuff, sprintf( ActBuff,
"<u:%sResponse xmlns:u=\"%s\"></u:%sResponse>", "<u:%sResponse xmlns:u=\"%s\">\r\n</u:%sResponse>",
ActionName, ServType, ActionName ); ActionName, ServType, ActionName );
} else { } else {
sprintf( ActBuff, "<u:%s xmlns:u=\"%s\"></u:%s>", sprintf( ActBuff,
ActionName, ServType, ActionName ); "<u:%s xmlns:u=\"%s\">\r\n</u:%s>",
ActionName, ServType, ActionName );
} }
rc = ixmlParseBufferEx( ActBuff, ActionDoc ); rc = ixmlParseBufferEx( ActBuff, ActionDoc );
@ -274,11 +275,13 @@ makeAction( IN int response,
} }
if( response ) { if( response ) {
sprintf( ActBuff, "<u:%sResponse xmlns:u=\"%s\"></u:%sResponse>", sprintf( ActBuff,
ActionName, ServType, ActionName ); "<u:%sResponse xmlns:u=\"%s\">\r\n</u:%sResponse>",
ActionName, ServType, ActionName );
} else { } else {
sprintf( ActBuff, "<u:%s xmlns:u=\"%s\"></u:%s>", sprintf( ActBuff,
ActionName, ServType, ActionName ); "<u:%s xmlns:u=\"%s\">\r\n</u:%s>",
ActionName, ServType, ActionName );
} }
if( ixmlParseBufferEx( ActBuff, &ActionDoc ) != IXML_SUCCESS ) { if( ixmlParseBufferEx( ActBuff, &ActionDoc ) != IXML_SUCCESS ) {

View File

@ -219,10 +219,11 @@ gena_unsubscribe( IN char *url,
// make request msg // make request msg
membuffer_init( &request ); membuffer_init( &request );
request.size_inc = 30; request.size_inc = 30;
return_code = http_MakeMessage( &request, 1, 1, return_code = http_MakeMessage(
"q" "ssc" "U" "c", &request, 1, 1,
HTTPMETHOD_UNSUBSCRIBE, &dest_url, "q" "ssc" "Uc",
"SID: ", sid ); HTTPMETHOD_UNSUBSCRIBE, &dest_url,
"SID: ", sid );
//Not able to make the message so destroy the existing buffer //Not able to make the message so destroy the existing buffer
if( return_code != 0 ) { if( return_code != 0 ) {
@ -305,20 +306,21 @@ gena_subscribe( IN char *url,
request.size_inc = 30; request.size_inc = 30;
if( renewal_sid ) { if( renewal_sid ) {
// renew subscription // renew subscription
return_code = http_MakeMessage( &request, 1, 1, return_code = http_MakeMessage(
"q" "ssc" "ssc" "c", &request, 1, 1,
HTTPMETHOD_SUBSCRIBE, &dest_url, "q" "ssc" "sscc",
"SID: ", renewal_sid, HTTPMETHOD_SUBSCRIBE, &dest_url,
"TIMEOUT: Second-", timeout_str ); "SID: ", renewal_sid,
"TIMEOUT: Second-", timeout_str );
} else { } else {
// subscribe // subscribe
return_code = http_MakeMessage( &request, 1, 1, return_code = http_MakeMessage(
"q" "sssdsscc", &request, 1, 1,
HTTPMETHOD_SUBSCRIBE, &dest_url, "q" "sssdsc" "sc" "sscc",
"CALLBACK: <http://", LOCAL_HOST, HTTPMETHOD_SUBSCRIBE, &dest_url,
":", LOCAL_PORT, "CALLBACK: <http://", LOCAL_HOST, ":", LOCAL_PORT, "/>",
"/>\r\n" "NT: upnp:event\r\n" "NT: upnp:event",
"TIMEOUT: Second-", timeout_str ); "TIMEOUT: Second-", timeout_str );
} }
if( return_code != 0 ) { if( return_code != 0 ) {
return return_code; return return_code;

View File

@ -219,9 +219,11 @@ notify_send_and_recv( IN uri_type * destination_url,
} }
// make start line and HOST header // make start line and HOST header
membuffer_init( &start_msg ); membuffer_init( &start_msg );
if( http_MakeMessage( &start_msg, 1, 1, if (http_MakeMessage(
"q" "s", &start_msg, 1, 1,
HTTPMETHOD_NOTIFY, &url, mid_msg->buf ) != 0 ) { "q" "s",
HTTPMETHOD_NOTIFY, &url,
mid_msg->buf ) != 0 ) {
membuffer_destroy( &start_msg ); membuffer_destroy( &start_msg );
sock_destroy( &info, SD_BOTH ); sock_destroy( &info, SD_BOTH );
return UPNP_E_OUTOF_MEMORY; return UPNP_E_OUTOF_MEMORY;
@ -296,11 +298,12 @@ genaNotify( IN char *headers,
// make 'end' msg (the part that won't vary with the destination) // make 'end' msg (the part that won't vary with the destination)
endmsg.size_inc = 30; endmsg.size_inc = 30;
if( http_MakeMessage( &mid_msg, 1, 1, if( http_MakeMessage(
"s" "ssc" "sdcc", &mid_msg, 1, 1,
headers, "s" "ssc" "sdcc",
"SID: ", sub->sid, headers,
"SEQ: ", sub->ToSendEventKey ) != 0 ) { "SID: ", sub->sid,
"SEQ: ", sub->ToSendEventKey ) != 0 ) {
membuffer_destroy( &mid_msg ); membuffer_destroy( &mid_msg );
return UPNP_E_OUTOF_MEMORY; return UPNP_E_OUTOF_MEMORY;
} }
@ -1165,10 +1168,14 @@ respond_ok( IN SOCKINFO * info,
membuffer_init( &response ); membuffer_init( &response );
response.size_inc = 30; response.size_inc = 30;
if( http_MakeMessage( &response, major, minor, if( http_MakeMessage(
"R" "D" "S" "N" "Xc" "ssc" "sc" "c", &response, major, minor,
HTTP_OK, 0, X_USER_AGENT, "R" "D" "S" "N" "Xc" "ssc" "scc",
"SID: ", sub->sid, timeout_str ) != 0 ) { HTTP_OK,
(off_t)0,
X_USER_AGENT,
"SID: ", sub->sid,
timeout_str ) != 0 ) {
membuffer_destroy( &response ); membuffer_destroy( &response );
error_respond( info, HTTP_INTERNAL_SERVER_ERROR, request ); error_respond( info, HTTP_INTERNAL_SERVER_ERROR, request );
return UPNP_E_OUTOF_MEMORY; return UPNP_E_OUTOF_MEMORY;

View File

@ -651,6 +651,11 @@ get_miniserver_sockets( MiniServerSockArray * out,
sizeof( struct sockaddr_in ) sizeof( struct sockaddr_in )
); );
if( sockError == UPNP_SOCKETERROR ) { if( sockError == UPNP_SOCKETERROR ) {
#ifdef WIN32
errCode = WSAGetLastError();
#else
errCode = errno;
#endif
if( errno == EADDRINUSE ) if( errno == EADDRINUSE )
errCode = 1; errCode = 1;
} else } else

View File

@ -306,8 +306,8 @@ http_SendMessage( IN SOCKINFO * info,
char *filename = NULL; char *filename = NULL;
FILE *Fp; FILE *Fp;
int num_read, int num_read,
num_written, num_written;
amount_to_be_read = 0; off_t amount_to_be_read = 0;
va_list argp; va_list argp;
char *file_buf = NULL, char *file_buf = NULL,
*ChunkBuf = NULL; *ChunkBuf = NULL;
@ -367,7 +367,7 @@ http_SendMessage( IN SOCKINFO * info,
return UPNP_E_FILE_READ_ERROR; return UPNP_E_FILE_READ_ERROR;
} }
} else if( Instr && Instr->IsRangeActive ) { } else if( Instr && Instr->IsRangeActive ) {
if( fseek( Fp, Instr->RangeOffset, SEEK_CUR ) != 0 ) { if( fseeko( Fp, Instr->RangeOffset, SEEK_CUR ) != 0 ) {
free( ChunkBuf ); free( ChunkBuf );
return UPNP_E_FILE_READ_ERROR; return UPNP_E_FILE_READ_ERROR;
} }
@ -640,10 +640,11 @@ http_Download( IN const char *url_str,
"HOSTNAME : %s Length : %d\n", hoststr, hostlen ); "HOSTNAME : %s Length : %d\n", hoststr, hostlen );
) )
ret_code = http_MakeMessage( &request, 1, 1, "QsbcDCUc", ret_code = http_MakeMessage(
HTTPMETHOD_GET, url.pathquery.buff, &request, 1, 1,
url.pathquery.size, "HOST: ", hoststr, "QsbcDCUc",
hostlen ); HTTPMETHOD_GET, url.pathquery.buff, url.pathquery.size,
"HOST: ", hoststr, hostlen );
if( ret_code != 0 ) { if( ret_code != 0 ) {
DBGONLY( UpnpPrintf DBGONLY( UpnpPrintf
( UPNP_INFO, HTTP, __FILE__, __LINE__, ( UPNP_INFO, HTTP, __FILE__, __LINE__,
@ -796,21 +797,27 @@ MakePostMessage( const char *url_str,
) )
if( contentLength >= 0 ) { if( contentLength >= 0 ) {
ret_code = http_MakeMessage( request, 1, 1, "QsbcDCUTNc", ret_code = http_MakeMessage(
HTTPMETHOD_POST, url->pathquery.buff, request, 1, 1,
url->pathquery.size, "HOST: ", "QsbcDCUTNc",
hoststr, hostlen, contentType, HTTPMETHOD_POST, url->pathquery.buff, url->pathquery.size,
contentLength ); "HOST: ", hoststr, hostlen,
contentType,
(off_t)contentLength );
} else if( contentLength == UPNP_USING_CHUNKED ) { } else if( contentLength == UPNP_USING_CHUNKED ) {
ret_code = http_MakeMessage( request, 1, 1, "QsbcDCUTKc", ret_code = http_MakeMessage(
HTTPMETHOD_POST, url->pathquery.buff, request, 1, 1,
url->pathquery.size, "HOST: ", "QsbcDCUTKc",
hoststr, hostlen, contentType ); HTTPMETHOD_POST, url->pathquery.buff, url->pathquery.size,
"HOST: ", hoststr, hostlen,
contentType );
} else if( contentLength == UPNP_UNTIL_CLOSE ) { } else if( contentLength == UPNP_UNTIL_CLOSE ) {
ret_code = http_MakeMessage( request, 1, 1, "QsbcDCUTc", ret_code = http_MakeMessage(
HTTPMETHOD_POST, url->pathquery.buff, request, 1, 1,
url->pathquery.size, "HOST: ", "QsbcDCUTc",
hoststr, hostlen, contentType ); HTTPMETHOD_POST, url->pathquery.buff, url->pathquery.size,
"HOST: ", hoststr, hostlen,
contentType );
} else { } else {
ret_code = UPNP_E_INVALID_PARAM; ret_code = UPNP_E_INVALID_PARAM;
} }
@ -1131,9 +1138,11 @@ MakeGetMessage( const char *url_str,
querylen = url->pathquery.size; querylen = url->pathquery.size;
} }
ret_code = http_MakeMessage( request, 1, 1, "QsbcDCUc", ret_code = http_MakeMessage(
HTTPMETHOD_GET, querystr, querylen, request, 1, 1,
"HOST: ", hoststr, hostlen ); "QsbcDCUc",
HTTPMETHOD_GET, querystr, querylen,
"HOST: ", hoststr, hostlen );
if( ret_code != 0 ) { if( ret_code != 0 ) {
DBGONLY( UpnpPrintf( UPNP_INFO, HTTP, __FILE__, __LINE__, DBGONLY( UpnpPrintf( UPNP_INFO, HTTP, __FILE__, __LINE__,
@ -1729,8 +1738,11 @@ http_SendStatusResponse( IN SOCKINFO * info,
membuffer_init( &membuf ); membuffer_init( &membuf );
membuf.size_inc = 70; membuf.size_inc = 70;
ret = http_MakeMessage( &membuf, response_major, response_minor, "RSCB", http_status_code, // response start line ret = http_MakeMessage(
http_status_code ); // body &membuf, response_major, response_minor,
"RSCB",
http_status_code, // response start line
http_status_code ); // body
if( ret == 0 ) { if( ret == 0 ) {
timeout = HTTP_DEFAULT_TIMEOUT; timeout = HTTP_DEFAULT_TIMEOUT;
ret = http_SendMessage( info, &timeout, "b", ret = http_SendMessage( info, &timeout, "b",
@ -1757,28 +1769,30 @@ http_SendStatusResponse( IN SOCKINFO * info,
* specified in the input parameters. * specified in the input parameters.
* *
* fmt types: * fmt types:
* 's': arg = const char* C_string * 'B': arg = int status_code
* appends content-length, content-type and HTML body for given code
* 'b': arg1 = const char* buf; arg2 = size_t buf_length * 'b': arg1 = const char* buf; arg2 = size_t buf_length
* memory ptr * memory ptr
* 'c': (no args) appends CRLF "\r\n"
* 'd': arg = int number // appends decimal number
* 't': arg = time_t * gmt_time // appends time in RFC 1123 fmt
* 'D': (no args) appends HTTP DATE: header
* 'S': (no args) appends HTTP SERVER: header
* 'U': (no args) appends HTTP USER-AGENT: header
* 'C': (no args) appends a HTTP CONNECTION: close header * 'C': (no args) appends a HTTP CONNECTION: close header
* depending on major,minor version * depending on major,minor version
* 'c': (no args) appends CRLF "\r\n"
* 'D': (no args) appends HTTP DATE: header
* 'd': arg = int number // appends decimal number
* 'G': arg = range information // add range header
* 'h': arg = off_t number // appends off_t number
* 'K': (no args) // add chunky header
* 'N': arg1 = int content_length // content-length header * 'N': arg1 = int content_length // content-length header
* 'q': arg1 = http_method_t, arg2 = (uri_type *) // request start line and HOST header
* 'Q': arg1 = http_method_t; arg2 = char* url; * 'Q': arg1 = http_method_t; arg2 = char* url;
* arg3 = int url_length // start line of request * arg3 = int url_length // start line of request
* 'R': arg = int status_code // adds a response start line * 'R': arg = int status_code // adds a response start line
* 'B': arg = int status_code * 'S': (no args) appends HTTP SERVER: header
* appends content-length, content-type and HTML body for given code * 's': arg = const char* C_string
* 'T': arg = char * content_type; format e.g: "text/html"; * 'T': arg = char * content_type; format e.g: "text/html";
* content-type header * content-type header
* --- PATCH START - Sergey 'Jin' Bostandzhyan <jin_eld@users.sourceforge.net> * 't': arg = time_t * gmt_time // appends time in RFC 1123 fmt
* 'X': arg = const char useragent; "redsonic" HTTP X-User-Agent: useragent * 'U': (no args) appends HTTP USER-AGENT: header
* --- PATCH END --- * 'X': arg = const char useragent; "redsonic" HTTP X-User-Agent: useragent
* *
* Return : int; * Return : int;
* 0 - On Success * 0 - On Success
@ -1797,6 +1811,7 @@ http_MakeMessage( INOUT membuffer * buf,
char c; char c;
char *s = NULL; char *s = NULL;
int num; int num;
off_t bignum;
size_t length; size_t length;
time_t *loc_time; time_t *loc_time;
time_t curr_time; time_t curr_time;
@ -1884,6 +1899,16 @@ http_MakeMessage( INOUT membuffer * buf,
} }
} }
else if( c == 'h' ) // off_t
{
bignum = ( off_t )va_arg( argp, off_t );
sprintf( tempbuf, "%lld", bignum );
if( membuffer_append( buf, tempbuf, strlen( tempbuf ) ) != 0 ) {
goto error_handler;
}
}
else if( c == 't' || c == 'D' ) // date else if( c == 't' || c == 'D' ) // date
{ {
if( c == 'D' ) { if( c == 'D' ) {
@ -1925,12 +1950,13 @@ http_MakeMessage( INOUT membuffer * buf,
else if( c == 'N' ) { else if( c == 'N' ) {
// content-length header // content-length header
num = ( int )va_arg( argp, int ); bignum = ( off_t )va_arg( argp, off_t );
assert( num >= 0 ); assert( bignum >= 0 );
if( http_MakeMessage if (http_MakeMessage(
( buf, http_major_version, http_minor_version, "sdc", buf, http_major_version, http_minor_version,
"CONTENT-LENGTH: ", num ) != 0 ) { "shc",
"CONTENT-LENGTH: ", bignum ) != 0 ) {
goto error_handler; goto error_handler;
} }
} }
@ -1940,14 +1966,14 @@ http_MakeMessage( INOUT membuffer * buf,
temp_str = ( c == 'S' ) ? "SERVER: " : "USER-AGENT: "; temp_str = ( c == 'S' ) ? "SERVER: " : "USER-AGENT: ";
get_sdk_info( tempbuf ); get_sdk_info( tempbuf );
if( http_MakeMessage if (http_MakeMessage(
( buf, http_major_version, http_minor_version, "ss", buf, http_major_version, http_minor_version,
temp_str, tempbuf ) != 0 ) { "ss",
temp_str, tempbuf ) != 0 ) {
goto error_handler; goto error_handler;
} }
} }
/* --- PATCH START - Sergey 'Jin' Bostandzhyan <jin_eld@users.sourceforge.net> */
else if( c == 'X' ) // C string else if( c == 'X' ) // C string
{ {
s = ( char * )va_arg( argp, char * ); s = ( char * )va_arg( argp, char * );
@ -1962,9 +1988,6 @@ http_MakeMessage( INOUT membuffer * buf,
} }
} }
/* --- PATCH END --- */
else if( c == 'R' ) { else if( c == 'R' ) {
// response start line // response start line
// e.g.: 'HTTP/1.1 200 OK' // e.g.: 'HTTP/1.1 200 OK'
@ -1979,9 +2002,11 @@ http_MakeMessage( INOUT membuffer * buf,
// str // str
status_msg = http_get_code_text( status_code ); status_msg = http_get_code_text( status_code );
if( http_MakeMessage if (http_MakeMessage(
( buf, http_major_version, http_minor_version, "ssc", buf, http_major_version, http_minor_version,
tempbuf, status_msg ) != 0 ) { "ssc",
tempbuf,
status_msg ) != 0 ) {
goto error_handler; goto error_handler;
} }
} }
@ -1996,11 +2021,14 @@ http_MakeMessage( INOUT membuffer * buf,
"<html><body><h1>", "<html><body><h1>",
status_code, http_get_code_text( status_code ), status_code, http_get_code_text( status_code ),
"</h1></body></html>" ); "</h1></body></html>" );
num = strlen( tempbuf ); bignum = strlen( tempbuf );
if( http_MakeMessage( buf, http_major_version, http_minor_version, "NTcs", num, // content-length if (http_MakeMessage(
"text/html", // content-type buf, http_major_version, http_minor_version,
tempbuf ) != 0 ) // body "NTcs",
bignum, // content-length
"text/html", // content-type
tempbuf ) != 0 ) // body
{ {
goto error_handler; goto error_handler;
} }
@ -2009,17 +2037,18 @@ http_MakeMessage( INOUT membuffer * buf,
else if( c == 'Q' ) { else if( c == 'Q' ) {
// request start line // request start line
// GET /foo/bar.html HTTP/1.1\r\n // GET /foo/bar.html HTTP/1.1\r\n
//
method = ( http_method_t ) va_arg( argp, http_method_t ); method = ( http_method_t ) va_arg( argp, http_method_t );
method_str = method_to_str( method ); method_str = method_to_str( method );
url_str = ( const char * )va_arg( argp, const char * ); url_str = ( const char * )va_arg( argp, const char * );
num = ( int )va_arg( argp, int ); // length of url_str num = ( int )va_arg( argp, int ); // length of url_str
if( http_MakeMessage( buf, http_major_version, http_minor_version, "ssbsdsdc", method_str, // method if (http_MakeMessage(
" ", url_str, num, // url buf, http_major_version, http_minor_version,
" HTTP/", http_major_version, ".", "ssbsdsdc",
http_minor_version ) != 0 ) { method_str, // method
" ", url_str, num, // url
" HTTP/", http_major_version, ".", http_minor_version ) != 0 ) {
goto error_handler; goto error_handler;
} }
} }
@ -2036,10 +2065,11 @@ http_MakeMessage( INOUT membuffer * buf,
goto error_handler; goto error_handler;
} }
if( http_MakeMessage if (http_MakeMessage(
( buf, http_major_version, http_minor_version, "Q" "sbc", buf, http_major_version, http_minor_version,
method, url.pathquery.buff, url.pathquery.size, "HOST: ", "Q" "sbc",
url.hostport.text.buff, url.hostport.text.size ) != 0 ) { method, url.pathquery.buff, url.pathquery.size,
"HOST: ", url.hostport.text.buff, url.hostport.text.size ) != 0 ) {
goto error_handler; goto error_handler;
} }
} }
@ -2048,9 +2078,10 @@ http_MakeMessage( INOUT membuffer * buf,
// content type header // content type header
temp_str = ( const char * )va_arg( argp, const char * ); // type/subtype format temp_str = ( const char * )va_arg( argp, const char * ); // type/subtype format
if( http_MakeMessage if (http_MakeMessage(
( buf, http_major_version, http_minor_version, "ssc", buf, http_major_version, http_minor_version,
"CONTENT-TYPE: ", temp_str ) != 0 ) { "ssc",
"CONTENT-TYPE: ", temp_str ) != 0 ) {
goto error_handler; goto error_handler;
} }
} }
@ -2174,16 +2205,13 @@ MakeGetMessageEx( const char *url_str,
hostlen ); hostlen );
) )
errCode = http_MakeMessage( request, errCode = http_MakeMessage(
1, request, 1, 1,
1, "QsbcGDCUc",
"QsbcGDCUc", HTTPMETHOD_GET,
HTTPMETHOD_GET, url->pathquery.buff, url->pathquery.size,
url->pathquery.buff, "HOST: ", hoststr, hostlen,
url->pathquery.size, pRangeSpecifier );
"HOST: ",
hoststr,
hostlen, pRangeSpecifier );
if( errCode != 0 ) { if( errCode != 0 ) {
DBGONLY( UpnpPrintf( UPNP_INFO, HTTP, __FILE__, __LINE__, DBGONLY( UpnpPrintf( UPNP_INFO, HTTP, __FILE__, __LINE__,

View File

@ -632,7 +632,7 @@ get_file_info( IN const char *filename,
rc = get_content_type( filename, &info->content_type ); rc = get_content_type( filename, &info->content_type );
DBGONLY( UpnpPrintf( UPNP_INFO, HTTP, __FILE__, __LINE__, DBGONLY( UpnpPrintf( UPNP_INFO, HTTP, __FILE__, __LINE__,
"file info: %s, length: %d, last_mod=%s readable=%d\n", "file info: %s, length: %lld, last_mod=%s readable=%d\n",
filename, info->file_length, filename, info->file_length,
asctime( gmtime( &info->last_modified ) ), asctime( gmtime( &info->last_modified ) ),
info->is_readable ); ) info->is_readable ); )
@ -871,8 +871,8 @@ StrTok( char **Src,
************************************************************************/ ************************************************************************/
int int
GetNextRange( char **SrcRangeStr, GetNextRange( char **SrcRangeStr,
int *FirstByte, off_t *FirstByte,
int *LastByte ) off_t *LastByte )
{ {
char *Ptr, char *Ptr,
*Tok; *Tok;
@ -936,11 +936,11 @@ GetNextRange( char **SrcRangeStr,
************************************************************************/ ************************************************************************/
int int
CreateHTTPRangeResponseHeader( char *ByteRangeSpecifier, CreateHTTPRangeResponseHeader( char *ByteRangeSpecifier,
long FileLength, off_t FileLength,
OUT struct SendInstruction *Instr ) OUT struct SendInstruction *Instr )
{ {
int FirstByte, off_t FirstByte,
LastByte; LastByte;
char *RangeInput, char *RangeInput,
*Ptr; *Ptr;
@ -984,26 +984,26 @@ CreateHTTPRangeResponseHeader( char *ByteRangeSpecifier,
Instr->RangeOffset = FirstByte; Instr->RangeOffset = FirstByte;
Instr->ReadSendSize = LastByte - FirstByte + 1; Instr->ReadSendSize = LastByte - FirstByte + 1;
sprintf( Instr->RangeHeader, "CONTENT-RANGE: bytes %d-%d/%ld\r\n", FirstByte, LastByte, FileLength ); //Data between two range. sprintf( Instr->RangeHeader, "CONTENT-RANGE: bytes %lld-%lld/%lld\r\n", FirstByte, LastByte, FileLength ); //Data between two range.
} else if( FirstByte >= 0 && LastByte == -1 } else if( FirstByte >= 0 && LastByte == -1
&& FirstByte < FileLength ) { && FirstByte < FileLength ) {
Instr->RangeOffset = FirstByte; Instr->RangeOffset = FirstByte;
Instr->ReadSendSize = FileLength - FirstByte; Instr->ReadSendSize = FileLength - FirstByte;
sprintf( Instr->RangeHeader, sprintf( Instr->RangeHeader,
"CONTENT-RANGE: bytes %d-%ld/%ld\r\n", FirstByte, "CONTENT-RANGE: bytes %lld-%lld/%lld\r\n", FirstByte,
FileLength - 1, FileLength ); FileLength - 1, FileLength );
} else if( FirstByte == -1 && LastByte > 0 ) { } else if( FirstByte == -1 && LastByte > 0 ) {
if( LastByte >= FileLength ) { if( LastByte >= FileLength ) {
Instr->RangeOffset = 0; Instr->RangeOffset = 0;
Instr->ReadSendSize = FileLength; Instr->ReadSendSize = FileLength;
sprintf( Instr->RangeHeader, sprintf( Instr->RangeHeader,
"CONTENT-RANGE: bytes 0-%ld/%ld\r\n", "CONTENT-RANGE: bytes 0-%lld/%lld\r\n",
FileLength - 1, FileLength ); FileLength - 1, FileLength );
} else { } else {
Instr->RangeOffset = FileLength - LastByte; Instr->RangeOffset = FileLength - LastByte;
Instr->ReadSendSize = LastByte; Instr->ReadSendSize = LastByte;
sprintf( Instr->RangeHeader, sprintf( Instr->RangeHeader,
"CONTENT-RANGE: bytes %ld-%ld/%ld\r\n", "CONTENT-RANGE: bytes %lld-%lld/%lld\r\n",
FileLength - LastByte + 1, FileLength, FileLength - LastByte + 1, FileLength,
FileLength ); FileLength );
} }
@ -1042,7 +1042,7 @@ CreateHTTPRangeResponseHeader( char *ByteRangeSpecifier,
int int
CheckOtherHTTPHeaders( IN http_message_t * Req, CheckOtherHTTPHeaders( IN http_message_t * Req,
OUT struct SendInstruction *RespInstr, OUT struct SendInstruction *RespInstr,
int FileSize ) off_t FileSize )
{ {
http_header_t *header; http_header_t *header;
ListNode *node; ListNode *node;
@ -1184,7 +1184,6 @@ process_request( IN http_message_t * req,
int code; int code;
int err_code; int err_code;
//membuffer content_type;
char *request_doc; char *request_doc;
struct File_Info finfo; struct File_Info finfo;
xboolean using_alias; xboolean using_alias;
@ -1208,7 +1207,6 @@ process_request( IN http_message_t * req,
// init // init
request_doc = NULL; request_doc = NULL;
finfo.content_type = NULL; finfo.content_type = NULL;
//membuffer_init( &content_type );
alias_grabbed = FALSE; alias_grabbed = FALSE;
err_code = HTTP_INTERNAL_SERVER_ERROR; // default error err_code = HTTP_INTERNAL_SERVER_ERROR; // default error
using_virtual_dir = FALSE; using_virtual_dir = FALSE;
@ -1362,7 +1360,7 @@ process_request( IN http_message_t * req,
RespInstr->ReadSendSize = finfo.file_length; RespInstr->ReadSendSize = finfo.file_length;
//Check other header field. // Check other header field.
if( ( err_code = if( ( err_code =
CheckOtherHTTPHeaders( req, RespInstr, CheckOtherHTTPHeaders( req, RespInstr,
finfo.file_length ) ) != HTTP_OK ) { finfo.file_length ) ) != HTTP_OK ) {
@ -1376,85 +1374,80 @@ process_request( IN http_message_t * req,
} }
if( RespInstr->IsRangeActive && RespInstr->IsChunkActive ) { if( RespInstr->IsRangeActive && RespInstr->IsChunkActive ) {
// Content-Range: bytes 222-3333/4000 HTTP_PARTIAL_CONTENT
/* - PATCH START - Sergey 'Jin' Bostandzhyan <jin_eld at users.sourceforge.net> // Transfer-Encoding: chunked
* added X-User-Agent header if (http_MakeMessage(
*/ headers, resp_major, resp_minor,
"R" "T" "GKD" "s" "tcS" "XcCc",
//Content-Range: bytes 222-3333/4000 HTTP_PARTIAL_CONTENT HTTP_PARTIAL_CONTENT, // status code
//Transfer-Encoding: chunked finfo.content_type, // content type
// K means add chunky header ang G means range header. RespInstr, // range info
if( http_MakeMessage( headers, resp_major, resp_minor, "RTGKDstcSXcCc", HTTP_PARTIAL_CONTENT, // status code "LAST-MODIFIED: ",
// RespInstr->ReadSendSize,// content length &finfo.last_modified,
finfo.content_type, X_USER_AGENT) != 0 ) {
// content_type.buf, // content type
RespInstr, // Range
"LAST-MODIFIED: ",
&finfo.last_modified,
X_USER_AGENT) != 0 ) {
goto error_handler; goto error_handler;
} }
} else if( RespInstr->IsRangeActive && !RespInstr->IsChunkActive ) { } else if( RespInstr->IsRangeActive && !RespInstr->IsChunkActive ) {
//Content-Range: bytes 222-3333/4000 HTTP_PARTIAL_CONTENT // Content-Range: bytes 222-3333/4000 HTTP_PARTIAL_CONTENT
//Transfer-Encoding: chunked // Transfer-Encoding: chunked
// K means add chunky header ang G means range header. if (http_MakeMessage(
if( http_MakeMessage( headers, resp_major, resp_minor, "RNTGDstcSXcCc", HTTP_PARTIAL_CONTENT, // status code headers, resp_major, resp_minor,
RespInstr->ReadSendSize, // content length "R" "N" "T" "GD" "s" "tcS" "XcCc",
finfo.content_type, HTTP_PARTIAL_CONTENT, // status code
//content_type.buf, // content type RespInstr->ReadSendSize, // content length
RespInstr, //Range Info finfo.content_type, // content type
"LAST-MODIFIED: ", RespInstr, // range info
&finfo.last_modified, "LAST-MODIFIED: ",
X_USER_AGENT) != 0 ) { &finfo.last_modified,
X_USER_AGENT) != 0 ) {
goto error_handler; goto error_handler;
} }
} else if( !RespInstr->IsRangeActive && RespInstr->IsChunkActive ) { } else if( !RespInstr->IsRangeActive && RespInstr->IsChunkActive ) {
// Content-Range: bytes 222-3333/4000 HTTP_PARTIAL_CONTENT
//Content-Range: bytes 222-3333/4000 HTTP_PARTIAL_CONTENT // Transfer-Encoding: chunked
//Transfer-Encoding: chunked if (http_MakeMessage(
// K means add chunky header ang G means range header. headers, resp_major, resp_minor,
if( http_MakeMessage( headers, resp_major, resp_minor, "RKTDstcSXcCc", HTTP_OK, // status code "RK" "TD" "s" "tcS" "XcCc",
//RespInstr->ReadSendSize,// content length HTTP_OK, // status code
finfo.content_type, finfo.content_type, // content type
// content_type.buf, // content type "LAST-MODIFIED: ",
"LAST-MODIFIED: ", &finfo.last_modified,
&finfo.last_modified, X_USER_AGENT) != 0 ) {
X_USER_AGENT) != 0 ) {
goto error_handler; goto error_handler;
} }
} else { } else { // !RespInstr->IsRangeActive && !RespInstr->IsChunkActive
if( RespInstr->ReadSendSize >= 0 ) { if (RespInstr->ReadSendSize >= 0) {
//Content-Range: bytes 222-3333/4000 HTTP_PARTIAL_CONTENT // Content-Range: bytes 222-3333/4000 HTTP_PARTIAL_CONTENT
//Transfer-Encoding: chunked // Transfer-Encoding: chunked
// K means add chunky header ang G means range header. if (http_MakeMessage(
if( http_MakeMessage( headers, resp_major, resp_minor, "RNTDstcSXcCc", HTTP_OK, // status code headers, resp_major, resp_minor,
RespInstr->ReadSendSize, // content length "R" "N" "TD" "s" "tcS" "XcCc",
finfo.content_type, HTTP_OK, // status code
//content_type.buf, // content type RespInstr->ReadSendSize, // content length
"LAST-MODIFIED: ", finfo.content_type, // content type
&finfo.last_modified, "LAST-MODIFIED: ",
X_USER_AGENT) != 0 ) { &finfo.last_modified,
X_USER_AGENT) != 0 ) {
goto error_handler; goto error_handler;
} }
} else { } else {
//Content-Range: bytes 222-3333/4000 HTTP_PARTIAL_CONTENT // Content-Range: bytes 222-3333/4000 HTTP_PARTIAL_CONTENT
//Transfer-Encoding: chunked // Transfer-Encoding: chunked
// K means add chunky header ang G means range header. if (http_MakeMessage(
if( http_MakeMessage( headers, resp_major, resp_minor, "RTDstcSXcCc", HTTP_OK, // status code headers, resp_major, resp_minor,
//RespInstr->ReadSendSize,// content length "R" "TD" "s" "tcS" "XcCc",
finfo.content_type, HTTP_OK, // status code
//content_type.buf, // content type finfo.content_type, // content type
"LAST-MODIFIED: ", "LAST-MODIFIED: ",
&finfo.last_modified, &finfo.last_modified,
X_USER_AGENT) != 0 ) { X_USER_AGENT) != 0 ) {
goto error_handler; goto error_handler;
} }
} }
} }
/* -- PATCH END -- */
if( req->method == HTTPMETHOD_HEAD ) { if( req->method == HTTPMETHOD_HEAD ) {
*rtype = RESP_HEADERS; *rtype = RESP_HEADERS;
@ -1468,8 +1461,8 @@ process_request( IN http_message_t * req,
*rtype = RESP_FILEDOC; *rtype = RESP_FILEDOC;
} }
//simple get http 0.9 as specified in http 1.0 // simple get http 0.9 as specified in http 1.0
//don't send headers // don't send headers
if( req->method == HTTPMETHOD_SIMPLEGET ) { if( req->method == HTTPMETHOD_SIMPLEGET ) {
membuffer_destroy( headers ); membuffer_destroy( headers );
} }
@ -1479,7 +1472,6 @@ process_request( IN http_message_t * req,
error_handler: error_handler:
free( request_doc ); free( request_doc );
ixmlFreeDOMString( finfo.content_type ); ixmlFreeDOMString( finfo.content_type );
// membuffer_destroy( &content_type );
if( err_code != UPNP_E_SUCCESS && alias_grabbed ) { if( err_code != UPNP_E_SUCCESS && alias_grabbed ) {
alias_release( alias ); alias_release( alias );
} }
@ -1738,12 +1730,12 @@ web_server_callback( IN http_parser_t * parser,
&RespInstr ); &RespInstr );
//Send response. //Send response.
/* - PATCH START - Sergey 'Jin' Bostandzhyan <jin_eld at users.sourceforge.net> http_MakeMessage(
* added X-User-Agent header &headers, 1, 1,
*/ "RTDSXcCc",
http_MakeMessage( &headers, 1, 1, "RTDSXcCc", ret, ret,
"text/html", X_USER_AGENT ); "text/html",
/* - PATCH END --- */ X_USER_AGENT );
http_SendMessage( info, &timeout, "b", headers.buf, http_SendMessage( info, &timeout, "b", headers.buf,
headers.length ); headers.length );

View File

@ -95,6 +95,17 @@
#define MAX_THREADS 12 #define MAX_THREADS 12
//@} //@}
/** @name MAX_JOBS_TOTAL
* The {\tt MAX_JOBS_TOTAL} constant determines the maximum number of jobs
* that can be queued. If this limit is reached further jobs will be thrown
* to avoid memory exhaustion. The default value 100.
* (Added by Axis.)
*/
//@{
#define MAX_JOBS_TOTAL 100
//@}
/** @name DEFAULT_SOAP_CONTENT_LENGTH /** @name DEFAULT_SOAP_CONTENT_LENGTH
* SOAP messages will read at most {\tt DEFAULT_SOAP_CONTENT_LENGTH} bytes. * SOAP messages will read at most {\tt DEFAULT_SOAP_CONTENT_LENGTH} bytes.
* This prevents devices that have a misbehaving web server to send * This prevents devices that have a misbehaving web server to send

View File

@ -475,6 +475,7 @@ int http_SendStatusResponse( IN SOCKINFO *info, IN int http_status_code,
* memory ptr * memory ptr
* 'c': (no args) appends CRLF "\r\n" * 'c': (no args) appends CRLF "\r\n"
* 'd': arg = int number // appends decimal number * 'd': arg = int number // appends decimal number
* 'h': arg = off_t number // appends off_t number
* 't': arg = time_t * gmt_time // appends time in RFC 1123 fmt * 't': arg = time_t * gmt_time // appends time in RFC 1123 fmt
* 'D': (no args) appends HTTP DATE: header * 'D': (no args) appends HTTP DATE: header
* 'S': (no args) appends HTTP SERVER: header * 'S': (no args) appends HTTP SERVER: header

View File

@ -80,7 +80,7 @@ typedef enum SsdpCmdType{SSDP_ERROR=-1,
#define SSDP_IP "239.255.255.250" #define SSDP_IP "239.255.255.250"
#define SSDP_PORT 1900 #define SSDP_PORT 1900
#define NUM_TRY 3 #define NUM_TRY 3
#define NUM_COPY 2 #define NUM_COPY 1
#define THREAD_LIMIT 50 #define THREAD_LIMIT 50
#define COMMAND_LEN 300 #define COMMAND_LEN 300

View File

@ -48,8 +48,8 @@ struct SendInstruction
int IsRangeActive; int IsRangeActive;
int IsTrailers; int IsTrailers;
char RangeHeader[200]; char RangeHeader[200];
long RangeOffset; off_t RangeOffset;
long ReadSendSize; // Read from local source and send on the network. off_t ReadSendSize; // Read from local source and send on the network.
long RecvWriteSize; // Recv from the network and write into local file. long RecvWriteSize; // Recv from the network and write into local file.
//Later few more member could be added depending on the requirement. //Later few more member could be added depending on the requirement.

View File

@ -602,12 +602,15 @@ SoapSendAction( IN char *action_url,
char *upnp_error_str; char *upnp_error_str;
xboolean got_response = FALSE; xboolean got_response = FALSE;
off_t content_length;
char *xml_start = char *xml_start =
// "<?xml version=\"1.0\"?>\n" required?? "<s:Envelope "
"<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" " "xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" "
"s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n" "s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\r\n"
"<s:Body>"; "<s:Body>";
char *xml_end = "</s:Body>\n" "</s:Envelope>\n"; char *xml_end =
"</s:Body>\r\n"
"</s:Envelope>\r\n\r\n";
int xml_start_len; int xml_start_len;
int xml_end_len; int xml_end_len;
int action_str_len; int action_str_len;
@ -645,18 +648,23 @@ SoapSendAction( IN char *action_url,
url.hostport.text.size, url.hostport.text.size,
url.hostport.text.buff ); ) url.hostport.text.buff ); )
xml_start_len = strlen( xml_start ); xml_start_len = strlen( xml_start );
xml_end_len = strlen( xml_end ); xml_end_len = strlen( xml_end );
action_str_len = strlen( action_str ); action_str_len = strlen( action_str );
// make request msg // make request msg
request.size_inc = 50; request.size_inc = 50;
if( http_MakeMessage( &request, 1, 1, "q" "N" "s" "sssbs" "U" "c" "bbb", SOAPMETHOD_POST, &url, xml_start_len + action_str_len + xml_end_len, // content-length content_length = xml_start_len + action_str_len + xml_end_len;
ContentTypeHeader, if (http_MakeMessage(
"SOAPACTION: \"", service_type, "#", name.buf, &request, 1, 1,
name.length, "\"\r\n", xml_start, xml_start_len, "q" "N" "s" "sssbsc" "Uc" "b" "b" "b",
action_str, action_str_len, xml_end, SOAPMETHOD_POST, &url,
xml_end_len ) != 0 ) { content_length,
ContentTypeHeader,
"SOAPACTION: \"", service_type, "#", name.buf, name.length, "\"",
xml_start, xml_start_len,
action_str, action_str_len,
xml_end, xml_end_len ) != 0 ) {
goto error_handler; goto error_handler;
} }
@ -737,20 +745,26 @@ SoapSendActionEx( IN char *action_url,
xboolean got_response = FALSE; xboolean got_response = FALSE;
char *xml_start = char *xml_start =
// "<?xml version=\"1.0\"?>\n" required?? "<s:Envelope "
"<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" " "xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" "
"s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n"; "s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\r\n";
char *xml_body_start = "<s:Body>"; char *xml_header_start =
char *xml_end = "</s:Body>\n" "</s:Envelope>\n"; "<s:Header>\r\n";
char *xml_header_end =
"</s:Header>\r\n";
char *xml_body_start =
"<s:Body>";
char *xml_end =
"</s:Body>\r\n"
"</s:Envelope>\r\n";
int xml_start_len; int xml_start_len;
int xml_end_len;
char *xml_header_start = "<s:Header>\n";
char *xml_header_end = "</s:Header>\n";
int xml_header_start_len; int xml_header_start_len;
int xml_header_end_len;
int xml_header_str_len; int xml_header_str_len;
int action_str_len; int xml_header_end_len;
int xml_body_start_len; int xml_body_start_len;
int action_str_len;
int xml_end_len;
off_t content_length;
*response_node = NULL; // init *response_node = NULL; // init
@ -790,7 +804,7 @@ SoapSendActionEx( IN char *action_url,
url.hostport.text.size, url.hostport.text.size,
url.hostport.text.buff ); ) url.hostport.text.buff ); )
xml_start_len = strlen( xml_start ); xml_start_len = strlen( xml_start );
xml_body_start_len = strlen( xml_body_start ); xml_body_start_len = strlen( xml_body_start );
xml_end_len = strlen( xml_end ); xml_end_len = strlen( xml_end );
action_str_len = strlen( action_str ); action_str_len = strlen( action_str );
@ -801,17 +815,24 @@ SoapSendActionEx( IN char *action_url,
// make request msg // make request msg
request.size_inc = 50; request.size_inc = 50;
if( http_MakeMessage( &request, 1, 1, "q" "N" "s" "sssbs" "U" "c" "bbbbbbb", SOAPMETHOD_POST, &url, xml_start_len + xml_header_start_len + xml_header_str_len + xml_header_end_len + xml_body_start_len + action_str_len + xml_end_len, // content-length content_length =
ContentTypeHeader, xml_start_len +
"SOAPACTION: \"", service_type, "#", name.buf, xml_header_start_len + xml_header_str_len + xml_header_end_len +
name.length, "\"\r\n", xml_body_start_len + action_str_len + xml_end_len;
xml_start, xml_start_len, if (http_MakeMessage(
xml_header_start, xml_header_start_len, &request, 1, 1,
xml_header_str, xml_header_str_len, "q" "N" "s" "sssbsc" "Uc" "bbbbbbb",
xml_header_end, xml_header_end_len, SOAPMETHOD_POST, &url,
xml_body_start, xml_body_start_len, content_length,
action_str, action_str_len, ContentTypeHeader,
xml_end, xml_end_len ) != 0 ) { "SOAPACTION: \"", service_type, "#", name.buf, name.length, "\"",
xml_start, xml_start_len,
xml_header_start, xml_header_start_len,
xml_header_str, xml_header_str_len,
xml_header_end, xml_header_end_len,
xml_body_start, xml_body_start_len,
action_str, action_str_len,
xml_end, xml_end_len ) != 0 ) {
goto error_handler; goto error_handler;
} }
@ -882,16 +903,20 @@ SoapGetServiceVarStatus( IN char *action_url,
http_parser_t response; http_parser_t response;
int upnp_error_code; int upnp_error_code;
off_t content_length;
char *xml_start = char *xml_start =
// "<?xml version=\"1.0\"?>\n" required?? "<s:Envelope "
"<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" " "xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" "
"s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n" "s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\r\n"
"<s:Body>\n" "<s:Body>\r\n"
"<u:QueryStateVariable xmlns:u=\"urn:schemas-upnp-org:control-1-0\">\n" "<u:QueryStateVariable xmlns:u=\"urn:schemas-upnp-org:control-1-0\">\r\n"
"<u:varName>"; "<u:varName>";
char *xml_end = "</u:varName>\n" char *xml_end =
"</u:QueryStateVariable>\n" "</s:Body>\n" "</s:Envelope>\n"; "</u:varName>\r\n"
"</u:QueryStateVariable>\r\n"
"</s:Body>\r\n"
"</s:Envelope>\r\n";
*var_value = NULL; // return NULL in case of an error *var_value = NULL; // return NULL in case of an error
@ -903,11 +928,16 @@ SoapGetServiceVarStatus( IN char *action_url,
} }
// make headers // make headers
request.size_inc = 50; request.size_inc = 50;
if( http_MakeMessage( &request, 1, 1, "Q" "sbc" "N" "s" "s" "U" "c" "sss", SOAPMETHOD_POST, path.buf, path.length, "HOST: ", host.buf, host.length, strlen( xml_start ) + strlen( var_name ) + strlen( xml_end ), // content-length content_length = strlen( xml_start ) + strlen( var_name ) + strlen( xml_end );
ContentTypeHeader, if (http_MakeMessage(
"SOAPACTION: \"urn:schemas" &request, 1, 1,
"-upnp-org:control-1-0#QueryStateVariable\"\r\n", "Q" "sbc" "N" "s" "s" "Ucc" "sss",
xml_start, var_name, xml_end ) != 0 ) { SOAPMETHOD_POST, path.buf, path.length,
"HOST: ", host.buf, host.length,
content_length,
ContentTypeHeader,
"SOAPACTION: \"urn:schemas-upnp-org:control-1-0#QueryStateVariable\"",
xml_start, var_name, xml_end ) != 0 ) {
return UPNP_E_OUTOF_MEMORY; return UPNP_E_OUTOF_MEMORY;
} }
// send msg and get reply // send msg and get reply

View File

@ -189,7 +189,7 @@ send_error_response( IN SOCKINFO * info,
IN const char *err_msg, IN const char *err_msg,
IN http_message_t * hmsg ) IN http_message_t * hmsg )
{ {
int content_length; off_t content_length;
int timeout_secs = SOAP_TIMEOUT; int timeout_secs = SOAP_TIMEOUT;
int major, int major,
minor; minor;
@ -228,20 +228,19 @@ send_error_response( IN SOCKINFO * info,
// make headers // make headers
membuffer_init( &headers ); membuffer_init( &headers );
/* -- PATCH START - Sergey 'Jin' Bostandzhyan <jin_eld at users.sourceforge.net> */ if (http_MakeMessage(
if( http_MakeMessage( &headers, major, minor, &headers, major, minor,
"RNsDsSXc" "sssss", "RNsDsSXcc" "sssss",
500, 500,
content_length, content_length,
ContentTypeHeader, ContentTypeHeader,
"EXT:\r\n", "EXT:\r\n",
X_USER_AGENT, X_USER_AGENT,
start_body, err_code_str, mid_body, err_msg, start_body, err_code_str, mid_body, err_msg,
end_body ) != 0 ) { end_body ) != 0 ) {
membuffer_destroy( &headers ); membuffer_destroy( &headers );
return; // out of mem return; // out of mem
} }
/*-- PATCH END - */
// send err msg // send err msg
http_SendMessage( info, &timeout_secs, "b", http_SendMessage( info, &timeout_secs, "b",
headers.buf, headers.length ); headers.buf, headers.length );
@ -268,12 +267,11 @@ send_var_query_response( IN SOCKINFO * info,
IN const char *var_value, IN const char *var_value,
IN http_message_t * hmsg ) IN http_message_t * hmsg )
{ {
int content_length; off_t content_length;
int timeout_secs = SOAP_TIMEOUT; int timeout_secs = SOAP_TIMEOUT;
int major, int major;
minor; int minor;
const char *start_body = const char *start_body =
// "<?xml version=\"1.0\"?>\n" required??
"<s:Envelope " "<s:Envelope "
"xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" " "xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" "
"s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n" "s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n"
@ -297,19 +295,18 @@ send_var_query_response( IN SOCKINFO * info,
// make headers // make headers
membuffer_init( &response ); membuffer_init( &response );
/* -- PATCH START - Sergey 'Jin' Bostandzhyan <jin_eld at users.sourceforge.net> */ if (http_MakeMessage(
if( http_MakeMessage( &response, major, minor, &response, major, minor,
"RNsDsSXcc" "sss", "RNsDsSXcc" "sss",
HTTP_OK, HTTP_OK,
content_length, content_length,
ContentTypeHeader, ContentTypeHeader,
"EXT:\r\n", "EXT:\r\n",
X_USER_AGENT, X_USER_AGENT,
start_body, var_value, end_body ) != 0 ) { start_body, var_value, end_body ) != 0 ) {
membuffer_destroy( &response ); membuffer_destroy( &response );
return; // out of mem return; // out of mem
} }
/* -- PATCH END - */
// send msg // send msg
http_SendMessage( info, &timeout_secs, "b", http_SendMessage( info, &timeout_secs, "b",
@ -695,7 +692,7 @@ send_action_response( IN SOCKINFO * info,
int major, int major,
minor; minor;
int err_code; int err_code;
int content_length; off_t content_length;
int ret_code; int ret_code;
int timeout_secs = SOAP_TIMEOUT; int timeout_secs = SOAP_TIMEOUT;
static char *start_body = static char *start_body =
@ -717,17 +714,22 @@ send_action_response( IN SOCKINFO * info,
goto error_handler; goto error_handler;
} }
content_length = strlen( start_body ) + strlen( xml_response ) + content_length =
strlen( start_body ) +
strlen( xml_response ) +
strlen( end_body ); strlen( end_body );
// make headers // make headers
/* -- PATCH START - Sergey 'Jin' Bostandzhyan <jin_eld at users.sourceforge.net> */ if (http_MakeMessage(
if( http_MakeMessage( &headers, major, minor, "RNsDsSXcc", HTTP_OK, // status code &headers, major, minor,
content_length, ContentTypeHeader, "EXT:\r\n", X_USER_AGENT // EXT header "RNsDsSXcc",
) != 0 ) { HTTP_OK, // status code
content_length,
ContentTypeHeader,
"EXT:\r\n",
X_USER_AGENT) != 0 ) {
goto error_handler; goto error_handler;
} }
/* -- PATCH END - */
// send whole msg // send whole msg
ret_code = http_SendMessage( info, &timeout_secs, "bbbb", ret_code = http_SendMessage( info, &timeout_secs, "bbbb",

View File

@ -234,7 +234,17 @@ NewRequestHandler( IN struct sockaddr_in *DestAddr,
for( Index = 0; Index < NumPacket; Index++ ) { for( Index = 0; Index < NumPacket; Index++ ) {
int rc; int rc;
// The reason to keep this loop is purely historical/documentation,
// according to section 9.2 of HTTPU spec:
//
// "If a multicast resource would send a response(s) to any copy of the
// request, it SHOULD send its response(s) to each copy of the request
// it receives. It MUST NOT repeat its response(s) per copy of the
// reuqest."
//
// http://www.upnp.org/download/draft-goland-http-udp-04.txt
//
// So, NUM_COPY has been changed from 2 to 1.
NumCopy = 0; NumCopy = 0;
while( NumCopy < NUM_COPY ) { while( NumCopy < NUM_COPY ) {
DBGONLY( UpnpPrintf( UPNP_INFO, SSDP, __FILE__, __LINE__, DBGONLY( UpnpPrintf( UPNP_INFO, SSDP, __FILE__, __LINE__,
@ -295,16 +305,16 @@ CreateServicePacket( IN int msg_type,
*packet = NULL; *packet = NULL;
if( msg_type == MSGTYPE_REPLY ) { if( msg_type == MSGTYPE_REPLY ) {
/* -- PATCH START - Sergey 'Jin' Bostandzhyan <jin_eld at users.sourceforge.net> */ ret_code = http_MakeMessage(
ret_code = http_MakeMessage( &buf, 1, 1, &buf, 1, 1,
"R" "sdc" "D" "s" "ssc" "S" "Xc" "ssc" "R" "sdc" "D" "sc" "ssc" "S" "Xc" "ssc" "sscc",
"ssc" "c", HTTP_OK, HTTP_OK,
"CACHE-CONTROL: max-age=", duration, "CACHE-CONTROL: max-age=", duration,
"EXT:\r\n", "LOCATION: ", location, "EXT:",
X_USER_AGENT, "LOCATION: ", location,
"ST: ", nt, "USN: ", usn ); X_USER_AGENT,
/* -- PATCH END - */ "ST: ", nt,
"USN: ", usn);
if( ret_code != 0 ) { if( ret_code != 0 ) {
return; return;
} }
@ -320,15 +330,17 @@ CreateServicePacket( IN int msg_type,
// NOTE: The CACHE-CONTROL and LOCATION headers are not present in // NOTE: The CACHE-CONTROL and LOCATION headers are not present in
// a shutdown msg, but are present here for MS WinMe interop. // a shutdown msg, but are present here for MS WinMe interop.
/* -- PATCH START - Sergey 'Jin' Bostandzhyan <jin_eld at users.sourceforge.net> */ ret_code = http_MakeMessage(
ret_code = http_MakeMessage( &buf, 1, 1, &buf, 1, 1,
"Q" "sssdc" "sdc" "ssc" "ssc" "ssc" "Q" "sssdc" "sdc" "ssc" "ssc" "ssc" "S" "Xc" "sscc",
"S" "Xc" "ssc" "c", HTTPMETHOD_NOTIFY, "*", HTTPMETHOD_NOTIFY, "*",
1, "HOST: ", SSDP_IP, ":", SSDP_PORT, 1, "HOST: ", SSDP_IP, ":", SSDP_PORT,
"CACHE-CONTROL: max-age=", duration, "CACHE-CONTROL: max-age=", duration,
"LOCATION: ", location, "NT: ", nt, "LOCATION: ", location,
"NTS: ", nts, X_USER_AGENT, "USN: ", usn ); "NT: ", nt,
/* -- PATCH END - */ "NTS: ", nts,
X_USER_AGENT,
"USN: ", usn );
if( ret_code != 0 ) { if( ret_code != 0 ) {
return; return;
} }

View File

@ -922,6 +922,7 @@ get_ssdp_sockets( MiniServerSockArray * out )
struct ip_mreq ssdpMcastAddr; struct ip_mreq ssdpMcastAddr;
struct sockaddr_in ssdpAddr; struct sockaddr_in ssdpAddr;
int option = 1; int option = 1;
struct in_addr addr;
CLIENTONLY( if( ( ssdpReqSock = socket( AF_INET, SOCK_DGRAM, 0 ) ) CLIENTONLY( if( ( ssdpReqSock = socket( AF_INET, SOCK_DGRAM, 0 ) )
== UPNP_INVALID_SOCKET ) { == UPNP_INVALID_SOCKET ) {
@ -997,7 +998,7 @@ get_ssdp_sockets( MiniServerSockArray * out )
} }
memset( ( void * )&ssdpMcastAddr, 0, sizeof( struct ip_mreq ) ); memset( ( void * )&ssdpMcastAddr, 0, sizeof( struct ip_mreq ) );
ssdpMcastAddr.imr_interface.s_addr = htonl( INADDR_ANY ); ssdpMcastAddr.imr_interface.s_addr = inet_addr( LOCAL_HOST );
ssdpMcastAddr.imr_multiaddr.s_addr = inet_addr( SSDP_IP ); ssdpMcastAddr.imr_multiaddr.s_addr = inet_addr( SSDP_IP );
if( setsockopt( ssdpSock, IPPROTO_IP, IP_ADD_MEMBERSHIP, if( setsockopt( ssdpSock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
( char * )&ssdpMcastAddr, ( char * )&ssdpMcastAddr,
@ -1012,6 +1013,17 @@ get_ssdp_sockets( MiniServerSockArray * out )
CLIENTONLY( UpnpCloseSocket( ssdpReqSock ) ); CLIENTONLY( UpnpCloseSocket( ssdpReqSock ) );
return UPNP_E_SOCKET_ERROR; return UPNP_E_SOCKET_ERROR;
} }
/* Set multicast interface. */
memset( ( void * )&addr, 0, sizeof( struct in_addr ));
addr.s_addr = inet_addr(LOCAL_HOST);
if (setsockopt(ssdpSock, IPPROTO_IP, IP_MULTICAST_IF,
(char *)&addr, sizeof addr) != 0) {
DBGONLY(UpnpPrintf( UPNP_INFO, SSDP, __FILE__, __LINE__,
"Couldn't set multicast interface.\n" ));
/* This is probably not a critical error, so let's continue. */
}
// result is not checked becuase it will fail in WinMe and Win9x. // result is not checked becuase it will fail in WinMe and Win9x.
setsockopt( ssdpSock, IPPROTO_IP, setsockopt( ssdpSock, IPPROTO_IP,
IP_MULTICAST_TTL, &ttl, sizeof( ttl ) ); IP_MULTICAST_TTL, &ttl, sizeof( ttl ) );