Compare commits

..

61 Commits

Author SHA1 Message Date
Marcelo Roberto Jimenez
79aa205657 Adjust the library numbers for release. 2010-12-11 16:35:29 -02:00
Marcelo Roberto Jimenez
9a28fcc95b Fixes a bug introduced in a previous commit in http_SendMessage.
The variable num_read was beeing used without beeing initialized.

Also, clean up the function return path and make sure va_end()
is beeing called.
2010-11-24 11:26:00 -02:00
Marcelo Roberto Jimenez
bfbd07cb40 Reformat calls to http_SendMessage(). 2010-11-24 11:12:33 -02:00
Marcelo Roberto Jimenez
255d5ee874 soap_device: Doxygen and code reformat. 2010-11-24 11:10:18 -02:00
Fabrice Fontaine
2c3bce13bd Major bug fix in http_SendMessage.
Currently, http_SendMessage was not able to write to write a buffer
due to a bad use of file_buf instead of buf. This bug was introduced by
the 0197-Doxygen-reformating-compiler-warnings patch.
2010-11-24 08:21:41 -02:00
Fabrice Fontaine
bda942b22a Returning the SID in Upnp_Event_Subscribe.
Currently, Upnp_Event_Subscribe always contains an empty chain in the
Sid parameter. This patch now saves the client Subscription ID in this
parameter so Control Points can see and use the same SID in the
Upnp_Event_Subscribe and in the Upnp_Event structures.
2010-11-24 08:21:33 -02:00
Juergen Lock
ed0ebe1588 Two fixes from Juergen Lock <nox(at)jelal.kn-bremen.de>:
1. varargs:  pass size of CRLF as size_t not as int:

--- upnp/src/gena/gena_device.c.orig
+++ upnp/src/gena/gena_device.c
@@ -225,7 +225,7 @@ static UPNP_INLINE int notify_send_and_r
		"bbb",
		start_msg.buf, start_msg.length,
		propertySet, strlen(propertySet),
-		"\r\n", 2);
+		"\r\n", sizeof "\r\n" - 1);
	if (ret_code) {
		membuffer_destroy(&start_msg);
		sock_destroy(&info, SD_BOTH);

2. Remove "b" arg here, there is no buffer passed:  (this caused a pointer
to be interpreted as a buffer size to be alloc'd/copied, hence the 32 GB.)

--- upnp/src/genlib/net/http/webserver.c.orig
+++ upnp/src/genlib/net/http/webserver.c
@@ -1262,7 +1262,7 @@ static int process_request(
			// Content-Range: bytes 222-3333/4000  HTTP_PARTIAL_CONTENT
			// Transfer-Encoding: chunked
			if (http_MakeMessage(headers, resp_major, resp_minor,
-				"R" "TLD" "s" "tcS" "b" "Xc" "sCc",
+				"R" "TLD" "s" "tcS" "Xc" "sCc",
				HTTP_OK,    // status code
				finfo.content_type, // content type
				RespInstr,  // language info
2010-11-22 23:28:56 -02:00
Marcelo Roberto Jimenez
a39f3a63c3 White spaces. 2010-11-22 13:21:30 -02:00
Marcelo Roberto Jimenez
6e7a2bb2dc Remove the "xboolean" typedef from the code base. 2010-11-22 09:28:17 -02:00
Marcelo Roberto Jimenez
c21a67f2d1 Doxygen, reformating, compiler warnings. 2010-11-21 21:40:07 -02:00
Marcelo Roberto Jimenez
c449fd1521 ssdp, soap, genlib: fix compiler warnings. 2010-11-20 19:08:20 -02:00
Marcelo Roberto Jimenez
594c611a33 gena: fix several compiler warnings. 2010-11-20 13:48:50 -02:00
Marcelo Roberto Jimenez
09f2b6ca30 uuid.c: fix compiler warnings. 2010-11-20 11:30:22 -02:00
Marcelo Roberto Jimenez
9b3a0999a9 upnp: fix for compiler warnings. 2010-11-18 14:57:11 -02:00
Marcelo Roberto Jimenez
d8a27bca96 upnp: fix for compiler warnings and incorrect API. 2010-11-18 14:55:39 -02:00
Marcelo Roberto Jimenez
6bee05a517 samples: One more code reorganization. 2010-11-18 13:59:08 -02:00
Marcelo Roberto Jimenez
2e96edcbc5 samples: fix compiler warnings. 2010-11-18 13:34:04 -02:00
Marcelo Roberto Jimenez
ef0aa38958 samples: More code reorganization. 2010-11-18 12:02:38 -02:00
Marcelo Roberto Jimenez
86159bc2a6 samples: Put more data in common_data.h. 2010-11-18 01:02:27 -02:00
Marcelo Roberto Jimenez
bd8d6cfc8b samples: Unified sample code.
This patch removes duplicated code in samples.
2010-11-18 00:47:45 -02:00
Marcelo Roberto Jimenez
8434e1e936 Update autoconfig.h. 2010-11-17 23:31:07 -02:00
Marcelo Roberto Jimenez
2765bc39c5 Remove "upnp_" prefix from samples. 2010-11-17 23:30:29 -02:00
Marcelo Roberto Jimenez
75695fcaf1 samples: Fix compiler warnings. 2010-11-17 11:54:31 -02:00
Marcelo Roberto Jimenez
5abd1a3b3e Fix some compiler warnings and some Doxygen. 2010-11-17 01:24:38 -02:00
Marcelo Roberto Jimenez
6c31683e29 Some Doxygen in upnp_tv_device.
(cherry picked from commit d5fa48bd37)
2010-11-16 23:22:59 -02:00
Marcelo Roberto Jimenez
d92e26779a Some Doxygen on sample_util.
(cherry picked from commit 0d625bd2e1)
2010-11-16 23:22:51 -02:00
Marcelo Roberto Jimenez
5d6bcabd45 Removes C++ style comments. 2010-11-16 03:14:12 -02:00
Marcelo Roberto Jimenez
7c524df1d9 threadutil: Doxygenation and compiler warnings. 2010-11-16 00:17:44 -02:00
Marcelo Roberto Jimenez
58c694f57d ixml: Fix for compiler warnings for size_t and ptrdiff_t.
ixmlparser.c static functions have been reordered.
2010-11-15 21:29:07 -02:00
Marcelo Roberto Jimenez
da7f3bf1c1 Deal with "inline" when "-ansi" compiler option is active.
This mode can be recognized by the macro __STRICT_ANSI__.

From man gcc:

-ansi
 In C mode, this is equivalent to -std=c89. In C++ mode, it is equivalent to
-std=c++98.

 This turns off certain features of GCC that are incompatible with ISO C90
(when compiling C code), or of standard (when compiling code), such as the
asm and typeof keywords, and predefined macros such as unix and vax that
identify the type of system you are using. It also enables the undesirable
and rarely used ISO trigraph feature. For the C compiler, it disables
recognition of style // comments as well as the inline keyword.

 The alternate keywords _ _asm_ _, _ _extension_ _, _ _inline_ _ and
_ _typeof_ _ continue to work despite -ansi. You would not want to use them
in an ISO C program, of course, but it is useful to put them in header files
that might be included in compilations done with -ansi. Alternate predefined
macros such as _ _unix_ _ and _ _vax_ _ are also available, with or without
-ansi.

 The -ansi option does not cause non-ISO programs to be rejected gratuitously.
For that, -pedantic is required in addition to -ansi.

 The macro _ _STRICT_ANSI_ _ is predefined when the -ansi option is used.
Some header files may notice this macro and refrain from declaring certain
functions or defining certain macros that the ISO standard doesn't call for;
this is to avoid interfering with any programs that might use these names for
other things.

 Functions that would normally be built in but do not have semantics defined
by ISO C (such as alloca and ffs) are not built-in functions when -ansi is
used.
2010-11-15 12:50:38 -02:00
Marcelo Roberto Jimenez
8651174861 Added the convenience function UpnpResolveURL2() to upnptools.c.
This function avoids some unecessary memory allocation.
The memory alloc'd by this function must be freed later by the caller.
2010-11-15 01:01:07 -02:00
Marcelo Roberto Jimenez
2dd19e5894 ReadResponseLineAndHeaders() is static.
(cherry picked from commit eb5db65692)
2010-11-11 22:00:27 -02:00
Fabrice Fontaine
e6c548f57a Add GENA_NOTIFICATION_xxx_TIMEOUT variable.
Currently, in notify_send_and_recv function, pupnp waits for
HTTP_DEFAULT_TIMEOUT seconds when trying to send a GENA notification.
When there is a lot of notifications with CPs which was disconnected
without unsusbcribing, all the pupnp threads are blocked on this
timeout. To correct, this issue, this patch adds a new variable,
GENA_NOTIFICATION_SENDING_TIMEOUT, which can be used to lower the
timeout so GENA threads return quickly when writing is impossible. By
the same mean, pupnp waits the CP's answer to the NOTIFY for
HTTP_DEFAULT_TIMEOUT seconds, so this patch adds a new variable,
GENA_NOTIFICATION_ANSWERING_TIMEOUT, to customize this value.
2010-11-11 21:42:50 -02:00
Fabrice Fontaine
32cffb5bb5 Add --disable-blocking-tcp-connections flag.
Currently, pupnp is using a blocking connect to sends GENA
notifications. As a result, when there is a lot of notifications with
CPs which were disconnected without unsusbcribing, all the pupnp
threads are blocked for 20s (timeout). To correct this issue, this
patch replace the call to connect with a call to private_connect and add
a compilation flag to disable blocking TCP connections, so if we are not
able to connect to the CP, the notification is lost.
2010-11-11 21:40:22 -02:00
Marcelo Roberto Jimenez
2b30575ca5 Remove commented old code from webserver.c. 2010-11-11 21:31:53 -02:00
Marcelo Roberto Jimenez
d32212a6fd Changelog and THANKS update. 2010-11-07 19:20:03 -02:00
Stefan Sommerfeld
508b782c79 Fixed some typos. 2010-11-07 18:42:44 -02:00
Stefan Sommerfeld
38d5e58e22 Add a simple strndup() implementation for win32. 2010-11-07 18:31:48 -02:00
Stefan Sommerfeld
ee5bd670d4 Fix for size_t in UpnpString. 2010-11-07 18:31:48 -02:00
Stefan Sommerfeld
fcb5e7c438 Fix for size_t related warnings. 2010-11-07 18:31:48 -02:00
Stefan Sommerfeld
243cd41974 Fix for inline usage. 2010-11-07 18:31:48 -02:00
Marcelo Roberto Jimenez
853cd32cfe Remove unused parameter bufferLen from GetDescDocumentAndURL(). 2010-11-07 18:31:48 -02:00
Marcelo Roberto Jimenez
f384e54fc6 Consistent usage of win32 INVALID_SOCKET and SOCKET_ERROR.
On win32 socket() returns INVALID_SOCKET, which is unsigned,
on error, not -1.

Also, most network functions return SOCKET_ERROR.

This patch tries to make the usage consistent.
2010-11-07 18:31:47 -02:00
Stefan Sommerfeld
9e12768cdb Fixed server port definition. 2010-11-07 18:31:47 -02:00
Stefan Sommerfeld
4b47e6a51d Fix for mixed usage of SOCKET and int. 2010-11-07 17:52:14 -02:00
Stefan Sommerfeld
a5fb5edfc9 Make notify_send_and_recv() return the appropriate error code.
notify_send_and_recv() was returning the connection fd.
2010-11-07 17:52:14 -02:00
Marcelo Roberto Jimenez
8bd32d330b Proper inclusion of inet_pton.h for win32. 2010-11-07 17:52:14 -02:00
Stefan Sommerfeld
00eb52cc85 fixed wrong declaration of inet_ntop4 2010-11-07 17:52:14 -02:00
Marcelo Roberto Jimenez
ff006272b5 PTHREAD_MUTEX_RECURSIVE on DragonFly is an enum.
SF Bug Tracker - ID: 3104527
Submitted: OBATA Akio ( obache ) - 2010-11-07 07:10:28 BRST

In threadutil/inc/ithread.h, it is expected that
PTHREAD_MUTEX_RECURSIVE is defined as macro. But on DragonFly BSD,
it is defined as enum, so not works as expected.

Attachment patch treat that DragonFly BSD always
have PTHREAD_MUTEX_RECURSIVE.
2010-11-07 11:49:33 -02:00
Marcelo Roberto Jimenez
852c301c5c ftime(3) in -lcompat should not be checked.
SF Bug Tracker - ID: 3104521
Submitted: OBATA Akio ( obache ) - 2010-11-07 07:03:44 BRST

In configure.ac
AC_CHECK_FUNCS(ftime,, [AC_CHECK_LIB(compat, ftime)])

But since version 1.6.3, ftime(3) is not used, so it should be
removed, or introduce unwanted linkage with -lcompat.
2010-11-07 09:45:05 -02:00
Marcelo Roberto Jimenez
d270499cd8 Homekeeping for the next release. 2010-11-07 01:43:50 -02:00
Marcelo Roberto Jimenez
6ac867bbb1 Fix the library numbers for release. 2010-11-07 01:33:18 -02:00
Marcelo Roberto Jimenez
9052ca95be Fix broken Makefile.am and remove unused file utilall.h. 2010-11-06 19:41:47 -02:00
Marcelo Roberto Jimenez
ef7edf6cf8 Fix for "SampleUtil_Initialize was called multiple times!" bug.
Fix for bug introduced in samples code in svn revision 502, commit
git:25c908c558c8e60eb386c155a6b93add447ffec0

Sample device and combo were aborting with the message:
"***** SampleUtil_Initialize was called multiple times!"
2010-11-06 00:45:24 -02:00
Fabrice Fontaine
c65ec8a720 Make multiple SSDP advertisements faster.
Put the loop to send multiple copies of each SSDP advertisements in
ssdp_server.c instead of ssdp_device.c so we have only one call to
imillisleep ( SSDP_PAUSE ) to speed up advertisements.
2010-11-05 23:52:17 -02:00
Fabrice Fontaine
2d22e997e1 Removing unused NUM_COPY variable.
Previously, NUM_COPY was used in ssdp_device.c to send multiple copies
of each advertisements but also multiple replies to each M-SEARCH
request. As sending multiple replies is not compliant with HTTPU/MU
spec, NUM_COPY has been set to 1 in an older patch. However, as this
variable is not needed and has been replaced with SSDP_COPY, it has
been removed.
2010-11-05 23:52:11 -02:00
Fabrice Fontaine
96dc968f18 Use SSDP_COPY to send multiple SSDP advertisements.
Currently, SSDP_COPY is used only to send multiple M-SEARCH requests (in
ssdp_ctrlpt.c). With this patch, SSDP_COPY is also used to send multiple
copies of each advertisements packets (in ssdp_device.c).
2010-11-05 13:25:40 -02:00
Carl Benson
8e846368e0 patch for taking notice of UPNP_USE_RWLOCK flag in threadutil
By "Carl Benson" <carl.benson@windriver.com>:

I had to do some modifications myself though, because the Android
build system insists on having a file named "util.h" taking precedence
in its include path, libupnp gets confused because of the same filename
in upnp/src/inc/util.h
2010-11-01 01:06:11 -02:00
Marcelo Roberto Jimenez
d6671c464f Bump config to 1.6.9. 2010-11-01 01:03:40 -02:00
Marcelo Roberto Jimenez
699dd3c82e Missed this line in configure.ac in the homekeeping commit. 2010-10-21 09:55:54 -02:00
Marcelo Roberto Jimenez
9be360bcd1 Homekeeping for the next release. 2010-10-20 11:15:23 -02:00
103 changed files with 12149 additions and 19438 deletions

6
.gitignore vendored
View File

@@ -98,8 +98,8 @@ m4/lt~obsolete.m4
stamp-h1 stamp-h1
upnp/inc/stamp-h2 upnp/inc/stamp-h2
upnp/inc/upnpconfig.h upnp/inc/upnpconfig.h
upnp/sample/upnp_tv_combo upnp/sample/tv_combo
upnp/sample/upnp_tv_ctrlpt upnp/sample/tv_ctrlpt
upnp/sample/upnp_tv_device upnp/sample/tv_device
docs/doxygen docs/doxygen

167
ChangeLog
View File

@@ -1,3 +1,170 @@
*******************************************************************************
Version 1.6.10
*******************************************************************************
2010-11-23 Fabrice Fontaine <fabrice.fontaine(at)orange-ftgroup.com>
Major bug fix in http_SendMessage.
Currently, http_SendMessage was not able to write to write a buffer
due to a bad use of file_buf instead of buf. This bug was introduced by
the 0197-Doxygen-reformating-compiler-warnings patch.
2010-11-23 Fabrice Fontaine <fabrice.fontaine(at)orange-ftgroup.com>
Returning the Sid in Upnp_Event_Subscribe.
Currently, Upnp_Event_Subscribe always contains an empty chain in the
Sid parameter. This patch now saves the client Subscription ID in this
parameter so Control Points can see and use the same SID in the
Upnp_Event_Subscribe and in the Upnp_Event structures.
2010-11-22 Marcelo Roberto Jimenez <mroberto(at)users.sourceforge.net>
Two fixes from Juergen Lock <nox(at)jelal.kn-bremen.de>:
1. varargs: pass size of CRLF as size_t not as int:
--- upnp/src/gena/gena_device.c.orig
+++ upnp/src/gena/gena_device.c
@@ -225,7 +225,7 @@ static UPNP_INLINE int notify_send_and_r
"bbb",
start_msg.buf, start_msg.length,
propertySet, strlen(propertySet),
- "\r\n", 2);
+ "\r\n", sizeof "\r\n" - 1);
if (ret_code) {
membuffer_destroy(&start_msg);
sock_destroy(&info, SD_BOTH);
2. Remove "b" arg here, there is no buffer passed: (this caused a pointer
to be interpreted as a buffer size to be alloc'd/copied, hence the 32 GB.)
--- upnp/src/genlib/net/http/webserver.c.orig
+++ upnp/src/genlib/net/http/webserver.c
@@ -1262,7 +1262,7 @@ static int process_request(
// Content-Range: bytes 222-3333/4000 HTTP_PARTIAL_CONTENT
// Transfer-Encoding: chunked
if (http_MakeMessage(headers, resp_major, resp_minor,
- "R" "TLD" "s" "tcS" "b" "Xc" "sCc",
+ "R" "TLD" "s" "tcS" "Xc" "sCc",
HTTP_OK, // status code
finfo.content_type, // content type
RespInstr, // language info
2010-11-15 Marcelo Roberto Jimenez <mroberto(at)users.sourceforge.net>
Added the convenience function UpnpResolveURL2() to upnptools.c.
This function avoids some unecessary memory allocation.
The memory alloc'd by this function must be freed later by the caller.
2010-11-10 Fabrice Fontaine <fabrice.fontaine(at)orange-ftgroup.com>
Add GENA_NOTIFICATION_xxx_TIMEOUT variable.
Currently, in notify_send_and_recv function, pupnp waits for
HTTP_DEFAULT_TIMEOUT seconds when trying to send a GENA notification.
When there is a lot of notifications with CPs which was disconnected
without unsusbcribing, all the pupnp threads are blocked on this
timeout. To correct, this issue, this patch adds a new variable,
GENA_NOTIFICATION_SENDING_TIMEOUT, which can be used to lower the
timeout so GENA threads return quickly when writing is impossible. By
the same mean, pupnp waits the CP's answer to the NOTIFY for
HTTP_DEFAULT_TIMEOUT seconds, so this patch adds a new variable,
GENA_NOTIFICATION_ANSWERING_TIMEOUT, to customize this value.
2010-11-10 Fabrice Fontaine <fabrice.fontaine(at)orange-ftgroup.com>
Add --disable-blocking-tcp-connections flag.
Currently, pupnp is using a blocking connect to sends GENA
notifications. As a result, when there is a lot of notifications with
CPs which were disconnected without unsusbcribing, all the pupnp
threads are blocked for 20s (timeout). To correct this issue, this
patch replace the call to connect with a call to private_connect and add
a compilation flag to disable blocking TCP connections, so if we are not
able to connect to the CP, the notification is lost.
2010-11-07 Stefan Sommerfeld <zerocom(at)cs.tu-berlin.de>
Several patches for windows compatibility and fixing warnings.
2010-11-07 Marcelo Roberto Jimenez <mroberto(at)users.sourceforge.net>
PTHREAD_MUTEX_RECURSIVE on DragonFly is an enum.
SF Bug Tracker - ID: 3104527
Submitted: OBATA Akio ( obache ) - 2010-11-07 07:10:28 BRST
In threadutil/inc/ithread.h, it is expected that
PTHREAD_MUTEX_RECURSIVE is defined as macro. But on DragonFly BSD,
it is defined as enum, so not works as expected.
Attachment patch treat that DragonFly BSD always
have PTHREAD_MUTEX_RECURSIVE.
2010-11-07 Marcelo Roberto Jimenez <mroberto(at)users.sourceforge.net>
ftime(3) in -lcompat should not be checked.
SF Bug Tracker - ID: 3104521
Submitted: OBATA Akio ( obache ) - 2010-11-07 07:03:44 BRST
In configure.ac
AC_CHECK_FUNCS(ftime,, [AC_CHECK_LIB(compat, ftime)])
But since version 1.6.3, ftime(3) is not used, so it should be
removed, or introduce unwanted linkage with -lcompat.
*******************************************************************************
Version 1.6.9
*******************************************************************************
2010-11-06 Marcelo Roberto Jimenez <mroberto(at)users.sourceforge.net>
Fix for bug introduced in samples code in svn revision 502, commit
git:25c908c558c8e60eb386c155a6b93add447ffec0
Sample device and combo were aborting with the message:
"***** SampleUtil_Initialize was called multiple times!"
2010-11-06 Fabrice Fontaine <fabrice.fontaine(at)orange-ftgroup.com>
Make multiple SSDP advertisements faster.
Put the loop to send multiple copies of each SSDP advertisements in
ssdp_server.c instead of ssdp_device.c so we have only one call to
imillisleep ( SSDP_PAUSE ) to speed up advertisements.
2010-11-05 Fabrice Fontaine <fabrice.fontaine(at)orange-ftgroup.com>
Removing unused NUM_COPY variable.
Previously, NUM_COPY was used in ssdp_device.c to send multiple copies
of each advertisements but also multiple replies to each M-SEARCH
request. As sending multiple replies is not compliant with HTTPU/MU
spec, NUM_COPY has been set to 1 in an older patch. However, as this
variable is not needed and has been replaced with SSDP_COPY, it has
been removed.
2010-11-05 Fabrice Fontaine <fabrice.fontaine(at)orange-ftgroup.com>
Use SSDP_COPY to send multiple SSDP advertisements.
Currently, SSDP_COPY is used only to send multiple M-SEARCH requests (in
ssdp_ctrlpt.c). With this patch, SSDP_COPY is also used to send multiple
copies of each advertisements packets (in ssdp_device.c).
2010-11-01 Carl Benson <carl.benson(at)windriver.com>
Fix for Android build.
I had to do some modifications myself though, because the Android
build system insists on having a file named "util.h" taking precedence
in its include path, libupnp gets confused because of the same filename
in upnp/src/inc/util.h
******************************************************************************* *******************************************************************************
Version 1.6.8 Version 1.6.8
******************************************************************************* *******************************************************************************

View File

@@ -31,7 +31,7 @@ PROJECT_NAME = libUPnP
# This could be handy for archiving the generated documentation or # This could be handy for archiving the generated documentation or
# if some version control system is used. # if some version control system is used.
PROJECT_NUMBER = 1.6.8 PROJECT_NUMBER = 1.6.10
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
# base path where the generated documentation will be put. # base path where the generated documentation will be put.

6
THANKS
View File

@@ -13,6 +13,7 @@ exempt of errors.
- Arno Willig - Arno Willig
- Bob Ciora - Bob Ciora
- Carlo Parata - Carlo Parata
- Carl Benson
- Chandra (inactiveneurons) - Chandra (inactiveneurons)
- Chaos - Chaos
- Charles Nepveu (cnepveu) - Charles Nepveu (cnepveu)
@@ -29,12 +30,13 @@ exempt of errors.
- Fabrice Fontaine - Fabrice Fontaine
- Fredrik Svensson - Fredrik Svensson
- Glen Masgai - Glen Masgai
- Hartmut Holzgraefe - hholzgra - Hartmut Holzgraefe (hholzgra)
- Ingo Hofmann - Ingo Hofmann
- Jiri Zouhar - Jiri Zouhar
- John Dennis - John Dennis
- Jonathan Casiot (no_dice) - Jonathan Casiot (no_dice)
- Josh Carroll - Josh Carroll
- Juergen Lock
- Keith Brindley - Keith Brindley
- Leuk_He - Leuk_He
- Loigu - Loigu
@@ -44,6 +46,7 @@ exempt of errors.
- Nektarios K. Papadopoulos (npapadop) - Nektarios K. Papadopoulos (npapadop)
- Nicholas Kraft - Nicholas Kraft
- Nick Leverton (leveret) - Nick Leverton (leveret)
- Obata Akio (obache)
- Oskar Liljeblad - Oskar Liljeblad
- Michael (oxygenic) - Michael (oxygenic)
- Paul Vixie - Paul Vixie
@@ -52,6 +55,7 @@ exempt of errors.
- Robert Gingher (robsbox) - Robert Gingher (robsbox)
- Ronan Menard - Ronan Menard
- Siva Chandran - Siva Chandran
- Stefan Sommerfeld (zerocom)
- Stéphane Corthésy - Stéphane Corthésy
- Steve Bresson - Steve Bresson
- Timothy Redaelli - Timothy Redaelli

View File

@@ -19,15 +19,9 @@
/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */ /* Define to 1 if fseeko (and presumably ftello) exists and is declared. */
#define HAVE_FSEEKO 1 #define HAVE_FSEEKO 1
/* Define to 1 if you have the `ftime' function. */
#define HAVE_FTIME 1
/* Define to 1 if you have the <inttypes.h> header file. */ /* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1 #define HAVE_INTTYPES_H 1
/* Define to 1 if you have the `compat' library (-lcompat). */
/* #undef HAVE_LIBCOMPAT */
/* Define to 1 if you have the <limits.h> header file. */ /* Define to 1 if you have the <limits.h> header file. */
#define HAVE_LIMITS_H 1 #define HAVE_LIMITS_H 1
@@ -105,13 +99,13 @@
#define PACKAGE_NAME "libupnp" #define PACKAGE_NAME "libupnp"
/* Define to the full name and version of this package. */ /* Define to the full name and version of this package. */
#define PACKAGE_STRING "libupnp 1.6.8" #define PACKAGE_STRING "libupnp 1.6.10"
/* Define to the one symbol short name of this package. */ /* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "libupnp" #define PACKAGE_TARNAME "libupnp"
/* Define to the version of this package. */ /* Define to the version of this package. */
#define PACKAGE_VERSION "1.6.8" #define PACKAGE_VERSION "1.6.10"
/* Define to necessary symbol if this constant uses a non-standard name on /* Define to necessary symbol if this constant uses a non-standard name on
your system. */ your system. */
@@ -120,6 +114,9 @@
/* Define to 1 if you have the ANSI C header files. */ /* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1 #define STDC_HEADERS 1
/* see upnpconfig.h */
#define UPNP_ENABLE_BLOCKING_TCP_CONNECTIONS 1
/* see upnpconfig.h */ /* see upnpconfig.h */
/* #undef UPNP_ENABLE_IPV6 */ /* #undef UPNP_ENABLE_IPV6 */
@@ -151,19 +148,19 @@
#define UPNP_VERSION_MINOR 6 #define UPNP_VERSION_MINOR 6
/* see upnpconfig.h */ /* see upnpconfig.h */
#define UPNP_VERSION_PATCH 8 #define UPNP_VERSION_PATCH 10
/* see upnpconfig.h */ /* see upnpconfig.h */
#define UPNP_VERSION_STRING "1.6.8" #define UPNP_VERSION_STRING "1.6.10"
/* Version number of package */ /* Version number of package */
#define VERSION "1.6.8" #define VERSION "1.6.10"
/* File Offset size */ /* File Offset size */
#define _FILE_OFFSET_BITS 64 #define _FILE_OFFSET_BITS 64
/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */ /* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
/* #undef _LARGEFILE_SOURCE */ #define _LARGEFILE_SOURCE 1
/* Large files support */ /* Large files support */
#define _LARGE_FILE_SOURCE /**/ #define _LARGE_FILE_SOURCE /**/

View File

@@ -40,7 +40,7 @@
***************************************************************************/ ***************************************************************************/
/** The library version (string) e.g. "1.3.0" */ /** The library version (string) e.g. "1.3.0" */
#define UPNP_VERSION_STRING "1.6.8" #define UPNP_VERSION_STRING "1.6.10"
/** Major version of the library */ /** Major version of the library */
#define UPNP_VERSION_MAJOR 1 #define UPNP_VERSION_MAJOR 1
@@ -49,7 +49,7 @@
#define UPNP_VERSION_MINOR 6 #define UPNP_VERSION_MINOR 6
/** Patch version of the library */ /** Patch version of the library */
#define UPNP_VERSION_PATCH 8 #define UPNP_VERSION_PATCH 10
/** The library version (numeric) e.g. 10300 means version 1.3.0 */ /** The library version (numeric) e.g. 10300 means version 1.3.0 */
#define UPNP_VERSION \ #define UPNP_VERSION \

View File

@@ -9,7 +9,7 @@
AC_PREREQ(2.60) AC_PREREQ(2.60)
AC_INIT([libupnp], [1.6.8], [mroberto@users.sourceforge.net]) AC_INIT([libupnp], [1.6.10], [mroberto@users.sourceforge.net])
dnl ############################################################################ dnl ############################################################################
dnl # *Independently* of the above libupnp package version, the libtool version dnl # *Independently* of the above libupnp package version, the libtool version
dnl # of the 3 libraries need to be updated whenever there is a change released: dnl # of the 3 libraries need to be updated whenever there is a change released:
@@ -175,14 +175,46 @@ dnl # - Code has changed in threadutil
dnl # revision: 0 -> 1 dnl # revision: 0 -> 1
dnl # - Code has changed in upnp dnl # - Code has changed in upnp
dnl # revision: 0 -> 1 dnl # revision: 0 -> 1
dnl #
dnl #AC_SUBST([LT_VERSION_IXML], [2:5:0]) dnl #AC_SUBST([LT_VERSION_IXML], [2:5:0])
dnl #AC_SUBST([LT_VERSION_THREADUTIL], [5:1:2]) dnl #AC_SUBST([LT_VERSION_THREADUTIL], [5:1:2])
dnl #AC_SUBST([LT_VERSION_UPNP], [4:1:0]) dnl #AC_SUBST([LT_VERSION_UPNP], [4:1:0])
dnl # dnl #
dnl ############################################################################ dnl ############################################################################
AC_SUBST([LT_VERSION_IXML], [2:5:0]) dnl # Release 1.6.9:
AC_SUBST([LT_VERSION_THREADUTIL], [5:1:2]) dnl # "current:revision:age"
AC_SUBST([LT_VERSION_UPNP], [4:1:0]) dnl #
dnl # - Code has changed in threadutil
dnl # revision: 1 -> 2
dnl # - Code has changed in upnp
dnl # revision: 1 -> 2
dnl #
dnl #AC_SUBST([LT_VERSION_IXML], [2:5:0])
dnl #AC_SUBST([LT_VERSION_THREADUTIL], [5:2:2])
dnl #AC_SUBST([LT_VERSION_UPNP], [4:2:0])
dnl #
dnl ############################################################################
dnl # Release 1.6.10:
dnl # "current:revision:age"
dnl #
dnl # - Code has changed inxml
dnl # revision: 5 -> 6
dnl # - Code has changed in threadutil
dnl # revision: 2 -> 3
dnl # - Code has changed in upnp
dnl # revision: 2 -> 3
dnl # - interface has changed in upnp
dnl # current: 4 -> 5
dnl # revision: 3 -> 0
dnl #
dnl #AC_SUBST([LT_VERSION_IXML], [2:6:0])
dnl #AC_SUBST([LT_VERSION_THREADUTIL], [5:3:2])
dnl #AC_SUBST([LT_VERSION_UPNP], [5:0:0])
dnl #
############################################################################
AC_SUBST([LT_VERSION_IXML], [2:6:0])
AC_SUBST([LT_VERSION_THREADUTIL], [5:3:2])
AC_SUBST([LT_VERSION_UPNP], [5:0:0])
dnl ############################################################################ dnl ############################################################################
dnl # Repeating the algorithm to place it closer to the modificatin place: dnl # Repeating the algorithm to place it closer to the modificatin place:
dnl # - library code modified: revision++ dnl # - library code modified: revision++
@@ -286,6 +318,11 @@ if test "x$enable_notification_reordering" = xyes ; then
AC_DEFINE(UPNP_ENABLE_NOTIFICATION_REORDERING, 1, [see upnpconfig.h]) AC_DEFINE(UPNP_ENABLE_NOTIFICATION_REORDERING, 1, [see upnpconfig.h])
fi fi
RT_BOOL_ARG_ENABLE([blocking_tcp_connections], [yes], [blocking TCP connections])
if test "x$enable_blocking_tcp_connections" = xyes ; then
AC_DEFINE(UPNP_ENABLE_BLOCKING_TCP_CONNECTIONS, 1, [see upnpconfig.h])
fi
RT_BOOL_ARG_ENABLE([samples], [yes], [compilation of upnp/sample/ code]) RT_BOOL_ARG_ENABLE([samples], [yes], [compilation of upnp/sample/ code])
@@ -450,7 +487,6 @@ fi
# #
AC_FUNC_VPRINTF AC_FUNC_VPRINTF
AC_FUNC_FSEEKO AC_FUNC_FSEEKO
AC_CHECK_FUNCS(ftime,, [AC_CHECK_LIB(compat, ftime)])
# #
# Solaris needs -lsocket -lnsl -lrt # Solaris needs -lsocket -lnsl -lrt
AC_SEARCH_LIBS([bind], [socket]) AC_SEARCH_LIBS([bind], [socket])

View File

@@ -41,7 +41,10 @@ void IxmlPrintf(
#else /* DEBUG */ #else /* DEBUG */
static UPNP_INLINE void IxmlPrintf( static UPNP_INLINE void IxmlPrintf(
const char *FmtStr, const char *FmtStr,
...) {} ...)
{
FmtStr = FmtStr;
}
#endif /* DEBUG */ #endif /* DEBUG */
@@ -59,6 +62,8 @@ static UPNP_INLINE void printNodes(
IXML_Node *tmpRoot, IXML_Node *tmpRoot,
int depth) int depth)
{ {
tmpRoot = tmpRoot;
depth = depth;
} }
#endif #endif

View File

@@ -139,7 +139,7 @@ int ixmlDocument_createElementEx(
errCode = IXML_INSUFFICIENT_MEMORY; errCode = IXML_INSUFFICIENT_MEMORY;
goto ErrorHandler; goto ErrorHandler;
} }
// set the node fields /* set the node fields */
newElement->n.nodeType = eELEMENT_NODE; newElement->n.nodeType = eELEMENT_NODE;
newElement->n.nodeName = strdup(tagName); newElement->n.nodeName = strdup(tagName);
if (newElement->n.nodeName == NULL) { if (newElement->n.nodeName == NULL) {
@@ -229,7 +229,7 @@ int ixmlDocument_createTextNodeEx(
rc = IXML_INSUFFICIENT_MEMORY; rc = IXML_INSUFFICIENT_MEMORY;
goto ErrorHandler; goto ErrorHandler;
} }
// initialize the node /* initialize the node */
ixmlNode_init(returnNode); ixmlNode_init(returnNode);
returnNode->nodeName = strdup(TEXTNODENAME); returnNode->nodeName = strdup(TEXTNODENAME);
@@ -239,7 +239,7 @@ int ixmlDocument_createTextNodeEx(
rc = IXML_INSUFFICIENT_MEMORY; rc = IXML_INSUFFICIENT_MEMORY;
goto ErrorHandler; goto ErrorHandler;
} }
// add in node value /* add in node value */
if (data != NULL) { if (data != NULL) {
returnNode->nodeValue = strdup(data); returnNode->nodeValue = strdup(data);
if (returnNode->nodeValue == NULL) { if (returnNode->nodeValue == NULL) {
@@ -295,7 +295,7 @@ int ixmlDocument_createAttributeEx(
ixmlAttr_init(attrNode); ixmlAttr_init(attrNode);
attrNode->n.nodeType = eATTRIBUTE_NODE; attrNode->n.nodeType = eATTRIBUTE_NODE;
// set the node fields /* set the node fields */
attrNode->n.nodeName = strdup(name); attrNode->n.nodeName = strdup(name);
if (attrNode->n.nodeName == NULL) { if (attrNode->n.nodeName == NULL) {
ixmlAttr_free(attrNode); ixmlAttr_free(attrNode);
@@ -343,7 +343,7 @@ int ixmlDocument_createAttributeNSEx(
if (errCode != IXML_SUCCESS) { if (errCode != IXML_SUCCESS) {
goto ErrorHandler; goto ErrorHandler;
} }
// set the namespaceURI field /* set the namespaceURI field */
attrNode->n.namespaceURI = strdup(namespaceURI); attrNode->n.namespaceURI = strdup(namespaceURI);
if (attrNode->n.namespaceURI == NULL) { if (attrNode->n.namespaceURI == NULL) {
ixmlAttr_free(attrNode); ixmlAttr_free(attrNode);
@@ -351,7 +351,7 @@ int ixmlDocument_createAttributeNSEx(
errCode = IXML_INSUFFICIENT_MEMORY; errCode = IXML_INSUFFICIENT_MEMORY;
goto ErrorHandler; goto ErrorHandler;
} }
// set the localName and prefix /* set the localName and prefix */
errCode = errCode =
ixmlNode_setNodeName((IXML_Node *)attrNode, qualifiedName); ixmlNode_setNodeName((IXML_Node *)attrNode, qualifiedName);
if (errCode != IXML_SUCCESS) { if (errCode != IXML_SUCCESS) {
@@ -458,7 +458,7 @@ int ixmlDocument_createElementNSEx(
line = __LINE__; line = __LINE__;
goto ErrorHandler; goto ErrorHandler;
} }
// set the namespaceURI field /* set the namespaceURI field */
newElement->n.namespaceURI = strdup(namespaceURI); newElement->n.namespaceURI = strdup(namespaceURI);
if (newElement->n.namespaceURI == NULL) { if (newElement->n.namespaceURI == NULL) {
line = __LINE__; line = __LINE__;
@@ -467,7 +467,7 @@ int ixmlDocument_createElementNSEx(
ret = IXML_INSUFFICIENT_MEMORY; ret = IXML_INSUFFICIENT_MEMORY;
goto ErrorHandler; goto ErrorHandler;
} }
// set the localName and prefix /* set the localName and prefix */
ret = ixmlNode_setNodeName((IXML_Node *)newElement, qualifiedName); ret = ixmlNode_setNodeName((IXML_Node *)newElement, qualifiedName);
if (ret != IXML_SUCCESS) { if (ret != IXML_SUCCESS) {
line = __LINE__; line = __LINE__;

View File

@@ -110,7 +110,7 @@ int ixmlElement_setAttribute(
{ {
IXML_Node *attrNode; IXML_Node *attrNode;
IXML_Attr *newAttrNode; IXML_Attr *newAttrNode;
short errCode = IXML_SUCCESS; int errCode = IXML_SUCCESS;
if (element == NULL || name == NULL || value == NULL) { if (element == NULL || name == NULL || value == NULL) {
errCode = IXML_INVALID_PARAMETER; errCode = IXML_INVALID_PARAMETER;
@@ -208,7 +208,8 @@ IXML_Attr *ixmlElement_getAttributeNode(IXML_Element *element, const DOMString n
attrNode = element->n.firstAttr; attrNode = element->n.firstAttr;
while (attrNode != NULL) { while (attrNode != NULL) {
if (strcmp(attrNode->nodeName, name) == 0) { // found it if (strcmp(attrNode->nodeName, name) == 0) {
/* found it */
break; break;
} else { } else {
attrNode = attrNode->nextSibling; attrNode = attrNode->nextSibling;
@@ -555,7 +556,7 @@ IXML_Attr *ixmlElement_getAttributeNodeNS(
while (attrNode != NULL) { while (attrNode != NULL) {
if (strcmp(attrNode->localName, localName) == 0 && if (strcmp(attrNode->localName, localName) == 0 &&
strcmp(attrNode->namespaceURI, namespaceURI) == 0) { strcmp(attrNode->namespaceURI, namespaceURI) == 0) {
// found it /* found it */
break; break;
} else { } else {
attrNode = attrNode->nextSibling; attrNode = attrNode->nextSibling;

View File

@@ -166,7 +166,7 @@ int ixml_membuf_insert(
size_t buf_len, size_t buf_len,
/*! [in] The point of insertion relative to the beggining of the /*! [in] The point of insertion relative to the beggining of the
* ixml_membuf internal buffer. */ * ixml_membuf internal buffer. */
int index); size_t index);
#endif /* IXML_MEMBUF_H */ #endif /* IXML_MEMBUF_H */

View File

@@ -54,37 +54,29 @@ static void copy_with_escape(
/*! [in] The string to copy from. */ /*! [in] The string to copy from. */
const char *p) const char *p)
{ {
int i; size_t i;
int plen; size_t plen;
if (p == NULL) { if (p == NULL)
return; return;
}
plen = strlen(p); plen = strlen(p);
for (i = 0; i < plen; ++i) {
for (i = 0; i < plen; i++) {
switch (p[i]) { switch (p[i]) {
case '<': case '<':
ixml_membuf_append_str(buf, "&lt;"); ixml_membuf_append_str(buf, "&lt;");
break; break;
case '>': case '>':
ixml_membuf_append_str(buf, "&gt;"); ixml_membuf_append_str(buf, "&gt;");
break; break;
case '&': case '&':
ixml_membuf_append_str(buf, "&amp;"); ixml_membuf_append_str(buf, "&amp;");
break; break;
case '\'': case '\'':
ixml_membuf_append_str(buf, "&apos;"); ixml_membuf_append_str(buf, "&apos;");
break; break;
case '\"': case '\"':
ixml_membuf_append_str(buf, "&quot;"); ixml_membuf_append_str(buf, "&quot;");
break; break;
default: default:
ixml_membuf_append(buf, &p[i]); ixml_membuf_append(buf, &p[i]);
break; break;
@@ -161,11 +153,11 @@ static void ixmlPrintDomTreeRecursive(
} else { } else {
ixml_membuf_append_str(buf, ">"); ixml_membuf_append_str(buf, ">");
} }
// output the children /* output the children */
ixmlPrintDomTreeRecursive( ixmlPrintDomTreeRecursive(
ixmlNode_getFirstChild(nodeptr), buf); ixmlNode_getFirstChild(nodeptr), buf);
// 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);
@@ -242,11 +234,11 @@ static void ixmlPrintDomTree(
ixml_membuf_append_str(buf, ">"); ixml_membuf_append_str(buf, ">");
} }
// output the children /* output the children */
ixmlPrintDomTreeRecursive( ixmlPrintDomTreeRecursive(
ixmlNode_getFirstChild(nodeptr), buf); ixmlNode_getFirstChild(nodeptr), buf);
// 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, ">\r\n"); ixml_membuf_append_str(buf, ">\r\n");
@@ -314,10 +306,10 @@ static void ixmlDomTreetoString(
ixml_membuf_append_str(buf, ">"); ixml_membuf_append_str(buf, ">");
} }
// output the children /* output the children */
ixmlPrintDomTreeRecursive(ixmlNode_getFirstChild(nodeptr), buf); ixmlPrintDomTreeRecursive(ixmlNode_getFirstChild(nodeptr), buf);
// 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, ">"); ixml_membuf_append_str(buf, ">");

View File

@@ -41,7 +41,7 @@ void IxmlPrintf(
void printNodes(IXML_Node *tmpRoot, int depth) void printNodes(IXML_Node *tmpRoot, int depth)
{ {
int i; unsigned long i;
IXML_NodeList *NodeList1; IXML_NodeList *NodeList1;
IXML_Node *ChildNode1; IXML_Node *ChildNode1;
unsigned short NodeType; unsigned short NodeType;

View File

@@ -75,10 +75,10 @@ static int ixml_membuf_set_size(
diff = new_length - m->length; diff = new_length - m->length;
alloc_len = MAXVAL(m->size_inc, diff) + m->capacity; alloc_len = MAXVAL(m->size_inc, diff) + m->capacity;
} else { } else {
// decrease length /* decrease length */
assert(new_length <= m->length); assert(new_length <= m->length);
// if diff is 0..m->size_inc, don't free /* if diff is 0..m->size_inc, don't free */
if ((m->capacity - new_length) <= m->size_inc) { if ((m->capacity - new_length) <= m->size_inc) {
return 0; return 0;
} }
@@ -135,21 +135,21 @@ int ixml_membuf_assign(
assert(m != NULL); assert(m != NULL);
// set value to null /* set value to null */
if (buf == NULL) { if (buf == NULL) {
ixml_membuf_destroy(m); ixml_membuf_destroy(m);
return IXML_SUCCESS; return IXML_SUCCESS;
} }
// alloc mem /* alloc mem */
return_code = ixml_membuf_set_size(m, buf_len); return_code = ixml_membuf_set_size(m, buf_len);
if (return_code != 0) { if (return_code != 0) {
return return_code; return return_code;
} }
// copy /* copy */
memcpy(m->buf, buf, buf_len); memcpy(m->buf, buf, buf_len);
// null-terminate /* null-terminate */
m->buf[buf_len] = 0; m->buf[buf_len] = 0;
m->length = buf_len; m->length = buf_len;
@@ -187,13 +187,13 @@ int ixml_membuf_insert(
INOUT ixml_membuf *m, INOUT ixml_membuf *m,
IN const void *buf, IN const void *buf,
IN size_t buf_len, IN size_t buf_len,
int index) size_t index)
{ {
int return_code = 0; int return_code = 0;
assert(m != NULL); assert(m != NULL);
if (index < 0 || index > (int)m->length) { if (index > m->length) {
return IXML_INDEX_SIZE_ERR; return IXML_INDEX_SIZE_ERR;
} }

File diff suppressed because it is too large Load Diff

View File

@@ -85,7 +85,7 @@ IXML_Node *ixmlNamedNodeMap_getNamedItem(
IXML_NamedNodeMap *nnMap, IXML_NamedNodeMap *nnMap,
const DOMString name) const DOMString name)
{ {
long index; unsigned long index;
if (nnMap == NULL || name == NULL) { if (nnMap == NULL || name == NULL) {
return NULL; return NULL;
@@ -95,7 +95,7 @@ IXML_Node *ixmlNamedNodeMap_getNamedItem(
if (index == IXML_INVALID_ITEM_NUMBER) { if (index == IXML_INVALID_ITEM_NUMBER) {
return NULL; return NULL;
} else { } else {
return ixmlNamedNodeMap_item(nnMap, (unsigned long)index); return ixmlNamedNodeMap_item(nnMap, index);
} }
} }
@@ -165,7 +165,7 @@ int ixmlNamedNodeMap_addToNamedNodeMap(
} }
if (*nnMap == NULL) { if (*nnMap == NULL) {
// nodelist is empty /* nodelist is empty */
*nnMap = (IXML_NamedNodeMap *)malloc(sizeof (IXML_NamedNodeMap)); *nnMap = (IXML_NamedNodeMap *)malloc(sizeof (IXML_NamedNodeMap));
if (*nnMap == NULL) { if (*nnMap == NULL) {
return IXML_INSUFFICIENT_MEMORY; return IXML_INSUFFICIENT_MEMORY;

View File

@@ -542,11 +542,11 @@ int ixmlNode_replaceChild(
if (ixmlNode_allowChildren(nodeptr, newChild) == FALSE) { if (ixmlNode_allowChildren(nodeptr, newChild) == FALSE) {
return IXML_HIERARCHY_REQUEST_ERR; return IXML_HIERARCHY_REQUEST_ERR;
} }
// if newChild was created from a different document /* if newChild was created from a different document */
if (nodeptr->ownerDocument != newChild->ownerDocument) { if (nodeptr->ownerDocument != newChild->ownerDocument) {
return IXML_WRONG_DOCUMENT_ERR; return IXML_WRONG_DOCUMENT_ERR;
} }
// if refChild is not a child of nodeptr /* if refChild is not a child of nodeptr */
if (ixmlNode_isParent(nodeptr, oldChild) != TRUE) { if (ixmlNode_isParent(nodeptr, oldChild) != TRUE) {
return IXML_NOT_FOUND_ERR; return IXML_NOT_FOUND_ERR;
} }
@@ -763,6 +763,10 @@ static IXML_Element *ixmlNode_cloneElement(
/*! /*!
* \brief Returns a clone of a document node. * \brief Returns a clone of a document node.
* *
* Currently, the IXML_Document struct is just a node, so this function
* just mallocs the IXML_Document, sets the node type and name. Curiously,
* the parameter nodeptr is not actually used.
*
* \return A clone of a document node. * \return A clone of a document node.
*/ */
static IXML_Document *ixmlNode_cloneDoc( static IXML_Document *ixmlNode_cloneDoc(
@@ -792,6 +796,7 @@ static IXML_Document *ixmlNode_cloneDoc(
newDoc->n.nodeType = eDOCUMENT_NODE; newDoc->n.nodeType = eDOCUMENT_NODE;
return newDoc; return newDoc;
nodeptr = nodeptr;
} }
/*! /*!

View File

@@ -57,11 +57,11 @@ IXML_Node *ixmlNodeList_item(
IXML_NodeList *next; IXML_NodeList *next;
unsigned int i; unsigned int i;
// if the list ptr is NULL /* if the list ptr is NULL */
if (nList == NULL) { if (nList == NULL) {
return NULL; return NULL;
} }
// if index is more than list length /* if index is more than list length */
if (index > ixmlNodeList_length(nList) - 1) { if (index > ixmlNodeList_length(nList) - 1) {
return NULL; return NULL;
} }
@@ -93,7 +93,7 @@ int ixmlNodeList_addToNodeList(
} }
if (*nList == NULL) { if (*nList == NULL) {
// nodelist is empty /* nodelist is empty */
*nList = (IXML_NodeList *)malloc(sizeof (IXML_NodeList)); *nList = (IXML_NodeList *)malloc(sizeof (IXML_NodeList));
if (*nList == NULL) { if (*nList == NULL) {
return IXML_INSUFFICIENT_MEMORY; return IXML_INSUFFICIENT_MEMORY;

View File

@@ -1,4 +1,4 @@
Version: 1.6.8 Version: 1.6.10
Summary: Universal Plug and Play (UPnP) SDK Summary: Universal Plug and Play (UPnP) SDK
Name: libupnp Name: libupnp
Release: 1%{?dist} Release: 1%{?dist}

View File

@@ -29,118 +29,99 @@
* *
******************************************************************************/ ******************************************************************************/
#ifndef FREE_LIST_H #ifndef FREE_LIST_H
#define FREE_LIST_H #define FREE_LIST_H
/*! /*!
* \file * \file
*/ */
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#include "ithread.h" #include "ithread.h"
#include <errno.h> #include <errno.h>
/**************************************************************************** /*!
* Name: FreeListNode * Free list node. points to next free item.
* * Memory for node is borrowed from allocated items.
* Description: * \internal
* free list node. points to next free item. */
* memory for node is borrowed from allocated items.
* Internal Use Only.
*****************************************************************************/
typedef struct FREELISTNODE typedef struct FREELISTNODE
{ {
struct FREELISTNODE *next; struct FREELISTNODE *next;
} FreeListNode; } FreeListNode;
/*!
/****************************************************************************
* Name: FreeList
*
* Description:
* Stores head and size of free list, as well as mutex for protection. * Stores head and size of free list, as well as mutex for protection.
* Internal Use Only. * \internal
*****************************************************************************/ */
typedef struct FREELIST typedef struct FREELIST
{ {
FreeListNode *head; FreeListNode *head;
size_t element_size; size_t element_size;
int maxFreeListLength; int maxFreeListLength;
int freeListLength; int freeListLength;
} FreeList; } FreeList;
/**************************************************************************** /*!
* Function: FreeListInit * \brief Initializes Free List.
* *
* Description: * Must be called first and only once for FreeList.
* Initializes Free List. Must be called first. *
* And only once for FreeList. * \return:
* Parameters: * \li \c 0 on success.
* free_list - must be valid, non null, pointer to a linked list. * \li \c EINVAL on failure.
* size_t - size of elements to store in free list */
* maxFreeListSize - max size that the free list can grow to int FreeListInit(
* before returning memory to O.S. /*! Must be valid, non null, pointer to a linked list. */
* Returns: FreeList *free_list,
* 0 on success. Nonzero on failure. /*! Size of elements to store in free list. */
* Always returns 0.
*****************************************************************************/
int FreeListInit(FreeList *free_list,
size_t elementSize, size_t elementSize,
int maxFreeListSize); /*! Max size that the free list can grow to before returning
* memory to O.S. */
int maxFreeListLength);
/**************************************************************************** /*!
* Function: FreeListAlloc * \brief Allocates chunk of set size.
* *
* Description: * If a free item is available in the list, returnes the stored item,
* Allocates chunk of set size. * otherwise calls the O.S. to allocate memory.
* If a free item is available in the list, returnes the stored item.
* Otherwise calls the O.S. to allocate memory.
* Parameters:
* free_list - must be valid, non null, pointer to a linked list.
* Returns:
* Non NULL on success. NULL on failure.
*****************************************************************************/
void * FreeListAlloc (FreeList *free_list);
/****************************************************************************
* Function: FreeListFree
* *
* Description: * \return Non NULL on success. NULL on failure.
* Returns an item to the Free List. */
* If the free list is smaller than the max size than void *FreeListAlloc(
* adds the item to the free list. /*! Must be valid, non null, pointer to a linked list. */
* Otherwise returns the item to the O.S. FreeList *free_list);
* Parameters:
* free_list - must be valid, non null, pointer to a linked list.
* Returns:
* 0 on success. Nonzero on failure.
* Always returns 0.
*****************************************************************************/
int FreeListFree (FreeList *free_list,void * element);
/**************************************************************************** /*!
* Function: FreeListDestroy * \brief Returns an item to the Free List.
* *
* Description: * If the free list is smaller than the max size then adds the item to the
* Releases the resources stored with the free list. * free list, otherwise returns the item to the O.S.
* Parameters: *
* free_list - must be valid, non null, pointer to a linked list. * \return:
* Returns: * \li \c 0 on success.
* 0 on success. Nonzero on failure. * \li \c EINVAL on failure.
* Always returns 0. */
*****************************************************************************/ int FreeListFree(
int FreeListDestroy (FreeList *free_list); /*! Must be valid, non null, pointer to a free list. */
FreeList *free_list,
/*! Must be a pointer allocated by FreeListAlloc. */
void *element);
/*!
* \brief Releases the resources stored with the free list.
*
* \return:
* \li \c 0 on success.
* \li \c EINVAL on failure.
*/
int FreeListDestroy(
/*! Must be valid, non null, pointer to a linked list. */
FreeList *free_list);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@@ -29,58 +29,34 @@
* *
******************************************************************************/ ******************************************************************************/
#ifndef LINKED_LIST_H #ifndef LINKED_LIST_H
#define LINKED_LIST_H #define LINKED_LIST_H
/*! /*!
* \file * \file
*/ */
#include "FreeList.h" #include "FreeList.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#define EOUTOFMEM (-7 & 1<<29) #define EOUTOFMEM (-7 & 1<<29)
#define FREELISTSIZE 100 #define FREELISTSIZE 100
#define LIST_SUCCESS 1 #define LIST_SUCCESS 1
#define LIST_FAIL 0 #define LIST_FAIL 0
/*! Function for freeing list items. */
/****************************************************************************
* Name: free_routine
*
* Description:
* Function for freeing list items
*****************************************************************************/
typedef void (*free_function)(void *arg); typedef void (*free_function)(void *arg);
/*! Function for comparing list items. Returns 1 if itemA==itemB */
/****************************************************************************
* Name: cmp_routine
*
* Description:
* Function for comparing list items
* Returns 1 if itemA==itemB
*****************************************************************************/
typedef int (*cmp_routine)(void *itemA,void *itemB); typedef int (*cmp_routine)(void *itemA,void *itemB);
/*! Linked list node. Stores generic item and pointers to next and prev.
/**************************************************************************** * \internal
* Name: ListNode */
*
* Description:
* linked list node. stores generic item and pointers to next and prev.
* Internal Use Only.
*****************************************************************************/
typedef struct LISTNODE typedef struct LISTNODE
{ {
struct LISTNODE *prev; struct LISTNODE *prev;
@@ -88,14 +64,10 @@ typedef struct LISTNODE
void *item; void *item;
} ListNode; } ListNode;
/*!
/**************************************************************************** * Linked list (no protection).
* Name: LinkedList
* *
* Description: * Because this is for internal use, parameters are NOT checked for validity.
* linked list (no protection). Internal Use Only.
* Because this is for internal use, parameters are NOT checked for
* validity.
* The first item of the list is stored at node: head->next * The first item of the list is stored at node: head->next
* The last item of the list is stored at node: tail->prev * The last item of the list is stored at node: tail->prev
* If head->next=tail, then list is empty. * If head->next=tail, then list is empty.
@@ -103,249 +75,211 @@ typedef struct LISTNODE
* *
* LinkedList g; * LinkedList g;
* ListNode *temp = NULL; * ListNode *temp = NULL;
* for (temp = ListHead(g);temp!=NULL;temp = ListNext(g,temp)) * for (temp = ListHead(g);temp!=NULL;temp = ListNext(g,temp)) {
* {
* } * }
* *
*****************************************************************************/ * \internal
*/
typedef struct LINKEDLIST typedef struct LINKEDLIST
{ {
ListNode head; /* head, first item is stored at: head->next */ /*! head, first item is stored at: head->next */
ListNode tail; /* tail, last item is stored at: tail->prev */ ListNode head;
long size; /* size of list */ /*! tail, last item is stored at: tail->prev */
FreeList freeNodeList; /* free list to use */ ListNode tail;
free_function free_func; /* free function to use */ /*! size of list */
cmp_routine cmp_func; /* compare function to use */ long size;
/*! free list to use */
FreeList freeNodeList;
/*! free function to use */
free_function free_func;
/*! compare function to use */
cmp_routine cmp_func;
} LinkedList; } LinkedList;
/*!
/**************************************************************************** * \brief Initializes LinkedList. Must be called first and only once for List.
* Function: ListInit
* *
* Description: * \return
* Initializes LinkedList. Must be called first. * \li \c 0 on success.
* And only once for List. * \li \c EOUTOFMEM on failure.
* Parameters: */
* list - must be valid, non null, pointer to a linked list. int ListInit(
* cmp_func - function used to compare items. (May be NULL) /*! Must be valid, non null, pointer to a linked list. */
* free_func - function used to free items. (May be NULL) LinkedList *list,
* Returns: /*! Function used to compare items. (May be NULL). */
* 0 on success, EOUTOFMEM on failure. cmp_routine cmp_func,
*****************************************************************************/ /*! Function used to free items. (May be NULL). */
int ListInit(LinkedList *list,cmp_routine cmp_func, free_function free_func); free_function free_func);
/*!
/**************************************************************************** * \brief Adds a node to the head of the list. Node gets immediately after
* Function: ListAddHead * list head.
* *
* Description:
* Adds a node to the head of the list.
* Node gets immediately after list.head.
* Parameters:
* LinkedList *list - must be valid, non null, pointer to a linked list.
* void * item - item to be added
* Returns:
* The pointer to the ListNode on success, NULL on failure.
* Precondition: * Precondition:
* The list has been initialized. * The list has been initialized.
*****************************************************************************/
ListNode *ListAddHead(LinkedList *list, void *item);
/****************************************************************************
* Function: ListAddTail
* *
* Description: * \return The pointer to the ListNode on success, NULL on failure.
* Adds a node to the tail of the list. */
* Node gets added immediately before list.tail. ListNode *ListAddHead(
* Parameters: /*! Must be valid, non null, pointer to a linked list. */
* LinkedList *list - must be valid, non null, pointer to a linked list. LinkedList *list,
* void * item - item to be added /*! Item to be added. */
* Returns: void *item);
* The pointer to the ListNode on success, NULL on failure.
* Precondition:
* The list has been initialized.
*****************************************************************************/
ListNode *ListAddTail(LinkedList *list, void *item);
/*!
* \brief Adds a node to the tail of the list. Node gets added immediately
* before list.tail.
*
* Precondition: The list has been initialized.
*
* \return The pointer to the ListNode on success, NULL on failure.
*/
ListNode *ListAddTail(
/*! Must be valid, non null, pointer to a linked list. */
LinkedList *list,
/*! Item to be added. */
void *item);
/**************************************************************************** /*!
* Function: ListAddAfter * \brief Adds a node after the specified node. Node gets added immediately
* after bnode.
* *
* Description: * Precondition: The list has been initialized.
* Adds a node after the specified node. *
* Node gets added immediately after bnode. * \return The pointer to the ListNode on success, NULL on failure.
* Parameters: */
* LinkedList *list - must be valid, non null, pointer to a linked list. ListNode *ListAddAfter(
* void * item - item to be added /*! Must be valid, non null, pointer to a linked list. */
* ListNode * bnode - node to add after LinkedList *list,
* Returns: /*! Item to be added. */
* The pointer to the ListNode on success, NULL on failure. void *item,
* Precondition: /*! Node to add after. */
* The list has been initialized. ListNode *bnode);
*****************************************************************************/
ListNode *ListAddAfter(LinkedList *list, void *item, ListNode *bnode);
/*!
* \brief Adds a node before the specified node. Node gets added immediately
* before anode.
*
* Precondition: The list has been initialized.
*
* \return The pointer to the ListNode on success, NULL on failure.
*/
ListNode *ListAddBefore(
/*! Must be valid, non null, pointer to a linked list. */
LinkedList *list,
/*! Item to be added. */
void *item,
/*! Node to add in front of. */
ListNode *anode);
/**************************************************************************** /*!
* Function: ListAddBefore * \brief Removes a node from the list. The memory for the node is freed.
* *
* Description: * Precondition: The list has been initialized.
* Adds a node before the specified node. *
* Node gets added immediately before anode. * \return The pointer to the item stored in the node or NULL if the item
* Parameters: * is freed.
* LinkedList *list - must be valid, non null, pointer to a linked list. */
* ListNode * anode - node to add the in front of. void *ListDelNode(
* void * item - item to be added /*! Must be valid, non null, pointer to a linked list. */
* Returns: LinkedList *list,
* The pointer to the ListNode on success, NULL on failure. /*! Node to delete. */
* Precondition: ListNode *dnode,
* The list has been initialized. /*! if !0 then item is freed using free function. If 0 (or free
*****************************************************************************/ * function is NULL) then item is not freed. */
ListNode *ListAddBefore(LinkedList *list,void *item, ListNode *anode); int freeItem);
/*!
* \brief Removes all memory associated with list nodes. Does not free
* LinkedList *list.
*
* Precondition: The list has been initialized.
*
* \return 0 on success, EINVAL on failure.
*/
int ListDestroy(
/*! Must be valid, non null, pointer to a linked list. */
LinkedList *list,
/*! if !0 then item is freed using free function. If 0 (or free
* function is NULL) then item is not freed. */
int freeItem);
/**************************************************************************** /*!
* Function: ListDelNode * \brief Returns the head of the list.
* *
* Description: * Precondition: The list has been initialized.
* Removes a node from the list *
* The memory for the node is freed. * \return The head of the list. NULL if list is empty.
* Parameters: */
* LinkedList *list - must be valid, non null, pointer to a linked list. ListNode *ListHead(
* ListNode *dnode - done to delete. /*! Must be valid, non null, pointer to a linked list. */
* freeItem - if !0 then item is freed using free function. LinkedList *list);
* if 0 (or free function is NULL) then item is not freed
* Returns:
* The pointer to the item stored in the node or NULL if the item is freed.
* Precondition:
* The list has been initialized.
*****************************************************************************/
void *ListDelNode(LinkedList *list,ListNode *dnode, int freeItem);
/*!
* \brief Returns the tail of the list.
*
* Precondition: The list has been initialized.
*
* \return The tail of the list. NULL if list is empty.
*/
ListNode *ListTail(
/*! Must be valid, non null, pointer to a linked list. */
LinkedList *list);
/**************************************************************************** /*!
* Function: ListDestroy * \brief Returns the next item in the list.
* *
* Description: * Precondition: The list has been initialized.
* Removes all memory associated with list nodes.
* Does not free LinkedList *list.
* *
* Parameters: * \return The next item in the list. NULL if there are no more items in list.
* LinkedList *list - must be valid, non null, pointer to a linked list. */
* freeItem - if !0 then items are freed using the free_function. ListNode *ListNext(
* if 0 (or free function is NULL) then items are not freed. /*! Must be valid, non null, pointer to a linked list. */
* Returns: LinkedList *list,
* 0 on success. Always returns 0. /*! Node from the list. */
* Precondition: ListNode *node);
* The list has been initialized.
*****************************************************************************/
int ListDestroy(LinkedList *list, int freeItem);
/*!
* \brief Returns the previous item in the list.
*
* Precondition: The list has been initialized.
*
* \return The previous item in the list. NULL if there are no more items in list.
*/
ListNode *ListPrev(
/*! Must be valid, non null, pointer to a linked list. */
LinkedList *list,
/*! Node from the list. */
ListNode *node);
/**************************************************************************** /*!
* Function: ListHead * \brief Finds the specified item in the list.
* *
* Description:
* Returns the head of the list.
*
* Parameters:
* LinkedList *list - must be valid, non null, pointer to a linked list.
*
* Returns:
* The head of the list. NULL if list is empty.
* Precondition:
* The list has been initialized.
*****************************************************************************/
ListNode* ListHead(LinkedList *list);
/****************************************************************************
* Function: ListTail
*
* Description:
* Returns the tail of the list.
*
* Parameters:
* LinkedList *list - must be valid, non null, pointer to a linked list.
*
* Returns:
* The tail of the list. NULL if list is empty.
* Precondition:
* The list has been initialized.
*****************************************************************************/
ListNode* ListTail(LinkedList *list);
/****************************************************************************
* Function: ListNext
*
* Description:
* Returns the next item in the list.
*
* Parameters:
* LinkedList *list - must be valid, non null, pointer to a linked list.
*
* Returns:
* The next item in the list. NULL if there are no more items in list.
* Precondition:
* The list has been initialized.
*****************************************************************************/
ListNode* ListNext(LinkedList *list, ListNode * node);
/****************************************************************************
* Function: ListPrev
*
* Description:
* Returns the previous item in the list.
*
* Parameters:
* LinkedList *list - must be valid, non null, pointer to a linked list.
*
* Returns:
* The previous item in the list. NULL if there are no more items in list.
* Precondition:
* The list has been initialized.
*****************************************************************************/
ListNode* ListPrev(LinkedList *list, ListNode * node);
/****************************************************************************
* Function: ListFind
*
* Description:
* Finds the specified item in the list.
* Uses the compare function specified in ListInit. If compare function * Uses the compare function specified in ListInit. If compare function
* is NULL then compares items as pointers. * is NULL then compares items as pointers.
* Parameters:
* LinkedList *list - must be valid, non null, pointer to a linked list.
* ListNode *start - the node to start from, NULL if to start from
* beginning.
* void * item - the item to search for.
* Returns:
* The node containing the item. NULL if no node contains the item.
* Precondition:
* The list has been initialized.
*****************************************************************************/
ListNode* ListFind(LinkedList *list, ListNode *start, void * item);
/****************************************************************************
* Function: ListSize
* *
* Description: * Precondition: The list has been initialized.
* Returns the size of the list. *
* Parameters: * \return The node containing the item. NULL if no node contains the item.
* LinkedList *list - must be valid, non null, pointer to a linked list. */
ListNode* ListFind(
* Returns: /*! Must be valid, non null, pointer to a linked list. */
* The number of items in the list. LinkedList *list,
* Precondition: /*! The node to start from, NULL if to start from beginning. */
* The list has been initialized. ListNode *start,
*****************************************************************************/ /*! The item to search for. */
int ListSize(LinkedList* list); void *item);
/*!
* \brief Returns the size of the list.
*
* Precondition: The list has been initialized.
*
* \return The number of items in the list.
*/
long ListSize(
/*! Must be valid, non null, pointer to a linked list. */
LinkedList* list);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@@ -29,26 +29,21 @@
* *
******************************************************************************/ ******************************************************************************/
#ifndef THREADPOOL_H #ifndef THREADPOOL_H
#define THREADPOOL_H #define THREADPOOL_H
/*! /*!
* \file * \file
*/ */
#include "FreeList.h" #include "FreeList.h"
#include "ithread.h" #include "ithread.h"
#include "LinkedList.h" #include "LinkedList.h"
#include "UpnpInet.h" #include "UpnpInet.h"
#include "UpnpGlobal.h" /* for UPNP_INLINE, EXPORT_SPEC */ #include "UpnpGlobal.h" /* for UPNP_INLINE, EXPORT_SPEC */
#include <errno.h> #include <errno.h>
#ifdef WIN32 #ifdef WIN32
#include <time.h> #include <time.h>
struct timezone struct timezone
@@ -63,82 +58,63 @@
#if defined(__OSX__) || defined(__APPLE__) || defined(__NetBSD__) #if defined(__OSX__) || defined(__APPLE__) || defined(__NetBSD__)
#include <sys/resource.h> /* for setpriority() */ #include <sys/resource.h> /* for setpriority() */
#endif #endif
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/*! Size of job free list */ /*! Size of job free list */
#define JOBFREELISTSIZE 100 #define JOBFREELISTSIZE 100
#define INFINITE_THREADS -1 #define INFINITE_THREADS -1
#define EMAXTHREADS (-8 & 1<<29) #define EMAXTHREADS (-8 & 1<<29)
/*! Invalid Policy */ /*! Invalid Policy */
#define INVALID_POLICY (-9 & 1<<29) #define INVALID_POLICY (-9 & 1<<29)
/*! Invalid JOB Id */ /*! Invalid JOB Id */
#define INVALID_JOB_ID (-2 & 1<<29) #define INVALID_JOB_ID (-2 & 1<<29)
typedef enum duration { typedef enum duration {
SHORT_TERM, SHORT_TERM,
PERSISTENT PERSISTENT
} Duration; } Duration;
typedef enum priority { typedef enum priority {
LOW_PRIORITY, LOW_PRIORITY,
MED_PRIORITY, MED_PRIORITY,
HIGH_PRIORITY HIGH_PRIORITY
} ThreadPriority; } ThreadPriority;
/*! default priority used by TPJobInit */ /*! default priority used by TPJobInit */
#define DEFAULT_PRIORITY MED_PRIORITY #define DEFAULT_PRIORITY MED_PRIORITY
/*! default minimum used by TPAttrInit */ /*! default minimum used by TPAttrInit */
#define DEFAULT_MIN_THREADS 1 #define DEFAULT_MIN_THREADS 1
/*! default max used by TPAttrInit */ /*! default max used by TPAttrInit */
#define DEFAULT_MAX_THREADS 10 #define DEFAULT_MAX_THREADS 10
/*! default stack size used by TPAttrInit */ /*! default stack size used by TPAttrInit */
#define DEFAULT_STACK_SIZE 0 #define DEFAULT_STACK_SIZE 0
/*! default jobs per thread used by TPAttrInit */ /*! default jobs per thread used by TPAttrInit */
#define DEFAULT_JOBS_PER_THREAD 10 #define DEFAULT_JOBS_PER_THREAD 10
/*! default starvation time used by TPAttrInit */ /*! default starvation time used by TPAttrInit */
#define DEFAULT_STARVATION_TIME 500 #define DEFAULT_STARVATION_TIME 500
/*! default idle time used by TPAttrInit */ /*! default idle time used by TPAttrInit */
#define DEFAULT_IDLE_TIME 10 * 1000 #define DEFAULT_IDLE_TIME 10 * 1000
/*! default free routine used TPJobInit */ /*! default free routine used TPJobInit */
#define DEFAULT_FREE_ROUTINE NULL #define DEFAULT_FREE_ROUTINE NULL
/*! default max jobs used TPAttrInit */ /*! default max jobs used TPAttrInit */
#define DEFAULT_MAX_JOBS_TOTAL 100 #define DEFAULT_MAX_JOBS_TOTAL 100
/*! /*!
* \brief Statistics. * \brief Statistics.
* *
@@ -146,71 +122,43 @@ typedef enum priority {
*/ */
#define STATS 1 #define STATS 1
#ifdef _DEBUG #ifdef _DEBUG
#define DEBUG 1 #define DEBUG 1
#endif #endif
typedef int PolicyType; typedef int PolicyType;
#define DEFAULT_POLICY SCHED_OTHER #define DEFAULT_POLICY SCHED_OTHER
/*! Function for freeing a thread argument. */
/****************************************************************************
* Name: free_routine
*
* Description:
* Function for freeing a thread argument
*****************************************************************************/
typedef void (*free_routine)(void *arg); typedef void (*free_routine)(void *arg);
/**************************************************************************** /*! Attributes for thread pool. Used to set and change parameters of thread
* Name: ThreadPoolAttr * pool. */
*
* Description:
* Attributes for thread pool. Used to set and change parameters of
* thread pool
*****************************************************************************/
typedef struct THREADPOOLATTR typedef struct THREADPOOLATTR
{ {
/* minThreads, ThreadPool will always maintain at least this many threads */ /*! ThreadPool will always maintain at least this many threads. */
int minThreads; int minThreads;
/*! ThreadPool will never have more than this number of threads. */
/* maxThreads, ThreadPool will never have more than this number of threads */
int maxThreads; int maxThreads;
/*! This is the minimum stack size allocated for each thread. */
/* stackSize (in bytes), this is the minimum stack size allocated for each
* thread */
size_t stackSize; size_t stackSize;
/*! This is the maximum time a thread will
/* maxIdleTime (in milliseconds) this is the maximum time a thread will * remain idle before dying (in milliseconds). */
* remain idle before dying */
int maxIdleTime; int maxIdleTime;
/*! Jobs per thread to maintain. */
/* jobs per thread to maintain */
int jobsPerThread; int jobsPerThread;
/*! Maximum number of jobs that can be queued totally. */
/* maximum number of jobs that can be queued totally. */
int maxJobsTotal; int maxJobsTotal;
/*! the time a low priority or med priority job waits before getting
/* the time a low priority or med priority job waits before getting bumped * bumped up a priority (in milliseconds). */
* up a priority (in milliseconds) */
int starvationTime; int starvationTime;
/*! scheduling policy to use. */
/* scheduling policy to use */
PolicyType schedPolicy; PolicyType schedPolicy;
} ThreadPoolAttr; } ThreadPoolAttr;
/*! Internal ThreadPool Job. */
/****************************************************************************
* Name: ThreadPool
*
* Description:
* Internal ThreadPool Job
*****************************************************************************/
typedef struct THREADPOOLJOB typedef struct THREADPOOLJOB
{ {
start_routine func; start_routine func;
@@ -221,13 +169,7 @@ typedef struct THREADPOOLJOB
int jobId; int jobId;
} ThreadPoolJob; } ThreadPoolJob;
/*! Structure to hold statistics. */
/****************************************************************************
* Name: ThreadPoolStats
*
* Description:
* Structure to hold statistics
*****************************************************************************/
typedef struct TPOOLSTATS typedef struct TPOOLSTATS
{ {
double totalTimeHQ; double totalTimeHQ;
@@ -251,7 +193,6 @@ typedef struct TPOOLSTATS
int currentJobsMQ; int currentJobsMQ;
} ThreadPoolStats; } ThreadPoolStats;
/*! /*!
* \brief A thread pool similar to the thread pool in the UPnP SDK. * \brief A thread pool similar to the thread pool in the UPnP SDK.
* *
@@ -269,374 +210,324 @@ typedef struct TPOOLSTATS
*/ */
typedef struct THREADPOOL typedef struct THREADPOOL
{ {
ithread_mutex_t mutex; /* mutex to protect job qs */ /*! Mutex to protect job qs. */
ithread_cond_t condition; /* condition variable to signal Q */ ithread_mutex_t mutex;
ithread_cond_t start_and_shutdown; /* condition variable for start and stop */ /*! Condition variable to signal Q. */
int lastJobId; /* ids for jobs */ ithread_cond_t condition;
int shutdown; /* whether or not we are shutting down */ /*! Condition variable for start and stop. */
int totalThreads; /* total number of threads */ ithread_cond_t start_and_shutdown;
int busyThreads; /* number of threads that are currently executing jobs */ /*! ids for jobs */
int persistentThreads; /* number of persistent threads */ int lastJobId;
FreeList jobFreeList; /* free list of jobs */ /*! whether or not we are shutting down */
LinkedList lowJobQ; /* low priority job Q */ int shutdown;
LinkedList medJobQ; /* med priority job Q */ /*! total number of threads */
LinkedList highJobQ; /* high priority job Q */ int totalThreads;
ThreadPoolJob *persistentJob; /* persistent job */ /*! number of threads that are currently executing jobs */
ThreadPoolAttr attr; /* thread pool attributes */ int busyThreads;
/*! number of persistent threads */
/* statistics */ int persistentThreads;
/*! free list of jobs */
FreeList jobFreeList;
/*! low priority job Q */
LinkedList lowJobQ;
/*! med priority job Q */
LinkedList medJobQ;
/*! high priority job Q */
LinkedList highJobQ;
/*! persistent job */
ThreadPoolJob *persistentJob;
/*! thread pool attributes */
ThreadPoolAttr attr;
/*! statistics */
ThreadPoolStats stats; ThreadPoolStats stats;
} ThreadPool; } ThreadPool;
/*!
* \brief Initializes and starts ThreadPool. Must be called first and
* only once for ThreadPool.
*
* \return
* \li \c 0 on success.
* \li \c EAGAIN if not enough system resources to create minimum threads.
* \li \c INVALID_POLICY if schedPolicy can't be set.
* \li \c EMAXTHREADS if minimum threads is greater than maximum threads.
*/
int ThreadPoolInit(
/*! Must be valid, non null, pointer to ThreadPool. */
ThreadPool *tp,
/*! Can be null. if not null then attr contains the following fields:
* \li \c minWorkerThreads - minimum number of worker threads thread
* pool will never have less than this number of threads.
* \li \c maxWorkerThreads - maximum number of worker threads thread
* pool will never have more than this number of threads.
* \li \c maxIdleTime - maximum time that a worker thread will spend
* idle. If a worker is idle longer than this time and there are more
* than the min number of workers running, then the worker thread
* exits.
* \li \c jobsPerThread - ratio of jobs to thread to try and maintain
* if a job is scheduled and the number of jobs per thread is greater
* than this number,and if less than the maximum number of workers are
* running then a new thread is started to help out with efficiency.
* \li \c schedPolicy - scheduling policy to try and set (OS dependent).
*/
ThreadPoolAttr *attr);
/**************************************************************************** /*!
* Function: ThreadPoolInit * \brief Adds a persistent job to the thread pool.
* *
* Description: * Job will be run as soon as possible. Call will block until job is scheduled.
* Initializes and starts ThreadPool. Must be called first.
* And only once for ThreadPool.
* Parameters:
* tp - must be valid, non null, pointer to ThreadPool.
* attr - can be null
* *
* if not null then attr contains the following fields: * \return
* * \li \c 0 on success.
* minWorkerThreads - minimum number of worker threads * \li \c EOUTOFMEM not enough memory to add job.
* thread pool will never have less than this * \li \c EMAXTHREADS not enough threads to add persistent job.
* number of threads. */
* maxWorkerThreads - maximum number of worker threads int ThreadPoolAddPersistent(
* thread pool will never have more than this /*! Valid thread pool pointer. */
* number of threads. ThreadPool*tp,
* maxIdleTime - maximum time that a worker thread will spend /*! Valid thread pool job. */
* idle. If a worker is idle longer than this ThreadPoolJob *job,
* time and there are more than the min /*! . */
* number of workers running, than the int *jobId);
* worker thread exits.
* jobsPerThread - ratio of jobs to thread to try and maintain
* if a job is scheduled and the number of jobs per
* thread is greater than this number,and
* if less than the maximum number of
* workers are running then a new thread is
* started to help out with efficiency.
* schedPolicy - scheduling policy to try and set (OS dependent)
* Returns:
* 0 on success, nonzero on failure.
* EAGAIN if not enough system resources to create minimum threads.
* INVALID_POLICY if schedPolicy can't be set
* EMAXTHREADS if minimum threads is greater than maximum threads
*****************************************************************************/
int ThreadPoolInit(ThreadPool *tp, ThreadPoolAttr *attr);
/*!
/**************************************************************************** * \brief Gets the current set of attributes associated with the thread pool.
* Function: ThreadPoolAddPersistent
* *
* Description: * \return
* Adds a persistent job to the thread pool. * \li \c 0 on success, nonzero on failure.
* Job will be run as soon as possible. */
* Call will block until job is scheduled. int ThreadPoolGetAttr(
* Parameters: /*! valid thread pool pointer. */
* tp - valid thread pool pointer ThreadPool *tp,
* ThreadPoolJob - valid thread pool job with the following fields: /*! non null pointer to store attributes. */
* ThreadPoolAttr *out);
* func - ThreadFunction to run
* arg - argument to function.
* priority - priority of job.
*
* Returns:
* 0 on success, nonzero on failure
* EOUTOFMEM not enough memory to add job.
* EMAXTHREADS not enough threads to add persistent job.
*****************************************************************************/
int ThreadPoolAddPersistent(ThreadPool*tp, ThreadPoolJob *job, int *jobId);
/*!
/**************************************************************************** * \brief Sets the attributes for the thread pool.
* Function: ThreadPoolGetAttr
*
* Description:
* Gets the current set of attributes
* associated with the thread pool.
* Parameters:
* tp - valid thread pool pointer
* out - non null pointer to store attributes
* Returns:
* 0 on success, nonzero on failure
* Always returns 0.
*****************************************************************************/
int ThreadPoolGetAttr(ThreadPool *tp, ThreadPoolAttr *out);
/****************************************************************************
* Function: ThreadPoolSetAttr
*
* Description:
* Sets the attributes for the thread pool.
* Only affects future calculations. * Only affects future calculations.
* Parameters:
* tp - valid thread pool pointer
* attr - pointer to attributes, null sets attributes to default.
* Returns:
* 0 on success, nonzero on failure
* Returns INVALID_POLICY if policy can not be set.
*****************************************************************************/
int ThreadPoolSetAttr(ThreadPool *tp, ThreadPoolAttr *attr);
/****************************************************************************
* Function: ThreadPoolAdd
* *
* Description: * \return
* Adds a job to the thread pool. * \li \c 0 on success, nonzero on failure.
* Job will be run as soon as possible. * \li \c INVALID_POLICY if policy can not be set.
* Parameters: */
* tp - valid thread pool pointer int ThreadPoolSetAttr(
* func - ThreadFunction to run /*! valid thread pool pointer. */
* arg - argument to function. ThreadPool *tp,
* priority - priority of job. /*! pointer to attributes, null sets attributes to default. */
* poolid - id of job ThreadPoolAttr *attr);
* free_function - function to use when freeing argument
* Returns:
* 0 on success, nonzero on failure
* EOUTOFMEM if not enough memory to add job.
*****************************************************************************/
int ThreadPoolAdd (ThreadPool*tp, ThreadPoolJob *job, int *jobId);
/*!
/**************************************************************************** * \brief Adds a job to the thread pool. Job will be run as soon as possible.
* Function: ThreadPoolRemove
* *
* Description: * \return
* Removes a job from the thread pool. * \li \c 0 on success, nonzero on failure.
* Can only remove jobs which are not * \li \c EOUTOFMEM if not enough memory to add job.
* currently running. */
* Parameters: int ThreadPoolAdd(
* tp - valid thread pool pointer /*! valid thread pool pointer. */
* jobid - id of job ThreadPool*tp,
* out - space for removed job. /*! . */
* Returns: ThreadPoolJob *job,
* 0 on success, nonzero on failure. /*! id of job. */
* INVALID_JOB_ID if job not found. int *jobId);
*****************************************************************************/
int ThreadPoolRemove(ThreadPool *tp, int jobId, ThreadPoolJob *out);
/*!
* \brief Removes a job from the thread pool. Can only remove jobs which
/**************************************************************************** * are not currently running.
* Function: ThreadPoolShutdown
* *
* Description: * \return
* Shuts the thread pool down. * \li \c 0 on success, nonzero on failure.
* Waits for all threads to finish. * \li \c INVALID_JOB_ID if job not found.
* May block indefinitely if jobs do not */
* exit. int ThreadPoolRemove(
* Parameters: /*! valid thread pool pointer. */
* tp - must be valid tp ThreadPool *tp,
* Returns: /*! id of job. */
* 0 on success, nonzero on failure int jobId,
* Always returns 0. /*! space for removed job. */
*****************************************************************************/ ThreadPoolJob *out);
int ThreadPoolShutdown(ThreadPool *tp);
/*!
/**************************************************************************** * \brief Shuts the thread pool down. Waits for all threads to finish.
* Function: TPJobInit * May block indefinitely if jobs do not exit.
* *
* Description: * \return 0 on success, nonzero on failure
* Initializes thread pool job. */
* Sets the priority to default defined in ThreadPool.h. int ThreadPoolShutdown(
* Sets the free_routine to default defined in ThreadPool.h /*! must be valid tp. */
* Parameters: ThreadPool *tp);
* ThreadPoolJob *job - must be valid thread pool attributes.
* start_routine func - function to run, must be valid
* void * arg - argument to pass to function.
* Returns:
* Always returns 0.
*****************************************************************************/
int TPJobInit(ThreadPoolJob *job, start_routine func, void *arg);
/*!
/**************************************************************************** * \brief Initializes thread pool job. Sets the priority to default defined
* Function: TPJobSetPriority * in ThreadPool.h. Sets the free_routine to default defined in ThreadPool.h.
* *
* Description: * \return Always returns 0.
* Sets the max threads for the thread pool attributes. */
* Parameters: int TPJobInit(
* attr - must be valid thread pool attributes. /*! must be valid thread pool attributes. */
* maxThreads - value to set ThreadPoolJob *job,
* Returns: /*! function to run, must be valid. */
* Always returns 0. start_routine func,
*****************************************************************************/ /*! argument to pass to function. */
int TPJobSetPriority(ThreadPoolJob *job, ThreadPriority priority); void *arg);
/*!
/**************************************************************************** * \brief Sets the max threads for the thread pool attributes.
* Function: TPJobSetFreeFunction
* *
* Description: * \return Always returns 0.
* Sets the max threads for the thread pool attributes. */
* Parameters: int TPJobSetPriority(
* attr - must be valid thread pool attributes. /*! must be valid thread pool attributes. */
* maxThreads - value to set ThreadPoolJob *job,
* Returns: /*! value to set. */
* Always returns 0. ThreadPriority priority);
*****************************************************************************/
int TPJobSetFreeFunction(ThreadPoolJob *job, free_routine func);
/*!
/**************************************************************************** * \brief Sets the max threads for the thread pool attributes.
* Function: TPAttrInit
* *
* Description: * \return Always returns 0.
* Initializes thread pool attributes. */
* Sets values to defaults defined in ThreadPool.h. int TPJobSetFreeFunction(
* Parameters: /*! must be valid thread pool attributes. */
* attr - must be valid thread pool attributes. ThreadPoolJob *job,
* Returns: /*! value to set. */
* Always returns 0. free_routine func);
*****************************************************************************/
int TPAttrInit(ThreadPoolAttr *attr);
/*!
/**************************************************************************** * \brief Initializes thread pool attributes. Sets values to defaults defined
* Function: TPAttrSetMaxThreads * in ThreadPool.h.
* *
* Description: * \return Always returns 0.
* Sets the max threads for the thread pool attributes. */
* Parameters: int TPAttrInit(
* attr - must be valid thread pool attributes. /*! must be valid thread pool attributes. */
* maxThreads - value to set ThreadPoolAttr *attr);
* Returns:
* Always returns 0.
*****************************************************************************/
int TPAttrSetMaxThreads(ThreadPoolAttr *attr, int maxThreads);
/*!
/**************************************************************************** * \brief Sets the max threads for the thread pool attributes.
* Function: TPAttrSetMinThreads
* *
* Description: * \return Always returns 0.
* Sets the min threads for the thread pool attributes. */
* Parameters: int TPAttrSetMaxThreads(
* attr - must be valid thread pool attributes. /*! must be valid thread pool attributes. */
* minThreads - value to set ThreadPoolAttr *attr,
* Returns: /*! value to set. */
* Always returns 0. int maxThreads);
*****************************************************************************/
int TPAttrSetMinThreads(ThreadPoolAttr *attr, int minThreads);
/*!
/**************************************************************************** * \brief Sets the min threads for the thread pool attributes.
* Function: TPAttrSetStackSize
* *
* Description: * \return Always returns 0.
* Sets the stack size for the thread pool attributes. */
* Parameters: int TPAttrSetMinThreads(
* attr - must be valid thread pool attributes. /*! must be valid thread pool attributes. */
* stackSize - value to set ThreadPoolAttr *attr,
* Returns: /*! value to set. */
* Always returns 0. int minThreads);
*****************************************************************************/
int TPAttrSetStackSize(ThreadPoolAttr *attr, size_t stackSize);
/*!
/**************************************************************************** * \brief Sets the stack size for the thread pool attributes.
* Function: TPAttrSetIdleTime
* *
* Description: * \return Always returns 0.
* Sets the idle time for the thread pool attributes. */
* Parameters: int TPAttrSetStackSize(
* attr - must be valid thread pool attributes. /*! must be valid thread pool attributes. */
* Returns: ThreadPoolAttr *attr,
* Always returns 0. /*! value to set. */
*****************************************************************************/ size_t stackSize);
int TPAttrSetIdleTime(ThreadPoolAttr *attr, int idleTime);
/*!
/**************************************************************************** * \brief Sets the idle time for the thread pool attributes.
* Function: TPAttrSetJobsPerThread
* *
* Description: * \return Always returns 0.
* Sets the jobs per thread ratio */
* Parameters: int TPAttrSetIdleTime(
* attr - must be valid thread pool attributes. /*! must be valid thread pool attributes. */
* jobsPerThread - number of jobs per thread to maintain ThreadPoolAttr *attr,
* Returns: /*! . */
* Always returns 0. int idleTime);
*****************************************************************************/
int TPAttrSetJobsPerThread(ThreadPoolAttr *attr, int jobsPerThread);
/*!
/**************************************************************************** * \brief Sets the jobs per thread ratio
* Function: TPAttrSetStarvationTime
* *
* Description: * \return Always returns 0.
* Sets the starvation time for the thread pool attributes. */
* Parameters: int TPAttrSetJobsPerThread(
* attr - must be valid thread pool attributes. /*! must be valid thread pool attributes. */
* int starvationTime - milliseconds ThreadPoolAttr *attr,
* Returns: /*! number of jobs per thread to maintain. */
* Always returns 0. int jobsPerThread);
*****************************************************************************/
int TPAttrSetStarvationTime(ThreadPoolAttr *attr, int starvationTime);
/*!
/**************************************************************************** * \brief Sets the starvation time for the thread pool attributes.
* Function: TPAttrSetSchedPolicy
* *
* Description: * \return Always returns 0.
* Sets the scheduling policy for the thread pool attributes. */
* Parameters: int TPAttrSetStarvationTime(
* attr - must be valid thread pool attributes. /*! must be valid thread pool attributes. */
* PolicyType schedPolicy - must be a valid policy type. ThreadPoolAttr *attr,
* Returns: /*! milliseconds. */
* Always returns 0. int starvationTime);
*****************************************************************************/
int TPAttrSetSchedPolicy(ThreadPoolAttr *attr, PolicyType schedPolicy);
/*!
/**************************************************************************** * \brief Sets the scheduling policy for the thread pool attributes.
* Function: TPAttrSetMaxJobsTotal
* *
* Description: * \return Always returns 0.
* Sets the maximum number jobs that can be qeued totally. */
* Parameters: int TPAttrSetSchedPolicy(
* attr - must be valid thread pool attributes. /*! must be valid thread pool attributes. */
* maxJobsTotal - maximum number of jobs ThreadPoolAttr *attr,
* Returns: /*! must be a valid policy type. */
* Always returns 0. PolicyType schedPolicy);
*****************************************************************************/
int TPAttrSetMaxJobsTotal(ThreadPoolAttr *attr, int maxJobsTotal);
/*!
/**************************************************************************** * \brief Sets the maximum number jobs that can be qeued totally.
* Function: ThreadPoolGetStats *
* \return Always returns 0.
*/
int TPAttrSetMaxJobsTotal(
/*! must be valid thread pool attributes. */
ThreadPoolAttr *attr,
/*! maximum number of jobs. */
int maxJobsTotal);
/*!
* \brief Returns various statistics about the thread pool.
* *
* Description:
* Returns various statistics about the
* thread pool.
* Only valid if STATS has been defined. * Only valid if STATS has been defined.
* Parameters: *
* ThreadPool *tp - valid initialized threadpool * \return Always returns 0.
* ThreadPoolStats *stats - valid stats, out parameter */
* Returns:
* Always returns 0.
*****************************************************************************/
#ifdef STATS #ifdef STATS
EXPORT_SPEC int ThreadPoolGetStats(ThreadPool *tp, ThreadPoolStats *stats); EXPORT_SPEC int ThreadPoolGetStats(
/*! Valid initialized threadpool. */
EXPORT_SPEC void ThreadPoolPrintStats(ThreadPoolStats *stats); ThreadPool *tp,
/*! Valid stats, out parameter. */
ThreadPoolStats *stats);
#else #else
static UPNP_INLINE int ThreadPoolGetStats(ThreadPool *tp, ThreadPoolStats *stats) {} static UPNP_INLINE int ThreadPoolGetStats(
/*! Valid initialized threadpool. */
static UPNP_INLINE void ThreadPoolPrintStats(ThreadPoolStats *stats) {} ThreadPool *tp,
/*! Valid stats, out parameter. */
ThreadPoolStats *stats) {}
#endif #endif
/*!
* \brief
*/
#ifdef STATS
EXPORT_SPEC void ThreadPoolPrintStats(
/*! . */
ThreadPoolStats *stats);
#else
static UPNP_INLINE void ThreadPoolPrintStats(
/*! . */
ThreadPoolStats *stats) {}
#endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* THREADPOOL_H */ #endif /* THREADPOOL_H */

View File

@@ -29,35 +29,31 @@
* *
******************************************************************************/ ******************************************************************************/
#ifndef TIMERTHREAD_H #ifndef TIMERTHREAD_H
#define TIMERTHREAD_H #define TIMERTHREAD_H
/*! /*!
* \file * \file
*/ */
#include "FreeList.h" #include "FreeList.h"
#include "ithread.h" #include "ithread.h"
#include "LinkedList.h" #include "LinkedList.h"
#include "ThreadPool.h" #include "ThreadPool.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#define INVALID_EVENT_ID (-10 & 1<<29) #define INVALID_EVENT_ID (-10 & 1<<29)
/*! Timeout Types. */
/* Timeout Types */ typedef enum timeoutType {
/* absolute means in seconds from Jan 1, 1970 */ /*! seconds from Jan 1, 1970. */
/* relative means in seconds from current time */ ABS_SEC,
typedef enum timeoutType {ABS_SEC,REL_SEC} TimeoutType; /*! seconds from current time. */
REL_SEC
} TimeoutType;
/*! /*!
* A timer thread similar to the one in the Upnp SDK that allows * A timer thread similar to the one in the Upnp SDK that allows
@@ -79,7 +75,6 @@ typedef struct TIMERTHREAD
ThreadPool *tp; ThreadPool *tp;
} TimerThread; } TimerThread;
/*! /*!
* Struct to contain information for a timer event. * Struct to contain information for a timer event.
* *
@@ -95,7 +90,6 @@ typedef struct TIMEREVENT
int id; int id;
} TimerEvent; } TimerEvent;
/*! /*!
* \brief Initializes and starts timer thread. * \brief Initializes and starts timer thread.
* *
@@ -109,7 +103,6 @@ int TimerThreadInit(
* lifetime of timer. Timer must be shutdown BEFORE thread pool. */ * lifetime of timer. Timer must be shutdown BEFORE thread pool. */
ThreadPool *tp); ThreadPool *tp);
/*! /*!
* \brief Schedules an event to run at a specified time. * \brief Schedules an event to run at a specified time.
* *
@@ -132,7 +125,6 @@ int TimerThreadSchedule(
/*! [in] Id of timer event. (out, can be null). */ /*! [in] Id of timer event. (out, can be null). */
int *id); int *id);
/*! /*!
* \brief Removes an event from the timer Q. * \brief Removes an event from the timer Q.
* *
@@ -148,7 +140,6 @@ int TimerThreadRemove(
/*! [in] Space for thread pool job. */ /*! [in] Space for thread pool job. */
ThreadPoolJob *out); ThreadPoolJob *out);
/*! /*!
* \brief Shutdown the timer thread. * \brief Shutdown the timer thread.
* *
@@ -162,7 +153,6 @@ int TimerThreadShutdown(
/*! [in] Valid timer thread pointer. */ /*! [in] Valid timer thread pointer. */
TimerThread *timer); TimerThread *timer);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@@ -65,7 +65,7 @@ extern "C" {
#endif #endif
#ifdef PTHREAD_MUTEX_RECURSIVE #if defined(PTHREAD_MUTEX_RECURSIVE) || defined(__DragonFly__)
/* This system has SuS2-compliant mutex attributes. /* This system has SuS2-compliant mutex attributes.
* E.g. on Cygwin, where we don't have the old nonportable (NP) symbols * E.g. on Cygwin, where we don't have the old nonportable (NP) symbols
*/ */
@@ -189,6 +189,9 @@ typedef pthread_rwlockattr_t ithread_rwlockattr_t;
***************************************************************************/ ***************************************************************************/
#if UPNP_USE_RWLOCK #if UPNP_USE_RWLOCK
typedef pthread_rwlock_t ithread_rwlock_t; typedef pthread_rwlock_t ithread_rwlock_t;
#else
/* Read-write locks aren't available: use mutex instead. */
typedef ithread_mutex_t ithread_rwlock_t;
#endif /* UPNP_USE_RWLOCK */ #endif /* UPNP_USE_RWLOCK */
@@ -333,11 +336,11 @@ static UPNP_INLINE int ithread_cleanup_thread(void) {
* Returns EINVAL if the kind is not supported. * Returns EINVAL if the kind is not supported.
* See man page for pthread_mutexattr_setkind_np * See man page for pthread_mutexattr_setkind_np
*****************************************************************************/ *****************************************************************************/
#ifdef PTHREAD_MUTEX_RECURSIVE #if defined(PTHREAD_MUTEX_RECURSIVE) || defined(__DragonFly__)
#define ithread_mutexattr_setkind_np pthread_mutexattr_settype #define ithread_mutexattr_setkind_np pthread_mutexattr_settype
#else #else
#define ithread_mutexattr_setkind_np pthread_mutexattr_setkind_np #define ithread_mutexattr_setkind_np pthread_mutexattr_setkind_np
#endif #endif /* UPNP_USE_RWLOCK */
/**************************************************************************** /****************************************************************************
* Function: ithread_mutexattr_getkind_np * Function: ithread_mutexattr_getkind_np
@@ -358,11 +361,11 @@ static UPNP_INLINE int ithread_cleanup_thread(void) {
* Always returns 0. * Always returns 0.
* See man page for pthread_mutexattr_getkind_np * See man page for pthread_mutexattr_getkind_np
*****************************************************************************/ *****************************************************************************/
#ifdef PTHREAD_MUTEX_RECURSIVE #if defined(PTHREAD_MUTEX_RECURSIVE) || defined(__DragonFly__)
#define ithread_mutexattr_getkind_np pthread_mutexattr_gettype #define ithread_mutexattr_getkind_np pthread_mutexattr_gettype
#else #else
#define ithread_mutexattr_getkind_np pthread_mutexattr_getkind_np #define ithread_mutexattr_getkind_np pthread_mutexattr_getkind_np
#endif #endif /* UPNP_USE_RWLOCK */
/**************************************************************************** /****************************************************************************
@@ -536,8 +539,10 @@ static UPNP_INLINE int ithread_cleanup_thread(void) {
*****************************************************************************/ *****************************************************************************/
#if UPNP_USE_RWLOCK #if UPNP_USE_RWLOCK
#define ithread_rwlock_init pthread_rwlock_init #define ithread_rwlock_init pthread_rwlock_init
#endif /* UPNP_USE_RWLOCK */ #else
/* Read-write locks aren't available: use mutex instead. */
#define ithread_rwlock_init ithread_mutex_init
#endif
/**************************************************************************** /****************************************************************************
* Function: ithread_rwlock_rdlock * Function: ithread_rwlock_rdlock
@@ -555,9 +560,11 @@ static UPNP_INLINE int ithread_cleanup_thread(void) {
*****************************************************************************/ *****************************************************************************/
#if UPNP_USE_RWLOCK #if UPNP_USE_RWLOCK
#define ithread_rwlock_rdlock pthread_rwlock_rdlock #define ithread_rwlock_rdlock pthread_rwlock_rdlock
#else
/* Read-write locks aren't available: use mutex instead. */
#define ithread_rwlock_rdlock ithread_mutex_lock
#endif /* UPNP_USE_RWLOCK */ #endif /* UPNP_USE_RWLOCK */
/**************************************************************************** /****************************************************************************
* Function: ithread_rwlock_wrlock * Function: ithread_rwlock_wrlock
* *
@@ -574,6 +581,9 @@ static UPNP_INLINE int ithread_cleanup_thread(void) {
*****************************************************************************/ *****************************************************************************/
#if UPNP_USE_RWLOCK #if UPNP_USE_RWLOCK
#define ithread_rwlock_wrlock pthread_rwlock_wrlock #define ithread_rwlock_wrlock pthread_rwlock_wrlock
#else
/* Read-write locks aren't available: use mutex instead. */
#define ithread_rwlock_wrlock ithread_mutex_lock
#endif /* UPNP_USE_RWLOCK */ #endif /* UPNP_USE_RWLOCK */
@@ -594,6 +604,9 @@ static UPNP_INLINE int ithread_cleanup_thread(void) {
*****************************************************************************/ *****************************************************************************/
#if UPNP_USE_RWLOCK #if UPNP_USE_RWLOCK
#define ithread_rwlock_unlock pthread_rwlock_unlock #define ithread_rwlock_unlock pthread_rwlock_unlock
#else
/* Read-write locks aren't available: use mutex instead. */
#define ithread_rwlock_unlock ithread_mutex_unlock
#endif /* UPNP_USE_RWLOCK */ #endif /* UPNP_USE_RWLOCK */
@@ -615,6 +628,9 @@ static UPNP_INLINE int ithread_cleanup_thread(void) {
*****************************************************************************/ *****************************************************************************/
#if UPNP_USE_RWLOCK #if UPNP_USE_RWLOCK
#define ithread_rwlock_destroy pthread_rwlock_destroy #define ithread_rwlock_destroy pthread_rwlock_destroy
#else
/* Read-write locks aren't available: use mutex instead. */
#define ithread_rwlock_destroy ithread_mutex_destroy
#endif /* UPNP_USE_RWLOCK */ #endif /* UPNP_USE_RWLOCK */
@@ -917,7 +933,7 @@ static UPNP_INLINE int ithread_cleanup_thread(void) {
#endif #endif
#ifndef PTHREAD_MUTEX_RECURSIVE #if !defined(PTHREAD_MUTEX_RECURSIVE) && !defined(__DragonFly__)
/* NK: Added for satisfying the gcc compiler */ /* NK: Added for satisfying the gcc compiler */
EXPORT_SPEC int pthread_mutexattr_setkind_np(pthread_mutexattr_t *attr, int kind); EXPORT_SPEC int pthread_mutexattr_setkind_np(pthread_mutexattr_t *attr, int kind);
#endif #endif

View File

@@ -1,85 +1,54 @@
/////////////////////////////////////////////////////////////////////////// /**************************************************************************
// *
// Copyright (c) 2000-2003 Intel Corporation * Copyright (c) 2000-2003 Intel Corporation
// All rights reserved. * All rights reserved.
// *
// Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
// *
// * Redistributions of source code must retain the above copyright notice, * - Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer. * this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice, * - Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation * this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution. * and/or other materials provided with the distribution.
// * Neither name of Intel Corporation nor the names of its contributors * - Neither name of Intel Corporation nor the names of its contributors
// may be used to endorse or promote products derived from this software * may be used to endorse or promote products derived from this software
// without specific prior written permission. * without specific prior written permission.
// *
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// *
/////////////////////////////////////////////////////////////////////////// **************************************************************************/
#include "FreeList.h" #include "FreeList.h"
#include <assert.h> #include <assert.h>
#include <stdlib.h> #include <stdlib.h>
/**************************************************************************** int FreeListInit(FreeList *free_list, size_t elementSize, int maxFreeListLength)
* Function: FreeListInit
*
* Description:
* Initializes Free List. Must be called first.
* And only once for FreeList.
* Parameters:
* free_list - must be valid, non null, pointer to a linked list.
* size_t - size of elements to store in free list
* maxFreeListSize - max size that the free list can grow to
* before returning memory to O.S.
* Returns:
* 0 on success. Nonzero on failure.
* Always returns 0.
*****************************************************************************/
int
FreeListInit( FreeList * free_list,
size_t elementSize,
int maxFreeListLength )
{ {
assert(free_list != NULL); assert(free_list != NULL);
if (free_list == NULL) if (free_list == NULL)
return EINVAL; return EINVAL;
free_list->element_size = elementSize; free_list->element_size = elementSize;
free_list->maxFreeListLength = maxFreeListLength; free_list->maxFreeListLength = maxFreeListLength;
free_list->head = NULL; free_list->head = NULL;
free_list->freeListLength = 0; free_list->freeListLength = 0;
return 0; return 0;
} }
/**************************************************************************** void *FreeListAlloc(FreeList *free_list)
* Function: FreeListAlloc
*
* Description:
* Allocates chunk of set size.
* If a free item is available in the list, returnes the stored item.
* Otherwise calls the O.S. to allocate memory.
* Parameters:
* free_list - must be valid, non null, pointer to a linked list.
* Returns:
* Non NULL on success. NULL on failure.
*****************************************************************************/
void *
FreeListAlloc( FreeList * free_list )
{ {
FreeListNode *ret = NULL; FreeListNode *ret = NULL;
@@ -99,79 +68,44 @@ FreeListAlloc( FreeList * free_list )
return ret; return ret;
} }
/**************************************************************************** int FreeListFree(FreeList *free_list, void *element)
* Function: FreeListFree
*
* Description:
* Returns an item to the Free List.
* If the free list is smaller than the max size than
* adds the item to the free list.
* Otherwise returns the item to the O.S.
* Parameters:
* free_list - must be valid, non null, pointer to a free list.
* element - must be a pointer allocated by FreeListAlloc
* Returns:
* 0 on success. Nonzero on failure.
* Always returns 0.
*****************************************************************************/
int
FreeListFree( FreeList * free_list,
void *element )
{ {
FreeListNode *temp = NULL; FreeListNode *temp = NULL;
assert(free_list != NULL); assert(free_list != NULL);
if (free_list == NULL) if (free_list == NULL)
return EINVAL; return EINVAL;
if (element != NULL &&
if( ( element != NULL ) && free_list->freeListLength + 1 < free_list->maxFreeListLength) {
( ( free_list->freeListLength + 1 ) <
free_list->maxFreeListLength ) ) {
free_list->freeListLength++; free_list->freeListLength++;
temp = (FreeListNode *)element; temp = (FreeListNode *)element;
temp->next = free_list->head; temp->next = free_list->head;
free_list->head = temp; free_list->head = temp;
} else { } else {
free(element); free(element);
} }
return 0; return 0;
} }
/**************************************************************************** int FreeListDestroy(FreeList *free_list)
* Function: FreeListDestroy
*
* Description:
* Releases the resources stored with the free list.
* Parameters:
* free_list - must be valid, non null, pointer to a linked list.
* Returns:
* 0 on success. Nonzero on failure.
* Always returns 0.
*****************************************************************************/
int
FreeListDestroy( FreeList * free_list )
{ {
FreeListNode *temp = NULL; FreeListNode *temp = NULL;
int i = 0; int i = 0;
assert(free_list != NULL); assert(free_list != NULL);
if( free_list == NULL ) if (!free_list)
return EINVAL; return EINVAL;
while (free_list->head) { while (free_list->head) {
i++; i++;
temp = free_list->head->next; temp = free_list->head->next;
free(free_list->head); free(free_list->head);
free_list->head = temp; free_list->head = temp;
} }
free_list->freeListLength = 0; free_list->freeListLength = 0;
return 0; return 0;
} }

View File

@@ -29,52 +29,43 @@
* *
**************************************************************************/ **************************************************************************/
#include "LinkedList.h" #include "LinkedList.h"
#ifdef WIN32 #ifdef WIN32
/* Do not #include <sys/param.h> */ /* Do not #include <sys/param.h> */
#else #else
#include <sys/param.h> #include <sys/param.h>
#endif #endif
#if (defined(BSD) && BSD >= 199306) || defined(__OSX__) || defined(__APPLE__) #if (defined(BSD) && BSD >= 199306) || defined(__OSX__) || defined(__APPLE__)
#include <stdlib.h> #include <stdlib.h>
#else #else
#include <malloc.h> #include <malloc.h>
#endif #endif
#include <assert.h> #include <assert.h>
static int freeListNode(ListNode *node, LinkedList *list)
static int
freeListNode( ListNode * node,
LinkedList * list )
{ {
assert(list != NULL); assert(list != NULL);
return FreeListFree(&list->freeNodeList, node); return FreeListFree(&list->freeNodeList, node);
} }
/**************************************************************************** /*!
* Function: CreateListNode * \brief Dynamically creates a list node.
*
* Description:
* Creates a list node. Dynamically.
* *
* Parameters: * Parameters:
* void * item - the item to store * void * item - the item to store
* Returns: * Returns:
* The new node, NULL on failure. * The new node, NULL on failure.
*****************************************************************************/ */
static ListNode * static ListNode *CreateListNode(
CreateListNode( void *item, /*! the item to store. */
void *item,
/*! The list to add it to. */
LinkedList *list) LinkedList *list)
{ {
ListNode *temp = NULL; ListNode *temp = NULL;
assert(list != NULL); assert(list != NULL);
@@ -85,49 +76,28 @@ CreateListNode( void *item,
temp->next = NULL; temp->next = NULL;
temp->item = item; temp->item = item;
} }
return temp; return temp;
} }
/**************************************************************************** int ListInit(LinkedList *list, cmp_routine cmp_func, free_function free_func)
* Function: ListInit
*
* Description:
* Initializes LinkedList. Must be called first.
* And only once for List.
* Parameters:
* list - must be valid, non null, pointer to a linked list.
* cmp_func - function used to compare items. (May be NULL)
* free_func - function used to free items. (May be NULL)
* Returns:
* 0 on success, EOUTOFMEM on failure.
*****************************************************************************/
int
ListInit( LinkedList * list,
cmp_routine cmp_func,
free_function free_func )
{ {
int retCode = 0; int retCode = 0;
assert(list != NULL); assert(list != NULL);
if( list == NULL ) if (!list)
return EINVAL; return EINVAL;
list->size = 0; list->size = 0;
list->cmp_func = cmp_func; list->cmp_func = cmp_func;
list->free_func = free_func; list->free_func = free_func;
retCode = FreeListInit(&list->freeNodeList, sizeof(ListNode), FREELISTSIZE);
retCode =
FreeListInit( &list->freeNodeList, sizeof( ListNode ),
FREELISTSIZE );
assert(retCode == 0); assert(retCode == 0);
list->head.item = NULL; list->head.item = NULL;
list->head.next = &list->tail; list->head.next = &list->tail;
list->head.prev = NULL; list->head.prev = NULL;
list->tail.item = NULL; list->tail.item = NULL;
list->tail.prev = &list->head; list->tail.prev = &list->head;
list->tail.next = NULL; list->tail.next = NULL;
@@ -135,23 +105,7 @@ ListInit( LinkedList * list,
return 0; return 0;
} }
/**************************************************************************** ListNode *ListAddHead(LinkedList *list, void *item)
* Function: ListAddHead
*
* Description:
* Adds a node to the head of the list.
* Node gets immediately after list.head.
* Parameters:
* LinkedList *list - must be valid, non null, pointer to a linked list.
* void * item - item to be added
* Returns:
* The pointer to the ListNode on success, NULL on failure.
* Precondition:
* The list has been initialized.
*****************************************************************************/
ListNode *
ListAddHead( LinkedList * list,
void *item )
{ {
assert(list != NULL); assert(list != NULL);
@@ -161,59 +115,24 @@ ListAddHead( LinkedList * list,
return ListAddAfter(list, item, &list->head); return ListAddAfter(list, item, &list->head);
} }
/**************************************************************************** ListNode *ListAddTail(LinkedList *list, void *item)
* Function: ListAddTail
*
* Description:
* Adds a node to the tail of the list.
* Node gets added immediately before list.tail.
* Parameters:
* LinkedList *list - must be valid, non null, pointer to a linked list.
* void * item - item to be added
* Returns:
* The pointer to the ListNode on success, NULL on failure.
* Precondition:
* The list has been initialized.
*****************************************************************************/
ListNode *
ListAddTail( LinkedList * list,
void *item )
{ {
assert(list != NULL); assert(list != NULL);
if( list == NULL ) if (!list)
return NULL; return NULL;
return ListAddBefore(list, item, &list->tail); return ListAddBefore(list, item, &list->tail);
} }
/**************************************************************************** ListNode *ListAddAfter(LinkedList *list, void *item, ListNode *bnode)
* Function: ListAddAfter
*
* Description:
* Adds a node after the specified node.
* Node gets added immediately after bnode.
* Parameters:
* LinkedList *list - must be valid, non null, pointer to a linked list.
* void * item - item to be added
* ListNode * bnode - node to add after
* Returns:
* The pointer to the ListNode on success, NULL on failure.
* Precondition:
* The list has been initialized.
*****************************************************************************/
ListNode *
ListAddAfter( LinkedList * list,
void *item,
ListNode * bnode )
{ {
ListNode *newNode = NULL; ListNode *newNode = NULL;
assert(list != NULL); assert(list != NULL);
if( ( list == NULL ) || ( bnode == NULL ) ) if (!list || !bnode)
return NULL; return NULL;
newNode = CreateListNode(item, list); newNode = CreateListNode(item, list);
if (newNode) { if (newNode) {
ListNode *temp = bnode->next; ListNode *temp = bnode->next;
@@ -223,40 +142,22 @@ ListAddAfter( LinkedList * list,
newNode->next = temp; newNode->next = temp;
temp->prev = newNode; temp->prev = newNode;
list->size++; list->size++;
return newNode; return newNode;
} }
return NULL; return NULL;
} }
/**************************************************************************** ListNode *ListAddBefore(LinkedList *list, void *item, ListNode *anode)
* Function: ListAddBefore
*
* Description:
* Adds a node before the specified node.
* Node gets added immediately before anode.
* Parameters:
* LinkedList *list - must be valid, non null, pointer to a linked list.
* ListNode * anode - node to add the in front of.
* void * item - item to be added
* Returns:
* The pointer to the ListNode on success, NULL on failure.
* Precondition:
* The list has been initialized.
*****************************************************************************/
ListNode *
ListAddBefore( LinkedList * list,
void *item,
ListNode * anode )
{ {
ListNode *newNode = NULL; ListNode *newNode = NULL;
assert(list != NULL); assert(list != NULL);
if( ( list == NULL ) || ( anode == NULL ) ) if (!list || !anode)
return NULL; return NULL;
newNode = CreateListNode(item, list); newNode = CreateListNode(item, list);
if (newNode) { if (newNode) {
ListNode *temp = anode->prev; ListNode *temp = anode->prev;
@@ -265,30 +166,14 @@ ListAddBefore( LinkedList * list,
newNode->prev = temp; newNode->prev = temp;
temp->next = newNode; temp->next = newNode;
list->size++; list->size++;
return newNode; return newNode;
} }
return NULL; return NULL;
} }
/**************************************************************************** void *ListDelNode(LinkedList *list, ListNode *dnode, int freeItem)
* Function: ListDelNode
*
* Description:
* Removes a node from the list
* The memory for the node is freed but the
* the memory for the items are not.
* Parameters:
* LinkedList *list - must be valid, non null, pointer to a linked list.
* ListNode *dnode - done to delete.
* Returns:
* The pointer to the item stored in node on success, NULL on failure.
* Precondition:
* The list has been initialized.
*****************************************************************************/
void *
ListDelNode( LinkedList * list,
ListNode * dnode,
int freeItem )
{ {
void *temp; void *temp;
@@ -296,19 +181,13 @@ ListDelNode( LinkedList * list,
assert(dnode != &list->head); assert(dnode != &list->head);
assert(dnode != &list->tail); assert(dnode != &list->tail);
if( ( list == NULL ) || if (!list || dnode == &list->head || dnode == &list->tail || !dnode)
( dnode == &list->head ) ||
( dnode == &list->tail ) || ( dnode == NULL ) ) {
return NULL; return NULL;
}
temp = dnode->item; temp = dnode->item;
dnode->prev->next = dnode->next; dnode->prev->next = dnode->next;
dnode->next->prev = dnode->prev; dnode->next->prev = dnode->prev;
freeListNode(dnode, list); freeListNode(dnode, list);
list->size--; list->size--;
if (freeItem && list->free_func) { if (freeItem && list->free_func) {
list->free_func(temp); list->free_func(temp);
temp = NULL; temp = NULL;
@@ -317,29 +196,12 @@ ListDelNode( LinkedList * list,
return temp; return temp;
} }
/**************************************************************************** int ListDestroy(LinkedList *list, int freeItem)
* Function: ListDestroy
*
* Description:
* Removes all memory associated with list nodes.
* Does not free LinkedList *list.
* Items stored in the list are not freed, only nodes are.
* Parameters:
* LinkedList *list - must be valid, non null, pointer to a linked list.
* Returns:
* 0 on success. Nonzero on failure.
* Always returns 0.
* Precondition:
* The list has been initialized.
*****************************************************************************/
int
ListDestroy( LinkedList * list,
int freeItem )
{ {
ListNode *dnode = NULL; ListNode *dnode = NULL;
ListNode *temp = NULL; ListNode *temp = NULL;
if( list == NULL ) if(!list)
return EINVAL; return EINVAL;
for (dnode = list->head.next; dnode != &list->tail; ) { for (dnode = list->head.next; dnode != &list->tail; ) {
@@ -347,120 +209,57 @@ ListDestroy( LinkedList * list,
ListDelNode(list, dnode, freeItem); ListDelNode(list, dnode, freeItem);
dnode = temp; dnode = temp;
} }
list->size = 0; list->size = 0;
FreeListDestroy(&list->freeNodeList); FreeListDestroy(&list->freeNodeList);
return 0; return 0;
} }
/**************************************************************************** ListNode *ListHead(LinkedList *list)
* Function: ListHead
*
* Description:
* Returns the head of the list.
*
* Parameters:
* LinkedList *list - must be valid, non null, pointer to a linked list.
*
* Returns:
* The head of the list. NULL if list is empty.
* Precondition:
* The list has been initialized.
*****************************************************************************/
ListNode *
ListHead( LinkedList * list )
{ {
assert(list != NULL); assert(list != NULL);
if( list == NULL ) if (!list)
return NULL; return NULL;
if( list->size == 0 ) if (!list->size)
return NULL; return NULL;
else else
return list->head.next; return list->head.next;
} }
/**************************************************************************** ListNode *ListTail(LinkedList *list)
* Function: ListTail
*
* Description:
* Returns the tail of the list.
*
* Parameters:
* LinkedList *list - must be valid, non null, pointer to a linked list.
*
* Returns:
* The tail of the list. NULL if list is empty.
* Precondition:
* The list has been initialized.
*****************************************************************************/
ListNode *
ListTail( LinkedList * list )
{ {
assert(list != NULL); assert(list != NULL);
if( list == NULL ) if (!list)
return NULL; return NULL;
if( list->size == 0 ) if (!list->size)
return NULL; return NULL;
else else
return list->tail.prev; return list->tail.prev;
} }
/**************************************************************************** ListNode *ListNext(LinkedList *list, ListNode *node)
* Function: ListNext
*
* Description:
* Returns the next item in the list.
*
* Parameters:
* LinkedList *list - must be valid, non null, pointer to a linked list.
*
* Returns:
* The next item in the list. NULL if there are no more items in list.
* Precondition:
* The list has been initialized.
*****************************************************************************/
ListNode *
ListNext( LinkedList * list,
ListNode * node )
{ {
assert(list != NULL); assert(list != NULL);
assert(node != NULL); assert(node != NULL);
if( ( list == NULL ) || ( node == NULL ) ) if (!list || !node)
return NULL; return NULL;
if (node->next == &list->tail) if (node->next == &list->tail)
return NULL; return NULL;
else else
return node->next; return node->next;
} }
/**************************************************************************** ListNode *ListPrev(LinkedList *list, ListNode *node)
* Function: ListPrev
*
* Description:
* Returns the previous item in the list.
*
* Parameters:
* LinkedList *list - must be valid, non null, pointer to a linked list.
*
* Returns:
* The previous item in the list. NULL if there are no more items in list.
* Precondition:
* The list has been initialized.
*****************************************************************************/
ListNode *
ListPrev( LinkedList * list,
ListNode * node )
{ {
assert(list != NULL); assert(list != NULL);
assert(node != NULL); assert(node != NULL);
if( ( list == NULL ) || ( node == NULL ) ) if (!list || !node)
return NULL; return NULL;
if (node->prev == &list->head) if (node->prev == &list->head)
@@ -469,35 +268,13 @@ ListPrev( LinkedList * list,
return node->prev; return node->prev;
} }
/**************************************************************************** ListNode *ListFind(LinkedList *list, ListNode *start, void *item)
* Function: ListFind
*
* Description:
* Finds the specified item in the list.
* Uses the compare function specified in ListInit. If compare function
* is NULL then compares items as pointers.
* Parameters:
* LinkedList *list - must be valid, non null, pointer to a linked list.
* ListNode *start - the node to start from, NULL if to start from
* beginning.
* void * item - the item to search for.
* Returns:
* The node containing the item. NULL if no node contains the item.
* Precondition:
* The list has been initialized.
*****************************************************************************/
ListNode *
ListFind( LinkedList * list,
ListNode * start,
void *item )
{ {
ListNode *finger = NULL; ListNode *finger = NULL;
if( list == NULL ) if (!list)
return NULL; return NULL;
if (!start)
if( start == NULL )
start = &list->head; start = &list->head;
assert(start); assert(start);
@@ -518,28 +295,13 @@ ListFind( LinkedList * list,
} }
return NULL; return NULL;
} }
/**************************************************************************** long ListSize(LinkedList *list)
* Function: ListSize
*
* Description:
* Returns the size of the list.
* Parameters:
* LinkedList *list - must be valid, non null, pointer to a linked list.
* Returns:
* The number of items in the list.
* Precondition:
* The list has been initialized.
*****************************************************************************/
int
ListSize( LinkedList * list )
{ {
assert(list != NULL); assert(list != NULL);
if( list == NULL ) if (!list)
return EINVAL; return EINVAL;
return list->size; return list->size;

File diff suppressed because it is too large Load Diff

View File

@@ -29,18 +29,14 @@
* *
******************************************************************************/ ******************************************************************************/
/*! /*!
* \file * \file
*/ */
#include "TimerThread.h" #include "TimerThread.h"
#include <assert.h> #include <assert.h>
/*! /*!
* \brief Deallocates a dynamically allocated TimerEvent. * \brief Deallocates a dynamically allocated TimerEvent.
*/ */
@@ -55,7 +51,6 @@ static void FreeTimerEvent(
FreeListFree(&timer->freeEvents, event); FreeListFree(&timer->freeEvents, event);
} }
/*! /*!
* \brief Implements timer thread. * \brief Implements timer thread.
* *
@@ -67,46 +62,34 @@ static void *TimerThreadWorker(
{ {
TimerThread *timer = ( TimerThread * ) arg; TimerThread *timer = ( TimerThread * ) arg;
ListNode *head = NULL; ListNode *head = NULL;
TimerEvent *nextEvent = NULL; TimerEvent *nextEvent = NULL;
time_t currentTime = 0; time_t currentTime = 0;
time_t nextEventTime = 0; time_t nextEventTime = 0;
struct timespec timeToWait; struct timespec timeToWait;
int tempId; int tempId;
assert( timer != NULL ); assert( timer != NULL );
ithread_mutex_lock( &timer->mutex ); ithread_mutex_lock( &timer->mutex );
while (1) {
while( 1 ) /* mutex should always be locked at top of loop */
{ /* Check for shutdown. */
//mutex should always be locked at top of loop if (timer->shutdown) {
//Check for shutdown
if( timer->shutdown )
{
timer->shutdown = 0; timer->shutdown = 0;
ithread_cond_signal( &timer->condition ); ithread_cond_signal( &timer->condition );
ithread_mutex_unlock( &timer->mutex ); ithread_mutex_unlock( &timer->mutex );
return NULL; return NULL;
} }
nextEvent = NULL; nextEvent = NULL;
/* Get the next event if possible. */
//Get the next event if possible if (timer->eventQ.size > 0) {
if( timer->eventQ.size > 0 )
{
head = ListHead( &timer->eventQ ); head = ListHead( &timer->eventQ );
nextEvent = ( TimerEvent * ) head->item; nextEvent = ( TimerEvent * ) head->item;
nextEventTime = nextEvent->eventTime; nextEventTime = nextEvent->eventTime;
} }
currentTime = time(NULL); currentTime = time(NULL);
/* If time has elapsed, schedule job. */
//If time has elapsed, schedule job if (nextEvent && currentTime >= nextEventTime) {
if( ( nextEvent != NULL ) && ( currentTime >= nextEventTime ) )
{
if( nextEvent->persistent ) { if( nextEvent->persistent ) {
ThreadPoolAddPersistent( timer->tp, &nextEvent->job, ThreadPoolAddPersistent( timer->tp, &nextEvent->job,
&tempId ); &tempId );
@@ -117,8 +100,7 @@ static void *TimerThreadWorker(
FreeTimerEvent( timer, nextEvent ); FreeTimerEvent( timer, nextEvent );
continue; continue;
} }
if (nextEvent) {
if( nextEvent != NULL ) {
timeToWait.tv_nsec = 0; timeToWait.tv_nsec = 0;
timeToWait.tv_sec = nextEvent->eventTime; timeToWait.tv_sec = nextEvent->eventTime;
ithread_cond_timedwait( &timer->condition, &timer->mutex, ithread_cond_timedwait( &timer->condition, &timer->mutex,
@@ -148,14 +130,13 @@ static int CalculateEventTime(
if (type == ABS_SEC) if (type == ABS_SEC)
return 0; return 0;
else if( type == REL_SEC ) { else /*if (type == REL_SEC) */{
time(&now); time(&now);
( *timeout ) += now; ( *timeout ) += now;
return 0; return 0;
} }
return -1; return -1;
} }
/*! /*!
@@ -246,10 +227,8 @@ int TimerThreadInit(TimerThread *timer, ThreadPool *tp)
} }
return rc; return rc;
} }
int TimerThreadSchedule( int TimerThreadSchedule(
TimerThread *timer, TimerThread *timer,
time_t timeout, time_t timeout,
@@ -258,7 +237,6 @@ int TimerThreadSchedule(
Duration duration, Duration duration,
int *id) int *id)
{ {
int rc = EOUTOFMEM; int rc = EOUTOFMEM;
int found = 0; int found = 0;
int tempId = 0; int tempId = 0;
@@ -291,35 +269,25 @@ int TimerThreadSchedule(
} }
tempNode = ListHead( &timer->eventQ ); tempNode = ListHead( &timer->eventQ );
//add job to Q /* add job to Q. Q is ordered by eventTime with the head of the Q being
//Q is ordered by eventTime * the next event. */
//with the head of the Q being the next event
while( tempNode != NULL ) { while( tempNode != NULL ) {
temp = ( TimerEvent * ) tempNode->item; temp = ( TimerEvent * ) tempNode->item;
if( temp->eventTime >= timeout ) if( temp->eventTime >= timeout ) {
{ if (ListAddBefore( &timer->eventQ, newEvent, tempNode))
if( ListAddBefore( &timer->eventQ, newEvent, tempNode ) !=
NULL )
rc = 0; rc = 0;
found = 1; found = 1;
break; break;
} }
tempNode = ListNext( &timer->eventQ, tempNode ); tempNode = ListNext( &timer->eventQ, tempNode );
} }
/* add to the end of Q. */
//add to the end of Q
if (!found) { if (!found) {
if( ListAddTail( &timer->eventQ, newEvent ) != NULL ) if( ListAddTail( &timer->eventQ, newEvent ) != NULL )
rc = 0; rc = 0;
} }
//signal change in Q /* signal change in Q. */
if( rc == 0 ) { if( rc == 0 ) {
ithread_cond_signal( &timer->condition ); ithread_cond_signal( &timer->condition );
} else { } else {
FreeTimerEvent( timer, newEvent ); FreeTimerEvent( timer, newEvent );
@@ -330,7 +298,6 @@ int TimerThreadSchedule(
return rc; return rc;
} }
int TimerThreadRemove( int TimerThreadRemove(
TimerThread *timer, TimerThread *timer,
int id, int id,
@@ -369,7 +336,6 @@ int TimerThreadRemove(
return rc; return rc;
} }
int TimerThreadShutdown(TimerThread *timer) int TimerThreadShutdown(TimerThread *timer)
{ {
ListNode *tempNode2 = NULL; ListNode *tempNode2 = NULL;
@@ -386,9 +352,7 @@ int TimerThreadShutdown(TimerThread *timer)
timer->shutdown = 1; timer->shutdown = 1;
tempNode = ListHead( &timer->eventQ ); tempNode = ListHead( &timer->eventQ );
//Delete nodes in Q /* Delete nodes in Q. Call registered free function on argument. */
//call registered free function
//on argument
while( tempNode != NULL ) { while( tempNode != NULL ) {
TimerEvent *temp = ( TimerEvent * ) tempNode->item; TimerEvent *temp = ( TimerEvent * ) tempNode->item;
@@ -406,18 +370,16 @@ int TimerThreadShutdown(TimerThread *timer)
ithread_cond_broadcast( &timer->condition ); ithread_cond_broadcast( &timer->condition );
while( timer->shutdown ) //wait for timer thread to shutdown while (timer->shutdown) {
{ /* wait for timer thread to shutdown. */
ithread_cond_wait( &timer->condition, &timer->mutex ); ithread_cond_wait( &timer->condition, &timer->mutex );
} }
ithread_mutex_unlock(&timer->mutex); ithread_mutex_unlock(&timer->mutex);
//destroy condition /* destroy condition. */
while(ithread_cond_destroy(&timer->condition) != 0) { while(ithread_cond_destroy(&timer->condition) != 0) {
} }
/* destroy mutex. */
//destroy mutex
while (ithread_mutex_destroy(&timer->mutex) != 0) { while (ithread_mutex_destroy(&timer->mutex) != 0) {
} }

View File

@@ -70,8 +70,7 @@ libupnp_la_SOURCES = \
src/inc/upnp_timeout.h \ src/inc/upnp_timeout.h \
src/inc/uri.h \ src/inc/uri.h \
src/inc/urlconfig.h \ src/inc/urlconfig.h \
src/inc/util.h \ src/inc/upnputil.h \
src/inc/utilall.h \
src/inc/uuid.h \ src/inc/uuid.h \
src/inc/VirtualDir.h \ src/inc/VirtualDir.h \
src/inc/webserver.h src/inc/webserver.h

View File

@@ -88,7 +88,11 @@
* inline keyword. This definition makes the use of this keyword * inline keyword. This definition makes the use of this keyword
* portable to these systems. * portable to these systems.
*/ */
#ifdef __STRICT_ANSI__
#define UPNP_INLINE __inline__
#else
#define UPNP_INLINE inline #define UPNP_INLINE inline
#endif
/*! /*!
* \brief Supply the PRId64 printf() macro. * \brief Supply the PRId64 printf() macro.

View File

@@ -1,16 +1,13 @@
#ifndef UPNPINET_H #ifndef UPNPINET_H
#define UPNPINET_H #define UPNPINET_H
/*! /*!
* \file * \file
* *
* \brief Provides a platform independent way to include TCP/IP types and functions. * \brief Provides a platform independent way to include TCP/IP types and functions.
*/ */
#ifdef WIN32 #ifdef WIN32
#include <iphlpapi.h> #include <iphlpapi.h>
#include <winsock2.h> #include <winsock2.h>
@@ -27,12 +24,17 @@
#endif #endif
#include <netinet/in.h> #include <netinet/in.h>
#include <unistd.h> /* for close(). Do not include in WIN32. */ /* include <unistd.h> for close().
* Do not include this file in win32. */
#include <unistd.h>
/* SOCKET is unsigned and is not a file descriptor on win32. */
#define SOCKET int #define SOCKET int
#define INVALID_SOCKET ((SOCKET)(-1)) /* INVALID_SOCKET is unsigned on win32. */
#define INVALID_SOCKET (-1)
/* select() returns SOCKET_ERROR on win32. */
#define SOCKET_ERROR (-1)
#define UpnpCloseSocket close #define UpnpCloseSocket close
#endif #endif
#endif /* UPNPINET_H */ #endif /* UPNPINET_H */

View File

@@ -17,7 +17,7 @@
* *
* \file * \file
* *
* \brief UpnpString object declarartion. * \brief UpnpString object declaration.
*/ */

View File

@@ -1328,7 +1328,7 @@ EXPORT_SPEC int UpnpSetContentLength(
* length needs to be set. */ * length needs to be set. */
UpnpClient_Handle Hnd, UpnpClient_Handle Hnd,
/*! [in] Permissible content length */ /*! [in] Permissible content length */
int contentLength); size_t contentLength);
/*! /*!
@@ -2412,7 +2412,7 @@ EXPORT_SPEC int UpnpReadHttpGet(
/*! [in,out] The buffer to store the read item. */ /*! [in,out] The buffer to store the read item. */
char *buf, char *buf,
/*! [in,out] The size of the buffer to be read. */ /*! [in,out] The size of the buffer to be read. */
unsigned int *size, size_t *size,
/*! [in] The time out value sent with the request during which a response is /*! [in] The time out value sent with the request during which a response is
* expected from the server, failing which, an error is reported back to * expected from the server, failing which, an error is reported back to
* the user. */ * the user. */
@@ -2431,9 +2431,9 @@ EXPORT_SPEC int UpnpHttpGetProgress(
/*! [in] The token created by the call to \b UpnpOpenHttpGet. */ /*! [in] The token created by the call to \b UpnpOpenHttpGet. */
void *handle, void *handle,
/*! [out] The number of bytes received. */ /*! [out] The number of bytes received. */
unsigned int *length, size_t *length,
/*! [out] The content length. */ /*! [out] The content length. */
unsigned int *total); size_t *total);
/*! /*!
@@ -2522,7 +2522,7 @@ EXPORT_SPEC int UpnpWriteHttpPost(
/*! [in] The buffer to be posted. */ /*! [in] The buffer to be posted. */
char *buf, char *buf,
/*! [in] The size, in bytes of \b buf. */ /*! [in] The size, in bytes of \b buf. */
unsigned int *size, size_t *size,
/*! [in] A timeout value sent with the request during which a response is /*! [in] A timeout value sent with the request during which a response is
* expected from the server, failing which, an error is reported. */ * expected from the server, failing which, an error is reported. */
int timeout); int timeout);

View File

@@ -1,7 +1,7 @@
/******************************************************************************* /*******************************************************************************
* *
* Copyright (c) 2000-2003 Intel Corporation * Copyright (c) 2000-2003 Intel Corporation
* Copyright (c) 2006 R<EFBFBD>mi Turboult <r3mi@users.sourceforge.net> * Copyright (c) 2006 Rémi Turboult <r3mi@users.sourceforge.net>
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -33,32 +33,27 @@
#ifndef UPNP_DEBUG_H #ifndef UPNP_DEBUG_H
#define UPNP_DEBUG_H #define UPNP_DEBUG_H
/*! /*!
* \file * \file
*/ */
#include "ThreadPool.h" #include "ThreadPool.h"
#include "upnpconfig.h" #include "upnpconfig.h"
#include "UpnpGlobal.h" /* for UPNP_INLINE */ #include "UpnpGlobal.h" /* for UPNP_INLINE */
#include <stdio.h> #include <stdio.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/*! \name Other debugging features
/** \name Other debugging features
* *
* The UPnP SDK contains other features to aid in debugging. * The UPnP SDK contains other features to aid in debugging.
*/ */
/*@{*/ /*@{*/
/** \name Upnp_LogLevel /*! \name Upnp_LogLevel
* The user has the option to select 4 different types of debugging levels, * The user has the option to select 4 different types of debugging levels,
* see \c UpnpSetLogLevel. * see \c UpnpSetLogLevel.
* The critical level will show only those messages * The critical level will show only those messages
@@ -85,7 +80,6 @@ typedef enum Upnp_Module {
HTTP HTTP
} Dbg_Module; } Dbg_Module;
/*@{*/ /*@{*/
typedef enum Upnp_LogLevel_e { typedef enum Upnp_LogLevel_e {
UPNP_CRITICAL, UPNP_CRITICAL,
@@ -95,14 +89,11 @@ typedef enum Upnp_LogLevel_e {
} Upnp_LogLevel; } Upnp_LogLevel;
/*@}*/ /*@}*/
/*!
/**
* Default log level : see \c Upnp_LogLevel * Default log level : see \c Upnp_LogLevel
*/ */
#define UPNP_DEFAULT_LOG_LEVEL UPNP_ALL #define UPNP_DEFAULT_LOG_LEVEL UPNP_ALL
/*! /*!
* \brief Initialize the log files. * \brief Initialize the log files.
* *
@@ -117,7 +108,6 @@ static UPNP_INLINE int UpnpInitLog(void)
} }
#endif #endif
/*! /*!
* \brief Set the log level (see \c Upnp_LogLevel). * \brief Set the log level (see \c Upnp_LogLevel).
*/ */
@@ -126,10 +116,13 @@ void UpnpSetLogLevel(
/*! [in] Log level. */ /*! [in] Log level. */
Upnp_LogLevel log_level); Upnp_LogLevel log_level);
#else #else
static UPNP_INLINE void UpnpSetLogLevel(Upnp_LogLevel log_level) {} static UPNP_INLINE void UpnpSetLogLevel(Upnp_LogLevel log_level)
{
return;
log_level = log_level;
}
#endif #endif
/*! /*!
* \brief Closes the log files. * \brief Closes the log files.
*/ */
@@ -139,7 +132,6 @@ void UpnpCloseLog(void);
static UPNP_INLINE void UpnpCloseLog(void) {} static UPNP_INLINE void UpnpCloseLog(void) {}
#endif #endif
/*! /*!
* \brief Set the name for error and information files, respectively. * \brief Set the name for error and information files, respectively.
*/ */
@@ -152,10 +144,14 @@ void UpnpSetLogFileNames(
#else #else
static UPNP_INLINE void UpnpSetLogFileNames( static UPNP_INLINE void UpnpSetLogFileNames(
const char *ErrFileName, const char *ErrFileName,
const char *InfoFileName) {} const char *InfoFileName)
{
return;
ErrFileName = ErrFileName;
InfoFileName = InfoFileName;
}
#endif #endif
/*! /*!
* \brief Check if the module is turned on for debug and returns the file * \brief Check if the module is turned on for debug and returns the file
* descriptor corresponding to the debug level * descriptor corresponding to the debug level
@@ -174,6 +170,8 @@ FILE *UpnpGetDebugFile(
static UPNP_INLINE FILE *UpnpGetDebugFile(Upnp_LogLevel level, Dbg_Module module) static UPNP_INLINE FILE *UpnpGetDebugFile(Upnp_LogLevel level, Dbg_Module module)
{ {
return NULL; return NULL;
level = level;
module = module;
} }
#endif #endif
@@ -196,6 +194,8 @@ static UPNP_INLINE int DebugAtThisLevel(
Dbg_Module Module) Dbg_Module Module)
{ {
return 0; return 0;
DLevel = DLevel;
Module = Module;
} }
#endif #endif
@@ -234,6 +234,12 @@ static UPNP_INLINE void UpnpPrintf(
const char* FmtStr, const char* FmtStr,
...) ...)
{ {
return;
DLevel = DLevel;
Module = Module;
DbgFileName = DbgFileName;
DbgLineNo = DbgLineNo;
FmtStr = FmtStr;
} }
#endif /* DEBUG */ #endif /* DEBUG */
@@ -254,7 +260,13 @@ void UpnpDisplayFileAndLine(
static UPNP_INLINE void UpnpDisplayFileAndLine( static UPNP_INLINE void UpnpDisplayFileAndLine(
FILE *fd, FILE *fd,
const char *DbgFileName, const char *DbgFileName,
int DbgLineNo) {} int DbgLineNo)
{
return;
fd = fd;
DbgFileName = DbgFileName;
DbgLineNo = DbgLineNo;
}
#endif #endif
@@ -270,13 +282,20 @@ void UpnpDisplayBanner(
/*! [in] Size of the buffer. */ /*! [in] Size of the buffer. */
size_t size, size_t size,
/*! [in] This parameter provides the width of the banner. */ /*! [in] This parameter provides the width of the banner. */
int starlength); size_t starlength);
#else #else
static UPNP_INLINE void UpnpDisplayBanner( static UPNP_INLINE void UpnpDisplayBanner(
FILE *fd, FILE *fd,
const char **lines, const char **lines,
size_t size, size_t size,
int starlength) {} int starlength)
{
return;
fd = fd;
lines = lines;
size = size;
starlength = starlength;
}
#endif #endif
@@ -300,10 +319,14 @@ static UPNP_INLINE void PrintThreadPoolStats(
int DbgLineNo, int DbgLineNo,
const char *msg) const char *msg)
{ {
return;
tp = tp;
DbgFileName = DbgFileName;
DbgLineNo = DbgLineNo;
msg = msg;
} }
#endif #endif
/*@}*/ /*@}*/
#ifdef __cplusplus #ifdef __cplusplus

View File

@@ -96,6 +96,30 @@ EXPORT_SPEC int UpnpResolveURL(
char *AbsURL); char *AbsURL);
/*!
* \brief Combines a base URL and a relative URL into a single absolute URL.
*
* The memory for \b AbsURL becomes owned by the caller and should be freed
* later.
*
* \return An integer representing one of the following:
* \li <tt>UPNP_E_SUCCESS</tt>: The operation completed successfully.
* \li <tt>UPNP_E_INVALID_PARAM</tt>: \b RelURL is <tt>NULL</tt>.
* \li <tt>UPNP_E_INVALID_URL</tt>: The \b BaseURL / \b RelURL
* combination does not form a valid URL.
* \li <tt>UPNP_E_OUTOF_MEMORY</tt>: Insufficient resources exist to
* complete this operation.
*/
EXPORT_SPEC int UpnpResolveURL2(
/*! [in] The base URL to combine. */
const char *BaseURL,
/*! [in] The relative URL to \b BaseURL. */
const char *RelURL,
/*! [out] A pointer to a pointer to a buffer to store the
* absolute URL. Must be freed later by the caller. */
char **AbsURL);
/*! /*!
* \brief Creates an action request packet based on its input parameters * \brief Creates an action request packet based on its input parameters
* (status variable name and value pair). * (status variable name and value pair).

View File

@@ -19,21 +19,21 @@ LDADD = \
noinst_PROGRAMS = noinst_PROGRAMS =
if ENABLE_SAMPLES if ENABLE_SAMPLES
if ENABLE_CLIENT if ENABLE_CLIENT
noinst_PROGRAMS += upnp_tv_ctrlpt noinst_PROGRAMS += tv_ctrlpt
upnp_tv_ctrlpt_CPPFLAGS = \ tv_ctrlpt_CPPFLAGS = \
$(AM_CPPFLAGS) \ $(AM_CPPFLAGS) \
-I$(srcdir)/common/ \ -I$(srcdir)/common/ \
-I$(srcdir)/tvctrlpt -I$(srcdir)/tvctrlpt
if ENABLE_DEVICE if ENABLE_DEVICE
noinst_PROGRAMS += upnp_tv_combo noinst_PROGRAMS += tv_combo
upnp_tv_combo_CPPFLAGS = $(AM_CPPFLAGS) \ tv_combo_CPPFLAGS = $(AM_CPPFLAGS) \
-I$(srcdir)/common/ \ -I$(srcdir)/common/ \
-I$(srcdir)/tvcombo -I$(srcdir)/tvcombo
endif endif
endif endif
if ENABLE_DEVICE if ENABLE_DEVICE
noinst_PROGRAMS += upnp_tv_device noinst_PROGRAMS += tv_device
upnp_tv_device_CPPFLAGS = \ tv_device_CPPFLAGS = \
$(AM_CPPFLAGS) \ $(AM_CPPFLAGS) \
-I$(srcdir)/common/ \ -I$(srcdir)/common/ \
-I$(srcdir)/tvdevice -I$(srcdir)/tvdevice
@@ -41,37 +41,37 @@ endif
endif endif
upnp_tv_device_SOURCES = \ tv_device_SOURCES = \
common/sample_util.c \ common/sample_util.c \
common/sample_util.h \ common/sample_util.h \
tvdevice/upnp_tv_device.c \ common/tv_device.c \
tvdevice/upnp_tv_device.h \ common/tv_device.h \
tvdevice/linux/upnp_tv_device_main.c linux/tv_device_main.c
upnp_tv_ctrlpt_SOURCES = \ tv_ctrlpt_SOURCES = \
common/sample_util.c \ common/sample_util.c \
common/sample_util.h \ common/sample_util.h \
tvctrlpt/upnp_tv_ctrlpt.c \ common/tv_ctrlpt.c \
tvctrlpt/upnp_tv_ctrlpt.h \ common/tv_ctrlpt.h \
tvctrlpt/linux/upnp_tv_ctrlpt_main.c linux/tv_ctrlpt_main.c
upnp_tv_combo_SOURCES = \ tv_combo_SOURCES = \
common/sample_util.c \ common/sample_util.c \
common/sample_util.h \ common/sample_util.h \
tvcombo/upnp_tv_ctrlpt.c \ common/tv_ctrlpt.c \
tvcombo/upnp_tv_ctrlpt.h \ common/tv_ctrlpt.h \
tvcombo/upnp_tv_device.c \ common/tv_device.c \
tvcombo/upnp_tv_device.h \ common/tv_device.h \
tvcombo/linux/upnp_tv_combo_main.c linux/tv_combo_main.c
if WITH_DOCUMENTATION if WITH_DOCUMENTATION
examplesdir = $(docdir)/examples examplesdir = $(docdir)/examples
examples_DATA = \ examples_DATA = \
$(sort \ $(sort \
$(upnp_tv_ctrlpt_SOURCES) \ $(tv_ctrlpt_SOURCES) \
$(upnp_tv_device_SOURCES)) $(tv_device_SOURCES))
endif endif

View File

@@ -30,8 +30,11 @@
******************************************************************************/ ******************************************************************************/
#define SAMPLE_UTIL_C
#include "sample_util.h" #include "sample_util.h"
#include "tv_ctrlpt.h"
#include "tv_device.h"
#include <assert.h> #include <assert.h>
#include <stdarg.h> #include <stdarg.h>
@@ -54,18 +57,6 @@ state_update gStateUpdateFun = NULL;
/*! mutex to control displaying of events */ /*! mutex to control displaying of events */
ithread_mutex_t display_mutex; ithread_mutex_t display_mutex;
/*******************************************************************************
* SampleUtil_Initialize
*
* Description:
* Initializes the sample util. Must be called before any sample util
* functions. May be called multiple times.
* But the initialization is done only once.
*
* Parameters:
* print_function - print function to use in SampleUtil_Print
*
******************************************************************************/
int SampleUtil_Initialize(print_string print_function) int SampleUtil_Initialize(print_string print_function)
{ {
if (initialize_init) { if (initialize_init) {
@@ -82,22 +73,11 @@ int SampleUtil_Initialize(print_string print_function)
ithread_mutex_unlock(&display_mutex); ithread_mutex_unlock(&display_mutex);
initialize_init = 0; initialize_init = 0;
} else {
SampleUtil_Print("***** SampleUtil_Initialize was called multiple times!\n");
abort();
} }
return UPNP_E_SUCCESS; return UPNP_E_SUCCESS;
} }
/*******************************************************************************
* SampleUtil_RegisterUpdateFunction
*
* Description:
*
* Parameters:
*
******************************************************************************/
int SampleUtil_RegisterUpdateFunction(state_update update_function) int SampleUtil_RegisterUpdateFunction(state_update update_function)
{ {
if (initialize_register) { if (initialize_register) {
@@ -108,15 +88,6 @@ int SampleUtil_RegisterUpdateFunction(state_update update_function)
return UPNP_E_SUCCESS; return UPNP_E_SUCCESS;
} }
/*******************************************************************************
* SampleUtil_Finish
*
* Description:
* Releases Resources held by sample util.
*
* Parameters:
*
******************************************************************************/
int SampleUtil_Finish() int SampleUtil_Finish()
{ {
ithread_mutex_destroy(&display_mutex); ithread_mutex_destroy(&display_mutex);
@@ -128,21 +99,7 @@ int SampleUtil_Finish()
return UPNP_E_SUCCESS; return UPNP_E_SUCCESS;
} }
/******************************************************************************* char *SampleUtil_GetElementValue(IXML_Element *element)
* SampleUtil_GetElementValue
*
* Description:
* Given a DOM node such as <Channel>11</Channel>, this routine
* extracts the value (e.g., 11) from the node and returns it as
* a string. The string must be freed by the caller using
* free.
*
* Parameters:
* node -- The DOM node from which to extract the value
*
******************************************************************************/
char *SampleUtil_GetElementValue(IN IXML_Element *element)
{ {
IXML_Node *child = ixmlNode_getFirstChild((IXML_Node *)element); IXML_Node *child = ixmlNode_getFirstChild((IXML_Node *)element);
char *temp = NULL; char *temp = NULL;
@@ -154,20 +111,7 @@ char *SampleUtil_GetElementValue(IN IXML_Element *element)
return temp; return temp;
} }
/******************************************************************************* IXML_NodeList *SampleUtil_GetFirstServiceList(IXML_Document *doc)
* SampleUtil_GetFirstServiceList
*
* Description:
* Given a DOM node representing a UPnP Device Description Document,
* this routine parses the document and finds the first service list
* (i.e., the service list for the root device). The service list
* is returned as a DOM node list.
*
* Parameters:
* node -- The DOM node from which to extract the service list
*
******************************************************************************/
IXML_NodeList *SampleUtil_GetFirstServiceList(IN IXML_Document *doc)
{ {
IXML_NodeList *ServiceList = NULL; IXML_NodeList *ServiceList = NULL;
IXML_NodeList *servlistnodelist = NULL; IXML_NodeList *servlistnodelist = NULL;
@@ -179,7 +123,6 @@ IXML_NodeList *SampleUtil_GetFirstServiceList(IN IXML_Document *doc)
/* we only care about the first service list, from the root /* we only care about the first service list, from the root
* device */ * device */
servlistnode = ixmlNodeList_item(servlistnodelist, 0); servlistnode = ixmlNodeList_item(servlistnodelist, 0);
/* create as list of DOM nodes */ /* create as list of DOM nodes */
ServiceList = ixmlElement_getElementsByTagName( ServiceList = ixmlElement_getElementsByTagName(
(IXML_Element *)servlistnode, "service"); (IXML_Element *)servlistnode, "service");
@@ -195,23 +138,24 @@ IXML_NodeList *SampleUtil_GetFirstServiceList(IN IXML_Document *doc)
* Obtain the service list * Obtain the service list
* n == 0 the first * n == 0 the first
* n == 1 the next in the device list, etc.. * n == 1 the next in the device list, etc..
*
*/ */
IXML_NodeList *SampleUtil_GetNthServiceList(IN IXML_Document *doc , int n) static IXML_NodeList *SampleUtil_GetNthServiceList(
/*! [in] . */
IXML_Document *doc,
/*! [in] . */
unsigned int n)
{ {
IXML_NodeList *ServiceList = NULL; IXML_NodeList *ServiceList = NULL;
IXML_NodeList *servlistnodelist = NULL; IXML_NodeList *servlistnodelist = NULL;
IXML_Node *servlistnode = NULL; IXML_Node *servlistnode = NULL;
/* /* ixmlDocument_getElementsByTagName()
* ixmlDocument_getElementsByTagName()
* Returns a NodeList of all Elements that match the given * Returns a NodeList of all Elements that match the given
* tag name in the order in which they were encountered in a preorder * tag name in the order in which they were encountered in a preorder
* traversal of the Document tree. * traversal of the Document tree.
* *
* return (NodeList*) A pointer to a NodeList containing the * return (NodeList*) A pointer to a NodeList containing the
* matching items or NULL on an error. * matching items or NULL on an error. */
*/
SampleUtil_Print("SampleUtil_GetNthServiceList called : n = %d\n", n); SampleUtil_Print("SampleUtil_GetNthServiceList called : n = %d\n", n);
servlistnodelist = servlistnodelist =
ixmlDocument_getElementsByTagName(doc, "serviceList"); ixmlDocument_getElementsByTagName(doc, "serviceList");
@@ -226,8 +170,7 @@ IXML_NodeList *SampleUtil_GetNthServiceList(IN IXML_Document *doc , int n)
* numerical index. * numerical index.
* *
* return (Node*) A pointer to a Node or NULL if there was an * return (Node*) A pointer to a Node or NULL if there was an
* error. * error. */
*/
servlistnode = ixmlNodeList_item(servlistnodelist, n); servlistnode = ixmlNodeList_item(servlistnodelist, n);
assert(servlistnode != 0); assert(servlistnode != 0);
@@ -244,20 +187,7 @@ IXML_NodeList *SampleUtil_GetNthServiceList(IN IXML_Document *doc , int n)
return ServiceList; return ServiceList;
} }
/******************************************************************************* char *SampleUtil_GetFirstDocumentItem(IXML_Document *doc, const char *item)
* SampleUtil_GetFirstDocumentItem
*
* Description:
* Given a document node, this routine searches for the first element
* named by the input string item, and returns its value as a string.
* String must be freed by caller using free.
* Parameters:
* doc -- The DOM document from which to extract the value
* item -- The item to search for
*
******************************************************************************/
char *SampleUtil_GetFirstDocumentItem(
IN IXML_Document *doc, IN const char *item)
{ {
IXML_NodeList *nodeList = NULL; IXML_NodeList *nodeList = NULL;
IXML_Node *textNode = NULL; IXML_Node *textNode = NULL;
@@ -302,20 +232,7 @@ epilogue:
return ret; return ret;
} }
/******************************************************************************* char *SampleUtil_GetFirstElementItem(IXML_Element *element, const char *item)
* SampleUtil_GetFirstElementItem
*
* Description:
* Given a DOM element, this routine searches for the first element
* named by the input string item, and returns its value as a string.
* The string must be freed using free.
* Parameters:
* node -- The DOM element from which to extract the value
* item -- The item to search for
*
******************************************************************************/
char *SampleUtil_GetFirstElementItem(
IN IXML_Element *element, IN const char *item)
{ {
IXML_NodeList *nodeList = NULL; IXML_NodeList *nodeList = NULL;
IXML_Node *textNode = NULL; IXML_Node *textNode = NULL;
@@ -349,17 +266,7 @@ char *SampleUtil_GetFirstElementItem(
return ret; return ret;
} }
/******************************************************************************* void SampleUtil_PrintEventType(Upnp_EventType S)
* SampleUtil_PrintEventType
*
* Description:
* Prints a callback event type as a string.
*
* Parameters:
* S -- The callback event
*
******************************************************************************/
void SampleUtil_PrintEventType(IN Upnp_EventType S)
{ {
switch (S) { switch (S) {
/* Discovery */ /* Discovery */
@@ -413,18 +320,7 @@ void SampleUtil_PrintEventType(IN Upnp_EventType S)
} }
} }
/******************************************************************************* int SampleUtil_PrintEvent(Upnp_EventType EventType, void *Event)
* SampleUtil_PrintEvent
*
* Description:
* Prints callback event structure details.
*
* Parameters:
* EventType -- The type of callback event
* Event -- The callback event structure
*
******************************************************************************/
int SampleUtil_PrintEvent(IN Upnp_EventType EventType, IN void *Event)
{ {
ithread_mutex_lock(&display_mutex); ithread_mutex_lock(&display_mutex);
@@ -542,7 +438,6 @@ int SampleUtil_PrintEvent(IN Upnp_EventType EventType, IN void *Event)
SampleUtil_Print("CurrentVal = %s\n", sv_event->CurrentVal); SampleUtil_Print("CurrentVal = %s\n", sv_event->CurrentVal);
break; break;
} }
/* GENA */ /* GENA */
case UPNP_EVENT_SUBSCRIPTION_REQUEST: { case UPNP_EVENT_SUBSCRIPTION_REQUEST: {
struct Upnp_Subscription_Request *sr_event = struct Upnp_Subscription_Request *sr_event =
@@ -610,31 +505,14 @@ int SampleUtil_PrintEvent(IN Upnp_EventType EventType, IN void *Event)
return 0; return 0;
} }
/******************************************************************************* int SampleUtil_FindAndParseService(IXML_Document *DescDoc, const char *location,
* SampleUtil_FindAndParseService const char *serviceType, char **serviceId, char **eventURL, char **controlURL)
*
* Description:
* This routine finds the first occurance of a service in a DOM representation
* of a description document and parses it.
*
* Parameters:
* DescDoc -- The DOM description document
* location -- The location of the description document
* serviceSearchType -- The type of service to search for
* serviceId -- OUT -- The service ID
* eventURL -- OUT -- The event URL for the service
* controlURL -- OUT -- The control URL for the service
*
******************************************************************************/
int SampleUtil_FindAndParseService(
IN IXML_Document *DescDoc, IN const char *location, IN char *serviceType,
OUT char **serviceId, OUT char **eventURL, OUT char **controlURL)
{ {
int i; unsigned int i;
int length; unsigned long length;
int found = 0; int found = 0;
int ret; int ret;
int sindex = 0; unsigned int sindex = 0;
char *tempServiceType = NULL; char *tempServiceType = NULL;
char *baseURL = NULL; char *baseURL = NULL;
const char *base = NULL; const char *base = NULL;
@@ -714,20 +592,7 @@ int SampleUtil_FindAndParseService(
return found; return found;
} }
/******************************************************************************* int SampleUtil_Print(const char *fmt, ...)
* SampleUtil_Print
*
* Description:
* Provides platform-specific print functionality. This function should be
* called when you want to print content suitable for console output (i.e.,
* in a large text box or on a screen). If your device/operating system is
* not supported here, you should add a port.
*
* Parameters:
* Same as printf()
*
******************************************************************************/
int SampleUtil_Print(char *fmt, ...)
{ {
#define MAX_BUF (8 * 1024) #define MAX_BUF (8 * 1024)
va_list ap; va_list ap;
@@ -740,9 +605,8 @@ int SampleUtil_Print(char *fmt, ...)
va_start(ap, fmt); va_start(ap, fmt);
rc = vsnprintf(buf, MAX_BUF, fmt, ap); rc = vsnprintf(buf, MAX_BUF, fmt, ap);
va_end(ap); va_end(ap);
if (gPrintFun) { if (gPrintFun) {
gPrintFun(buf); gPrintFun("%s", buf);
} }
ithread_mutex_unlock(&display_mutex); ithread_mutex_unlock(&display_mutex);
@@ -750,14 +614,6 @@ int SampleUtil_Print(char *fmt, ...)
return rc; return rc;
} }
/*******************************************************************************
* SampleUtil_StateUpdate
*
* Description:
*
* Parameters:
*
******************************************************************************/
void SampleUtil_StateUpdate(const char *varName, const char *varValue, void SampleUtil_StateUpdate(const char *varName, const char *varValue,
const char *UDN, eventType type) const char *UDN, eventType type)
{ {
@@ -767,3 +623,15 @@ void SampleUtil_StateUpdate(const char *varName, const char *varValue,
} }
} }
/*!
* \brief Prints a string to standard out.
*/
void linux_print(const char *format, ...)
{
va_list argList;
va_start(argList, format);
vfprintf(stdout, format, argList);
fflush(stdout);
va_end(argList);
}

View File

@@ -29,30 +29,38 @@
* *
******************************************************************************/ ******************************************************************************/
#ifndef SAMPLE_UTIL_H #ifndef SAMPLE_UTIL_H
#define SAMPLE_UTIL_H #define SAMPLE_UTIL_H
/*!
* \file
*/
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif /* __cplusplus */ #endif /* __cplusplus */
#include "ithread.h" #include "ithread.h"
#include "ixml.h" /* for IXML_Document, IXML_Element */ #include "ixml.h" /* for IXML_Document, IXML_Element */
#include "upnp.h" /* for Upnp_EventType */ #include "upnp.h" /* for Upnp_EventType */
#include "upnptools.h" #include "upnptools.h"
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#ifdef SAMPLE_UTIL_C
/*! Service types for tv services. */
const char *TvServiceType[] = {
"urn:schemas-upnp-org:service:tvcontrol:1",
"urn:schemas-upnp-org:service:tvpicture:1"
};
#else /* SAMPLE_UTIL_C */
extern const char *TvServiceType[];
#endif /* SAMPLE_UTIL_C */
/* mutex to control displaying of events */ /* mutex to control displaying of events */
extern ithread_mutex_t display_mutex; extern ithread_mutex_t display_mutex;
typedef enum { typedef enum {
STATE_UPDATE = 0, STATE_UPDATE = 0,
DEVICE_ADDED = 1, DEVICE_ADDED = 1,
@@ -60,233 +68,196 @@ typedef enum {
GET_VAR_COMPLETE = 3 GET_VAR_COMPLETE = 3
} eventType; } eventType;
/*!
/******************************************************************************** * \brief Given a DOM node such as <Channel>11</Channel>, this routine
* SampleUtil_GetElementValue
*
* Description:
* Given a DOM node such as <Channel>11</Channel>, this routine
* extracts the value (e.g., 11) from the node and returns it as * extracts the value (e.g., 11) from the node and returns it as
* a string. The string must be freed by the caller using * a string. The string must be freed by the caller using free.
* free.
* *
* Parameters: * \return The DOM node as a string.
* node -- The DOM node from which to extract the value */
* char *SampleUtil_GetElementValue(
********************************************************************************/ /*! [in] The DOM node from which to extract the value. */
char *SampleUtil_GetElementValue(IN IXML_Element *element); IXML_Element *element);
/******************************************************************************** /*!
* SampleUtil_GetFirstServiceList * \brief Given a DOM node representing a UPnP Device Description Document,
*
* Description:
* Given a DOM node representing a UPnP Device Description Document,
* this routine parses the document and finds the first service list * this routine parses the document and finds the first service list
* (i.e., the service list for the root device). The service list * (i.e., the service list for the root device). The service list
* is returned as a DOM node list. The NodeList must be freed using * is returned as a DOM node list. The NodeList must be freed using
* NodeList_free. * NodeList_free.
* *
* Parameters: * \return The service list is returned as a DOM node list.
* node -- The DOM node from which to extract the service list */
* IXML_NodeList *SampleUtil_GetFirstServiceList(
********************************************************************************/ /*! [in] The DOM node from which to extract the service list. */
IXML_Document *doc);
IXML_NodeList *SampleUtil_GetFirstServiceList(IN IXML_Document *doc); /*!
* \brief Given a document node, this routine searches for the first element
/********************************************************************************
* SampleUtil_GetFirstDocumentItem
*
* Description:
* Given a document node, this routine searches for the first element
* named by the input string item, and returns its value as a string. * named by the input string item, and returns its value as a string.
* String must be freed by caller using free. * String must be freed by caller using free.
* Parameters: */
* doc -- The DOM document from which to extract the value char *SampleUtil_GetFirstDocumentItem(
* item -- The item to search for /*! [in] The DOM document from which to extract the value. */
* IXML_Document *doc,
********************************************************************************/ /*! [in] The item to search for. */
char *SampleUtil_GetFirstDocumentItem(IN IXML_Document *doc, IN const char *item); const char *item);
/*!
* \brief Given a DOM element, this routine searches for the first element
/********************************************************************************
* SampleUtil_GetFirstElementItem
*
* Description:
* Given a DOM element, this routine searches for the first element
* named by the input string item, and returns its value as a string. * named by the input string item, and returns its value as a string.
* The string must be freed using free. * The string must be freed using free.
* Parameters: */
* node -- The DOM element from which to extract the value char *SampleUtil_GetFirstElementItem(
* item -- The item to search for /*! [in] The DOM element from which to extract the value. */
* IXML_Element *element,
********************************************************************************/ /*! [in] The item to search for. */
char *SampleUtil_GetFirstElementItem(IN IXML_Element *element, IN const char *item); const char *item);
/******************************************************************************** /*!
* SampleUtil_PrintEventType * \brief Prints a callback event type as a string.
* */
* Description: void SampleUtil_PrintEventType(
* Prints a callback event type as a string. /*! [in] The callback event. */
* Upnp_EventType S);
* Parameters:
* S -- The callback event
*
********************************************************************************/
void SampleUtil_PrintEventType(IN Upnp_EventType S);
/******************************************************************************** /*!
* SampleUtil_PrintEvent * \brief Prints callback event structure details.
* */
* Description: int SampleUtil_PrintEvent(
* Prints callback event structure details. /*! [in] The type of callback event. */
* Upnp_EventType EventType,
* Parameters: /*! [in] The callback event structure. */
* EventType -- The type of callback event void *Event);
* Event -- The callback event structure
*
********************************************************************************/
int SampleUtil_PrintEvent(IN Upnp_EventType EventType,
IN void *Event);
/******************************************************************************** /*!
* SampleUtil_FindAndParseService * \brief This routine finds the first occurance of a service in a DOM
* * representation of a description document and parses it. Note that this
* Description: * function currently assumes that the eventURL and controlURL values in
* This routine finds the first occurance of a service in a DOM representation * the service definitions are full URLs. Relative URLs are not handled here.
* of a description document and parses it. Note that this function currently */
* assumes that the eventURL and controlURL values in the service definitions
* are full URLs. Relative URLs are not handled here.
*
* Parameters:
* DescDoc -- The DOM description document
* location -- The location of the description document
* serviceSearchType -- The type of service to search for
* serviceId -- OUT -- The service ID
* eventURL -- OUT -- The event URL for the service
* controlURL -- OUT -- The control URL for the service
*
********************************************************************************/
int SampleUtil_FindAndParseService ( int SampleUtil_FindAndParseService (
IN IXML_Document *DescDoc, /*! [in] The DOM description document. */
IN const char* location, IXML_Document *DescDoc,
IN char *serviceType, /*! [in] The location of the description document. */
OUT char **serviceId, const char *location,
OUT char **eventURL, /*! [in] The type of service to search for. */
OUT char **controlURL); const char *serviceType,
/*! [out] The service ID. */
char **serviceId,
/*! [out] The event URL for the service. */
char **eventURL,
/*! [out] The control URL for the service. */
char **controlURL);
/*!
/******************************************************************************** * \brief Prototype for displaying strings. All printing done by the device,
* print_string
*
* Description:
* Prototype for displaying strings. All printing done by the device,
* control point, and sample util, ultimately use this to display strings * control point, and sample util, ultimately use this to display strings
* to the user. * to the user.
* */
* Parameters: typedef void (*print_string)(
* const char * string. /*! [in] Format. */
* const char *string,
********************************************************************************/ /*! [in] Arguments. */
typedef void (*print_string)(const char *string); ...)
#if (__GNUC__ >= 3)
/* This enables printf like format checking by the compiler */
__attribute__((format (__printf__, 1, 2)))
#endif
;
//global print function used by sample util /*! global print function used by sample util */
extern print_string gPrintFun; extern print_string gPrintFun;
/******************************************************************************** /*!
* state_update * \brief Prototype for passing back state changes.
* */
* Description:
* Prototype for passing back state changes
*
* Parameters:
* const char * varName
* const char * varValue
* const char * UDN
* int newDevice
********************************************************************************/
typedef void (*state_update)( typedef void (*state_update)(
/*! [in] . */
const char *varName, const char *varName,
/*! [in] . */
const char *varValue, const char *varValue,
/*! [in] . */
const char *UDN, const char *UDN,
/*! [in] . */
eventType type); eventType type);
//global state update function used by smaple util /*! global state update function used by smaple util */
extern state_update gStateUpdateFun; extern state_update gStateUpdateFun;
/******************************************************************************** /*!
* SampleUtil_Initialize * \brief Initializes the sample util. Must be called before any sample util
*
* Description:
* Initializes the sample util. Must be called before any sample util
* functions. May be called multiple times. * functions. May be called multiple times.
* */
* Parameters: int SampleUtil_Initialize(
* print_function - print function to use in SampleUtil_Print /*! [in] Print function to use in SampleUtil_Print. */
* print_string print_function);
********************************************************************************/
int SampleUtil_Initialize(print_string print_function);
/******************************************************************************** /*!
* SampleUtil_Finish * \brief Releases Resources held by sample util.
* */
* Description:
* Releases Resources held by sample util.
*
* Parameters:
*
********************************************************************************/
int SampleUtil_Finish(); int SampleUtil_Finish();
/******************************************************************************** /*!
* SampleUtil_Print * \brief Function emulating printf that ultimately calls the registered print
*
* Description:
* Function emulating printf that ultimately calls the registered print
* function with the formatted string. * function with the formatted string.
* *
* Parameters: * Provides platform-specific print functionality. This function should be
* fmt - format (see printf) * called when you want to print content suitable for console output (i.e.,
* . . . - variable number of args. (see printf) * in a large text box or on a screen). If your device/operating system is
* not supported here, you should add a port.
* *
********************************************************************************/ * \return The same as printf.
int SampleUtil_Print(char *fmt, ...); */
int SampleUtil_Print(
/*! [in] Format (see printf). */
const char *fmt,
/*! [in] Format data. */
...)
#if (__GNUC__ >= 3)
/* This enables printf like format checking by the compiler */
__attribute__((format (__printf__, 1, 2)))
#endif
;
/******************************************************************************** /*!
* SampleUtil_RegisterUpdateFunction * \brief
* */
* Description: int SampleUtil_RegisterUpdateFunction(
* /*! [in] . */
* Parameters: state_update update_function);
*
********************************************************************************/
int SampleUtil_RegisterUpdateFunction(state_update update_function);
/******************************************************************************** /*!
* SampleUtil_StateUpdate * \brief
* */
* Description:
*
* Parameters:
*
********************************************************************************/
void SampleUtil_StateUpdate( void SampleUtil_StateUpdate(
/*! [in] . */
const char *varName, const char *varName,
/*! [in] . */
const char *varValue, const char *varValue,
/*! [in] . */
const char *UDN, const char *UDN,
/*! [in] . */
eventType type); eventType type);
/*!
* \brief Prints a string to standard out.
*/
void linux_print(const char *format, ...)
#if (__GNUC__ >= 3)
/* This enables printf like format checking by the compiler */
__attribute__((format (__printf__, 1, 2)))
#endif
;
#ifdef __cplusplus #ifdef __cplusplus
}; };
#endif /* __cplusplus */ #endif /* __cplusplus */
#ifdef WIN32 #ifdef WIN32
#define snprintf _snprintf #define snprintf _snprintf
#define strcasecmp stricmp #define strcasecmp stricmp
#endif #endif
#endif /* SAMPLE_UTIL_H */ #endif /* SAMPLE_UTIL_H */

File diff suppressed because it is too large Load Diff

View File

@@ -29,39 +29,36 @@
* *
**************************************************************************/ **************************************************************************/
#ifndef UPNP_TV_CTRLPT_H #ifndef UPNP_TV_CTRLPT_H
#define UPNP_TV_CTRLPT_H #define UPNP_TV_CTRLPT_H
/*!
* \file
*/
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#include "sample_util.h" #include "sample_util.h"
#include "ithread.h" #include "ithread.h"
#include "upnp.h" #include "upnp.h"
#include "UpnpString.h" #include "UpnpString.h"
#include "upnptools.h" #include "upnptools.h"
#include <signal.h> #include <signal.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#ifdef WIN32 #ifdef WIN32
/* Do not #include <unistd.h> */ /* Do not #include <unistd.h> */
#else #else
#include <unistd.h> #include <unistd.h>
#endif #endif
#define TV_SERVICE_SERVCOUNT 2 #define TV_SERVICE_SERVCOUNT 2
#define TV_SERVICE_CONTROL 0 #define TV_SERVICE_CONTROL 0
#define TV_SERVICE_PICTURE 1 #define TV_SERVICE_PICTURE 1
@@ -86,10 +83,8 @@ extern "C" {
/* This should be the maximum VARCOUNT from above */ /* This should be the maximum VARCOUNT from above */
#define TV_MAXVARS TV_PICTURE_VARCOUNT #define TV_MAXVARS TV_PICTURE_VARCOUNT
extern char TvDeviceType[]; extern const char *TvServiceName[];
extern char *TvServiceType[]; extern const char *TvVarName[TV_SERVICE_SERVCOUNT][TV_MAXVARS];
extern char *TvServiceName[];
extern char *TvVarName[TV_SERVICE_SERVCOUNT][TV_MAXVARS];
extern char TvVarCount[]; extern char TvVarCount[];
struct tv_service { struct tv_service {
@@ -127,9 +122,8 @@ int TvCtrlPointRemoveDevice(const char *);
int TvCtrlPointRemoveAll(void); int TvCtrlPointRemoveAll(void);
int TvCtrlPointRefresh(void); int TvCtrlPointRefresh(void);
int TvCtrlPointSendAction(int, int, const char *, const char **, char **, int);
int TvCtrlPointSendAction(int, int, char *, char **, char **, int); int TvCtrlPointSendActionNumericArg(int devnum, int service, const char *actionName, const char *paramName, int paramValue);
int TvCtrlPointSendActionNumericArg(int devnum, int service, char *actionName, char *paramName, int paramValue);
int TvCtrlPointSendPowerOn(int devnum); int TvCtrlPointSendPowerOn(int devnum);
int TvCtrlPointSendPowerOff(int devnum); int TvCtrlPointSendPowerOff(int devnum);
int TvCtrlPointSendSetChannel(int, int); int TvCtrlPointSendSetChannel(int, int);
@@ -139,7 +133,7 @@ int TvCtrlPointSendSetTint(int, int);
int TvCtrlPointSendSetContrast(int, int); int TvCtrlPointSendSetContrast(int, int);
int TvCtrlPointSendSetBrightness(int, int); int TvCtrlPointSendSetBrightness(int, int);
int TvCtrlPointGetVar(int, int, char*); int TvCtrlPointGetVar(int, int, const char *);
int TvCtrlPointGetPower(int devnum); int TvCtrlPointGetPower(int devnum);
int TvCtrlPointGetChannel(int); int TvCtrlPointGetChannel(int);
int TvCtrlPointGetVolume(int); int TvCtrlPointGetVolume(int);
@@ -153,19 +147,76 @@ int TvCtrlPointPrintList(void);
int TvCtrlPointPrintDevice(int); int TvCtrlPointPrintDevice(int);
void TvCtrlPointAddDevice(IXML_Document *, const char *, int); void TvCtrlPointAddDevice(IXML_Document *, const char *, int);
void TvCtrlPointHandleGetVar(const char *, const char *, const DOMString); void TvCtrlPointHandleGetVar(const char *, const char *, const DOMString);
void TvStateUpdate(char*,int, IXML_Document * , char **);
/*!
* \brief Update a Tv state table. Called when an event is received.
*
* Note: this function is NOT thread save. It must be called from another
* function that has locked the global device list.
**/
void TvStateUpdate(
/*! [in] The UDN of the parent device. */
char *UDN,
/*! [in] The service state table to update. */
int Service,
/*! [out] DOM document representing the XML received with the event. */
IXML_Document *ChangedVariables,
/*! [out] pointer to the state table for the Tv service to update. */
char **State);
void TvCtrlPointHandleEvent(const char *, int, IXML_Document *); void TvCtrlPointHandleEvent(const char *, int, IXML_Document *);
void TvCtrlPointHandleSubscribeUpdate(const char *, const Upnp_SID, int); void TvCtrlPointHandleSubscribeUpdate(const char *, const Upnp_SID, int);
int TvCtrlPointCallbackEventHandler(Upnp_EventType, void *, void *); int TvCtrlPointCallbackEventHandler(Upnp_EventType, void *, void *);
void TvCtrlPointVerifyTimeouts(int);
/*!
* \brief Checks the advertisement each device in the global device list.
*
* If an advertisement expires, the device is removed from the list.
*
* If an advertisement is about to expire, a search request is sent for that
* device.
*/
void TvCtrlPointVerifyTimeouts(
/*! [in] The increment to subtract from the timeouts each time the
* function is called. */
int incr);
void TvCtrlPointPrintCommands(void); void TvCtrlPointPrintCommands(void);
void* TvCtrlPointCommandLoop(void *); void* TvCtrlPointCommandLoop(void *);
int TvCtrlPointStart(print_string printFunctionPtr, state_update updateFunctionPtr); int TvCtrlPointStart(print_string printFunctionPtr, state_update updateFunctionPtr, int combo);
int TvCtrlPointStop(void); int TvCtrlPointStop(void);
int TvCtrlPointProcessCommand(char *cmdline); int TvCtrlPointProcessCommand(char *cmdline);
/*!
* \brief Print help info for this application.
*/
void TvCtrlPointPrintShortHelp(void);
/*!
* \brief Print long help info for this application.
*/
void TvCtrlPointPrintLongHelp(void);
/*!
* \briefPrint the list of valid command line commands to the user
*/
void TvCtrlPointPrintCommands(void);
/*!
* \brief Function that receives commands from the user at the command prompt
* during the lifetime of the device, and calls the appropriate
* functions for those commands.
*/
void *TvCtrlPointCommandLoop(void *args);
/*!
* \brief
*/
int TvCtrlPointProcessCommand(char *cmdline);
#ifdef __cplusplus #ifdef __cplusplus
}; };
#endif #endif
#endif //UPNP_TV_CTRLPT_H #endif /* UPNP_TV_CTRLPT_H */

View File

@@ -0,0 +1,566 @@
/**************************************************************************
*
* Copyright (c) 2000-2003 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
**************************************************************************/
#ifndef UPNP_TV_DEVICE_H
#define UPNP_TV_DEVICE_H
/*!
* \file
*/
#include <stdio.h>
#include <signal.h>
#ifdef __cplusplus
extern "C" {
#endif
#include "sample_util.h"
#include "ithread.h"
#include "upnp.h"
#include <stdlib.h>
#include <string.h>
#ifdef WIN32
/* Do not #include <unistd.h> */
#else
#include <unistd.h>
#endif
/*! Color constants */
#define MAX_COLOR 10
#define MIN_COLOR 1
/*! Brightness constants */
#define MAX_BRIGHTNESS 10
#define MIN_BRIGHTNESS 1
/*! Power constants */
#define POWER_ON 1
#define POWER_OFF 0
/*! Tint constants */
#define MAX_TINT 10
#define MIN_TINT 1
/*! Volume constants */
#define MAX_VOLUME 10
#define MIN_VOLUME 1
/*! Contrast constants */
#define MAX_CONTRAST 10
#define MIN_CONTRAST 1
/*! Channel constants */
#define MAX_CHANNEL 100
#define MIN_CHANNEL 1
/*! Number of services. */
#define TV_SERVICE_SERVCOUNT 2
/*! Index of control service */
#define TV_SERVICE_CONTROL 0
/*! Index of picture service */
#define TV_SERVICE_PICTURE 1
/*! Number of control variables */
#define TV_CONTROL_VARCOUNT 3
/*! Index of power variable */
#define TV_CONTROL_POWER 0
/*! Index of channel variable */
#define TV_CONTROL_CHANNEL 1
/*! Index of volume variable */
#define TV_CONTROL_VOLUME 2
/*! Number of picture variables */
#define TV_PICTURE_VARCOUNT 4
/*! Index of color variable */
#define TV_PICTURE_COLOR 0
/*! Index of tint variable */
#define TV_PICTURE_TINT 1
/*! Index of contrast variable */
#define TV_PICTURE_CONTRAST 2
/*! Index of brightness variable */
#define TV_PICTURE_BRIGHTNESS 3
/*! Max value length */
#define TV_MAX_VAL_LEN 5
/*! Max actions */
#define TV_MAXACTIONS 12
/*! This should be the maximum VARCOUNT from above */
#define TV_MAXVARS TV_PICTURE_VARCOUNT
/*!
* \brief Prototype for all actions. For each action that a service
* implements, there is a corresponding function with this prototype.
*
* Pointers to these functions, along with action names, are stored
* in the service table. When an action request comes in the action
* name is matched, and the appropriate function is called.
* Each function returns UPNP_E_SUCCESS, on success, and a nonzero
* error code on failure.
*/
typedef int (*upnp_action)(
/*! [in] Document of action request. */
IXML_Document *request,
/*! [out] Action result. */
IXML_Document **out,
/*! [out] Error string in case action was unsuccessful. */
const char **errorString);
/*! Structure for storing Tv Service identifiers and state table. */
struct TvService {
/*! Universally Unique Device Name. */
char UDN[NAME_SIZE];
/*! . */
char ServiceId[NAME_SIZE];
/*! . */
char ServiceType[NAME_SIZE];
/*! . */
const char *VariableName[TV_MAXVARS];
/*! . */
char *VariableStrVal[TV_MAXVARS];
/*! . */
const char *ActionNames[TV_MAXACTIONS];
/*! . */
upnp_action actions[TV_MAXACTIONS];
/*! . */
int VariableCount;
};
/*! Array of service structures */
extern struct TvService tv_service_table[];
/*! Device handle returned from sdk */
extern UpnpDevice_Handle device_handle;
/*! Mutex for protecting the global state table data
* in a multi-threaded, asynchronous environment.
* All functions should lock this mutex before reading
* or writing the state table data. */
extern ithread_mutex_t TVDevMutex;
/*!
* \brief Initializes the action table for the specified service.
*
* Note that knowledge of the service description is assumed.
* Action names are hardcoded.
*/
int SetActionTable(
/*! [in] one of TV_SERVICE_CONTROL or, TV_SERVICE_PICTURE. */
int serviceType,
/*! [in,out] service containing action table to set. */
struct TvService *out);
/*!
* \brief Initialize the device state table for this TvDevice, pulling
* identifier info from the description Document.
*
* Note that knowledge of the service description is assumed.
* State table variables and default values are currently hardcoded in
* this file rather than being read from service description documents.
*/
int TvDeviceStateTableInit(
/*! [in] The description document URL. */
char *DescDocURL);
/*!
* \brief Called during a subscription request callback.
*
* If the subscription request is for this device and either its
* control service or picture service, then accept it.
*/
int TvDeviceHandleSubscriptionRequest(
/*! [in] The subscription request event structure. */
struct Upnp_Subscription_Request *sr_event);
/*!
* \brief Called during a get variable request callback.
*
* If the request is for this device and either its control service or
* picture service, then respond with the variable value.
*/
int TvDeviceHandleGetVarRequest(
/*! [in,out] The control get variable request event structure. */
struct Upnp_State_Var_Request *cgv_event);
/*!
* \brief Called during an action request callback.
*
* If the request is for this device and either its control service
* or picture service, then perform the action and respond.
*/
int TvDeviceHandleActionRequest(
/*! [in,out] The control action request event structure. */
struct Upnp_Action_Request *ca_event);
/*!
* \brief The callback handler registered with the SDK while registering
* root device.
*
* Dispatches the request to the appropriate procedure
* based on the value of EventType. The four requests handled by the
* device are:
* \li 1) Event Subscription requests.
* \li 2) Get Variable requests.
* \li 3) Action requests.
*/
int TvDeviceCallbackEventHandler(
/*! [in] The type of callback event. */
Upnp_EventType,
/*! [in] Data structure containing event data. */
void *Event,
/*! [in] Optional data specified during callback registration. */
void *Cookie);
/*!
* \brief Update the TvDevice service state table, and notify all subscribed
* control points of the updated state.
*
* Note that since this function blocks on the mutex TVDevMutex,
* to avoid a hang this function should not be called within any other
* function that currently has this mutex locked.
*/
int TvDeviceSetServiceTableVar(
/*! [in] The service number (TV_SERVICE_CONTROL or TV_SERVICE_PICTURE). */
unsigned int service,
/*! [in] The variable number (TV_CONTROL_POWER, TV_CONTROL_CHANNEL,
* TV_CONTROL_VOLUME, TV_PICTURE_COLOR, TV_PICTURE_TINT,
* TV_PICTURE_CONTRAST, or TV_PICTURE_BRIGHTNESS). */
int variable,
/*! [in] The string representation of the new value. */
char *value);
/* Control Service Actions */
/*!
* \brief Turn the power on.
*/
int TvDevicePowerOn(
/*! [in] Document of action request. */
IXML_Document *in,
/*! [in] Action result. */
IXML_Document **out,
/*! [out] ErrorString in case action was unsuccessful. */
const char **errorString);
/*!
* \brief Turn the power off.
*/
int TvDevicePowerOff(
/*! [in] Document of action request. */
IXML_Document *in,
/*! [in] Action result. */
IXML_Document **out,
/*! [out] ErrorString in case action was unsuccessful. */
const char **errorString);
/*!
* \brief Change the channel, update the TvDevice control service
* state table, and notify all subscribed control points of the
* updated state.
*/
int TvDeviceSetChannel(
/*! [in] Document of action request. */
IXML_Document *in,
/*! [in] Action result. */
IXML_Document **out,
/*! [out] ErrorString in case action was unsuccessful. */
const char **errorString);
/*!
* \brief Increase the channel.
*/
int TvDeviceIncreaseChannel(
/*! [in] Document of action request. */
IXML_Document *in,
/*! [in] Action result. */
IXML_Document **out,
/*! [out] ErrorString in case action was unsuccessful. */
const char **errorString);
/*!
* \brief Decrease the channel.
*/
int TvDeviceDecreaseChannel(
/*! [in] Document of action request. */
IXML_Document *in,
/*! [in] Action result. */
IXML_Document **out,
/*! [out] ErrorString in case action was unsuccessful. */
const char **errorString);
/*!
* \brief Change the volume, update the TvDevice control service
* state table, and notify all subscribed control points of the
* updated state.
*/
int TvDeviceSetVolume(
/*! [in] Document of action request. */
IXML_Document *in,
/*! [in] Action result. */
IXML_Document **out,
/*! [out] ErrorString in case action was unsuccessful. */
const char **errorString);
/*!
* \brief Increase the volume.
*/
int TvDeviceIncreaseVolume(
/*! [in] Document of action request. */
IXML_Document *in,
/*! [in] Action result. */
IXML_Document **out,
/*! [out] ErrorString in case action was unsuccessful. */
const char **errorString);
/*!
* \brief Decrease the volume.
*/
int TvDeviceDecreaseVolume(
/*! [in] Document of action request. */
IXML_Document *in,
/*! [in] Action result. */
IXML_Document **out,
/*! [out] ErrorString in case action was unsuccessful. */
const char **errorString);
/*Picture Service Actions */
/*!
* \brief Change the color, update the TvDevice picture service
* state table, and notify all subscribed control points of the
* updated state.
*/
int TvDeviceSetColor(
/*! [in] Document of action request. */
IXML_Document *in,
/*! [in] Action result. */
IXML_Document **out,
/*! [out] ErrorString in case action was unsuccessful. */
const char **errorString);
/*!
* \brief Increase the color.
*/
int TvDeviceIncreaseColor(
/*! [in] Document of action request. */
IXML_Document *in,
/*! [in] Action result. */
IXML_Document **out,
/*! [out] ErrorString in case action was unsuccessful. */
const char **errorString);
/*!
* \brief Decrease the color.
*/
int TvDeviceDecreaseColor(
/*! [in] Document of action request. */
IXML_Document *in,
/*! [in] Action result. */
IXML_Document **out,
/*! [out] ErrorString in case action was unsuccessful. */
const char **errorString);
/*!
* \brief Change the tint, update the TvDevice picture service
* state table, and notify all subscribed control points of the
* updated state.
*/
int TvDeviceSetTint(
/*! [in] Document of action request. */
IXML_Document *in,
/*! [in] Action result. */
IXML_Document **out,
/*! [out] ErrorString in case action was unsuccessful. */
const char **errorString);
/*!
* \brief Increase tint.
*/
int TvDeviceIncreaseTint(
/*! [in] Document of action request. */
IXML_Document *in,
/*! [in] Action result. */
IXML_Document **out,
/*! [out] ErrorString in case action was unsuccessful. */
const char **errorString);
/*!
* \brief Decrease tint.
*/
int TvDeviceDecreaseTint(
/*! [in] Document of action request. */
IXML_Document *in,
/*! [in] Action result. */
IXML_Document **out,
/*! [out] ErrorString in case action was unsuccessful. */
const char **errorString);
/*!
* \brief Change the contrast, update the TvDevice picture service
* state table, and notify all subscribed control points of the
* updated state.
*/
int TvDeviceSetContrast(
/*! [in] Document of action request. */
IXML_Document *in,
/*! [in] Action result. */
IXML_Document **out,
/*! [out] ErrorString in case action was unsuccessful. */
const char **errorString);
/*!
* \brief Increase the contrast.
*/
int TvDeviceIncreaseContrast(
/*! [in] Document of action request. */
IXML_Document *in,
/*! [in] Action result. */
IXML_Document **out,
/*! [out] ErrorString in case action was unsuccessful. */
const char **errorString);
/*!
* \brief Decrease the contrast.
*/
int TvDeviceDecreaseContrast(
/*! [in] Document of action request. */
IXML_Document *in,
/*! [in] Action result. */
IXML_Document **out,
/*! [out] ErrorString in case action was unsuccessful. */
const char **errorString);
/*!
* \brief Change the brightness, update the TvDevice picture service
* state table, and notify all subscribed control points of the
* updated state.
*/
int TvDeviceSetBrightness(
/*! [in] Document of action request. */
IXML_Document *in,
/*! [in] Action result. */
IXML_Document **out,
/*! [out] ErrorString in case action was unsuccessful. */
const char **errorString);
/*!
* \brief Increase brightnesss.
*/
int TvDeviceIncreaseBrightness(
/*! [in] Document of action request. */
IXML_Document *in,
/*! [in] Action result. */
IXML_Document **out,
/*! [out] ErrorString in case action was unsuccessful. */
const char **errorString);
/*!
* \brief Decrease brightnesss.
*/
int TvDeviceDecreaseBrightness(
/*! [in] Document of action request. */
IXML_Document *in,
/*! [in] Action result. */
IXML_Document **out,
/*! [out] ErrorString in case action was unsuccessful. */
const char **errorString);
/*!
* \brief Initializes the UPnP Sdk, registers the device, and sends out
* advertisements.
*/
int TvDeviceStart(
/*! [in] ip address to initialize the sdk (may be NULL)
* if null, then the first non null loopback address is used. */
char *ip_address,
/*! [in] port number to initialize the sdk (may be 0)
* if zero, then a random number is used. */
unsigned short port,
/*! [in] name of description document.
* may be NULL. Default is tvdevicedesc.xml. */
const char *desc_doc_name,
/*! [in] path of web directory.
* may be NULL. Default is ./web (for Linux) or ../tvdevice/web. */
const char *web_dir_path,
/*! [in] print function to use. */
print_string pfun,
/*! [in] Non-zero if called from the combo application. */
int combo);
/*!
* \brief Stops the device. Uninitializes the sdk.
*/
int TvDeviceStop(void);
/*!
* \brief Function that receives commands from the user at the command prompt
* during the lifetime of the device, and calls the appropriate
* functions for those commands. Only one command, exit, is currently
* defined.
*/
void *TvDeviceCommandLoop(void *args);
/*!
* \brief Main entry point for tv device application.
*
* Initializes and registers with the sdk.
* Initializes the state stables of the service.
* Starts the command loop.
*
* Accepts the following optional arguments:
* \li \c -ip ipaddress
* \li \c -port port
* \li \c -desc desc_doc_name
* \li \c -webdir web_dir_path
* \li \c -help
*/
int device_main(int argc, char *argv[]);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,72 @@
/*******************************************************************************
*
* Copyright (c) 2000-2003 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************/
#include "sample_util.h"
#include "tv_ctrlpt.h"
#include "tv_device.h"
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
int rc;
ithread_t cmdloop_thread;
#ifdef WIN32
#else
int sig;
sigset_t sigs_to_catch;
#endif
int code;
device_main(argc, argv);
rc = TvCtrlPointStart(linux_print, NULL, 1);
if (rc != TV_SUCCESS) {
SampleUtil_Print("Error starting UPnP TV Control Point\n");
return rc;
}
/* start a command loop thread */
code = ithread_create(&cmdloop_thread, NULL, TvCtrlPointCommandLoop, NULL);
#ifdef WIN32
ithread_join(cmdloop_thread, NULL);
#else
/* Catch Ctrl-C and properly shutdown */
sigemptyset(&sigs_to_catch);
sigaddset(&sigs_to_catch, SIGINT);
sigwait(&sigs_to_catch, &sig);
SampleUtil_Print("Shutting down on signal %d...\n", sig);
#endif
TvDeviceStop();
rc = TvCtrlPointStop();
return rc;
}

View File

@@ -0,0 +1,72 @@
/*******************************************************************************
*
* Copyright (c) 2000-2003 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************/
#include "sample_util.h"
#include "tv_ctrlpt.h"
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv)
{
int rc;
ithread_t cmdloop_thread;
#ifdef WIN32
#else
int sig;
sigset_t sigs_to_catch;
#endif
int code;
rc = TvCtrlPointStart(linux_print, NULL, 0);
if (rc != TV_SUCCESS) {
SampleUtil_Print("Error starting UPnP TV Control Point\n");
return rc;
}
/* start a command loop thread */
code = ithread_create(&cmdloop_thread, NULL, TvCtrlPointCommandLoop, NULL);
#ifdef WIN32
ithread_join(cmdloop_thread, NULL);
#else
/* Catch Ctrl-C and properly shutdown */
sigemptyset(&sigs_to_catch);
sigaddset(&sigs_to_catch, SIGINT);
sigwait(&sigs_to_catch, &sig);
SampleUtil_Print("Shutting down on signal %d...\n", sig);
#endif
rc = TvCtrlPointStop();
return rc;
argc = argc;
argv = argv;
}

View File

@@ -0,0 +1,65 @@
/*******************************************************************************
*
* Copyright (c) 2000-2003 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************/
#include "sample_util.h"
#include "tv_device.h"
#include <stdarg.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
int rc;
ithread_t cmdloop_thread;
#ifdef WIN32
#else
int sig;
sigset_t sigs_to_catch;
#endif
int code;
device_main(argc, argv);
/* start a command loop thread */
code = ithread_create(&cmdloop_thread, NULL, TvDeviceCommandLoop, NULL);
#ifdef WIN32
ithread_join(cmdloop_thread, NULL);
#else
/* Catch Ctrl-C and properly shutdown */
sigemptyset(&sigs_to_catch);
sigaddset(&sigs_to_catch, SIGINT);
sigwait(&sigs_to_catch, &sig);
SampleUtil_Print("Shutting down on signal %d...\n", sig);
#endif
rc = TvDeviceStop();
return rc;
}

View File

@@ -1,491 +0,0 @@
/*******************************************************************************
*
* Copyright (c) 2000-2003 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************/
#include "sample_util.h"
#include "upnp_tv_ctrlpt.h"
#include "upnp_tv_device.h"
#include <stdio.h>
#include <string.h>
/*
Tags for valid commands issued at the command prompt
*/
enum cmdloop_tvcmds {
PRTHELP = 0, PRTFULLHELP, POWON, POWOFF,
SETCHAN, SETVOL, SETCOL, SETTINT, SETCONT, SETBRT,
CTRLACTION, PICTACTION, CTRLGETVAR, PICTGETVAR,
PRTDEV, LSTDEV, REFRESH, EXITCMD
};
/*
Data structure for parsing commands from the command line
*/
struct cmdloop_commands {
char *str; // the string
int cmdnum; // the command
int numargs; // the number of arguments
char *args; // the args
} cmdloop_commands;
/*
Mappings between command text names, command tag,
and required command arguments for command line
commands
*/
static struct cmdloop_commands cmdloop_cmdlist[] = {
{"Help", PRTHELP, 1, ""},
{"HelpFull", PRTFULLHELP, 1, ""},
{"ListDev", LSTDEV, 1, ""},
{"Refresh", REFRESH, 1, ""},
{"PrintDev", PRTDEV, 2, "<devnum>"},
{"PowerOn", POWON, 2, "<devnum>"},
{"PowerOff", POWOFF, 2, "<devnum>"},
{"SetChannel", SETCHAN, 3, "<devnum> <channel (int)>"},
{"SetVolume", SETVOL, 3, "<devnum> <volume (int)>"},
{"SetColor", SETCOL, 3, "<devnum> <color (int)>"},
{"SetTint", SETTINT, 3, "<devnum> <tint (int)>"},
{"SetContrast", SETCONT, 3, "<devnum> <contrast (int)>"},
{"SetBrightness", SETBRT, 3, "<devnum> <brightness (int)>"},
{"CtrlAction", CTRLACTION, 2, "<devnum> <action (string)>"},
{"PictAction", PICTACTION, 2, "<devnum> <action (string)>"},
{"CtrlGetVar", CTRLGETVAR, 2, "<devnum> <varname (string)>"},
{"PictGetVar", PICTGETVAR, 2, "<devnum> <varname (string)>"},
{"Exit", EXITCMD, 1, ""}
};
void
linux_print( const char *string )
{
puts( string );
}
/********************************************************************************
* TvCtrlPointPrintHelp
*
* Description:
* Print help info for this application.
********************************************************************************/
void
TvCtrlPointPrintShortHelp( void )
{
SampleUtil_Print( "Commands:" );
SampleUtil_Print( " Help" );
SampleUtil_Print( " HelpFull" );
SampleUtil_Print( " ListDev" );
SampleUtil_Print( " Refresh" );
SampleUtil_Print( " PrintDev <devnum>" );
SampleUtil_Print( " PowerOn <devnum>" );
SampleUtil_Print( " PowerOff <devnum>" );
SampleUtil_Print( " SetChannel <devnum> <channel>" );
SampleUtil_Print( " SetVolume <devnum> <volume>" );
SampleUtil_Print( " SetColor <devnum> <color>" );
SampleUtil_Print( " SetTint <devnum> <tint>" );
SampleUtil_Print( " SetContrast <devnum> <contrast>" );
SampleUtil_Print( " SetBrightness <devnum> <brightness>" );
SampleUtil_Print( " CtrlAction <devnum> <action>" );
SampleUtil_Print( " PictAction <devnum> <action>" );
SampleUtil_Print( " CtrlGetVar <devnum> <varname>" );
SampleUtil_Print( " PictGetVar <devnum> <action>" );
SampleUtil_Print( " Exit" );
}
void
TvCtrlPointPrintLongHelp( void )
{
SampleUtil_Print( "" );
SampleUtil_Print( "******************************" );
SampleUtil_Print( "* TV Control Point Help Info *" );
SampleUtil_Print( "******************************" );
SampleUtil_Print( "" );
SampleUtil_Print( "This sample control point application automatically searches" );
SampleUtil_Print( "for and subscribes to the services of television device emulator" );
SampleUtil_Print( "devices, described in the tvdevicedesc.xml description document." );
SampleUtil_Print( "It also registers itself as a tv device." );
SampleUtil_Print( "" );
SampleUtil_Print( "Commands:" );
SampleUtil_Print( " Help" );
SampleUtil_Print( " Print this help info." );
SampleUtil_Print( " ListDev" );
SampleUtil_Print( " Print the current list of TV Device Emulators that this" );
SampleUtil_Print( " control point is aware of. Each device is preceded by a" );
SampleUtil_Print( " device number which corresponds to the devnum argument of" );
SampleUtil_Print( " commands listed below." );
SampleUtil_Print( " Refresh" );
SampleUtil_Print( " Delete all of the devices from the device list and issue new" );
SampleUtil_Print( " search request to rebuild the list from scratch." );
SampleUtil_Print( " PrintDev <devnum>" );
SampleUtil_Print( " Print the state table for the device <devnum>." );
SampleUtil_Print( " e.g., 'PrintDev 1' prints the state table for the first" );
SampleUtil_Print( " device in the device list." );
SampleUtil_Print( " PowerOn <devnum>" );
SampleUtil_Print( " Sends the PowerOn action to the Control Service of" );
SampleUtil_Print( " device <devnum>." );
SampleUtil_Print( " PowerOff <devnum>" );
SampleUtil_Print( " Sends the PowerOff action to the Control Service of" );
SampleUtil_Print( " device <devnum>." );
SampleUtil_Print( " SetChannel <devnum> <channel>" );
SampleUtil_Print( " Sends the SetChannel action to the Control Service of" );
SampleUtil_Print( " device <devnum>, requesting the channel to be changed" );
SampleUtil_Print( " to <channel>." );
SampleUtil_Print( " SetVolume <devnum> <volume>" );
SampleUtil_Print( " Sends the SetVolume action to the Control Service of" );
SampleUtil_Print( " device <devnum>, requesting the volume to be changed" );
SampleUtil_Print( " to <volume>." );
SampleUtil_Print( " SetColor <devnum> <color>" );
SampleUtil_Print( " Sends the SetColor action to the Control Service of" );
SampleUtil_Print( " device <devnum>, requesting the color to be changed" );
SampleUtil_Print( " to <color>." );
SampleUtil_Print( " SetTint <devnum> <tint>" );
SampleUtil_Print( " Sends the SetTint action to the Control Service of" );
SampleUtil_Print( " device <devnum>, requesting the tint to be changed" );
SampleUtil_Print( " to <tint>." );
SampleUtil_Print( " SetContrast <devnum> <contrast>" );
SampleUtil_Print( " Sends the SetContrast action to the Control Service of" );
SampleUtil_Print( " device <devnum>, requesting the contrast to be changed" );
SampleUtil_Print( " to <contrast>." );
SampleUtil_Print( " SetBrightness <devnum> <brightness>" );
SampleUtil_Print( " Sends the SetBrightness action to the Control Service of" );
SampleUtil_Print( " device <devnum>, requesting the brightness to be changed" );
SampleUtil_Print( " to <brightness>." );
SampleUtil_Print( " CtrlAction <devnum> <action>" );
SampleUtil_Print( " Sends an action request specified by the string <action>" );
SampleUtil_Print( " to the Control Service of device <devnum>. This command" );
SampleUtil_Print( " only works for actions that have no arguments." );
SampleUtil_Print( " (e.g., \"CtrlAction 1 IncreaseChannel\")" );
SampleUtil_Print( " PictAction <devnum> <action>" );
SampleUtil_Print( " Sends an action request specified by the string <action>" );
SampleUtil_Print( " to the Picture Service of device <devnum>. This command" );
SampleUtil_Print( " only works for actions that have no arguments." );
SampleUtil_Print( " (e.g., \"PictAction 1 DecreaseContrast\")" );
SampleUtil_Print( " CtrlGetVar <devnum> <varname>" );
SampleUtil_Print( " Requests the value of a variable specified by the string <varname>" );
SampleUtil_Print( " from the Control Service of device <devnum>." );
SampleUtil_Print( " (e.g., \"CtrlGetVar 1 Volume\")" );
SampleUtil_Print( " PictGetVar <devnum> <action>" );
SampleUtil_Print( " Requests the value of a variable specified by the string <varname>" );
SampleUtil_Print( " from the Picture Service of device <devnum>." );
SampleUtil_Print( " (e.g., \"PictGetVar 1 Tint\")" );
SampleUtil_Print( " Exit" );
SampleUtil_Print( " Exits the control point application." );
}
/********************************************************************************
* TvCtrlPointPrintCommands
*
* Description:
* Print the list of valid command line commands to the user
*
* Parameters:
* None
*
********************************************************************************/
void
TvCtrlPointPrintCommands()
{
int i;
int numofcmds = sizeof( cmdloop_cmdlist ) / sizeof( cmdloop_commands );
SampleUtil_Print( "Valid Commands:" );
for( i = 0; i < numofcmds; i++ ) {
SampleUtil_Print( " %-14s %s", cmdloop_cmdlist[i].str,
cmdloop_cmdlist[i].args );
}
SampleUtil_Print( "" );
}
/********************************************************************************
* TvCtrlPointCommandLoop
*
* Description:
* Function that receives commands from the user at the command prompt
* during the lifetime of the control point, and calls the appropriate
* functions for those commands.
*
* Parameters:
* None
*
********************************************************************************/
void *
TvCtrlPointCommandLoop( void *args )
{
char cmdline[100];
while( 1 ) {
SampleUtil_Print( "\n>> " );
fgets( cmdline, 100, stdin );
TvCtrlPointProcessCommand( cmdline );
}
return NULL;
}
int
TvCtrlPointProcessCommand( char *cmdline )
{
char cmd[100];
char strarg[100];
int arg_val_err = -99999;
int arg1 = arg_val_err;
int arg2 = arg_val_err;
int cmdnum = -1;
int numofcmds = sizeof( cmdloop_cmdlist ) / sizeof( cmdloop_commands );
int cmdfound = 0;
int i,
rc;
int invalidargs = 0;
int validargs;
validargs = sscanf( cmdline, "%s %d %d", cmd, &arg1, &arg2 );
for( i = 0; i < numofcmds; i++ ) {
if( strcasecmp( cmd, cmdloop_cmdlist[i].str ) == 0 ) {
cmdnum = cmdloop_cmdlist[i].cmdnum;
cmdfound++;
if( validargs != cmdloop_cmdlist[i].numargs )
invalidargs++;
break;
}
}
if( !cmdfound ) {
SampleUtil_Print( "Command not found; try 'Help'" );
return TV_SUCCESS;
}
if( invalidargs ) {
SampleUtil_Print( "Invalid arguments; try 'Help'" );
return TV_SUCCESS;
}
switch ( cmdnum ) {
case PRTHELP:
TvCtrlPointPrintShortHelp();
break;
case PRTFULLHELP:
TvCtrlPointPrintLongHelp();
break;
case POWON:
TvCtrlPointSendPowerOn( arg1 );
break;
case POWOFF:
TvCtrlPointSendPowerOff( arg1 );
break;
case SETCHAN:
TvCtrlPointSendSetChannel( arg1, arg2 );
break;
case SETVOL:
TvCtrlPointSendSetVolume( arg1, arg2 );
break;
case SETCOL:
TvCtrlPointSendSetColor( arg1, arg2 );
break;
case SETTINT:
TvCtrlPointSendSetTint( arg1, arg2 );
break;
case SETCONT:
TvCtrlPointSendSetContrast( arg1, arg2 );
break;
case SETBRT:
TvCtrlPointSendSetBrightness( arg1, arg2 );
break;
case CTRLACTION:
/*
re-parse commandline since second arg is string
*/
validargs = sscanf( cmdline, "%s %d %s", cmd, &arg1, strarg );
if( 3 == validargs )
TvCtrlPointSendAction( TV_SERVICE_CONTROL, arg1, strarg,
NULL, NULL, 0 );
else
invalidargs++;
break;
case PICTACTION:
/*
re-parse commandline since second arg is string
*/
validargs = sscanf( cmdline, "%s %d %s", cmd, &arg1, strarg );
if( 3 == validargs )
TvCtrlPointSendAction( TV_SERVICE_PICTURE, arg1, strarg,
NULL, NULL, 0 );
else
invalidargs++;
break;
case CTRLGETVAR:
/*
re-parse commandline since second arg is string
*/
validargs = sscanf( cmdline, "%s %d %s", cmd, &arg1, strarg );
if( 3 == validargs )
TvCtrlPointGetVar( TV_SERVICE_CONTROL, arg1, strarg );
else
invalidargs++;
break;
case PICTGETVAR:
/*
re-parse commandline since second arg is string
*/
validargs = sscanf( cmdline, "%s %d %s", cmd, &arg1, strarg );
if( 3 == validargs )
TvCtrlPointGetVar( TV_SERVICE_PICTURE, arg1, strarg );
else
invalidargs++;
break;
case PRTDEV:
TvCtrlPointPrintDevice( arg1 );
break;
case LSTDEV:
TvCtrlPointPrintList();
break;
case REFRESH:
TvCtrlPointRefresh();
break;
case EXITCMD:
rc = TvCtrlPointStop();
exit( rc );
break;
default:
SampleUtil_Print( "Command not implemented; see 'Help'" );
break;
}
if( invalidargs )
SampleUtil_Print( "Invalid args in command; see 'Help'" );
return TV_SUCCESS;
}
int
device_main( int argc, char **argv )
{
unsigned int portTemp = 0;
char *ip_address = NULL,
*desc_doc_name = NULL,
*web_dir_path = NULL;
unsigned int port = 0;
int i = 0;
SampleUtil_Initialize( linux_print );
// Parse options
for( i = 1; i < argc; i++ ) {
if( strcmp( argv[i], "-ip" ) == 0 ) {
ip_address = argv[++i];
} else if( strcmp( argv[i], "-port" ) == 0 ) {
sscanf( argv[++i], "%u", &portTemp );
} else if( strcmp( argv[i], "-desc" ) == 0 ) {
desc_doc_name = argv[++i];
} else if( strcmp( argv[i], "-webdir" ) == 0 ) {
web_dir_path = argv[++i];
} else if( strcmp( argv[i], "-help" ) == 0 ) {
SampleUtil_Print( "Usage: %s -ip ipaddress -port port"
" -desc desc_doc_name -webdir web_dir_path"
" -help (this message)\n", argv[0] );
SampleUtil_Print( "\tipaddress: IP address of the device"
" (must match desc. doc)\n" );
SampleUtil_Print( "\t\te.g.: 192.168.0.4\n" );
SampleUtil_Print( "\tport: Port number to use for "
"receiving UPnP messages (must match desc. doc)\n" );
SampleUtil_Print( "\t\te.g.: 5431\n" );
SampleUtil_Print
( "\tdesc_doc_name: name of device description document\n" );
SampleUtil_Print( "\t\te.g.: tvcombodesc.xml\n" );
SampleUtil_Print
( "\tweb_dir_path: Filesystem path where web files "
"related to the device are stored\n" );
SampleUtil_Print( "\t\te.g.: /upnp/sample/web\n" );
return 1;
}
}
port = ( unsigned short )portTemp;
return TvDeviceStart( ip_address, port, desc_doc_name, web_dir_path, linux_print );
}
int main( int argc, char **argv )
{
int rc;
ithread_t cmdloop_thread;
#ifdef WIN32
#else
int sig;
sigset_t sigs_to_catch;
#endif
int code;
device_main(argc, argv);
rc = TvCtrlPointStart( linux_print, NULL );
if( rc != TV_SUCCESS ) {
SampleUtil_Print( "Error starting UPnP TV Control Point" );
return rc;
}
/* start a command loop thread */
code = ithread_create( &cmdloop_thread, NULL, TvCtrlPointCommandLoop, NULL );
#ifdef WIN32
ithread_join(cmdloop_thread, NULL);
#else
/*
Catch Ctrl-C and properly shutdown
*/
sigemptyset( &sigs_to_catch );
sigaddset( &sigs_to_catch, SIGINT );
sigwait( &sigs_to_catch, &sig );
SampleUtil_Print( "Shutting down on signal %d...\n", sig );
#endif
TvDeviceStop();
rc = TvCtrlPointStop();
return rc;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,171 +0,0 @@
/**************************************************************************
*
* Copyright (c) 2000-2003 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
**************************************************************************/
#ifndef UPNP_TV_CTRLPT_H
#define UPNP_TV_CTRLPT_H
#ifdef __cplusplus
extern "C" {
#endif
#include "sample_util.h"
#include "ithread.h"
#include "upnp.h"
#include "UpnpString.h"
#include "upnptools.h"
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef WIN32
/* Do not #include <unistd.h> */
#else
#include <unistd.h>
#endif
#define TV_SERVICE_SERVCOUNT 2
#define TV_SERVICE_CONTROL 0
#define TV_SERVICE_PICTURE 1
#define TV_CONTROL_VARCOUNT 3
#define TV_CONTROL_POWER 0
#define TV_CONTROL_CHANNEL 1
#define TV_CONTROL_VOLUME 2
#define TV_PICTURE_VARCOUNT 4
#define TV_PICTURE_COLOR 0
#define TV_PICTURE_TINT 1
#define TV_PICTURE_CONTRAST 2
#define TV_PICTURE_BRIGHTNESS 3
#define TV_MAX_VAL_LEN 5
#define TV_SUCCESS 0
#define TV_ERROR (-1)
#define TV_WARNING 1
/* This should be the maximum VARCOUNT from above */
#define TV_MAXVARS TV_PICTURE_VARCOUNT
extern char TvDeviceType[];
extern char *TvServiceType[];
extern char *TvServiceName[];
extern char *TvVarName[TV_SERVICE_SERVCOUNT][TV_MAXVARS];
extern char TvVarCount[];
struct tv_service {
char ServiceId[NAME_SIZE];
char ServiceType[NAME_SIZE];
char *VariableStrVal[TV_MAXVARS];
char EventURL[NAME_SIZE];
char ControlURL[NAME_SIZE];
char SID[NAME_SIZE];
};
extern struct TvDeviceNode *GlobalDeviceList;
struct TvDevice {
char UDN[250];
char DescDocURL[250];
char FriendlyName[250];
char PresURL[250];
int AdvrTimeOut;
struct tv_service TvService[TV_SERVICE_SERVCOUNT];
};
struct TvDeviceNode {
struct TvDevice device;
struct TvDeviceNode *next;
};
extern ithread_mutex_t DeviceListMutex;
extern UpnpClient_Handle ctrlpt_handle;
void TvCtrlPointPrintHelp(void);
int TvCtrlPointDeleteNode(struct TvDeviceNode *);
int TvCtrlPointRemoveDevice(const char *);
int TvCtrlPointRemoveAll(void);
int TvCtrlPointRefresh(void);
int TvCtrlPointSendAction(int, int, char *, char **, char **, int);
int TvCtrlPointSendActionNumericArg(int devnum, int service, char *actionName, char *paramName, int paramValue);
int TvCtrlPointSendPowerOn(int devnum);
int TvCtrlPointSendPowerOff(int devnum);
int TvCtrlPointSendSetChannel(int, int);
int TvCtrlPointSendSetVolume(int, int);
int TvCtrlPointSendSetColor(int, int);
int TvCtrlPointSendSetTint(int, int);
int TvCtrlPointSendSetContrast(int, int);
int TvCtrlPointSendSetBrightness(int, int);
int TvCtrlPointGetVar(int, int, char*);
int TvCtrlPointGetPower(int devnum);
int TvCtrlPointGetChannel(int);
int TvCtrlPointGetVolume(int);
int TvCtrlPointGetColor(int);
int TvCtrlPointGetTint(int);
int TvCtrlPointGetContrast(int);
int TvCtrlPointGetBrightness(int);
int TvCtrlPointGetDevice(int, struct TvDeviceNode **);
int TvCtrlPointPrintList(void);
int TvCtrlPointPrintDevice(int);
void TvCtrlPointAddDevice(IXML_Document *, const char *, int);
void TvCtrlPointHandleGetVar(const char *, const char *, const DOMString);
void TvStateUpdate(char*,int, IXML_Document * , char **);
void TvCtrlPointHandleEvent(const char *, int, IXML_Document *);
void TvCtrlPointHandleSubscribeUpdate(const char *, const Upnp_SID, int);
int TvCtrlPointCallbackEventHandler(Upnp_EventType, void *, void *);
void TvCtrlPointVerifyTimeouts(int);
void TvCtrlPointPrintCommands(void);
void* TvCtrlPointCommandLoop(void *);
int TvCtrlPointStart(print_string printFunctionPtr, state_update updateFunctionPtr);
int TvCtrlPointStop(void);
int TvCtrlPointProcessCommand(char *cmdline);
#ifdef __cplusplus
};
#endif
#endif //UPNP_TV_CTRLPT_H

View File

@@ -1,632 +0,0 @@
/**************************************************************************
*
* Copyright (c) 2000-2003 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
**************************************************************************/
#ifndef UPNP_TV_DEVICE_H
#define UPNP_TV_DEVICE_H
#include <stdio.h>
#include <signal.h>
#ifdef __cplusplus
extern "C" {
#endif
#include "sample_util.h"
#include "ithread.h"
#include "upnp.h"
#include <stdlib.h>
#include <string.h>
#ifdef WIN32
/* Do not #include <unistd.h> */
#else
#include <unistd.h>
#endif
//Color constants
#define MAX_COLOR 10
#define MIN_COLOR 1
//Brightness constants
#define MAX_BRIGHTNESS 10
#define MIN_BRIGHTNESS 1
//Power constants
#define POWER_ON 1
#define POWER_OFF 0
//Tint constants
#define MAX_TINT 10
#define MIN_TINT 1
//Volume constants
#define MAX_VOLUME 10
#define MIN_VOLUME 1
//Contrast constants
#define MAX_CONTRAST 10
#define MIN_CONTRAST 1
//Channel constants
#define MAX_CHANNEL 100
#define MIN_CHANNEL 1
//Number of services.
#define TV_SERVICE_SERVCOUNT 2
//Index of control service
#define TV_SERVICE_CONTROL 0
//Index of picture service
#define TV_SERVICE_PICTURE 1
//Number of control variables
#define TV_CONTROL_VARCOUNT 3
//Index of power variable
#define TV_CONTROL_POWER 0
//Index of channel variable
#define TV_CONTROL_CHANNEL 1
//Index of volume variable
#define TV_CONTROL_VOLUME 2
//Number of picture variables
#define TV_PICTURE_VARCOUNT 4
//Index of color variable
#define TV_PICTURE_COLOR 0
//Index of tint variable
#define TV_PICTURE_TINT 1
//Index of contrast variable
#define TV_PICTURE_CONTRAST 2
//Index of brightness variable
#define TV_PICTURE_BRIGHTNESS 3
//Max value length
#define TV_MAX_VAL_LEN 5
//Max actions
#define TV_MAXACTIONS 12
/* This should be the maximum VARCOUNT from above */
#define TV_MAXVARS TV_PICTURE_VARCOUNT
extern char TvDeviceType[];
extern char *TvServiceType[];
/******************************************************************************
* upnp_action
*
* Description:
* Prototype for all actions. For each action that a service
* implements, there is a corresponding function with this prototype.
* Pointers to these functions, along with action names, are stored
* in the service table. When an action request comes in the action
* name is matched, and the appropriate function is called.
* Each function returns UPNP_E_SUCCESS, on success, and a nonzero
* error code on failure.
*
* Parameters:
*
* IXML_Document * request - document of action request
* IXML_Document **out - action result
* char **errorString - errorString (in case action was unsuccessful)
*
*****************************************************************************/
typedef int (*upnp_action) (IXML_Document *request, IXML_Document **out, char **errorString);
/* Structure for storing Tv Service
identifiers and state table */
struct TvService {
char UDN[NAME_SIZE]; /* Universally Unique Device Name */
char ServiceId[NAME_SIZE];
char ServiceType[NAME_SIZE];
char *VariableName[TV_MAXVARS];
char *VariableStrVal[TV_MAXVARS];
char *ActionNames[TV_MAXACTIONS];
upnp_action actions[TV_MAXACTIONS];
unsigned int VariableCount;
};
//Array of service structures
extern struct TvService tv_service_table[];
//Device handle returned from sdk
extern UpnpDevice_Handle device_handle;
/* Mutex for protecting the global state table data
in a multi-threaded, asynchronous environment.
All functions should lock this mutex before reading
or writing the state table data. */
extern ithread_mutex_t TVDevMutex;
/******************************************************************************
* SetActionTable
*
* Description:
* Initializes the action table for the specified service.
* Note that
* knowledge of the service description is
* assumed. Action names are hardcoded.
* Parameters:
* int serviceType - one of TV_SERVICE_CONTROL or, TV_SERVICE_PICTURE
* struct TvService *out - service containing action table to set.
*
*****************************************************************************/
int SetActionTable(int serviceType, struct TvService *out);
/******************************************************************************
* TvDeviceStateTableInit
*
* Description:
* Initialize the device state table for
* this TvDevice, pulling identifier info
* from the description Document. Note that
* knowledge of the service description is
* assumed. State table variables and default
* values are currently hardcoded in this file
* rather than being read from service description
* documents.
*
* Parameters:
* DescDocURL -- The description document URL
*
*****************************************************************************/
int TvDeviceStateTableInit(char*);
/******************************************************************************
* TvDeviceHandleSubscriptionRequest
*
* Description:
* Called during a subscription request callback. If the
* subscription request is for this device and either its
* control service or picture service, then accept it.
*
* Parameters:
* sr_event -- The subscription request event structure
*
*****************************************************************************/
int TvDeviceHandleSubscriptionRequest(struct Upnp_Subscription_Request *);
/******************************************************************************
* TvDeviceHandleGetVarRequest
*
* Description:
* Called during a get variable request callback. If the
* request is for this device and either its control service
* or picture service, then respond with the variable value.
*
* Parameters:
* cgv_event -- The control get variable request event structure
*
*****************************************************************************/
int TvDeviceHandleGetVarRequest(struct Upnp_State_Var_Request *);
/******************************************************************************
* TvDeviceHandleActionRequest
*
* Description:
* Called during an action request callback. If the
* request is for this device and either its control service
* or picture service, then perform the action and respond.
*
* Parameters:
* ca_event -- The control action request event structure
*
*****************************************************************************/
int TvDeviceHandleActionRequest(struct Upnp_Action_Request *);
/******************************************************************************
* TvDeviceCallbackEventHandler
*
* Description:
* The callback handler registered with the SDK while registering
* root device. Dispatches the request to the appropriate procedure
* based on the value of EventType. The four requests handled by the
* device are:
* 1) Event Subscription requests.
* 2) Get Variable requests.
* 3) Action requests.
*
* Parameters:
*
* EventType -- The type of callback event
* Event -- Data structure containing event data
* Cookie -- Optional data specified during callback registration
*
*****************************************************************************/
int TvDeviceCallbackEventHandler(Upnp_EventType, void*, void*);
/******************************************************************************
* TvDeviceSetServiceTableVar
*
* Description:
* Update the TvDevice service state table, and notify all subscribed
* control points of the updated state. Note that since this function
* blocks on the mutex TVDevMutex, to avoid a hang this function should
* not be called within any other function that currently has this mutex
* locked.
*
* Parameters:
* service -- The service number (TV_SERVICE_CONTROL or TV_SERVICE_PICTURE)
* variable -- The variable number (TV_CONTROL_POWER, TV_CONTROL_CHANNEL,
* TV_CONTROL_VOLUME, TV_PICTURE_COLOR, TV_PICTURE_TINT,
* TV_PICTURE_CONTRAST, or TV_PICTURE_BRIGHTNESS)
* value -- The string representation of the new value
*
*****************************************************************************/
int TvDeviceSetServiceTableVar(unsigned int, unsigned int, char*);
//Control Service Actions
/******************************************************************************
* TvDevicePowerOn
*
* Description:
* Turn the power on.
*
* Parameters:
*
* IXML_Document * in - document of action request
* IXML_Document **out - action result
* char **errorString - errorString (in case action was unsuccessful)
*
*****************************************************************************/
int TvDevicePowerOn(IN IXML_Document * in, OUT IXML_Document **out, OUT char **errorString);
/******************************************************************************
* TvDevicePowerOff
*
* Description:
* Turn the power off.
*
* Parameters:
*
* IXML_Document * in - document of action request
* IXML_Document **out - action result
* char **errorString - errorString (in case action was unsuccessful)
*
*****************************************************************************/
int TvDevicePowerOff(IN IXML_Document *in, OUT IXML_Document **out, OUT char **errorString);
/******************************************************************************
* TvDeviceSetChannel
*
* Description:
* Change the channel, update the TvDevice control service
* state table, and notify all subscribed control points of the
* updated state.
*
* Parameters:
*
* IXML_Document * in - action request document
* IXML_Document **out - action result document
* char **errorString - errorString (in case action was unsuccessful)
*
*****************************************************************************/
int TvDeviceSetChannel(IN IXML_Document *in, OUT IXML_Document **out, OUT char **errorString);
/******************************************************************************
* TvDeviceIncreaseChannel
*
* Description:
* Increase the channel.
*
* Parameters:
*
* IXML_Document * in - action request document
* IXML_Document **out - action result document
* char **errorString - errorString (in case action was unsuccessful)
*
*****************************************************************************/
int TvDeviceIncreaseChannel(IN IXML_Document *in, OUT IXML_Document **out, OUT char **errorString);
/******************************************************************************
* TvDeviceDecreaseChannel
*
* Description:
* Decrease the channel.
*
* Parameters:
*
* IXML_Document * in - action request document
* IXML_Document **out - action result document
* char **errorString - errorString (in case action was unsuccessful)
*
*****************************************************************************/
int TvDeviceDecreaseChannel(IN IXML_Document *in, OUT IXML_Document **out, OUT char **errorString);
/******************************************************************************
* TvDeviceSetVolume
*
* Description:
* Change the volume, update the TvDevice control service
* state table, and notify all subscribed control points of the
* updated state.
*
* Parameters:
*
* IXML_Document * in - action request document
* IXML_Document **out - action result document
* char **errorString - errorString (in case action was unsuccessful)
*
*****************************************************************************/
int TvDeviceSetVolume(IN IXML_Document *in, OUT IXML_Document **out, OUT char **errorString);
/******************************************************************************
* TvDeviceIncreaseVolume
*
* Description:
* Increase the volume.
*
* Parameters:
*
*
* IXML_Document * in - action request document
* IXML_Document **out - action result document
* char **errorString - errorString (in case action was unsuccessful)
*****************************************************************************/
int TvDeviceIncreaseVolume(IN IXML_Document *in, OUT IXML_Document **out, OUT char **errorString);
/******************************************************************************
* TvDeviceDecreaseVolume
*
* Description:
* Decrease the volume.
*
* Parameters:
*
* IXML_Document * in - action request document
* IXML_Document **out - action result document
* char **errorString - errorString (in case action was unsuccessful)
*
*****************************************************************************/
int TvDeviceDecreaseVolume(IN IXML_Document *in, OUT IXML_Document **out, OUT char **errorString);
//Picture Service Actions
/******************************************************************************
* TvDeviceSetColor
*
* Description:
* Change the color, update the TvDevice picture service
* state table, and notify all subscribed control points of the
* updated state.
*
* Parameters:
*
* IXML_Document * in - action request document
* IXML_Document **out - action result document
* char **errorString - errorString (in case action was unsuccessful)
*
*****************************************************************************/
int TvDeviceSetColor(IN IXML_Document *in, OUT IXML_Document **out, OUT char **errorString);
/******************************************************************************
* TvDeviceIncreaseColor
*
* Description:
* Increase the color.
*
* Parameters:
*
* IXML_Document * in - action request document
* IXML_Document **out - action result document
* char **errorString - errorString (in case action was unsuccessful)
*****************************************************************************/
int TvDeviceIncreaseColor(IN IXML_Document * in, OUT IXML_Document **out, OUT char **errorString);
/******************************************************************************
* TvDeviceDecreaseColor
*
* Description:
* Decrease the color.
*
* Parameters:
*
* IXML_Document * in - action request document
* IXML_Document **out - action result document
* char **errorString - errorString (in case action was unsuccessful)
*****************************************************************************/
int TvDeviceDecreaseColor(IN IXML_Document * in, OUT IXML_Document **out, OUT char **errorString);
/******************************************************************************
* TvDeviceSetTint
*
* Description:
* Change the tint, update the TvDevice picture service
* state table, and notify all subscribed control points of the
* updated state.
*
* Parameters:
*
* IXML_Document * in - action request document
* IXML_Document **out - action result document
* char **errorString - errorString (in case action was unsuccessful)
*
*****************************************************************************/
int TvDeviceSetTint(IN IXML_Document *in, OUT IXML_Document **out, OUT char **errorString);
/******************************************************************************
* TvDeviceIncreaseTint
*
* Description:
* Increase tint.
*
* Parameters:
*
* IXML_Document * in - action request document
* IXML_Document **out - action result document
* char **errorString - errorString (in case action was unsuccessful)
*
*****************************************************************************/
int TvDeviceIncreaseTint(IN IXML_Document *in, OUT IXML_Document **out, OUT char **errorString);
/******************************************************************************
* TvDeviceDecreaseTint
*
* Description:
* Decrease tint.
*
* Parameters:
*
* IXML_Document * in - action request document
* IXML_Document **out - action result document
* char **errorString - errorString (in case action was unsuccessful)
*
*****************************************************************************/
int TvDeviceDecreaseTint(IN IXML_Document *in, OUT IXML_Document **out, OUT char **errorString);
/*****************************************************************************
* TvDeviceSetContrast
*
* Description:
* Change the contrast, update the TvDevice picture service
* state table, and notify all subscribed control points of the
* updated state.
*
* Parameters:
*
* IXML_Document * in - action request document
* IXML_Document **out - action result document
* char **errorString - errorString (in case action was unsuccessful)
*
****************************************************************************/
int TvDeviceSetContrast(IN IXML_Document *in, OUT IXML_Document **out, OUT char **errorString);
/******************************************************************************
* TvDeviceIncreaseContrast
*
* Description:
*
* Increase the contrast.
*
* Parameters:
*
* IXML_Document * in - action request document
* IXML_Document **out - action result document
* char **errorString - errorString (in case action was unsuccessful)
*
*****************************************************************************/
int TvDeviceIncreaseContrast(IN IXML_Document *in, OUT IXML_Document **out, OUT char **errorString);
/******************************************************************************
* TvDeviceDecreaseContrast
*
* Description:
* Decrease the contrast.
*
* Parameters:
*
* IXML_Document * in - action request document
* IXML_Document **out - action result document
* char **errorString - errorString (in case action was unsuccessful)
*
*****************************************************************************/
int TvDeviceDecreaseContrast(IN IXML_Document *in, OUT IXML_Document **out, OUT char **errorString);
/******************************************************************************
* TvDeviceSetBrightness
*
* Description:
* Change the brightness, update the TvDevice picture service
* state table, and notify all subscribed control points of the
* updated state.
*
* Parameters:
* brightness -- The brightness value to change to.
*
*****************************************************************************/
int TvDeviceSetBrightness(IN IXML_Document *in, OUT IXML_Document **out, OUT char **errorString);
/******************************************************************************
* TvDeviceIncreaseBrightness
*
* Description:
* Increase brightness.
*
* Parameters:
*
* IXML_Document * in - action request document
* IXML_Document **out - action result document
* char **errorString - errorString (in case action was unsuccessful)
*
*****************************************************************************/
int TvDeviceIncreaseBrightness(IN IXML_Document *in, OUT IXML_Document **out, OUT char **errorString);
/******************************************************************************
* TvDeviceDecreaseBrightness
*
* Description:
* Decrease brightnesss.
*
* Parameters:
* IXML_Document * in - action request document
* IXML_Document **out - action result document
* char **errorString - errorString (in case action was unsuccessful)
*
*****************************************************************************/
int TvDeviceDecreaseBrightness(IN IXML_Document *in, OUT IXML_Document **out, OUT char **errorString);
int TvDeviceStart(char * ip_address, unsigned short port,char * desc_doc_name,
char *web_dir_path, print_string pfun);
int TvDeviceStop(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,441 +0,0 @@
/*******************************************************************************
*
* Copyright (c) 2000-2003 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************/
#include "sample_util.h"
#include "upnp_tv_ctrlpt.h"
#include <stdio.h>
#include <string.h>
/*
Tags for valid commands issued at the command prompt
*/
enum cmdloop_tvcmds {
PRTHELP = 0, PRTFULLHELP, POWON, POWOFF,
SETCHAN, SETVOL, SETCOL, SETTINT, SETCONT, SETBRT,
CTRLACTION, PICTACTION, CTRLGETVAR, PICTGETVAR,
PRTDEV, LSTDEV, REFRESH, EXITCMD
};
/*
Data structure for parsing commands from the command line
*/
struct cmdloop_commands {
char *str; // the string
int cmdnum; // the command
int numargs; // the number of arguments
char *args; // the args
} cmdloop_commands;
/*
Mappings between command text names, command tag,
and required command arguments for command line
commands
*/
static struct cmdloop_commands cmdloop_cmdlist[] = {
{"Help", PRTHELP, 1, ""},
{"HelpFull", PRTFULLHELP, 1, ""},
{"ListDev", LSTDEV, 1, ""},
{"Refresh", REFRESH, 1, ""},
{"PrintDev", PRTDEV, 2, "<devnum>"},
{"PowerOn", POWON, 2, "<devnum>"},
{"PowerOff", POWOFF, 2, "<devnum>"},
{"SetChannel", SETCHAN, 3, "<devnum> <channel (int)>"},
{"SetVolume", SETVOL, 3, "<devnum> <volume (int)>"},
{"SetColor", SETCOL, 3, "<devnum> <color (int)>"},
{"SetTint", SETTINT, 3, "<devnum> <tint (int)>"},
{"SetContrast", SETCONT, 3, "<devnum> <contrast (int)>"},
{"SetBrightness", SETBRT, 3, "<devnum> <brightness (int)>"},
{"CtrlAction", CTRLACTION, 2, "<devnum> <action (string)>"},
{"PictAction", PICTACTION, 2, "<devnum> <action (string)>"},
{"CtrlGetVar", CTRLGETVAR, 2, "<devnum> <varname (string)>"},
{"PictGetVar", PICTGETVAR, 2, "<devnum> <varname (string)>"},
{"Exit", EXITCMD, 1, ""}
};
void
linux_print( const char *string )
{
puts( string );
}
/********************************************************************************
* TvCtrlPointPrintHelp
*
* Description:
* Print help info for this application.
********************************************************************************/
void
TvCtrlPointPrintShortHelp( void )
{
SampleUtil_Print( "Commands:" );
SampleUtil_Print( " Help" );
SampleUtil_Print( " HelpFull" );
SampleUtil_Print( " ListDev" );
SampleUtil_Print( " Refresh" );
SampleUtil_Print( " PrintDev <devnum>" );
SampleUtil_Print( " PowerOn <devnum>" );
SampleUtil_Print( " PowerOff <devnum>" );
SampleUtil_Print( " SetChannel <devnum> <channel>" );
SampleUtil_Print( " SetVolume <devnum> <volume>" );
SampleUtil_Print( " SetColor <devnum> <color>" );
SampleUtil_Print( " SetTint <devnum> <tint>" );
SampleUtil_Print( " SetContrast <devnum> <contrast>" );
SampleUtil_Print( " SetBrightness <devnum> <brightness>" );
SampleUtil_Print( " CtrlAction <devnum> <action>" );
SampleUtil_Print( " PictAction <devnum> <action>" );
SampleUtil_Print( " CtrlGetVar <devnum> <varname>" );
SampleUtil_Print( " PictGetVar <devnum> <action>" );
SampleUtil_Print( " Exit" );
}
void
TvCtrlPointPrintLongHelp( void )
{
SampleUtil_Print( "" );
SampleUtil_Print( "******************************" );
SampleUtil_Print( "* TV Control Point Help Info *" );
SampleUtil_Print( "******************************" );
SampleUtil_Print( "" );
SampleUtil_Print( "This sample control point application automatically searches" );
SampleUtil_Print( "for and subscribes to the services of television device emulator" );
SampleUtil_Print( "devices, described in the tvdevicedesc.xml description document." );
SampleUtil_Print( "" );
SampleUtil_Print( "Commands:" );
SampleUtil_Print( " Help" );
SampleUtil_Print( " Print this help info." );
SampleUtil_Print( " ListDev" );
SampleUtil_Print( " Print the current list of TV Device Emulators that this" );
SampleUtil_Print( " control point is aware of. Each device is preceded by a" );
SampleUtil_Print( " device number which corresponds to the devnum argument of" );
SampleUtil_Print( " commands listed below." );
SampleUtil_Print( " Refresh" );
SampleUtil_Print( " Delete all of the devices from the device list and issue new" );
SampleUtil_Print( " search request to rebuild the list from scratch." );
SampleUtil_Print( " PrintDev <devnum>" );
SampleUtil_Print( " Print the state table for the device <devnum>." );
SampleUtil_Print( " e.g., 'PrintDev 1' prints the state table for the first" );
SampleUtil_Print( " device in the device list." );
SampleUtil_Print( " PowerOn <devnum>" );
SampleUtil_Print( " Sends the PowerOn action to the Control Service of" );
SampleUtil_Print( " device <devnum>." );
SampleUtil_Print( " PowerOff <devnum>" );
SampleUtil_Print( " Sends the PowerOff action to the Control Service of" );
SampleUtil_Print( " device <devnum>." );
SampleUtil_Print( " SetChannel <devnum> <channel>" );
SampleUtil_Print( " Sends the SetChannel action to the Control Service of" );
SampleUtil_Print( " device <devnum>, requesting the channel to be changed" );
SampleUtil_Print( " to <channel>." );
SampleUtil_Print( " SetVolume <devnum> <volume>" );
SampleUtil_Print( " Sends the SetVolume action to the Control Service of" );
SampleUtil_Print( " device <devnum>, requesting the volume to be changed" );
SampleUtil_Print( " to <volume>." );
SampleUtil_Print( " SetColor <devnum> <color>" );
SampleUtil_Print( " Sends the SetColor action to the Control Service of" );
SampleUtil_Print( " device <devnum>, requesting the color to be changed" );
SampleUtil_Print( " to <color>." );
SampleUtil_Print( " SetTint <devnum> <tint>" );
SampleUtil_Print( " Sends the SetTint action to the Control Service of" );
SampleUtil_Print( " device <devnum>, requesting the tint to be changed" );
SampleUtil_Print( " to <tint>." );
SampleUtil_Print( " SetContrast <devnum> <contrast>" );
SampleUtil_Print( " Sends the SetContrast action to the Control Service of" );
SampleUtil_Print( " device <devnum>, requesting the contrast to be changed" );
SampleUtil_Print( " to <contrast>." );
SampleUtil_Print( " SetBrightness <devnum> <brightness>" );
SampleUtil_Print( " Sends the SetBrightness action to the Control Service of" );
SampleUtil_Print( " device <devnum>, requesting the brightness to be changed" );
SampleUtil_Print( " to <brightness>." );
SampleUtil_Print( " CtrlAction <devnum> <action>" );
SampleUtil_Print( " Sends an action request specified by the string <action>" );
SampleUtil_Print( " to the Control Service of device <devnum>. This command" );
SampleUtil_Print( " only works for actions that have no arguments." );
SampleUtil_Print( " (e.g., \"CtrlAction 1 IncreaseChannel\")" );
SampleUtil_Print( " PictAction <devnum> <action>" );
SampleUtil_Print( " Sends an action request specified by the string <action>" );
SampleUtil_Print( " to the Picture Service of device <devnum>. This command" );
SampleUtil_Print( " only works for actions that have no arguments." );
SampleUtil_Print( " (e.g., \"PictAction 1 DecreaseContrast\")" );
SampleUtil_Print( " CtrlGetVar <devnum> <varname>" );
SampleUtil_Print( " Requests the value of a variable specified by the string <varname>" );
SampleUtil_Print( " from the Control Service of device <devnum>." );
SampleUtil_Print( " (e.g., \"CtrlGetVar 1 Volume\")" );
SampleUtil_Print( " PictGetVar <devnum> <action>" );
SampleUtil_Print( " Requests the value of a variable specified by the string <varname>" );
SampleUtil_Print( " from the Picture Service of device <devnum>." );
SampleUtil_Print( " (e.g., \"PictGetVar 1 Tint\")" );
SampleUtil_Print( " Exit" );
SampleUtil_Print( " Exits the control point application." );
}
/********************************************************************************
* TvCtrlPointPrintCommands
*
* Description:
* Print the list of valid command line commands to the user
*
* Parameters:
* None
*
********************************************************************************/
void
TvCtrlPointPrintCommands()
{
int i;
int numofcmds = sizeof( cmdloop_cmdlist ) / sizeof( cmdloop_commands );
SampleUtil_Print( "Valid Commands:" );
for( i = 0; i < numofcmds; i++ ) {
SampleUtil_Print( " %-14s %s", cmdloop_cmdlist[i].str,
cmdloop_cmdlist[i].args );
}
SampleUtil_Print( "" );
}
/********************************************************************************
* TvCtrlPointCommandLoop
*
* Description:
* Function that receives commands from the user at the command prompt
* during the lifetime of the control point, and calls the appropriate
* functions for those commands.
*
* Parameters:
* None
*
********************************************************************************/
void *
TvCtrlPointCommandLoop( void *args )
{
char cmdline[100];
while( 1 ) {
SampleUtil_Print( "\n>> " );
fgets( cmdline, 100, stdin );
TvCtrlPointProcessCommand( cmdline );
}
return NULL;
}
int
TvCtrlPointProcessCommand( char *cmdline )
{
char cmd[100];
char strarg[100];
int arg_val_err = -99999;
int arg1 = arg_val_err;
int arg2 = arg_val_err;
int cmdnum = -1;
int numofcmds = sizeof( cmdloop_cmdlist ) / sizeof( cmdloop_commands );
int cmdfound = 0;
int i,
rc;
int invalidargs = 0;
int validargs;
validargs = sscanf( cmdline, "%s %d %d", cmd, &arg1, &arg2 );
for( i = 0; i < numofcmds; i++ ) {
if( strcasecmp( cmd, cmdloop_cmdlist[i].str ) == 0 ) {
cmdnum = cmdloop_cmdlist[i].cmdnum;
cmdfound++;
if( validargs != cmdloop_cmdlist[i].numargs )
invalidargs++;
break;
}
}
if( !cmdfound ) {
SampleUtil_Print( "Command not found; try 'Help'" );
return TV_SUCCESS;
}
if( invalidargs ) {
SampleUtil_Print( "Invalid arguments; try 'Help'" );
return TV_SUCCESS;
}
switch ( cmdnum ) {
case PRTHELP:
TvCtrlPointPrintShortHelp();
break;
case PRTFULLHELP:
TvCtrlPointPrintLongHelp();
break;
case POWON:
TvCtrlPointSendPowerOn( arg1 );
break;
case POWOFF:
TvCtrlPointSendPowerOff( arg1 );
break;
case SETCHAN:
TvCtrlPointSendSetChannel( arg1, arg2 );
break;
case SETVOL:
TvCtrlPointSendSetVolume( arg1, arg2 );
break;
case SETCOL:
TvCtrlPointSendSetColor( arg1, arg2 );
break;
case SETTINT:
TvCtrlPointSendSetTint( arg1, arg2 );
break;
case SETCONT:
TvCtrlPointSendSetContrast( arg1, arg2 );
break;
case SETBRT:
TvCtrlPointSendSetBrightness( arg1, arg2 );
break;
case CTRLACTION:
/*
re-parse commandline since second arg is string
*/
validargs = sscanf( cmdline, "%s %d %s", cmd, &arg1, strarg );
if( 3 == validargs )
TvCtrlPointSendAction( TV_SERVICE_CONTROL, arg1, strarg,
NULL, NULL, 0 );
else
invalidargs++;
break;
case PICTACTION:
/*
re-parse commandline since second arg is string
*/
validargs = sscanf( cmdline, "%s %d %s", cmd, &arg1, strarg );
if( 3 == validargs )
TvCtrlPointSendAction( TV_SERVICE_PICTURE, arg1, strarg,
NULL, NULL, 0 );
else
invalidargs++;
break;
case CTRLGETVAR:
/*
re-parse commandline since second arg is string
*/
validargs = sscanf( cmdline, "%s %d %s", cmd, &arg1, strarg );
if( 3 == validargs )
TvCtrlPointGetVar( TV_SERVICE_CONTROL, arg1, strarg );
else
invalidargs++;
break;
case PICTGETVAR:
/*
re-parse commandline since second arg is string
*/
validargs = sscanf( cmdline, "%s %d %s", cmd, &arg1, strarg );
if( 3 == validargs )
TvCtrlPointGetVar( TV_SERVICE_PICTURE, arg1, strarg );
else
invalidargs++;
break;
case PRTDEV:
TvCtrlPointPrintDevice( arg1 );
break;
case LSTDEV:
TvCtrlPointPrintList();
break;
case REFRESH:
TvCtrlPointRefresh();
break;
case EXITCMD:
rc = TvCtrlPointStop();
exit( rc );
break;
default:
SampleUtil_Print( "Command not implemented; see 'Help'" );
break;
}
if( invalidargs )
SampleUtil_Print( "Invalid args in command; see 'Help'" );
return TV_SUCCESS;
}
int main( int argc, char **argv )
{
int rc;
ithread_t cmdloop_thread;
#ifdef WIN32
#else
int sig;
sigset_t sigs_to_catch;
#endif
int code;
rc = TvCtrlPointStart( linux_print, NULL );
if( rc != TV_SUCCESS ) {
SampleUtil_Print( "Error starting UPnP TV Control Point" );
return rc;
}
/* start a command loop thread */
code = ithread_create( &cmdloop_thread, NULL, TvCtrlPointCommandLoop, NULL );
#ifdef WIN32
ithread_join(cmdloop_thread, NULL);
#else
/*
Catch Ctrl-C and properly shutdown
*/
sigemptyset( &sigs_to_catch );
sigaddset( &sigs_to_catch, SIGINT );
sigwait( &sigs_to_catch, &sig );
SampleUtil_Print( "Shutting down on signal %d...\n", sig );
#endif
rc = TvCtrlPointStop();
return rc;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,198 +0,0 @@
/*******************************************************************************
*
* Copyright (c) 2000-2003 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************/
#include "sample_util.h"
#include "upnp_tv_device.h"
#include <stdio.h>
/******************************************************************************
* linux_print
*
* Description:
* Prints a string to standard out.
*
* Parameters:
* None
*
*****************************************************************************/
void
linux_print( const char *string )
{
printf( "%s", string );
}
/******************************************************************************
* TvDeviceCommandLoop
*
* Description:
* Function that receives commands from the user at the command prompt
* during the lifetime of the device, and calls the appropriate
* functions for those commands. Only one command, exit, is currently
* defined.
*
* Parameters:
* None
*
*****************************************************************************/
void *
TvDeviceCommandLoop( void *args )
{
int stoploop = 0;
char cmdline[100];
char cmd[100];
while( !stoploop ) {
sprintf( cmdline, " " );
sprintf( cmd, " " );
SampleUtil_Print( "\n>> " );
// Get a command line
fgets( cmdline, 100, stdin );
sscanf( cmdline, "%s", cmd );
if( strcasecmp( cmd, "exit" ) == 0 ) {
SampleUtil_Print( "Shutting down...\n" );
TvDeviceStop();
exit( 0 );
} else {
SampleUtil_Print( "\n Unknown command: %s\n\n", cmd );
SampleUtil_Print( " Valid Commands:\n" );
SampleUtil_Print( " Exit\n\n" );
}
}
return NULL;
}
/******************************************************************************
* main
*
* Description:
* Main entry point for tv device application.
* Initializes and registers with the sdk.
* Initializes the state stables of the service.
* Starts the command loop.
*
* Parameters:
* int argc - count of arguments
* char ** argv -arguments. The application
* accepts the following optional arguments:
*
* -ip ipaddress
* -port port
* -desc desc_doc_name
* -webdir web_dir_path"
* -help
*
*
*****************************************************************************/
int main( IN int argc, IN char **argv )
{
unsigned int portTemp = 0;
char *ip_address = NULL,
*desc_doc_name = NULL,
*web_dir_path = NULL;
int rc;
ithread_t cmdloop_thread;
#ifdef WIN32
#else
int sig;
sigset_t sigs_to_catch;
#endif
int code;
unsigned int port = 0;
int i = 0;
SampleUtil_Initialize( linux_print );
// Parse options
for( i = 1; i < argc; i++ ) {
if( strcmp( argv[i], "-ip" ) == 0 ) {
ip_address = argv[++i];
} else if( strcmp( argv[i], "-port" ) == 0 ) {
sscanf( argv[++i], "%u", &portTemp );
} else if( strcmp( argv[i], "-desc" ) == 0 ) {
desc_doc_name = argv[++i];
} else if( strcmp( argv[i], "-webdir" ) == 0 ) {
web_dir_path = argv[++i];
} else if( strcmp( argv[i], "-help" ) == 0 ) {
SampleUtil_Print( "Usage: %s -ip ipaddress -port port"
" -desc desc_doc_name -webdir web_dir_path"
" -help (this message)\n", argv[0] );
SampleUtil_Print( "\tipaddress: IP address of the device"
" (must match desc. doc)\n" );
SampleUtil_Print( "\t\te.g.: 192.168.0.4\n" );
SampleUtil_Print( "\tport: Port number to use for "
"receiving UPnP messages (must match desc. doc)\n" );
SampleUtil_Print( "\t\te.g.: 5431\n" );
SampleUtil_Print
( "\tdesc_doc_name: name of device description document\n" );
SampleUtil_Print( "\t\te.g.: tvdevicedesc.xml\n" );
SampleUtil_Print
( "\tweb_dir_path: Filesystem path where web files "
"related to the device are stored\n" );
SampleUtil_Print( "\t\te.g.: /upnp/sample/tvdevice/web\n" );
return 1;
}
}
port = ( unsigned short )portTemp;
TvDeviceStart( ip_address, port, desc_doc_name, web_dir_path, linux_print );
/* start a command loop thread */
code = ithread_create( &cmdloop_thread, NULL, TvDeviceCommandLoop, NULL );
#ifdef WIN32
ithread_join(cmdloop_thread, NULL);
#else
/*
Catch Ctrl-C and properly shutdown
*/
sigemptyset( &sigs_to_catch );
sigaddset( &sigs_to_catch, SIGINT );
sigwait( &sigs_to_catch, &sig );
SampleUtil_Print( "Shutting down on signal %d...\n", sig );
#endif
rc = TvDeviceStop();
return rc;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,632 +0,0 @@
/**************************************************************************
*
* Copyright (c) 2000-2003 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
**************************************************************************/
#ifndef UPNP_TV_DEVICE_H
#define UPNP_TV_DEVICE_H
#include <stdio.h>
#include <signal.h>
#ifdef __cplusplus
extern "C" {
#endif
#include "sample_util.h"
#include "ithread.h"
#include "upnp.h"
#include <stdlib.h>
#include <string.h>
#ifdef WIN32
/* Do not #include <unistd.h> */
#else
#include <unistd.h>
#endif
//Color constants
#define MAX_COLOR 10
#define MIN_COLOR 1
//Brightness constants
#define MAX_BRIGHTNESS 10
#define MIN_BRIGHTNESS 1
//Power constants
#define POWER_ON 1
#define POWER_OFF 0
//Tint constants
#define MAX_TINT 10
#define MIN_TINT 1
//Volume constants
#define MAX_VOLUME 10
#define MIN_VOLUME 1
//Contrast constants
#define MAX_CONTRAST 10
#define MIN_CONTRAST 1
//Channel constants
#define MAX_CHANNEL 100
#define MIN_CHANNEL 1
//Number of services.
#define TV_SERVICE_SERVCOUNT 2
//Index of control service
#define TV_SERVICE_CONTROL 0
//Index of picture service
#define TV_SERVICE_PICTURE 1
//Number of control variables
#define TV_CONTROL_VARCOUNT 3
//Index of power variable
#define TV_CONTROL_POWER 0
//Index of channel variable
#define TV_CONTROL_CHANNEL 1
//Index of volume variable
#define TV_CONTROL_VOLUME 2
//Number of picture variables
#define TV_PICTURE_VARCOUNT 4
//Index of color variable
#define TV_PICTURE_COLOR 0
//Index of tint variable
#define TV_PICTURE_TINT 1
//Index of contrast variable
#define TV_PICTURE_CONTRAST 2
//Index of brightness variable
#define TV_PICTURE_BRIGHTNESS 3
//Max value length
#define TV_MAX_VAL_LEN 5
//Max actions
#define TV_MAXACTIONS 12
/* This should be the maximum VARCOUNT from above */
#define TV_MAXVARS TV_PICTURE_VARCOUNT
extern char TvDeviceType[];
extern char *TvServiceType[];
/******************************************************************************
* upnp_action
*
* Description:
* Prototype for all actions. For each action that a service
* implements, there is a corresponding function with this prototype.
* Pointers to these functions, along with action names, are stored
* in the service table. When an action request comes in the action
* name is matched, and the appropriate function is called.
* Each function returns UPNP_E_SUCCESS, on success, and a nonzero
* error code on failure.
*
* Parameters:
*
* IXML_Document * request - document of action request
* IXML_Document **out - action result
* char **errorString - errorString (in case action was unsuccessful)
*
*****************************************************************************/
typedef int (*upnp_action) (IXML_Document *request, IXML_Document **out, char **errorString);
/* Structure for storing Tv Service
identifiers and state table */
struct TvService {
char UDN[NAME_SIZE]; /* Universally Unique Device Name */
char ServiceId[NAME_SIZE];
char ServiceType[NAME_SIZE];
char *VariableName[TV_MAXVARS];
char *VariableStrVal[TV_MAXVARS];
char *ActionNames[TV_MAXACTIONS];
upnp_action actions[TV_MAXACTIONS];
unsigned int VariableCount;
};
//Array of service structures
extern struct TvService tv_service_table[];
//Device handle returned from sdk
extern UpnpDevice_Handle device_handle;
/* Mutex for protecting the global state table data
in a multi-threaded, asynchronous environment.
All functions should lock this mutex before reading
or writing the state table data. */
extern ithread_mutex_t TVDevMutex;
/******************************************************************************
* SetActionTable
*
* Description:
* Initializes the action table for the specified service.
* Note that
* knowledge of the service description is
* assumed. Action names are hardcoded.
* Parameters:
* int serviceType - one of TV_SERVICE_CONTROL or, TV_SERVICE_PICTURE
* struct TvService *out - service containing action table to set.
*
*****************************************************************************/
int SetActionTable(int serviceType, struct TvService *out);
/******************************************************************************
* TvDeviceStateTableInit
*
* Description:
* Initialize the device state table for
* this TvDevice, pulling identifier info
* from the description Document. Note that
* knowledge of the service description is
* assumed. State table variables and default
* values are currently hardcoded in this file
* rather than being read from service description
* documents.
*
* Parameters:
* DescDocURL -- The description document URL
*
*****************************************************************************/
int TvDeviceStateTableInit(char*);
/******************************************************************************
* TvDeviceHandleSubscriptionRequest
*
* Description:
* Called during a subscription request callback. If the
* subscription request is for this device and either its
* control service or picture service, then accept it.
*
* Parameters:
* sr_event -- The subscription request event structure
*
*****************************************************************************/
int TvDeviceHandleSubscriptionRequest(struct Upnp_Subscription_Request *);
/******************************************************************************
* TvDeviceHandleGetVarRequest
*
* Description:
* Called during a get variable request callback. If the
* request is for this device and either its control service
* or picture service, then respond with the variable value.
*
* Parameters:
* cgv_event -- The control get variable request event structure
*
*****************************************************************************/
int TvDeviceHandleGetVarRequest(struct Upnp_State_Var_Request *);
/******************************************************************************
* TvDeviceHandleActionRequest
*
* Description:
* Called during an action request callback. If the
* request is for this device and either its control service
* or picture service, then perform the action and respond.
*
* Parameters:
* ca_event -- The control action request event structure
*
*****************************************************************************/
int TvDeviceHandleActionRequest(struct Upnp_Action_Request *);
/******************************************************************************
* TvDeviceCallbackEventHandler
*
* Description:
* The callback handler registered with the SDK while registering
* root device. Dispatches the request to the appropriate procedure
* based on the value of EventType. The four requests handled by the
* device are:
* 1) Event Subscription requests.
* 2) Get Variable requests.
* 3) Action requests.
*
* Parameters:
*
* EventType -- The type of callback event
* Event -- Data structure containing event data
* Cookie -- Optional data specified during callback registration
*
*****************************************************************************/
int TvDeviceCallbackEventHandler(Upnp_EventType, void*, void*);
/******************************************************************************
* TvDeviceSetServiceTableVar
*
* Description:
* Update the TvDevice service state table, and notify all subscribed
* control points of the updated state. Note that since this function
* blocks on the mutex TVDevMutex, to avoid a hang this function should
* not be called within any other function that currently has this mutex
* locked.
*
* Parameters:
* service -- The service number (TV_SERVICE_CONTROL or TV_SERVICE_PICTURE)
* variable -- The variable number (TV_CONTROL_POWER, TV_CONTROL_CHANNEL,
* TV_CONTROL_VOLUME, TV_PICTURE_COLOR, TV_PICTURE_TINT,
* TV_PICTURE_CONTRAST, or TV_PICTURE_BRIGHTNESS)
* value -- The string representation of the new value
*
*****************************************************************************/
int TvDeviceSetServiceTableVar(unsigned int, unsigned int, char*);
//Control Service Actions
/******************************************************************************
* TvDevicePowerOn
*
* Description:
* Turn the power on.
*
* Parameters:
*
* IXML_Document * in - document of action request
* IXML_Document **out - action result
* char **errorString - errorString (in case action was unsuccessful)
*
*****************************************************************************/
int TvDevicePowerOn(IN IXML_Document * in, OUT IXML_Document **out, OUT char **errorString);
/******************************************************************************
* TvDevicePowerOff
*
* Description:
* Turn the power off.
*
* Parameters:
*
* IXML_Document * in - document of action request
* IXML_Document **out - action result
* char **errorString - errorString (in case action was unsuccessful)
*
*****************************************************************************/
int TvDevicePowerOff(IN IXML_Document *in, OUT IXML_Document **out, OUT char **errorString);
/******************************************************************************
* TvDeviceSetChannel
*
* Description:
* Change the channel, update the TvDevice control service
* state table, and notify all subscribed control points of the
* updated state.
*
* Parameters:
*
* IXML_Document * in - action request document
* IXML_Document **out - action result document
* char **errorString - errorString (in case action was unsuccessful)
*
*****************************************************************************/
int TvDeviceSetChannel(IN IXML_Document *in, OUT IXML_Document **out, OUT char **errorString);
/******************************************************************************
* TvDeviceIncreaseChannel
*
* Description:
* Increase the channel.
*
* Parameters:
*
* IXML_Document * in - action request document
* IXML_Document **out - action result document
* char **errorString - errorString (in case action was unsuccessful)
*
*****************************************************************************/
int TvDeviceIncreaseChannel(IN IXML_Document *in, OUT IXML_Document **out, OUT char **errorString);
/******************************************************************************
* TvDeviceDecreaseChannel
*
* Description:
* Decrease the channel.
*
* Parameters:
*
* IXML_Document * in - action request document
* IXML_Document **out - action result document
* char **errorString - errorString (in case action was unsuccessful)
*
*****************************************************************************/
int TvDeviceDecreaseChannel(IN IXML_Document *in, OUT IXML_Document **out, OUT char **errorString);
/******************************************************************************
* TvDeviceSetVolume
*
* Description:
* Change the volume, update the TvDevice control service
* state table, and notify all subscribed control points of the
* updated state.
*
* Parameters:
*
* IXML_Document * in - action request document
* IXML_Document **out - action result document
* char **errorString - errorString (in case action was unsuccessful)
*
*****************************************************************************/
int TvDeviceSetVolume(IN IXML_Document *in, OUT IXML_Document **out, OUT char **errorString);
/******************************************************************************
* TvDeviceIncreaseVolume
*
* Description:
* Increase the volume.
*
* Parameters:
*
*
* IXML_Document * in - action request document
* IXML_Document **out - action result document
* char **errorString - errorString (in case action was unsuccessful)
*****************************************************************************/
int TvDeviceIncreaseVolume(IN IXML_Document *in, OUT IXML_Document **out, OUT char **errorString);
/******************************************************************************
* TvDeviceDecreaseVolume
*
* Description:
* Decrease the volume.
*
* Parameters:
*
* IXML_Document * in - action request document
* IXML_Document **out - action result document
* char **errorString - errorString (in case action was unsuccessful)
*
*****************************************************************************/
int TvDeviceDecreaseVolume(IN IXML_Document *in, OUT IXML_Document **out, OUT char **errorString);
//Picture Service Actions
/******************************************************************************
* TvDeviceSetColor
*
* Description:
* Change the color, update the TvDevice picture service
* state table, and notify all subscribed control points of the
* updated state.
*
* Parameters:
*
* IXML_Document * in - action request document
* IXML_Document **out - action result document
* char **errorString - errorString (in case action was unsuccessful)
*
*****************************************************************************/
int TvDeviceSetColor(IN IXML_Document *in, OUT IXML_Document **out, OUT char **errorString);
/******************************************************************************
* TvDeviceIncreaseColor
*
* Description:
* Increase the color.
*
* Parameters:
*
* IXML_Document * in - action request document
* IXML_Document **out - action result document
* char **errorString - errorString (in case action was unsuccessful)
*****************************************************************************/
int TvDeviceIncreaseColor(IN IXML_Document * in, OUT IXML_Document **out, OUT char **errorString);
/******************************************************************************
* TvDeviceDecreaseColor
*
* Description:
* Decrease the color.
*
* Parameters:
*
* IXML_Document * in - action request document
* IXML_Document **out - action result document
* char **errorString - errorString (in case action was unsuccessful)
*****************************************************************************/
int TvDeviceDecreaseColor(IN IXML_Document * in, OUT IXML_Document **out, OUT char **errorString);
/******************************************************************************
* TvDeviceSetTint
*
* Description:
* Change the tint, update the TvDevice picture service
* state table, and notify all subscribed control points of the
* updated state.
*
* Parameters:
*
* IXML_Document * in - action request document
* IXML_Document **out - action result document
* char **errorString - errorString (in case action was unsuccessful)
*
*****************************************************************************/
int TvDeviceSetTint(IN IXML_Document *in, OUT IXML_Document **out, OUT char **errorString);
/******************************************************************************
* TvDeviceIncreaseTint
*
* Description:
* Increase tint.
*
* Parameters:
*
* IXML_Document * in - action request document
* IXML_Document **out - action result document
* char **errorString - errorString (in case action was unsuccessful)
*
*****************************************************************************/
int TvDeviceIncreaseTint(IN IXML_Document *in, OUT IXML_Document **out, OUT char **errorString);
/******************************************************************************
* TvDeviceDecreaseTint
*
* Description:
* Decrease tint.
*
* Parameters:
*
* IXML_Document * in - action request document
* IXML_Document **out - action result document
* char **errorString - errorString (in case action was unsuccessful)
*
*****************************************************************************/
int TvDeviceDecreaseTint(IN IXML_Document *in, OUT IXML_Document **out, OUT char **errorString);
/*****************************************************************************
* TvDeviceSetContrast
*
* Description:
* Change the contrast, update the TvDevice picture service
* state table, and notify all subscribed control points of the
* updated state.
*
* Parameters:
*
* IXML_Document * in - action request document
* IXML_Document **out - action result document
* char **errorString - errorString (in case action was unsuccessful)
*
****************************************************************************/
int TvDeviceSetContrast(IN IXML_Document *in, OUT IXML_Document **out, OUT char **errorString);
/******************************************************************************
* TvDeviceIncreaseContrast
*
* Description:
*
* Increase the contrast.
*
* Parameters:
*
* IXML_Document * in - action request document
* IXML_Document **out - action result document
* char **errorString - errorString (in case action was unsuccessful)
*
*****************************************************************************/
int TvDeviceIncreaseContrast(IN IXML_Document *in, OUT IXML_Document **out, OUT char **errorString);
/******************************************************************************
* TvDeviceDecreaseContrast
*
* Description:
* Decrease the contrast.
*
* Parameters:
*
* IXML_Document * in - action request document
* IXML_Document **out - action result document
* char **errorString - errorString (in case action was unsuccessful)
*
*****************************************************************************/
int TvDeviceDecreaseContrast(IN IXML_Document *in, OUT IXML_Document **out, OUT char **errorString);
/******************************************************************************
* TvDeviceSetBrightness
*
* Description:
* Change the brightness, update the TvDevice picture service
* state table, and notify all subscribed control points of the
* updated state.
*
* Parameters:
* brightness -- The brightness value to change to.
*
*****************************************************************************/
int TvDeviceSetBrightness(IN IXML_Document *in, OUT IXML_Document **out, OUT char **errorString);
/******************************************************************************
* TvDeviceIncreaseBrightness
*
* Description:
* Increase brightness.
*
* Parameters:
*
* IXML_Document * in - action request document
* IXML_Document **out - action result document
* char **errorString - errorString (in case action was unsuccessful)
*
*****************************************************************************/
int TvDeviceIncreaseBrightness(IN IXML_Document *in, OUT IXML_Document **out, OUT char **errorString);
/******************************************************************************
* TvDeviceDecreaseBrightness
*
* Description:
* Decrease brightnesss.
*
* Parameters:
* IXML_Document * in - action request document
* IXML_Document **out - action result document
* char **errorString - errorString (in case action was unsuccessful)
*
*****************************************************************************/
int TvDeviceDecreaseBrightness(IN IXML_Document *in, OUT IXML_Document **out, OUT char **errorString);
int TvDeviceStart(char * ip_address, unsigned short port,char * desc_doc_name,
char *web_dir_path, print_string pfun);
int TvDeviceStop(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -38,6 +38,14 @@
/* strndup() is a GNU extension. Other systems must fix it with elif's. */ /* strndup() is a GNU extension. Other systems must fix it with elif's. */
#ifdef __GNUC__ #ifdef __GNUC__
extern char *strndup(__const char *__string, size_t __n); extern char *strndup(__const char *__string, size_t __n);
#elif defined(WIN32)
static char *strndup(const char *__string, size_t __n)
{
size_t strsize = strnlen(__string,__n);
char *newstr = (char *) malloc(strsize + 1);
strncpy(newstr,__string,__n);
return(newstr);
}
#endif #endif
@@ -49,7 +57,7 @@ extern char *strndup(__const char *__string, size_t __n);
struct SUpnpString struct SUpnpString
{ {
/*! \brief Length of the string. */ /*! \brief Length of the string. */
int m_length; size_t m_length;
/*! \brief Pointer to a dynamically allocated area that holds the NULL /*! \brief Pointer to a dynamically allocated area that holds the NULL
* terminated string. */ * terminated string. */
char *m_string; char *m_string;
@@ -58,7 +66,7 @@ struct SUpnpString
UpnpString *UpnpString_new() UpnpString *UpnpString_new()
{ {
// All bytes are zero, and so is the length of the string. /* All bytes are zero, and so is the length of the string. */
struct SUpnpString *p = calloc(1, sizeof (struct SUpnpString)); struct SUpnpString *p = calloc(1, sizeof (struct SUpnpString));
if (p == NULL) { if (p == NULL) {
goto error_handler1; goto error_handler1;
@@ -67,7 +75,7 @@ UpnpString *UpnpString_new()
p->m_length = 0; p->m_length = 0;
#endif #endif
// This byte is zero, calloc does initialize it. /* This byte is zero, calloc does initialize it. */
p->m_string = calloc(1, 1); p->m_string = calloc(1, 1);
if (p->m_string == NULL) { if (p->m_string == NULL) {
goto error_handler2; goto error_handler2;
@@ -75,7 +83,7 @@ UpnpString *UpnpString_new()
return (UpnpString *)p; return (UpnpString *)p;
//free(p->m_string); /*free(p->m_string); */
error_handler2: error_handler2:
free(p); free(p);
error_handler1: error_handler1:
@@ -112,7 +120,7 @@ UpnpString *UpnpString_dup(const UpnpString *p)
return (UpnpString *)q; return (UpnpString *)q;
//free(q->m_string); /*free(q->m_string); */
error_handler2: error_handler2:
free(q); free(q);
error_handler1: error_handler1:

View File

@@ -122,6 +122,7 @@ ithread_mutex_t GlobalClientSubscribeMutex;
/*! rwlock to synchronize handles (root device or control point handle). */ /*! rwlock to synchronize handles (root device or control point handle). */
ithread_rwlock_t GlobalHndRWLock; ithread_rwlock_t GlobalHndRWLock;
/*! Mutex to synchronize the uuid creation process. */ /*! Mutex to synchronize the uuid creation process. */
ithread_mutex_t gUUIDMutex; ithread_mutex_t gUUIDMutex;
@@ -156,7 +157,7 @@ char gIF_IPV6[65]/* INET6_ADDRSTRLEN*/ = { '\0' };
char gIF_IPV6_ULA_GUA[INET6_ADDRSTRLEN] = { '\0' }; char gIF_IPV6_ULA_GUA[INET6_ADDRSTRLEN] = { '\0' };
/*! Contains interface index. (extern'ed in upnp.h) */ /*! Contains interface index. (extern'ed in upnp.h) */
int gIF_INDEX = -1; unsigned gIF_INDEX = (unsigned)-1;
/*! local IPv4 port for the mini-server */ /*! local IPv4 port for the mini-server */
unsigned short LOCAL_PORT_V4; unsigned short LOCAL_PORT_V4;
@@ -469,7 +470,7 @@ int UpnpInit(const char *HostIP, unsigned short DestPort)
} }
} }
/* Set the UpnpSdkInit flag to 1 to indicate we're sucessfully initialized. */ /* Set the UpnpSdkInit flag to 1 to indicate we're successfully initialized. */
UpnpSdkInit = 1; UpnpSdkInit = 1;
/* Finish initializing the SDK. */ /* Finish initializing the SDK. */
@@ -521,7 +522,7 @@ int UpnpInit2(const char *IfName, unsigned short DestPort)
goto exit_function; goto exit_function;
} }
/* Set the UpnpSdkInit flag to 1 to indicate we're sucessfully initialized. */ /* Set the UpnpSdkInit flag to 1 to indicate we're successfully initialized. */
UpnpSdkInit = 1; UpnpSdkInit = 1;
/* Finish initializing the SDK. */ /* Finish initializing the SDK. */
@@ -867,8 +868,6 @@ static int GetDescDocumentAndURL(
/* [in] . */ /* [in] . */
char *description, char *description,
/* [in] . */ /* [in] . */
unsigned int bufferLen,
/* [in] . */
int config_baseURL, int config_baseURL,
/* [in] . */ /* [in] . */
int AddressFamily, int AddressFamily,
@@ -882,7 +881,7 @@ static int GetDescDocumentAndURL(
int UpnpRegisterRootDevice2( int UpnpRegisterRootDevice2(
Upnp_DescType descriptionType, Upnp_DescType descriptionType,
const char *description_const, const char *description_const,
size_t bufferLen, // ignored unless descType == UPNPREG_BUF_DESC size_t bufferLen, /* ignored */
int config_baseURL, int config_baseURL,
Upnp_FunPtr Fun, Upnp_FunPtr Fun,
const void *Cookie, const void *Cookie,
@@ -926,11 +925,11 @@ int UpnpRegisterRootDevice2(
} }
HandleTable[*Hnd] = HInfo; HandleTable[*Hnd] = HInfo;
// prevent accidental removal of a non-existent alias /* prevent accidental removal of a non-existent alias */
HInfo->aliasInstalled = 0; HInfo->aliasInstalled = 0;
retVal = GetDescDocumentAndURL( retVal = GetDescDocumentAndURL(
descriptionType, description, bufferLen, descriptionType, description,
config_baseURL, AF_INET, config_baseURL, AF_INET,
&HInfo->DescDocument, HInfo->DescURL); &HInfo->DescDocument, HInfo->DescURL);
if (retVal != UPNP_E_SUCCESS) { if (retVal != UPNP_E_SUCCESS) {
@@ -1008,6 +1007,7 @@ exit_function:
HandleUnlock(); HandleUnlock();
return retVal; return retVal;
bufferLen = bufferLen;
} }
#endif /* INCLUDE_DEVICE_APIS */ #endif /* INCLUDE_DEVICE_APIS */
@@ -1190,7 +1190,7 @@ int UpnpUnRegisterRootDevice(UpnpDevice_Handle Hnd)
HandleUnlock(); HandleUnlock();
return UPNP_E_INVALID_HANDLE; return UPNP_E_INVALID_HANDLE;
} }
//info = (struct Handle_Info *) HandleTable[Hnd]; /*info = (struct Handle_Info *) HandleTable[Hnd]; */
ixmlNodeList_free( HInfo->DeviceList ); ixmlNodeList_free( HInfo->DeviceList );
ixmlNodeList_free( HInfo->ServiceList ); ixmlNodeList_free( HInfo->ServiceList );
ixmlDocument_free( HInfo->DescDocument ); ixmlDocument_free( HInfo->DescDocument );
@@ -1203,7 +1203,7 @@ int UpnpUnRegisterRootDevice(UpnpDevice_Handle Hnd)
if( HInfo->aliasInstalled ) { if( HInfo->aliasInstalled ) {
web_server_set_alias( NULL, NULL, 0, 0 ); web_server_set_alias( NULL, NULL, 0, 0 );
} }
#endif // INTERNAL_WEB_SERVER #endif /* INTERNAL_WEB_SERVER */
if( HInfo->DeviceAf == AF_INET ) { if( HInfo->DeviceAf == AF_INET ) {
UpnpSdkDeviceRegisteredV4 = 0; UpnpSdkDeviceRegisteredV4 = 0;
@@ -1399,7 +1399,6 @@ static void get_server_addr6(
static int GetDescDocumentAndURL( static int GetDescDocumentAndURL(
Upnp_DescType descriptionType, Upnp_DescType descriptionType,
char *description, char *description,
unsigned int bufferLen,
int config_baseURL, int config_baseURL,
int AddressFamily, int AddressFamily,
IXML_Document **xmlDoc, IXML_Document **xmlDoc,
@@ -1410,38 +1409,33 @@ static int GetDescDocumentAndURL(
char aliasStr[LINE_SIZE]; char aliasStr[LINE_SIZE];
char *temp_str = NULL; char *temp_str = NULL;
FILE *fp = NULL; FILE *fp = NULL;
off_t fileLen; size_t fileLen;
size_t num_read; size_t num_read;
time_t last_modified; time_t last_modified;
struct stat file_info; struct stat file_info;
struct sockaddr_storage serverAddr; struct sockaddr_storage serverAddr;
int rc = UPNP_E_SUCCESS; int rc = UPNP_E_SUCCESS;
if (description == NULL) { if (description == NULL)
return UPNP_E_INVALID_PARAM; return UPNP_E_INVALID_PARAM;
}
/* non-URL description must have configuration specified */ /* non-URL description must have configuration specified */
if (descriptionType != UPNPREG_URL_DESC && !config_baseURL) { if (descriptionType != UPNPREG_URL_DESC && !config_baseURL)
return UPNP_E_INVALID_PARAM; return UPNP_E_INVALID_PARAM;
}
/* Get XML doc and last modified time */ /* Get XML doc and last modified time */
if (descriptionType == UPNPREG_URL_DESC) { if (descriptionType == UPNPREG_URL_DESC) {
retVal = UpnpDownloadXmlDoc(description, xmlDoc); retVal = UpnpDownloadXmlDoc(description, xmlDoc);
if (retVal != UPNP_E_SUCCESS) { if (retVal != UPNP_E_SUCCESS)
return retVal; return retVal;
}
last_modified = time(NULL); last_modified = time(NULL);
} else if (descriptionType == UPNPREG_FILENAME_DESC) { } else if (descriptionType == UPNPREG_FILENAME_DESC) {
retVal = stat(description, &file_info); retVal = stat(description, &file_info);
if (retVal == -1) { if (retVal == -1)
return UPNP_E_FILE_NOT_FOUND; return UPNP_E_FILE_NOT_FOUND;
} fileLen = (size_t)file_info.st_size;
fileLen = file_info.st_size;
last_modified = file_info.st_mtime; last_modified = file_info.st_mtime;
fp = fopen(description, "rb"); fp = fopen(description, "rb");
if (fp == NULL) { if (fp == NULL)
return UPNP_E_FILE_NOT_FOUND; return UPNP_E_FILE_NOT_FOUND;
}
membuf = (char *)malloc(fileLen + 1); membuf = (char *)malloc(fileLen + 1);
if (membuf == NULL) { if (membuf == NULL) {
fclose(fp); fclose(fp);
@@ -1465,12 +1459,11 @@ static int GetDescDocumentAndURL(
} }
if (rc != IXML_SUCCESS && descriptionType != UPNPREG_URL_DESC) { if (rc != IXML_SUCCESS && descriptionType != UPNPREG_URL_DESC) {
if (rc == IXML_INSUFFICIENT_MEMORY) { if (rc == IXML_INSUFFICIENT_MEMORY)
return UPNP_E_OUTOF_MEMORY; return UPNP_E_OUTOF_MEMORY;
} else { else
return UPNP_E_INVALID_DESC; return UPNP_E_INVALID_DESC;
} }
}
/* Determine alias */ /* Determine alias */
if (config_baseURL) { if (config_baseURL) {
if (descriptionType == UPNPREG_BUF_DESC) { if (descriptionType == UPNPREG_BUF_DESC) {
@@ -1496,7 +1489,8 @@ static int GetDescDocumentAndURL(
} }
/* config */ /* config */
retVal = configure_urlbase(*xmlDoc, (struct sockaddr *)&serverAddr, retVal =
configure_urlbase(*xmlDoc, (struct sockaddr *)&serverAddr,
aliasStr, last_modified, descURL); aliasStr, last_modified, descURL);
if (retVal != UPNP_E_SUCCESS) { if (retVal != UPNP_E_SUCCESS) {
ixmlDocument_free(*xmlDoc); ixmlDocument_free(*xmlDoc);
@@ -1521,7 +1515,6 @@ static int GetDescDocumentAndURL(
static int GetDescDocumentAndURL( static int GetDescDocumentAndURL(
Upnp_DescType descriptionType, Upnp_DescType descriptionType,
char *description, char *description,
unsigned int bufferLen,
int config_baseURL, int config_baseURL,
int AddressFamily, int AddressFamily,
IXML_Document **xmlDoc, IXML_Document **xmlDoc,
@@ -2808,7 +2801,7 @@ int UpnpOpenHttpPost(
int UpnpWriteHttpPost( int UpnpWriteHttpPost(
void *handle, void *handle,
char *buf, char *buf,
unsigned int *size, size_t *size,
int timeout) int timeout)
{ {
return http_WriteHttpPost(handle, buf, size, timeout); return http_WriteHttpPost(handle, buf, size, timeout);
@@ -2880,13 +2873,13 @@ int UpnpCloseHttpGet(void *Handle)
} }
int UpnpReadHttpGet(void *Handle, char *buf, unsigned int *size, int timeout) int UpnpReadHttpGet(void *Handle, char *buf, size_t *size, int timeout)
{ {
return http_ReadHttpGet(Handle, buf, size, timeout); return http_ReadHttpGet(Handle, buf, size, timeout);
} }
int UpnpHttpGetProgress(void *Handle, unsigned int *length, unsigned int *total) int UpnpHttpGetProgress(void *Handle, size_t *length, size_t *total)
{ {
return http_HttpGetProgress(Handle, length, total); return http_HttpGetProgress(Handle, length, total);
} }
@@ -2895,18 +2888,15 @@ int UpnpHttpGetProgress(void *Handle, unsigned int *length, unsigned int *total)
int UpnpDownloadUrlItem(const char *url, char **outBuf, char *contentType) int UpnpDownloadUrlItem(const char *url, char **outBuf, char *contentType)
{ {
int ret_code; int ret_code;
int dummy; size_t dummy;
if( url == NULL || outBuf == NULL || contentType == NULL ) { if (url == NULL || outBuf == NULL || contentType == NULL)
return UPNP_E_INVALID_PARAM; return UPNP_E_INVALID_PARAM;
}
ret_code = http_Download(url, HTTP_DEFAULT_TIMEOUT, outBuf, &dummy, ret_code = http_Download(url, HTTP_DEFAULT_TIMEOUT, outBuf, &dummy,
contentType); contentType);
if( ret_code > 0 ) { if (ret_code > 0)
/* error reply was received */ /* error reply was received */
ret_code = UPNP_E_INVALID_URL; ret_code = UPNP_E_INVALID_URL;
}
return ret_code; return ret_code;
} }
@@ -2976,9 +2966,9 @@ int UpnpDownloadXmlDoc(const char *url, IXML_Document **xmlDoc)
int UpnpGetIfInfo(const char *IfName) int UpnpGetIfInfo(const char *IfName)
{ {
#ifdef WIN32 #ifdef WIN32
// ---------------------------------------------------- /* ---------------------------------------------------- */
// WIN32 implementation will use the IpHlpAPI library. /* WIN32 implementation will use the IpHlpAPI library. */
// ---------------------------------------------------- /* ---------------------------------------------------- */
PIP_ADAPTER_ADDRESSES adapts = NULL; PIP_ADAPTER_ADDRESSES adapts = NULL;
PIP_ADAPTER_ADDRESSES adapts_item; PIP_ADAPTER_ADDRESSES adapts_item;
PIP_ADAPTER_UNICAST_ADDRESS uni_addr; PIP_ADAPTER_UNICAST_ADDRESS uni_addr;
@@ -2990,34 +2980,33 @@ int UpnpGetIfInfo(const char *IfName)
int ifname_found = 0; int ifname_found = 0;
int valid_addr_found = 0; int valid_addr_found = 0;
// Get Adapters addresses required size. /* Get Adapters addresses required size. */
ret = GetAdaptersAddresses(AF_UNSPEC, ret = GetAdaptersAddresses(AF_UNSPEC,
GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_DNS_SERVER, GAA_FLAG_SKIP_ANYCAST |
NULL, adapts, &adapts_sz ); GAA_FLAG_SKIP_DNS_SERVER, NULL, adapts,
&adapts_sz);
if (ret != ERROR_BUFFER_OVERFLOW) { if (ret != ERROR_BUFFER_OVERFLOW) {
UpnpPrintf(UPNP_CRITICAL, API, __FILE__, __LINE__, UpnpPrintf(UPNP_CRITICAL, API, __FILE__, __LINE__,
"GetAdaptersAddresses failed to find list of adapters\n"); "GetAdaptersAddresses failed to find list of adapters\n");
return UPNP_E_INIT; return UPNP_E_INIT;
} }
/* Allocate enough memory. */
// Allocate enough memory.
adapts = (PIP_ADAPTER_ADDRESSES) malloc(adapts_sz); adapts = (PIP_ADAPTER_ADDRESSES) malloc(adapts_sz);
if (adapts == NULL) { if (adapts == NULL) {
return UPNP_E_OUTOF_MEMORY; return UPNP_E_OUTOF_MEMORY;
} }
/* Do the call that will actually return the info. */
// Do the call that will actually return the info.
ret = GetAdaptersAddresses(AF_UNSPEC, ret = GetAdaptersAddresses(AF_UNSPEC,
GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_DNS_SERVER, GAA_FLAG_SKIP_ANYCAST |
NULL, adapts, &adapts_sz ); GAA_FLAG_SKIP_DNS_SERVER, NULL, adapts,
&adapts_sz);
if (ret != ERROR_SUCCESS) { if (ret != ERROR_SUCCESS) {
free(adapts); free(adapts);
UpnpPrintf(UPNP_CRITICAL, API, __FILE__, __LINE__, UpnpPrintf(UPNP_CRITICAL, API, __FILE__, __LINE__,
"GetAdaptersAddresses failed to find list of adapters\n"); "GetAdaptersAddresses failed to find list of adapters\n");
return UPNP_E_INIT; return UPNP_E_INIT;
} }
/* Copy interface name, if it was provided. */
// Copy interface name, if it was provided.
if (IfName != NULL) { if (IfName != NULL) {
if (strlen(IfName) > sizeof(gIF_NAME)) if (strlen(IfName) > sizeof(gIF_NAME))
return UPNP_E_INVALID_INTERFACE; return UPNP_E_INVALID_INTERFACE;
@@ -3025,70 +3014,71 @@ int UpnpGetIfInfo(const char *IfName)
strncpy(gIF_NAME, IfName, sizeof(gIF_NAME)); strncpy(gIF_NAME, IfName, sizeof(gIF_NAME));
ifname_found = 1; ifname_found = 1;
} }
adapts_item = adapts; adapts_item = adapts;
while (adapts_item != NULL) { while (adapts_item != NULL) {
if (adapts_item->Flags & IP_ADAPTER_NO_MULTICAST) { if (adapts_item->Flags & IP_ADAPTER_NO_MULTICAST) {
continue; continue;
} }
if (ifname_found == 0) { if (ifname_found == 0) {
// We have found a valid interface name. Keep it. /* We have found a valid interface name. Keep it. */
strncpy( gIF_NAME, adapts_item->FriendlyName, sizeof(gIF_NAME) ); strncpy(gIF_NAME, adapts_item->FriendlyName,
sizeof(gIF_NAME));
ifname_found = 1; ifname_found = 1;
} else { } else {
if( strncmp( gIF_NAME, adapts_item->FriendlyName, sizeof(gIF_NAME) ) != 0 ) { if (strncmp
// This is not the interface we're looking for. (gIF_NAME, adapts_item->FriendlyName,
sizeof(gIF_NAME)) != 0) {
/* This is not the interface we're looking for. */
continue; continue;
} }
} }
/* Loop thru this adapter's unicast IP addresses. */
// Loop thru this adapter's unicast IP addresses.
uni_addr = adapts_item->FirstUnicastAddress; uni_addr = adapts_item->FirstUnicastAddress;
while (uni_addr) { while (uni_addr) {
ip_addr = uni_addr->Address.lpSockaddr; ip_addr = uni_addr->Address.lpSockaddr;
switch (ip_addr->sa_family) { switch (ip_addr->sa_family) {
case AF_INET: case AF_INET:
memcpy( &v4_addr, &((struct sockaddr_in *)ip_addr)->sin_addr, sizeof(v4_addr) ); memcpy(&v4_addr,
&((struct sockaddr_in *)ip_addr)->
sin_addr, sizeof(v4_addr));
valid_addr_found = 1; valid_addr_found = 1;
break; break;
case AF_INET6: case AF_INET6:
// Only keep IPv6 link-local addresses. /* Only keep IPv6 link-local addresses. */
if( IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)ip_addr)->sin6_addr) ) { if (IN6_IS_ADDR_LINKLOCAL
memcpy( &v6_addr, &((struct sockaddr_in6 *)ip_addr)->sin6_addr, sizeof(v6_addr) ); (&((struct sockaddr_in6 *)ip_addr)->
sin6_addr)) {
memcpy(&v6_addr,
&((struct sockaddr_in6 *)
ip_addr)->sin6_addr,
sizeof(v6_addr));
valid_addr_found = 1; valid_addr_found = 1;
} }
break; break;
default: default:
if (valid_addr_found == 0) { if (valid_addr_found == 0) {
// Address is not IPv4 or IPv6 and no valid address has /* Address is not IPv4 or IPv6 and no valid address has */
// yet been found for this interface. Discard interface name. /* yet been found for this interface. Discard interface name. */
ifname_found = 0; ifname_found = 0;
} }
break; break;
} }
/* Next address. */
// Next address.
uni_addr = uni_addr->Next; uni_addr = uni_addr->Next;
} }
if (valid_addr_found == 1) { if (valid_addr_found == 1) {
gIF_INDEX = adapts_item->IfIndex; gIF_INDEX = adapts_item->IfIndex;
break; break;
} }
/* Next adapter. */
// Next adapter.
adapts_item = adapts_item->Next; adapts_item = adapts_item->Next;
} }
/* Failed to find a valid interface, or valid address. */
// Failed to find a valid interface, or valid address.
if (ifname_found == 0 || valid_addr_found == 0) { if (ifname_found == 0 || valid_addr_found == 0) {
UpnpPrintf(UPNP_CRITICAL, API, __FILE__, __LINE__, UpnpPrintf(UPNP_CRITICAL, API, __FILE__, __LINE__,
"Failed to find an adapter with valid IP addresses for use.\n"); "Failed to find an adapter with valid IP addresses for use.\n");
return UPNP_E_INVALID_INTERFACE; return UPNP_E_INVALID_INTERFACE;
} }
inet_ntop(AF_INET, &v4_addr, gIF_IPV4, sizeof(gIF_IPV4)); inet_ntop(AF_INET, &v4_addr, gIF_IPV4, sizeof(gIF_IPV4));
inet_ntop(AF_INET6, &v6_addr, gIF_IPV6, sizeof(gIF_IPV6)); inet_ntop(AF_INET6, &v6_addr, gIF_IPV6, sizeof(gIF_IPV6));
#elif (defined(BSD) && BSD >= 199306) || defined(__FreeBSD_kernel__) #elif (defined(BSD) && BSD >= 199306) || defined(__FreeBSD_kernel__)
@@ -3098,7 +3088,7 @@ int UpnpGetIfInfo(const char *IfName)
int ifname_found = 0; int ifname_found = 0;
int valid_addr_found = 0; int valid_addr_found = 0;
// Copy interface name, if it was provided. /* Copy interface name, if it was provided. */
if (IfName != NULL) { if (IfName != NULL) {
if (strlen(IfName) > sizeof(gIF_NAME)) if (strlen(IfName) > sizeof(gIF_NAME))
return UPNP_E_INVALID_INTERFACE; return UPNP_E_INVALID_INTERFACE;
@@ -3106,68 +3096,68 @@ int UpnpGetIfInfo(const char *IfName)
strncpy(gIF_NAME, IfName, sizeof(gIF_NAME)); strncpy(gIF_NAME, IfName, sizeof(gIF_NAME));
ifname_found = 1; ifname_found = 1;
} }
/* Get system interface addresses. */
// Get system interface addresses.
if (getifaddrs(&ifap) != 0) { if (getifaddrs(&ifap) != 0) {
UpnpPrintf(UPNP_CRITICAL, API, __FILE__, __LINE__, UpnpPrintf(UPNP_CRITICAL, API, __FILE__, __LINE__,
"getifaddrs failed to find list of addresses\n"); "getifaddrs failed to find list of addresses\n");
return UPNP_E_INIT; return UPNP_E_INIT;
} }
/* cycle through available interfaces and their addresses. */
// cycle through available interfaces and their addresses. for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) /* Skip LOOPBACK interfaces, DOWN interfaces and interfaces that */
{ /* don't support MULTICAST. */
// Skip LOOPBACK interfaces, DOWN interfaces and interfaces that
// don't support MULTICAST.
if ((ifa->ifa_flags & IFF_LOOPBACK) if ((ifa->ifa_flags & IFF_LOOPBACK)
|| (!(ifa->ifa_flags & IFF_UP)) || (!(ifa->ifa_flags & IFF_UP))
|| (!(ifa->ifa_flags & IFF_MULTICAST))) { || (!(ifa->ifa_flags & IFF_MULTICAST))) {
continue; continue;
} }
if (ifname_found == 0) { if (ifname_found == 0) {
// We have found a valid interface name. Keep it. /* We have found a valid interface name. Keep it. */
strncpy(gIF_NAME, ifa->ifa_name, sizeof(gIF_NAME)); strncpy(gIF_NAME, ifa->ifa_name, sizeof(gIF_NAME));
ifname_found = 1; ifname_found = 1;
} else { } else {
if( strncmp( gIF_NAME, ifa->ifa_name, sizeof(gIF_NAME) ) != 0 ) { if (strncmp(gIF_NAME, ifa->ifa_name, sizeof(gIF_NAME))
// This is not the interface we're looking for. != 0) {
/* This is not the interface we're looking for. */
continue; continue;
} }
} }
/* Keep interface addresses for later. */
// Keep interface addresses for later. switch (ifa->ifa_addr->sa_family) {
switch( ifa->ifa_addr->sa_family )
{
case AF_INET: case AF_INET:
memcpy( &v4_addr, &((struct sockaddr_in *)(ifa->ifa_addr))->sin_addr, sizeof(v4_addr) ); memcpy(&v4_addr,
&((struct sockaddr_in *)(ifa->ifa_addr))->
sin_addr, sizeof(v4_addr));
valid_addr_found = 1; valid_addr_found = 1;
break; break;
case AF_INET6: case AF_INET6:
// Only keep IPv6 link-local addresses. /* Only keep IPv6 link-local addresses. */
if( IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)(ifa->ifa_addr))->sin6_addr) ) { if (IN6_IS_ADDR_LINKLOCAL
memcpy( &v6_addr, &((struct sockaddr_in6 *)(ifa->ifa_addr))->sin6_addr, sizeof(v6_addr) ); (&((struct sockaddr_in6 *)(ifa->ifa_addr))->
sin6_addr)) {
memcpy(&v6_addr,
&((struct sockaddr_in6 *)(ifa->
ifa_addr))->
sin6_addr, sizeof(v6_addr));
valid_addr_found = 1; valid_addr_found = 1;
} }
break; break;
default: default:
if (valid_addr_found == 0) { if (valid_addr_found == 0) {
// Address is not IPv4 or IPv6 and no valid address has /* Address is not IPv4 or IPv6 and no valid address has */
// yet been found for this interface. Discard interface name. /* yet been found for this interface. Discard interface name. */
ifname_found = 0; ifname_found = 0;
} }
break; break;
} }
} }
freeifaddrs(ifap); freeifaddrs(ifap);
/* Failed to find a valid interface, or valid address. */
// Failed to find a valid interface, or valid address.
if (ifname_found == 0 || valid_addr_found == 0) { if (ifname_found == 0 || valid_addr_found == 0) {
UpnpPrintf(UPNP_CRITICAL, API, __FILE__, __LINE__, UpnpPrintf(UPNP_CRITICAL, API, __FILE__, __LINE__,
"Failed to find an adapter with valid IP addresses for use.\n"); "Failed to find an adapter with valid IP addresses for use.\n");
return UPNP_E_INVALID_INTERFACE; return UPNP_E_INVALID_INTERFACE;
} }
inet_ntop(AF_INET, &v4_addr, gIF_IPV4, sizeof(gIF_IPV4)); inet_ntop(AF_INET, &v4_addr, gIF_IPV4, sizeof(gIF_IPV4));
inet_ntop(AF_INET6, &v6_addr, gIF_IPV6, sizeof(gIF_IPV6)); inet_ntop(AF_INET6, &v6_addr, gIF_IPV6, sizeof(gIF_IPV6));
gIF_INDEX = if_nametoindex(gIF_NAME); gIF_INDEX = if_nametoindex(gIF_NAME);
@@ -3176,16 +3166,16 @@ int UpnpGetIfInfo(const char *IfName)
struct ifconf ifConf; struct ifconf ifConf;
struct ifreq ifReq; struct ifreq ifReq;
FILE *inet6_procfd; FILE *inet6_procfd;
int i; size_t i;
int LocalSock; int LocalSock;
struct in6_addr v6_addr; struct in6_addr v6_addr;
int if_idx; unsigned if_idx;
char addr6[8][5]; char addr6[8][5];
char buf[65]; // INET6_ADDRSTRLEN char buf[65]; /* INET6_ADDRSTRLEN */
int ifname_found = 0; int ifname_found = 0;
int valid_addr_found = 0; int valid_addr_found = 0;
// Copy interface name, if it was provided. /* Copy interface name, if it was provided. */
if (IfName != NULL) { if (IfName != NULL) {
if (strlen(IfName) > sizeof(gIF_NAME)) if (strlen(IfName) > sizeof(gIF_NAME))
return UPNP_E_INVALID_INTERFACE; return UPNP_E_INVALID_INTERFACE;
@@ -3193,15 +3183,13 @@ int UpnpGetIfInfo(const char *IfName)
strncpy(gIF_NAME, IfName, sizeof(gIF_NAME)); strncpy(gIF_NAME, IfName, sizeof(gIF_NAME));
ifname_found = 1; ifname_found = 1;
} }
/* Create an unbound datagram socket to do the SIOCGIFADDR ioctl on. */
// Create an unbound datagram socket to do the SIOCGIFADDR ioctl on.
if ((LocalSock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { if ((LocalSock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__, UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
"Can't create addrlist socket\n"); "Can't create addrlist socket\n");
return UPNP_E_INIT; return UPNP_E_INIT;
} }
/* Get the interface configuration information... */
// Get the interface configuration information...
ifConf.ifc_len = sizeof szBuffer; ifConf.ifc_len = sizeof szBuffer;
ifConf.ifc_ifcu.ifcu_buf = (caddr_t) szBuffer; ifConf.ifc_ifcu.ifcu_buf = (caddr_t) szBuffer;
@@ -3210,90 +3198,95 @@ int UpnpGetIfInfo(const char *IfName)
"DiscoverInterfaces: SIOCGIFCONF returned error\n"); "DiscoverInterfaces: SIOCGIFCONF returned error\n");
return UPNP_E_INIT; return UPNP_E_INIT;
} }
/* Cycle through the list of interfaces looking for IP addresses. */
// Cycle through the list of interfaces looking for IP addresses. for (i = 0; i < (size_t)ifConf.ifc_len;) {
for( i = 0; i < ifConf.ifc_len ; ) {
struct ifreq *pifReq = struct ifreq *pifReq =
(struct ifreq *)((caddr_t) ifConf.ifc_req + i); (struct ifreq *)((caddr_t) ifConf.ifc_req + i);
i += sizeof *pifReq; i += sizeof *pifReq;
/* See if this is the sort of interface we want to deal with. */
// See if this is the sort of interface we want to deal with.
strcpy(ifReq.ifr_name, pifReq->ifr_name); strcpy(ifReq.ifr_name, pifReq->ifr_name);
if (ioctl(LocalSock, SIOCGIFFLAGS, &ifReq) < 0) { if (ioctl(LocalSock, SIOCGIFFLAGS, &ifReq) < 0) {
UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__, UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
"Can't get interface flags for %s:\n", "Can't get interface flags for %s:\n",
ifReq.ifr_name); ifReq.ifr_name);
} }
/* Skip LOOPBACK interfaces, DOWN interfaces and interfaces that */
// Skip LOOPBACK interfaces, DOWN interfaces and interfaces that /* don't support MULTICAST. */
// don't support MULTICAST.
if ((ifReq.ifr_flags & IFF_LOOPBACK) if ((ifReq.ifr_flags & IFF_LOOPBACK)
|| (!(ifReq.ifr_flags & IFF_UP)) || (!(ifReq.ifr_flags & IFF_UP))
|| (!(ifReq.ifr_flags & IFF_MULTICAST))) { || (!(ifReq.ifr_flags & IFF_MULTICAST))) {
continue; continue;
} }
if (ifname_found == 0) { if (ifname_found == 0) {
// We have found a valid interface name. Keep it. /* We have found a valid interface name. Keep it. */
strncpy(gIF_NAME, pifReq->ifr_name, sizeof(gIF_NAME)); strncpy(gIF_NAME, pifReq->ifr_name, sizeof(gIF_NAME));
ifname_found = 1; ifname_found = 1;
} else { } else {
if( strncmp( gIF_NAME, pifReq->ifr_name, sizeof(gIF_NAME) ) != 0 ) { if (strncmp
// This is not the interface we're looking for. (gIF_NAME, pifReq->ifr_name,
sizeof(gIF_NAME)) != 0) {
/* This is not the interface we're looking for. */
continue; continue;
} }
} }
/* Check address family. */
// Check address family.
if (pifReq->ifr_addr.sa_family == AF_INET) { if (pifReq->ifr_addr.sa_family == AF_INET) {
// Copy interface name, IPv4 address and interface index. /* Copy interface name, IPv4 address and interface index. */
strncpy(gIF_NAME, pifReq->ifr_name, sizeof(gIF_NAME)); strncpy(gIF_NAME, pifReq->ifr_name, sizeof(gIF_NAME));
inet_ntop(AF_INET, &((struct sockaddr_in*)&pifReq->ifr_addr)->sin_addr, gIF_IPV4, sizeof(gIF_IPV4)); inet_ntop(AF_INET,
&((struct sockaddr_in *)&pifReq->ifr_addr)->
sin_addr, gIF_IPV4, sizeof(gIF_IPV4));
gIF_INDEX = if_nametoindex(gIF_NAME); gIF_INDEX = if_nametoindex(gIF_NAME);
valid_addr_found = 1; valid_addr_found = 1;
break; break;
} else { } else {
// Address is not IPv4 /* Address is not IPv4 */
ifname_found = 0; ifname_found = 0;
} }
} }
close(LocalSock); close(LocalSock);
/* Failed to find a valid interface, or valid address. */
// Failed to find a valid interface, or valid address.
if (ifname_found == 0 || valid_addr_found == 0) { if (ifname_found == 0 || valid_addr_found == 0) {
UpnpPrintf(UPNP_CRITICAL, API, __FILE__, __LINE__, UpnpPrintf(UPNP_CRITICAL, API, __FILE__, __LINE__,
"Failed to find an adapter with valid IP addresses for use.\n"); "Failed to find an adapter with valid IP addresses for use.\n");
return UPNP_E_INVALID_INTERFACE; return UPNP_E_INVALID_INTERFACE;
} }
/* Try to get the IPv6 address for the same interface */
// Try to get the IPv6 address for the same interface /* from "/proc/net/if_inet6", if possible. */
// from "/proc/net/if_inet6", if possible.
inet6_procfd = fopen("/proc/net/if_inet6", "r"); inet6_procfd = fopen("/proc/net/if_inet6", "r");
if (inet6_procfd) { if (inet6_procfd) {
while (fscanf(inet6_procfd, while (fscanf(inet6_procfd,
"%4s%4s%4s%4s%4s%4s%4s%4s %02x %*02x %*02x %*02x %*20s\n", "%4s%4s%4s%4s%4s%4s%4s%4s %02x %*02x %*02x %*02x %*20s\n",
addr6[0], addr6[1], addr6[2], addr6[3], addr6[0], addr6[1], addr6[2], addr6[3],
addr6[4],addr6[5],addr6[6],addr6[7], &if_idx) != EOF) { addr6[4], addr6[5], addr6[6], addr6[7],
// Get same interface as IPv4 address retrieved. &if_idx) != EOF) {
/* Get same interface as IPv4 address retrieved. */
if (gIF_INDEX == if_idx) { if (gIF_INDEX == if_idx) {
snprintf(buf, sizeof(buf), "%s:%s:%s:%s:%s:%s:%s:%s", snprintf(buf, sizeof(buf),
addr6[0],addr6[1],addr6[2],addr6[3], "%s:%s:%s:%s:%s:%s:%s:%s", addr6[0],
addr6[4],addr6[5],addr6[6],addr6[7]); addr6[1], addr6[2], addr6[3], addr6[4],
// Validate formed address and check for link-local. addr6[5], addr6[6], addr6[7]);
/* Validate formed address and check for link-local. */
if (inet_pton(AF_INET6, buf, &v6_addr) > 0) { if (inet_pton(AF_INET6, buf, &v6_addr) > 0) {
if (IN6_IS_ADDR_ULA(&v6_addr)) { if (IN6_IS_ADDR_ULA(&v6_addr)) {
// Got valid IPv6 ula. /* Got valid IPv6 ula. */
strncpy(gIF_IPV6_ULA_GUA, buf, sizeof(gIF_IPV6_ULA_GUA)); strncpy(gIF_IPV6_ULA_GUA, buf,
} else if (IN6_IS_ADDR_GLOBAL(&v6_addr) && sizeof
strlen(gIF_IPV6_ULA_GUA) == 0) { (gIF_IPV6_ULA_GUA));
// got a GUA, should store it while no ULA is found } else if (IN6_IS_ADDR_GLOBAL(&v6_addr)
strncpy(gIF_IPV6_ULA_GUA, buf, sizeof(gIF_IPV6_ULA_GUA)); && strlen(gIF_IPV6_ULA_GUA)
} else if (IN6_IS_ADDR_LINKLOCAL(&v6_addr) && == 0) {
strlen(gIF_IPV6) == 0) { /* got a GUA, should store it while no ULA is found */
// got a Link local IPv6 address. strncpy(gIF_IPV6_ULA_GUA, buf,
strncpy(gIF_IPV6, buf, sizeof(gIF_IPV6)); sizeof
(gIF_IPV6_ULA_GUA));
} else
if (IN6_IS_ADDR_LINKLOCAL(&v6_addr)
&& strlen(gIF_IPV6) == 0) {
/* got a Link local IPv6 address. */
strncpy(gIF_IPV6, buf,
sizeof(gIF_IPV6));
} }
} }
} }
@@ -3301,7 +3294,6 @@ int UpnpGetIfInfo(const char *IfName)
fclose(inet6_procfd); fclose(inet6_procfd);
} }
#endif #endif
UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__, UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
"Interface name=%s, index=%d, v4=%s, v6=%s, ULA or GUA v6=%s\n", "Interface name=%s, index=%d, v4=%s, v6=%s, ULA or GUA v6=%s\n",
gIF_NAME, gIF_INDEX, gIF_IPV4, gIF_IPV6, gIF_IPV6_ULA_GUA); gIF_NAME, gIF_INDEX, gIF_IPV4, gIF_IPV6, gIF_IPV6_ULA_GUA);
@@ -3330,7 +3322,6 @@ void UpnpThreadDistribution(struct UpnpNonblockParam *Param)
UpnpString *Sid = UpnpString_new(); UpnpString *Sid = UpnpString_new();
UpnpString *Url = UpnpString_new(); UpnpString *Url = UpnpString_new();
UpnpString_set_String(Url, Param->Url); UpnpString_set_String(Url, Param->Url);
UpnpString_set_String(Sid, (char *)Evt.Sid);
Evt.ErrCode = genaSubscribe( Evt.ErrCode = genaSubscribe(
Param->Handle, Param->Handle,
Url, Url,
@@ -3338,6 +3329,7 @@ void UpnpThreadDistribution(struct UpnpNonblockParam *Param)
Sid); Sid);
strcpy(Evt.PublisherUrl, Param->Url); strcpy(Evt.PublisherUrl, Param->Url);
Evt.TimeOut = Param->TimeOut; Evt.TimeOut = Param->TimeOut;
strcpy((char *)Evt.Sid, UpnpString_get_String(Sid));
Param->Fun(UPNP_EVENT_SUBSCRIBE_COMPLETE, &Evt, Param->Cookie); Param->Fun(UPNP_EVENT_SUBSCRIBE_COMPLETE, &Evt, Param->Cookie);
UpnpString_delete(Sid); UpnpString_delete(Sid);
UpnpString_delete(Url); UpnpString_delete(Url);
@@ -3523,7 +3515,7 @@ int PrintHandleInfo(UpnpClient_Handle Hnd)
} }
int getlocalhostname(char *out, const int out_len) int getlocalhostname(char *out, size_t out_len)
{ {
int ret = UPNP_E_SUCCESS; int ret = UPNP_E_SUCCESS;
char tempstr[16]; char tempstr[16];
@@ -3598,7 +3590,7 @@ int getlocalhostname(char *out, const int out_len)
struct ifconf ifConf; struct ifconf ifConf;
struct ifreq ifReq; struct ifreq ifReq;
int nResult; int nResult;
int i; long unsigned int i;
int LocalSock; int LocalSock;
struct sockaddr_in LocalAddr; struct sockaddr_in LocalAddr;
int j = 0; int j = 0;
@@ -3627,7 +3619,7 @@ int getlocalhostname(char *out, const int out_len)
} }
/* Cycle through the list of interfaces looking for IP addresses. */ /* Cycle through the list of interfaces looking for IP addresses. */
for (i = 0; i < ifConf.ifc_len && j < DEFAULT_INTERFACE; ) { for (i = 0; i < (long unsigned int)ifConf.ifc_len && j < DEFAULT_INTERFACE; ) {
struct ifreq *pifReq = struct ifreq *pifReq =
(struct ifreq *)((caddr_t)ifConf.ifc_req + i); (struct ifreq *)((caddr_t)ifConf.ifc_req + i);
i += sizeof *pifReq; i += sizeof *pifReq;
@@ -3713,7 +3705,7 @@ int UpnpAddVirtualDir(const char *newDirName)
char dirName[NAME_SIZE]; char dirName[NAME_SIZE];
if( UpnpSdkInit != 1 ) { if( UpnpSdkInit != 1 ) {
// SDK is not initialized /* SDK is not initialized */
return UPNP_E_FINISH; return UPNP_E_FINISH;
} }
@@ -3730,7 +3722,7 @@ int UpnpAddVirtualDir(const char *newDirName)
pCurVirtualDir = pVirtualDirList; pCurVirtualDir = pVirtualDirList;
while( pCurVirtualDir != NULL ) { while( pCurVirtualDir != NULL ) {
// already has this entry /* already has this entry */
if( strcmp( pCurVirtualDir->dirName, dirName ) == 0 ) { if( strcmp( pCurVirtualDir->dirName, dirName ) == 0 ) {
return UPNP_E_SUCCESS; return UPNP_E_SUCCESS;
} }
@@ -3747,7 +3739,7 @@ int UpnpAddVirtualDir(const char *newDirName)
strcpy( pNewVirtualDir->dirName, dirName ); strcpy( pNewVirtualDir->dirName, dirName );
*( pNewVirtualDir->dirName + strlen( dirName ) ) = 0; *( pNewVirtualDir->dirName + strlen( dirName ) ) = 0;
if( pVirtualDirList == NULL ) { // first virtual dir if( pVirtualDirList == NULL ) { /* first virtual dir */
pVirtualDirList = pNewVirtualDir; pVirtualDirList = pNewVirtualDir;
} else { } else {
pLast = pVirtualDirList; pLast = pVirtualDirList;
@@ -3778,11 +3770,8 @@ int UpnpRemoveVirtualDir(const char *dirName)
if( pVirtualDirList == NULL ) { if( pVirtualDirList == NULL ) {
return UPNP_E_INVALID_PARAM; return UPNP_E_INVALID_PARAM;
} }
// /* Handle the special case where the directory that we are */
// Handle the special case where the directory that we are /* removing is the first and only one in the list. */
// removing is the first and only one in the list.
//
if( ( pVirtualDirList->next == NULL ) && if( ( pVirtualDirList->next == NULL ) &&
( strcmp( pVirtualDirList->dirName, dirName ) == 0 ) ) { ( strcmp( pVirtualDirList->dirName, dirName ) == 0 ) ) {
free( pVirtualDirList ); free( pVirtualDirList );
@@ -3958,10 +3947,7 @@ int UpnpVirtualDir_set_CloseCallback(VDCallback_Close callback)
return ret; return ret;
} }
int UpnpSetContentLength(UpnpClient_Handle Hnd, size_t contentLength)
int UpnpSetContentLength(
UpnpClient_Handle Hnd,
int contentLength)
{ {
int errCode = UPNP_E_SUCCESS; int errCode = UPNP_E_SUCCESS;
struct Handle_Info *HInfo = NULL; struct Handle_Info *HInfo = NULL;
@@ -3975,17 +3961,14 @@ int UpnpSetContentLength(
HandleLock(); HandleLock();
errCode = GetHandleInfo(Hnd, &HInfo); errCode = GetHandleInfo(Hnd, &HInfo);
if (errCode != HND_DEVICE) { if (errCode != HND_DEVICE) {
errCode = UPNP_E_INVALID_HANDLE; errCode = UPNP_E_INVALID_HANDLE;
break; break;
} }
if (contentLength > MAX_SOAP_CONTENT_LENGTH) { if (contentLength > MAX_SOAP_CONTENT_LENGTH) {
errCode = UPNP_E_OUTOF_BOUNDS; errCode = UPNP_E_OUTOF_BOUNDS;
break; break;
} }
g_maxContentLength = contentLength; g_maxContentLength = contentLength;
} while (0); } while (0);
@@ -3993,7 +3976,6 @@ int UpnpSetContentLength(
return errCode; return errCode;
} }
int UpnpSetMaxContentLength(size_t contentLength) int UpnpSetMaxContentLength(size_t contentLength)
{ {
int errCode = UPNP_E_SUCCESS; int errCode = UPNP_E_SUCCESS;

View File

@@ -229,23 +229,22 @@ void UpnpDisplayFileAndLine(
fflush(fd); fflush(fd);
} }
void UpnpDisplayBanner( void UpnpDisplayBanner(
FILE * fd, FILE * fd,
const char **lines, const char **lines,
size_t size, size_t size,
int starLength) size_t starLength)
{ {
int leftMarginLength = starLength / 2 + 1; size_t leftMarginLength = starLength / 2 + 1;
int rightMarginLength = starLength / 2 + 1; size_t rightMarginLength = starLength / 2 + 1;
int i = 0; size_t i = 0;
int LineSize = 0; size_t LineSize = 0;
int starLengthMinus2 = starLength - 2; size_t starLengthMinus2 = starLength - 2;
char *leftMargin = ( char * )malloc( leftMarginLength ); char *leftMargin = malloc(leftMarginLength);
char *rightMargin = ( char * )malloc( rightMarginLength ); char *rightMargin = malloc(rightMarginLength);
char *stars = ( char * )malloc( starLength + 1 ); char *stars = malloc(starLength + 1);
char *currentLine = ( char * )malloc( starLength + 1 ); char *currentLine = malloc(starLength + 1);
const char *line = NULL; const char *line = NULL;
memset(stars, '*', starLength); memset(stars, '*', starLength);
@@ -283,7 +282,6 @@ void UpnpDisplayBanner(
free(leftMargin); free(leftMargin);
} }
void PrintThreadPoolStats( void PrintThreadPoolStats(
ThreadPool *tp, ThreadPool *tp,
const char *DbgFileName, const char *DbgFileName,

View File

@@ -119,10 +119,9 @@ struct ErrorString ErrorMessages[] = {
{UPNP_E_INTERNAL_ERROR, "UPNP_E_INTERNAL_ERROR"}, {UPNP_E_INTERNAL_ERROR, "UPNP_E_INTERNAL_ERROR"},
}; };
const char *UpnpGetErrorMessage(int rc) const char *UpnpGetErrorMessage(int rc)
{ {
int i; size_t i;
for (i = 0; i < sizeof (ErrorMessages) / sizeof (ErrorMessages[0]); ++i) { for (i = 0; i < sizeof (ErrorMessages) / sizeof (ErrorMessages[0]); ++i) {
if (rc == ErrorMessages[i].rc) { if (rc == ErrorMessages[i].rc) {
@@ -133,7 +132,6 @@ const char *UpnpGetErrorMessage(int rc)
return "Unknown error code"; return "Unknown error code";
} }
/*! /*!
* \todo There is some unnecessary allocation and deallocation going on here * \todo There is some unnecessary allocation and deallocation going on here
* because of the way resolve_rel_url() was originally written and used. In the * because of the way resolve_rel_url() was originally written and used. In the
@@ -147,19 +145,37 @@ int UpnpResolveURL(
int ret = UPNP_E_SUCCESS; int ret = UPNP_E_SUCCESS;
char *tempRel = NULL; char *tempRel = NULL;
if (RelURL == NULL) { if (!RelURL) {
ret = UPNP_E_INVALID_PARAM; ret = UPNP_E_INVALID_PARAM;
goto ExitFunction; goto ExitFunction;
} }
tempRel = resolve_rel_url((char *)BaseURL, (char *)RelURL); tempRel = resolve_rel_url((char *)BaseURL, (char *)RelURL);
if (tempRel) { if (tempRel) {
strcpy(AbsURL, tempRel); strcpy(AbsURL, tempRel);
free(tempRel); free(tempRel);
} else { } else
ret = UPNP_E_INVALID_URL; ret = UPNP_E_INVALID_URL;
ExitFunction:
return UPNP_E_SUCCESS;
} }
int UpnpResolveURL2(
const char *BaseURL,
const char *RelURL,
char **AbsURL)
{
int ret = UPNP_E_SUCCESS;
if (!RelURL) {
ret = UPNP_E_INVALID_PARAM;
goto ExitFunction;
}
*AbsURL = resolve_rel_url((char *)BaseURL, (char *)RelURL);
if (!*AbsURL)
ret = UPNP_E_INVALID_URL;
ExitFunction: ExitFunction:
return UPNP_E_SUCCESS; return UPNP_E_SUCCESS;
} }
@@ -296,7 +312,7 @@ static IXML_Document *makeAction(
} }
if (NumArg > 0) { if (NumArg > 0) {
//va_start(ArgList, Arg); /*va_start(ArgList, Arg); */
ArgName = Arg; ArgName = Arg;
for ( ; ; ) { for ( ; ; ) {
ArgValue = va_arg(ArgList, const char *); ArgValue = va_arg(ArgList, const char *);
@@ -315,7 +331,7 @@ static IXML_Document *makeAction(
break; break;
} }
} }
//va_end(ArgList); /*va_end(ArgList); */
} }
return ActionDoc; return ActionDoc;

View File

@@ -1,33 +1,33 @@
/////////////////////////////////////////////////////////////////////////// /*******************************************************************************
// *
// Copyright (c) 2000-2003 Intel Corporation * Copyright (c) 2000-2003 Intel Corporation
// All rights reserved. * All rights reserved.
// *
// Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
// *
// * Redistributions of source code must retain the above copyright notice, * - Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer. * this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice, * - Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation * this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution. * and/or other materials provided with the distribution.
// * Neither name of Intel Corporation nor the names of its contributors * - Neither name of Intel Corporation nor the names of its contributors
// may be used to endorse or promote products derived from this software * may be used to endorse or promote products derived from this software
// without specific prior written permission. * without specific prior written permission.
// *
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// *
/////////////////////////////////////////////////////////////////////////// ******************************************************************************/
#include "config.h" #include "config.h"
#if EXCLUDE_GENA == 0 #if EXCLUDE_GENA == 0
@@ -63,7 +63,7 @@ error_respond( IN SOCKINFO * info,
int major, int major,
minor; minor;
// retrieve the minor and major version from the GENA request /* retrieve the minor and major version from the GENA request */
http_CalcResponseVersion( hmsg->major_version, http_CalcResponseVersion( hmsg->major_version,
hmsg->minor_version, &major, &minor ); hmsg->minor_version, &major, &minor );
@@ -90,38 +90,40 @@ genaCallback( IN http_parser_t * parser,
IN http_message_t * request, IN http_message_t * request,
INOUT SOCKINFO * info ) INOUT SOCKINFO * info )
{ {
xboolean found_function = FALSE; int found_function = FALSE;
if( request->method == HTTPMETHOD_SUBSCRIBE ) { if( request->method == HTTPMETHOD_SUBSCRIBE ) {
#ifdef INCLUDE_DEVICE_APIS #ifdef INCLUDE_DEVICE_APIS
found_function = TRUE; found_function = TRUE;
if( httpmsg_find_hdr( request, HDR_NT, NULL ) == NULL ) { if( httpmsg_find_hdr( request, HDR_NT, NULL ) == NULL ) {
// renew subscription /* renew subscription */
gena_process_subscription_renewal_request gena_process_subscription_renewal_request
( info, request ); ( info, request );
} else { } else {
// subscribe /* subscribe */
gena_process_subscription_request( info, request ); gena_process_subscription_request( info, request );
} }
UpnpPrintf( UPNP_ALL, GENA, __FILE__, __LINE__, UpnpPrintf( UPNP_ALL, GENA, __FILE__, __LINE__,
"got subscription request\n" ); "got subscription request\n" );
} else if( request->method == HTTPMETHOD_UNSUBSCRIBE ) { } else if( request->method == HTTPMETHOD_UNSUBSCRIBE ) {
found_function = TRUE; found_function = TRUE;
// unsubscribe /* unsubscribe */
gena_process_unsubscribe_request( info, request ); gena_process_unsubscribe_request( info, request );
#endif #endif
} else if( request->method == HTTPMETHOD_NOTIFY ) { } else if( request->method == HTTPMETHOD_NOTIFY ) {
#ifdef INCLUDE_CLIENT_APIS #ifdef INCLUDE_CLIENT_APIS
found_function = TRUE; found_function = TRUE;
// notify /* notify */
gena_process_notification_event( info, request ); gena_process_notification_event( info, request );
#endif #endif
} }
if( !found_function ) { if( !found_function ) {
// handle missing functions of device or ctrl pt /* handle missing functions of device or ctrl pt */
error_respond( info, HTTP_NOT_IMPLEMENTED, request ); error_respond( info, HTTP_NOT_IMPLEMENTED, request );
} }
return;
parser = parser;
} }
#endif // EXCLUDE_GENA #endif /* EXCLUDE_GENA */

View File

@@ -106,7 +106,7 @@ static void GenaAutoRenewSubscription(
} }
UpnpPrintf(UPNP_INFO, GENA, __FILE__, __LINE__, "HANDLE IS VALID"); UpnpPrintf(UPNP_INFO, GENA, __FILE__, __LINE__, "HANDLE IS VALID");
// make callback /* make callback */
callback_fun = handle_info->Callback; callback_fun = handle_info->Callback;
cookie = handle_info->Cookie; cookie = handle_info->Cookie;
HandleUnlock(); HandleUnlock();
@@ -160,14 +160,14 @@ static int ScheduleGenaAutoRenew(
goto end_function; goto end_function;
} }
// schedule expire event /* schedule expire event */
RenewEventStruct->ErrCode = UPNP_E_SUCCESS; RenewEventStruct->ErrCode = UPNP_E_SUCCESS;
RenewEventStruct->TimeOut = TimeOut; RenewEventStruct->TimeOut = TimeOut;
strcpy(RenewEventStruct->Sid, UpnpString_get_String(tmpSID)); strcpy(RenewEventStruct->Sid, UpnpString_get_String(tmpSID));
strncpy(RenewEventStruct->PublisherUrl, strncpy(RenewEventStruct->PublisherUrl,
UpnpString_get_String(tmpEventURL), NAME_SIZE - 1); UpnpString_get_String(tmpEventURL), NAME_SIZE - 1);
// RenewEvent->EventType=UPNP_EVENT_SUBSCRIPTION_EXPIRE; /* RenewEvent->EventType=UPNP_EVENT_SUBSCRIPTION_EXPIRE; */
RenewEvent->handle = client_handle; RenewEvent->handle = client_handle;
RenewEvent->Event = RenewEventStruct; RenewEvent->Event = RenewEventStruct;
@@ -175,7 +175,7 @@ static int ScheduleGenaAutoRenew(
TPJobSetFreeFunction(&job, (free_routine)free_upnp_timeout); TPJobSetFreeFunction(&job, (free_routine)free_upnp_timeout);
TPJobSetPriority(&job, MED_PRIORITY); TPJobSetPriority(&job, MED_PRIORITY);
// Schedule the job /* Schedule the job */
return_code = TimerThreadSchedule( return_code = TimerThreadSchedule(
&gTimerThread, &gTimerThread,
TimeOut - AUTO_RENEW_TIME, TimeOut - AUTO_RENEW_TIME,
@@ -215,7 +215,7 @@ static int gena_unsubscribe(
uri_type dest_url; uri_type dest_url;
membuffer request; membuffer request;
// parse url /* parse url */
return_code = http_FixStrUrl( return_code = http_FixStrUrl(
UpnpString_get_String(url), UpnpString_get_String(url),
UpnpString_get_Length(url), UpnpString_get_Length(url),
@@ -224,7 +224,7 @@ static int gena_unsubscribe(
return return_code; return return_code;
} }
// make request msg /* make request msg */
membuffer_init(&request); membuffer_init(&request);
request.size_inc = 30; request.size_inc = 30;
return_code = http_MakeMessage( return_code = http_MakeMessage(
@@ -233,14 +233,14 @@ static int gena_unsubscribe(
HTTPMETHOD_UNSUBSCRIBE, &dest_url, HTTPMETHOD_UNSUBSCRIBE, &dest_url,
"SID: ", UpnpString_get_String(sid)); "SID: ", UpnpString_get_String(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) {
membuffer_destroy(&request); membuffer_destroy(&request);
return return_code; return return_code;
} }
// send request and get reply /* send request and get reply */
return_code = http_RequestAndResponse( return_code = http_RequestAndResponse(
&dest_url, request.buf, request.length, &dest_url, request.buf, request.length,
HTTPMETHOD_UNSUBSCRIBE, HTTP_DEFAULT_TIMEOUT, response); HTTPMETHOD_UNSUBSCRIBE, HTTP_DEFAULT_TIMEOUT, response);
@@ -286,7 +286,7 @@ static int gena_subscribe(
UpnpString_clear(sid); UpnpString_clear(sid);
// request timeout to string /* request timeout to string */
if (timeout == NULL) { if (timeout == NULL) {
timeout = &local_timeout; timeout = &local_timeout;
} }
@@ -298,7 +298,7 @@ static int gena_subscribe(
sprintf(timeout_str, "%d", *timeout); sprintf(timeout_str, "%d", *timeout);
} }
// parse url /* parse url */
return_code = http_FixStrUrl( return_code = http_FixStrUrl(
UpnpString_get_String(url), UpnpString_get_String(url),
UpnpString_get_Length(url), UpnpString_get_Length(url),
@@ -307,11 +307,11 @@ static int gena_subscribe(
return return_code; return return_code;
} }
// make request msg /* make request msg */
membuffer_init(&request); membuffer_init(&request);
request.size_inc = 30; request.size_inc = 30;
if (renewal_sid) { if (renewal_sid) {
// renew subscription /* renew subscription */
return_code = http_MakeMessage( return_code = http_MakeMessage(
&request, 1, 1, &request, 1, 1,
"q" "ssc" "sscc", "q" "ssc" "sscc",
@@ -319,7 +319,7 @@ static int gena_subscribe(
"SID: ", UpnpString_get_String(renewal_sid), "SID: ", UpnpString_get_String(renewal_sid),
"TIMEOUT: Second-", timeout_str ); "TIMEOUT: Second-", timeout_str );
} else { } else {
// subscribe /* subscribe */
if (dest_url.hostport.IPaddress.ss_family == AF_INET6) { if (dest_url.hostport.IPaddress.ss_family == AF_INET6) {
struct sockaddr_in6* DestAddr6 = (struct sockaddr_in6*)&dest_url.hostport.IPaddress; struct sockaddr_in6* DestAddr6 = (struct sockaddr_in6*)&dest_url.hostport.IPaddress;
return_code = http_MakeMessage( return_code = http_MakeMessage(
@@ -346,7 +346,7 @@ static int gena_subscribe(
return return_code; return return_code;
} }
// send request and get reply /* send request and get reply */
return_code = http_RequestAndResponse(&dest_url, request.buf, return_code = http_RequestAndResponse(&dest_url, request.buf,
request.length, request.length,
HTTPMETHOD_SUBSCRIBE, HTTPMETHOD_SUBSCRIBE,
@@ -365,7 +365,7 @@ static int gena_subscribe(
return UPNP_E_SUBSCRIBE_UNACCEPTED; return UPNP_E_SUBSCRIBE_UNACCEPTED;
} }
// get SID and TIMEOUT /* get SID and TIMEOUT */
if (httpmsg_find_hdr(&response.msg, HDR_SID, &sid_hdr) == NULL || if (httpmsg_find_hdr(&response.msg, HDR_SID, &sid_hdr) == NULL ||
sid_hdr.length == 0 || sid_hdr.length == 0 ||
httpmsg_find_hdr( &response.msg, HDR_TIMEOUT, &timeout_hdr ) == NULL || httpmsg_find_hdr( &response.msg, HDR_TIMEOUT, &timeout_hdr ) == NULL ||
@@ -375,10 +375,10 @@ static int gena_subscribe(
return UPNP_E_BAD_RESPONSE; return UPNP_E_BAD_RESPONSE;
} }
// save timeout /* save timeout */
parse_ret = matchstr(timeout_hdr.buf, timeout_hdr.length, "%iSecond-%d%0", timeout); parse_ret = matchstr(timeout_hdr.buf, timeout_hdr.length, "%iSecond-%d%0", timeout);
if (parse_ret == PARSE_OK) { if (parse_ret == PARSE_OK) {
// nothing to do /* nothing to do */
} else if (memptr_cmp_nocase(&timeout_hdr, "Second-infinite") == 0) { } else if (memptr_cmp_nocase(&timeout_hdr, "Second-infinite") == 0) {
*timeout = -1; *timeout = -1;
} else { } else {
@@ -387,7 +387,7 @@ static int gena_subscribe(
return UPNP_E_BAD_RESPONSE; return UPNP_E_BAD_RESPONSE;
} }
// save SID /* save SID */
UpnpString_set_StringN(sid, sid_hdr.buf, sid_hdr.length); UpnpString_set_StringN(sid, sid_hdr.buf, sid_hdr.length);
if (UpnpString_get_String(sid) == NULL) { if (UpnpString_get_String(sid) == NULL) {
httpmsg_destroy(&response.msg); httpmsg_destroy(&response.msg);
@@ -456,7 +456,7 @@ int genaUnSubscribe(
ClientSubscription *sub_copy = UpnpClientSubscription_new(); ClientSubscription *sub_copy = UpnpClientSubscription_new();
http_parser_t response; http_parser_t response;
// validate handle and sid /* validate handle and sid */
HandleLock(); HandleLock();
if (GetHandleInfo(client_handle, &handle_info) != HND_CLIENT) { if (GetHandleInfo(client_handle, &handle_info) != HND_CLIENT) {
HandleUnlock(); HandleUnlock();
@@ -518,7 +518,7 @@ int genaSubscribe(
UpnpString_clear(out_sid); UpnpString_clear(out_sid);
HandleReadLock(); HandleReadLock();
// validate handle /* validate handle */
if (GetHandleInfo(client_handle, &handle_info) != HND_CLIENT) { if (GetHandleInfo(client_handle, &handle_info) != HND_CLIENT) {
HandleUnlock(); HandleUnlock();
@@ -526,7 +526,7 @@ int genaSubscribe(
} }
HandleUnlock(); HandleUnlock();
// subscribe /* subscribe */
SubscribeLock(); SubscribeLock();
return_code = gena_subscribe(PublisherURL, TimeOut, NULL, ActualSID); return_code = gena_subscribe(PublisherURL, TimeOut, NULL, ActualSID);
HandleLock(); HandleLock();
@@ -542,16 +542,16 @@ int genaSubscribe(
goto error_handler; goto error_handler;
} }
// generate client SID /* generate client SID */
uuid_create(&uid ); uuid_create(&uid );
uuid_unpack(&uid, temp_sid); uuid_unpack(&uid, temp_sid);
sprintf(temp_sid2, "uuid:%s", temp_sid); sprintf(temp_sid2, "uuid:%s", temp_sid);
UpnpString_set_String(out_sid, temp_sid2); UpnpString_set_String(out_sid, temp_sid2);
// create event url /* create event url */
UpnpString_assign(EventURL, PublisherURL); UpnpString_assign(EventURL, PublisherURL);
// fill subscription /* fill subscription */
if (newSubscription == NULL) { if (newSubscription == NULL) {
return_code = UPNP_E_OUTOF_MEMORY; return_code = UPNP_E_OUTOF_MEMORY;
goto error_handler; goto error_handler;
@@ -563,7 +563,7 @@ int genaSubscribe(
UpnpClientSubscription_set_Next(newSubscription, handle_info->ClientSubList); UpnpClientSubscription_set_Next(newSubscription, handle_info->ClientSubList);
handle_info->ClientSubList = newSubscription; handle_info->ClientSubList = newSubscription;
// schedule expiration event /* schedule expiration event */
return_code = ScheduleGenaAutoRenew(client_handle, *TimeOut, newSubscription); return_code = ScheduleGenaAutoRenew(client_handle, *TimeOut, newSubscription);
error_handler: error_handler:
@@ -594,7 +594,7 @@ int genaRenewSubscription(
HandleLock(); HandleLock();
// validate handle and sid /* validate handle and sid */
if (GetHandleInfo(client_handle, &handle_info) != HND_CLIENT) { if (GetHandleInfo(client_handle, &handle_info) != HND_CLIENT) {
HandleUnlock(); HandleUnlock();
@@ -610,7 +610,7 @@ int genaRenewSubscription(
goto exit_function; goto exit_function;
} }
// remove old events /* remove old events */
if (TimerThreadRemove( if (TimerThreadRemove(
&gTimerThread, &gTimerThread,
UpnpClientSubscription_get_RenewEventId(sub), UpnpClientSubscription_get_RenewEventId(sub),
@@ -639,17 +639,17 @@ int genaRenewSubscription(
goto exit_function; goto exit_function;
} }
// we just called GetHandleInfo, so we don't check for return value /* we just called GetHandleInfo, so we don't check for return value */
//GetHandleInfo(client_handle, &handle_info); /*GetHandleInfo(client_handle, &handle_info); */
if (return_code != UPNP_E_SUCCESS) { if (return_code != UPNP_E_SUCCESS) {
// network failure (remove client sub) /* network failure (remove client sub) */
RemoveClientSubClientSID(&handle_info->ClientSubList, in_sid); RemoveClientSubClientSID(&handle_info->ClientSubList, in_sid);
free_client_subscription(sub_copy); free_client_subscription(sub_copy);
HandleUnlock(); HandleUnlock();
goto exit_function; goto exit_function;
} }
// get subscription /* get subscription */
sub = GetClientSubClientSID(handle_info->ClientSubList, in_sid); sub = GetClientSubClientSID(handle_info->ClientSubList, in_sid);
if (sub == NULL) { if (sub == NULL) {
free_client_subscription(sub_copy); free_client_subscription(sub_copy);
@@ -658,10 +658,10 @@ int genaRenewSubscription(
goto exit_function; goto exit_function;
} }
// store actual sid /* store actual sid */
UpnpClientSubscription_set_ActualSID(sub, ActualSID); UpnpClientSubscription_set_ActualSID(sub, ActualSID);
// start renew subscription timer /* start renew subscription timer */
return_code = ScheduleGenaAutoRenew(client_handle, *TimeOut, sub); return_code = ScheduleGenaAutoRenew(client_handle, *TimeOut, sub);
if (return_code != GENA_SUCCESS) { if (return_code != GENA_SUCCESS) {
RemoveClientSubClientSID( RemoveClientSubClientSID(
@@ -698,7 +698,7 @@ void gena_process_notification_event(
nts_hdr; nts_hdr;
memptr seq_hdr; memptr seq_hdr;
// get SID /* get SID */
if (httpmsg_find_hdr(event, HDR_SID, &sid_hdr) == NULL) { if (httpmsg_find_hdr(event, HDR_SID, &sid_hdr) == NULL) {
error_respond(info, HTTP_PRECONDITION_FAILED, event); error_respond(info, HTTP_PRECONDITION_FAILED, event);
goto exit_function; goto exit_function;
@@ -706,28 +706,28 @@ void gena_process_notification_event(
sid.buff = sid_hdr.buf; sid.buff = sid_hdr.buf;
sid.size = sid_hdr.length; sid.size = sid_hdr.length;
// get event key /* get event key */
if (httpmsg_find_hdr(event, HDR_SEQ, &seq_hdr) == NULL || if (httpmsg_find_hdr(event, HDR_SEQ, &seq_hdr) == NULL ||
matchstr(seq_hdr.buf, seq_hdr.length, "%d%0", &eventKey) != PARSE_OK) { matchstr(seq_hdr.buf, seq_hdr.length, "%d%0", &eventKey) != PARSE_OK) {
error_respond( info, HTTP_BAD_REQUEST, event ); error_respond( info, HTTP_BAD_REQUEST, event );
goto exit_function; goto exit_function;
} }
// get NT and NTS headers /* get NT and NTS headers */
if (httpmsg_find_hdr(event, HDR_NT, &nt_hdr) == NULL || if (httpmsg_find_hdr(event, HDR_NT, &nt_hdr) == NULL ||
httpmsg_find_hdr(event, HDR_NTS, &nts_hdr) == NULL) { httpmsg_find_hdr(event, HDR_NTS, &nts_hdr) == NULL) {
error_respond( info, HTTP_BAD_REQUEST, event ); error_respond( info, HTTP_BAD_REQUEST, event );
goto exit_function; goto exit_function;
} }
// verify NT and NTS headers /* verify NT and NTS headers */
if (memptr_cmp(&nt_hdr, "upnp:event") != 0 || if (memptr_cmp(&nt_hdr, "upnp:event") != 0 ||
memptr_cmp(&nts_hdr, "upnp:propchange") != 0) { memptr_cmp(&nts_hdr, "upnp:propchange") != 0) {
error_respond(info, HTTP_PRECONDITION_FAILED, event); error_respond(info, HTTP_PRECONDITION_FAILED, event);
goto exit_function; goto exit_function;
} }
// parse the content (should be XML) /* parse the content (should be XML) */
if (!has_xml_content_type(event) || if (!has_xml_content_type(event) ||
event->msg.length == 0 || event->msg.length == 0 ||
ixmlParseBufferEx(event->entity.buf, &ChangedVars) != IXML_SUCCESS) { ixmlParseBufferEx(event->entity.buf, &ChangedVars) != IXML_SUCCESS) {
@@ -737,28 +737,28 @@ void gena_process_notification_event(
HandleLock(); HandleLock();
// get client info /* get client info */
if (GetClientHandleInfo(&client_handle, &handle_info) != HND_CLIENT) { if (GetClientHandleInfo(&client_handle, &handle_info) != HND_CLIENT) {
error_respond(info, HTTP_PRECONDITION_FAILED, event); error_respond(info, HTTP_PRECONDITION_FAILED, event);
HandleUnlock(); HandleUnlock();
goto exit_function; goto exit_function;
} }
// get subscription based on SID /* get subscription based on SID */
subscription = GetClientSubActualSID(handle_info->ClientSubList, &sid); subscription = GetClientSubActualSID(handle_info->ClientSubList, &sid);
if (subscription == NULL) { if (subscription == NULL) {
if (eventKey == 0) { if (eventKey == 0) {
// wait until we've finished processing a subscription /* wait until we've finished processing a subscription */
// (if we are in the middle) /* (if we are in the middle) */
// this is to avoid mistakenly rejecting the first event if we /* this is to avoid mistakenly rejecting the first event if we */
// receive it before the subscription response /* receive it before the subscription response */
HandleUnlock(); HandleUnlock();
// try and get Subscription Lock /* try and get Subscription Lock */
// (in case we are in the process of subscribing) /* (in case we are in the process of subscribing) */
SubscribeLock(); SubscribeLock();
// get HandleLock again /* get HandleLock again */
HandleLock(); HandleLock();
if (GetClientHandleInfo(&client_handle, &handle_info) != HND_CLIENT) { if (GetClientHandleInfo(&client_handle, &handle_info) != HND_CLIENT) {
@@ -784,25 +784,25 @@ void gena_process_notification_event(
} }
} }
// success /* success */
error_respond(info, HTTP_OK, event); error_respond(info, HTTP_OK, event);
// fill event struct /* fill event struct */
tmpSID = UpnpClientSubscription_get_SID(subscription); tmpSID = UpnpClientSubscription_get_SID(subscription);
strcpy(event_struct.Sid, UpnpString_get_String(tmpSID)); strcpy(event_struct.Sid, UpnpString_get_String(tmpSID));
event_struct.EventKey = eventKey; event_struct.EventKey = eventKey;
event_struct.ChangedVariables = ChangedVars; event_struct.ChangedVariables = ChangedVars;
// copy callback /* copy callback */
callback = handle_info->Callback; callback = handle_info->Callback;
cookie = handle_info->Cookie; cookie = handle_info->Cookie;
HandleUnlock(); HandleUnlock();
// make callback with event struct /* make callback with event struct */
// In future, should find a way of mainting /* In future, should find a way of mainting */
// that the handle is not unregistered in the middle of a /* that the handle is not unregistered in the middle of a */
// callback /* callback */
callback(UPNP_EVENT_RECEIVED, &event_struct, cookie); callback(UPNP_EVENT_RECEIVED, &event_struct, cookie);
exit_function: exit_function:

View File

@@ -29,19 +29,15 @@
* *
******************************************************************************/ ******************************************************************************/
/*! /*!
* \file * \file
*/ */
#include "config.h" #include "config.h"
#if EXCLUDE_GENA == 0 #if EXCLUDE_GENA == 0
#ifdef INCLUDE_DEVICE_APIS #ifdef INCLUDE_DEVICE_APIS
#include "gena.h" #include "gena.h"
#include "httpparser.h" #include "httpparser.h"
#include "httpreadwrite.h" #include "httpreadwrite.h"
@@ -53,7 +49,6 @@
#include "upnpapi.h" #include "upnpapi.h"
#include "uuid.h" #include "uuid.h"
/*! /*!
* \brief Unregisters a device. * \brief Unregisters a device.
* *
@@ -81,7 +76,6 @@ int genaUnregisterDevice(
return ret; return ret;
} }
/*! /*!
* \brief Generates XML property set for notifications. * \brief Generates XML property set for notifications.
* *
@@ -102,7 +96,7 @@ static int GeneratePropertySet(
{ {
char *buffer; char *buffer;
int counter = 0; int counter = 0;
int size = 0; size_t size = 0;
int temp_counter = 0; int temp_counter = 0;
/*size += strlen(XML_VERSION);*/ /*size += strlen(XML_VERSION);*/
@@ -116,9 +110,8 @@ static int GeneratePropertySet(
} }
buffer = (char *)malloc(size + 1); buffer = (char *)malloc(size + 1);
if (buffer == NULL) { if (buffer == NULL)
return UPNP_E_OUTOF_MEMORY; return UPNP_E_OUTOF_MEMORY;
}
memset(buffer, 0, size + 1); memset(buffer, 0, size + 1);
/* /*
strcpy(buffer,XML_VERSION); strcpy(buffer,XML_VERSION);
@@ -140,7 +133,6 @@ static int GeneratePropertySet(
return XML_SUCCESS; return XML_SUCCESS;
} }
/*! /*!
* \brief Frees memory used in notify_threads if the reference count is 0, * \brief Frees memory used in notify_threads if the reference count is 0,
* otherwise decrements the refrence count. * otherwise decrements the refrence count.
@@ -160,7 +152,6 @@ static void free_notify_struct(
free(input); free(input);
} }
/*! /*!
* \brief Sends the notify message and returns a reply. * \brief Sends the notify message and returns a reply.
* *
@@ -179,12 +170,13 @@ static UPNP_INLINE int notify_send_and_recv(
http_parser_t *response) http_parser_t *response)
{ {
uri_type url; uri_type url;
int conn_fd; SOCKET conn_fd;
membuffer start_msg; membuffer start_msg;
int ret_code; int ret_code;
int err_code; int err_code;
int timeout; int timeout;
SOCKINFO info; SOCKINFO info;
const char *CRLF = "\r\n";
/* connect */ /* connect */
UpnpPrintf(UPNP_ALL, GENA, __FILE__, __LINE__, UpnpPrintf(UPNP_ALL, GENA, __FILE__, __LINE__,
@@ -193,16 +185,12 @@ static UPNP_INLINE int notify_send_and_recv(
destination_url->hostport.text.buff); destination_url->hostport.text.buff);
conn_fd = http_Connect(destination_url, &url); conn_fd = http_Connect(destination_url, &url);
if (conn_fd < 0) { if (conn_fd < 0)
/* return UPNP error */ /* return UPNP error */
return UPNP_E_SOCKET_CONNECT;
return conn_fd;
}
ret_code = sock_init(&info, conn_fd); ret_code = sock_init(&info, conn_fd);
if (ret_code) { if (ret_code) {
sock_destroy(&info, SD_BOTH); sock_destroy(&info, SD_BOTH);
return ret_code; return ret_code;
} }
/* make start line and HOST header */ /* make start line and HOST header */
@@ -214,35 +202,29 @@ static UPNP_INLINE int notify_send_and_recv(
mid_msg->buf) != 0) { 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;
} }
timeout = GENA_NOTIFICATION_SENDING_TIMEOUT;
timeout = HTTP_DEFAULT_TIMEOUT;
/* send msg (note: end of notification will contain "\r\n" twice) */ /* send msg (note: end of notification will contain "\r\n" twice) */
ret_code = http_SendMessage(&info, &timeout, ret_code = http_SendMessage(&info, &timeout,
"bbb", "bbb",
start_msg.buf, start_msg.length, start_msg.buf, start_msg.length,
propertySet, strlen(propertySet), propertySet, strlen(propertySet),
"\r\n", 2); CRLF, sizeof CRLF);
if (ret_code) { if (ret_code) {
membuffer_destroy(&start_msg); membuffer_destroy(&start_msg);
sock_destroy(&info, SD_BOTH); sock_destroy(&info, SD_BOTH);
return ret_code; return ret_code;
} }
timeout = GENA_NOTIFICATION_ANSWERING_TIMEOUT;
ret_code = http_RecvMessage(&info, response, ret_code = http_RecvMessage(&info, response,
HTTPMETHOD_NOTIFY, &timeout, &err_code); HTTPMETHOD_NOTIFY, &timeout, &err_code);
if (ret_code) { if (ret_code) {
membuffer_destroy(&start_msg); membuffer_destroy(&start_msg);
sock_destroy(&info, SD_BOTH); sock_destroy(&info, SD_BOTH);
httpmsg_destroy(&response->msg); httpmsg_destroy(&response->msg);
return ret_code; return ret_code;
} }
/* should shutdown completely when closing socket */ /* should shutdown completely when closing socket */
sock_destroy(&info, SD_BOTH); sock_destroy(&info, SD_BOTH);
membuffer_destroy(&start_msg); membuffer_destroy(&start_msg);
@@ -250,7 +232,6 @@ static UPNP_INLINE int notify_send_and_recv(
return UPNP_E_SUCCESS; return UPNP_E_SUCCESS;
} }
/*! /*!
* \brief Function to Notify a particular subscription of a particular event. * \brief Function to Notify a particular subscription of a particular event.
* *
@@ -270,7 +251,7 @@ static int genaNotify(
/*! [in] subscription to be Notified, assumes this is valid for life of function. */ /*! [in] subscription to be Notified, assumes this is valid for life of function. */
subscription *sub) subscription *sub)
{ {
int i; size_t i;
membuffer mid_msg; membuffer mid_msg;
membuffer endmsg; membuffer endmsg;
uri_type *url; uri_type *url;
@@ -278,11 +259,9 @@ static int genaNotify(
int return_code = -1; int return_code = -1;
membuffer_init(&mid_msg); membuffer_init(&mid_msg);
/* 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( if (http_MakeMessage(&mid_msg, 1, 1,
&mid_msg, 1, 1,
"s" "ssc" "sdcc", "s" "ssc" "sdcc",
headers, headers,
"SID: ", sub->sid, "SID: ", sub->sid,
@@ -290,31 +269,25 @@ static int genaNotify(
membuffer_destroy(&mid_msg); membuffer_destroy(&mid_msg);
return UPNP_E_OUTOF_MEMORY; return UPNP_E_OUTOF_MEMORY;
} }
// send a notify to each url until one goes thru /* send a notify to each url until one goes thru */
for (i = 0; i < sub->DeliveryURLs.size; i++) { for (i = 0; i < sub->DeliveryURLs.size; i++) {
url = &sub->DeliveryURLs.parsedURLs[i]; url = &sub->DeliveryURLs.parsedURLs[i];
return_code = notify_send_and_recv(
if( ( return_code = notify_send_and_recv( url, url, &mid_msg, propertySet, &response);
&mid_msg, propertySet, if (return_code == UPNP_E_SUCCESS)
&response ) ) ==
UPNP_E_SUCCESS ) {
break; break;
} }
}
membuffer_destroy(&mid_msg); membuffer_destroy(&mid_msg);
if (return_code == UPNP_E_SUCCESS) { if (return_code == UPNP_E_SUCCESS) {
if( response.msg.status_code == HTTP_OK ) { if (response.msg.status_code == HTTP_OK)
return_code = GENA_SUCCESS; return_code = GENA_SUCCESS;
} else { else {
if( response.msg.status_code == HTTP_PRECONDITION_FAILED ) { if (response.msg.status_code == HTTP_PRECONDITION_FAILED)
//Invalid SID gets removed /*Invalid SID gets removed */
return_code = GENA_E_NOTIFY_UNACCEPTED_REMOVE_SUB; return_code = GENA_E_NOTIFY_UNACCEPTED_REMOVE_SUB;
} else { else
return_code = GENA_E_NOTIFY_UNACCEPTED; return_code = GENA_E_NOTIFY_UNACCEPTED;
} }
}
httpmsg_destroy(&response.msg); httpmsg_destroy(&response.msg);
} }
@@ -346,9 +319,9 @@ static void genaNotifyThread(
* is a lot of notifications, then multiple threads will acquire a read * is a lot of notifications, then multiple threads will acquire a read
* lock and the thread which sends the notification will be blocked forever * lock and the thread which sends the notification will be blocked forever
* on the HandleLock at the end of this function. */ * on the HandleLock at the end of this function. */
//HandleReadLock(); /*HandleReadLock(); */
HandleLock(); HandleLock();
//validate context /* validate context */
if (GetHandleInfo(in->device_handle, &handle_info) != HND_DEVICE) { if (GetHandleInfo(in->device_handle, &handle_info) != HND_DEVICE) {
free_notify_struct(in); free_notify_struct(in);
@@ -356,31 +329,25 @@ static void genaNotifyThread(
return; return;
} }
if( ( ( service = FindServiceId( &handle_info->ServiceTable, if (!(service = FindServiceId(&handle_info->ServiceTable, in->servId, in->UDN)) ||
in->servId, in->UDN ) ) == NULL ) !service->active ||
|| ( !service->active ) !(sub = GetSubscriptionSID(in->sid, service)) ||
|| ( ( sub = GetSubscriptionSID( in->sid, service ) ) == NULL ) copy_subscription(sub, &sub_copy) != HTTP_SUCCESS) {
|| ( ( copy_subscription( sub, &sub_copy ) != HTTP_SUCCESS ) ) ) {
free_notify_struct(in); free_notify_struct(in);
HandleUnlock(); HandleUnlock();
return; return;
} }
#ifdef UPNP_ENABLE_NOTIFICATION_REORDERING #ifdef UPNP_ENABLE_NOTIFICATION_REORDERING
//If the event is out of order push it back to the job queue /*If the event is out of order push it back to the job queue */
if (in->eventKey != sub->ToSendEventKey) { if (in->eventKey != sub->ToSendEventKey) {
TPJobInit(&job, (start_routine) genaNotifyThread, input); TPJobInit(&job, (start_routine) genaNotifyThread, input);
TPJobSetFreeFunction(&job, (free_function) free_notify_struct); TPJobSetFreeFunction(&job, (free_function) free_notify_struct);
TPJobSetPriority(&job, MED_PRIORITY); TPJobSetPriority(&job, MED_PRIORITY);
/* Sleep a little before creating another thread otherwise if there is /* Sleep a little before creating another thread otherwise if there is
* a lot of notifications to send, the device will take 100% of the CPU * a lot of notifications to send, the device will take 100% of the CPU
* to create threads and push them back to the job queue. */ * to create threads and push them back to the job queue. */
imillisleep(1); imillisleep(1);
ThreadPoolAdd(&gSendThreadPool, &job, NULL); ThreadPoolAdd(&gSendThreadPool, &job, NULL);
freeSubscription(&sub_copy); freeSubscription(&sub_copy);
HandleUnlock(); HandleUnlock();
return; return;
@@ -389,38 +356,31 @@ static void genaNotifyThread(
HandleUnlock(); HandleUnlock();
//send the notify /* send the notify */
return_code = genaNotify(in->headers, in->propertySet, &sub_copy); return_code = genaNotify(in->headers, in->propertySet, &sub_copy);
freeSubscription(&sub_copy); freeSubscription(&sub_copy);
HandleLock(); HandleLock();
if (GetHandleInfo(in->device_handle, &handle_info) != HND_DEVICE) { if (GetHandleInfo(in->device_handle, &handle_info) != HND_DEVICE) {
free_notify_struct(in); free_notify_struct(in);
HandleUnlock(); HandleUnlock();
return; return;
} }
//validate context /* validate context */
if( ( ( service = FindServiceId( &handle_info->ServiceTable, if (!(service = FindServiceId(&handle_info->ServiceTable, in->servId, in->UDN)) ||
in->servId, in->UDN ) ) == NULL ) !service->active ||
|| ( !service->active ) !(sub = GetSubscriptionSID(in->sid, service))) {
|| ( ( sub = GetSubscriptionSID( in->sid, service ) ) == NULL ) ) {
free_notify_struct(in); free_notify_struct(in);
HandleUnlock(); HandleUnlock();
return; return;
} }
sub->ToSendEventKey++; sub->ToSendEventKey++;
if (sub->ToSendEventKey < 0)
if( sub->ToSendEventKey < 0 ) //wrap to 1 for overflow /* wrap to 1 for overflow */
sub->ToSendEventKey = 1; sub->ToSendEventKey = 1;
if (return_code == GENA_E_NOTIFY_UNACCEPTED_REMOVE_SUB)
if( return_code == GENA_E_NOTIFY_UNACCEPTED_REMOVE_SUB ) {
RemoveSubscriptionSID(in->sid, service); RemoveSubscriptionSID(in->sid, service);
}
free_notify_struct(in); free_notify_struct(in);
HandleUnlock(); HandleUnlock();
} }
@@ -448,7 +408,7 @@ static char *AllocGenaHeaders(
static const char *HEADER_LINE_4 = static const char *HEADER_LINE_4 =
"NTS: upnp:propchange\r\n"; "NTS: upnp:propchange\r\n";
char *headers = NULL; char *headers = NULL;
int headers_size = 0; size_t headers_size = 0;
int line = 0; int line = 0;
headers_size = headers_size =
@@ -1135,8 +1095,8 @@ static int create_url_list(
/*! [out] . */ /*! [out] . */
URL_list *out) URL_list *out)
{ {
int URLcount = 0; size_t URLcount = 0;
int i; size_t i;
int return_code = 0; int return_code = 0;
uri_type temp; uri_type temp;
token urls; token urls;
@@ -1166,10 +1126,9 @@ static int create_url_list(
} }
if( URLcount > 0 ) { if( URLcount > 0 ) {
out->URLs = ( char * )malloc( URLS->size + 1 ); out->URLs = malloc(URLS->size + 1);
out->parsedURLs = out->parsedURLs = malloc(sizeof(uri_type) * URLcount);
( uri_type * ) malloc( sizeof( uri_type ) * URLcount ); if (!out->URLs || !out->parsedURLs) {
if( ( out->URLs == NULL ) || ( out->parsedURLs == NULL ) ) {
free(out->URLs); free(out->URLs);
free(out->parsedURLs); free(out->parsedURLs);
out->URLs = NULL; out->URLs = NULL;
@@ -1202,7 +1161,7 @@ static int create_url_list(
} }
out->size = URLcount; out->size = URLcount;
return URLcount; return (int)URLcount;
} }
@@ -1234,20 +1193,20 @@ void gena_process_subscription_request(
goto exit_function; goto exit_function;
} }
// check NT header /* check NT header */
// Windows Millenium Interoperability: /* Windows Millenium Interoperability: */
// we accept either upnp:event, or upnp:propchange for the NT header /* we accept either upnp:event, or upnp:propchange for the NT header */
if (memptr_cmp_nocase(&nt_hdr, "upnp:event") != 0) { if (memptr_cmp_nocase(&nt_hdr, "upnp:event") != 0) {
error_respond(info, HTTP_PRECONDITION_FAILED, request); error_respond(info, HTTP_PRECONDITION_FAILED, request);
goto exit_function; goto exit_function;
} }
// if a SID is present then the we have a bad request "incompatible headers" /* if a SID is present then the we have a bad request "incompatible headers" */
if (httpmsg_find_hdr(request, HDR_SID, NULL) != NULL) { if (httpmsg_find_hdr(request, HDR_SID, NULL) != NULL) {
error_respond(info, HTTP_BAD_REQUEST, request); error_respond(info, HTTP_BAD_REQUEST, request);
goto exit_function; goto exit_function;
} }
// look up service by eventURL /* look up service by eventURL */
event_url_path = str_alloc(request->uri.pathquery.buff, request->uri.pathquery.size); event_url_path = str_alloc(request->uri.pathquery.buff, request->uri.pathquery.size);
if (event_url_path == NULL) { if (event_url_path == NULL) {
error_respond(info, HTTP_INTERNAL_SERVER_ERROR, request); error_respond(info, HTTP_INTERNAL_SERVER_ERROR, request);
@@ -1260,7 +1219,7 @@ void gena_process_subscription_request(
HandleLock(); HandleLock();
// CURRENTLY, ONLY ONE DEVICE /* CURRENTLY, ONLY ONE DEVICE */
if (GetDeviceHandleInfo(info->foreign_sockaddr.ss_family , if (GetDeviceHandleInfo(info->foreign_sockaddr.ss_family ,
&device_handle, &handle_info) != HND_DEVICE) { &device_handle, &handle_info) != HND_DEVICE) {
free(event_url_path); free(event_url_path);
@@ -1283,14 +1242,14 @@ void gena_process_subscription_request(
service->TotalSubscriptions, service->TotalSubscriptions,
handle_info->MaxSubscriptions); handle_info->MaxSubscriptions);
// too many subscriptions /* too many subscriptions */
if (handle_info->MaxSubscriptions != -1 && if (handle_info->MaxSubscriptions != -1 &&
service->TotalSubscriptions >= handle_info->MaxSubscriptions) { service->TotalSubscriptions >= handle_info->MaxSubscriptions) {
error_respond(info, HTTP_INTERNAL_SERVER_ERROR, request); error_respond(info, HTTP_INTERNAL_SERVER_ERROR, request);
HandleUnlock(); HandleUnlock();
goto exit_function; goto exit_function;
} }
// generate new subscription /* generate new subscription */
sub = (subscription *)malloc(sizeof (subscription)); sub = (subscription *)malloc(sizeof (subscription));
if (sub == NULL) { if (sub == NULL) {
error_respond(info, HTTP_INTERNAL_SERVER_ERROR, request); error_respond(info, HTTP_INTERNAL_SERVER_ERROR, request);
@@ -1305,7 +1264,7 @@ void gena_process_subscription_request(
sub->DeliveryURLs.URLs = NULL; sub->DeliveryURLs.URLs = NULL;
sub->DeliveryURLs.parsedURLs = NULL; sub->DeliveryURLs.parsedURLs = NULL;
// check for valid callbacks /* check for valid callbacks */
if (httpmsg_find_hdr( request, HDR_CALLBACK, &callback_hdr) == NULL) { if (httpmsg_find_hdr( request, HDR_CALLBACK, &callback_hdr) == NULL) {
error_respond(info, HTTP_PRECONDITION_FAILED, request); error_respond(info, HTTP_PRECONDITION_FAILED, request);
freeSubscriptionList(sub); freeSubscriptionList(sub);
@@ -1325,20 +1284,20 @@ void gena_process_subscription_request(
HandleUnlock(); HandleUnlock();
goto exit_function; goto exit_function;
} }
// set the timeout /* set the timeout */
if (httpmsg_find_hdr(request, HDR_TIMEOUT, &timeout_hdr) != NULL) { if (httpmsg_find_hdr(request, HDR_TIMEOUT, &timeout_hdr) != NULL) {
if (matchstr(timeout_hdr.buf, timeout_hdr.length, if (matchstr(timeout_hdr.buf, timeout_hdr.length,
"%iSecond-%d%0", &time_out) == PARSE_OK) { "%iSecond-%d%0", &time_out) == PARSE_OK) {
// nothing /* nothing */
} else if(memptr_cmp_nocase(&timeout_hdr, "Second-infinite") == 0) { } else if(memptr_cmp_nocase(&timeout_hdr, "Second-infinite") == 0) {
// infinite timeout /* infinite timeout */
time_out = -1; time_out = -1;
} else { } else {
// default is > 1800 seconds /* default is > 1800 seconds */
time_out = DEFAULT_TIMEOUT; time_out = DEFAULT_TIMEOUT;
} }
} }
// replace infinite timeout with max timeout, if possible /* replace infinite timeout with max timeout, if possible */
if (handle_info->MaxSubscriptionTimeOut != -1) { if (handle_info->MaxSubscriptionTimeOut != -1) {
if (time_out == -1 || if (time_out == -1 ||
time_out > handle_info->MaxSubscriptionTimeOut) { time_out > handle_info->MaxSubscriptionTimeOut) {
@@ -1348,40 +1307,40 @@ void gena_process_subscription_request(
if (time_out >= 0) { if (time_out >= 0) {
sub->expireTime = time(NULL) + time_out; sub->expireTime = time(NULL) + time_out;
} else { } else {
// infinite time /* infinite time */
sub->expireTime = 0; sub->expireTime = 0;
} }
// generate SID /* generate SID */
uuid_create(&uid); uuid_create(&uid);
uuid_unpack(&uid, temp_sid); uuid_unpack(&uid, temp_sid);
sprintf(sub->sid, "uuid:%s", temp_sid); sprintf(sub->sid, "uuid:%s", temp_sid);
// respond OK /* respond OK */
if (respond_ok(info, time_out, sub, request) != UPNP_E_SUCCESS) { if (respond_ok(info, time_out, sub, request) != UPNP_E_SUCCESS) {
freeSubscriptionList(sub); freeSubscriptionList(sub);
HandleUnlock(); HandleUnlock();
goto exit_function; goto exit_function;
} }
// add to subscription list /* add to subscription list */
sub->next = service->subscriptionList; sub->next = service->subscriptionList;
service->subscriptionList = sub; service->subscriptionList = sub;
service->TotalSubscriptions++; service->TotalSubscriptions++;
// finally generate callback for init table dump /* finally generate callback for init table dump */
request_struct.ServiceId = service->serviceId; request_struct.ServiceId = service->serviceId;
request_struct.UDN = service->UDN; request_struct.UDN = service->UDN;
strcpy((char *)request_struct.Sid, sub->sid); strcpy((char *)request_struct.Sid, sub->sid);
// copy callback /* copy callback */
callback_fun = handle_info->Callback; callback_fun = handle_info->Callback;
cookie = handle_info->Cookie; cookie = handle_info->Cookie;
HandleUnlock(); HandleUnlock();
// make call back with request struct /* make call back with request struct */
// in the future should find a way of mainting that the handle /* in the future should find a way of mainting that the handle */
// is not unregistered in the middle of a callback /* is not unregistered in the middle of a callback */
callback_fun(UPNP_EVENT_SUBSCRIPTION_REQUEST, &request_struct, cookie); callback_fun(UPNP_EVENT_SUBSCRIPTION_REQUEST, &request_struct, cookie);
exit_function: exit_function:
@@ -1403,13 +1362,13 @@ void gena_process_subscription_renewal_request(
membuffer event_url_path; membuffer event_url_path;
memptr timeout_hdr; memptr timeout_hdr;
// if a CALLBACK or NT header is present, then it is an error /* if a CALLBACK or NT header is present, then it is an error */
if( httpmsg_find_hdr( request, HDR_CALLBACK, NULL ) != NULL || if( httpmsg_find_hdr( request, HDR_CALLBACK, NULL ) != NULL ||
httpmsg_find_hdr( request, HDR_NT, NULL ) != NULL ) { httpmsg_find_hdr( request, HDR_NT, NULL ) != NULL ) {
error_respond( info, HTTP_BAD_REQUEST, request ); error_respond( info, HTTP_BAD_REQUEST, request );
return; return;
} }
// get SID /* get SID */
if( httpmsg_find_hdr( request, HDR_SID, &temp_hdr ) == NULL || if( httpmsg_find_hdr( request, HDR_SID, &temp_hdr ) == NULL ||
temp_hdr.length > SID_SIZE ) { temp_hdr.length > SID_SIZE ) {
error_respond( info, HTTP_PRECONDITION_FAILED, request ); error_respond( info, HTTP_PRECONDITION_FAILED, request );
@@ -1418,7 +1377,7 @@ void gena_process_subscription_renewal_request(
memcpy( sid, temp_hdr.buf, temp_hdr.length ); memcpy( sid, temp_hdr.buf, temp_hdr.length );
sid[temp_hdr.length] = '\0'; sid[temp_hdr.length] = '\0';
// lookup service by eventURL /* lookup service by eventURL */
membuffer_init( &event_url_path ); membuffer_init( &event_url_path );
if( membuffer_append( &event_url_path, request->uri.pathquery.buff, if( membuffer_append( &event_url_path, request->uri.pathquery.buff,
request->uri.pathquery.size ) != 0 ) { request->uri.pathquery.size ) != 0 ) {
@@ -1428,7 +1387,7 @@ void gena_process_subscription_renewal_request(
HandleLock(); HandleLock();
// CURRENTLY, ONLY SUPPORT ONE DEVICE /* CURRENTLY, ONLY SUPPORT ONE DEVICE */
if( GetDeviceHandleInfo( info->foreign_sockaddr.ss_family, if( GetDeviceHandleInfo( info->foreign_sockaddr.ss_family,
&device_handle, &handle_info ) != HND_DEVICE ) { &device_handle, &handle_info ) != HND_DEVICE ) {
error_respond( info, HTTP_PRECONDITION_FAILED, request ); error_respond( info, HTTP_PRECONDITION_FAILED, request );
@@ -1440,7 +1399,7 @@ void gena_process_subscription_renewal_request(
event_url_path.buf ); event_url_path.buf );
membuffer_destroy( &event_url_path ); membuffer_destroy( &event_url_path );
// get subscription /* get subscription */
if( service == NULL || if( service == NULL ||
!service->active || !service->active ||
( ( sub = GetSubscriptionSID( sid, service ) ) == NULL ) ) { ( ( sub = GetSubscriptionSID( sid, service ) ) == NULL ) ) {
@@ -1454,7 +1413,7 @@ void gena_process_subscription_renewal_request(
"Max Subscriptions allowed:%d\n", "Max Subscriptions allowed:%d\n",
service->TotalSubscriptions, service->TotalSubscriptions,
handle_info->MaxSubscriptions ); handle_info->MaxSubscriptions );
// too many subscriptions /* too many subscriptions */
if( handle_info->MaxSubscriptions != -1 && if( handle_info->MaxSubscriptions != -1 &&
service->TotalSubscriptions > handle_info->MaxSubscriptions ) { service->TotalSubscriptions > handle_info->MaxSubscriptions ) {
error_respond( info, HTTP_INTERNAL_SERVER_ERROR, request ); error_respond( info, HTTP_INTERNAL_SERVER_ERROR, request );
@@ -1462,25 +1421,25 @@ void gena_process_subscription_renewal_request(
HandleUnlock(); HandleUnlock();
return; return;
} }
// set the timeout /* set the timeout */
if( httpmsg_find_hdr( request, HDR_TIMEOUT, &timeout_hdr ) != NULL ) { if( httpmsg_find_hdr( request, HDR_TIMEOUT, &timeout_hdr ) != NULL ) {
if( matchstr( timeout_hdr.buf, timeout_hdr.length, if( matchstr( timeout_hdr.buf, timeout_hdr.length,
"%iSecond-%d%0", &time_out ) == PARSE_OK ) { "%iSecond-%d%0", &time_out ) == PARSE_OK ) {
//nothing /*nothing */
} else if( memptr_cmp_nocase( &timeout_hdr, "Second-infinite" ) == } else if( memptr_cmp_nocase( &timeout_hdr, "Second-infinite" ) ==
0 ) { 0 ) {
time_out = -1; // inifinite timeout time_out = -1; /* inifinite timeout */
} else { } else {
time_out = DEFAULT_TIMEOUT; // default is > 1800 seconds time_out = DEFAULT_TIMEOUT; /* default is > 1800 seconds */
} }
} }
// replace infinite timeout with max timeout, if possible /* replace infinite timeout with max timeout, if possible */
if( handle_info->MaxSubscriptionTimeOut != -1 ) { if( handle_info->MaxSubscriptionTimeOut != -1 ) {
if( time_out == -1 || if( time_out == -1 ||
time_out > handle_info->MaxSubscriptionTimeOut ) { time_out > handle_info->MaxSubscriptionTimeOut ) {
@@ -1514,13 +1473,13 @@ void gena_process_unsubscribe_request(
memptr temp_hdr; memptr temp_hdr;
membuffer event_url_path; membuffer event_url_path;
// if a CALLBACK or NT header is present, then it is an error /* if a CALLBACK or NT header is present, then it is an error */
if( httpmsg_find_hdr( request, HDR_CALLBACK, NULL ) != NULL || if( httpmsg_find_hdr( request, HDR_CALLBACK, NULL ) != NULL ||
httpmsg_find_hdr( request, HDR_NT, NULL ) != NULL ) { httpmsg_find_hdr( request, HDR_NT, NULL ) != NULL ) {
error_respond( info, HTTP_BAD_REQUEST, request ); error_respond( info, HTTP_BAD_REQUEST, request );
return; return;
} }
// get SID /* get SID */
if( httpmsg_find_hdr( request, HDR_SID, &temp_hdr ) == NULL || if( httpmsg_find_hdr( request, HDR_SID, &temp_hdr ) == NULL ||
temp_hdr.length > SID_SIZE ) { temp_hdr.length > SID_SIZE ) {
error_respond( info, HTTP_PRECONDITION_FAILED, request ); error_respond( info, HTTP_PRECONDITION_FAILED, request );
@@ -1529,7 +1488,7 @@ void gena_process_unsubscribe_request(
memcpy( sid, temp_hdr.buf, temp_hdr.length ); memcpy( sid, temp_hdr.buf, temp_hdr.length );
sid[temp_hdr.length] = '\0'; sid[temp_hdr.length] = '\0';
// lookup service by eventURL /* lookup service by eventURL */
membuffer_init( &event_url_path ); membuffer_init( &event_url_path );
if( membuffer_append( &event_url_path, request->uri.pathquery.buff, if( membuffer_append( &event_url_path, request->uri.pathquery.buff,
request->uri.pathquery.size ) != 0 ) { request->uri.pathquery.size ) != 0 ) {
@@ -1539,7 +1498,7 @@ void gena_process_unsubscribe_request(
HandleLock(); HandleLock();
// CURRENTLY, ONLY SUPPORT ONE DEVICE /* CURRENTLY, ONLY SUPPORT ONE DEVICE */
if( GetDeviceHandleInfo( info->foreign_sockaddr.ss_family, if( GetDeviceHandleInfo( info->foreign_sockaddr.ss_family,
&device_handle, &handle_info ) != HND_DEVICE ) { &device_handle, &handle_info ) != HND_DEVICE ) {
error_respond( info, HTTP_PRECONDITION_FAILED, request ); error_respond( info, HTTP_PRECONDITION_FAILED, request );
@@ -1551,7 +1510,7 @@ void gena_process_unsubscribe_request(
event_url_path.buf ); event_url_path.buf );
membuffer_destroy( &event_url_path ); membuffer_destroy( &event_url_path );
// validate service /* validate service */
if( service == NULL || if( service == NULL ||
!service->active || GetSubscriptionSID( sid, service ) == NULL ) !service->active || GetSubscriptionSID( sid, service ) == NULL )
{ {
@@ -1561,7 +1520,7 @@ void gena_process_unsubscribe_request(
} }
RemoveSubscriptionSID(sid, service); RemoveSubscriptionSID(sid, service);
error_respond(info, HTTP_OK, request); // success error_respond(info, HTTP_OK, request); /* success */
HandleUnlock(); HandleUnlock();
} }

View File

@@ -46,7 +46,7 @@
#ifdef INCLUDE_CLIENT_APIS #ifdef INCLUDE_CLIENT_APIS
#include <stdlib.h> // for calloc(), free() #include <stdlib.h> /* for calloc(), free() */
struct SClientSubscription { struct SClientSubscription {
@@ -113,12 +113,12 @@ ClientSubscription *UpnpClientSubscription_dup(const ClientSubscription *p)
void UpnpClientSubscription_assign(ClientSubscription *q, const ClientSubscription *p) void UpnpClientSubscription_assign(ClientSubscription *q, const ClientSubscription *p)
{ {
if (q != p) { if (q != p) {
// Do not copy RenewEventId /* Do not copy RenewEventId */
((struct SClientSubscription *)q)->m_renewEventId = -1; ((struct SClientSubscription *)q)->m_renewEventId = -1;
UpnpClientSubscription_set_SID(q, UpnpClientSubscription_get_SID(p)); UpnpClientSubscription_set_SID(q, UpnpClientSubscription_get_SID(p));
UpnpClientSubscription_set_ActualSID(q, UpnpClientSubscription_get_ActualSID(p)); UpnpClientSubscription_set_ActualSID(q, UpnpClientSubscription_get_ActualSID(p));
UpnpClientSubscription_set_EventURL(q, UpnpClientSubscription_get_EventURL(p)); UpnpClientSubscription_set_EventURL(q, UpnpClientSubscription_get_EventURL(p));
// Do not copy m_next /* Do not copy m_next */
((struct SClientSubscription *)q)->m_next = NULL; ((struct SClientSubscription *)q)->m_next = NULL;
} }
} }
@@ -238,8 +238,8 @@ void free_client_subscription(ClientSubscription *sub)
UpnpClientSubscription_strcpy_ActualSID(sub, ""); UpnpClientSubscription_strcpy_ActualSID(sub, "");
UpnpClientSubscription_strcpy_EventURL(sub, ""); UpnpClientSubscription_strcpy_EventURL(sub, "");
if (renewEventId != -1) { if (renewEventId != -1) {
// do not remove timer event of copy /* do not remove timer event of copy */
// invalid timer event id /* invalid timer event id */
if (TimerThreadRemove(&gTimerThread, renewEventId, &tempJob) == 0) { if (TimerThreadRemove(&gTimerThread, renewEventId, &tempJob) == 0) {
event = (upnp_timeout *)tempJob.arg; event = (upnp_timeout *)tempJob.arg;
free_upnp_timeout(event); free_upnp_timeout(event);

View File

@@ -57,7 +57,7 @@
#include "ThreadPool.h" #include "ThreadPool.h"
#include "unixutil.h" /* for socklen_t, EAFNOSUPPORT */ #include "unixutil.h" /* for socklen_t, EAFNOSUPPORT */
#include "upnpapi.h" #include "upnpapi.h"
#include "util.h" #include "upnputil.h"
#include <assert.h> #include <assert.h>
@@ -74,7 +74,7 @@
struct mserv_request_t { struct mserv_request_t {
/*! Connection handle. */ /*! Connection handle. */
int connfd; SOCKET connfd;
/*! . */ /*! . */
struct sockaddr_storage foreign_sockaddr; struct sockaddr_storage foreign_sockaddr;
}; };
@@ -92,7 +92,7 @@ typedef enum {
/*! . */ /*! . */
unsigned short miniStopSockPort; uint16_t miniStopSockPort;
/*! /*!
@@ -218,7 +218,7 @@ static void handle_request(
http_message_t *hmsg = NULL; http_message_t *hmsg = NULL;
int timeout = HTTP_DEFAULT_TIMEOUT; int timeout = HTTP_DEFAULT_TIMEOUT;
struct mserv_request_t *request = (struct mserv_request_t *)args; struct mserv_request_t *request = (struct mserv_request_t *)args;
int connfd = request->connfd; SOCKET connfd = request->connfd;
UpnpPrintf( UPNP_INFO, MSERV, __FILE__, __LINE__, UpnpPrintf( UPNP_INFO, MSERV, __FILE__, __LINE__,
"miniserver %d: READING\n", connfd ); "miniserver %d: READING\n", connfd );
@@ -269,7 +269,7 @@ error_handler:
*/ */
static UPNP_INLINE void schedule_request_job( static UPNP_INLINE void schedule_request_job(
/*! [in] Socket Descriptor on which connection is accepted. */ /*! [in] Socket Descriptor on which connection is accepted. */
int connfd, SOCKET connfd,
/*! [in] Clients Address information. */ /*! [in] Clients Address information. */
struct sockaddr *clientAddr) struct sockaddr *clientAddr)
{ {
@@ -301,26 +301,26 @@ static UPNP_INLINE void schedule_request_job(
} }
#endif #endif
static inline void fdset_if_valid(int sock, fd_set *set) static UPNP_INLINE void fdset_if_valid(SOCKET sock, fd_set *set)
{ {
if (sock != -1) { if (sock != INVALID_SOCKET) {
FD_SET(sock, set); FD_SET(sock, set);
} }
} }
static void web_server_accept(int lsock, fd_set *set) static void web_server_accept(SOCKET lsock, fd_set *set)
{ {
#ifdef INTERNAL_WEB_SERVER #ifdef INTERNAL_WEB_SERVER
int asock; SOCKET asock;
socklen_t clientLen; socklen_t clientLen;
struct sockaddr_storage clientAddr; struct sockaddr_storage clientAddr;
char errorBuffer[ERROR_BUFFER_LEN]; char errorBuffer[ERROR_BUFFER_LEN];
if (lsock != -1 && FD_ISSET(lsock, set)) { if (lsock != INVALID_SOCKET && FD_ISSET(lsock, set)) {
clientLen = sizeof(clientAddr); clientLen = sizeof(clientAddr);
asock = accept(lsock, (struct sockaddr *)&clientAddr, asock = accept(lsock, (struct sockaddr *)&clientAddr,
&clientLen); &clientLen);
if (asock == -1) { if (asock == INVALID_SOCKET) {
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
UpnpPrintf(UPNP_INFO, MSERV, __FILE__, __LINE__, UpnpPrintf(UPNP_INFO, MSERV, __FILE__, __LINE__,
"miniserver: Error in accept(): %s\n", "miniserver: Error in accept(): %s\n",
@@ -333,16 +333,16 @@ static void web_server_accept(int lsock, fd_set *set)
#endif /* INTERNAL_WEB_SERVER */ #endif /* INTERNAL_WEB_SERVER */
} }
static void ssdp_read(int rsock, fd_set *set) static void ssdp_read(SOCKET rsock, fd_set *set)
{ {
if (rsock != -1 && FD_ISSET(rsock, set)) { if (rsock != INVALID_SOCKET && FD_ISSET(rsock, set)) {
readFromSSDPSocket(rsock); readFromSSDPSocket(rsock);
} }
} }
static int receive_from_stopSock(int ssock, fd_set *set) static int receive_from_stopSock(SOCKET ssock, fd_set *set)
{ {
int byteReceived; ssize_t byteReceived;
socklen_t clientLen; socklen_t clientLen;
struct sockaddr_storage clientAddr; struct sockaddr_storage clientAddr;
char requestBuf[256]; char requestBuf[256];
@@ -387,9 +387,9 @@ static void RunMiniServer(
char errorBuffer[ERROR_BUFFER_LEN]; char errorBuffer[ERROR_BUFFER_LEN];
fd_set expSet; fd_set expSet;
fd_set rdSet; fd_set rdSet;
int maxMiniSock; SOCKET maxMiniSock;
int ret = 0; int ret = 0;
int stopSock = 0; SOCKET stopSock = 0;
maxMiniSock = 0; maxMiniSock = 0;
maxMiniSock = max(maxMiniSock, miniSock->miniServerSock4); maxMiniSock = max(maxMiniSock, miniSock->miniServerSock4);
@@ -417,11 +417,11 @@ static void RunMiniServer(
fdset_if_valid(miniSock->ssdpReqSock4, &rdSet); fdset_if_valid(miniSock->ssdpReqSock4, &rdSet);
fdset_if_valid(miniSock->ssdpReqSock6, &rdSet); fdset_if_valid(miniSock->ssdpReqSock6, &rdSet);
/* select() */ /* select() */
ret = select(maxMiniSock, &rdSet, NULL, &expSet, NULL); ret = select((int) maxMiniSock, &rdSet, NULL, &expSet, NULL);
if (ret == -1 && errno == EINTR) { if (ret == SOCKET_ERROR && errno == EINTR) {
continue; continue;
} }
if (ret == -1) { if (ret == SOCKET_ERROR) {
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
UpnpPrintf(UPNP_CRITICAL, SSDP, __FILE__, __LINE__, UpnpPrintf(UPNP_CRITICAL, SSDP, __FILE__, __LINE__,
"Error in select(): %s\n", errorBuffer); "Error in select(): %s\n", errorBuffer);
@@ -460,16 +460,17 @@ static void RunMiniServer(
/*! /*!
* \brief Returns port to which socket, sockfd, is bound. * \brief Returns port to which socket, sockfd, is bound.
* *
* \return -1 on error; check errno, otherwise > 0 means port number. * \return -1 on error; check errno. 0 if successfull.
*/ */
static int get_port( static int get_port(
/*! [in] Socket descriptor. */ /*! [in] Socket descriptor. */
int sockfd) SOCKET sockfd,
/*! [out] The port value if successful, otherwise, untouched. */
uint16_t *port)
{ {
struct sockaddr_storage sockinfo; struct sockaddr_storage sockinfo;
socklen_t len; socklen_t len;
int code; int code;
int port = 0;
len = sizeof(sockinfo); len = sizeof(sockinfo);
code = getsockname(sockfd, (struct sockaddr *)&sockinfo, &len); code = getsockname(sockfd, (struct sockaddr *)&sockinfo, &len);
@@ -477,14 +478,14 @@ static int get_port(
return -1; return -1;
} }
if (sockinfo.ss_family == AF_INET) { if (sockinfo.ss_family == AF_INET) {
port = ntohs(((struct sockaddr_in*)&sockinfo)->sin_port); *port = ntohs(((struct sockaddr_in*)&sockinfo)->sin_port);
} else if(sockinfo.ss_family == AF_INET6) { } else if(sockinfo.ss_family == AF_INET6) {
port = ntohs(((struct sockaddr_in6*)&sockinfo)->sin6_port); *port = ntohs(((struct sockaddr_in6*)&sockinfo)->sin6_port);
} }
UpnpPrintf(UPNP_INFO, MSERV, __FILE__, __LINE__, UpnpPrintf(UPNP_INFO, MSERV, __FILE__, __LINE__,
"sockfd = %d, .... port = %d\n", sockfd, port); "sockfd = %d, .... port = %u\n", sockfd, *port);
return port; return 0;
} }
@@ -509,10 +510,10 @@ static int get_miniserver_sockets(
MiniServerSockArray *out, MiniServerSockArray *out,
/*! [in] port on which the server is listening for incoming IPv4 /*! [in] port on which the server is listening for incoming IPv4
* connections. */ * connections. */
unsigned short listen_port4, uint16_t listen_port4,
/*! [in] port on which the server is listening for incoming IPv6 /*! [in] port on which the server is listening for incoming IPv6
* connections. */ * connections. */
unsigned short listen_port6) uint16_t listen_port6)
{ {
char errorBuffer[ERROR_BUFFER_LEN]; char errorBuffer[ERROR_BUFFER_LEN];
struct sockaddr_storage __ss_v4; struct sockaddr_storage __ss_v4;
@@ -533,12 +534,12 @@ static int get_miniserver_sockets(
/* Create listen socket for IPv4/IPv6. An error here may indicate /* Create listen socket for IPv4/IPv6. An error here may indicate
* that we don't have an IPv4/IPv6 stack. */ * that we don't have an IPv4/IPv6 stack. */
listenfd4 = socket(AF_INET, SOCK_STREAM, 0); listenfd4 = socket(AF_INET, SOCK_STREAM, 0);
if (listenfd4 == -1) { if (listenfd4 == INVALID_SOCKET) {
return UPNP_E_OUTOF_SOCKET; return UPNP_E_OUTOF_SOCKET;
} }
#ifdef UPNP_ENABLE_IPV6 #ifdef UPNP_ENABLE_IPV6
listenfd6 = socket(AF_INET6, SOCK_STREAM, 0); listenfd6 = socket(AF_INET6, SOCK_STREAM, 0);
if (listenfd6 == -1) { if (listenfd6 == INVALID_SOCKET) {
return UPNP_E_OUTOF_SOCKET; return UPNP_E_OUTOF_SOCKET;
} }
#endif #endif
@@ -572,11 +573,11 @@ static int get_miniserver_sockets(
* HOWEVER IT HAS BEEN SUGESTED FOR TCP SERVERS. */ * HOWEVER IT HAS BEEN SUGESTED FOR TCP SERVERS. */
UpnpPrintf(UPNP_INFO, MSERV, __FILE__, __LINE__, UpnpPrintf(UPNP_INFO, MSERV, __FILE__, __LINE__,
"get_miniserver_sockets: resuseaddr is set.\n"); "get_miniserver_sockets: resuseaddr is set.\n");
if (listenfd4 != -1) { if (listenfd4 != INVALID_SOCKET) {
sockError = setsockopt(listenfd4, SOL_SOCKET, sockError = setsockopt(listenfd4, SOL_SOCKET,
SO_REUSEADDR, SO_REUSEADDR,
(const char *)&reuseaddr_on, sizeof (int)); (const char *)&reuseaddr_on, sizeof (int));
if (sockError == -1) { if (sockError == SOCKET_ERROR) {
sock_close(listenfd4); sock_close(listenfd4);
#ifdef UPNP_ENABLE_IPV6 #ifdef UPNP_ENABLE_IPV6
sock_close(listenfd6); sock_close(listenfd6);
@@ -587,7 +588,7 @@ static int get_miniserver_sockets(
sockError = bind(listenfd4, sockError = bind(listenfd4,
(struct sockaddr *)&__ss_v4, (struct sockaddr *)&__ss_v4,
sizeof (__ss_v4)); sizeof (__ss_v4));
if (sockError == -1) { if (sockError == SOCKET_ERROR) {
strerror_r(errno, errorBuffer, strerror_r(errno, errorBuffer,
ERROR_BUFFER_LEN); ERROR_BUFFER_LEN);
UpnpPrintf(UPNP_INFO, MSERV, UpnpPrintf(UPNP_INFO, MSERV,
@@ -604,11 +605,11 @@ static int get_miniserver_sockets(
} }
} }
#ifdef UPNP_ENABLE_IPV6 #ifdef UPNP_ENABLE_IPV6
if (listenfd6 != -1) { if (listenfd6 != INVALID_SOCKET) {
sockError = setsockopt(listenfd6, SOL_SOCKET, sockError = setsockopt(listenfd6, SOL_SOCKET,
SO_REUSEADDR, SO_REUSEADDR,
(const char *)&reuseaddr_on, sizeof (int)); (const char *)&reuseaddr_on, sizeof (int));
if (sockError == -1) { if (sockError == SOCKET_ERROR) {
sock_close(listenfd4); sock_close(listenfd4);
sock_close(listenfd6); sock_close(listenfd6);
return UPNP_E_SOCKET_BIND; return UPNP_E_SOCKET_BIND;
@@ -617,7 +618,7 @@ static int get_miniserver_sockets(
sockError = bind(listenfd6, sockError = bind(listenfd6,
(struct sockaddr *)&__ss_v6, (struct sockaddr *)&__ss_v6,
sizeof (__ss_v6)); sizeof (__ss_v6));
if (sockError == -1) { if (sockError == SOCKET_ERROR) {
strerror_r(errno, errorBuffer, strerror_r(errno, errorBuffer,
ERROR_BUFFER_LEN); ERROR_BUFFER_LEN);
UpnpPrintf(UPNP_INFO, MSERV, UpnpPrintf(UPNP_INFO, MSERV,
@@ -633,14 +634,14 @@ static int get_miniserver_sockets(
} }
#endif /* IPv6 */ #endif /* IPv6 */
} else { } else {
if (listenfd4 != -1) { if (listenfd4 != INVALID_SOCKET) {
unsigned short orig_listen_port4 = listen_port4; unsigned short orig_listen_port4 = listen_port4;
do { do {
serverAddr4->sin_port = htons(listen_port4++); serverAddr4->sin_port = htons(listen_port4++);
sockError = bind(listenfd4, sockError = bind(listenfd4,
(struct sockaddr *)serverAddr4, (struct sockaddr *)serverAddr4,
sizeof(*serverAddr4)); sizeof(*serverAddr4));
if (sockError == -1) { if (sockError == SOCKET_ERROR) {
#ifdef WIN32 #ifdef WIN32
errCode = WSAGetLastError(); errCode = WSAGetLastError();
#else #else
@@ -654,7 +655,7 @@ static int get_miniserver_sockets(
} }
} while (errCode != 0 && } while (errCode != 0 &&
listen_port4 >= orig_listen_port4); listen_port4 >= orig_listen_port4);
if (sockError == -1) { if (sockError == SOCKET_ERROR) {
strerror_r(errno, errorBuffer, strerror_r(errno, errorBuffer,
ERROR_BUFFER_LEN); ERROR_BUFFER_LEN);
UpnpPrintf(UPNP_INFO, MSERV, UpnpPrintf(UPNP_INFO, MSERV,
@@ -671,14 +672,14 @@ static int get_miniserver_sockets(
} }
} }
#ifdef UPNP_ENABLE_IPV6 #ifdef UPNP_ENABLE_IPV6
if (listenfd6 != -1) { if (listenfd6 != INVALID_SOCKET) {
unsigned short orig_listen_port6 = listen_port6; unsigned short orig_listen_port6 = listen_port6;
do { do {
serverAddr6->sin6_port = htons(listen_port6++); serverAddr6->sin6_port = htons(listen_port6++);
sockError = bind(listenfd6, sockError = bind(listenfd6,
(struct sockaddr *)serverAddr6, (struct sockaddr *)serverAddr6,
sizeof(*serverAddr6)); sizeof(*serverAddr6));
if (sockError == -1) { if (sockError == SOCKET_ERROR) {
#ifdef WIN32 #ifdef WIN32
errCode = WSAGetLastError(); errCode = WSAGetLastError();
#else #else
@@ -692,7 +693,7 @@ static int get_miniserver_sockets(
} }
} while (errCode != 0 && } while (errCode != 0 &&
listen_port6 >= orig_listen_port6); listen_port6 >= orig_listen_port6);
if (sockError == -1) { if (sockError == SOCKET_ERROR) {
strerror_r(errno, errorBuffer, strerror_r(errno, errorBuffer,
ERROR_BUFFER_LEN); ERROR_BUFFER_LEN);
UpnpPrintf(UPNP_INFO, MSERV, UpnpPrintf(UPNP_INFO, MSERV,
@@ -710,9 +711,9 @@ static int get_miniserver_sockets(
} }
UpnpPrintf(UPNP_INFO, MSERV, __FILE__, __LINE__, UpnpPrintf(UPNP_INFO, MSERV, __FILE__, __LINE__,
"get_miniserver_sockets: bind successful\n"); "get_miniserver_sockets: bind successful\n");
if (listenfd4 != -1) { if (listenfd4 != INVALID_SOCKET) {
ret_code = listen(listenfd4, SOMAXCONN); ret_code = listen(listenfd4, SOMAXCONN);
if (ret_code == -1) { if (ret_code == SOCKET_ERROR) {
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
UpnpPrintf(UPNP_INFO, MSERV, __FILE__, __LINE__, UpnpPrintf(UPNP_INFO, MSERV, __FILE__, __LINE__,
"mserv start: Error in IPv4 listen(): %s\n", "mserv start: Error in IPv4 listen(): %s\n",
@@ -723,8 +724,8 @@ static int get_miniserver_sockets(
#endif #endif
return UPNP_E_LISTEN; return UPNP_E_LISTEN;
} }
actual_port4 = get_port(listenfd4); ret_code = get_port(listenfd4, &actual_port4);
if (actual_port4 <= 0) { if (ret_code < 0) {
sock_close(listenfd4); sock_close(listenfd4);
#ifdef UPNP_ENABLE_IPV6 #ifdef UPNP_ENABLE_IPV6
sock_close(listenfd6); sock_close(listenfd6);
@@ -734,9 +735,9 @@ static int get_miniserver_sockets(
out->miniServerPort4 = actual_port4; out->miniServerPort4 = actual_port4;
} }
#ifdef UPNP_ENABLE_IPV6 #ifdef UPNP_ENABLE_IPV6
if (listenfd6 != -1) { if (listenfd6 != INVALID_SOCKET) {
ret_code = listen(listenfd6, SOMAXCONN); ret_code = listen(listenfd6, SOMAXCONN);
if (ret_code == -1) { if (ret_code == SOCKET_ERROR) {
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
UpnpPrintf(UPNP_INFO, MSERV, __FILE__, __LINE__, UpnpPrintf(UPNP_INFO, MSERV, __FILE__, __LINE__,
"mserv start: Error in IPv6 listen(): %s\n", "mserv start: Error in IPv6 listen(): %s\n",
@@ -745,8 +746,8 @@ static int get_miniserver_sockets(
sock_close(listenfd6); sock_close(listenfd6);
return UPNP_E_LISTEN; return UPNP_E_LISTEN;
} }
actual_port6 = get_port(listenfd6); ret_code = get_port(listenfd6, &actual_port6);
if (actual_port6 <= 0) { if (ret_code <= 0) {
sock_close(listenfd4); sock_close(listenfd4);
sock_close(listenfd6); sock_close(listenfd6);
return UPNP_E_INTERNAL_ERROR; return UPNP_E_INTERNAL_ERROR;
@@ -779,11 +780,11 @@ static int get_miniserver_stopsock(
{ {
char errorBuffer[ERROR_BUFFER_LEN]; char errorBuffer[ERROR_BUFFER_LEN];
struct sockaddr_in stop_sockaddr; struct sockaddr_in stop_sockaddr;
int miniServerStopSock = 0; SOCKET miniServerStopSock = 0;
int ret = 0; int ret = 0;
miniServerStopSock = socket(AF_INET, SOCK_DGRAM, 0); miniServerStopSock = socket(AF_INET, SOCK_DGRAM, 0);
if (miniServerStopSock == -1) { if (miniServerStopSock == INVALID_SOCKET) {
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
UpnpPrintf(UPNP_CRITICAL, MSERV, __FILE__, __LINE__, UpnpPrintf(UPNP_CRITICAL, MSERV, __FILE__, __LINE__,
"Error in socket(): %s\n", errorBuffer); "Error in socket(): %s\n", errorBuffer);
@@ -795,15 +796,15 @@ static int get_miniserver_stopsock(
stop_sockaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); stop_sockaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
ret = bind(miniServerStopSock, (struct sockaddr *)&stop_sockaddr, ret = bind(miniServerStopSock, (struct sockaddr *)&stop_sockaddr,
sizeof(stop_sockaddr)); sizeof(stop_sockaddr));
if (ret == -1) { if (ret == SOCKET_ERROR) {
UpnpPrintf(UPNP_CRITICAL, UpnpPrintf(UPNP_CRITICAL,
MSERV, __FILE__, __LINE__, MSERV, __FILE__, __LINE__,
"Error in binding localhost!!!\n"); "Error in binding localhost!!!\n");
sock_close(miniServerStopSock); sock_close(miniServerStopSock);
return UPNP_E_SOCKET_BIND; return UPNP_E_SOCKET_BIND;
} }
miniStopSockPort = get_port( miniServerStopSock ); ret = get_port(miniServerStopSock, &miniStopSockPort);
if (miniStopSockPort <= 0) { if (ret < 0) {
sock_close(miniServerStopSock); sock_close(miniServerStopSock);
return UPNP_E_INTERNAL_ERROR; return UPNP_E_INTERNAL_ERROR;
} }
@@ -813,19 +814,19 @@ static int get_miniserver_stopsock(
return UPNP_E_SUCCESS; return UPNP_E_SUCCESS;
} }
static inline void InitMiniServerSockArray(MiniServerSockArray *miniSocket) static UPNP_INLINE void InitMiniServerSockArray(MiniServerSockArray *miniSocket)
{ {
miniSocket->miniServerSock4 = -1; miniSocket->miniServerSock4 = INVALID_SOCKET;
miniSocket->miniServerSock6 = -1; miniSocket->miniServerSock6 = INVALID_SOCKET;
miniSocket->miniServerStopSock = -1; miniSocket->miniServerStopSock = INVALID_SOCKET;
miniSocket->ssdpSock4 = -1; miniSocket->ssdpSock4 = INVALID_SOCKET;
miniSocket->ssdpSock6 = -1; miniSocket->ssdpSock6 = INVALID_SOCKET;
miniSocket->ssdpSock6UlaGua = -1; miniSocket->ssdpSock6UlaGua = INVALID_SOCKET;
miniSocket->stopPort = -1; miniSocket->stopPort = 0;
miniSocket->miniServerPort4 = -1; miniSocket->miniServerPort4 = 0;
miniSocket->miniServerPort6 = -1; miniSocket->miniServerPort6 = 0;
miniSocket->ssdpReqSock4 = -1; miniSocket->ssdpReqSock4 = INVALID_SOCKET;
miniSocket->ssdpReqSock6 = -1; miniSocket->ssdpReqSock6 = INVALID_SOCKET;
} }
int StartMiniServer( int StartMiniServer(
@@ -924,11 +925,11 @@ int StartMiniServer(
int StopMiniServer() int StopMiniServer()
{ {
char errorBuffer[ERROR_BUFFER_LEN]; char errorBuffer[ERROR_BUFFER_LEN];
int socklen = sizeof (struct sockaddr_in); socklen_t socklen = sizeof (struct sockaddr_in);
SOCKET sock; SOCKET sock;
struct sockaddr_in ssdpAddr; struct sockaddr_in ssdpAddr;
char buf[256] = "ShutDown"; char buf[256] = "ShutDown";
int bufLen = strlen(buf); size_t bufLen = strlen(buf);
if(gMServState == MSERV_RUNNING) { if(gMServState == MSERV_RUNNING) {
gMServState = MSERV_STOPPING; gMServState = MSERV_STOPPING;
@@ -936,7 +937,7 @@ int StopMiniServer()
return 0; return 0;
} }
sock = socket(AF_INET, SOCK_DGRAM, 0); sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock == -1) { if (sock == INVALID_SOCKET) {
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__, UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__,
"SSDP_SERVER: StopSSDPServer: Error in socket() %s\n", "SSDP_SERVER: StopSSDPServer: Error in socket() %s\n",
@@ -947,8 +948,8 @@ int StopMiniServer()
ssdpAddr.sin_family = AF_INET; ssdpAddr.sin_family = AF_INET;
ssdpAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); ssdpAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
ssdpAddr.sin_port = htons(miniStopSockPort); ssdpAddr.sin_port = htons(miniStopSockPort);
sendto(sock, buf, bufLen, 0, (struct sockaddr *)&ssdpAddr, sendto(sock, buf, bufLen, 0,
socklen); (struct sockaddr *)&ssdpAddr, socklen);
usleep(1000); usleep(1000);
if (gMServState == MSERV_IDLE) { if (gMServState == MSERV_IDLE) {
break; break;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,71 +1,60 @@
/////////////////////////////////////////////////////////////////////////// /*******************************************************************************
// *
// Copyright (c) 2000-2003 Intel Corporation * Copyright (c) 2000-2003 Intel Corporation
// All rights reserved. * All rights reserved.
// *
// Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
// *
// * Redistributions of source code must retain the above copyright notice, * - Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer. * this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice, * - Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation * this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution. * and/or other materials provided with the distribution.
// * Neither name of Intel Corporation nor the names of its contributors * - Neither name of Intel Corporation nor the names of its contributors
// may be used to endorse or promote products derived from this software * may be used to endorse or promote products derived from this software
// without specific prior written permission. * without specific prior written permission.
// *
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// *
/////////////////////////////////////////////////////////////////////////// ******************************************************************************/
/************************************************************************ /*!
* Purpose: This file a function to extract the header information from * * \file
* an http message and then matches the data with XML data. * *
************************************************************************/ * Purpose: This file a function to extract the header information from
* an http message and then matches the data with XML data.
*/
#include "config.h" #include "config.h"
#include <assert.h> #include <assert.h>
#include "util.h" #include "upnputil.h"
#include "membuffer.h" #include "membuffer.h"
#include "httpparser.h" #include "httpparser.h"
#include "statcodes.h" #include "statcodes.h"
#include "parsetools.h" #include "parsetools.h"
/************************************************************************ int has_xml_content_type(http_message_t *hmsg)
* Function: has_xml_content_type
*
* Parameters:
* IN http_message_t* hmsg ; HTTP Message object
*
* Description: Find the header from the HTTP message and match the
* header for xml data.
*
* Returns:
* BOOLEAN
************************************************************************/
xboolean
has_xml_content_type( IN http_message_t * hmsg )
{ {
memptr hdr_value; memptr hdr_value;
assert(hmsg); assert(hmsg);
// find 'content-type' header which must have text/xml /* find 'content-type' header which must have text/xml */
if( httpmsg_find_hdr( hmsg, HDR_CONTENT_TYPE, &hdr_value ) != NULL && if (httpmsg_find_hdr(hmsg, HDR_CONTENT_TYPE, &hdr_value) &&
matchstr( hdr_value.buf, hdr_value.length, matchstr(hdr_value.buf, hdr_value.length, "%itext%w/%wxml" ) == PARSE_OK) {
"%itext%w/%wxml" ) == PARSE_OK ) {
return TRUE; return TRUE;
} }
return FALSE; return FALSE;
} }

View File

@@ -1,33 +1,33 @@
/////////////////////////////////////////////////////////////////////////// /*******************************************************************************
// *
// Copyright (c) 2000-2003 Intel Corporation * Copyright (c) 2000-2003 Intel Corporation
// All rights reserved. * All rights reserved.
// *
// Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
// *
// * Redistributions of source code must retain the above copyright notice, * - Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer. * this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice, * - Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation * this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution. * and/or other materials provided with the distribution.
// * Neither name of Intel Corporation nor the names of its contributors * - Neither name of Intel Corporation nor the names of its contributors
// may be used to endorse or promote products derived from this software * may be used to endorse or promote products derived from this software
// without specific prior written permission. * without specific prior written permission.
// *
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// *
/////////////////////////////////////////////////////////////////////////// ******************************************************************************/
/************************************************************************ /************************************************************************
* Purpose: This file defines status codes, buffers to store the status * * Purpose: This file defines status codes, buffers to store the status *
@@ -37,7 +37,7 @@
#include "config.h" #include "config.h"
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "util.h" #include "upnputil.h"
#include "statcodes.h" #include "statcodes.h"
#ifdef WIN32 #ifdef WIN32
@@ -96,7 +96,7 @@ static const char *Http5xxStr =
"Service Unavailable\0" "Service Unavailable\0"
"Gateway Timeout\0" "HTTP Version Not Supported\0"; "Gateway Timeout\0" "HTTP Version Not Supported\0";
static xboolean gInitialized = FALSE; static int gInitialized = FALSE;
/************************************************************************ /************************************************************************
************************* Functions ************************************* ************************* Functions *************************************
@@ -128,7 +128,7 @@ init_table( IN const char *encoded_str,
for( i = 0; i < tbl_size; i++ ) { for( i = 0; i < tbl_size; i++ ) {
table[i] = s; table[i] = s;
s += strlen( s ) + 1; // next entry s += strlen( s ) + 1; /* next entry */
} }
} }
@@ -153,7 +153,7 @@ init_tables( void )
init_table( Http4xxStr, Http4xxCodes, NUM_4XX_CODES ); init_table( Http4xxStr, Http4xxCodes, NUM_4XX_CODES );
init_table( Http5xxStr, Http5xxCodes, NUM_5XX_CODES ); init_table( Http5xxStr, Http5xxCodes, NUM_5XX_CODES );
gInitialized = TRUE; // mark only after complete gInitialized = TRUE; /* mark only after complete */
} }
/************************************************************************ /************************************************************************

View File

@@ -51,7 +51,7 @@
#include "unixutil.h" #include "unixutil.h"
#include "upnp.h" #include "upnp.h"
#include "upnpapi.h" #include "upnpapi.h"
#include "util.h" #include "upnputil.h"
#include "VirtualDir.h" #include "VirtualDir.h"
#include <assert.h> #include <assert.h>
@@ -309,28 +309,25 @@ static UPNP_INLINE int get_content_type(
const char *extension; const char *extension;
const char *type; const char *type;
const char *subtype; const char *subtype;
xboolean ctype_found = FALSE; int ctype_found = FALSE;
char *temp = NULL; char *temp = NULL;
int length = 0; size_t length = 0;
(*content_type) = NULL; (*content_type) = NULL;
/* get ext */
// get ext
extension = strrchr(filename, '.'); extension = strrchr(filename, '.');
if (extension != NULL) { if (extension != NULL) {
if (search_extension(extension + 1, &type, &subtype) == 0) { if (search_extension(extension + 1, &type, &subtype) == 0) {
ctype_found = TRUE; ctype_found = TRUE;
} }
} }
if (!ctype_found) { if (!ctype_found) {
// unknown content type /* unknown content type */
type = gMediaTypes[APPLICATION_INDEX]; type = gMediaTypes[APPLICATION_INDEX];
subtype = "octet-stream"; subtype = "octet-stream";
} }
length = strlen(type) + strlen("/") + strlen(subtype) + 1; length = strlen(type) + strlen("/") + strlen(subtype) + 1;
temp = (char *)malloc(length); temp = malloc(length);
if (!temp) { if (!temp) {
return UPNP_E_OUTOF_MEMORY; return UPNP_E_OUTOF_MEMORY;
} }
@@ -341,7 +338,6 @@ static UPNP_INLINE int get_content_type(
if (!content_type) { if (!content_type) {
return UPNP_E_OUTOF_MEMORY; return UPNP_E_OUTOF_MEMORY;
} }
return 0; return 0;
} }
@@ -364,7 +360,7 @@ static UPNP_INLINE void glob_alias_init(void)
* *
* \return BOOLEAN. * \return BOOLEAN.
*/ */
static UPNP_INLINE xboolean is_valid_alias( static UPNP_INLINE int is_valid_alias(
/*! [in] XML alias object. */ /*! [in] XML alias object. */
const struct xml_alias_t *alias) const struct xml_alias_t *alias)
{ {
@@ -395,13 +391,13 @@ static void alias_release(
struct xml_alias_t *alias) struct xml_alias_t *alias)
{ {
ithread_mutex_lock(&gWebMutex); ithread_mutex_lock(&gWebMutex);
// ignore invalid alias /* ignore invalid alias */
if (!is_valid_alias(alias)) { if (!is_valid_alias(alias)) {
ithread_mutex_unlock(&gWebMutex); ithread_mutex_unlock(&gWebMutex);
return; return;
} }
assert(alias->ct > 0); assert(*alias->ct > 0);
*alias->ct = *alias->ct - 1; *alias->ct -= 1;
if (*alias->ct <= 0) { if (*alias->ct <= 0) {
membuffer_destroy(&alias->doc); membuffer_destroy(&alias->doc);
membuffer_destroy(&alias->name); membuffer_destroy(&alias->name);
@@ -419,7 +415,7 @@ int web_server_set_alias(const char *alias_name,
alias_release(&gAliasDoc); alias_release(&gAliasDoc);
if (alias_name == NULL) { if (alias_name == NULL) {
// don't serve aliased doc anymore /* don't serve aliased doc anymore */
return 0; return 0;
} }
assert(alias_content != NULL); assert(alias_content != NULL);
@@ -427,24 +423,24 @@ int web_server_set_alias(const char *alias_name,
membuffer_init(&alias.name); membuffer_init(&alias.name);
alias.ct = NULL; alias.ct = NULL;
do { do {
// insert leading /, if missing /* insert leading /, if missing */
if (*alias_name != '/') { if (*alias_name != '/') {
if (membuffer_assign_str(&alias.name, "/") != 0) { if (membuffer_assign_str(&alias.name, "/") != 0) {
break; // error; out of mem break; /* error; out of mem */
} }
} }
ret_code = membuffer_append_str(&alias.name, alias_name); ret_code = membuffer_append_str(&alias.name, alias_name);
if (ret_code != 0) { if (ret_code != 0) {
break; // error break; /* error */
} }
if ((alias.ct = (int *)malloc(sizeof(int))) == NULL) { if ((alias.ct = (int *)malloc(sizeof(int))) == NULL) {
break; // error break; /* error */
} }
*alias.ct = 1; *alias.ct = 1;
membuffer_attach(&alias.doc, (char *)alias_content, membuffer_attach(&alias.doc, (char *)alias_content,
alias_content_length); alias_content_length);
alias.last_modified = last_modified; alias.last_modified = last_modified;
// save in module var /* save in module var */
ithread_mutex_lock(&gWebMutex); ithread_mutex_lock(&gWebMutex);
gAliasDoc = alias; gAliasDoc = alias;
ithread_mutex_unlock(&gWebMutex); ithread_mutex_unlock(&gWebMutex);
@@ -452,8 +448,8 @@ int web_server_set_alias(const char *alias_name,
return 0; return 0;
} while (FALSE); } while (FALSE);
// error handler /* error handler */
// free temp alias /* free temp alias */
membuffer_destroy(&alias.name); membuffer_destroy(&alias.name);
membuffer_destroy(&alias.doc); membuffer_destroy(&alias.doc);
free(alias.ct); free(alias.ct);
@@ -464,13 +460,13 @@ int web_server_init()
{ {
int ret = 0; int ret = 0;
if (bWebServerState == WEB_SERVER_DISABLED) { if (bWebServerState == WEB_SERVER_DISABLED) {
// decode media list /* decode media list */
media_list_init(); media_list_init();
membuffer_init(&gDocumentRootDir); membuffer_init(&gDocumentRootDir);
glob_alias_init(); glob_alias_init();
pVirtualDirList = NULL; pVirtualDirList = NULL;
// Initialize callbacks /* Initialize callbacks */
virtualDirCallback.get_info = NULL; virtualDirCallback.get_info = NULL;
virtualDirCallback.open = NULL; virtualDirCallback.open = NULL;
virtualDirCallback.read = NULL; virtualDirCallback.read = NULL;
@@ -541,7 +537,7 @@ static int get_file_info(
return -1; return -1;
} }
// check readable /* check readable */
fp = fopen(filename, "r"); fp = fopen(filename, "r");
info->is_readable = (fp != NULL); info->is_readable = (fp != NULL);
if (fp) { if (fp) {
@@ -563,16 +559,16 @@ static int get_file_info(
int web_server_set_root_dir(const char *root_dir) int web_server_set_root_dir(const char *root_dir)
{ {
int index; size_t index;
int ret; int ret;
ret = membuffer_assign_str(&gDocumentRootDir, root_dir); ret = membuffer_assign_str(&gDocumentRootDir, root_dir);
if (ret != 0) { if (ret != 0) {
return ret; return ret;
} }
// remove trailing '/', if any /* remove trailing '/', if any */
if (gDocumentRootDir.length > 0) { if (gDocumentRootDir.length > 0) {
index = gDocumentRootDir.length - 1; // last char index = gDocumentRootDir.length - 1; /* last char */
if (gDocumentRootDir.buf[index] == '/') { if (gDocumentRootDir.buf[index] == '/') {
membuffer_delete(&gDocumentRootDir, index, 1); membuffer_delete(&gDocumentRootDir, index, 1);
} }
@@ -589,7 +585,7 @@ int web_server_set_root_dir(const char *root_dir)
* \li \c TRUE - On Success * \li \c TRUE - On Success
* \li \c FALSE if request is not an alias * \li \c FALSE if request is not an alias
*/ */
static UPNP_INLINE xboolean get_alias( static UPNP_INLINE int get_alias(
/*! [in] request file passed in to be compared with. */ /*! [in] request file passed in to be compared with. */
const char *request_file, const char *request_file,
/*! [out] xml alias object which has a file name stored. */ /*! [out] xml alias object which has a file name stored. */
@@ -600,8 +596,8 @@ static UPNP_INLINE xboolean get_alias(
{ {
int cmp = strcmp(alias->name.buf, request_file); int cmp = strcmp(alias->name.buf, request_file);
if (cmp == 0) { if (cmp == 0) {
// fill up info /* fill up info */
info->file_length = alias->doc.length; info->file_length = (off_t)alias->doc.length;
info->is_readable = TRUE; info->is_readable = TRUE;
info->is_directory = FALSE; info->is_directory = FALSE;
info->last_modified = alias->last_modified; info->last_modified = alias->last_modified;
@@ -614,32 +610,36 @@ static UPNP_INLINE xboolean get_alias(
* \brief Compares filePath with paths from the list of virtual directory * \brief Compares filePath with paths from the list of virtual directory
* lists. * lists.
* *
* \return BOOLEAN * \return BOOLEAN.
*/ */
static int isFileInVirtualDir( static int isFileInVirtualDir(
/*! [in] Directory path to be tested for virtual directory. */ /*! [in] Directory path to be tested for virtual directory. */
char *filePath) char *filePath)
{ {
virtualDirList *pCurVirtualDir; virtualDirList *pCurVirtualDir;
int webDirLen; size_t webDirLen;
pCurVirtualDir = pVirtualDirList; pCurVirtualDir = pVirtualDirList;
while (pCurVirtualDir != NULL) { while (pCurVirtualDir != NULL) {
webDirLen = strlen(pCurVirtualDir->dirName); webDirLen = strlen(pCurVirtualDir->dirName);
if (webDirLen) {
if (pCurVirtualDir->dirName[webDirLen - 1] == '/') { if (pCurVirtualDir->dirName[webDirLen - 1] == '/') {
if (strncmp(pCurVirtualDir->dirName, filePath, webDirLen) == 0) if (strncmp(pCurVirtualDir->dirName, filePath,
return TRUE; webDirLen) == 0)
return !0;
} else { } else {
if (strncmp(pCurVirtualDir->dirName, filePath, webDirLen) == 0 && if (strncmp(pCurVirtualDir->dirName, filePath,
webDirLen) == 0 &&
(filePath[webDirLen] == '/' || (filePath[webDirLen] == '/' ||
filePath[webDirLen] == '\0' || filePath[webDirLen] == '\0' ||
filePath[webDirLen] == '?')) filePath[webDirLen] == '?'))
return TRUE; return !0;
}
} }
pCurVirtualDir = pCurVirtualDir->next; pCurVirtualDir = pCurVirtualDir->next;
} }
return FALSE; return 0;
} }
/*! /*!
@@ -650,7 +650,7 @@ static void ToUpperCase(
char *s) char *s)
{ {
while (*s) { while (*s) {
*s = toupper(*s); *s = (char)toupper(*s);
++s; ++s;
} }
} }
@@ -664,13 +664,12 @@ static char *StrStr(
/*! Input string. */ /*! Input string. */
char *s1, char *s1,
/*! Input sub-string. */ /*! Input sub-string. */
char *s2) const char *s2)
{ {
char *Str1; char *Str1;
char *Str2; char *Str2;
char *Ptr; const char *Ptr;
char *ret = NULL; char *ret = NULL;
int Pos;
Str1 = strdup(s1); Str1 = strdup(s1);
if (!Str1) if (!Str1)
@@ -685,8 +684,7 @@ static char *StrStr(
if (!Ptr) { if (!Ptr) {
ret = NULL; ret = NULL;
} else { } else {
Pos = Ptr - Str1; ret = s1 + (Ptr - Str1);
ret = s1 + Pos;
} }
free(Str2); free(Str2);
@@ -705,9 +703,10 @@ static char *StrTok(
/*! String containing the token. */ /*! String containing the token. */
char **Src, char **Src,
/*! Set of delimiter characters. */ /*! Set of delimiter characters. */
char *Del) const char *Del)
{ {
char *TmpPtr, *RetPtr; char *TmpPtr;
char *RetPtr;
if (*Src != NULL) { if (*Src != NULL) {
RetPtr = *Src; RetPtr = *Src;
@@ -794,7 +793,8 @@ static int CreateHTTPRangeResponseHeader(
struct SendInstruction *Instr) struct SendInstruction *Instr)
{ {
off_t FirstByte, LastByte; off_t FirstByte, LastByte;
char *RangeInput, *Ptr; char *RangeInput;
char *Ptr;
Instr->IsRangeActive = 1; Instr->IsRangeActive = 1;
Instr->ReadSendSize = FileLength; Instr->ReadSendSize = FileLength;
@@ -896,7 +896,7 @@ static int CheckOtherHTTPHeaders(
{ {
http_header_t *header; http_header_t *header;
ListNode *node; ListNode *node;
//NNS: dlist_node* node; /*NNS: dlist_node* node; */
int index, RetCode = HTTP_OK; int index, RetCode = HTTP_OK;
char *TmpBuf; char *TmpBuf;
@@ -906,7 +906,7 @@ static int CheckOtherHTTPHeaders(
node = ListHead(&Req->headers); node = ListHead(&Req->headers);
while (node != NULL) { while (node != NULL) {
header = (http_header_t *) node->item; header = (http_header_t *) node->item;
// find header type. /* find header type. */
index = map_str_to_int((const char *)header->name.buf, index = map_str_to_int((const char *)header->name.buf,
header->name.length, Http_Header_Names, header->name.length, Http_Header_Names,
NUM_HTTP_HEADER_NAMES, FALSE); NUM_HTTP_HEADER_NAMES, FALSE);
@@ -955,23 +955,23 @@ static int CheckOtherHTTPHeaders(
header.value is the value. header.value is the value.
*/ */
/* /*
case HDR_CONTENT_TYPE: //return 1; case HDR_CONTENT_TYPE: return 1;
case HDR_CONTENT_LANGUAGE://return 1; case HDR_CONTENT_LANGUAGE:return 1;
case HDR_LOCATION: //return 1; case HDR_LOCATION: return 1;
case HDR_CONTENT_LOCATION://return 1; case HDR_CONTENT_LOCATION:return 1;
case HDR_ACCEPT: //return 1; case HDR_ACCEPT: return 1;
case HDR_ACCEPT_CHARSET://return 1; case HDR_ACCEPT_CHARSET: return 1;
case HDR_USER_AGENT: break;//return 1; case HDR_USER_AGENT: return 1;
*/ */
//Header check for encoding /*Header check for encoding */
/* /*
case HDR_ACCEPT_RANGE: //Server capability. case HDR_ACCEPT_RANGE:
case HDR_CONTENT_RANGE://Response. case HDR_CONTENT_RANGE:
case HDR_IF_RANGE: case HDR_IF_RANGE:
*/ */
//Header check for encoding /*Header check for encoding */
/* /*
case HDR_ACCEPT_ENCODING: case HDR_ACCEPT_ENCODING:
if(StrStr(TmpBuf, "identity")) if(StrStr(TmpBuf, "identity"))
@@ -980,7 +980,7 @@ static int CheckOtherHTTPHeaders(
} }
else return -1; else return -1;
case HDR_CONTENT_ENCODING: case HDR_CONTENT_ENCODING:
case HDR_TRANSFER_ENCODING: //Response case HDR_TRANSFER_ENCODING:
*/ */
break; break;
} }
@@ -1020,13 +1020,13 @@ static int process_request(
char *request_doc; char *request_doc;
struct File_Info finfo; struct File_Info finfo;
xboolean using_alias; int using_alias;
xboolean using_virtual_dir; int using_virtual_dir;
uri_type *url; uri_type *url;
char *temp_str; const char *temp_str;
int resp_major; int resp_major;
int resp_minor; int resp_minor;
xboolean alias_grabbed; int alias_grabbed;
size_t dummy; size_t dummy;
const char *extra_headers = NULL; const char *extra_headers = NULL;
@@ -1036,22 +1036,22 @@ static int process_request(
req->method == HTTPMETHOD_HEAD || req->method == HTTPMETHOD_HEAD ||
req->method == HTTPMETHOD_POST || req->method == HTTPMETHOD_POST ||
req->method == HTTPMETHOD_SIMPLEGET); req->method == HTTPMETHOD_SIMPLEGET);
// init /* init */
request_doc = NULL; request_doc = NULL;
finfo.content_type = NULL; finfo.content_type = NULL;
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;
using_alias = FALSE; using_alias = FALSE;
http_CalcResponseVersion(req->major_version, req->minor_version, http_CalcResponseVersion(req->major_version, req->minor_version,
&resp_major, &resp_minor); &resp_major, &resp_minor);
// /* */
// remove dots /* remove dots */
// /* */
request_doc = malloc(url->pathquery.size + 1); request_doc = malloc(url->pathquery.size + 1);
if (request_doc == NULL) { if (request_doc == NULL) {
goto error_handler; // out of mem goto error_handler; /* out of mem */
} }
memcpy(request_doc, url->pathquery.buff, url->pathquery.size); memcpy(request_doc, url->pathquery.buff, url->pathquery.size);
request_doc[url->pathquery.size] = '\0'; request_doc[url->pathquery.size] = '\0';
@@ -1063,7 +1063,7 @@ static int process_request(
goto error_handler; goto error_handler;
} }
if (*request_doc != '/') { if (*request_doc != '/') {
// no slash /* no slash */
err_code = HTTP_BAD_REQUEST; err_code = HTTP_BAD_REQUEST;
goto error_handler; goto error_handler;
} }
@@ -1078,7 +1078,6 @@ static int process_request(
if (is_valid_alias(&gAliasDoc)) { if (is_valid_alias(&gAliasDoc)) {
alias_grab(alias); alias_grab(alias);
alias_grabbed = TRUE; alias_grabbed = TRUE;
using_alias = get_alias(request_doc, alias, &finfo); using_alias = get_alias(request_doc, alias, &finfo);
if (using_alias == TRUE) { if (using_alias == TRUE) {
finfo.content_type = finfo.content_type =
@@ -1092,13 +1091,13 @@ static int process_request(
} }
if (using_virtual_dir) { if (using_virtual_dir) {
if (req->method != HTTPMETHOD_POST) { if (req->method != HTTPMETHOD_POST) {
// get file info /* get file info */
if (virtualDirCallback. if (virtualDirCallback.
get_info(filename->buf, &finfo) != 0) { get_info(filename->buf, &finfo) != 0) {
err_code = HTTP_NOT_FOUND; err_code = HTTP_NOT_FOUND;
goto error_handler; goto error_handler;
} }
// try index.html if req is a dir /* try index.html if req is a dir */
if (finfo.is_directory) { if (finfo.is_directory) {
if (filename->buf[filename->length - 1] == '/') { if (filename->buf[filename->length - 1] == '/') {
temp_str = "index.html"; temp_str = "index.html";
@@ -1109,7 +1108,7 @@ static int process_request(
0) { 0) {
goto error_handler; goto error_handler;
} }
// get info /* get info */
if ((virtualDirCallback. if ((virtualDirCallback.
get_info(filename->buf, get_info(filename->buf,
&finfo) != UPNP_E_SUCCESS) &finfo) != UPNP_E_SUCCESS)
@@ -1118,42 +1117,42 @@ static int process_request(
goto error_handler; goto error_handler;
} }
} }
// not readable /* not readable */
if (!finfo.is_readable) { if (!finfo.is_readable) {
err_code = HTTP_FORBIDDEN; err_code = HTTP_FORBIDDEN;
goto error_handler; goto error_handler;
} }
// finally, get content type /* finally, get content type */
// if ( get_content_type(filename->buf, &content_type) != 0 ) /* if ( get_content_type(filename->buf, &content_type) != 0 ) */
//{ /*{ */
// goto error_handler; /* goto error_handler; */
// } /* } */
} }
} else if (!using_alias) { } else if (!using_alias) {
if (gDocumentRootDir.length == 0) { if (gDocumentRootDir.length == 0) {
goto error_handler; goto error_handler;
} }
// /* */
// get file name /* get file name */
// /* */
// filename str /* filename str */
if (membuffer_assign_str(filename, gDocumentRootDir.buf) != 0 || if (membuffer_assign_str(filename, gDocumentRootDir.buf) != 0 ||
membuffer_append_str(filename, request_doc) != 0) { membuffer_append_str(filename, request_doc) != 0) {
goto error_handler; // out of mem goto error_handler; /* out of mem */
} }
// remove trailing slashes /* remove trailing slashes */
while (filename->length > 0 && while (filename->length > 0 &&
filename->buf[filename->length - 1] == '/') { filename->buf[filename->length - 1] == '/') {
membuffer_delete(filename, filename->length - 1, 1); membuffer_delete(filename, filename->length - 1, 1);
} }
if (req->method != HTTPMETHOD_POST) { if (req->method != HTTPMETHOD_POST) {
// get info on file /* get info on file */
if (get_file_info(filename->buf, &finfo) != 0) { if (get_file_info(filename->buf, &finfo) != 0) {
err_code = HTTP_NOT_FOUND; err_code = HTTP_NOT_FOUND;
goto error_handler; goto error_handler;
} }
// try index.html if req is a dir /* try index.html if req is a dir */
if (finfo.is_directory) { if (finfo.is_directory) {
if (filename->buf[filename->length - 1] == '/') { if (filename->buf[filename->length - 1] == '/') {
temp_str = "index.html"; temp_str = "index.html";
@@ -1164,27 +1163,27 @@ static int process_request(
0) { 0) {
goto error_handler; goto error_handler;
} }
// get info /* get info */
if (get_file_info(filename->buf, &finfo) != 0 || if (get_file_info(filename->buf, &finfo) != 0 ||
finfo.is_directory) { finfo.is_directory) {
err_code = HTTP_NOT_FOUND; err_code = HTTP_NOT_FOUND;
goto error_handler; goto error_handler;
} }
} }
// not readable /* not readable */
if (!finfo.is_readable) { if (!finfo.is_readable) {
err_code = HTTP_FORBIDDEN; err_code = HTTP_FORBIDDEN;
goto error_handler; goto error_handler;
} }
} }
// finally, get content type /* finally, get content type */
// if ( get_content_type(filename->buf, &content_type) != 0 ) /* if ( get_content_type(filename->buf, &content_type) != 0 ) */
// { /* { */
// goto error_handler; /* goto error_handler; */
// } /* } */
} }
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) {
@@ -1200,58 +1199,58 @@ static int process_request(
extra_headers = ""; extra_headers = "";
} }
if (RespInstr->IsRangeActive && RespInstr->IsChunkActive) { 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(headers, resp_major, resp_minor, if (http_MakeMessage(headers, resp_major, resp_minor,
"R" "T" "GKLD" "s" "tcS" "Xc" "sCc", "R" "T" "GKLD" "s" "tcS" "Xc" "sCc",
HTTP_PARTIAL_CONTENT, // status code HTTP_PARTIAL_CONTENT, /* status code */
finfo.content_type, // content type finfo.content_type, /* content type */
RespInstr, // range info RespInstr, /* range info */
RespInstr, // language info RespInstr, /* language info */
"LAST-MODIFIED: ", "LAST-MODIFIED: ",
&finfo.last_modified, &finfo.last_modified,
X_USER_AGENT, extra_headers) != 0) { X_USER_AGENT, extra_headers) != 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(headers, resp_major, resp_minor, if (http_MakeMessage(headers, resp_major, resp_minor,
"R" "N" "T" "GLD" "s" "tcS" "Xc" "sCc", "R" "N" "T" "GLD" "s" "tcS" "Xc" "sCc",
HTTP_PARTIAL_CONTENT, // status code HTTP_PARTIAL_CONTENT, /* status code */
RespInstr->ReadSendSize, // content length RespInstr->ReadSendSize, /* content length */
finfo.content_type, // content type finfo.content_type, /* content type */
RespInstr, // range info RespInstr, /* range info */
RespInstr, // language info RespInstr, /* language info */
"LAST-MODIFIED: ", "LAST-MODIFIED: ",
&finfo.last_modified, &finfo.last_modified,
X_USER_AGENT, extra_headers) != 0) { X_USER_AGENT, extra_headers) != 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(headers, resp_major, resp_minor, if (http_MakeMessage(headers, resp_major, resp_minor,
"RK" "TLD" "s" "tcS" "Xc" "sCc", "RK" "TLD" "s" "tcS" "Xc" "sCc",
HTTP_OK, // status code HTTP_OK, /* status code */
finfo.content_type, // content type finfo.content_type, /* content type */
RespInstr, // language info RespInstr, /* language info */
"LAST-MODIFIED: ", "LAST-MODIFIED: ",
&finfo.last_modified, &finfo.last_modified,
X_USER_AGENT, extra_headers) != 0) { X_USER_AGENT, extra_headers) != 0) {
goto error_handler; goto error_handler;
} }
} else { } else {
// !RespInstr->IsRangeActive && !RespInstr->IsChunkActive /* !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 */
if (http_MakeMessage(headers, resp_major, resp_minor, if (http_MakeMessage(headers, resp_major, resp_minor,
"R" "N" "TLD" "s" "tcS" "Xc" "sCc", "R" "N" "TLD" "s" "tcS" "Xc" "sCc",
HTTP_OK, // status code HTTP_OK, /* status code */
RespInstr->ReadSendSize, // content length RespInstr->ReadSendSize, /* content length */
finfo.content_type, // content type finfo.content_type, /* content type */
RespInstr, // language info RespInstr, /* language info */
"LAST-MODIFIED: ", "LAST-MODIFIED: ",
&finfo.last_modified, &finfo.last_modified,
X_USER_AGENT, X_USER_AGENT,
@@ -1259,13 +1258,13 @@ static int process_request(
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 */
if (http_MakeMessage(headers, resp_major, resp_minor, if (http_MakeMessage(headers, resp_major, resp_minor,
"R" "TLD" "s" "tcS" "b" "Xc" "sCc", "R" "TLD" "s" "tcS" "Xc" "sCc",
HTTP_OK, // status code HTTP_OK, /* status code */
finfo.content_type, // content type finfo.content_type, /* content type */
RespInstr, // language info RespInstr, /* language info */
"LAST-MODIFIED: ", "LAST-MODIFIED: ",
&finfo.last_modified, &finfo.last_modified,
X_USER_AGENT, X_USER_AGENT,
@@ -1277,16 +1276,16 @@ static int process_request(
if (req->method == HTTPMETHOD_HEAD) { if (req->method == HTTPMETHOD_HEAD) {
*rtype = RESP_HEADERS; *rtype = RESP_HEADERS;
} else if (using_alias) { } else if (using_alias) {
// GET xml /* GET xml */
*rtype = RESP_XMLDOC; *rtype = RESP_XMLDOC;
} else if (using_virtual_dir) { } else if (using_virtual_dir) {
*rtype = RESP_WEBDOC; *rtype = RESP_WEBDOC;
} else { } else {
// GET filename /* GET filename */
*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);
} }
@@ -1322,14 +1321,13 @@ static int http_RecvPostMessage(
* is a virtual file or not. */ * is a virtual file or not. */
struct SendInstruction *Instr) struct SendInstruction *Instr)
{ {
unsigned int Data_Buf_Size = 1024; size_t Data_Buf_Size = 1024;
char Buf[1024]; char Buf[1024];
int Timeout = 0; int Timeout = 0;
long Num_Write = 0;
FILE *Fp; FILE *Fp;
parse_status_t status = PARSE_OK; parse_status_t status = PARSE_OK;
xboolean ok_on_close = FALSE; int ok_on_close = FALSE;
unsigned int entity_offset = 0; size_t entity_offset = 0;
int num_read = 0; int num_read = 0;
int ret_code = 0; int ret_code = 0;
@@ -1346,37 +1344,37 @@ static int http_RecvPostMessage(
} }
parser->position = POS_ENTITY; parser->position = POS_ENTITY;
do { do {
// first parse what has already been gotten /* first parse what has already been gotten */
if (parser->position != POS_COMPLETE) { if (parser->position != POS_COMPLETE) {
status = parser_parse_entity(parser); status = parser_parse_entity(parser);
} }
if (status == PARSE_INCOMPLETE_ENTITY) { if (status == PARSE_INCOMPLETE_ENTITY) {
// read until close /* read until close */
ok_on_close = TRUE; ok_on_close = TRUE;
} else if ((status != PARSE_SUCCESS) } else if ((status != PARSE_SUCCESS)
&& (status != PARSE_CONTINUE_1) && (status != PARSE_CONTINUE_1)
&& (status != PARSE_INCOMPLETE)) { && (status != PARSE_INCOMPLETE)) {
// error /* error */
fclose(Fp); fclose(Fp);
return HTTP_BAD_REQUEST; return HTTP_BAD_REQUEST;
} }
// read more if necessary entity /* read more if necessary entity */
while (entity_offset + Data_Buf_Size > parser->msg.entity.length && while (entity_offset + Data_Buf_Size > parser->msg.entity.length &&
parser->position != POS_COMPLETE) { parser->position != POS_COMPLETE) {
num_read = sock_read(info, Buf, sizeof(Buf), &Timeout); num_read = sock_read(info, Buf, sizeof(Buf), &Timeout);
if (num_read > 0) { if (num_read > 0) {
// append data to buffer /* append data to buffer */
ret_code = membuffer_append(&parser->msg.msg, ret_code = membuffer_append(&parser->msg.msg,
Buf, num_read); Buf, (size_t)num_read);
if (ret_code != 0) { if (ret_code != 0) {
// set failure status /* set failure status */
parser->http_error_code = parser->http_error_code =
HTTP_INTERNAL_SERVER_ERROR; HTTP_INTERNAL_SERVER_ERROR;
return HTTP_INTERNAL_SERVER_ERROR; return HTTP_INTERNAL_SERVER_ERROR;
} }
status = parser_parse_entity(parser); status = parser_parse_entity(parser);
if (status == PARSE_INCOMPLETE_ENTITY) { if (status == PARSE_INCOMPLETE_ENTITY) {
// read until close /* read until close */
ok_on_close = TRUE; ok_on_close = TRUE;
} else if ((status != PARSE_SUCCESS) } else if ((status != PARSE_SUCCESS)
&& (status != PARSE_CONTINUE_1) && (status != PARSE_CONTINUE_1)
@@ -1391,7 +1389,7 @@ static int http_RecvPostMessage(
print_http_headers(&parser->msg); print_http_headers(&parser->msg);
parser->position = POS_COMPLETE; parser->position = POS_COMPLETE;
} else { } else {
// partial msg or response /* partial msg or response */
parser->http_error_code = HTTP_BAD_REQUEST; parser->http_error_code = HTTP_BAD_REQUEST;
return HTTP_BAD_REQUEST; return HTTP_BAD_REQUEST;
} }
@@ -1408,14 +1406,14 @@ static int http_RecvPostMessage(
Data_Buf_Size); Data_Buf_Size);
entity_offset += Data_Buf_Size; entity_offset += Data_Buf_Size;
if (Instr->IsVirtualFile) { if (Instr->IsVirtualFile) {
Num_Write = virtualDirCallback.write(Fp, Buf, Data_Buf_Size); int n = virtualDirCallback.write(Fp, Buf, Data_Buf_Size);
if (Num_Write < 0) { if (n < 0) {
virtualDirCallback.close(Fp); virtualDirCallback.close(Fp);
return HTTP_INTERNAL_SERVER_ERROR; return HTTP_INTERNAL_SERVER_ERROR;
} }
} else { } else {
Num_Write = fwrite(Buf, 1, Data_Buf_Size, Fp); size_t n = fwrite(Buf, 1, Data_Buf_Size, Fp);
if (Num_Write < 0) { if (n != Data_Buf_Size) {
fclose(Fp); fclose(Fp);
return HTTP_INTERNAL_SERVER_ERROR; return HTTP_INTERNAL_SERVER_ERROR;
} }
@@ -1428,27 +1426,6 @@ static int http_RecvPostMessage(
fclose(Fp); fclose(Fp);
} }
/*
while(TotalByteReceived < Instr->RecvWriteSize &&
(NumReceived = sock_read(info,Buf, Data_Buf_Size,&Timeout) ) > 0 )
{
TotalByteReceived = TotalByteReceived + NumReceived;
Num_Write = virtualDirCallback.write(Fp, Buf, NumReceived);
if (ferror(Fp))
{
virtualDirCallback.close(Fp);
return HTTP_INTERNAL_SERVER_ERROR;
}
}
if(TotalByteReceived < Instr->RecvWriteSize)
{
return HTTP_INTERNAL_SERVER_ERROR;
}
virtualDirCallback.close(Fp);
}
*/
return HTTP_OK; return HTTP_OK;
} }
@@ -1463,72 +1440,70 @@ void web_server_callback(http_parser_t *parser, INOUT http_message_t *req,
struct xml_alias_t xmldoc; struct xml_alias_t xmldoc;
struct SendInstruction RespInstr; struct SendInstruction RespInstr;
//Initialize instruction header. /*Initialize instruction header. */
RespInstr.IsVirtualFile = 0; RespInstr.IsVirtualFile = 0;
RespInstr.IsChunkActive = 0; RespInstr.IsChunkActive = 0;
RespInstr.IsRangeActive = 0; RespInstr.IsRangeActive = 0;
RespInstr.IsTrailers = 0; RespInstr.IsTrailers = 0;
memset(RespInstr.AcceptLanguageHeader, 0, memset(RespInstr.AcceptLanguageHeader, 0,
sizeof(RespInstr.AcceptLanguageHeader)); sizeof(RespInstr.AcceptLanguageHeader));
// init /* init */
membuffer_init(&headers); membuffer_init(&headers);
membuffer_init(&filename); membuffer_init(&filename);
//Process request should create the different kind of header depending on the /*Process request should create the different kind of header depending on the */
//the type of request. /*the type of request. */
ret = process_request(req, &rtype, &headers, &filename, &xmldoc, ret = process_request(req, &rtype, &headers, &filename, &xmldoc,
&RespInstr); &RespInstr);
if (ret != UPNP_E_SUCCESS) { if (ret != UPNP_E_SUCCESS) {
// send error code /* send error code */
http_SendStatusResponse(info, ret, req->major_version, http_SendStatusResponse(info, ret, req->major_version,
req->minor_version); req->minor_version);
} else { } else {
// send response /* send response */
switch (rtype) { switch (rtype) {
case RESP_FILEDOC: case RESP_FILEDOC:
// send file, I = further instruction to send data. http_SendMessage(info, &timeout, "Ibf",
http_SendMessage(info, &timeout, "Ibf", &RespInstr, &RespInstr,
headers.buf, headers.length, headers.buf, headers.length,
filename.buf); filename.buf);
break; break;
case RESP_XMLDOC: case RESP_XMLDOC:
// send xmldoc , I = further instruction to send data. http_SendMessage(info, &timeout, "Ibb",
http_SendMessage(info, &timeout, &RespInstr,
"Ibb", &RespInstr,
headers.buf, headers.length, headers.buf, headers.length,
xmldoc.doc.buf, xmldoc.doc.length); xmldoc.doc.buf, xmldoc.doc.length);
alias_release(&xmldoc); alias_release(&xmldoc);
break; break;
case RESP_WEBDOC: case RESP_WEBDOC:
//, I = further instruction to send data. /*http_SendVirtualDirDoc(info, &timeout, "Ibf",
/* &RespInstr,
http_SendVirtualDirDoc( info, &timeout, "Ibf",&RespInstr,
headers.buf, headers.length, headers.buf, headers.length,
filename.buf ); filename.buf);*/
*/ http_SendMessage(info, &timeout, "Ibf",
http_SendMessage(info, &timeout, &RespInstr,
"Ibf", &RespInstr,
headers.buf, headers.length, headers.buf, headers.length,
filename.buf); filename.buf);
break; break;
case RESP_HEADERS: case RESP_HEADERS:
// headers only /* headers only */
http_SendMessage(info, &timeout, http_SendMessage(info, &timeout, "b",
"b",
headers.buf, headers.length); headers.buf, headers.length);
break; break;
case RESP_POST: case RESP_POST:
// headers only /* headers only */
ret = http_RecvPostMessage(parser, info, filename.buf, ret = http_RecvPostMessage(parser, info, filename.buf,
&RespInstr); &RespInstr);
// Send response. /* Send response. */
http_MakeMessage(&headers, 1, 1, http_MakeMessage(&headers, 1, 1,
"RTLSXcCc", "RTLSXcCc",
ret, "text/html", X_USER_AGENT); ret, "text/html", X_USER_AGENT);
http_SendMessage(info, &timeout, "b", headers.buf, http_SendMessage(info, &timeout, "b",
headers.length); headers.buf, headers.length);
break; break;
default: default:
UpnpPrintf(UPNP_INFO, HTTP, __FILE__, __LINE__,
"webserver: Invalid response type received.\n");
assert(0); assert(0);
} }
} }

View File

@@ -107,53 +107,50 @@ static int sock_read_write(
/*! Buffer to get data to or send data from. */ /*! Buffer to get data to or send data from. */
OUT char *buffer, OUT char *buffer,
/*! Size of the buffer. */ /*! Size of the buffer. */
IN size_t bufsize, IN int bufsize,
/*! timeout value. */ /*! timeout value. */
IN int *timeoutSecs, IN int *timeoutSecs,
/*! Boolean value specifying read or write option. */ /*! Boolean value specifying read or write option. */
IN xboolean bRead) IN int bRead)
{ {
int retCode; int retCode;
fd_set readSet; fd_set readSet;
fd_set writeSet; fd_set writeSet;
struct timeval timeout; struct timeval timeout;
int numBytes; long numBytes;
time_t start_time = time(NULL); time_t start_time = time(NULL);
SOCKET sockfd = info->socket; SOCKET sockfd = info->socket;
long bytes_sent = 0, byte_left = 0, num_written; long bytes_sent = 0;
long byte_left = 0;
long num_written;
if (*timeoutSecs < 0) { if (*timeoutSecs < 0)
return UPNP_E_TIMEDOUT; return UPNP_E_TIMEDOUT;
}
FD_ZERO(&readSet); FD_ZERO(&readSet);
FD_ZERO(&writeSet); FD_ZERO(&writeSet);
if (bRead) { if (bRead)
FD_SET(sockfd, &readSet); FD_SET(sockfd, &readSet);
} else { else
FD_SET(sockfd, &writeSet); FD_SET(sockfd, &writeSet);
}
timeout.tv_sec = *timeoutSecs; timeout.tv_sec = *timeoutSecs;
timeout.tv_usec = 0; timeout.tv_usec = 0;
while (TRUE) { while (TRUE) {
if (*timeoutSecs == 0) { if (*timeoutSecs == 0)
retCode = select(sockfd + 1, &readSet, &writeSet, retCode = select(sockfd + 1, &readSet, &writeSet,
NULL, NULL); NULL, NULL);
} else { else
retCode = select(sockfd + 1, &readSet, &writeSet, retCode = select(sockfd + 1, &readSet, &writeSet,
NULL, &timeout); NULL, &timeout);
} if (retCode == 0)
if (retCode == 0) {
return UPNP_E_TIMEDOUT; return UPNP_E_TIMEDOUT;
}
if (retCode == -1) { if (retCode == -1) {
if (errno == EINTR) if (errno == EINTR)
continue; continue;
return UPNP_E_SOCKET_ERROR; return UPNP_E_SOCKET_ERROR;
} else { } else
/* read or write. */ /* read or write. */
break; break;
} }
}
#ifdef SO_NOSIGPIPE #ifdef SO_NOSIGPIPE
{ {
int old; int old;
@@ -164,21 +161,21 @@ static int sock_read_write(
#endif #endif
if (bRead) { if (bRead) {
/* read data. */ /* read data. */
numBytes = recv(sockfd, buffer, bufsize, MSG_NOSIGNAL); numBytes = (long)recv(sockfd, buffer, (size_t)bufsize, MSG_NOSIGNAL);
} else { } else {
byte_left = bufsize; byte_left = bufsize;
bytes_sent = 0; bytes_sent = 0;
while (byte_left > 0) { while (byte_left > 0) {
/* write data. */ /* write data. */
num_written = send(sockfd, num_written = send(sockfd,
buffer + bytes_sent, byte_left, buffer + bytes_sent, (size_t)byte_left,
MSG_DONTROUTE | MSG_NOSIGNAL); MSG_DONTROUTE | MSG_NOSIGNAL);
if (num_written == -1) { if (num_written == -1) {
#ifdef SO_NOSIGPIPE #ifdef SO_NOSIGPIPE
setsockopt(sockfd, SOL_SOCKET, setsockopt(sockfd, SOL_SOCKET,
SO_NOSIGPIPE, &old, olen); SO_NOSIGPIPE, &old, olen);
#endif #endif
return num_written; return (int)num_written;
} }
byte_left = byte_left - num_written; byte_left = byte_left - num_written;
bytes_sent += num_written; bytes_sent += num_written;
@@ -189,26 +186,24 @@ static int sock_read_write(
setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, &old, olen); setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, &old, olen);
} }
#endif #endif
if (numBytes < 0) { if (numBytes < 0)
return UPNP_E_SOCKET_ERROR; return UPNP_E_SOCKET_ERROR;
}
/* subtract time used for reading/writing. */ /* subtract time used for reading/writing. */
if (*timeoutSecs != 0) { if (*timeoutSecs != 0)
*timeoutSecs -= time(NULL) - start_time; *timeoutSecs -= (int)(time(NULL) - start_time);
return (int)numBytes;
} }
return numBytes; int sock_read(IN SOCKINFO *info, OUT char *buffer, IN int bufsize,
}
int sock_read(IN SOCKINFO *info, OUT char *buffer, IN size_t bufsize,
INOUT int *timeoutSecs) INOUT int *timeoutSecs)
{ {
return sock_read_write(info, buffer, bufsize, timeoutSecs, TRUE); return sock_read_write(info, buffer, bufsize, timeoutSecs, TRUE);
} }
int sock_write(IN SOCKINFO *info, IN char *buffer, IN size_t bufsize, int sock_write(IN SOCKINFO *info, IN const char *buffer, IN int bufsize,
INOUT int *timeoutSecs) INOUT int *timeoutSecs)
{ {
return sock_read_write(info, buffer, bufsize, timeoutSecs, FALSE); return sock_read_write(info, (char *)buffer, bufsize, timeoutSecs, FALSE);
} }

View File

@@ -128,13 +128,12 @@ int is_escaped(
} }
} }
int replace_escaped(char *in, size_t index, size_t *max)
int replace_escaped(char *in, int index, size_t *max)
{ {
int tempInt = 0; int tempInt = 0;
char tempChar = 0; char tempChar = 0;
int i = 0; size_t i = 0;
int j = 0; size_t j = 0;
if (in[index] == '%' && isxdigit(in[index + 1]) && isxdigit(in[index + 2])) { if (in[index] == '%' && isxdigit(in[index + 1]) && isxdigit(in[index + 2])) {
/* Note the "%2x", makes sure that we convert a maximum of two /* Note the "%2x", makes sure that we convert a maximum of two
@@ -142,7 +141,6 @@ int replace_escaped(char *in, int index, size_t *max)
if (sscanf(&in[index + 1], "%2x", &tempInt) != 1) { if (sscanf(&in[index + 1], "%2x", &tempInt) != 1) {
return 0; return 0;
} }
tempChar = (char)tempInt; tempChar = (char)tempInt;
for (i = index + 3, j = index; j < *max; i++, j++) { for (i = index + 3, j = index; j < *max; i++, j++) {
in[j] = tempChar; in[j] = tempChar;
@@ -166,15 +164,15 @@ int replace_escaped(char *in, int index, size_t *max)
* *
* \return * \return
*/ */
static int parse_uric( static size_t parse_uric(
/*! [in] String of characters. */ /*! [in] String of characters. */
const char *in, const char *in,
/*! [in] Maximum limit. */ /*! [in] Maximum limit. */
int max, size_t max,
/*! [out] Token object where the string of characters is copied. */ /*! [out] Token object where the string of characters is copied. */
token *out) token *out)
{ {
int i = 0; size_t i = 0;
while (i < max && while (i < max &&
(is_unreserved(in[i]) || (is_unreserved(in[i]) ||
@@ -211,28 +209,24 @@ static void copy_token(
int copy_URL_list(URL_list *in, URL_list *out) int copy_URL_list(URL_list *in, URL_list *out)
{ {
int len = strlen( in->URLs ) + 1; size_t len = strlen(in->URLs) + 1;
int i = 0; size_t i = 0;
out->URLs = NULL; out->URLs = NULL;
out->parsedURLs = NULL; out->parsedURLs = NULL;
out->size = 0; out->size = 0;
out->URLs = ( char * )malloc( len ); out->URLs = malloc(len);
out->parsedURLs = out->parsedURLs = malloc(sizeof(uri_type) * in->size);
( uri_type * ) malloc( sizeof( uri_type ) * in->size );
if( ( out->URLs == NULL ) || ( out->parsedURLs == NULL ) ) if ( !out->URLs || !out->parsedURLs)
return UPNP_E_OUTOF_MEMORY; return UPNP_E_OUTOF_MEMORY;
memcpy(out->URLs, in->URLs, len); memcpy(out->URLs, in->URLs, len);
for( i = 0; i < in->size; i++ ) { for( i = 0; i < in->size; i++ ) {
//copy the parsed uri /*copy the parsed uri */
out->parsedURLs[i].type = in->parsedURLs[i].type; out->parsedURLs[i].type = in->parsedURLs[i].type;
copy_token( &in->parsedURLs[i].scheme, in->URLs, copy_token( &in->parsedURLs[i].scheme, in->URLs,
&out->parsedURLs[i].scheme, out->URLs ); &out->parsedURLs[i].scheme, out->URLs );
out->parsedURLs[i].path_type = in->parsedURLs[i].path_type; out->parsedURLs[i].path_type = in->parsedURLs[i].path_type;
copy_token( &in->parsedURLs[i].pathquery, in->URLs, copy_token( &in->parsedURLs[i].pathquery, in->URLs,
&out->parsedURLs[i].pathquery, out->URLs ); &out->parsedURLs[i].pathquery, out->URLs );
@@ -241,7 +235,6 @@ int copy_URL_list(URL_list *in, URL_list *out)
copy_token( &in->parsedURLs[i].hostport.text, copy_token( &in->parsedURLs[i].hostport.text,
in->URLs, &out->parsedURLs[i].hostport.text, in->URLs, &out->parsedURLs[i].hostport.text,
out->URLs ); out->URLs );
memcpy( &out->parsedURLs[i].hostport.IPaddress, memcpy( &out->parsedURLs[i].hostport.IPaddress,
&in->parsedURLs[i].hostport.IPaddress, &in->parsedURLs[i].hostport.IPaddress,
sizeof(struct sockaddr_storage) ); sizeof(struct sockaddr_storage) );
@@ -278,54 +271,47 @@ void print_uri(uri_type *in)
#ifdef DEBUG #ifdef DEBUG
void print_token(token * in) void print_token(token * in)
{ {
int i = 0; size_t i = 0;
printf("Token Size : %" PRIzu "\n\'", in->size); printf("Token Size : %" PRIzu "\n\'", in->size);
for( i = 0; i < in->size; i++ ) { for (i = 0; i < in->size; i++)
putchar(in->buff[i]); putchar(in->buff[i]);
}
putchar('\''); putchar('\'');
putchar('\n'); putchar('\n');
} }
#endif /* DEBUG */ #endif /* DEBUG */
int token_string_casecmp(token *in1, char *in2) int token_string_casecmp(token *in1, const char *in2)
{ {
int in2_length = strlen(in2); size_t in2_length = strlen(in2);
if (in1->size != in2_length)
if (in1->size != in2_length) {
return 1; return 1;
} else { else
return strncasecmp(in1->buff, in2, in1->size); return strncasecmp(in1->buff, in2, in1->size);
} }
}
int token_string_cmp(token * in1, char *in2) int token_string_cmp(token * in1, char *in2)
{ {
int in2_length = strlen(in2); size_t in2_length = strlen(in2);
if (in1->size != in2_length)
if (in1->size != in2_length) {
return 1; return 1;
} else { else
return strncmp(in1->buff, in2, in1->size); return strncmp(in1->buff, in2, in1->size);
} }
}
int token_cmp(token *in1, token *in2) int token_cmp(token *in1, token *in2)
{ {
if (in1->size != in2->size) { if (in1->size != in2->size)
return 1; return 1;
} else { else
return memcmp(in1->buff, in2->buff, in1->size); return memcmp(in1->buff, in2->buff, in1->size);
} }
}
int parse_hostport( int parse_hostport(
const char *in, const char *in,
int max, size_t max,
hostport_type *out) hostport_type *out)
{ {
char workbuf[256]; char workbuf[256];
@@ -337,54 +323,48 @@ int parse_hostport(
char *last_dot = NULL; char *last_dot = NULL;
unsigned short int port; unsigned short int port;
int af = AF_UNSPEC; int af = AF_UNSPEC;
int hostport_size; size_t hostport_size;
int has_port = 0; int has_port = 0;
int ret; int ret;
memset(out, 0, sizeof(hostport_type)); memset(out, 0, sizeof(hostport_type));
/* Work on a copy of the input string. */
// Work on a copy of the input string.
strncpy(workbuf, in, sizeof(workbuf)); strncpy(workbuf, in, sizeof(workbuf));
c = workbuf; c = workbuf;
if (*c == '[') { if (*c == '[') {
// IPv6 addresses are enclosed in square brackets. /* IPv6 addresses are enclosed in square brackets. */
srvname = ++c; srvname = ++c;
while( *c != '\0' && *c != ']' ) { while (*c != '\0' && *c != ']')
c++; c++;
} if (*c == '\0')
if( *c == '\0' ) { /* did not find closing bracket. */
// did not find closing bracket.
return UPNP_E_INVALID_URL; return UPNP_E_INVALID_URL;
} /* NULL terminate the srvname and then increment c. */
// NULL terminate the srvname and then increment c. *c++ = '\0'; /* overwrite the ']' */
*c++ = '\0'; // overwrite the ']'
if (*c == ':') { if (*c == ':') {
has_port = 1; has_port = 1;
c++; c++;
} }
af = AF_INET6; af = AF_INET6;
} } else {
else { /* IPv4 address -OR- host name. */
// IPv4 address -OR- host name.
srvname = c; srvname = c;
while( (*c != ':') && (*c != '/') && ( (isalnum(*c)) || (*c == '.') || (*c == '-') ) ) { while (*c != ':' && *c != '/' &&
(isalnum(*c) || *c == '.' || *c == '-')) {
if (*c == '.') if (*c == '.')
last_dot = c; last_dot = c;
c++; c++;
} }
has_port = (*c == ':') ? 1 : 0; has_port = (*c == ':') ? 1 : 0;
// NULL terminate the srvname /* NULL terminate the srvname */
*c = '\0'; *c = '\0';
if (has_port == 1) if (has_port == 1)
c++; c++;
if (last_dot != NULL && isdigit(*(last_dot + 1)))
if( last_dot != NULL && isdigit(*(last_dot+1)) ) { /* Must be an IPv4 address. */
// Must be an IPv4 address.
af = AF_INET; af = AF_INET;
}
else { else {
// Must be a host name. /* Must be a host name. */
struct addrinfo hints, *res, *res0; struct addrinfo hints, *res, *res0;
memset(&hints, 0, sizeof(hints)); memset(&hints, 0, sizeof(hints));
@@ -396,78 +376,65 @@ int parse_hostport(
for (res = res0; res; res = res->ai_next) { for (res = res0; res; res = res->ai_next) {
if (res->ai_family == AF_INET || if (res->ai_family == AF_INET ||
res->ai_family == AF_INET6) { res->ai_family == AF_INET6) {
// Found a valid IPv4 or IPv6 address. /* Found a valid IPv4 or IPv6 address. */
memcpy( &out->IPaddress, res->ai_addr, memcpy(&out->IPaddress,
res->ai_addr,
res->ai_addrlen); res->ai_addrlen);
break; break;
} }
} }
freeaddrinfo(res0); freeaddrinfo(res0);
if (res == NULL)
if( res == NULL ) { /* Didn't find an AF_INET or AF_INET6 address. */
// Didn't find an AF_INET or AF_INET6 address. return UPNP_E_INVALID_URL;
} else
/* getaddrinfo failed. */
return UPNP_E_INVALID_URL; return UPNP_E_INVALID_URL;
} }
} }
else { /* Check if a port is specified. */
// getaddrinfo failed.
return UPNP_E_INVALID_URL;
}
}
}
// Check if a port is specified.
if (has_port == 1) { if (has_port == 1) {
// Port is specified. /* Port is specified. */
srvport = c; srvport = c;
while( *c != '\0' && isdigit(*c) ) { while (*c != '\0' && isdigit(*c))
c++; c++;
}
port = (unsigned short int)atoi(srvport); port = (unsigned short int)atoi(srvport);
if( port == 0 ) { if (port == 0)
// Bad port number. /* Bad port number. */
return UPNP_E_INVALID_URL; return UPNP_E_INVALID_URL;
} } else
} /* Port was not specified, use default port. */
else {
// Port was not specified, use default port.
port = 80; port = 80;
} /* The length of the host and port string can be calculated by */
/* subtracting pointers. */
// The length of the host and port string can be calculated by hostport_size = (size_t)(c - workbuf);
// subtracting pointers. /* Fill in the 'out' information. */
hostport_size = (int)(c - workbuf);
// Fill in the 'out' information.
if (af == AF_INET) { if (af == AF_INET) {
sai4->sin_family = AF_INET; sai4->sin_family = AF_INET;
sai4->sin_port = htons(port); sai4->sin_port = htons(port);
ret = inet_pton(AF_INET, srvname, &sai4->sin_addr); ret = inet_pton(AF_INET, srvname, &sai4->sin_addr);
} } else if (af == AF_INET6) {
else if( af == AF_INET6 ) {
sai6->sin6_family = AF_INET6; sai6->sin6_family = AF_INET6;
sai6->sin6_port = htons(port); sai6->sin6_port = htons(port);
sai6->sin6_scope_id = gIF_INDEX; sai6->sin6_scope_id = gIF_INDEX;
ret = inet_pton(AF_INET6, srvname, &sai6->sin6_addr); ret = inet_pton(AF_INET6, srvname, &sai6->sin6_addr);
} else { } else {
// IP address was set by the hostname (getaddrinfo). /* IP address was set by the hostname (getaddrinfo). */
// Override port: /* Override port: */
if (out->IPaddress.ss_family == AF_INET) if (out->IPaddress.ss_family == AF_INET)
sai4->sin_port = htons(port); sai4->sin_port = htons(port);
else else
sai6->sin6_port = htons(port); sai6->sin6_port = htons(port);
ret = 1; ret = 1;
} }
/* Check if address was converted successfully. */ /* Check if address was converted successfully. */
if (ret <= 0) { if (ret <= 0)
return UPNP_E_INVALID_URL; return UPNP_E_INVALID_URL;
}
out->text.size = hostport_size; out->text.size = hostport_size;
out->text.buff = in; out->text.buff = in;
return hostport_size; return (int)hostport_size;
max = max;
} }
/*! /*!
@@ -480,29 +447,27 @@ int parse_hostport(
* *
* \return * \return
*/ */
static int parse_scheme( static size_t parse_scheme(
/*! [in] String of characters representing a scheme. */ /*! [in] String of characters representing a scheme. */
const char *in, const char *in,
/*! [in] Maximum number of characters. */ /*! [in] Maximum number of characters. */
int max, size_t max,
/*! [out] Output parameter whose buffer is filled in with the scheme. */ /*! [out] Output parameter whose buffer is filled in with the scheme. */
token *out) token *out)
{ {
int i = 0; size_t i = 0;
out->size = 0; out->size = 0;
out->buff = NULL; out->buff = NULL;
if( ( max == 0 ) || ( !isalpha( in[0] ) ) ) if( ( max == 0 ) || ( !isalpha( in[0] ) ) )
return FALSE; return 0;
i++; i++;
while( ( i < max ) && ( in[i] != ':' ) ) { while( ( i < max ) && ( in[i] != ':' ) ) {
if( !( isalnum( in[i] ) || ( in[i] == '+' ) || ( in[i] == '-' ) if( !( isalnum( in[i] ) || ( in[i] == '+' ) || ( in[i] == '-' )
|| ( in[i] == '.' ) ) ) || ( in[i] == '.' ) ) )
return FALSE; return 0;
i++; i++;
} }
if( i < max ) { if( i < max ) {
@@ -511,18 +476,18 @@ static int parse_scheme(
return i; return i;
} }
return FALSE; return 0;
} }
int remove_escaped_chars(INOUT char *in, INOUT size_t *size) int remove_escaped_chars(INOUT char *in, INOUT size_t *size)
{ {
int i = 0; size_t i = 0;
for (i = 0; i < *size; i++) { for (i = 0; i < *size; i++) {
replace_escaped(in, i, size); replace_escaped(in, i, size);
} }
return UPNP_E_SUCCESS; return UPNP_E_SUCCESS;
} }
@@ -562,7 +527,7 @@ int remove_dots(char *in, size_t size)
copyTo = Segments[--lastSegment]; copyTo = Segments[--lastSegment];
} else { } else {
free( Segments ); free( Segments );
//TRACE("ERROR RESOLVING URL, ../ at ROOT"); /*TRACE("ERROR RESOLVING URL, ../ at ROOT"); */
return UPNP_E_INVALID_URL; return UPNP_E_INVALID_URL;
} }
continue; continue;
@@ -599,7 +564,7 @@ char *resolve_rel_url(char *base_url, char *rel_url)
uri_type rel; uri_type rel;
char temp_path = '/'; char temp_path = '/';
int i = 0; size_t i = 0;
char *finger = NULL; char *finger = NULL;
char *last_slash = NULL; char *last_slash = NULL;
@@ -665,7 +630,6 @@ char *resolve_rel_url(char *base_url, char *rel_url)
finger = out_finger; finger = out_finger;
last_slash = finger; last_slash = finger;
i = 0; i = 0;
while( ( i < base.pathquery.size ) && while( ( i < base.pathquery.size ) &&
( base.pathquery.buff[i] != '?' ) ) { ( base.pathquery.buff[i] != '?' ) ) {
( *finger ) = base.pathquery.buff[i]; ( *finger ) = base.pathquery.buff[i];
@@ -675,7 +639,6 @@ char *resolve_rel_url(char *base_url, char *rel_url)
finger++; finger++;
} }
i = 0;
strcpy( last_slash, rel_url ); strcpy( last_slash, rel_url );
if( remove_dots( out_finger, if( remove_dots( out_finger,
strlen( out_finger ) ) != strlen( out_finger ) ) !=
@@ -705,13 +668,14 @@ char *resolve_rel_url(char *base_url, char *rel_url)
} }
int parse_uri(const char *in, int max, uri_type *out) int parse_uri(const char *in, size_t max, uri_type *out)
{ {
int begin_path = 0; int begin_path = 0;
int begin_hostport = 0; size_t begin_hostport = 0;
int begin_fragment = 0; size_t begin_fragment = 0;
if( ( begin_hostport = parse_scheme( in, max, &out->scheme ) ) ) { begin_hostport = parse_scheme(in, max, &out->scheme);
if (begin_hostport) {
out->type = ABSOLUTE; out->type = ABSOLUTE;
out->path_type = OPAQUE_PART; out->path_type = OPAQUE_PART;
begin_hostport++; begin_hostport++;
@@ -719,32 +683,28 @@ int parse_uri(const char *in, int max, uri_type *out)
out->type = RELATIVE; out->type = RELATIVE;
out->path_type = REL_PATH; out->path_type = REL_PATH;
} }
if (begin_hostport + 1 < max &&
if( ( ( begin_hostport + 1 ) < max ) && ( in[begin_hostport] == '/' ) in[begin_hostport] == '/' &&
&& ( in[begin_hostport + 1] == '/' ) ) { in[begin_hostport + 1] == '/') {
begin_hostport += 2; begin_hostport += 2;
begin_path = parse_hostport(&in[begin_hostport],
if( ( begin_path = parse_hostport( &in[begin_hostport],
max - begin_hostport, max - begin_hostport,
&out->hostport ) ) >= 0 ) { &out->hostport);
begin_path += begin_hostport; if (begin_path >= 0) {
begin_path += (int)begin_hostport;
} else } else
return begin_path; return begin_path;
} else { } else {
memset(&out->hostport, 0, sizeof(out->hostport)); memset(&out->hostport, 0, sizeof(out->hostport));
begin_path = begin_hostport; begin_path = (int)begin_hostport;
} }
begin_fragment = parse_uric(&in[begin_path],
begin_fragment = max - (size_t)begin_path,
parse_uric( &in[begin_path], max - begin_path, &out->pathquery) + (size_t)begin_path;
&out->pathquery ) + begin_path; if (out->pathquery.size && out->pathquery.buff[0] == '/') {
if( ( out->pathquery.size ) && ( out->pathquery.buff[0] == '/' ) ) {
out->path_type = ABS_PATH; out->path_type = ABS_PATH;
} }
if (begin_fragment < max && in[begin_fragment] == '#') {
if( ( begin_fragment < max ) && ( in[begin_fragment] == '#' ) ) {
begin_fragment++; begin_fragment++;
parse_uric(&in[begin_fragment], max - begin_fragment, parse_uric(&in[begin_fragment], max - begin_fragment,
&out->fragment); &out->fragment);
@@ -752,11 +712,11 @@ int parse_uri(const char *in, int max, uri_type *out)
out->fragment.buff = NULL; out->fragment.buff = NULL;
out->fragment.size = 0; out->fragment.size = 0;
} }
return HTTP_SUCCESS; return HTTP_SUCCESS;
} }
int parse_uri_and_unescape(char *in, size_t max, uri_type *out)
int parse_uri_and_unescape(char *in, int max, uri_type *out)
{ {
int ret = parse_uri(in, max, out); int ret = parse_uri(in, max, out);

View File

@@ -52,7 +52,7 @@
* Description : Makes a copy of the subscription * Description : Makes a copy of the subscription
* *
* Return : int ; * Return : int ;
* HTTP_SUCCESS - On Sucess * HTTP_SUCCESS - On success
* *
* Note : * Note :
************************************************************************/ ************************************************************************/
@@ -135,7 +135,7 @@ subscription *GetSubscriptionSID(const Upnp_SID sid, service_info *service)
} }
} }
if( found ) { if( found ) {
//get the current_time /*get the current_time */
time( &current_time ); time( &current_time );
if( ( found->expireTime != 0 ) if( ( found->expireTime != 0 )
&& ( found->expireTime < current_time ) ) { && ( found->expireTime < current_time ) ) {
@@ -161,7 +161,7 @@ subscription *GetNextSubscription(service_info *service, subscription *current)
subscription *previous = NULL; subscription *previous = NULL;
int notDone = 1; int notDone = 1;
// get the current_time /* get the current_time */
time( &current_time ); time( &current_time );
while( ( notDone ) && ( current ) ) { while( ( notDone ) && ( current ) ) {
previous = current; previous = current;
@@ -195,7 +195,7 @@ subscription *GetFirstSubscription(service_info *service)
temp.next = service->subscriptionList; temp.next = service->subscriptionList;
next = GetNextSubscription(service, &temp); next = GetNextSubscription(service, &temp);
service->subscriptionList = temp.next; service->subscriptionList = temp.next;
// service->subscriptionList = next; /* service->subscriptionList = next; */
return next; return next;
} }
@@ -718,8 +718,8 @@ getSubElement( const char *element_name,
* *
* Note : * Note :
************************************************************************/ ************************************************************************/
service_info * service_info *getServiceList(
getServiceList( IXML_Node * node, IXML_Node *node,
service_info **end, service_info **end,
char *URLBase) char *URLBase)
{ {
@@ -737,43 +737,32 @@ getServiceList( IXML_Node * node,
service_info *current = NULL; service_info *current = NULL;
service_info *previous = NULL; service_info *previous = NULL;
IXML_NodeList *serviceNodeList = NULL; IXML_NodeList *serviceNodeList = NULL;
int NumOfServices = 0; long unsigned int NumOfServices = 0;
int i = 0; long unsigned int i = 0;
int fail = 0; int fail = 0;
if (getSubElement("UDN", node, &UDN) && if (getSubElement("UDN", node, &UDN) &&
getSubElement("serviceList", node, &serviceList)) { getSubElement("serviceList", node, &serviceList)) {
serviceNodeList = ixmlElement_getElementsByTagName(
serviceNodeList = ixmlElement_getElementsByTagName( ( IXML_Element (IXML_Element *)serviceList, "service");
* )
serviceList,
"service" );
if (serviceNodeList != NULL) { if (serviceNodeList != NULL) {
NumOfServices = ixmlNodeList_length(serviceNodeList); NumOfServices = ixmlNodeList_length(serviceNodeList);
for (i = 0; i < NumOfServices; i++) { for (i = 0; i < NumOfServices; i++) {
current_service = ixmlNodeList_item( serviceNodeList, i ); current_service =
ixmlNodeList_item(serviceNodeList, i);
fail = 0; fail = 0;
if (current) { if (current) {
current->next = current->next = malloc(sizeof(service_info));
( service_info * )
malloc( sizeof( service_info ) );
previous = current; previous = current;
current = current->next; current = current->next;
} else { } else {
head = head = malloc(sizeof(service_info));
( service_info * )
malloc( sizeof( service_info ) );
current = head; current = head;
} }
if (!current) { if (!current) {
freeServiceList(head); freeServiceList(head);
return NULL; return NULL;
} }
current->next = NULL; current->next = NULL;
current->controlURL = NULL; current->controlURL = NULL;
current->eventURL = NULL; current->eventURL = NULL;
@@ -783,99 +772,65 @@ getServiceList( IXML_Node * node,
current->active = 1; current->active = 1;
current->subscriptionList = NULL; current->subscriptionList = NULL;
current->TotalSubscriptions = 0; current->TotalSubscriptions = 0;
if (!(current->UDN = getElementValue(UDN))) if (!(current->UDN = getElementValue(UDN)))
fail = 1; fail = 1;
if (!getSubElement("serviceType", current_service, &serviceType) ||
if( ( !getSubElement( "serviceType", current_service, !(current->serviceType = getElementValue(serviceType)))
&serviceType ) ) ||
( !( current->serviceType =
getElementValue( serviceType ) ) ) )
fail = 1; fail = 1;
if (!getSubElement("serviceId", current_service, &serviceId) ||
if( ( !getSubElement( "serviceId", current_service, !(current->serviceId = getElementValue(serviceId)))
&serviceId ) ) ||
( !
( current->serviceId =
getElementValue( serviceId ) ) ) )
fail = 1; fail = 1;
if (!getSubElement("SCPDURL", current_service, &SCPDURL) ||
if( ( ! !(tempDOMString = getElementValue(SCPDURL)) ||
( getSubElement !(current->SCPDURL = resolve_rel_url(URLBase, tempDOMString)))
( "SCPDURL", current_service, &SCPDURL ) ) )
|| ( !( tempDOMString = getElementValue( SCPDURL ) ) )
||
( !
( current->SCPDURL =
resolve_rel_url( URLBase, tempDOMString ) ) ) )
fail = 1; fail = 1;
ixmlFreeDOMString(tempDOMString); ixmlFreeDOMString(tempDOMString);
tempDOMString = NULL; tempDOMString = NULL;
if (!(getSubElement("controlURL", current_service, &controlURL)) ||
if( ( ! !(tempDOMString = getElementValue(controlURL)) ||
( getSubElement !(current->controlURL = resolve_rel_url(URLBase, tempDOMString))) {
( "controlURL", current_service, &controlURL ) ) ) UpnpPrintf(UPNP_INFO, GENA, __FILE__,
|| __LINE__,
( !( tempDOMString = getElementValue( controlURL ) ) )
||
( !
( current->controlURL =
resolve_rel_url( URLBase, tempDOMString ) ) ) ) {
UpnpPrintf( UPNP_INFO, GENA, __FILE__, __LINE__,
"BAD OR MISSING CONTROL URL"); "BAD OR MISSING CONTROL URL");
UpnpPrintf( UPNP_INFO, GENA, __FILE__, __LINE__, UpnpPrintf(UPNP_INFO, GENA, __FILE__,
__LINE__,
"CONTROL URL SET TO NULL IN SERVICE INFO"); "CONTROL URL SET TO NULL IN SERVICE INFO");
current->controlURL = NULL; current->controlURL = NULL;
fail = 0; fail = 0;
} }
ixmlFreeDOMString(tempDOMString); ixmlFreeDOMString(tempDOMString);
tempDOMString = NULL; tempDOMString = NULL;
if (!getSubElement("eventSubURL", current_service, &eventURL) ||
if( ( ! !(tempDOMString = getElementValue(eventURL)) ||
( getSubElement !(current->eventURL = resolve_rel_url(URLBase, tempDOMString))) {
( "eventSubURL", current_service, &eventURL ) ) ) UpnpPrintf(UPNP_INFO, GENA, __FILE__,
|| ( !( tempDOMString = getElementValue( eventURL ) ) ) __LINE__,
||
( !
( current->eventURL =
resolve_rel_url( URLBase, tempDOMString ) ) ) ) {
UpnpPrintf( UPNP_INFO, GENA, __FILE__, __LINE__,
"BAD OR MISSING EVENT URL"); "BAD OR MISSING EVENT URL");
UpnpPrintf( UPNP_INFO, GENA, __FILE__, __LINE__, UpnpPrintf(UPNP_INFO, GENA, __FILE__,
__LINE__,
"EVENT URL SET TO NULL IN SERVICE INFO"); "EVENT URL SET TO NULL IN SERVICE INFO");
current->eventURL = NULL; current->eventURL = NULL;
fail = 0; fail = 0;
} }
ixmlFreeDOMString(tempDOMString); ixmlFreeDOMString(tempDOMString);
tempDOMString = NULL; tempDOMString = NULL;
if (fail) { if (fail) {
freeServiceList(current); freeServiceList(current);
if (previous) if (previous)
previous->next = NULL; previous->next = NULL;
else else
head = NULL; head = NULL;
current = previous; current = previous;
} }
} }
ixmlNodeList_free(serviceNodeList); ixmlNodeList_free(serviceNodeList);
} }
(*end) = current; (*end) = current;
return head; return head;
} else { } else {
(*end) = NULL; (*end) = NULL;
return NULL; return NULL;
} }
} }
/************************************************************************ /************************************************************************
@@ -905,28 +860,26 @@ getAllServiceList( IXML_Node * node,
IXML_NodeList *deviceList = NULL; IXML_NodeList *deviceList = NULL;
IXML_Node *currentDevice = NULL; IXML_Node *currentDevice = NULL;
int NumOfDevices = 0; long unsigned int NumOfDevices = 0;
int i = 0; long unsigned int i = 0;
(*out_end) = NULL; (*out_end) = NULL;
deviceList = deviceList = ixmlElement_getElementsByTagName(
ixmlElement_getElementsByTagName( ( IXML_Element * ) node, (IXML_Element *)node, "device");
"device" ); if (deviceList) {
if( deviceList != NULL ) {
NumOfDevices = ixmlNodeList_length(deviceList); NumOfDevices = ixmlNodeList_length(deviceList);
for (i = 0; i < NumOfDevices; i++) { for (i = 0; i < NumOfDevices; i++) {
currentDevice = ixmlNodeList_item(deviceList, i); currentDevice = ixmlNodeList_item(deviceList, i);
if (head) { if (head) {
end->next = end->next = getServiceList(currentDevice,
getServiceList( currentDevice, &next_end, URLBase ); &next_end, URLBase);
if (next_end) if (next_end)
end = next_end; end = next_end;
} else } else
head = getServiceList( currentDevice, &end, URLBase ); head = getServiceList(currentDevice, &end,
URLBase);
} }
ixmlNodeList_free(deviceList); ixmlNodeList_free(deviceList);
} }
@@ -963,8 +916,8 @@ removeServiceTable( IXML_Node * node,
service_info *current_service = NULL; service_info *current_service = NULL;
service_info *start_search = NULL; service_info *start_search = NULL;
service_info *prev_service = NULL; service_info *prev_service = NULL;
int NumOfDevices = 0; long unsigned int NumOfDevices = 0;
int i = 0; long unsigned int i = 0;
if( getSubElement( "root", node, &root ) ) { if( getSubElement( "root", node, &root ) ) {
current_service = in->serviceList; current_service = in->serviceList;
@@ -980,9 +933,9 @@ removeServiceTable( IXML_Node * node,
&& ( ( getSubElement( "UDN", node, &currentUDN ) ) && ( ( getSubElement( "UDN", node, &currentUDN ) )
&& ( UDN = getElementValue( currentUDN ) ) ) ) { && ( UDN = getElementValue( currentUDN ) ) ) ) {
current_service = start_search; current_service = start_search;
//Services are put in the service table in the order in which they appear in the /*Services are put in the service table in the order in which they appear in the */
//description document, therefore we go through the list only once to remove a particular /*description document, therefore we go through the list only once to remove a particular */
//root device /*root device */
while( ( current_service ) while( ( current_service )
&& ( strcmp( current_service->UDN, UDN ) ) ) { && ( strcmp( current_service->UDN, UDN ) ) ) {
current_service = current_service->next; current_service = current_service->next;
@@ -1108,4 +1061,5 @@ getServiceTable( IXML_Node * node,
return 0; return 0;
} }
#endif // INCLUDE_DEVICE_APIS #endif /* INCLUDE_DEVICE_APIS */

View File

@@ -70,7 +70,7 @@ str_alloc( IN const char *str,
s = ( char * )malloc( str_len + 1 ); s = ( char * )malloc( str_len + 1 );
if( s == NULL ) { if( s == NULL ) {
return NULL; // no mem return NULL; /* no mem */
} }
memcpy( s, str, str_len ); memcpy( s, str, str_len );
@@ -111,8 +111,8 @@ memptr_cmp( IN memptr * m,
cmp = strncmp( m->buf, s, m->length ); cmp = strncmp( m->buf, s, m->length );
if( cmp == 0 && m->length < strlen( s ) ) { if( cmp == 0 && m->length < strlen( s ) ) {
// both strings equal for 'm->length' chars /* both strings equal for 'm->length' chars */
// if m is shorter than s, then s is greater /* if m is shorter than s, then s is greater */
return -1; return -1;
} }
@@ -147,8 +147,8 @@ memptr_cmp_nocase( IN memptr * m,
cmp = strncasecmp( m->buf, s, m->length ); cmp = strncasecmp( m->buf, s, m->length );
if( cmp == 0 && m->length < strlen( s ) ) { if( cmp == 0 && m->length < strlen( s ) ) {
// both strings equal for 'm->length' chars /* both strings equal for 'm->length' chars */
// if m is shorter than s, then s is greater /* if m is shorter than s, then s is greater */
return -1; return -1;
} }
@@ -204,20 +204,20 @@ membuffer_set_size( INOUT membuffer * m,
size_t alloc_len; size_t alloc_len;
char *temp_buf; char *temp_buf;
if( new_length >= m->length ) // increase length if( new_length >= m->length ) /* increase length */
{ {
// need more mem? /* need more mem? */
if( new_length <= m->capacity ) { if( new_length <= m->capacity ) {
return 0; // have enough mem; done return 0; /* have enough mem; done */
} }
diff = new_length - m->length; diff = new_length - m->length;
alloc_len = MAXVAL( m->size_inc, diff ) + m->capacity; alloc_len = MAXVAL( m->size_inc, diff ) + m->capacity;
} else // decrease length } else /* decrease length */
{ {
assert( new_length <= m->length ); assert( new_length <= m->length );
// if diff is 0..m->size_inc, don't free /* if diff is 0..m->size_inc, don't free */
if( ( m->capacity - new_length ) <= m->size_inc ) { if( ( m->capacity - new_length ) <= m->size_inc ) {
return 0; return 0;
} }
@@ -227,21 +227,21 @@ membuffer_set_size( INOUT membuffer * m,
assert( alloc_len >= new_length ); assert( alloc_len >= new_length );
temp_buf = realloc( m->buf, alloc_len + 1 ); //LEAK_FIX_MK temp_buf = realloc( m->buf, alloc_len + 1 ); /*LEAK_FIX_MK */
//temp_buf = Realloc( m->buf,m->length, alloc_len + 1 );//LEAK_FIX_MK /*temp_buf = Realloc( m->buf,m->length, alloc_len + 1 );LEAK_FIX_MK */
if( temp_buf == NULL ) { if( temp_buf == NULL ) {
// try smaller size /* try smaller size */
alloc_len = new_length; alloc_len = new_length;
temp_buf = realloc( m->buf, alloc_len + 1 ); //LEAK_FIX_MK temp_buf = realloc( m->buf, alloc_len + 1 ); /*LEAK_FIX_MK */
//temp_buf = Realloc( m->buf,m->length, alloc_len + 1 );//LEAK_FIX_MK /*temp_buf = Realloc( m->buf,m->length, alloc_len + 1 );LEAK_FIX_MK */
if( temp_buf == NULL ) { if( temp_buf == NULL ) {
return UPNP_E_OUTOF_MEMORY; return UPNP_E_OUTOF_MEMORY;
} }
} }
// save /* save */
m->buf = temp_buf; m->buf = temp_buf;
m->capacity = alloc_len; m->capacity = alloc_len;
return 0; return 0;
@@ -311,8 +311,7 @@ membuffer_destroy( INOUT membuffer * m )
* *
* Note : * Note :
************************************************************************/ ************************************************************************/
int int membuffer_assign( INOUT membuffer * m,
membuffer_assign( INOUT membuffer * m,
IN const void *buf, IN const void *buf,
IN size_t buf_len ) IN size_t buf_len )
{ {
@@ -320,20 +319,19 @@ membuffer_assign( INOUT membuffer * m,
assert(m != NULL); assert(m != NULL);
// set value to null /* set value to null */
if (buf == NULL) { if (buf == NULL) {
membuffer_destroy(m); membuffer_destroy(m);
return 0; return 0;
} }
// alloc mem /* alloc mem */
return_code = membuffer_set_size(m, buf_len); return_code = membuffer_set_size(m, buf_len);
if( return_code != 0 ) { if (return_code != 0)
return return_code; return return_code;
} /* copy */
// copy
if (buf_len) { if (buf_len) {
memcpy(m->buf, buf, buf_len); memcpy(m->buf, buf, buf_len);
m->buf[buf_len] = 0; // null-terminate m->buf[buf_len] = 0; /* null-terminate */
} }
m->length = buf_len; m->length = buf_len;
@@ -411,110 +409,60 @@ membuffer_append_str( INOUT membuffer * m,
return membuffer_insert( m, c_str, strlen( c_str ), m->length ); return membuffer_insert( m, c_str, strlen( c_str ), m->length );
} }
/************************************************************************ int membuffer_insert(membuffer *m, const void *buf, size_t buf_len, size_t index)
* Function : membuffer_insert
*
* Parameters :
* INOUT membuffer* m ; buffer whose memory size is to be increased
* and appended.
* IN const void* buf ; source buffer whose contents will be
* copied
* IN size_t buf_len ; size of the source buffer
* int index ; index to determine the bounds while movinf the data
*
* Description : Allocates memory for the new data to be inserted. Does
* memory management by moving the data from the existing memory to
* the newly allocated memory and then appending the new data.
*
* Return : int ;
*
* Note :
************************************************************************/
int
membuffer_insert( INOUT membuffer * m,
IN const void *buf,
IN size_t buf_len,
int index )
{ {
int return_code; int return_code;
assert(m != NULL); assert(m != NULL);
if( index < 0 || index > ( int )m->length ) if (index > m->length)
return UPNP_E_OUTOF_BOUNDS; return UPNP_E_OUTOF_BOUNDS;
if (!buf || !buf_len) {
if( buf == NULL || buf_len == 0 ) {
return 0; return 0;
} }
// alloc mem /* alloc mem */
return_code = membuffer_set_size(m, m->length + buf_len); return_code = membuffer_set_size(m, m->length + buf_len);
if( return_code != 0 ) { if (return_code) {
return return_code; return return_code;
} }
// insert data /* insert data */
/* move data to right of insertion point */
// move data to right of insertion point
memmove(m->buf + index + buf_len, m->buf + index, m->length - index); memmove(m->buf + index + buf_len, m->buf + index, m->length - index);
memcpy(m->buf + index, buf, buf_len); memcpy(m->buf + index, buf, buf_len);
m->length += buf_len; m->length += buf_len;
m->buf[m->length] = 0; // null-terminate /* null-terminate */
m->buf[m->length] = 0;
return 0; return 0;
} }
/************************************************************************ void membuffer_delete(membuffer *m, size_t index, size_t num_bytes)
* Function : membuffer_delete
*
* Parameters :
* INOUT membuffer* m ; buffer whose memory size is to be decreased
* and copied to the odified location
* IN int index ; index to determine bounds while moving data
* IN size_t num_bytes ; number of bytes that the data needs to
* shrink by
*
* Description : Shrink the size of the buffer depending on the current
* size of the bufer and te input parameters. Move contents from the
* old buffer to the new sized buffer.
*
* Return : void ;
*
* Note :
************************************************************************/
void
membuffer_delete( INOUT membuffer * m,
IN int index,
IN size_t num_bytes )
{ {
int return_value; int return_value;
int new_length; size_t new_length;
size_t copy_len; size_t copy_len;
assert(m != NULL); assert(m != NULL);
if (!m) return; if (!m || !m->length)
if( m->length == 0 ) {
return; return;
} /* shrink count if it goes beyond buffer */
assert( index >= 0 && index < ( int )m->length );
// shrink count if it goes beyond buffer
if (index + num_bytes > m->length) { if (index + num_bytes > m->length) {
num_bytes = m->length - ( size_t ) index; num_bytes = m->length - index;
copy_len = 0; // every thing at and after index purged /* every thing at and after index purged */
copy_len = 0;
} else { } else {
// calc num bytes after deleted string /* calc num bytes after deleted string */
copy_len = m->length - (index + num_bytes); copy_len = m->length - (index + num_bytes);
} }
memmove(m->buf + index, m->buf + index + num_bytes, copy_len); memmove(m->buf + index, m->buf + index + num_bytes, copy_len);
new_length = m->length - num_bytes; new_length = m->length - num_bytes;
return_value = membuffer_set_size( m, new_length ); // trim buffer /* trim buffer */
assert( return_value == 0 ); // shrinking should always work return_value = membuffer_set_size(m, new_length);
/* shrinking should always work */
assert(return_value == 0);
// don't modify until buffer is set /* don't modify until buffer is set */
m->length = new_length; m->length = new_length;
m->buf[new_length] = 0; m->buf[new_length] = 0;
} }
@@ -543,7 +491,7 @@ membuffer_detach( INOUT membuffer * m )
buf = m->buf; buf = m->buf;
// free all /* free all */
membuffer_initialize( m ); membuffer_initialize( m );
return buf; return buf;

View File

@@ -1,33 +1,33 @@
/////////////////////////////////////////////////////////////////////////// /*******************************************************************************
// *
// Copyright (c) 2000-2003 Intel Corporation * Copyright (c) 2000-2003 Intel Corporation
// All rights reserved. * All rights reserved.
// *
// Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
// *
// * Redistributions of source code must retain the above copyright notice, * - Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer. * this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice, * - Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation * this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution. * and/or other materials provided with the distribution.
// * Neither name of Intel Corporation nor the names of its contributors * - Neither name of Intel Corporation nor the names of its contributors
// may be used to endorse or promote products derived from this software * may be used to endorse or promote products derived from this software
// without specific prior written permission. * without specific prior written permission.
// *
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// *
/////////////////////////////////////////////////////////////////////////// ******************************************************************************/
/************************************************************************ /************************************************************************
* Purpose: This file contains string to integer and integer to string * Purpose: This file contains string to integer and integer to string
@@ -48,7 +48,7 @@
* matched. * matched.
* IN int num_entries ; number of entries in the table that need * IN int num_entries ; number of entries in the table that need
* to be searched. * to be searched.
* IN xboolean case_sensitive ; whether the case should be case * IN int case_sensitive ; whether the case should be case
* sensitive or not * sensitive or not
* *
* Description : Match the given name with names from the entries in the * Description : Match the given name with names from the entries in the
@@ -65,7 +65,7 @@ map_str_to_int( IN const char *name,
IN size_t name_len, IN size_t name_len,
IN str_int_entry * table, IN str_int_entry * table,
IN int num_entries, IN int num_entries,
IN xboolean case_sensitive ) IN int case_sensitive )
{ {
int top, int top,
mid, mid,
@@ -82,24 +82,24 @@ map_str_to_int( IN const char *name,
while( top <= bot ) { while( top <= bot ) {
mid = ( top + bot ) / 2; mid = ( top + bot ) / 2;
if( case_sensitive ) { if( case_sensitive ) {
//cmp = strcmp( name, table[mid].name ); /*cmp = strcmp( name, table[mid].name ); */
cmp = memptr_cmp( &name_ptr, table[mid].name ); cmp = memptr_cmp( &name_ptr, table[mid].name );
} else { } else {
//cmp = strcasecmp( name, table[mid].name ); /*cmp = strcasecmp( name, table[mid].name ); */
cmp = memptr_cmp_nocase( &name_ptr, table[mid].name ); cmp = memptr_cmp_nocase( &name_ptr, table[mid].name );
} }
if( cmp > 0 ) { if( cmp > 0 ) {
top = mid + 1; // look below mid top = mid + 1; /* look below mid */
} else if( cmp < 0 ) { } else if( cmp < 0 ) {
bot = mid - 1; // look above mid bot = mid - 1; /* look above mid */
} else // cmp == 0 } else /* cmp == 0 */
{ {
return mid; // match; return table index return mid; /* match; return table index */
} }
} }
return -1; // header name not found return -1; /* header name not found */
} }
/************************************************************************ /************************************************************************

View File

@@ -29,90 +29,39 @@
* *
******************************************************************************/ ******************************************************************************/
/************************************************************************ /*!
* \file
*
* Purpose: This file contains functions for copying strings based on * Purpose: This file contains functions for copying strings based on
* different options. * different options.
************************************************************************/ */
#include "config.h" #include "config.h"
#include "upnp.h" #include "upnp.h"
#include "util.h" #include "upnputil.h"
#include <string.h> #include <string.h>
void linecopy(char dest[LINE_SIZE], const char *src)
/************************************************************************
* Function : linecopy
*
* Parameters :
* OUT char dest[LINE_SIZE] ; output buffer
* IN const char* src ; input buffer
*
* Description : Copy no of bytes spcified by the LINE_SIZE constant,
* from the source buffer. Null terminate the destination buffer
*
* Return : void ;
*
* Note :
************************************************************************/
void
linecopy( OUT char dest[LINE_SIZE],
IN const char *src )
{ {
strncpy(dest, src, LINE_SIZE - 1); strncpy(dest, src, LINE_SIZE - 1);
dest[LINE_SIZE - 1] = '\0'; // null-terminate if len(src) >= LINE_SIZE /* null-terminate if len(src) >= LINE_SIZE. */
dest[LINE_SIZE - 1] = '\0';
} }
/************************************************************************ void namecopy(char dest[NAME_SIZE], const char *src)
* Function : namecopy
*
* Parameters :
* OUT char dest[NAME_SIZE] ; output buffer
* IN const char* src ; input buffer
*
* Description : Copy no of bytes spcified by the NAME_SIZE constant,
* from the source buffer. Null terminate the destination buffer
*
* Return : void ;
*
* Note :
************************************************************************/
void
namecopy( OUT char dest[NAME_SIZE],
IN const char *src )
{ {
strncpy(dest, src, NAME_SIZE - 1); strncpy(dest, src, NAME_SIZE - 1);
dest[NAME_SIZE - 1] = '\0'; // null-terminate if len(src) >= NAME_SIZE /* null-terminate if len(src) >= NAME_SIZE. */
dest[NAME_SIZE - 1] = '\0';
} }
/************************************************************************ void linecopylen(char dest[LINE_SIZE], const char *src, size_t srclen)
* Function : linecopylen
*
* Parameters :
* OUT char dest[LINE_SIZE] ; output buffer
* IN const char* src ; input buffer
* IN size_t srclen ; bytes to be copied.
*
* Description : Determine if the srclen passed in paramter is less than
* the permitted LINE_SIZE. If it is use the passed parameter, if not
* use the permitted LINE_SIZE as the length parameter
* Copy no of bytes spcified by the LINE_SIZE constant,
* from the source buffer. Null terminate the destination buffer
*
* Return : void ;
*
* Note :
************************************************************************/
void
linecopylen( OUT char dest[LINE_SIZE],
IN const char *src,
IN size_t srclen )
{ {
int len; size_t len;
len = srclen < (LINE_SIZE - 1) ? srclen : (LINE_SIZE - 1); len = srclen < (LINE_SIZE - 1) ? srclen : (LINE_SIZE - 1);
strncpy(dest, src, len); strncpy(dest, src, len);
dest[len] = '\0'; dest[len] = '\0';
} }

View File

@@ -294,6 +294,50 @@
/* @} */ /* @} */
/*!
* \name GENA_NOTIFICATION_SENDING_TIMEOUT
*
* The {\tt GENA_NOTIFICATION_SENDING_TIMEOUT} specifies the number of seconds
* to wait for sending GENA notifications to the Control Point.
*
* This timeout will be used to know how many seconds GENA notification threads
* will wait to write on the socket to send the notification. By putting a
* lower value than HTTP_DEFAULT_TIMEOUT, the thread will not wait too long and
* will return quickly if writing is impossible. This is very useful as some
* Control Points disconnect from the network without unsubscribing as a result
* if HTTP_DEFAULT_TIMEOUT is used, all the GENA threads will be blocked to send
* notifications to those disconnected Control Points until the subscription
* expires.
*
* @{
*/
#define GENA_NOTIFICATION_SENDING_TIMEOUT HTTP_DEFAULT_TIMEOUT
/* @} */
/*!
* \name GENA_NOTIFICATION_ANSWERING_TIMEOUT
*
* The {\tt GENA_NOTIFICATION_ANSWERING_TIMEOUT} specifies the number of seconds
* to wait for receiving the answer to a GENA notification from the Control
* Point.
*
* This timeout will be used to know how many seconds GENA notification threads
* will wait on the socket to read for an answer from the CP. By putting a
* lower value than HTTP_DEFAULT_TIMEOUT, the thread will not wait too long and
* will return quickly if there is no answer from the CP. This is very useful as
* some Control Points disconnect from the network without unsubscribing and if
* HTTP_DEFAULT_TIMEOUT is used, all the GENA threads will be blocked to wait
* for an answer from those disconnected Control Points until the subscription
* expires. However, it should be noted that UDA specifies a value of 30s for
* waiting the CP's answer.
*
* @{
*/
#define GENA_NOTIFICATION_ANSWERING_TIMEOUT HTTP_DEFAULT_TIMEOUT
/* @} */
/*! /*!
* \name Module Exclusion * \name Module Exclusion
* *

View File

@@ -29,11 +29,9 @@
* *
**************************************************************************/ **************************************************************************/
#ifndef GLOBAL_H #ifndef GLOBAL_H
#define GLOBAL_H #define GLOBAL_H
/* GLOBAL.H - RSAREF types and constants */ /* GLOBAL.H - RSAREF types and constants */
/* PROTOTYPES should be set to one if and only if the compiler supports /* PROTOTYPES should be set to one if and only if the compiler supports
function argument prototyping. function argument prototyping.
@@ -42,7 +40,6 @@
been defined with C compiler flags. been defined with C compiler flags.
*/ */
#ifndef PROTOTYPES #ifndef PROTOTYPES
#define PROTOTYPES 1 #define PROTOTYPES 1
#endif #endif

View File

@@ -29,49 +29,45 @@
* *
******************************************************************************/ ******************************************************************************/
#ifndef GENLIB_NET_HTTP_HTTPPARSER_H #ifndef GENLIB_NET_HTTP_HTTPPARSER_H
#define GENLIB_NET_HTTP_HTTPPARSER_H #define GENLIB_NET_HTTP_HTTPPARSER_H
/*! /*!
* \file * \file
*/ */
#include "LinkedList.h" #include "LinkedList.h"
#include "membuffer.h" #include "membuffer.h"
#include "uri.h" #include "uri.h"
#include "util.h" #include "upnputil.h"
/* private types */
////// private types //////////// /* scanner */
/* Used to represent different types of tokens in input. */
////////////////////// typedef enum
// scanner
///////////////////////
// Used to represent different types of tokens in input
typedef enum // token_type_t
{ {
TT_IDENTIFIER, TT_IDENTIFIER,
TT_WHITESPACE, TT_WHITESPACE,
TT_CRLF, TT_CRLF,
TT_CTRL, // needed ?? TT_CTRL,
TT_SEPARATOR, // ?? TT_SEPARATOR,
TT_QUOTEDSTRING, // ?? TT_QUOTEDSTRING,
} token_type_t; } token_type_t;
typedef struct // scanner_t typedef struct
{ {
membuffer* msg; // raw http msg /*! raw http msg. */
size_t cursor; // current position in buffer membuffer* msg;
xboolean entire_msg_loaded; // set this to TRUE if the entire msg is loaded in /*! current position in buffer. */
// in 'msg'; else FALSE if only partial msg in 'msg' size_t cursor;
// (default is FALSE) /*! set this to TRUE if the entire msg is loaded in 'msg';
* else FALSE if only partial msg in 'msg' (default is FALSE). */
int entire_msg_loaded;
} scanner_t; } scanner_t;
typedef enum // parser_pos_t typedef enum
{ {
POS_REQUEST_LINE, POS_REQUEST_LINE,
POS_RESPONSE_LINE, POS_RESPONSE_LINE,
@@ -80,7 +76,6 @@ typedef enum // parser_pos_t
POS_COMPLETE, POS_COMPLETE,
} parser_pos_t; } parser_pos_t;
#define ENTREAD_DETERMINE_READ_METHOD 1 #define ENTREAD_DETERMINE_READ_METHOD 1
#define ENTREAD_USING_CLEN 2 #define ENTREAD_USING_CLEN 2
#define ENTREAD_USING_CHUNKED 3 #define ENTREAD_USING_CHUNKED 3
@@ -88,13 +83,10 @@ typedef enum // parser_pos_t
#define ENTREAD_CHUNKY_BODY 5 #define ENTREAD_CHUNKY_BODY 5
#define ENTREAD_CHUNKY_HEADERS 6 #define ENTREAD_CHUNKY_HEADERS 6
/* end of private section. */
// end of private section /* method in a HTTP request. */
////////////////// typedef enum
// ##################################################################################
// method in a HTTP request
typedef enum // http_method_t
{ {
HTTPMETHOD_POST, HTTPMETHOD_POST,
HTTPMETHOD_MPOST, HTTPMETHOD_MPOST,
@@ -105,11 +97,11 @@ typedef enum // http_method_t
HTTPMETHOD_HEAD, HTTPMETHOD_HEAD,
HTTPMETHOD_MSEARCH, HTTPMETHOD_MSEARCH,
HTTPMETHOD_UNKNOWN, HTTPMETHOD_UNKNOWN,
SOAPMETHOD_POST, //murari SOAPMETHOD_POST,
HTTPMETHOD_SIMPLEGET HTTPMETHOD_SIMPLEGET
} http_method_t; } http_method_t;
// different types of HTTP headers /* different types of HTTP headers */
#define HDR_UNKNOWN -1 #define HDR_UNKNOWN -1
#define HDR_CACHE_CONTROL 1 #define HDR_CACHE_CONTROL 1
#define HDR_CALLBACK 2 #define HDR_CALLBACK 2
@@ -118,9 +110,9 @@ typedef enum // http_method_t
#define HDR_DATE 5 #define HDR_DATE 5
#define HDR_EXT 6 #define HDR_EXT 6
#define HDR_HOST 7 #define HDR_HOST 7
//#define HDR_IF_MODIFIED_SINCE 8 /*define HDR_IF_MODIFIED_SINCE 8 */
//#define HDR_IF_UNMODIFIED_SINCE 9 /*define HDR_IF_UNMODIFIED_SINCE 9 */
//#define HDR_LAST_MODIFIED 10 /*define HDR_LAST_MODIFIED 10 */
#define HDR_LOCATION 11 #define HDR_LOCATION 11
#define HDR_MAN 12 #define HDR_MAN 12
#define HDR_MX 13 #define HDR_MX 13
@@ -136,7 +128,7 @@ typedef enum // http_method_t
#define HDR_USN 23 #define HDR_USN 23
#define HDR_USER_AGENT 24 #define HDR_USER_AGENT 24
//Adding new header difinition//Beg_Murari /* Adding new header difinition */
#define HDR_ACCEPT 25 #define HDR_ACCEPT 25
#define HDR_ACCEPT_ENCODING 26 #define HDR_ACCEPT_ENCODING 26
#define HDR_ACCEPT_CHARSET 27 #define HDR_ACCEPT_CHARSET 27
@@ -149,72 +141,77 @@ typedef enum // http_method_t
#define HDR_IF_RANGE 34 #define HDR_IF_RANGE 34
#define HDR_RANGE 35 #define HDR_RANGE 35
#define HDR_TE 36 #define HDR_TE 36
//End_Murari
// status of parsing /*! status of parsing */
typedef enum // parse_status_t typedef enum {
{ /*! msg was parsed successfully. */
PARSE_SUCCESS = 0, // msg was parsed successfully PARSE_SUCCESS = 0,
PARSE_INCOMPLETE, // need more data to continue /*! need more data to continue. */
PARSE_INCOMPLETE_ENTITY, // for responses that don't have length specified PARSE_INCOMPLETE,
PARSE_FAILURE, // parse failed; check status code for details /*! for responses that don't have length specified. */
PARSE_OK, // done partial PARSE_INCOMPLETE_ENTITY,
PARSE_NO_MATCH, // token not matched /*! parse failed; check status code for details. */
PARSE_FAILURE,
// private /*! done partial. */
PARSE_OK,
/*! token not matched. */
PARSE_NO_MATCH,
/*! private. */
PARSE_CONTINUE_1 PARSE_CONTINUE_1
} parse_status_t; } parse_status_t;
typedef struct // http_header_t typedef struct {
{ /*! header name as a string. */
memptr name; // header name as a string memptr name;
int name_id; // header name id (for a selective group of headers only) /*! header name id (for a selective group of headers only). */
membuffer value; // raw-value; could be multi-lined; min-length = 0 int name_id;
/*! raw-value; could be multi-lined; min-length = 0. */
// private membuffer value;
/* private. */
membuffer name_buf; membuffer name_buf;
} http_header_t; } http_header_t;
typedef struct // http_message_t typedef struct {
{
int initialized; int initialized;
// request only /*! request only. */
http_method_t method; http_method_t method;
/*! request only. */
uri_type uri; uri_type uri;
/*! response only. */
// response only
http_method_t request_method; http_method_t request_method;
/*! response only. */
int status_code; int status_code;
/*! response only. */
membuffer status_msg; membuffer status_msg;
/* fields used in both request or response messages. */
// fields used in both request or response messages /*! if TRUE, msg is a request, else response. */
xboolean is_request; // if TRUE, msg is a request, else response int is_request;
/* http major version. */
int major_version; // http major.minor version int major_version;
/* http minor version. */
int minor_version; int minor_version;
/*! . */
LinkedList headers; LinkedList headers;
//NNS: dlist headers; // dlist<http_header_t *> /*! message body(entity). */
memptr entity; // message body(entity) memptr entity;
/* private fields. */
// private fields /*! entire raw message. */
membuffer msg; // entire raw message membuffer msg;
char *urlbuf; // storage for url string /*! storage for url string. */
char *urlbuf;
/*! . */
size_t entity_offset; size_t entity_offset;
} http_message_t; } http_message_t;
typedef struct // http_parser_t typedef struct {
{
http_message_t msg; http_message_t msg;
int http_error_code; // read-only; in case of parse error, this /*! read-only; in case of parse error, this
// contains the HTTP error code (4XX or 5XX) * contains the HTTP error code (4XX or 5XX). */
int http_error_code;
// read-only; this is set to true if a NOTIFY request has no content-length. /*! read-only; this is set to true if a NOTIFY request has no
// used to read valid sspd notify msg. * content-length. used to read valid sspd notify msg. */
xboolean valid_ssdp_notify_hack; int valid_ssdp_notify_hack;
/* private data -- don't touch. */
// private data -- don't touch
parser_pos_t position; parser_pos_t position;
int ent_position; int ent_position;
unsigned int content_length; unsigned int content_length;
@@ -223,15 +220,9 @@ typedef struct // http_parser_t
scanner_t scanner; scanner_t scanner;
} http_parser_t; } http_parser_t;
//--------------------------------------------------
//////////////// functions /////////////////////////
//--------------------------------------------------
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif // __cplusplus #endif /* __cplusplus */
/************************************************************************ /************************************************************************
* Function : httpmsg_init * Function : httpmsg_init
@@ -273,7 +264,6 @@ void httpmsg_destroy( INOUT http_message_t* msg );
* *
* Return : http_header_t* - Pointer to a header on success; * Return : http_header_t* - Pointer to a header on success;
* NULL on failure * NULL on failure
*
* Note : * Note :
************************************************************************/ ************************************************************************/
http_header_t* httpmsg_find_hdr_str( IN http_message_t* msg, http_header_t* httpmsg_find_hdr_str( IN http_message_t* msg,
@@ -289,7 +279,7 @@ http_header_t* httpmsg_find_hdr_str( IN http_message_t* msg,
* *
* Description : Finds header from a list, with the given 'name_id'. * Description : Finds header from a list, with the given 'name_id'.
* *
* Return : http_header_t* - Pointer to a header on success; * * Return : http_header_t* - Pointer to a header on success;
* NULL on failure * NULL on failure
* *
* Note : * Note :
@@ -437,10 +427,6 @@ parse_status_t parser_append( INOUT http_parser_t* parser,
************************************************************************/ ************************************************************************/
int matchstr( IN char *str, IN size_t slen, IN const char* fmt, ... ); int matchstr( IN char *str, IN size_t slen, IN const char* fmt, ... );
// ====================================================
// misc functions
/************************************************************************ /************************************************************************
* Function: raw_to_int * Function: raw_to_int
* *
@@ -481,11 +467,10 @@ int raw_find_str( IN memptr* raw_value, IN const char* str );
* nameConverts a http_method id stored in the HTTP Method * nameConverts a http_method id stored in the HTTP Method
* *
* Returns: * Returns:
* const char* ptr - Ptr to the HTTP Method * * const char* ptr - Ptr to the HTTP Method
************************************************************************/ ************************************************************************/
const char* method_to_str( IN http_method_t method ); const char* method_to_str( IN http_method_t method );
/*! /*!
* \brief Print the HTTP headers. * \brief Print the HTTP headers.
*/ */
@@ -494,13 +479,16 @@ void print_http_headers(
/*! [in] HTTP Message object. */ /*! [in] HTTP Message object. */
http_message_t *hmsg); http_message_t *hmsg);
#else #else
static UPNP_INLINE void print_http_headers(http_message_t *hmsg) {} static UPNP_INLINE void print_http_headers(http_message_t *hmsg)
{
return;
hmsg = hmsg;
}
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */
#endif /* __cplusplus */ #endif /* __cplusplus */
#endif /* GENLIB_NET_HTTP_HTTPPARSER_H */ #endif /* GENLIB_NET_HTTP_HTTPPARSER_H */

View File

@@ -1,88 +1,82 @@
/////////////////////////////////////////////////////////////////////////// /*******************************************************************************
// *
// Copyright (c) 2000-2003 Intel Corporation * Copyright (c) 2000-2003 Intel Corporation
// All rights reserved. * All rights reserved.
// *
// Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
// *
// * Redistributions of source code must retain the above copyright notice, * - Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer. * this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice, * - Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation * this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution. * and/or other materials provided with the distribution.
// * Neither name of Intel Corporation nor the names of its contributors * - Neither name of Intel Corporation nor the names of its contributors
// may be used to endorse or promote products derived from this software * may be used to endorse or promote products derived from this software
// without specific prior written permission. * without specific prior written permission.
// *
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// *
/////////////////////////////////////////////////////////////////////////// ******************************************************************************/
#ifndef GENLIB_NET_HTTP_HTTPREADWRITE_H #ifndef GENLIB_NET_HTTP_HTTPREADWRITE_H
#define GENLIB_NET_HTTP_HTTPREADWRITE_H #define GENLIB_NET_HTTP_HTTPREADWRITE_H
/*
* \file
*/
#include "config.h" #include "config.h"
#include "util.h" #include "upnputil.h"
#include "sock.h" #include "sock.h"
#include "httpparser.h" #include "httpparser.h"
// timeout in secs /*! timeout in secs. */
#define HTTP_DEFAULT_TIMEOUT 30 #define HTTP_DEFAULT_TIMEOUT 30
#ifdef __cplusplus #ifdef __cplusplus
#extern "C" { #extern "C" {
#endif #endif
int int http_CancelHttpGet(IN void *Handle);
http_CancelHttpGet( IN void *Handle );
/************************************************************************ /*!
* Function: http_FixUrl * \brief Validates URL.
* *
* Parameters: * \return
* IN uri_type* url; URL to be validated and fixed * \li \c UPNP_E_INVALID_URL
* OUT uri_type* fixed_url; URL after being fixed. * \li \c UPNP_E_SUCCESS
* */
* Description: int http_FixUrl(
* Validates URL /*! [in] URL to be validated and fixed. */
* uri_type *url,
* Returns: /*! [out] URL after being fixed. */
* UPNP_E_INVALID_URL uri_type *fixed_url);
* UPNP_E_SUCCESS
************************************************************************/
int http_FixUrl( IN uri_type* url, OUT uri_type* fixed_url );
/*!
/************************************************************************ * \brief Parses URL and then validates URL.
* Function: http_FixStrUrl
* *
* Parameters: * \return
* IN char* urlstr ; Character string as a URL * \li \c UPNP_E_INVALID_URL
* IN int urlstrlen ; Length of the character string * \li \c UPNP_E_SUCCESS
* OUT uri_type* fixed_url ; Fixed and corrected URL */
* int http_FixStrUrl(
* Description: /*! [in] Character string as a URL. */
* Parses URL and then validates URL const char *urlstr,
* /*! [in] Length of the character string. */
* Returns: size_t urlstrlen,
* UPNP_E_INVALID_URL /*! [out] Fixed and corrected URL. */
* UPNP_E_SUCCESS uri_type *fixed_url);
************************************************************************/
int http_FixStrUrl( IN const char* urlstr, IN int urlstrlen, OUT uri_type* fixed_url );
/************************************************************************ /************************************************************************
* Function: http_Connect * Function: http_Connect
@@ -95,7 +89,7 @@ int http_FixStrUrl( IN const char* urlstr, IN int urlstrlen, OUT uri_type* fixed
* Gets destination address from URL and then connects to the remote end * Gets destination address from URL and then connects to the remote end
* *
* Returns: * Returns:
* socket descriptor on sucess * socket descriptor on success
* UPNP_E_OUTOF_SOCKET * UPNP_E_OUTOF_SOCKET
* UPNP_E_SOCKET_CONNECT on error * UPNP_E_SOCKET_CONNECT on error
************************************************************************/ ************************************************************************/
@@ -128,37 +122,37 @@ int http_RecvMessage( IN SOCKINFO *info, OUT http_parser_t* parser,
OUT int* http_error_code ); OUT int* http_error_code );
/************************************************************************ /*!
* Function: http_SendMessage * \brief Sends a message to the destination based on the format parameter.
* *
* Parameters:
* IN SOCKINFO *info ; Socket information object
* IN OUT int * TimeOut ; time out value
* IN const char* fmt, ... Pattern format to take actions upon
*
* Description:
* Sends a message to the destination based on the
* IN const char* fmt parameter
* fmt types: * fmt types:
* 'f': arg = const char * file name * \li \c 'f': arg = "const char *" file name
* 'm': arg1 = const char * mem_buffer; arg2= size_t buf_length * \li \c 'b': arg1 = "const char *" mem_buffer; arg2 = "size_t" buffer length.
* E.g.: * \li \c 'I': arg = "struct SendInstruction *"
* char *buf = "POST /xyz.cgi http/1.1\r\n\r\n";
* char *filename = "foo.dat";
* int status = http_SendMessage( tcpsock, "mf",
* buf, strlen(buf), // args for memory buffer
* filename ); // arg for file
* *
* Returns: * E.g.:
* UPNP_E_OUTOF_MEMORY \verbatim
* UPNP_E_FILE_READ_ERROR char *buf = "POST /xyz.cgi http/1.1\r\n\r\n";
* UPNP_E_SUCCESS char *filename = "foo.dat";
************************************************************************/ int status = http_SendMessage(tcpsock, "bf",
buf, strlen(buf), // args for memory buffer
filename); // arg for file
\endverbatim
*
* \return
* \li \c UPNP_E_OUTOF_MEMORY
* \li \c UPNP_E_FILE_READ_ERROR
* \li \c UPNP_E_SUCCESS
*/
int http_SendMessage( int http_SendMessage(
IN SOCKINFO *info, /* [in] Socket information object. */
IN OUT int* timeout_secs, SOCKINFO *info,
IN const char* fmt, ... ); /* [in,out] Time out value. */
int* timeout_secs,
/* [in] Pattern format to take actions upon. */
const char* fmt,
/* [in] Variable parameter list. */
...);
/************************************************************************ /************************************************************************
* Function: http_RequestAndResponse * Function: http_RequestAndResponse
@@ -212,7 +206,7 @@ int http_RequestAndResponse(
* IN int timeout_secs; time out value * IN int timeout_secs; time out value
* OUT char** document; buffer to store the document extracted * OUT char** document; buffer to store the document extracted
* from the donloaded message. * from the donloaded message.
* OUT int* doc_length; length of the extracted document * OUT size_t* doc_length; length of the extracted document
* OUT char* content_type; Type of content * OUT char* content_type; Type of content
* *
* Description: * Description:
@@ -227,7 +221,7 @@ int http_Download(
IN const char* url, IN const char* url,
IN int timeout_secs, IN int timeout_secs,
OUT char** document, OUT char** document,
OUT int* doc_length, OUT size_t *doc_length,
OUT char* content_type ); OUT char* content_type );
@@ -238,7 +232,7 @@ int http_Download(
* IN void *Handle: Handle to the http post object * IN void *Handle: Handle to the http post object
* IN char *buf: Buffer to send to peer, if format used * IN char *buf: Buffer to send to peer, if format used
* is not UPNP_USING_CHUNKED, * is not UPNP_USING_CHUNKED,
* IN unsigned int *size: Size of the data to be sent. * IN size_t *size: Size of the data to be sent.
* IN int timeout: time out value * IN int timeout: time out value
* *
* Description: * Description:
@@ -252,7 +246,7 @@ int http_Download(
************************************************************************/ ************************************************************************/
int http_WriteHttpPost(IN void *Handle, int http_WriteHttpPost(IN void *Handle,
IN char *buf, IN char *buf,
IN unsigned int *size, IN size_t *size,
IN int timeout); IN int timeout);
@@ -271,7 +265,7 @@ int http_WriteHttpPost(IN void *Handle,
* associated memory. Frees handle associated with the HTTP POST msg. * associated memory. Frees handle associated with the HTTP POST msg.
* *
* Return: int * Return: int
* UPNP_E_SUCCESS - On Sucess * UPNP_E_SUCCESS - On success
* UPNP_E_INVALID_PARAM - Invalid Parameter * UPNP_E_INVALID_PARAM - Invalid Parameter
************************************************************************/ ************************************************************************/
int http_CloseHttpPost(IN void *Handle, int http_CloseHttpPost(IN void *Handle,
@@ -296,7 +290,7 @@ int http_CloseHttpPost(IN void *Handle,
* such handles * such handles
* *
* Return : int; * Return : int;
* UPNP_E_SUCCESS - On Sucess * UPNP_E_SUCCESS - On success
* UPNP_E_INVALID_PARAM - Invalid Parameter * UPNP_E_INVALID_PARAM - Invalid Parameter
* UPNP_E_OUTOF_MEMORY * UPNP_E_OUTOF_MEMORY
* UPNP_E_SOCKET_ERROR * UPNP_E_SOCKET_ERROR
@@ -315,7 +309,7 @@ int http_OpenHttpPost(IN const char *url_str,
* Parameters: * Parameters:
* IN void *Handle; Handle to the HTTP get object * IN void *Handle; Handle to the HTTP get object
* IN OUT char *buf; Buffer to get the read and parsed data * IN OUT char *buf; Buffer to get the read and parsed data
* IN OUT unsigned int *size; Size of the buffer passed * IN OUT size_t *size; Size of the buffer passed
* IN int timeout; time out value * IN int timeout; time out value
* *
* Description: * Description:
@@ -323,7 +317,7 @@ int http_OpenHttpPost(IN const char *url_str,
* Parses and extracts information from the new data. * Parses and extracts information from the new data.
* *
* Return: int * Return: int
* UPNP_E_SUCCESS - On Sucess * UPNP_E_SUCCESS - On success
* UPNP_E_INVALID_PARAM - Invalid Parameter * UPNP_E_INVALID_PARAM - Invalid Parameter
* UPNP_E_BAD_RESPONSE * UPNP_E_BAD_RESPONSE
* UPNP_E_BAD_HTTPMSG * UPNP_E_BAD_HTTPMSG
@@ -332,7 +326,7 @@ int http_OpenHttpPost(IN const char *url_str,
int http_ReadHttpGet( int http_ReadHttpGet(
IN void *Handle, IN void *Handle,
IN OUT char *buf, IN OUT char *buf,
IN OUT unsigned int *size, IN OUT size_t *size,
IN int timeout); IN int timeout);
@@ -341,8 +335,8 @@ int http_ReadHttpGet(
* *
* Parameters: * Parameters:
* IN void *Handle; Handle to the HTTP get object * IN void *Handle; Handle to the HTTP get object
* OUT unsigned int *length; Buffer to get the read and parsed data * OUT size_t *length; Buffer to get the read and parsed data
* OUT unsigned int *total; Size of tge buffer passed * OUT size_t *total; Size of tge buffer passed
* *
* Description: * Description:
* Extracts information from the Handle to the HTTP get object. * Extracts information from the Handle to the HTTP get object.
@@ -353,9 +347,8 @@ int http_ReadHttpGet(
************************************************************************/ ************************************************************************/
int http_HttpGetProgress( int http_HttpGetProgress(
IN void *Handle, IN void *Handle,
OUT unsigned int *length, OUT size_t *length,
OUT unsigned int *total ); OUT size_t *total);
/************************************************************************ /************************************************************************
* Function: http_CloseHttpGet * Function: http_CloseHttpGet
@@ -373,74 +366,61 @@ int http_HttpGetProgress(
************************************************************************/ ************************************************************************/
int http_CloseHttpGet(IN void *Handle); int http_CloseHttpGet(IN void *Handle);
/*!
/************************************************************************ * \brief Makes the HTTP GET message, connects to the peer,
* Function: http_OpenHttpGet
*
* Parameters:
* IN const char *url_str: String as a URL
* IN OUT void **Handle: Pointer to buffer to store HTTP
* post handle
* IN OUT char **contentType: Type of content
* OUT int *contentLength: length of content
* OUT int *httpStatus: HTTP status returned on receiving a
* response message
* IN int timeout: time out value
*
* Description:
* Makes the HTTP GET message, connects to the peer,
* sends the HTTP GET request, gets the response and parses the
* response.
*
* Return: int
* UPNP_E_SUCCESS - On Success
* UPNP_E_INVALID_PARAM - Invalid Paramters
* UPNP_E_OUTOF_MEMORY
* UPNP_E_SOCKET_ERROR
* UPNP_E_BAD_RESPONSE
************************************************************************/
int http_OpenHttpGet(
IN const char *url_str,
IN OUT void **Handle,
IN OUT char **contentType,
OUT int *contentLength,
OUT int *httpStatus,
IN int timeout);
/************************************************************************
* Function: http_OpenHttpGetProxy
*
* Parameters:
* IN const char *url_str; String as a URL
* IN const char *proxy_str; String as a URL
* IN OUT void **Handle; Pointer to buffer to store HTTP
* post handle
* IN OUT char **contentType; Type of content
* OUT int *contentLength; length of content
* OUT int *httpStatus; HTTP status returned on receiving a
* response message
* IN int timeout: time out value
*
* Description:
* Makes the HTTP GET message, connects to the peer,
* sends the HTTP GET request, gets the response and parses the response. * sends the HTTP GET request, gets the response and parses the response.
*
* If a proxy URL is defined then the connection is made there. * If a proxy URL is defined then the connection is made there.
* *
* Return: int * \return integer
* UPNP_E_SUCCESS - On Success * \li \c UPNP_E_SUCCESS - On Success
* UPNP_E_INVALID_PARAM - Invalid Paramters * \li \c UPNP_E_INVALID_PARAM - Invalid Paramters
* UPNP_E_OUTOF_MEMORY * \li \c UPNP_E_OUTOF_MEMORY
* UPNP_E_SOCKET_ERROR * \li \c UPNP_E_SOCKET_ERROR
* UPNP_E_BAD_RESPONSE * \li \c UPNP_E_BAD_RESPONSE
************************************************************************/ */
int http_OpenHttpGetProxy(IN const char *url_str, int http_OpenHttpGet(
IN const char *proxy_str, /* [in] String as a URL. */
IN OUT void **Handle, const char *url_str,
IN OUT char **contentType, /* [in,out] Pointer to buffer to store HTTP post handle. */
OUT int *contentLength, void **Handle,
OUT int *httpStatus, /* [in,out] Type of content. */
IN int timeout); char **contentType,
/* [out] length of content. */
int *contentLength,
/* [out] HTTP status returned on receiving a response message. */
int *httpStatus,
/* [in] time out value. */
int timeout);
/*!
* \brief Makes the HTTP GET message, connects to the peer,
* sends the HTTP GET request, gets the response and parses the response.
*
* If a proxy URL is defined then the connection is made there.
*
* \return integer
* \li \c UPNP_E_SUCCESS - On Success
* \li \c UPNP_E_INVALID_PARAM - Invalid Paramters
* \li \c UPNP_E_OUTOF_MEMORY
* \li \c UPNP_E_SOCKET_ERROR
* \li \c UPNP_E_BAD_RESPONSE
*/
int http_OpenHttpGetProxy(
/* [in] String as a URL. */
const char *url_str,
/* [in] String as a URL. */
const char *proxy_str,
/* [in,out] Pointer to buffer to store HTTP post handle. */
void **Handle,
/* [in,out] Type of content. */
char **contentType,
/* [out] length of content. */
int *contentLength,
/* [out] HTTP status returned on receiving a response message. */
int *httpStatus,
/* [in] time out value. */
int timeout);
/************************************************************************ /************************************************************************
@@ -469,61 +449,55 @@ int http_SendStatusResponse(
IN int request_major_version, IN int request_major_version,
IN int request_minor_version ); IN int request_minor_version );
/*!
/************************************************************************ * \brief Generate an HTTP message based on the format that is specified in
* Function: http_MakeMessage * the input parameters.
* *
* Parameters: \verbatim
* INOUT membuffer* buf; buffer with the contents of the Format types:
* message 'B': arg = int status_code -- appends content-length, content-type and HTML body for given code.
* IN int http_major_version; HTTP major version 'b': arg1 = const char *buf;
* IN int http_minor_version; HTTP minor version arg2 = size_t buf_length memory ptr
* IN const char* fmt; Pattern format 'C': (no args) -- appends a HTTP CONNECTION: close header 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
'L': arg = language information -- add Content-Language header if Accept-Language header is not empty and if
WEB_SERVER_CONTENT_LANGUAGE is not empty
'N': arg1 = off_t content_length -- content-length header
'q': arg1 = http_method_t -- request start line and HOST header
arg2 = (uri_type *)
'Q': arg1 = http_method_t; -- start line of request
arg2 = char* url;
arg3 = size_t url_length
'R': arg = int status_code -- adds a response start line
'S': (no args) -- appends HTTP SERVER: header
's': arg = const char * -- C_string
'T': arg = char * content_type; -- format e.g: "text/html"; content-type header
't': arg = time_t * gmt_time -- appends time in RFC 1123 fmt
'U': (no args) -- appends HTTP USER-AGENT: header
'X': arg = const char * -- useragent; "redsonic" HTTP X-User-Agent: useragent
\endverbatim
* *
* Description: * \return
* Generate an HTTP message based on the format that is specified * \li \c 0 - On Success
* in the input parameters. * \li \c UPNP_E_OUTOF_MEMORY
* * \li \c UPNP_E_INVALID_URL
* fmt types: */
* '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 memory ptr
* 'C': (no args) appends a HTTP CONNECTION: close header
* 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 = off_t content_length // content-length header
* 'q': arg1 = http_method_t // request start line and HOST header
* arg2 = (uri_type *)
* 'Q': arg1 = http_method_t; // start line of request
* arg2 = char* url;
* arg3 = size_t url_length
* 'R': arg = int status_code // adds a response start line
* 'S': (no args) appends HTTP SERVER: header
* 's': arg = const char* C_string
* 'T': arg = char * content_type; format
* e.g: "text/html"; content-type header
* 't': arg = time_t * gmt_time // appends time in RFC 1123 fmt
* 'U': (no args) appends HTTP USER-AGENT: header
* 'X': arg = const char useragent; "redsonic" HTTP X-User-Agent: useragent
*
* Return: int
* 0 - On Success
* UPNP_E_OUTOF_MEMORY
* UPNP_E_INVALID_URL
************************************************************************/
int http_MakeMessage( int http_MakeMessage(
/* [in,out] Buffer with the contents of the message. */
INOUT membuffer* buf, INOUT membuffer* buf,
/* [in] HTTP major version. */
IN int http_major_version, IN int http_major_version,
/* [in] HTTP minor version. */
IN int http_minor_version, IN int http_minor_version,
IN const char* fmt, ... ); /* [in] Pattern format. */
IN const char* fmt,
/* [in] Format arguments. */
... );
/************************************************************************ /************************************************************************
@@ -597,9 +571,9 @@ int http_OpenHttpGetEx(IN const char *url_str,
void get_sdk_info( OUT char *info ); void get_sdk_info( OUT char *info );
#ifdef __cplusplus #ifdef __cplusplus
} // #extern "C" } /* #extern "C" */
#endif #endif
#endif // GENLIB_NET_HTTP_HTTPREADWRITE_H #endif /* GENLIB_NET_HTTP_HTTPREADWRITE_H */

View File

@@ -40,7 +40,7 @@
* \li (2) takes a u_char* not an in_addr as input * \li (2) takes a u_char* not an in_addr as input
* *
*/ */
extern const char *inet_ntop4(const u_char src, char *dst, socklen_t size); extern const char *inet_ntop4(const u_char *src, char *dst, socklen_t size);
/*! /*!

View File

@@ -1,72 +1,76 @@
/////////////////////////////////////////////////////////////////////////// /*******************************************************************************
// *
// Copyright (c) 2000-2003 Intel Corporation * Copyright (c) 2000-2003 Intel Corporation
// All rights reserved. * All rights reserved.
// *
// Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
// *
// * Redistributions of source code must retain the above copyright notice, * - Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer. * this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice, * - Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation * this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution. * and/or other materials provided with the distribution.
// * Neither name of Intel Corporation nor the names of its contributors * - Neither name of Intel Corporation nor the names of its contributors
// may be used to endorse or promote products derived from this software * may be used to endorse or promote products derived from this software
// without specific prior written permission. * without specific prior written permission.
// *
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// *
/////////////////////////////////////////////////////////////////////////// ******************************************************************************/
#ifndef GENLIB_UTIL_MEMBUFFER_H #ifndef GENLIB_UTIL_MEMBUFFER_H
#define GENLIB_UTIL_MEMBUFFER_H #define GENLIB_UTIL_MEMBUFFER_H
/*!
* \file
*/
#include <stdlib.h> #include <stdlib.h>
#include "util.h" #include "upnputil.h"
#define MINVAL( a, b ) ( (a) < (b) ? (a) : (b) ) #define MINVAL( a, b ) ( (a) < (b) ? (a) : (b) )
#define MAXVAL( a, b ) ( (a) > (b) ? (a) : (b) ) #define MAXVAL( a, b ) ( (a) > (b) ? (a) : (b) )
// pointer to a chunk of memory /*! pointer to a chunk of memory. */
typedef struct // memptr typedef struct
{ {
char *buf; // start of memory (read/write) /*! start of memory (read/write). */
size_t length; // length of memory (read-only) char *buf;
/*! length of memory (read-only). */
size_t length;
} memptr; } memptr;
// maintains a block of dynamically allocated memory /*! Maintains a block of dynamically allocated memory
// note: Total length/capacity should not exceed MAX_INT * note: Total length/capacity should not exceed MAX_INT */
typedef struct // membuffer typedef struct
{ {
char *buf; // mem buffer; must not write beyond buf[length-1] (read/write) /*! mem buffer; must not write beyond buf[length-1] (read/write). */
size_t length; // length of buffer (read-only) char *buf;
size_t capacity; // total allocated memory (read-only) /*! length of buffer (read-only). */
size_t size_inc; // used to increase size; MUST be > 0; (read/write) size_t length;
/*! total allocated memory (read-only). */
// default value of size_inc size_t capacity;
/*! used to increase size; MUST be > 0; (read/write). */
size_t size_inc;
/*! default value of size_inc. */
#define MEMBUF_DEF_SIZE_INC 5 #define MEMBUF_DEF_SIZE_INC 5
} membuffer; } membuffer;
//--------------------------------------------------
//////////////// functions /////////////////////////
//--------------------------------------------------
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif // __cplusplus #endif /* __cplusplus */
/************************************************************************ /************************************************************************
* Function : str_alloc * Function : str_alloc
@@ -253,47 +257,37 @@ int membuffer_append( INOUT membuffer* m, IN const void* buf, IN size_t buf_len
************************************************************************/ ************************************************************************/
int membuffer_append_str( INOUT membuffer* m, IN const char* c_str ); int membuffer_append_str( INOUT membuffer* m, IN const char* c_str );
/************************************************************************ /*!
* Function : membuffer_insert * \brief Allocates memory for the new data to be inserted. Does
*
* Parameters :
* INOUT membuffer* m ; buffer whose memory size is to be increased
* and appended.
* IN const void* buf ; source buffer whose contents will be
* copied
* IN size_t buf_len ; size of the source buffer
* int index ; index to determine the bounds while movinf the data
*
* Description : Allocates memory for the new data to be inserted. Does
* memory management by moving the data from the existing memory to * memory management by moving the data from the existing memory to
* the newly allocated memory and then appending the new data. * the newly allocated memory and then appending the new data.
* *
* Return : int ; * \return 0 if successful, error code if error.
* */
* Note : int membuffer_insert(
************************************************************************/ /* [in,out] Buffer whose memory size is to be increased and appended. */
int membuffer_insert( INOUT membuffer* m, IN const void* buf, IN size_t buf_len, int index ); membuffer *m,
/* [in] source buffer whose contents will be copied. */
const void *buf,
/* [in] size of the source buffer. */
size_t buf_len,
/* [in] index to determine the bounds while movinf the data. */
size_t index);
/************************************************************************ /*!
* Function : membuffer_delete * \brief Shrink the size of the buffer depending on the current size of the
* * bufer and te input parameters. Move contents from the old buffer to the
* Parameters : * new sized buffer.
* INOUT membuffer* m ; buffer whose memory size is to be decreased */
* and copied to the odified location void membuffer_delete(
* IN int index ; index to determine bounds while moving data /* [in,out] Buffer whose memory size is to be decreased and copied
* IN size_t num_bytes ; number of bytes that the data needs to * to the modified location. */
* shrink by INOUT membuffer *m,
* /* [in] Index to determine bounds while moving data. */
* Description : Shrink the size of the buffer depending on the current IN size_t index,
* size of the bufer and te input parameters. Move contents from the /* [in] Number of bytes that the data needs to shrink by. */
* old buffer to the new sized buffer. IN size_t num_bytes);
*
* Return : void ;
*
* Note :
************************************************************************/
void membuffer_delete( INOUT membuffer* m, IN int index, IN size_t num_bytes );
/************************************************************************ /************************************************************************
@@ -332,7 +326,8 @@ char* membuffer_detach( INOUT membuffer* m );
************************************************************************/ ************************************************************************/
void membuffer_attach( INOUT membuffer* m, IN char* new_buf, IN size_t buf_len ); void membuffer_attach( INOUT membuffer* m, IN char* new_buf, IN size_t buf_len );
#ifdef __cplusplus #ifdef __cplusplus
} // extern "C" } /* extern "C" */
#endif // __cplusplus #endif /* __cplusplus */
#endif /* GENLIB_UTIL_H */
#endif // GENLIB_UTIL_H

View File

@@ -59,11 +59,11 @@ typedef struct MServerSockArray {
/*! IPv6 SSDP Socket for incoming advertisments and search requests. */ /*! IPv6 SSDP Socket for incoming advertisments and search requests. */
SOCKET ssdpSock6UlaGua; SOCKET ssdpSock6UlaGua;
/* ! . */ /* ! . */
SOCKET stopPort; uint16_t stopPort;
/* ! . */ /* ! . */
SOCKET miniServerPort4; uint16_t miniServerPort4;
/* ! . */ /* ! . */
SOCKET miniServerPort6; uint16_t miniServerPort6;
#ifdef INCLUDE_CLIENT_APIS #ifdef INCLUDE_CLIENT_APIS
/*! IPv4 SSDP socket for sending search requests and receiving search /*! IPv4 SSDP socket for sending search requests and receiving search
* replies */ * replies */
@@ -106,7 +106,7 @@ void SetSoapCallback(
/*! [in] SOAP Callback to be invoked . */ /*! [in] SOAP Callback to be invoked . */
MiniServerCallback callback); MiniServerCallback callback);
#else /* INCLUDE_DEVICE_APIS */ #else /* INCLUDE_DEVICE_APIS */
static inline void SetSoapCallback(MiniServerCallback callback) {} static UPNP_INLINE void SetSoapCallback(MiniServerCallback callback) {}
#endif /* INCLUDE_DEVICE_APIS */ #endif /* INCLUDE_DEVICE_APIS */

View File

@@ -1,63 +1,61 @@
/////////////////////////////////////////////////////////////////////////// /*******************************************************************************
// *
// Copyright (c) 2000-2003 Intel Corporation * Copyright (c) 2000-2003 Intel Corporation
// All rights reserved. * All rights reserved.
// *
// Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
// *
// * Redistributions of source code must retain the above copyright notice, * - Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer. * this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice, * - Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation * this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution. * and/or other materials provided with the distribution.
// * Neither name of Intel Corporation nor the names of its contributors * - Neither name of Intel Corporation nor the names of its contributors
// may be used to endorse or promote products derived from this software * may be used to endorse or promote products derived from this software
// without specific prior written permission. * without specific prior written permission.
// *
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// *
/////////////////////////////////////////////////////////////////////////// ******************************************************************************/
#ifndef GENLIB_NET_HTTP_PARSETOOLS_H #ifndef GENLIB_NET_HTTP_PARSETOOLS_H
#define GENLIB_NET_HTTP_PARSETOOLS_H #define GENLIB_NET_HTTP_PARSETOOLS_H
#include "util.h" /*!
#include "httpparser.h" * \file
*/
#include "upnputil.h"
#include "httpparser.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/*!
/************************************************************************ * \brief Find the header from the HTTP message and match the header for
* Function: has_xml_content_type * xml data.
* *
* Parameters: * \return boolean.
* IN http_message_t* hmsg ; HTTP Message object */
* int has_xml_content_type(
* Description: Find the header from the HTTP message and match the /*! HTTP Message object. */
* header for xml data. IN http_message_t *hmsg);
*
* Returns:
* BOOLEAN
************************************************************************/
xboolean has_xml_content_type( IN http_message_t* hmsg );
#ifdef __cplusplus #ifdef __cplusplus
} // extern C } /* extern C */
#endif #endif
#endif /* GENLIB_NET_HTTP_PARSETOOLS_H */
#endif // GENLIB_NET_HTTP_PARSETOOLS_H

View File

@@ -29,38 +29,30 @@
* *
******************************************************************************/ ******************************************************************************/
#ifndef SERVICE_TABLE_H #ifndef SERVICE_TABLE_H
#define SERVICE_TABLE_H #define SERVICE_TABLE_H
/*! /*!
* \file * \file
*/ */
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#include "config.h" #include "config.h"
#include "uri.h" #include "uri.h"
#include "ixml.h" #include "ixml.h"
#include "upnp.h" #include "upnp.h"
#include "upnpdebug.h" #include "upnpdebug.h"
#include <stdio.h> #include <stdio.h>
#include <time.h> #include <time.h>
#define SID_SIZE 41 #define SID_SIZE 41
#ifdef INCLUDE_DEVICE_APIS #ifdef INCLUDE_DEVICE_APIS
typedef struct SUBSCRIPTION { typedef struct SUBSCRIPTION {
Upnp_SID sid; Upnp_SID sid;
int eventKey; int eventKey;
@@ -71,7 +63,6 @@ typedef struct SUBSCRIPTION {
struct SUBSCRIPTION *next; struct SUBSCRIPTION *next;
} subscription; } subscription;
typedef struct SERVICE_INFO { typedef struct SERVICE_INFO {
DOMString serviceType; DOMString serviceType;
DOMString serviceId; DOMString serviceId;
@@ -85,21 +76,18 @@ typedef struct SERVICE_INFO {
struct SERVICE_INFO *next; struct SERVICE_INFO *next;
} service_info; } service_info;
typedef struct SERVICE_TABLE { typedef struct SERVICE_TABLE {
DOMString URLBase; DOMString URLBase;
service_info *serviceList; service_info *serviceList;
service_info *endServiceList; service_info *endServiceList;
} service_table; } service_table;
/* Functions for Subscriptions */ /* Functions for Subscriptions */
/*! /*!
* \brief Makes a copy of the subscription. * \brief Makes a copy of the subscription.
* *
* \return HTTP_SUCCESS on Sucess. * \return HTTP_SUCCESS on success.
*/ */
int copy_subscription( int copy_subscription(
/*! [in] Source subscription. */ /*! [in] Source subscription. */
@@ -107,7 +95,6 @@ int copy_subscription(
/*! [in] Destination subscription. */ /*! [in] Destination subscription. */
subscription *out); subscription *out);
/* /*
* \brief Remove the subscription represented by the const Upnp_SID sid parameter * \brief Remove the subscription represented by the const Upnp_SID sid parameter
* from the service table and update the service table. * from the service table and update the service table.
@@ -118,7 +105,6 @@ void RemoveSubscriptionSID(
/*! [in] Service object providing the list of subscriptions. */ /*! [in] Service object providing the list of subscriptions. */
service_info *service); service_info *service);
/*! /*!
* \brief Return the subscription from the service table that matches * \brief Return the subscription from the service table that matches
* const Upnp_SID sid value. * const Upnp_SID sid value.
@@ -131,7 +117,6 @@ subscription *GetSubscriptionSID(
/*! [in] Service object providing the list of subscriptions. */ /*! [in] Service object providing the list of subscriptions. */
service_info *service); service_info *service);
/*! /*!
* \brief Gets pointer to the first subscription node in the service table. * \brief Gets pointer to the first subscription node in the service table.
* *
@@ -141,7 +126,6 @@ subscription *GetFirstSubscription(
/*! [in] Service object providing the list of subscriptions. */ /*! [in] Service object providing the list of subscriptions. */
service_info *service); service_info *service);
/*! /*!
* \brief Get current and valid subscription from the service table. * \brief Get current and valid subscription from the service table.
* *
@@ -153,7 +137,6 @@ subscription *GetNextSubscription(
/*! [in] Current subscription object. */ /*! [in] Current subscription object. */
subscription *current); subscription *current);
/*! /*!
* \brief Free's the memory allocated for storing the URL of the subscription. * \brief Free's the memory allocated for storing the URL of the subscription.
*/ */
@@ -161,7 +144,6 @@ void freeSubscription(
/*! [in] Subscription object to be freed. */ /*! [in] Subscription object to be freed. */
subscription *sub); subscription *sub);
/*! /*!
* \brief Free's memory allocated for all the subscriptions in the service table. * \brief Free's memory allocated for all the subscriptions in the service table.
*/ */
@@ -169,7 +151,6 @@ void freeSubscriptionList(
/*! [in] Head of the subscription list. */ /*! [in] Head of the subscription list. */
subscription * head); subscription * head);
/*! /*!
* \brief Traverses through the service table and returns a pointer to the * \brief Traverses through the service table and returns a pointer to the
* service node that matches a known service id and a known UDN. * service node that matches a known service id and a known UDN.
@@ -186,7 +167,6 @@ service_info *FindServiceId(
* table. */ * table. */
const char *UDN); const char *UDN);
/*! /*!
* \brief Traverses the service table and finds the node whose event URL Path * \brief Traverses the service table and finds the node whose event URL Path
* matches a know value. * matches a know value.
@@ -200,7 +180,6 @@ service_info *FindServiceEventURLPath(
/*! [in] Event URL path used to find a service from the table. */ /*! [in] Event URL path used to find a service from the table. */
char *eventURLPath); char *eventURLPath);
/*! /*!
* \brief Traverses the service table and finds the node whose control URL Path * \brief Traverses the service table and finds the node whose control URL Path
* matches a know value. * matches a know value.
@@ -214,7 +193,6 @@ service_info * FindServiceControlURLPath(
/*! [in] Control URL path used to find a service from the table. */ /*! [in] Control URL path used to find a service from the table. */
const char *controlURLPath); const char *controlURLPath);
/*! /*!
* \brief For debugging purposes prints information from the service passed * \brief For debugging purposes prints information from the service passed
* into the function. * into the function.
@@ -231,10 +209,15 @@ void printService(
static UPNP_INLINE void printService( static UPNP_INLINE void printService(
service_info *service, service_info *service,
Upnp_LogLevel level, Upnp_LogLevel level,
Dbg_Module module) {} Dbg_Module module)
{
return;
service = service;
level = level;
module = module;
}
#endif #endif
/*! /*!
* \brief For debugging purposes prints information of each service from the * \brief For debugging purposes prints information of each service from the
* service table passed into the function. * service table passed into the function.
@@ -251,10 +234,15 @@ void printServiceList(
static UPNP_INLINE void printServiceList( static UPNP_INLINE void printServiceList(
service_info *service, service_info *service,
Upnp_LogLevel level, Upnp_LogLevel level,
Dbg_Module module) {} Dbg_Module module)
{
return;
service = service;
level = level;
module = module;
}
#endif #endif
/*! /*!
* \brief For debugging purposes prints the URL base of the table and information * \brief For debugging purposes prints the URL base of the table and information
* of each service from the service table passed into the function. * of each service from the service table passed into the function.
@@ -271,10 +259,15 @@ void printServiceTable(
static UPNP_INLINE void printServiceTable( static UPNP_INLINE void printServiceTable(
service_table *table, service_table *table,
Upnp_LogLevel level, Upnp_LogLevel level,
Dbg_Module module) {} Dbg_Module module)
{
return;
table = table;
level = level;
module = module;
}
#endif #endif
/*! /*!
* \brief Free's memory allocated for the various components of the service * \brief Free's memory allocated for the various components of the service
* entry in the service table. * entry in the service table.
@@ -283,7 +276,6 @@ void freeService(
/*! [in] Service information that is to be freed. */ /*! [in] Service information that is to be freed. */
service_info *in); service_info *in);
/*! /*!
* \brief Free's memory allocated for the various components of each service * \brief Free's memory allocated for the various components of each service
* entry in the service table. * entry in the service table.
@@ -292,7 +284,6 @@ void freeServiceList(
/*! [in] Head of the service list to be freed. */ /*! [in] Head of the service list to be freed. */
service_info *head); service_info *head);
/*! /*!
* \brief Free's dynamic memory in table (does not free table, only memory * \brief Free's dynamic memory in table (does not free table, only memory
* within the structure). * within the structure).
@@ -301,7 +292,6 @@ void freeServiceTable(
/*! [in] Service table whose internal memory needs to be freed. */ /*! [in] Service table whose internal memory needs to be freed. */
service_table *table); service_table *table);
/*! /*!
* \brief This function assumes that services for a particular root device are * \brief This function assumes that services for a particular root device are
* placed linearly in the service table, and in the order in which they are * placed linearly in the service table, and in the order in which they are
@@ -316,7 +306,6 @@ int removeServiceTable(
/*! [in] Service table from which services will be removed. */ /*! [in] Service table from which services will be removed. */
service_table *in); service_table *in);
/*! /*!
* \brief Add Service to the table. * \brief Add Service to the table.
*/ */
@@ -329,7 +318,6 @@ int addServiceTable(
* service list. */ * service list. */
const char *DefaultURLBase); const char *DefaultURLBase);
/*! /*!
* \brief Retrieve service from the table. * \brief Retrieve service from the table.
* *
@@ -343,10 +331,8 @@ int getServiceTable(
/*! [in] Default base URL on which the URL will be returned. */ /*! [in] Default base URL on which the URL will be returned. */
const char *DefaultURLBase); const char *DefaultURLBase);
/* Misc helper functions */ /* Misc helper functions */
/*! /*!
* \brief Returns the clone of the element value. * \brief Returns the clone of the element value.
* *
@@ -358,7 +344,6 @@ DOMString getElementValue(
/*! [in] Input node which provides the list of child nodes. */ /*! [in] Input node which provides the list of child nodes. */
IXML_Node *node); IXML_Node *node);
/*! /*!
* \brief Traverses through a list of XML nodes to find the node with the * \brief Traverses through a list of XML nodes to find the node with the
* known element name. * known element name.
@@ -375,7 +360,6 @@ int getSubElement(
/*! [out] Ouput node to which the matched child node is returned. */ /*! [out] Ouput node to which the matched child node is returned. */
IXML_Node **out); IXML_Node **out);
#endif /* INCLUDE_DEVICE_APIS */ #endif /* INCLUDE_DEVICE_APIS */
#ifdef __cplusplus #ifdef __cplusplus

View File

@@ -32,31 +32,25 @@
#ifndef SOAPLIB_H #ifndef SOAPLIB_H
#define SOAPLIB_H #define SOAPLIB_H
/*!
* \file
*/
/* SOAP module API to be called in Upnp-Dk API */ /* SOAP module API to be called in Upnp-Dk API */
/**************************************************************************** /*!
* Function: soap_device_callback * \brief This is a callback called by minisever after receiving the request
* * from the control point. This function will start processing the request.
* Parameters: * It calls handle_invoke_action to handle the SOAP action.
* IN http_parser_t *parser: Parsed request received by the device */
* IN http_message_t* request: HTTP request
* INOUT SOCKINFO *info: socket info
*
* Description: This is a callback called by minisever after receiving
* the request from the control point. This function will start
* processing the request. It calls handle_invoke_action to handle the
* SOAP action
*
* Return: void
*
* Note:
****************************************************************************/
void soap_device_callback( void soap_device_callback(
IN http_parser_t *parser, /*! [in] Parsed request received by the device. */
IN http_message_t* request, http_parser_t *parser,
INOUT SOCKINFO *info); /*! [in] HTTP request. */
http_message_t *request,
/*! [in,out] Socket info. */
SOCKINFO *info);
/**************************************************************************** /****************************************************************************

View File

@@ -36,7 +36,7 @@
* \file * \file
*/ */
#include "util.h" #include "upnputil.h"
#ifdef WIN32 #ifdef WIN32
/* Do not #include <netinet/in.h> */ /* Do not #include <netinet/in.h> */
@@ -110,7 +110,7 @@ int sock_read(
/*! Buffer to get data to. */ /*! Buffer to get data to. */
OUT char* buffer, OUT char* buffer,
/*! Size of the buffer. */ /*! Size of the buffer. */
IN size_t bufsize, IN int bufsize,
/*! timeout value. */ /*! timeout value. */
INOUT int *timeoutSecs); INOUT int *timeoutSecs);
@@ -126,9 +126,9 @@ int sock_write(
/*! Socket Information Object. */ /*! Socket Information Object. */
IN SOCKINFO *info, IN SOCKINFO *info,
/*! Buffer to send data from. */ /*! Buffer to send data from. */
IN char* buffer, IN const char *buffer,
/*! Size of the buffer. */ /*! Size of the buffer. */
IN size_t bufsize, IN int bufsize,
/*! timeout value. */ /*! timeout value. */
INOUT int *timeoutSecs); INOUT int *timeoutSecs);
@@ -154,9 +154,9 @@ int sock_destroy(
* *
* \return -1 if an error occurred or if the socket is -1. * \return -1 if an error occurred or if the socket is -1.
*/ */
static inline int sock_close( static UPNP_INLINE int sock_close(
/*! Socket descriptor. */ /*! Socket descriptor. */
int sock) SOCKET sock)
{ {
int ret = -1; int ret = -1;

View File

@@ -29,7 +29,6 @@
* *
**************************************************************************/ **************************************************************************/
#ifndef SSDPLIB_H #ifndef SSDPLIB_H
#define SSDPLIB_H #define SSDPLIB_H
@@ -90,7 +89,6 @@ typedef enum SsdpCmdType{
#define SSDP_IPV6_SITELOCAL "FF05::C" #define SSDP_IPV6_SITELOCAL "FF05::C"
#define SSDP_PORT 1900 #define SSDP_PORT 1900
#define NUM_TRY 3 #define NUM_TRY 3
#define NUM_COPY 1
#define THREAD_LIMIT 50 #define THREAD_LIMIT 50
#define COMMAND_LEN 300 #define COMMAND_LEN 300
@@ -114,11 +112,8 @@ typedef enum SsdpCmdType{
#define E_SOCKET -7 #define E_SOCKET -7
#define RQST_TIMEOUT 20 #define RQST_TIMEOUT 20
/*! Structure to store the SSDP information */
typedef struct SsdpEventStruct {
/* Structure to store the SSDP information */
typedef struct SsdpEventStruct
{
enum SsdpCmdType Cmd; enum SsdpCmdType Cmd;
enum SsdpSearchType RequestType; enum SsdpSearchType RequestType;
int ErrCode; int ErrCode;
@@ -126,7 +121,8 @@ typedef struct SsdpEventStruct
int Mx; int Mx;
char UDN[LINE_SIZE]; char UDN[LINE_SIZE];
char DeviceType[LINE_SIZE]; char DeviceType[LINE_SIZE];
char ServiceType[LINE_SIZE]; //NT or ST /* NT or ST */
char ServiceType[LINE_SIZE];
char Location[LINE_SIZE]; char Location[LINE_SIZE];
char HostAddr[LINE_SIZE]; char HostAddr[LINE_SIZE];
char Os[LINE_SIZE]; char Os[LINE_SIZE];
@@ -140,7 +136,7 @@ typedef void (* SsdpFunPtr)(Event *);
typedef Event SsdpEvent ; typedef Event SsdpEvent ;
// Structure to contain Discovery response /*! Structure to contain Discovery response. */
typedef struct resultData typedef struct resultData
{ {
struct Upnp_Discovery param; struct Upnp_Discovery param;
@@ -238,7 +234,7 @@ static inline void ssdp_handle_device_request(
* Parameters: * Parameters:
* IN http_message_t* hmsg: SSDP message from the device * IN http_message_t* hmsg: SSDP message from the device
* IN struct sockaddr* dest_addr: Address of the device * IN struct sockaddr* dest_addr: Address of the device
* IN xboolean timeout: timeout kept by the control point while sending * IN int timeout: timeout kept by the control point while sending
* search message * search message
* IN void* cookie: Cookie stored by the control point application. * IN void* cookie: Cookie stored by the control point application.
* This cookie will be returned to the control point * This cookie will be returned to the control point
@@ -255,7 +251,7 @@ static inline void ssdp_handle_device_request(
void ssdp_handle_ctrlpt_msg( void ssdp_handle_ctrlpt_msg(
IN http_message_t *hmsg, IN http_message_t *hmsg,
IN struct sockaddr *dest_addr, IN struct sockaddr *dest_addr,
IN xboolean timeout, IN int timeout,
IN void *cookie); IN void *cookie);
/************************************************************************ /************************************************************************

View File

@@ -1,38 +1,38 @@
/////////////////////////////////////////////////////////////////////////// /*******************************************************************************
// *
// Copyright (c) 2000-2003 Intel Corporation * Copyright (c) 2000-2003 Intel Corporation
// All rights reserved. * All rights reserved.
// *
// Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
// *
// * Redistributions of source code must retain the above copyright notice, * - Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer. * this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice, * - Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation * this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution. * and/or other materials provided with the distribution.
// * Neither name of Intel Corporation nor the names of its contributors * - Neither name of Intel Corporation nor the names of its contributors
// may be used to endorse or promote products derived from this software * may be used to endorse or promote products derived from this software
// without specific prior written permission. * without specific prior written permission.
// *
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// *
/////////////////////////////////////////////////////////////////////////// ******************************************************************************/
#ifndef GENLIB_NET_HTTP_STATCODES_H #ifndef GENLIB_NET_HTTP_STATCODES_H
#define GENLIB_NET_HTTP_STATCODES_H #define GENLIB_NET_HTTP_STATCODES_H
// HTTP response status codes /* HTTP response status codes */
#define HTTP_CONTINUE 100 #define HTTP_CONTINUE 100
#define HTTP_SWITCHING_PROCOTOLS 101 #define HTTP_SWITCHING_PROCOTOLS 101
@@ -80,15 +80,13 @@
#define HTTP_GATEWAY_TIMEOUT 504 #define HTTP_GATEWAY_TIMEOUT 504
#define HTTP_HTTP_VERSION_NOT_SUPPORTED 505 #define HTTP_HTTP_VERSION_NOT_SUPPORTED 505
// *********** HTTP lib error codes ********** /* HTTP lib error codes */
#define HTTP_E_OUT_OF_MEMORY -2 #define HTTP_E_OUT_OF_MEMORY -2
#define HTTP_E_BAD_MSG_FORMAT -3 #define HTTP_E_BAD_MSG_FORMAT -3
#define HTTP_E_TIMEDOUT -4 #define HTTP_E_TIMEDOUT -4
#define HTTP_E_FILE_READ -5 #define HTTP_E_FILE_READ -5
// *******************************************
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@@ -109,7 +107,8 @@ extern "C" {
const char* http_get_code_text( int statusCode ); const char* http_get_code_text( int statusCode );
#ifdef __cplusplus #ifdef __cplusplus
} // extern C } /* extern C */
#endif #endif
#endif /* GENLIB_NET_HTTP_STATCODES_H */ #endif /* GENLIB_NET_HTTP_STATCODES_H */

View File

@@ -1,46 +1,46 @@
/////////////////////////////////////////////////////////////////////////// /*******************************************************************************
// *
// Copyright (c) 2000-2003 Intel Corporation * Copyright (c) 2000-2003 Intel Corporation
// All rights reserved. * All rights reserved.
// *
// Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
// *
// * Redistributions of source code must retain the above copyright notice, * - Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer. * this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice, * - Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation * this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution. * and/or other materials provided with the distribution.
// * Neither name of Intel Corporation nor the names of its contributors * - Neither name of Intel Corporation nor the names of its contributors
// may be used to endorse or promote products derived from this software * may be used to endorse or promote products derived from this software
// without specific prior written permission. * without specific prior written permission.
// *
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// *
/////////////////////////////////////////////////////////////////////////// ******************************************************************************/
#ifndef GENLIB_UTIL_STRINTMAP_H #ifndef GENLIB_UTIL_STRINTMAP_H
#define GENLIB_UTIL_STRINTMAP_H #define GENLIB_UTIL_STRINTMAP_H
#include <stdlib.h> #include <stdlib.h>
#include "util.h" #include "upnputil.h"
// Util to map from a string to an integer and vice versa /* Util to map from a string to an integer and vice versa */
typedef struct // str_int_entry typedef struct /* str_int_entry */
{ {
char *name; // a value in string form const char *name; /* a value in string form */
int id; // same value in integer form int id; /* same value in integer form */
} str_int_entry; } str_int_entry;
#ifdef __cplusplus #ifdef __cplusplus
@@ -57,7 +57,7 @@ extern "C" {
* matched. * matched.
* IN int num_entries ; number of entries in the table that need * IN int num_entries ; number of entries in the table that need
* to be searched. * to be searched.
* IN xboolean case_sensitive ; whether the case should be case * IN int case_sensitive ; whether the case should be case
* sensitive or not * sensitive or not
* *
* Description : Match the given name with names from the entries in the * Description : Match the given name with names from the entries in the
@@ -71,7 +71,7 @@ extern "C" {
************************************************************************/ ************************************************************************/
int map_str_to_int( IN const char* name, IN size_t name_len, int map_str_to_int( IN const char* name, IN size_t name_len,
IN str_int_entry* table, IN int num_entries, IN str_int_entry* table, IN int num_entries,
IN xboolean case_sensitive ); IN int case_sensitive );
/************************************************************************ /************************************************************************
@@ -95,8 +95,9 @@ int map_int_to_str( IN int id, IN str_int_entry* table,
IN int num_entries ); IN int num_entries );
#ifdef __cplusplus #ifdef __cplusplus
} // extern C } /* extern C */
#endif #endif
#endif // GENLIB_UTIL_STRINTMAP_H #endif /* GENLIB_UTIL_STRINTMAP_H */

View File

@@ -109,10 +109,8 @@ struct Handle_Info
#endif #endif
}; };
extern ithread_rwlock_t GlobalHndRWLock; extern ithread_rwlock_t GlobalHndRWLock;
/*! /*!
* \brief Get handle information. * \brief Get handle information.
* *
@@ -181,7 +179,7 @@ extern char gIF_IPV6[65];
extern char gIF_IPV6_ULA_GUA[INET6_ADDRSTRLEN]; extern char gIF_IPV6_ULA_GUA[INET6_ADDRSTRLEN];
extern int gIF_INDEX; extern unsigned gIF_INDEX;
extern unsigned short LOCAL_PORT_V4; extern unsigned short LOCAL_PORT_V4;
@@ -294,7 +292,7 @@ int getlocalhostname(
/*! [out] IP address of the interface. */ /*! [out] IP address of the interface. */
char *out, char *out,
/*! [in] Length of the output buffer. */ /*! [in] Length of the output buffer. */
const int out_len); size_t out_len);
/*! /*!

136
upnp/src/inc/upnputil.h Normal file
View File

@@ -0,0 +1,136 @@
/*******************************************************************************
*
* Copyright (c) 2000-2003 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************/
#ifndef UTIL_H
#define UTIL_H
/*!
* \file
*/
#include "upnp.h"
/* usually used to specify direction of parameters in functions */
#ifndef IN
#define IN
#endif
#ifndef OUT
#define OUT
#endif
#ifndef INOUT
#define INOUT
#endif
#define GEMD_OUT_OF_MEMORY -1
#define EVENT_TIMEDOUT -2
#define EVENT_TERMINATE -3
/*! boolean type in C. */
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#ifdef __cplusplus
extern "C" {
#endif
/*!
* \brief Copy no of bytes spcified by the LINE_SIZE constant, from the
* source buffer. Null terminate the destination buffer.
*/
void linecopy(
/*! [out] output buffer. */
char dest[LINE_SIZE],
/*! [in] input buffer. */
const char *src);
/*!
* \brief Copy no of bytes spcified by the NAME_SIZE constant, from the
* source buffer. Null terminate the destination buffer
*/
void namecopy(
/*! [out] output buffer. */
char dest[NAME_SIZE],
/*! [in] input buffer. */
const char *src);
/*!
* \brief Determine if the srclen passed in paramter is less than the
* permitted LINE_SIZE. If it is use the passed parameter, if not
* use the permitted LINE_SIZE as the length parameter.
*
* Copy no of bytes spcified by the LINE_SIZE constant, from the source
* buffer. Null terminate the destination buffer.
*/
void linecopylen(
/*! [out] output buffer. */
char dest[LINE_SIZE],
/*! [in] input buffer. */
const char *src,
/*! [in] bytes to be copied. */
size_t srclen);
#ifdef __cplusplus
}
#endif
/* Size of the errorBuffer variable, passed to the strerror_r() function */
#define ERROR_BUFFER_LEN 256
/* C specific */
#ifndef __cplusplus
#ifdef WIN32
#ifndef S_ISREG
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
#endif
#ifndef S_ISDIR
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#endif
#define EADDRINUSE WSAEADDRINUSE
#define strcasecmp stricmp
#define strncasecmp strnicmp
#define sleep(a) Sleep((a)*1000)
#define usleep(a) Sleep((a)/1000)
#define strerror_r(a,b,c) (strerror_s((b),(c),(a)))
#else
#define max(a, b) (((a)>(b))? (a):(b))
#define min(a, b) (((a)<(b))? (a):(b))
#endif /* WIN32 */
#endif /* __cplusplus */
#endif /* UTIL_H */

View File

@@ -29,11 +29,9 @@
* *
******************************************************************************/ ******************************************************************************/
#ifndef GENLIB_NET_URI_H #ifndef GENLIB_NET_URI_H
#define GENLIB_NET_URI_H #define GENLIB_NET_URI_H
/*! /*!
* \file * \file
*/ */
@@ -42,11 +40,9 @@
#include <sys/param.h> #include <sys/param.h>
#endif #endif
#include "UpnpGlobal.h" /* for */ #include "UpnpGlobal.h" /* for */
#include "UpnpInet.h" #include "UpnpInet.h"
#include <ctype.h> #include <ctype.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
@@ -58,56 +54,52 @@
#include <sys/types.h> #include <sys/types.h>
#include <time.h> #include <time.h>
#ifdef WIN32 #ifdef WIN32
#include "inet_pton.h"
#else #else
#include <arpa/inet.h> /* for inet_pton() */ #include <arpa/inet.h> /* for inet_pton() */
#include <netdb.h> /* for struct addrinfo */ #include <netdb.h> /* for struct addrinfo */
#endif #endif
#ifdef WIN32 #ifdef WIN32
#define strncasecmp strnicmp #define strncasecmp strnicmp
#else #else
/* Other systems have strncasecmp */ /* Other systems have strncasecmp */
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/*! length for HTTP DATE: "DATE: Sun, 01 Jul 2000 08:15:23 GMT<cr><lf>" */
#define HTTP_DATE_LENGTH 37
#define HTTP_DATE_LENGTH 37 // length for HTTP DATE:
//"DATE: Sun, 01 Jul 2000 08:15:23 GMT<cr><lf>"
#define SEPARATORS "()<>@,;:\\\"/[]?={} \t" #define SEPARATORS "()<>@,;:\\\"/[]?={} \t"
#define MARK "-_.!~*'()" #define MARK "-_.!~*'()"
#define RESERVED ";/?:@&=+$,{}" //added {} for compatibility
/*! added {} for compatibility */
#define RESERVED ";/?:@&=+$,{}"
#define HTTP_SUCCESS 1 #define HTTP_SUCCESS 1
#define FALSE 0 #define FALSE 0
#define TAB 9 #define TAB 9
#define CR 13 #define CR 13
#define LF 10 #define LF 10
#define SOCKET_BUFFER_SIZE 5000 #define SOCKET_BUFFER_SIZE 5000
enum hostType { enum hostType {
HOSTNAME, HOSTNAME,
IPv4address IPv4address
}; };
enum pathType { enum pathType {
ABS_PATH, ABS_PATH,
REL_PATH, REL_PATH,
OPAQUE_PART OPAQUE_PART
}; };
#ifdef WIN32 #ifdef WIN32
/* there is a conflict in windows with other symbols */ /* there is a conflict in windows with other symbols. */
enum uriType { enum uriType {
absolute, absolute,
relative relative
@@ -119,7 +111,6 @@ enum pathType {
}; };
#endif #endif
/*! /*!
* \brief Buffer used in parsinghttp messages, urls, etc. generally this simply * \brief Buffer used in parsinghttp messages, urls, etc. generally this simply
* holds a pointer into a larger array. * holds a pointer into a larger array.
@@ -129,7 +120,6 @@ typedef struct TOKEN {
size_t size; size_t size;
} token; } token;
/*! /*!
* \brief Represents a host port: e.g. "127.127.0.1:80" text is a token * \brief Represents a host port: e.g. "127.127.0.1:80" text is a token
* pointing to the full string representation. * pointing to the full string representation.
@@ -141,7 +131,6 @@ typedef struct HOSTPORT {
struct sockaddr_storage IPaddress; struct sockaddr_storage IPaddress;
} hostport_type; } hostport_type;
/*! /*!
* \brief Represents a URI used in parse_uri and elsewhere * \brief Represents a URI used in parse_uri and elsewhere
*/ */
@@ -154,21 +143,19 @@ typedef struct URI{
hostport_type hostport; hostport_type hostport;
} uri_type; } uri_type;
/*! /*!
* \brief Represents a list of URLs as in the "callback" header of SUBSCRIBE * \brief Represents a list of URLs as in the "callback" header of SUBSCRIBE
* message in GENA. "char *" URLs holds dynamic memory. * message in GENA. "char *" URLs holds dynamic memory.
*/ */
typedef struct URL_LIST { typedef struct URL_LIST {
/*! */ /*! */
int size; size_t size;
/*! All the urls, delimited by <> */ /*! All the urls, delimited by <> */
char *URLs; char *URLs;
/*! */ /*! */
uri_type *parsedURLs; uri_type *parsedURLs;
} URL_list; } URL_list;
/*! /*!
* \brief Replaces an escaped sequence with its unescaped version as in * \brief Replaces an escaped sequence with its unescaped version as in
* http://www.ietf.org/rfc/rfc2396.txt (RFC explaining URIs) * http://www.ietf.org/rfc/rfc2396.txt (RFC explaining URIs)
@@ -182,14 +169,13 @@ typedef struct URL_LIST {
* \return * \return
*/ */
int replace_escaped( int replace_escaped(
/*! [in] String of characters. */ /*! [in,out] String of characters. */
char *in, char *in,
/*! [in] Index at which to start checking the characters. */ /*! [in] Index at which to start checking the characters. */
int index, size_t index,
/*! [out] . */ /*! [out] . */
size_t *max); size_t *max);
/*! /*!
* \brief Copies one URL_list into another. * \brief Copies one URL_list into another.
* *
@@ -217,7 +203,6 @@ void free_URL_list(
/*! [in] URL list object. */ /*! [in] URL list object. */
URL_list *list); URL_list *list);
/*! /*!
* \brief Function useful in debugging for printing a parsed uri. * \brief Function useful in debugging for printing a parsed uri.
*/ */
@@ -226,10 +211,13 @@ void print_uri(
/*! [in] URI object to print. */ /*! [in] URI object to print. */
uri_type *in); uri_type *in);
#else #else
static UPNP_INLINE void print_uri(uri_type *in) {} static UPNP_INLINE void print_uri(uri_type *in)
{
return;
in = in;
}
#endif #endif
/*! /*!
* \brief Function useful in debugging for printing a token. * \brief Function useful in debugging for printing a token.
*/ */
@@ -238,10 +226,15 @@ void print_token(
/*! [in] Token object to print. */ /*! [in] Token object to print. */
token *in); token *in);
#else #else
static UPNP_INLINE void print_token(token * in) {} static UPNP_INLINE void print_token(
/*! [in] Token object to print. */
token *in)
{
return;
in = in;
}
#endif #endif
/*! /*!
* \brief Compares buffer in the token object with the buffer in in2. * \brief Compares buffer in the token object with the buffer in in2.
* *
@@ -254,8 +247,7 @@ int token_string_casecmp(
/*! [in] Token object whose buffer is to be compared. */ /*! [in] Token object whose buffer is to be compared. */
token *in1, token *in1,
/*! [in] String of characters to compare with. */ /*! [in] String of characters to compare with. */
char *in2); const char *in2);
/*! /*!
* \brief Compares a null terminated string to a token (exact). * \brief Compares a null terminated string to a token (exact).
@@ -271,7 +263,6 @@ int token_string_cmp(
/*! [in] String of characters to compare with. */ /*! [in] String of characters to compare with. */
char *in2); char *in2);
/*! /*!
* \brief Compares two tokens. * \brief Compares two tokens.
* *
@@ -286,7 +277,6 @@ int token_cmp(
/*! [in] Second token object used for the comparison. */ /*! [in] Second token object used for the comparison. */
token *in2); token *in2);
/*! /*!
* \brief Parses a string representing a host and port (e.g. "127.127.0.1:80" * \brief Parses a string representing a host and port (e.g. "127.127.0.1:80"
* or "localhost") and fills out a hostport_type struct with internet address * or "localhost") and fills out a hostport_type struct with internet address
@@ -298,12 +288,11 @@ int parse_hostport(
/*! [in] String of characters representing host and port. */ /*! [in] String of characters representing host and port. */
const char *in, const char *in,
/*! [in] Sets a maximum limit. */ /*! [in] Sets a maximum limit. */
int max, size_t max,
/*! [out] Output parameter where the host and port are represented as /*! [out] Output parameter where the host and port are represented as
* an internet address. */ * an internet address. */
hostport_type *out); hostport_type *out);
/*! /*!
* \brief Removes http escaped characters such as: "%20" and replaces them with * \brief Removes http escaped characters such as: "%20" and replaces them with
* their character representation. i.e. "hello%20foo" -> "hello foo". * their character representation. i.e. "hello%20foo" -> "hello foo".
@@ -319,7 +308,6 @@ int remove_escaped_chars(
/*! [in,out] Size limit for the number of characters. */ /*! [in,out] Size limit for the number of characters. */
size_t *size); size_t *size);
/*! /*!
* \brief Removes ".", and ".." from a path. * \brief Removes ".", and ".." from a path.
* *
@@ -348,7 +336,6 @@ int remove_dots(
/*! [in] Size limit for the number of characters. */ /*! [in] Size limit for the number of characters. */
size_t size); size_t size);
/*! /*!
* \brief resolves a relative url with a base url returning a NEW (dynamically * \brief resolves a relative url with a base url returning a NEW (dynamically
* allocated with malloc) full url. * allocated with malloc) full url.
@@ -369,7 +356,6 @@ char *resolve_rel_url(
/*! [in] Relative URL. */ /*! [in] Relative URL. */
char *rel_url); char *rel_url);
/*! /*!
* \brief Parses a uri as defined in http://www.ietf.org/rfc/rfc2396.txt * \brief Parses a uri as defined in http://www.ietf.org/rfc/rfc2396.txt
* (RFC explaining URIs). * (RFC explaining URIs).
@@ -386,11 +372,10 @@ int parse_uri(
/*! [in] Character string containing uri information to be parsed. */ /*! [in] Character string containing uri information to be parsed. */
const char *in, const char *in,
/*! [in] Maximum limit on the number of characters. */ /*! [in] Maximum limit on the number of characters. */
int max, size_t max,
/*! [out] Output parameter which will have the parsed uri information. */ /*! [out] Output parameter which will have the parsed uri information. */
uri_type *out); uri_type *out);
/*! /*!
* \brief Same as parse_uri(), except that all strings are unescaped * \brief Same as parse_uri(), except that all strings are unescaped
* (%XX replaced by chars). * (%XX replaced by chars).
@@ -403,11 +388,10 @@ int parse_uri_and_unescape(
/*! [in] Character string containing uri information to be parsed. */ /*! [in] Character string containing uri information to be parsed. */
char *in, char *in,
/*! [in] Maximum limit on the number of characters. */ /*! [in] Maximum limit on the number of characters. */
int max, size_t max,
/*! [out] Output parameter which will have the parsed uri information. */ /*! [out] Output parameter which will have the parsed uri information. */
uri_type *out); uri_type *out);
/*! /*!
* \brief * \brief
* *
@@ -421,7 +405,6 @@ int parse_token(
/*! [in] . */ /*! [in] . */
int max_size); int max_size);
/* Commented #defines, functions and typdefs */ /* Commented #defines, functions and typdefs */
#if 0 #if 0

View File

@@ -1,173 +0,0 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2000-2003 Intel Corporation
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither name of Intel Corporation nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
#ifndef UTIL_H
#define UTIL_H
#include "upnp.h"
// usually used to specify direction of parameters in functions
#ifndef IN
#define IN
#endif
#ifndef OUT
#define OUT
#endif
#ifndef INOUT
#define INOUT
#endif
#define GEMD_OUT_OF_MEMORY -1
#define EVENT_TIMEDOUT -2
#define EVENT_TERMINATE -3
// boolean type in C
typedef char xboolean;
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
///////////////////////////
// funcs
#ifdef __cplusplus
extern "C" {
#endif
/************************************************************************
* Function: logerror
*
* Parameters:
* IN const char *fmt; format string
*
* Description: Log an error message.
*
* Return: void
************************************************************************/
void log_error( IN const char *fmt, ... );
/************************************************************************
* Function: linecopy
*
* Parameters:
* OUT char dest[LINE_SIZE]; output buffer
* IN const char *src; input buffer
*
* Description: Copy no of bytes spcified by the LINE_SIZE constant,
* from the source buffer. Null terminate the destination buffer.
*
* Return: void
************************************************************************/
void linecopy( OUT char dest[LINE_SIZE], IN const char* src );
/************************************************************************
* Function: namecopy
*
* Parameters:
* OUT char dest[NAME_SIZE]; output buffer
* IN const char *src; input buffer
*
* Description: Copy no of bytes spcified by the NAME_SIZE constant,
* from the source buffer. Null terminate the destination buffer
*
* Return: void
************************************************************************/
void namecopy( OUT char dest[NAME_SIZE], IN const char* src );
/************************************************************************
* Function: linecopylen
*
* Parameters:
* OUT char dest[LINE_SIZE]; output buffer
* IN const char *src; input buffer
* IN size_t srclen; bytes to be copied.
*
* Description : Determine if the srclen passed in paramter is less than
* the permitted LINE_SIZE. If it is use the passed parameter, if not
* use the permitted LINE_SIZE as the length parameter
* Copy no of bytes spcified by the LINE_SIZE constant,
* from the source buffer. Null terminate the destination buffer
*
* Return: void
************************************************************************/
void linecopylen( OUT char dest[LINE_SIZE], IN const char* src, IN size_t srclen );
#ifdef __cplusplus
} // extern C
#endif
/* Size of the errorBuffer variable, passed to the strerror_r() function */
#define ERROR_BUFFER_LEN 256
//////////////////////////////////
// C specific
#ifndef __cplusplus
#ifdef WIN32
#ifndef S_ISREG
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
#endif
#ifndef S_ISDIR
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#endif
#define EADDRINUSE WSAEADDRINUSE
#define strcasecmp stricmp
#define strncasecmp strnicmp
#define sleep(a) Sleep((a)*1000)
#define usleep(a) Sleep((a)/1000)
#define strerror_r(a,b,c) (strerror_s((b),(c),(a)))
#else
#define max(a, b) (((a)>(b))? (a):(b))
#define min(a, b) (((a)<(b))? (a):(b))
#endif /* WIN32 */
#endif // __cplusplus
#endif /* UTIL_H */

View File

@@ -1,34 +0,0 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2000-2003 Intel Corporation
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither name of Intel Corporation nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
#include <genlib/util/util.h>
#include <genlib/util/xstring.h>

View File

@@ -130,9 +130,9 @@ void web_server_callback(
#ifdef __cplusplus #ifdef __cplusplus
} // extern C } /* extern C */
#endif #endif
#endif // GENLIB_NET_HTTP_WEBSERVER_H #endif /* GENLIB_NET_HTTP_WEBSERVER_H */

View File

@@ -6,7 +6,5 @@
#include "sock.h" #include "sock.h"
#include "soaplib.h" #include "soaplib.h"
#endif /* EXCLUDE_SOAP */
#endif // EXCLUDE_SOAP

View File

@@ -1,33 +1,33 @@
/////////////////////////////////////////////////////////////////////////// /*******************************************************************************
// *
// Copyright (c) 2000-2003 Intel Corporation * Copyright (c) 2000-2003 Intel Corporation
// All rights reserved. * All rights reserved.
// *
// Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
// *
// * Redistributions of source code must retain the above copyright notice, * - Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer. * this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice, * - Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation * this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution. * and/or other materials provided with the distribution.
// * Neither name of Intel Corporation nor the names of its contributors * - Neither name of Intel Corporation nor the names of its contributors
// may be used to endorse or promote products derived from this software * may be used to endorse or promote products derived from this software
// without specific prior written permission. * without specific prior written permission.
// *
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// *
/////////////////////////////////////////////////////////////////////////// ******************************************************************************/
#include "config.h" #include "config.h"
#ifdef INCLUDE_CLIENT_APIS #ifdef INCLUDE_CLIENT_APIS
@@ -54,119 +54,92 @@
#define SOAP_ACTION_RESP 1 #define SOAP_ACTION_RESP 1
#define SOAP_VAR_RESP 2 #define SOAP_VAR_RESP 2
//#define SOAP_ERROR_RESP 3 /*#define SOAP_ERROR_RESP 3*/
#define SOAP_ACTION_RESP_ERROR 3 #define SOAP_ACTION_RESP_ERROR 3
#define SOAP_VAR_RESP_ERROR 4 #define SOAP_VAR_RESP_ERROR 4
/**************************************************************************** /*!
* Function : dom_cmp_name * \brief Compares 'name' and node's name.
* *
* Parameters : * \return 0 if both are equal; 1 if not equal, and UPNP_E_OUTOF_MEMORY.
* IN char *name : lookup name */
* IN IXML_Node *node : xml node static int dom_cmp_name(
* /* [in] lookup name. */
* Description : This function compares 'name' and node's name const char *name,
* /* [in] xml node. */
* Return : int IXML_Node *node)
* 0 if both are equal; 1 if not equal, and UPNP_E_OUTOF_MEMORY
*
* Note :
****************************************************************************/
static int
dom_cmp_name( IN char *name,
IN IXML_Node * node )
{ {
const DOMString node_name = NULL; const DOMString node_name = NULL;
memptr nameptr, memptr nameptr;
dummy; memptr dummy;
int ret_code; int ret_code;
assert(name); assert(name);
assert(node); assert(node);
node_name = ixmlNode_getNodeName(node); node_name = ixmlNode_getNodeName(node);
if( node_name == NULL ) { if (node_name == NULL)
return UPNP_E_OUTOF_MEMORY; return UPNP_E_OUTOF_MEMORY;
} if (strcmp(name, node_name) == 0)
if( strcmp( name, node_name ) == 0 ) {
ret_code = 0; ret_code = 0;
} else if( matchstr( ( char * )node_name, strlen( node_name ), else if (matchstr((char *)node_name, strlen(node_name),
"%s:%s%0", &dummy, &nameptr) == PARSE_OK && "%s:%s%0", &dummy, &nameptr) == PARSE_OK &&
strcmp( nameptr.buf, name ) == 0 ) { strcmp(nameptr.buf, name) == 0)
ret_code = 0; ret_code = 0;
} else { else
ret_code = 1; // names are not the same /* names are not the same */
} ret_code = 1;
return ret_code; return ret_code;
} }
/**************************************************************************** /*!
* Function : dom_find_node * \brief Goes thru each child of 'start_node' looking for a node having
* the name 'node_name'.
* *
* Parameters : * \return UPNP_E_SUCCESS if successful else returns appropriate error.
* IN char* node_name : name of the node */
* IN IXML_Node *start_node : complete xml node static int dom_find_node(
* OUT IXML_Node ** matching_node : matched node /* [in] name of the node. */
* const char *node_name,
* Description : This function goes thru each child of 'start_node' /* [in] complete xml node. */
* looking for a node having the name 'node_name'. IXML_Node *start_node,
* /* [out] matched node. */
* Return : int IXML_Node **matching_node)
* return UPNP_E_SUCCESS if successful else returns appropriate error
*
* Note :
****************************************************************************/
static int
dom_find_node( IN char *node_name,
IN IXML_Node * start_node,
OUT IXML_Node ** matching_node )
{ {
IXML_Node *node; IXML_Node *node;
// invalid args /* invalid args */
if( node_name == NULL || start_node == NULL ) { if (!node_name || !start_node)
return UPNP_E_NOT_FOUND; return UPNP_E_NOT_FOUND;
}
node = ixmlNode_getFirstChild(start_node); node = ixmlNode_getFirstChild(start_node);
while (node != NULL) { while (node != NULL) {
// match name /* match name */
if (dom_cmp_name(node_name, node) == 0) { if (dom_cmp_name(node_name, node) == 0) {
*matching_node = node; *matching_node = node;
return UPNP_E_SUCCESS; return UPNP_E_SUCCESS;
} }
// free and next node /* free and next node */
node = ixmlNode_getNextSibling( node ); // next node node = ixmlNode_getNextSibling(node);
} }
return UPNP_E_NOT_FOUND; return UPNP_E_NOT_FOUND;
} }
/**************************************************************************** /*!
* Function : dom_find_deep_node * \brief Searches for the node specifed by the last name in the 'name' array.
* *
* Parameters : * \return UPNP_E_SUCCESS if successful, else returns appropriate error.
* IN char* names[] : array of names */
* IN int num_names : size of array static int dom_find_deep_node(
* IN IXML_Node *start_node : Node from where it should should be /* [in] array of names. */
* searched const char *names[],
* OUT IXML_Node ** matching_node : Node that matches the last name /* [in] size of array. */
* of the array int num_names,
* /* [in] Node from where it should should be searched. */
* Description : This function searches for the node specifed by the last IXML_Node *start_node,
* name in the 'name' array. /* [out] Node that matches the last name of the array. */
* IXML_Node **matching_node)
* Return : int
* return UPNP_E_SUCCESS if successful else returns appropriate error
* Note :
****************************************************************************/
static int
dom_find_deep_node( IN char *names[],
IN int num_names,
IN IXML_Node * start_node,
OUT IXML_Node ** matching_node )
{ {
int i; int i;
IXML_Node *node; IXML_Node *node;
@@ -181,22 +154,19 @@ dom_find_deep_node( IN char *names[],
return UPNP_E_SUCCESS; return UPNP_E_SUCCESS;
} }
} }
for (i = 1; i < num_names; i++) { for (i = 1; i < num_names; i++) {
if( dom_find_node( names[i], node, &match_node ) != if (dom_find_node(names[i], node, &match_node) != UPNP_E_SUCCESS)
UPNP_E_SUCCESS ) {
return UPNP_E_NOT_FOUND; return UPNP_E_NOT_FOUND;
}
if (i == num_names - 1) { if (i == num_names - 1) {
*matching_node = match_node; *matching_node = match_node;
return UPNP_E_SUCCESS; return UPNP_E_SUCCESS;
} }
/* try again */
node = match_node; // try again node = match_node;
} }
return UPNP_E_NOT_FOUND; // this line not reached /* this line not reached */
return UPNP_E_NOT_FOUND;
} }
/**************************************************************************** /****************************************************************************
@@ -240,7 +210,7 @@ get_node_value( IN IXML_Node * node )
* control URL * control URL
* *
* Return : int * Return : int
* returns 0 on sucess; -1 on error * returns 0 on success; -1 on error
* *
* Note : * Note :
****************************************************************************/ ****************************************************************************/
@@ -253,7 +223,7 @@ get_host_and_path( IN char *ctrl_url,
if( parse_uri( ctrl_url, strlen( ctrl_url ), url ) != HTTP_SUCCESS ) { if( parse_uri( ctrl_url, strlen( ctrl_url ), url ) != HTTP_SUCCESS ) {
return -1; return -1;
} }
// This is done to ensure that the buffer is kept const /* This is done to ensure that the buffer is kept const */
((memptr *)host)->buf = (char *)url->hostport.text.buff; ((memptr *)host)->buf = (char *)url->hostport.text.buff;
((memptr *)host)->length = url->hostport.text.size; ((memptr *)host)->length = url->hostport.text.size;
@@ -290,39 +260,30 @@ get_action_name( IN char *action,
return ret_code == PARSE_OK ? 0 : -1; return ret_code == PARSE_OK ? 0 : -1;
} }
/**************************************************************************** /*!
* Function : add_man_header * \brief Adds "MAN" field in the HTTP header.
* *
* Parameters : * \return 0 on success, UPNP_E_OUTOFMEMORY on error.
* INOUT membuffer* headers : HTTP header */
* static UPNP_INLINE int add_man_header(
* Description : This function adds "MAN" field in the HTTP header /* [in,out] HTTP header. */
* membuffer *headers)
* Return : int
* returns 0 on success; UPNP_E_OUTOFMEMORY on error
*
* Note :
****************************************************************************/
static UPNP_INLINE int
add_man_header( INOUT membuffer * headers )
{ {
size_t n;
char *soap_action_hdr; char *soap_action_hdr;
char *man_hdr = "MAN: \"http://schemas.xmlsoap.org/soap/envelope/\"; " const char *man_hdr =
"ns=01\r\n01-"; "MAN: \"http://schemas.xmlsoap.org/soap/envelope/\"; ns=01\r\n01-";
// change POST to M-POST /* change POST to M-POST */
if( membuffer_insert( headers, "M-", 2, 0 ) != 0 ) { if (membuffer_insert(headers, "M-", 2, 0) != 0)
return UPNP_E_OUTOF_MEMORY; return UPNP_E_OUTOF_MEMORY;
}
soap_action_hdr = strstr(headers->buf, "SOAPACTION:"); soap_action_hdr = strstr(headers->buf, "SOAPACTION:");
assert( soap_action_hdr != NULL ); // can't fail /* can't fail */
assert(soap_action_hdr != NULL);
// insert MAN header /* insert MAN header */
if( membuffer_insert( headers, man_hdr, strlen( man_hdr ), n = (size_t)(soap_action_hdr - headers->buf);
soap_action_hdr - headers->buf ) != 0 ) { if (membuffer_insert(headers, man_hdr, strlen(man_hdr), n))
return UPNP_E_OUTOF_MEMORY; return UPNP_E_OUTOF_MEMORY;
}
return 0; return 0;
} }
@@ -357,16 +318,16 @@ soap_request_and_response( IN membuffer * request,
httpmsg_destroy( &response->msg ); httpmsg_destroy( &response->msg );
return ret_code; return ret_code;
} }
// method-not-allowed error /* method-not-allowed error */
if( response->msg.status_code == HTTP_METHOD_NOT_ALLOWED ) { if( response->msg.status_code == HTTP_METHOD_NOT_ALLOWED ) {
ret_code = add_man_header( request ); // change to M-POST msg ret_code = add_man_header( request ); /* change to M-POST msg */
if( ret_code != 0 ) { if( ret_code != 0 ) {
return ret_code; return ret_code;
} }
httpmsg_destroy( &response->msg ); // about to reuse response httpmsg_destroy( &response->msg ); /* about to reuse response */
// try again /* try again */
ret_code = http_RequestAndResponse( destination_url, request->buf, ret_code = http_RequestAndResponse( destination_url, request->buf,
request->length, request->length,
HTTPMETHOD_MPOST, HTTPMETHOD_MPOST,
@@ -418,40 +379,26 @@ get_response_value( IN http_message_t * hmsg,
char *node_str = NULL; char *node_str = NULL;
const char *temp_str = NULL; const char *temp_str = NULL;
DOMString error_node_str = NULL; DOMString error_node_str = NULL;
int err_code; int err_code = UPNP_E_BAD_RESPONSE; /* default error */ ;
xboolean done = FALSE; int done = FALSE;
char *names[5]; const char *names[5];
const DOMString nodeValue; const DOMString nodeValue;
err_code = UPNP_E_BAD_RESPONSE; // default error /* only 200 and 500 status codes are relevant */
// only 200 and 500 status codes are relevant
if ((hmsg->status_code != HTTP_OK && if ((hmsg->status_code != HTTP_OK &&
hmsg->status_code != HTTP_INTERNAL_SERVER_ERROR) || hmsg->status_code != HTTP_INTERNAL_SERVER_ERROR) ||
!has_xml_content_type( hmsg ) ) { !has_xml_content_type(hmsg))
goto error_handler; goto error_handler;
} if (ixmlParseBufferEx(hmsg->entity.buf, &doc) != IXML_SUCCESS)
if( ixmlParseBufferEx( hmsg->entity.buf, &doc ) != IXML_SUCCESS ) {
goto error_handler; goto error_handler;
}
root_node = ixmlNode_getFirstChild((IXML_Node *) doc); root_node = ixmlNode_getFirstChild((IXML_Node *) doc);
if( root_node == NULL ) { if (root_node == NULL)
goto error_handler; goto error_handler;
}
if (code == SOAP_ACTION_RESP) { if (code == SOAP_ACTION_RESP) {
// /* try reading soap action response */
// try reading soap action response
//
assert(action_value != NULL); assert(action_value != NULL);
*action_value = NULL; *action_value = NULL;
names[0] = "Envelope"; names[0] = "Envelope";
names[1] = "Body"; names[1] = "Body";
names[2] = name; names[2] = name;
@@ -462,22 +409,20 @@ get_response_value( IN http_message_t * hmsg,
err_code = UPNP_E_OUTOF_MEMORY; err_code = UPNP_E_OUTOF_MEMORY;
goto error_handler; goto error_handler;
} }
if (ixmlParseBufferEx(node_str, if (ixmlParseBufferEx(node_str,
( IXML_Document ** ) action_value ) != (IXML_Document **) action_value)
IXML_SUCCESS ) { != IXML_SUCCESS) {
err_code = UPNP_E_BAD_RESPONSE; err_code = UPNP_E_BAD_RESPONSE;
goto error_handler; goto error_handler;
} }
err_code = SOAP_ACTION_RESP; err_code = SOAP_ACTION_RESP;
done = TRUE; done = TRUE;
} }
} else if (code == SOAP_VAR_RESP) { } else if (code == SOAP_VAR_RESP) {
// try reading var response /* try reading var response */
assert(str_value != NULL); assert(str_value != NULL);
*str_value = NULL;
*str_value = NULL;
names[0] = "Envelope"; names[0] = "Envelope";
names[1] = "Body"; names[1] = "Body";
names[2] = "QueryStateVariableResponse"; names[2] = "QueryStateVariableResponse";
@@ -485,52 +430,40 @@ get_response_value( IN http_message_t * hmsg,
if (dom_find_deep_node(names, 4, root_node, &node) if (dom_find_deep_node(names, 4, root_node, &node)
== UPNP_E_SUCCESS) { == UPNP_E_SUCCESS) {
nodeValue = get_node_value(node); nodeValue = get_node_value(node);
if( nodeValue == NULL ) { if (nodeValue == NULL)
goto error_handler; goto error_handler;
}
*str_value = ixmlCloneDOMString(nodeValue); *str_value = ixmlCloneDOMString(nodeValue);
err_code = SOAP_VAR_RESP; err_code = SOAP_VAR_RESP;
done = TRUE; done = TRUE;
} }
} }
if (!done) { if (!done) {
// not action or var resp; read error code and description /* not action or var resp; read error code and description */
*str_value = NULL; *str_value = NULL;
names[0] = "Envelope"; names[0] = "Envelope";
names[1] = "Body"; names[1] = "Body";
names[2] = "Fault"; names[2] = "Fault";
names[3] = "detail"; names[3] = "detail";
names[4] = "UPnPError"; names[4] = "UPnPError";
if( dom_find_deep_node( names, 5, root_node, &error_node ) if (dom_find_deep_node(names, 5, root_node, &error_node) !=
!= UPNP_E_SUCCESS ) { UPNP_E_SUCCESS)
goto error_handler; goto error_handler;
} if (dom_find_node("errorCode", error_node, &node) !=
UPNP_E_SUCCESS)
if( dom_find_node( "errorCode", error_node, &node )
!= UPNP_E_SUCCESS ) {
goto error_handler; goto error_handler;
}
temp_str = get_node_value(node); temp_str = get_node_value(node);
if( temp_str == NULL ) { if (!temp_str)
goto error_handler; goto error_handler;
}
*upnp_error_code = atoi(temp_str); *upnp_error_code = atoi(temp_str);
if (*upnp_error_code < 400) { if (*upnp_error_code < 400) {
err_code = *upnp_error_code; err_code = *upnp_error_code;
goto error_handler; // bad SOAP error code goto error_handler; /* bad SOAP error code */
} }
if (code == SOAP_VAR_RESP) { if (code == SOAP_VAR_RESP) {
if (dom_find_node("errorDescription", error_node, &node) if (dom_find_node("errorDescription", error_node, &node)
!= UPNP_E_SUCCESS) { != UPNP_E_SUCCESS) {
goto error_handler; goto error_handler;
} }
nodeValue = get_node_value(node); nodeValue = get_node_value(node);
if (nodeValue == NULL) { if (nodeValue == NULL) {
goto error_handler; goto error_handler;
@@ -540,18 +473,15 @@ get_response_value( IN http_message_t * hmsg,
goto error_handler; goto error_handler;
} }
err_code = SOAP_VAR_RESP_ERROR; err_code = SOAP_VAR_RESP_ERROR;
} } else if (code == SOAP_ACTION_RESP) {
else if( code == SOAP_ACTION_RESP ) {
error_node_str = ixmlPrintNode(error_node); error_node_str = ixmlPrintNode(error_node);
if (error_node_str == NULL) { if (error_node_str == NULL) {
err_code = UPNP_E_OUTOF_MEMORY; err_code = UPNP_E_OUTOF_MEMORY;
goto error_handler; goto error_handler;
} }
if (ixmlParseBufferEx(error_node_str, if (ixmlParseBufferEx(error_node_str,
( IXML_Document ** ) action_value ) != (IXML_Document **) action_value)
IXML_SUCCESS ) { != IXML_SUCCESS) {
err_code = UPNP_E_BAD_RESPONSE; err_code = UPNP_E_BAD_RESPONSE;
goto error_handler; goto error_handler;
@@ -561,7 +491,6 @@ get_response_value( IN http_message_t * hmsg,
} }
error_handler: error_handler:
ixmlDocument_free(doc); ixmlDocument_free(doc);
ixmlFreeDOMString(node_str); ixmlFreeDOMString(node_str);
ixmlFreeDOMString(error_node_str); ixmlFreeDOMString(error_node_str);
@@ -601,42 +530,42 @@ SoapSendAction( IN char *action_url,
uri_type url; uri_type url;
int upnp_error_code; int upnp_error_code;
char *upnp_error_str; char *upnp_error_str;
xboolean got_response = FALSE; int got_response = FALSE;
off_t content_length; off_t content_length;
char *xml_start = const char *xml_start =
"<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/\">\r\n" "s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\r\n"
"<s:Body>"; "<s:Body>";
char *xml_end = const char *xml_end =
"</s:Body>\r\n" "</s:Body>\r\n"
"</s:Envelope>\r\n\r\n"; "</s:Envelope>\r\n\r\n";
size_t xml_start_len; size_t xml_start_len;
size_t xml_end_len; size_t xml_end_len;
size_t action_str_len; size_t action_str_len;
*response_node = NULL; // init *response_node = NULL; /* init */
err_code = UPNP_E_OUTOF_MEMORY; // default error err_code = UPNP_E_OUTOF_MEMORY; /* default error */
UpnpPrintf( UPNP_INFO, SOAP, __FILE__, __LINE__, UpnpPrintf( UPNP_INFO, SOAP, __FILE__, __LINE__,
"Inside SoapSendAction():" ); "Inside SoapSendAction():" );
// init /* init */
membuffer_init( &request ); membuffer_init( &request );
membuffer_init( &responsename ); membuffer_init( &responsename );
// print action /* print action */
action_str = ixmlPrintNode( ( IXML_Node * ) action_node ); action_str = ixmlPrintNode( ( IXML_Node * ) action_node );
if( action_str == NULL ) { if( action_str == NULL ) {
goto error_handler; goto error_handler;
} }
// get action name /* get action name */
if( get_action_name( action_str, &name ) != 0 ) { if( get_action_name( action_str, &name ) != 0 ) {
err_code = UPNP_E_INVALID_ACTION; err_code = UPNP_E_INVALID_ACTION;
goto error_handler; goto error_handler;
} }
// parse url /* parse url */
if( http_FixStrUrl( action_url, strlen( action_url ), &url ) != 0 ) { if( http_FixStrUrl( action_url, strlen( action_url ), &url ) != 0 ) {
err_code = UPNP_E_INVALID_URL; err_code = UPNP_E_INVALID_URL;
goto error_handler; goto error_handler;
@@ -653,9 +582,9 @@ SoapSendAction( IN char *action_url,
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;
content_length = xml_start_len + action_str_len + xml_end_len; content_length = (off_t)(xml_start_len + action_str_len + xml_end_len);
if (http_MakeMessage( if (http_MakeMessage(
&request, 1, 1, &request, 1, 1,
"q" "N" "s" "sssbsc" "Uc" "b" "b" "b", "q" "N" "s" "sssbsc" "Uc" "b" "b" "b",
@@ -680,7 +609,7 @@ SoapSendAction( IN char *action_url,
membuffer_append_str( &responsename, "Response" ) != 0 ) { membuffer_append_str( &responsename, "Response" ) != 0 ) {
goto error_handler; goto error_handler;
} }
// get action node from the response /* get action node from the response */
ret_code = get_response_value( &response.msg, SOAP_ACTION_RESP, ret_code = get_response_value( &response.msg, SOAP_ACTION_RESP,
responsename.buf, &upnp_error_code, responsename.buf, &upnp_error_code,
( IXML_Node ** ) response_node, ( IXML_Node ** ) response_node,
@@ -725,8 +654,8 @@ error_handler:
* returns UPNP_E_SUCCESS if successful else returns appropriate error * returns UPNP_E_SUCCESS if successful else returns appropriate error
* Note : * Note :
****************************************************************************/ ****************************************************************************/
int int SoapSendActionEx(
SoapSendActionEx( IN char *action_url, IN char *action_url,
IN char *service_type, IN char *service_type,
IN IXML_Document * header, IN IXML_Document * header,
IN IXML_Document * action_node, IN IXML_Document * action_node,
@@ -743,19 +672,18 @@ SoapSendActionEx( IN char *action_url,
uri_type url; uri_type url;
int upnp_error_code; int upnp_error_code;
char *upnp_error_str; char *upnp_error_str;
xboolean got_response = FALSE; int got_response = FALSE;
const char *xml_start =
char *xml_start =
"<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/\">\r\n"; "s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\r\n";
char *xml_header_start = const char *xml_header_start =
"<s:Header>\r\n"; "<s:Header>\r\n";
char *xml_header_end = const char *xml_header_end =
"</s:Header>\r\n"; "</s:Header>\r\n";
char *xml_body_start = const char *xml_body_start =
"<s:Body>"; "<s:Body>";
char *xml_end = const char *xml_end =
"</s:Body>\r\n" "</s:Body>\r\n"
"</s:Envelope>\r\n"; "</s:Envelope>\r\n";
size_t xml_start_len; size_t xml_start_len;
@@ -767,32 +695,32 @@ SoapSendActionEx( IN char *action_url,
size_t xml_end_len; size_t xml_end_len;
off_t content_length; off_t content_length;
*response_node = NULL; // init *response_node = NULL; /* init */
err_code = UPNP_E_OUTOF_MEMORY; // default error err_code = UPNP_E_OUTOF_MEMORY; /* default error */
UpnpPrintf( UPNP_INFO, SOAP, __FILE__, __LINE__, UpnpPrintf( UPNP_INFO, SOAP, __FILE__, __LINE__,
"Inside SoapSendActionEx():" ); "Inside SoapSendActionEx():" );
// init /* init */
membuffer_init( &request ); membuffer_init( &request );
membuffer_init( &responsename ); membuffer_init( &responsename );
// header string /* header string */
xml_header_str = ixmlPrintNode( ( IXML_Node * ) header ); xml_header_str = ixmlPrintNode( ( IXML_Node * ) header );
if( xml_header_str == NULL ) { if( xml_header_str == NULL ) {
goto error_handler; goto error_handler;
} }
// print action /* print action */
action_str = ixmlPrintNode( ( IXML_Node * ) action_node ); action_str = ixmlPrintNode( ( IXML_Node * ) action_node );
if( action_str == NULL ) { if( action_str == NULL ) {
goto error_handler; goto error_handler;
} }
// get action name /* get action name */
if( get_action_name( action_str, &name ) != 0 ) { if( get_action_name( action_str, &name ) != 0 ) {
err_code = UPNP_E_INVALID_ACTION; err_code = UPNP_E_INVALID_ACTION;
goto error_handler; goto error_handler;
} }
// parse url /* parse url */
if( http_FixStrUrl( action_url, strlen( action_url ), &url ) != 0 ) { if( http_FixStrUrl( action_url, strlen( action_url ), &url ) != 0 ) {
err_code = UPNP_E_INVALID_URL; err_code = UPNP_E_INVALID_URL;
goto error_handler; goto error_handler;
@@ -814,12 +742,11 @@ SoapSendActionEx( IN char *action_url,
xml_header_end_len = strlen( xml_header_end ); xml_header_end_len = strlen( xml_header_end );
xml_header_str_len = strlen( xml_header_str ); xml_header_str_len = strlen( xml_header_str );
// make request msg /* make request msg */
request.size_inc = 50; request.size_inc = 50;
content_length = content_length = (off_t)(xml_start_len + xml_header_start_len +
xml_start_len + xml_header_str_len + xml_header_end_len +
xml_header_start_len + xml_header_str_len + xml_header_end_len + xml_body_start_len + action_str_len + xml_end_len);
xml_body_start_len + action_str_len + xml_end_len;
if (http_MakeMessage( if (http_MakeMessage(
&request, 1, 1, &request, 1, 1,
"q" "N" "s" "sssbsc" "Uc" "b" "b" "b" "b" "b" "b" "b", "q" "N" "s" "sssbsc" "Uc" "b" "b" "b" "b" "b" "b" "b",
@@ -848,7 +775,7 @@ SoapSendActionEx( IN char *action_url,
membuffer_append_str( &responsename, "Response" ) != 0 ) { membuffer_append_str( &responsename, "Response" ) != 0 ) {
goto error_handler; goto error_handler;
} }
// get action node from the response /* get action node from the response */
ret_code = get_response_value( &response.msg, SOAP_ACTION_RESP, ret_code = get_response_value( &response.msg, SOAP_ACTION_RESP,
responsename.buf, &upnp_error_code, responsename.buf, &upnp_error_code,
( IXML_Node ** ) response_node, ( IXML_Node ** ) response_node,
@@ -896,40 +823,37 @@ SoapGetServiceVarStatus( IN char *action_url,
IN char *var_name, IN char *var_name,
OUT char **var_value ) OUT char **var_value )
{ {
const memptr host; // value for HOST header const memptr host; /* value for HOST header */
const memptr path; // ctrl path in first line in msg const memptr path; /* ctrl path in first line in msg */
uri_type url; uri_type url;
membuffer request; membuffer request;
int ret_code; int ret_code;
http_parser_t response; http_parser_t response;
int upnp_error_code; int upnp_error_code;
off_t content_length; off_t content_length;
char *xml_start = const char *xml_start =
"<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/\">\r\n" "s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\r\n"
"<s:Body>\r\n" "<s:Body>\r\n"
"<u:QueryStateVariable xmlns:u=\"urn:schemas-upnp-org:control-1-0\">\r\n" "<u:QueryStateVariable xmlns:u=\"urn:schemas-upnp-org:control-1-0\">\r\n"
"<u:varName>"; "<u:varName>";
const char *xml_end =
char *xml_end =
"</u:varName>\r\n" "</u:varName>\r\n"
"</u:QueryStateVariable>\r\n" "</u:QueryStateVariable>\r\n"
"</s:Body>\r\n" "</s:Body>\r\n"
"</s:Envelope>\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 */
membuffer_init( &request ); membuffer_init( &request );
/* get host hdr and url path */
// get host hdr and url path
if( get_host_and_path( action_url, &host, &path, &url ) == -1 ) { if( get_host_and_path( action_url, &host, &path, &url ) == -1 ) {
return UPNP_E_INVALID_URL; return UPNP_E_INVALID_URL;
} }
// make headers /* make headers */
request.size_inc = 50; request.size_inc = 50;
content_length = strlen( xml_start ) + strlen( var_name ) + strlen( xml_end ); content_length = (off_t)(strlen(xml_start) + strlen(var_name) +
strlen(xml_end));
if (http_MakeMessage( if (http_MakeMessage(
&request, 1, 1, &request, 1, 1,
"Q" "sbc" "N" "s" "sc" "Ucc" "sss", "Q" "sbc" "N" "s" "sc" "Ucc" "sss",
@@ -941,18 +865,16 @@ SoapGetServiceVarStatus( IN char *action_url,
xml_start, var_name, xml_end ) != 0 ) { 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 */
ret_code = soap_request_and_response( &request, &url, &response ); ret_code = soap_request_and_response( &request, &url, &response );
membuffer_destroy( &request ); membuffer_destroy( &request );
if( ret_code != UPNP_E_SUCCESS ) { if( ret_code != UPNP_E_SUCCESS ) {
return ret_code; return ret_code;
} }
// get variable value from the response /* get variable value from the response */
ret_code = get_response_value( &response.msg, SOAP_VAR_RESP, NULL, ret_code = get_response_value( &response.msg, SOAP_VAR_RESP, NULL,
&upnp_error_code, NULL, var_value ); &upnp_error_code, NULL, var_value );
httpmsg_destroy( &response.msg ); httpmsg_destroy( &response.msg );
if( ret_code == SOAP_VAR_RESP ) { if( ret_code == SOAP_VAR_RESP ) {
return UPNP_E_SUCCESS; return UPNP_E_SUCCESS;
} else if( ret_code == SOAP_VAR_RESP_ERROR ) { } else if( ret_code == SOAP_VAR_RESP_ERROR ) {
@@ -962,5 +884,6 @@ SoapGetServiceVarStatus( IN char *action_url,
} }
} }
#endif // EXCLUDE_SOAP #endif /* EXCLUDE_SOAP */
#endif // INCLUDE_CLIENT_APIS #endif /* INCLUDE_CLIENT_APIS */

File diff suppressed because it is too large Load Diff

View File

@@ -29,17 +29,13 @@
* *
**************************************************************************/ **************************************************************************/
#include "config.h" #include "config.h"
#include "upnputil.h"
#include "util.h"
#ifdef INCLUDE_CLIENT_APIS #ifdef INCLUDE_CLIENT_APIS
#if EXCLUDE_SSDP == 0 #if EXCLUDE_SSDP == 0
#include "httpparser.h" #include "httpparser.h"
#include "httpreadwrite.h" #include "httpreadwrite.h"
/*#include "ssdp_ResultData.h"*/ /*#include "ssdp_ResultData.h"*/
@@ -50,15 +46,12 @@
#include "UpnpInet.h" #include "UpnpInet.h"
#include "ThreadPool.h" #include "ThreadPool.h"
#include <stdio.h> #include <stdio.h>
#ifdef WIN32 #ifdef WIN32
#include <string.h> #include <string.h>
#endif /* WIN32 */ #endif /* WIN32 */
/************************************************************************ /************************************************************************
* Function: send_search_result * Function: send_search_result
* *
@@ -88,7 +81,7 @@ void send_search_result(IN void *data)
* SSDP message from the device * SSDP message from the device
* IN struct sockaddr *dest_addr: * IN struct sockaddr *dest_addr:
* Address of the device * Address of the device
* IN xboolean timeout: * IN int timeout:
* timeout kept by the control point while * timeout kept by the control point while
* sending search message * sending search message
* IN void* cookie: * IN void* cookie:
@@ -107,18 +100,21 @@ void send_search_result(IN void *data)
void ssdp_handle_ctrlpt_msg( void ssdp_handle_ctrlpt_msg(
IN http_message_t *hmsg, IN http_message_t *hmsg,
IN struct sockaddr *dest_addr, IN struct sockaddr *dest_addr,
IN xboolean timeout, // only in search reply /* only in search reply */
IN void *cookie) // only in search reply IN int timeout,
/* only in search reply */
IN void *cookie)
{ {
int handle; int handle;
struct Handle_Info *ctrlpt_info = NULL; struct Handle_Info *ctrlpt_info = NULL;
memptr hdr_value; memptr hdr_value;
xboolean is_byebye; // byebye or alive /* byebye or alive */
int is_byebye;
struct Upnp_Discovery param; struct Upnp_Discovery param;
SsdpEvent event; SsdpEvent event;
xboolean nt_found; int nt_found;
xboolean usn_found; int usn_found;
xboolean st_found; int st_found;
char save_char; char save_char;
Upnp_EventType event_type; Upnp_EventType event_type;
Upnp_FunPtr ctrlpt_callback; Upnp_FunPtr ctrlpt_callback;
@@ -129,81 +125,69 @@ void ssdp_handle_ctrlpt_msg(
ResultData *threadData = NULL; ResultData *threadData = NULL;
ThreadPoolJob job; ThreadPoolJob job;
// we are assuming that there can be only one client supported at a time /* we are assuming that there can be only one client supported at a time */
HandleReadLock(); HandleReadLock();
if (GetClientHandleInfo(&handle, &ctrlpt_info) != HND_CLIENT) { if (GetClientHandleInfo(&handle, &ctrlpt_info) != HND_CLIENT) {
HandleUnlock(); HandleUnlock();
return; return;
} }
// copy /* copy */
ctrlpt_callback = ctrlpt_info->Callback; ctrlpt_callback = ctrlpt_info->Callback;
ctrlpt_cookie = ctrlpt_info->Cookie; ctrlpt_cookie = ctrlpt_info->Cookie;
HandleUnlock(); HandleUnlock();
/* search timeout */
// search timeout
if (timeout) { if (timeout) {
ctrlpt_callback(UPNP_DISCOVERY_SEARCH_TIMEOUT, NULL, cookie); ctrlpt_callback(UPNP_DISCOVERY_SEARCH_TIMEOUT, NULL, cookie);
return; return;
} }
param.ErrCode = UPNP_E_SUCCESS; param.ErrCode = UPNP_E_SUCCESS;
/* MAX-AGE, assume error */
// MAX-AGE
// assume error
param.Expires = -1; param.Expires = -1;
if (httpmsg_find_hdr(hmsg, HDR_CACHE_CONTROL, &hdr_value) != NULL) { if (httpmsg_find_hdr(hmsg, HDR_CACHE_CONTROL, &hdr_value) != NULL) {
if (matchstr(hdr_value.buf, hdr_value.length, if (matchstr(hdr_value.buf, hdr_value.length,
"%imax-age = %d%0", &param.Expires) != PARSE_OK) "%imax-age = %d%0", &param.Expires) != PARSE_OK)
return; return;
} }
/* DATE */
// DATE
param.Date[0] = '\0'; param.Date[0] = '\0';
if (httpmsg_find_hdr(hmsg, HDR_DATE, &hdr_value) != NULL) { if (httpmsg_find_hdr(hmsg, HDR_DATE, &hdr_value) != NULL) {
linecopylen(param.Date, hdr_value.buf, hdr_value.length); linecopylen(param.Date, hdr_value.buf, hdr_value.length);
} }
/* dest addr */
// dest addr
memcpy(&param.DestAddr, dest_addr, sizeof(struct sockaddr_in)); memcpy(&param.DestAddr, dest_addr, sizeof(struct sockaddr_in));
/* EXT */
// EXT
param.Ext[0] = '\0'; param.Ext[0] = '\0';
if (httpmsg_find_hdr(hmsg, HDR_EXT, &hdr_value) != NULL) { if (httpmsg_find_hdr(hmsg, HDR_EXT, &hdr_value) != NULL) {
linecopylen(param.Ext, hdr_value.buf, hdr_value.length); linecopylen(param.Ext, hdr_value.buf, hdr_value.length);
} }
// LOCATION /* LOCATION */
param.Location[0] = '\0'; param.Location[0] = '\0';
if (httpmsg_find_hdr(hmsg, HDR_LOCATION, &hdr_value) != NULL) { if (httpmsg_find_hdr(hmsg, HDR_LOCATION, &hdr_value) != NULL) {
linecopylen(param.Location, hdr_value.buf, hdr_value.length); linecopylen(param.Location, hdr_value.buf, hdr_value.length);
} }
// SERVER / USER-AGENT /* SERVER / USER-AGENT */
param.Os[0] = '\0'; param.Os[0] = '\0';
if (httpmsg_find_hdr(hmsg, HDR_SERVER, &hdr_value) != NULL || if (httpmsg_find_hdr(hmsg, HDR_SERVER, &hdr_value) != NULL ||
httpmsg_find_hdr(hmsg, HDR_USER_AGENT, &hdr_value) != NULL) { httpmsg_find_hdr(hmsg, HDR_USER_AGENT, &hdr_value) != NULL) {
linecopylen(param.Os, hdr_value.buf, hdr_value.length); linecopylen(param.Os, hdr_value.buf, hdr_value.length);
} }
// clear everything /* clear everything */
param.DeviceId[0] = '\0'; param.DeviceId[0] = '\0';
param.DeviceType[0] = '\0'; param.DeviceType[0] = '\0';
param.ServiceType[0] = '\0'; param.ServiceType[0] = '\0';
/* not used; version is in ServiceType */
param.ServiceVer[0] = '\0'; // not used; version is in ServiceType param.ServiceVer[0] = '\0';
event.UDN[0] = '\0'; event.UDN[0] = '\0';
event.DeviceType[0] = '\0'; event.DeviceType[0] = '\0';
event.ServiceType[0] = '\0'; event.ServiceType[0] = '\0';
nt_found = FALSE; nt_found = FALSE;
if (httpmsg_find_hdr(hmsg, HDR_NT, &hdr_value) != NULL) { if (httpmsg_find_hdr(hmsg, HDR_NT, &hdr_value) != NULL) {
save_char = hdr_value.buf[hdr_value.length]; save_char = hdr_value.buf[hdr_value.length];
hdr_value.buf[hdr_value.length] = '\0'; hdr_value.buf[hdr_value.length] = '\0';
nt_found = (ssdp_request_type(hdr_value.buf, &event) == 0); nt_found = (ssdp_request_type(hdr_value.buf, &event) == 0);
hdr_value.buf[hdr_value.length] = save_char; hdr_value.buf[hdr_value.length] = save_char;
} }
usn_found = FALSE; usn_found = FALSE;
if (httpmsg_find_hdr(hmsg, HDR_USN, &hdr_value) != NULL) { if (httpmsg_find_hdr(hmsg, HDR_USN, &hdr_value) != NULL) {
save_char = hdr_value.buf[hdr_value.length]; save_char = hdr_value.buf[hdr_value.length];
@@ -211,131 +195,132 @@ void ssdp_handle_ctrlpt_msg(
usn_found = (unique_service_name(hdr_value.buf, &event) == 0); usn_found = (unique_service_name(hdr_value.buf, &event) == 0);
hdr_value.buf[hdr_value.length] = save_char; hdr_value.buf[hdr_value.length] = save_char;
} }
if (nt_found || usn_found) { if (nt_found || usn_found) {
strcpy(param.DeviceId, event.UDN); strcpy(param.DeviceId, event.UDN);
strcpy(param.DeviceType, event.DeviceType); strcpy(param.DeviceType, event.DeviceType);
strcpy(param.ServiceType, event.ServiceType); strcpy(param.ServiceType, event.ServiceType);
} }
/* ADVERT. OR BYEBYE */
// ADVERT. OR BYEBYE
if (hmsg->is_request) { if (hmsg->is_request) {
// use NTS hdr to determine advert., or byebye /* use NTS hdr to determine advert., or byebye */
if (httpmsg_find_hdr(hmsg, HDR_NTS, &hdr_value) == NULL) { if (httpmsg_find_hdr(hmsg, HDR_NTS, &hdr_value) == NULL) {
return; // error; NTS header not found return; /* error; NTS header not found */
} }
if (memptr_cmp(&hdr_value, "ssdp:alive") == 0) { if (memptr_cmp(&hdr_value, "ssdp:alive") == 0) {
is_byebye = FALSE; is_byebye = FALSE;
} else if (memptr_cmp(&hdr_value, "ssdp:byebye") == 0) { } else if (memptr_cmp(&hdr_value, "ssdp:byebye") == 0) {
is_byebye = TRUE; is_byebye = TRUE;
} else { } else {
return; // bad value return; /* bad value */
} }
if (is_byebye) { if (is_byebye) {
// check device byebye /* check device byebye */
if (!nt_found || !usn_found) { if (!nt_found || !usn_found) {
return; // bad byebye return; /* bad byebye */
} }
event_type = UPNP_DISCOVERY_ADVERTISEMENT_BYEBYE; event_type = UPNP_DISCOVERY_ADVERTISEMENT_BYEBYE;
} else { } else {
// check advertisement /* check advertisement.
// .Expires is valid if positive. This is for testing * Expires is valid if positive. This is for testing
// only. Expires should be greater than 1800 (30 mins) * only. Expires should be greater than 1800 (30 mins) */
if (!nt_found || if (!nt_found ||
!usn_found || !usn_found ||
strlen(param.Location) == 0 || param.Expires <= 0) { strlen(param.Location) == 0 || param.Expires <= 0) {
return; // bad advertisement return; /* bad advertisement */
} }
event_type = UPNP_DISCOVERY_ADVERTISEMENT_ALIVE; event_type = UPNP_DISCOVERY_ADVERTISEMENT_ALIVE;
} }
/* call callback */
// call callback
ctrlpt_callback(event_type, &param, ctrlpt_cookie); ctrlpt_callback(event_type, &param, ctrlpt_cookie);
} else {
} else // reply (to a SEARCH) /* reply (to a SEARCH) */
{ /* only checking to see if there is a valid ST header */
// only checking to see if there is a valid ST header
st_found = FALSE; st_found = FALSE;
if (httpmsg_find_hdr(hmsg, HDR_ST, &hdr_value) != NULL) { if (httpmsg_find_hdr(hmsg, HDR_ST, &hdr_value) != NULL) {
save_char = hdr_value.buf[hdr_value.length]; save_char = hdr_value.buf[hdr_value.length];
hdr_value.buf[hdr_value.length] = '\0'; hdr_value.buf[hdr_value.length] = '\0';
st_found = ssdp_request_type( hdr_value.buf, &event ) == 0; st_found =
ssdp_request_type(hdr_value.buf, &event) == 0;
hdr_value.buf[hdr_value.length] = save_char; hdr_value.buf[hdr_value.length] = save_char;
} }
if (hmsg->status_code != HTTP_OK || if (hmsg->status_code != HTTP_OK ||
param.Expires <= 0 || param.Expires <= 0 ||
strlen(param.Location) == 0 || !usn_found || !st_found) { strlen(param.Location) == 0 || !usn_found || !st_found) {
return; // bad reply return; /* bad reply */
} }
// check each current search /* check each current search */
HandleLock(); HandleLock();
if (GetClientHandleInfo(&handle, &ctrlpt_info) != HND_CLIENT) { if (GetClientHandleInfo(&handle, &ctrlpt_info) != HND_CLIENT) {
HandleUnlock(); HandleUnlock();
return; return;
} }
node = ListHead(&ctrlpt_info->SsdpSearchList); node = ListHead(&ctrlpt_info->SsdpSearchList);
/* temporary add null termination */
// temporary add null termination /*save_char = hdr_value.buf[ hdr_value.length ]; */
//save_char = hdr_value.buf[ hdr_value.length ]; /*hdr_value.buf[ hdr_value.length ] = '\0'; */
//hdr_value.buf[ hdr_value.length ] = '\0';
while (node != NULL) { while (node != NULL) {
searchArg = node->item; searchArg = node->item;
matched = 0; matched = 0;
// check for match of ST header and search target /* check for match of ST header and search target */
switch (searchArg->requestType) { switch (searchArg->requestType) {
case SSDP_ALL: case SSDP_ALL:
matched = 1; matched = 1;
break; break;
case SSDP_ROOTDEVICE: case SSDP_ROOTDEVICE:
matched = ( event.RequestType == SSDP_ROOTDEVICE ); matched =
(event.RequestType == SSDP_ROOTDEVICE);
break; break;
case SSDP_DEVICEUDN: case SSDP_DEVICEUDN:
matched = !( strncmp( searchArg->searchTarget, matched = !strncmp(searchArg->searchTarget,
hdr_value.buf, hdr_value.buf,
hdr_value.length ) ); hdr_value.length);
break; break;
case SSDP_DEVICETYPE:{ case SSDP_DEVICETYPE:{
int m = min( hdr_value.length, size_t m = min(hdr_value.length,
strlen( searchArg->searchTarget ) ); strlen(searchArg->
matched = !( strncmp( searchArg->searchTarget, searchTarget));
hdr_value.buf, m ) ); matched = !strncmp(searchArg->searchTarget,
hdr_value.buf, m);
break; break;
} }
case SSDP_SERVICE:{ case SSDP_SERVICE:{
int m = min( hdr_value.length, size_t m = min(hdr_value.length,
strlen( searchArg->searchTarget ) ); strlen(searchArg->
searchTarget));
matched = !( strncmp( searchArg->searchTarget, matched = !strncmp(searchArg->searchTarget,
hdr_value.buf, m ) ); hdr_value.buf, m);
break; break;
} }
default: default:
matched = 0; matched = 0;
break; break;
} }
if (matched) { if (matched) {
// schedule call back /* schedule call back */
threadData = threadData =
(ResultData *) malloc(sizeof(ResultData)); (ResultData *) malloc(sizeof(ResultData));
if (threadData != NULL) { if (threadData != NULL) {
threadData->param = param; threadData->param = param;
threadData->cookie = searchArg->cookie; threadData->cookie = searchArg->cookie;
threadData->ctrlpt_callback = ctrlpt_callback; threadData->ctrlpt_callback =
TPJobInit( &job, ( start_routine ) send_search_result, ctrlpt_callback;
TPJobInit(&job,
(start_routine)
send_search_result,
threadData); threadData);
TPJobSetPriority(&job, MED_PRIORITY); TPJobSetPriority(&job, MED_PRIORITY);
TPJobSetFreeFunction(&job, (free_routine)free); TPJobSetFreeFunction(&job,
ThreadPoolAdd(&gRecvThreadPool, &job, NULL); (free_routine)
free);
ThreadPoolAdd(&gRecvThreadPool, &job,
NULL);
} }
} }
node = ListNext(&ctrlpt_info->SsdpSearchList, node); node = ListNext(&ctrlpt_info->SsdpSearchList, node);
} }
HandleUnlock(); HandleUnlock();
//ctrlpt_callback( UPNP_DISCOVERY_SEARCH_RESULT, &param, cookie ); /*ctrlpt_callback( UPNP_DISCOVERY_SEARCH_RESULT, &param, cookie ); */
} }
} }
@@ -428,15 +413,14 @@ static void CreateClientRequestPacketUlaGua(
* Returns: void * Returns: void
* *
***************************************************************************/ ***************************************************************************/
void void searchExpired(void *arg)
searchExpired( void *arg )
{ {
int *id = (int *)arg; int *id = (int *)arg;
int handle = -1; int handle = -1;
struct Handle_Info *ctrlpt_info = NULL; struct Handle_Info *ctrlpt_info = NULL;
//remove search Target from list and call client back /* remove search Target from list and call client back */
ListNode *node = NULL; ListNode *node = NULL;
SsdpSearchArg *item; SsdpSearchArg *item;
Upnp_FunPtr ctrlpt_callback; Upnp_FunPtr ctrlpt_callback;
@@ -445,18 +429,14 @@ searchExpired( void *arg )
HandleLock(); HandleLock();
//remove search target from search list /* remove search target from search list */
if( GetClientHandleInfo( &handle, &ctrlpt_info ) != HND_CLIENT ) { if( GetClientHandleInfo( &handle, &ctrlpt_info ) != HND_CLIENT ) {
free( id ); free( id );
HandleUnlock(); HandleUnlock();
return; return;
} }
ctrlpt_callback = ctrlpt_info->Callback; ctrlpt_callback = ctrlpt_info->Callback;
node = ListHead( &ctrlpt_info->SsdpSearchList ); node = ListHead( &ctrlpt_info->SsdpSearchList );
while( node != NULL ) { while( node != NULL ) {
item = ( SsdpSearchArg * ) node->item; item = ( SsdpSearchArg * ) node->item;
if( item->timeoutEventId == ( *id ) ) { if( item->timeoutEventId == ( *id ) ) {
@@ -528,7 +508,7 @@ int SearchByTarget(
unsigned long addrv4 = inet_addr(gIF_IPV4); unsigned long addrv4 = inet_addr(gIF_IPV4);
int max_fd = 0; int max_fd = 0;
//ThreadData *ThData; /*ThreadData *ThData;*/
ThreadPoolJob job; ThreadPoolJob job;
requestType = ssdp_request_type1(St); requestType = ssdp_request_type1(St);
@@ -644,7 +624,7 @@ int SearchByTarget(
imillisleep(SSDP_PAUSE); imillisleep(SSDP_PAUSE);
} }
} }
#endif //IPv6 #endif /* IPv6 */
if (gSsdpReqSocket4 != INVALID_SOCKET && if (gSsdpReqSocket4 != INVALID_SOCKET &&
FD_ISSET(gSsdpReqSocket4, &wrSet)) { FD_ISSET(gSsdpReqSocket4, &wrSet)) {
@@ -665,5 +645,6 @@ int SearchByTarget(
return 1; return 1;
} }
#endif // EXCLUDE_SSDP #endif /* EXCLUDE_SSDP */
#endif // INCLUDE_CLIENT_APIS #endif /* INCLUDE_CLIENT_APIS */

View File

@@ -120,34 +120,38 @@ void ssdp_handle_device_request(
int replyTime; int replyTime;
int maxAge; int maxAge;
// check man hdr /* check man hdr. */
if( httpmsg_find_hdr( hmsg, HDR_MAN, &hdr_value ) == NULL || if( httpmsg_find_hdr( hmsg, HDR_MAN, &hdr_value ) == NULL ||
memptr_cmp( &hdr_value, "\"ssdp:discover\"" ) != 0 ) { memptr_cmp( &hdr_value, "\"ssdp:discover\"" ) != 0 ) {
return; // bad or missing hdr /* bad or missing hdr. */
return;
} }
// MX header /* MX header. */
if( httpmsg_find_hdr( hmsg, HDR_MX, &hdr_value ) == NULL || if( httpmsg_find_hdr( hmsg, HDR_MX, &hdr_value ) == NULL ||
( mx = raw_to_int( &hdr_value, 10 ) ) < 0 ) { ( mx = raw_to_int( &hdr_value, 10 ) ) < 0 ) {
return; return;
} }
// ST header /* ST header. */
if( httpmsg_find_hdr( hmsg, HDR_ST, &hdr_value ) == NULL ) { if( httpmsg_find_hdr( hmsg, HDR_ST, &hdr_value ) == NULL ) {
return; return;
} }
save_char = hdr_value.buf[hdr_value.length]; save_char = hdr_value.buf[hdr_value.length];
hdr_value.buf[hdr_value.length] = '\0'; hdr_value.buf[hdr_value.length] = '\0';
ret_code = ssdp_request_type( hdr_value.buf, &event ); ret_code = ssdp_request_type( hdr_value.buf, &event );
hdr_value.buf[hdr_value.length] = save_char; // restore /* restore. */
hdr_value.buf[hdr_value.length] = save_char;
if( ret_code == -1 ) { if( ret_code == -1 ) {
return; // bad ST header /* bad ST header. */
return;
} }
HandleLock(); HandleLock();
// device info /* device info. */
if( GetDeviceHandleInfo( dest_addr->sa_family, if( GetDeviceHandleInfo( dest_addr->sa_family,
&handle, &dev_info ) != HND_DEVICE ) { &handle, &dev_info ) != HND_DEVICE ) {
HandleUnlock(); HandleUnlock();
return; // no info found /* no info found. */
return;
} }
maxAge = dev_info->MaxAge; maxAge = dev_info->MaxAge;
HandleUnlock(); HandleUnlock();
@@ -180,11 +184,9 @@ void ssdp_handle_device_request(
TPJobInit( &job, advertiseAndReplyThread, threadArg ); TPJobInit( &job, advertiseAndReplyThread, threadArg );
TPJobSetFreeFunction( &job, ( free_routine ) free ); TPJobSetFreeFunction( &job, ( free_routine ) free );
//Subtract a percentage from the mx /* Subtract a percentage from the mx to allow for network and processing
//to allow for network and processing delays * delays (i.e. if search is for 30 seconds, respond
// (i.e. if search is for 30 seconds, * within 0 - 27 seconds). */
// respond withing 0 - 27 seconds)
if( mx >= 2 ) { if( mx >= 2 ) {
mx -= MAXVAL( 1, mx / MX_FUDGE_FACTOR ); mx -= MAXVAL( 1, mx / MX_FUDGE_FACTOR );
} }
@@ -215,18 +217,16 @@ void ssdp_handle_device_request(
* Returns: void * * Returns: void *
* 1 if successful else appropriate error * 1 if successful else appropriate error
***************************************************************************/ ***************************************************************************/
static int static int NewRequestHandler(IN struct sockaddr *DestAddr, IN int NumPacket,
NewRequestHandler( IN struct sockaddr *DestAddr,
IN int NumPacket,
IN char **RqPacket) IN char **RqPacket)
{ {
char errorBuffer[ERROR_BUFFER_LEN]; char errorBuffer[ERROR_BUFFER_LEN];
SOCKET ReplySock; SOCKET ReplySock;
int socklen = sizeof( struct sockaddr_storage ); socklen_t socklen = sizeof(struct sockaddr_storage);
int NumCopy;
int Index; int Index;
unsigned long replyAddr = inet_addr(gIF_IPV4); unsigned long replyAddr = inet_addr(gIF_IPV4);
int ttl = 4; // a/c to UPNP Spec /* a/c to UPNP Spec */
int ttl = 4;
int hops = 1; int hops = 1;
char buf_ntop[64]; char buf_ntop[64];
int ret = UPNP_E_SUCCESS; int ret = UPNP_E_SUCCESS;
@@ -250,7 +250,8 @@ NewRequestHandler( IN struct sockaddr *DestAddr,
(char *)&ttl, sizeof(int)); (char *)&ttl, sizeof(int));
socklen = sizeof(struct sockaddr_in); socklen = sizeof(struct sockaddr_in);
} else if (DestAddr->sa_family == AF_INET6) { } else if (DestAddr->sa_family == AF_INET6) {
inet_ntop(AF_INET6, &((struct sockaddr_in6*)DestAddr)->sin6_addr, inet_ntop(AF_INET6,
&((struct sockaddr_in6 *)DestAddr)->sin6_addr,
buf_ntop, sizeof(buf_ntop)); buf_ntop, sizeof(buf_ntop));
setsockopt(ReplySock, IPPROTO_IPV6, IPV6_MULTICAST_IF, setsockopt(ReplySock, IPPROTO_IPV6, IPV6_MULTICAST_IF,
(char *)&gIF_INDEX, sizeof(gIF_INDEX)); (char *)&gIF_INDEX, sizeof(gIF_INDEX));
@@ -264,27 +265,12 @@ NewRequestHandler( IN struct sockaddr *DestAddr,
} }
for (Index = 0; Index < NumPacket; Index++) { for (Index = 0; Index < NumPacket; Index++) {
int rc; ssize_t 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
// request."
//
// http://www.upnp.org/download/draft-goland-http-udp-04.txt
//
// So, NUM_COPY has been changed from 2 to 1.
NumCopy = 0;
while( NumCopy < NUM_COPY ) {
UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__, UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__,
">>> SSDP SEND to %s >>>\n%s\n", ">>> SSDP SEND to %s >>>\n%s\n",
buf_ntop, *(RqPacket + Index)); buf_ntop, *(RqPacket + Index));
rc = sendto(ReplySock, *(RqPacket + Index), rc = sendto(ReplySock, *(RqPacket + Index),
strlen( *( RqPacket + Index ) ), strlen(*(RqPacket + Index)), 0, DestAddr, socklen);
0, DestAddr, socklen );
if (rc == -1) { if (rc == -1) {
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__, UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__,
@@ -293,11 +279,6 @@ NewRequestHandler( IN struct sockaddr *DestAddr,
ret = UPNP_E_SOCKET_WRITE; ret = UPNP_E_SOCKET_WRITE;
goto end_NewRequestHandler; goto end_NewRequestHandler;
} }
imillisleep( SSDP_PAUSE );
++NumCopy;
}
} }
end_NewRequestHandler: end_NewRequestHandler:
@@ -383,9 +364,9 @@ int isUrlV6UlaGua(char *descdocUrl)
* Returns: void * Returns: void
* *
***************************************************************************/ ***************************************************************************/
void CreateServicePacket( static void CreateServicePacket(
IN int msg_type, IN int msg_type,
IN char *nt, const IN char *nt,
IN char *usn, IN char *usn,
IN char *location, IN char *location,
IN int duration, IN int duration,
@@ -393,7 +374,7 @@ void CreateServicePacket(
IN int AddressFamily) IN int AddressFamily)
{ {
int ret_code; int ret_code;
char *nts; const char *nts;
membuffer buf; membuffer buf;
/* Notf == 0 means service shutdown, /* Notf == 0 means service shutdown,
@@ -421,24 +402,23 @@ void CreateServicePacket(
} }
} else if (msg_type == MSGTYPE_ADVERTISEMENT || } else if (msg_type == MSGTYPE_ADVERTISEMENT ||
msg_type == MSGTYPE_SHUTDOWN) { msg_type == MSGTYPE_SHUTDOWN) {
char *host = NULL; const char *host = NULL;
if (msg_type == MSGTYPE_ADVERTISEMENT) {
if (msg_type == MSGTYPE_ADVERTISEMENT)
nts = "ssdp:alive"; nts = "ssdp:alive";
} else { else
/* shutdown */ /* shutdown */
nts = "ssdp:byebye"; nts = "ssdp:byebye";
}
/* 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. */
if (AddressFamily == AF_INET) { if (AddressFamily == AF_INET)
host = SSDP_IP; host = SSDP_IP;
} else { else {
if (isUrlV6UlaGua(location)) { if (isUrlV6UlaGua(location))
host = "[" SSDP_IPV6_SITELOCAL "]"; host = "[" SSDP_IPV6_SITELOCAL "]";
} else { else
host = "[" SSDP_IPV6_LINKLOCAL "]"; host = "[" SSDP_IPV6_LINKLOCAL "]";
} }
}
ret_code = http_MakeMessage( ret_code = http_MakeMessage(
&buf, 1, 1, &buf, 1, 1,
"Q" "sssdc" "sdc" "ssc" "ssc" "ssc" "ssc" "ssc" "S" "Xc" "sscc", "Q" "sssdc" "sdc" "ssc" "ssc" "ssc" "ssc" "ssc" "S" "Xc" "sscc",
@@ -453,14 +433,11 @@ void CreateServicePacket(
"NTS: ", nts, "NTS: ", nts,
X_USER_AGENT, X_USER_AGENT,
"USN: ", usn ); "USN: ", usn );
if (ret_code != 0) { if (ret_code)
return; return;
} } else
} else {
/* unknown msg */ /* unknown msg */
assert(0); assert(0);
}
/* return msg */ /* return msg */
*packet = membuffer_detach(&buf); *packet = membuffer_detach(&buf);
membuffer_destroy(&buf); membuffer_destroy(&buf);
@@ -499,10 +476,10 @@ DeviceAdvertisement( IN char *DevType,
struct sockaddr_in* DestAddr4 = (struct sockaddr_in*)&__ss; struct sockaddr_in* DestAddr4 = (struct sockaddr_in*)&__ss;
struct sockaddr_in6* DestAddr6 = (struct sockaddr_in6*)&__ss; struct sockaddr_in6* DestAddr6 = (struct sockaddr_in6*)&__ss;
//char Mil_Nt[LINE_SIZE] /* char Mil_Nt[LINE_SIZE] */
char Mil_Usn[LINE_SIZE]; char Mil_Usn[LINE_SIZE];
char *msgs[3]; char *msgs[3];
int ret_code; int ret_code = UPNP_E_SUCCESS;
UpnpPrintf( UPNP_INFO, SSDP, __FILE__, __LINE__, UpnpPrintf( UPNP_INFO, SSDP, __FILE__, __LINE__,
"In function DeviceAdvertisement\n" ); "In function DeviceAdvertisement\n" );
@@ -528,24 +505,20 @@ DeviceAdvertisement( IN char *DevType,
msgs[1] = NULL; msgs[1] = NULL;
msgs[2] = NULL; msgs[2] = NULL;
//If deviceis a root device , here we need to /* If deviceis a root device , here we need to send 3 advertisement
//send 3 advertisement or reply * or reply */
if( RootDev ) { if( RootDev ) {
sprintf( Mil_Usn, "%s::upnp:rootdevice", Udn ); sprintf( Mil_Usn, "%s::upnp:rootdevice", Udn );
CreateServicePacket( MSGTYPE_ADVERTISEMENT, "upnp:rootdevice", CreateServicePacket( MSGTYPE_ADVERTISEMENT, "upnp:rootdevice",
Mil_Usn, Location, Duration, &msgs[0], AddressFamily ); Mil_Usn, Location, Duration, &msgs[0], AddressFamily );
} }
// both root and sub-devices need to send these two messages /* both root and sub-devices need to send these two messages */
//
CreateServicePacket( MSGTYPE_ADVERTISEMENT, Udn, Udn, CreateServicePacket( MSGTYPE_ADVERTISEMENT, Udn, Udn,
Location, Duration, &msgs[1], AddressFamily ); Location, Duration, &msgs[1], AddressFamily );
sprintf( Mil_Usn, "%s::%s", Udn, DevType ); sprintf( Mil_Usn, "%s::%s", Udn, DevType );
CreateServicePacket( MSGTYPE_ADVERTISEMENT, DevType, Mil_Usn, CreateServicePacket( MSGTYPE_ADVERTISEMENT, DevType, Mil_Usn,
Location, Duration, &msgs[2], AddressFamily ); Location, Duration, &msgs[2], AddressFamily );
/* check error */
// check error
if( ( RootDev && msgs[0] == NULL ) || if( ( RootDev && msgs[0] == NULL ) ||
msgs[1] == NULL || msgs[2] == NULL ) { msgs[1] == NULL || msgs[2] == NULL ) {
free( msgs[0] ); free( msgs[0] );
@@ -553,17 +526,17 @@ DeviceAdvertisement( IN char *DevType,
free( msgs[2] ); free( msgs[2] );
return UPNP_E_OUTOF_MEMORY; return UPNP_E_OUTOF_MEMORY;
} }
// send packets /* send packets */
if( RootDev ) { if( RootDev ) {
// send 3 msg types /* send 3 msg types */
ret_code = NewRequestHandler( (struct sockaddr*)&__ss, 3, &msgs[0] ); ret_code = NewRequestHandler( (struct sockaddr*)&__ss, 3, &msgs[0] );
} else // sub-device } else /* sub-device */
{ {
// send 2 msg types /* send 2 msg types */
ret_code = NewRequestHandler( (struct sockaddr*)&__ss, 2, &msgs[1] ); ret_code = NewRequestHandler( (struct sockaddr*)&__ss, 2, &msgs[1] );
} }
// free msgs /* free msgs */
free( msgs[0] ); free( msgs[0] );
free( msgs[1] ); free( msgs[1] );
free( msgs[2] ); free( msgs[2] );
@@ -609,17 +582,17 @@ SendReply( IN struct sockaddr *DestAddr,
msgs[1] = NULL; msgs[1] = NULL;
if( RootDev ) { if( RootDev ) {
// one msg for root device /* one msg for root device */
num_msgs = 1; num_msgs = 1;
sprintf( Mil_Usn, "%s::upnp:rootdevice", Udn ); sprintf( Mil_Usn, "%s::upnp:rootdevice", Udn );
CreateServicePacket( MSGTYPE_REPLY, "upnp:rootdevice", CreateServicePacket( MSGTYPE_REPLY, "upnp:rootdevice",
Mil_Usn, Location, Duration, &msgs[0], DestAddr->sa_family ); Mil_Usn, Location, Duration, &msgs[0], DestAddr->sa_family );
} else { } else {
// two msgs for embedded devices /* two msgs for embedded devices */
num_msgs = 1; num_msgs = 1;
//NK: FIX for extra response when someone searches by udn /*NK: FIX for extra response when someone searches by udn */
if( !ByType ) { if( !ByType ) {
CreateServicePacket( MSGTYPE_REPLY, Udn, Udn, Location, CreateServicePacket( MSGTYPE_REPLY, Udn, Udn, Location,
Duration, &msgs[0], DestAddr->sa_family ); Duration, &msgs[0], DestAddr->sa_family );
@@ -630,7 +603,7 @@ SendReply( IN struct sockaddr *DestAddr,
} }
} }
// check error /* check error */
for( i = 0; i < num_msgs; i++ ) { for( i = 0; i < num_msgs; i++ ) {
if( msgs[i] == NULL ) { if( msgs[i] == NULL ) {
free( msgs[0] ); free( msgs[0] );
@@ -638,7 +611,7 @@ SendReply( IN struct sockaddr *DestAddr,
} }
} }
// send msgs /* send msgs */
ret_code = NewRequestHandler( DestAddr, num_msgs, msgs ); ret_code = NewRequestHandler( DestAddr, num_msgs, msgs );
for( i = 0; i < num_msgs; i++ ) { for( i = 0; i < num_msgs; i++ ) {
if( msgs[i] != NULL ) if( msgs[i] != NULL )
@@ -682,28 +655,23 @@ DeviceReply( IN struct sockaddr *DestAddr,
szReq[1] = NULL; szReq[1] = NULL;
szReq[2] = NULL; szReq[2] = NULL;
// create 2 or 3 msgs /* create 2 or 3 msgs */
if( RootDev ) { if( RootDev ) {
// 3 replies for root device /* 3 replies for root device */
strcpy( Mil_Nt, "upnp:rootdevice" ); strcpy( Mil_Nt, "upnp:rootdevice" );
sprintf( Mil_Usn, "%s::upnp:rootdevice", Udn ); sprintf( Mil_Usn, "%s::upnp:rootdevice", Udn );
CreateServicePacket( MSGTYPE_REPLY, Mil_Nt, Mil_Usn, CreateServicePacket( MSGTYPE_REPLY, Mil_Nt, Mil_Usn,
Location, Duration, &szReq[0], DestAddr->sa_family ); Location, Duration, &szReq[0], DestAddr->sa_family );
} }
sprintf( Mil_Nt, "%s", Udn ); sprintf( Mil_Nt, "%s", Udn );
sprintf( Mil_Usn, "%s", Udn ); sprintf( Mil_Usn, "%s", Udn );
CreateServicePacket( MSGTYPE_REPLY, Mil_Nt, Mil_Usn, CreateServicePacket( MSGTYPE_REPLY, Mil_Nt, Mil_Usn,
Location, Duration, &szReq[1], DestAddr->sa_family ); Location, Duration, &szReq[1], DestAddr->sa_family );
sprintf( Mil_Nt, "%s", DevType ); sprintf( Mil_Nt, "%s", DevType );
sprintf( Mil_Usn, "%s::%s", Udn, DevType ); sprintf( Mil_Usn, "%s::%s", Udn, DevType );
CreateServicePacket( MSGTYPE_REPLY, Mil_Nt, Mil_Usn, CreateServicePacket( MSGTYPE_REPLY, Mil_Nt, Mil_Usn,
Location, Duration, &szReq[2], DestAddr->sa_family ); Location, Duration, &szReq[2], DestAddr->sa_family );
/* check error */
// check error
if( ( RootDev && szReq[0] == NULL ) || if( ( RootDev && szReq[0] == NULL ) ||
szReq[1] == NULL || szReq[2] == NULL ) { szReq[1] == NULL || szReq[2] == NULL ) {
free( szReq[0] ); free( szReq[0] );
@@ -711,14 +679,13 @@ DeviceReply( IN struct sockaddr *DestAddr,
free( szReq[2] ); free( szReq[2] );
return UPNP_E_OUTOF_MEMORY; return UPNP_E_OUTOF_MEMORY;
} }
// send replies /* send replies */
if( RootDev ) { if( RootDev ) {
RetVal = NewRequestHandler( DestAddr, 3, szReq ); RetVal = NewRequestHandler( DestAddr, 3, szReq );
} else { } else {
RetVal = NewRequestHandler( DestAddr, 2, &szReq[1] ); RetVal = NewRequestHandler( DestAddr, 2, &szReq[1] );
} }
/* free */
// free
free( szReq[0] ); free( szReq[0] );
free( szReq[1] ); free( szReq[1] );
free( szReq[2] ); free( szReq[2] );
@@ -751,7 +718,7 @@ ServiceAdvertisement( IN char *Udn,
{ {
char Mil_Usn[LINE_SIZE]; char Mil_Usn[LINE_SIZE];
char *szReq[1]; char *szReq[1];
int RetVal; int RetVal = UPNP_E_SUCCESS;
struct sockaddr_storage __ss; struct sockaddr_storage __ss;
struct sockaddr_in* DestAddr4 = (struct sockaddr_in*)&__ss; struct sockaddr_in* DestAddr4 = (struct sockaddr_in*)&__ss;
struct sockaddr_in6* DestAddr6 = (struct sockaddr_in6*)&__ss; struct sockaddr_in6* DestAddr6 = (struct sockaddr_in6*)&__ss;
@@ -775,8 +742,8 @@ ServiceAdvertisement( IN char *Udn,
sprintf( Mil_Usn, "%s::%s", Udn, ServType ); sprintf( Mil_Usn, "%s::%s", Udn, ServType );
//CreateServiceRequestPacket(1,szReq[0],Mil_Nt,Mil_Usn, /* CreateServiceRequestPacket(1,szReq[0],Mil_Nt,Mil_Usn,
//Server,Location,Duration); * Server,Location,Duration); */
CreateServicePacket( MSGTYPE_ADVERTISEMENT, ServType, Mil_Usn, CreateServicePacket( MSGTYPE_ADVERTISEMENT, ServType, Mil_Usn,
Location, Duration, &szReq[0], AddressFamily ); Location, Duration, &szReq[0], AddressFamily );
if( szReq[0] == NULL ) { if( szReq[0] == NULL ) {
@@ -860,7 +827,7 @@ ServiceShutdown( IN char *Udn,
struct sockaddr_storage __ss; struct sockaddr_storage __ss;
struct sockaddr_in* DestAddr4 = (struct sockaddr_in*)&__ss; struct sockaddr_in* DestAddr4 = (struct sockaddr_in*)&__ss;
struct sockaddr_in6* DestAddr6 = (struct sockaddr_in6*)&__ss; struct sockaddr_in6* DestAddr6 = (struct sockaddr_in6*)&__ss;
int RetVal; int RetVal = UPNP_E_SUCCESS;
memset( &__ss, 0, sizeof(__ss) ); memset( &__ss, 0, sizeof(__ss) );
if( AddressFamily == AF_INET ) { if( AddressFamily == AF_INET ) {
@@ -879,10 +846,10 @@ ServiceShutdown( IN char *Udn,
"Invalid device address family.\n" ); "Invalid device address family.\n" );
} }
//sprintf(Mil_Nt,"%s",ServType); /* sprintf(Mil_Nt,"%s",ServType); */
sprintf( Mil_Usn, "%s::%s", Udn, ServType ); sprintf( Mil_Usn, "%s::%s", Udn, ServType );
//CreateServiceRequestPacket(0,szReq[0],Mil_Nt,Mil_Usn, /* CreateServiceRequestPacket(0,szReq[0],Mil_Nt,Mil_Usn,
//Server,Location,Duration); * Server,Location,Duration); */
CreateServicePacket( MSGTYPE_SHUTDOWN, ServType, Mil_Usn, CreateServicePacket( MSGTYPE_SHUTDOWN, ServType, Mil_Usn,
Location, Duration, &szReq[0], AddressFamily ); Location, Duration, &szReq[0], AddressFamily );
if( szReq[0] == NULL ) { if( szReq[0] == NULL ) {
@@ -926,7 +893,7 @@ DeviceShutdown( IN char *DevType,
struct sockaddr_in6* DestAddr6 = (struct sockaddr_in6*)&__ss; struct sockaddr_in6* DestAddr6 = (struct sockaddr_in6*)&__ss;
char *msgs[3]; char *msgs[3];
char Mil_Usn[LINE_SIZE]; char Mil_Usn[LINE_SIZE];
int ret_code; int ret_code = UPNP_E_SUCCESS;
msgs[0] = NULL; msgs[0] = NULL;
msgs[1] = NULL; msgs[1] = NULL;
@@ -948,25 +915,21 @@ DeviceShutdown( IN char *DevType,
UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__, UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__,
"Invalid device address family.\n" ); "Invalid device address family.\n" );
} }
/* root device has one extra msg */
// root device has one extra msg
if( RootDev ) { if( RootDev ) {
sprintf( Mil_Usn, "%s::upnp:rootdevice", Udn ); sprintf( Mil_Usn, "%s::upnp:rootdevice", Udn );
CreateServicePacket( MSGTYPE_SHUTDOWN, "upnp:rootdevice", CreateServicePacket( MSGTYPE_SHUTDOWN, "upnp:rootdevice",
Mil_Usn, Location, Duration, &msgs[0], AddressFamily ); Mil_Usn, Location, Duration, &msgs[0], AddressFamily );
} }
UpnpPrintf( UPNP_INFO, SSDP, __FILE__, __LINE__, UpnpPrintf( UPNP_INFO, SSDP, __FILE__, __LINE__,
"In function DeviceShutdown\n" ); "In function DeviceShutdown\n" );
// both root and sub-devices need to send these two messages /* both root and sub-devices need to send these two messages */
CreateServicePacket( MSGTYPE_SHUTDOWN, Udn, Udn, CreateServicePacket( MSGTYPE_SHUTDOWN, Udn, Udn,
Location, Duration, &msgs[1], AddressFamily ); Location, Duration, &msgs[1], AddressFamily );
sprintf( Mil_Usn, "%s::%s", Udn, DevType ); sprintf( Mil_Usn, "%s::%s", Udn, DevType );
CreateServicePacket( MSGTYPE_SHUTDOWN, DevType, Mil_Usn, CreateServicePacket( MSGTYPE_SHUTDOWN, DevType, Mil_Usn,
Location, Duration, &msgs[2], AddressFamily ); Location, Duration, &msgs[2], AddressFamily );
/* check error */
// check error
if( ( RootDev && msgs[0] == NULL ) || if( ( RootDev && msgs[0] == NULL ) ||
msgs[1] == NULL || msgs[2] == NULL ) { msgs[1] == NULL || msgs[2] == NULL ) {
free( msgs[0] ); free( msgs[0] );
@@ -974,24 +937,24 @@ DeviceShutdown( IN char *DevType,
free( msgs[2] ); free( msgs[2] );
return UPNP_E_OUTOF_MEMORY; return UPNP_E_OUTOF_MEMORY;
} }
// send packets /* send packets */
if( RootDev ) { if( RootDev ) {
// send 3 msg types /* send 3 msg types */
ret_code = NewRequestHandler( (struct sockaddr*)&__ss, 3, &msgs[0] ); ret_code = NewRequestHandler( (struct sockaddr*)&__ss, 3, &msgs[0] );
} else // sub-device } else {
{ /* sub-device */
// send 2 msg types /* send 2 msg types */
ret_code = NewRequestHandler( (struct sockaddr*)&__ss, 2, &msgs[1] ); ret_code = NewRequestHandler( (struct sockaddr*)&__ss, 2, &msgs[1] );
} }
/* free msgs */
// free msgs
free( msgs[0] ); free( msgs[0] );
free( msgs[1] ); free( msgs[1] );
free( msgs[2] ); free( msgs[2] );
return ret_code; return ret_code;
_Server = _Server;
} }
#endif // EXCLUDE_SSDP #endif /* EXCLUDE_SSDP */
#endif // INCLUDE_DEVICE_APIS #endif /* INCLUDE_DEVICE_APIS */

View File

@@ -120,8 +120,8 @@ int AdvertiseAndReply(
int Exp) int Exp)
{ {
int retVal = UPNP_E_SUCCESS; int retVal = UPNP_E_SUCCESS;
int i; long unsigned int i;
int j; long unsigned int j;
int defaultExp = DEFAULT_MAXAGE; int defaultExp = DEFAULT_MAXAGE;
struct Handle_Info *SInfo = NULL; struct Handle_Info *SInfo = NULL;
char UDNstr[100]; char UDNstr[100];
@@ -135,6 +135,7 @@ int AdvertiseAndReply(
const DOMString tmpStr; const DOMString tmpStr;
char SERVER[200]; char SERVER[200];
const DOMString dbgStr; const DOMString dbgStr;
int NumCopy = 0;
UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__, UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
"Inside AdvertiseAndReply with AdFlag = %d\n", AdFlag); "Inside AdvertiseAndReply with AdFlag = %d\n", AdFlag);
@@ -152,41 +153,43 @@ int AdvertiseAndReply(
get_sdk_info(SERVER); get_sdk_info(SERVER);
/* parse the device list and send advertisements/replies */ /* parse the device list and send advertisements/replies */
while (NumCopy == 0 || (AdFlag && NumCopy < NUM_SSDP_COPY)) {
if (NumCopy != 0)
imillisleep(SSDP_PAUSE);
NumCopy++;
for (i = 0;; i++) { for (i = 0;; i++) {
UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__, UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
"Entering new device list with i = %d\n\n", i); "Entering new device list with i = %lu\n\n", i);
tmpNode = ixmlNodeList_item(SInfo->DeviceList, i); tmpNode = ixmlNodeList_item(SInfo->DeviceList, i);
if (!tmpNode) { if (!tmpNode) {
UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__, UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
"Exiting new device list with i = %d\n\n", i); "Exiting new device list with i = %lu\n\n", i);
break; break;
} }
dbgStr = ixmlNode_getNodeName(tmpNode); dbgStr = ixmlNode_getNodeName(tmpNode);
UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__, UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
"Extracting device type once for %s\n", dbgStr); "Extracting device type once for %s\n", dbgStr);
ixmlNodeList_free(nodeList); ixmlNodeList_free(nodeList);
nodeList = ixmlElement_getElementsByTagName( nodeList = ixmlElement_getElementsByTagName(
(IXML_Element *)tmpNode, "deviceType"); (IXML_Element *)tmpNode, "deviceType");
if (!nodeList) continue; if (!nodeList)
continue;
UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__, UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
"Extracting UDN for %s\n", dbgStr); "Extracting UDN for %s\n", dbgStr);
dbgStr = ixmlNode_getNodeName(tmpNode); dbgStr = ixmlNode_getNodeName(tmpNode);
UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__, UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
"Extracting device type\n"); "Extracting device type\n");
tmpNode2 = ixmlNodeList_item(nodeList, 0); tmpNode2 = ixmlNodeList_item(nodeList, 0);
if (!tmpNode2) continue; if (!tmpNode2)
continue;
textNode = ixmlNode_getFirstChild(tmpNode2); textNode = ixmlNode_getFirstChild(tmpNode2);
if (!textNode) continue; if (!textNode) continue;
UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__, UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
"Extracting device type \n"); "Extracting device type \n");
tmpStr = ixmlNode_getNodeValue(textNode); tmpStr = ixmlNode_getNodeValue(textNode);
if (!tmpStr) continue; if (!tmpStr)
continue;
strcpy(devType, tmpStr); strcpy(devType, tmpStr);
UpnpPrintf( UPNP_ALL, API, __FILE__, __LINE__, UpnpPrintf( UPNP_ALL, API, __FILE__, __LINE__,
"Extracting device type = %s\n", devType); "Extracting device type = %s\n", devType);
@@ -195,7 +198,6 @@ int AdvertiseAndReply(
"TempNode is NULL\n"); "TempNode is NULL\n");
} }
dbgStr = ixmlNode_getNodeName(tmpNode); dbgStr = ixmlNode_getNodeName(tmpNode);
UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__, UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
"Extracting UDN for %s\n", dbgStr); "Extracting UDN for %s\n", dbgStr);
ixmlNodeList_free(nodeList); ixmlNodeList_free(nodeList);
@@ -220,8 +222,8 @@ int AdvertiseAndReply(
} }
tmpStr = ixmlNode_getNodeValue(textNode); tmpStr = ixmlNode_getNodeValue(textNode);
if (!tmpStr) { if (!tmpStr) {
UpnpPrintf(UPNP_CRITICAL, API, __FILE__, __LINE__, UpnpPrintf(UPNP_CRITICAL, API, __FILE__,
"UDN not found!\n"); __LINE__, "UDN not found!\n");
continue; continue;
} }
strcpy(UDNstr, tmpStr); strcpy(UDNstr, tmpStr);
@@ -231,11 +233,13 @@ int AdvertiseAndReply(
/* send the device advertisement */ /* send the device advertisement */
if (AdFlag == 1) { if (AdFlag == 1) {
DeviceAdvertisement(devType, i == 0, DeviceAdvertisement(devType, i == 0,
UDNstr, SInfo->DescURL, Exp, SInfo->DeviceAf ); UDNstr, SInfo->DescURL, Exp,
SInfo->DeviceAf);
} else { } else {
/* AdFlag == -1 */ /* AdFlag == -1 */
DeviceShutdown(devType, i == 0, UDNstr, DeviceShutdown(devType, i == 0, UDNstr,
SERVER, SInfo->DescURL, Exp, SInfo->DeviceAf ); SERVER, SInfo->DescURL, Exp,
SInfo->DeviceAf);
} }
} else { } else {
switch (SearchType) { switch (SearchType) {
@@ -392,6 +396,7 @@ int AdvertiseAndReply(
ixmlNodeList_free(nodeList); ixmlNodeList_free(nodeList);
nodeList = NULL; nodeList = NULL;
} }
}
end_function: end_function:
ixmlNodeList_free(tmpNodeList); ixmlNodeList_free(tmpNodeList);
@@ -461,78 +466,64 @@ int unique_service_name(IN char *cmd, IN SsdpEvent *Evt)
char *ptr2 = NULL; char *ptr2 = NULL;
char *ptr3 = NULL; char *ptr3 = NULL;
int CommandFound = 0; int CommandFound = 0;
int length = 0; size_t n = 0;
if ((TempPtr = strstr(cmd, "uuid:schemas")) != NULL) { if ((TempPtr = strstr(cmd, "uuid:schemas")) != NULL) {
ptr1 = strstr(cmd, ":device"); ptr1 = strstr(cmd, ":device");
if( ptr1 != NULL ) { if (ptr1 != NULL)
ptr2 = strstr(ptr1 + 1, ":"); ptr2 = strstr(ptr1 + 1, ":");
} else { else
return -1; return -1;
} if (ptr2 != NULL)
if( ptr2 != NULL ) {
ptr3 = strstr(ptr2 + 1, ":"); ptr3 = strstr(ptr2 + 1, ":");
} else { else
return -1; return -1;
} if (ptr3 != NULL)
if( ptr3 != NULL ) {
sprintf(Evt->UDN, "uuid:%s", ptr3 + 1); sprintf(Evt->UDN, "uuid:%s", ptr3 + 1);
} else { else
return -1; return -1;
}
ptr1 = strstr(cmd, ":"); ptr1 = strstr(cmd, ":");
if (ptr1 != NULL) { if (ptr1 != NULL) {
strncpy( TempBuf, ptr1, ptr3 - ptr1 ); n = (size_t)(ptr3 - ptr1);
TempBuf[ptr3 - ptr1] = '\0'; strncpy(TempBuf, ptr1, n);
TempBuf[n] = '\0';
sprintf(Evt->DeviceType, "urn%s", TempBuf); sprintf(Evt->DeviceType, "urn%s", TempBuf);
} else { } else
return -1; return -1;
}
return 0; return 0;
} }
if ((TempPtr = strstr(cmd, "uuid")) != NULL) { if ((TempPtr = strstr(cmd, "uuid")) != NULL) {
if ((Ptr = strstr(cmd, "::")) != NULL) { if ((Ptr = strstr(cmd, "::")) != NULL) {
strncpy( Evt->UDN, TempPtr, Ptr - TempPtr ); n = (size_t)(Ptr - TempPtr);
Evt->UDN[Ptr - TempPtr] = '\0'; strncpy(Evt->UDN, TempPtr, n);
} else { Evt->UDN[n] = '\0';
} else
strcpy(Evt->UDN, TempPtr); strcpy(Evt->UDN, TempPtr);
}
CommandFound = 1; CommandFound = 1;
} }
if (strstr(cmd, "urn:") != NULL && strstr(cmd, ":service:") != NULL) {
if( strstr( cmd, "urn:" ) != NULL
&& strstr( cmd, ":service:" ) != NULL ) {
if ((TempPtr = strstr(cmd, "urn")) != NULL) { if ((TempPtr = strstr(cmd, "urn")) != NULL) {
strcpy(Evt->ServiceType, TempPtr); strcpy(Evt->ServiceType, TempPtr);
CommandFound = 1; CommandFound = 1;
} }
} }
if (strstr(cmd, "urn:") != NULL && strstr(cmd, ":device:") != NULL) {
if( strstr( cmd, "urn:" ) != NULL
&& strstr( cmd, ":device:" ) != NULL ) {
if ((TempPtr = strstr(cmd, "urn")) != NULL) { if ((TempPtr = strstr(cmd, "urn")) != NULL) {
strcpy(Evt->DeviceType, TempPtr); strcpy(Evt->DeviceType, TempPtr);
CommandFound = 1; CommandFound = 1;
} }
} }
if ((TempPtr = strstr(cmd, "::upnp:rootdevice")) != NULL) { if ((TempPtr = strstr(cmd, "::upnp:rootdevice")) != NULL) {
/* Everything before "::upnp::rootdevice" is the UDN. */ /* Everything before "::upnp::rootdevice" is the UDN. */
if (TempPtr != cmd) { if (TempPtr != cmd) {
length = TempPtr - cmd; n = (size_t)(TempPtr - cmd);
strncpy(Evt->UDN, cmd, length); strncpy(Evt->UDN, cmd, n);
Evt->UDN[length] = 0; Evt->UDN[n] = 0;
CommandFound = 1; CommandFound = 1;
} }
} }
if (CommandFound == 0)
if( CommandFound == 0 ) {
return -1; return -1;
}
return 0; return 0;
} }
@@ -588,11 +579,9 @@ ssdp_request_type1( IN char *cmd )
* Returns: int * Returns: int
* 0 on success; -1 on error * 0 on success; -1 on error
***************************************************************************/ ***************************************************************************/
int int ssdp_request_type(IN char *cmd, OUT SsdpEvent *Evt)
ssdp_request_type( IN char *cmd,
OUT SsdpEvent * Evt )
{ {
// clear event /* clear event */
memset( Evt, 0, sizeof( SsdpEvent ) ); memset( Evt, 0, sizeof( SsdpEvent ) );
unique_service_name( cmd, Evt ); unique_service_name( cmd, Evt );
Evt->ErrCode = NO_ERROR_FOUND; Evt->ErrCode = NO_ERROR_FOUND;
@@ -617,15 +606,13 @@ ssdp_request_type( IN char *cmd,
* Returns: VOID * Returns: VOID
* *
***************************************************************************/ ***************************************************************************/
static void static void free_ssdp_event_handler_data(void *the_data)
free_ssdp_event_handler_data( void *the_data )
{ {
ssdp_thread_data *data = ( ssdp_thread_data * ) the_data; ssdp_thread_data *data = ( ssdp_thread_data * ) the_data;
if( data != NULL ) { if( data != NULL ) {
http_message_t *hmsg = &data->parser.msg; http_message_t *hmsg = &data->parser.msg;
/* free data */
// free data
httpmsg_destroy( hmsg ); httpmsg_destroy( hmsg );
free( data ); free( data );
} }
@@ -641,10 +628,10 @@ free_ssdp_event_handler_data( void *the_data )
* Description: * Description:
* This function do some quick checking of the ssdp msg * This function do some quick checking of the ssdp msg
* *
* Returns: xboolean * Returns: int
* returns TRUE if msg is valid else FALSE * returns TRUE if msg is valid else FALSE
***************************************************************************/ ***************************************************************************/
static UPNP_INLINE xboolean valid_ssdp_msg(IN http_message_t *hmsg) static UPNP_INLINE int valid_ssdp_msg(IN http_message_t *hmsg)
{ {
memptr hdr_value; memptr hdr_value;
@@ -692,8 +679,7 @@ static UPNP_INLINE xboolean valid_ssdp_msg(IN http_message_t *hmsg)
* Returns: int * Returns: int
* 0 if successful -1 if error * 0 if successful -1 if error
***************************************************************************/ ***************************************************************************/
static UPNP_INLINE int static UPNP_INLINE int start_event_handler(void *Data)
start_event_handler( void *Data )
{ {
http_parser_t *parser = NULL; http_parser_t *parser = NULL;
@@ -709,21 +695,21 @@ start_event_handler( void *Data )
UpnpPrintf( UPNP_INFO, SSDP, __FILE__, __LINE__, UpnpPrintf( UPNP_INFO, SSDP, __FILE__, __LINE__,
"SSDP recvd bad msg code = %d\n", "SSDP recvd bad msg code = %d\n",
status ); status );
// ignore bad msg, or not enuf mem /* ignore bad msg, or not enuf mem */
goto error_handler; goto error_handler;
} }
// valid notify msg /* valid notify msg */
} else if( status != PARSE_SUCCESS ) { } else if( status != PARSE_SUCCESS ) {
UpnpPrintf( UPNP_INFO, SSDP, __FILE__, __LINE__, UpnpPrintf( UPNP_INFO, SSDP, __FILE__, __LINE__,
"SSDP recvd bad msg code = %d\n", status ); "SSDP recvd bad msg code = %d\n", status );
goto error_handler; goto error_handler;
} }
// check msg /* check msg */
if( valid_ssdp_msg( &parser->msg ) != TRUE ) { if( valid_ssdp_msg( &parser->msg ) != TRUE ) {
goto error_handler; goto error_handler;
} }
return 0; //////// done; thread will free 'data' return 0; /* done; thread will free 'data' */
error_handler: error_handler:
free_ssdp_event_handler_data( data ); free_ssdp_event_handler_data( data );
@@ -777,8 +763,7 @@ static void ssdp_event_handler_thread(void *the_data)
* Returns: void * Returns: void
* *
***************************************************************************/ ***************************************************************************/
void void readFromSSDPSocket(SOCKET socket)
readFromSSDPSocket( SOCKET socket )
{ {
char *requestBuf = NULL; char *requestBuf = NULL;
char staticBuf[BUFSIZE]; char staticBuf[BUFSIZE];
@@ -786,99 +771,78 @@ readFromSSDPSocket( SOCKET socket )
ThreadPoolJob job; ThreadPoolJob job;
ssdp_thread_data *data = NULL; ssdp_thread_data *data = NULL;
socklen_t socklen = sizeof(__ss); socklen_t socklen = sizeof(__ss);
int byteReceived = 0; ssize_t byteReceived = 0;
char ntop_buf[64]; char ntop_buf[64];
requestBuf = staticBuf; requestBuf = staticBuf;
/* in case memory can't be allocated, still drain the socket using a
//in case memory * static buffer. */
//can't be allocated, still drain the data = malloc(sizeof(ssdp_thread_data));
//socket using a static buffer if (data) {
/* initialize parser */
data = ( ssdp_thread_data * )
malloc( sizeof( ssdp_thread_data ) );
if( data != NULL ) {
//initialize parser
#ifdef INCLUDE_CLIENT_APIS #ifdef INCLUDE_CLIENT_APIS
#ifdef UPNP_ENABLE_IPV6 #ifdef UPNP_ENABLE_IPV6
if( socket == gSsdpReqSocket4 || socket == gSsdpReqSocket6 ) { if (socket == gSsdpReqSocket4 || socket == gSsdpReqSocket6)
parser_response_init(&data->parser, HTTPMETHOD_MSEARCH); parser_response_init(&data->parser, HTTPMETHOD_MSEARCH);
} else { else
parser_request_init(&data->parser); parser_request_init(&data->parser);
} #else /* UPNP_ENABLE_IPV6 */
#else if (socket == gSsdpReqSocket4)
if( socket == gSsdpReqSocket4 ) {
parser_response_init(&data->parser, HTTPMETHOD_MSEARCH); parser_response_init(&data->parser, HTTPMETHOD_MSEARCH);
} else { else
parser_request_init(&data->parser); parser_request_init(&data->parser);
} #endif /* UPNP_ENABLE_IPV6 */
#else /* INCLUDE_CLIENT_APIS */
#endif
#else
parser_request_init(&data->parser); parser_request_init(&data->parser);
#endif #endif /* INCLUDE_CLIENT_APIS */
/* set size of parser buffer */
//set size of parser buffer if (membuffer_set_size(&data->parser.msg.msg, BUFSIZE) == 0)
/* use this as the buffer for recv */
if( membuffer_set_size( &data->parser.msg.msg, BUFSIZE ) == 0 ) {
//use this as the buffer for recv
requestBuf = data->parser.msg.msg.buf; requestBuf = data->parser.msg.msg.buf;
else {
} else {
free(data); free(data);
data = NULL; data = NULL;
} }
} }
byteReceived = recvfrom( socket, requestBuf, byteReceived = recvfrom(socket, requestBuf, BUFSIZE - 1, 0,
BUFSIZE - 1, 0,
(struct sockaddr *)&__ss, &socklen); (struct sockaddr *)&__ss, &socklen);
if (byteReceived > 0) { if (byteReceived > 0) {
requestBuf[byteReceived] = '\0'; requestBuf[byteReceived] = '\0';
if (__ss.ss_family == AF_INET) if (__ss.ss_family == AF_INET)
inet_ntop( AF_INET, &((struct sockaddr_in*)&__ss)->sin_addr, ntop_buf, sizeof(ntop_buf) ); inet_ntop(AF_INET,
&((struct sockaddr_in *)&__ss)->sin_addr,
ntop_buf, sizeof(ntop_buf));
#ifdef UPNP_ENABLE_IPV6 #ifdef UPNP_ENABLE_IPV6
else if (__ss.ss_family == AF_INET6) else if (__ss.ss_family == AF_INET6)
inet_ntop( AF_INET6, &((struct sockaddr_in6*)&__ss)->sin6_addr, ntop_buf, sizeof(ntop_buf) ); inet_ntop(AF_INET6,
&((struct sockaddr_in6 *)&__ss)->sin6_addr,
ntop_buf, sizeof(ntop_buf));
#endif #endif
else else
strncpy( ntop_buf, "<Invalid address family>", sizeof(ntop_buf) ); strncpy(ntop_buf, "<Invalid address family>",
sizeof(ntop_buf));
UpnpPrintf( UPNP_INFO, SSDP, UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__,
__FILE__, __LINE__,
"Start of received response ----------------------------------------------------\n" "Start of received response ----------------------------------------------------\n"
"%s\n" "%s\n"
"End of received response ------------------------------------------------------\n" "End of received response ------------------------------------------------------\n"
"From host %s\n", "From host %s\n", requestBuf, ntop_buf);
requestBuf, /* add thread pool job to handle request */
ntop_buf );
UpnpPrintf( UPNP_PACKET, SSDP, __FILE__, __LINE__,
"Start of received multicast packet --------------------------------------------\n"
"%s\n"
"End of received multicast packet ----------------------------------------------\n",
requestBuf );
//add thread pool job to handle request
if (data != NULL) { if (data != NULL) {
data->parser.msg.msg.length += byteReceived; data->parser.msg.msg.length += (size_t)byteReceived;
// null-terminate /* null-terminate */
data->parser.msg.msg.buf[byteReceived] = 0; data->parser.msg.msg.buf[byteReceived] = 0;
memcpy(&data->dest_addr, &__ss, sizeof(__ss)); memcpy(&data->dest_addr, &__ss, sizeof(__ss));
TPJobInit(&job, (start_routine) TPJobInit(&job, (start_routine)
ssdp_event_handler_thread, data); ssdp_event_handler_thread, data);
TPJobSetFreeFunction( &job, free_ssdp_event_handler_data ); TPJobSetFreeFunction(&job,
free_ssdp_event_handler_data);
TPJobSetPriority(&job, MED_PRIORITY); TPJobSetPriority(&job, MED_PRIORITY);
if (ThreadPoolAdd(&gRecvThreadPool, &job, NULL) != 0)
if( ThreadPoolAdd( &gRecvThreadPool, &job, NULL ) != 0 ) {
free_ssdp_event_handler_data(data); free_ssdp_event_handler_data(data);
} }
} } else
} else {
free_ssdp_event_handler_data(data); free_ssdp_event_handler_data(data);
} }
}
/************************************************************************ /************************************************************************
@@ -910,10 +874,8 @@ int get_ssdp_sockets(MiniServerSockArray *out)
} }
/* For use by ssdp control point. */ /* For use by ssdp control point. */
gSsdpReqSocket4 = out->ssdpReqSock4; gSsdpReqSocket4 = out->ssdpReqSock4;
} else { } else
out->ssdpReqSock4 = INVALID_SOCKET; out->ssdpReqSock4 = INVALID_SOCKET;
}
/* Create the IPv6 socket for SSDP REQUESTS */ /* Create the IPv6 socket for SSDP REQUESTS */
#ifdef UPNP_ENABLE_IPV6 #ifdef UPNP_ENABLE_IPV6
if (strlen(gIF_IPV6) > 0) { if (strlen(gIF_IPV6) > 0) {
@@ -925,14 +887,10 @@ int get_ssdp_sockets(MiniServerSockArray *out)
} }
/* For use by ssdp control point. */ /* For use by ssdp control point. */
gSsdpReqSocket6 = out->ssdpReqSock6; gSsdpReqSocket6 = out->ssdpReqSock6;
} else { } else
out->ssdpReqSock6 = INVALID_SOCKET; out->ssdpReqSock6 = INVALID_SOCKET;
} #endif /* IPv6 */
#endif //IPv6
#endif /* INCLUDE_CLIENT_APIS */ #endif /* INCLUDE_CLIENT_APIS */
/* Create the IPv4 socket for SSDP */ /* Create the IPv4 socket for SSDP */
if (strlen(gIF_IPV4) > 0) { if (strlen(gIF_IPV4) > 0) {
retVal = create_ssdp_sock_v4(&out->ssdpSock4); retVal = create_ssdp_sock_v4(&out->ssdpSock4);
@@ -945,10 +903,8 @@ int get_ssdp_sockets(MiniServerSockArray *out)
#endif #endif
return retVal; return retVal;
} }
} else { } else
out->ssdpSock4 = INVALID_SOCKET; out->ssdpSock4 = INVALID_SOCKET;
}
/* Create the IPv6 socket for SSDP */ /* Create the IPv6 socket for SSDP */
#ifdef UPNP_ENABLE_IPV6 #ifdef UPNP_ENABLE_IPV6
if (strlen(gIF_IPV6) > 0) { if (strlen(gIF_IPV6) > 0) {
@@ -964,10 +920,8 @@ int get_ssdp_sockets(MiniServerSockArray *out)
#endif #endif
return retVal; return retVal;
} }
} else { } else
out->ssdpSock6 = INVALID_SOCKET; out->ssdpSock6 = INVALID_SOCKET;
}
if (strlen(gIF_IPV6_ULA_GUA) > 0) { if (strlen(gIF_IPV6_ULA_GUA) > 0) {
retVal = create_ssdp_sock_v6_ula_gua(&out->ssdpSock6UlaGua); retVal = create_ssdp_sock_v6_ula_gua(&out->ssdpSock6UlaGua);
if (retVal != UPNP_E_SUCCESS) { if (retVal != UPNP_E_SUCCESS) {
@@ -983,11 +937,9 @@ int get_ssdp_sockets(MiniServerSockArray *out)
#endif #endif
return retVal; return retVal;
} }
} else { } else
out->ssdpSock6UlaGua = INVALID_SOCKET; out->ssdpSock6UlaGua = INVALID_SOCKET;
} #endif /* IPv6 */
#endif //IPv6
return UPNP_E_SUCCESS; return UPNP_E_SUCCESS;
} }
@@ -1019,11 +971,9 @@ int create_ssdp_sock_reqv4( SOCKET* ssdpReqSock )
"Error in socket(): %s\n", errorBuffer); "Error in socket(): %s\n", errorBuffer);
return UPNP_E_OUTOF_SOCKET; return UPNP_E_OUTOF_SOCKET;
} }
setsockopt(*ssdpReqSock, IPPROTO_IP, IP_MULTICAST_TTL, setsockopt(*ssdpReqSock, IPPROTO_IP, IP_MULTICAST_TTL,
&ttl, sizeof(ttl)); &ttl, sizeof(ttl));
/* just do it, regardless if fails or not. */
// just do it, regardless if fails or not.
Make_Socket_NoBlocking(*ssdpReqSock); Make_Socket_NoBlocking(*ssdpReqSock);
return UPNP_E_SUCCESS; return UPNP_E_SUCCESS;
@@ -1057,18 +1007,18 @@ int create_ssdp_sock_reqv6( SOCKET* ssdpReqSock )
return UPNP_E_OUTOF_SOCKET; return UPNP_E_OUTOF_SOCKET;
} }
// MUST use scoping of IPv6 addresses to control the propagation os SSDP /* MUST use scoping of IPv6 addresses to control the propagation os SSDP
// messages instead of relying on the Hop Limit (Equivalent to the TTL * messages instead of relying on the Hop Limit (Equivalent to the TTL
// limit in IPv4). * limit in IPv4). */
setsockopt( *ssdpReqSock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, setsockopt( *ssdpReqSock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
&hops, sizeof(hops) ); &hops, sizeof(hops) );
// just do it, regardless if fails or not. /* just do it, regardless if fails or not. */
Make_Socket_NoBlocking( *ssdpReqSock ); Make_Socket_NoBlocking( *ssdpReqSock );
return UPNP_E_SUCCESS; return UPNP_E_SUCCESS;
} }
#endif // IPv6 #endif /* IPv6 */
#endif /* INCLUDE_CLIENT_APIS */ #endif /* INCLUDE_CLIENT_APIS */
@@ -1310,7 +1260,7 @@ int create_ssdp_sock_v6( SOCKET* ssdpSock )
return UPNP_E_SUCCESS; return UPNP_E_SUCCESS;
} }
#endif // IPv6 #endif /* IPv6 */
/************************************************************************ /************************************************************************
* Function : create_ssdp_sock_v6_ula_gua * Function : create_ssdp_sock_v6_ula_gua
@@ -1422,7 +1372,7 @@ int create_ssdp_sock_v6_ula_gua(SOCKET *ssdpSock)
return UPNP_E_SUCCESS; return UPNP_E_SUCCESS;
} }
#endif //IPv6 #endif /* IPv6 */
#endif /* EXCLUDE_SSDP */ #endif /* EXCLUDE_SSDP */

Some files were not shown because too many files have changed in this diff Show More