Compare commits
38 Commits
last_svn_1
...
release-1.
Author | SHA1 | Date | |
---|---|---|---|
![]() |
95f7a7eeef | ||
![]() |
ca50c2153e | ||
![]() |
c73d870f46 | ||
![]() |
ab54cb3dc5 | ||
![]() |
c33b11d09f | ||
![]() |
4966423d96 | ||
![]() |
2fb55d3874 | ||
![]() |
d2238615e3 | ||
![]() |
2fcbe6df52 | ||
![]() |
467f9987a1 | ||
![]() |
8fbecaee5e | ||
![]() |
55d581481f | ||
![]() |
a0b405f902 | ||
![]() |
b37f9ac64a | ||
![]() |
2dad42679d | ||
![]() |
ea00f0f222 | ||
![]() |
f3ae1b4116 | ||
![]() |
67009170d1 | ||
![]() |
2b399b1791 | ||
![]() |
0bec9ec1ae | ||
![]() |
25a4bd6d25 | ||
![]() |
5755ac022f | ||
![]() |
0158f52ee2 | ||
![]() |
0db4a6beac | ||
![]() |
575e5fc196 | ||
![]() |
0e45dd9b8f | ||
![]() |
ae516b6bd3 | ||
![]() |
7137f6e261 | ||
![]() |
92b241b560 | ||
![]() |
2b3ab1799b | ||
![]() |
4657e57766 | ||
![]() |
21660334e4 | ||
![]() |
97af8b6fdb | ||
![]() |
934bd2682f | ||
![]() |
b8e9628140 | ||
![]() |
b3b7a91a64 | ||
![]() |
ebc941f265 | ||
![]() |
842a6ce5c8 |
104
.gitignore
vendored
Normal file
104
.gitignore
vendored
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
#
|
||||||
|
# NOTE! Don't add files that are generated in specific
|
||||||
|
# subdirectories here. Add them in the ".gitignore" file
|
||||||
|
# in that subdirectory instead.
|
||||||
|
#
|
||||||
|
# NOTE! Please use 'git ls-files -i --exclude-standard'
|
||||||
|
# command after changing this file, to see if there are
|
||||||
|
# any tracked files which get ignored after the change.
|
||||||
|
#
|
||||||
|
# Normal rules
|
||||||
|
#
|
||||||
|
.*
|
||||||
|
*.o
|
||||||
|
*.o.*
|
||||||
|
*.a
|
||||||
|
*.s
|
||||||
|
*.ko
|
||||||
|
*.so
|
||||||
|
*.so.dbg
|
||||||
|
*.mod.c
|
||||||
|
*.i
|
||||||
|
*.lst
|
||||||
|
*.symtypes
|
||||||
|
*.order
|
||||||
|
modules.builtin
|
||||||
|
*.elf
|
||||||
|
*.bin
|
||||||
|
*.gz
|
||||||
|
*.bz2
|
||||||
|
*.lzma
|
||||||
|
*.patch
|
||||||
|
*.gcno
|
||||||
|
|
||||||
|
#
|
||||||
|
# Top-level generic files
|
||||||
|
#
|
||||||
|
/tags
|
||||||
|
/TAGS
|
||||||
|
/linux
|
||||||
|
/vmlinux
|
||||||
|
/vmlinuz
|
||||||
|
/System.map
|
||||||
|
/Module.markers
|
||||||
|
/Module.symvers
|
||||||
|
|
||||||
|
#
|
||||||
|
# git files that we don't want to ignore even it they are dot-files
|
||||||
|
#
|
||||||
|
!.gitignore
|
||||||
|
!.mailmap
|
||||||
|
|
||||||
|
#
|
||||||
|
# Generated include files
|
||||||
|
#
|
||||||
|
include/config
|
||||||
|
include/linux/version.h
|
||||||
|
include/generated
|
||||||
|
|
||||||
|
# stgit generated dirs
|
||||||
|
patches-*
|
||||||
|
|
||||||
|
# quilt's files
|
||||||
|
patches
|
||||||
|
series
|
||||||
|
|
||||||
|
# cscope files
|
||||||
|
cscope.*
|
||||||
|
ncscope.*
|
||||||
|
|
||||||
|
# gnu global files
|
||||||
|
GPATH
|
||||||
|
GRTAGS
|
||||||
|
GSYMS
|
||||||
|
GTAGS
|
||||||
|
|
||||||
|
*.orig
|
||||||
|
*~
|
||||||
|
\#*#
|
||||||
|
*.lo
|
||||||
|
*.la
|
||||||
|
Makefile
|
||||||
|
Makefile.in
|
||||||
|
aclocal.m4
|
||||||
|
autoconfig.h
|
||||||
|
autoconfig.h.in
|
||||||
|
autom4te.cache/
|
||||||
|
build-aux/
|
||||||
|
config.log
|
||||||
|
config.status
|
||||||
|
configure
|
||||||
|
libtool
|
||||||
|
libupnp.pc
|
||||||
|
m4/libtool.m4
|
||||||
|
m4/ltoptions.m4
|
||||||
|
m4/ltsugar.m4
|
||||||
|
m4/ltversion.m4
|
||||||
|
m4/lt~obsolete.m4
|
||||||
|
stamp-h1
|
||||||
|
upnp/inc/stamp-h2
|
||||||
|
upnp/inc/upnpconfig.h
|
||||||
|
upnp/sample/upnp_tv_combo
|
||||||
|
upnp/sample/upnp_tv_ctrlpt
|
||||||
|
upnp/sample/upnp_tv_device
|
||||||
|
|
188
ChangeLog
188
ChangeLog
@@ -2,6 +2,194 @@
|
|||||||
Version 1.6.7
|
Version 1.6.7
|
||||||
*******************************************************************************
|
*******************************************************************************
|
||||||
|
|
||||||
|
2010-10-01 Fabrice Fontaine <fabrice.fontaine(at)orange-ftgroup.com>
|
||||||
|
|
||||||
|
Adding --disable-notification-reordering option
|
||||||
|
|
||||||
|
Adding a configure flag to disable GENA notification reordering as even
|
||||||
|
with an imillisleep(1), this mechanism consumes too much CPU on embedded
|
||||||
|
devices when there is a burst of notifications.
|
||||||
|
|
||||||
|
2010-09-30 Fabrice Fontaine <fabrice.fontaine(at)orange-ftgroup.com>
|
||||||
|
|
||||||
|
Bug fix when there is no service in embedded devices
|
||||||
|
|
||||||
|
When a device with embedded devices (like IGD) when created and one of
|
||||||
|
the embedded devices did not have any service, there was a Segmentation
|
||||||
|
Fault (see SF Tracker [ 2688125 ]).
|
||||||
|
|
||||||
|
Original SF Tracker issue follows:
|
||||||
|
|
||||||
|
SF Tracker [ 2688125 ] v1.6.6 crashes on subdevices without services
|
||||||
|
Submitted by: Arno Willig ( akw ) - 2009-03-15 22:45:23 BRT
|
||||||
|
|
||||||
|
I discovered a bug, which will make libupnp (1.6.6) segfault, when you
|
||||||
|
create a upnp description document with multiple devices which have
|
||||||
|
subdevices, but no own services.
|
||||||
|
|
||||||
|
The crash occurs in genlib/service_table.c in line 977:
|
||||||
|
end->next =
|
||||||
|
getServiceList( currentDevice, &next_end, URLBase );
|
||||||
|
|
||||||
|
In this case "end" seems not to be defined, so end->next crashes.
|
||||||
|
|
||||||
|
Can anyone confirm this, please?
|
||||||
|
|
||||||
|
2010-09-28 Marc Essayan <marc.essayan(at)orange-ftgroup.com>
|
||||||
|
|
||||||
|
Bug fix on burst of GENA notification
|
||||||
|
|
||||||
|
When a lot of notifications were generated by a device in a short
|
||||||
|
period of time then 100% of the CPU was used to reorder those
|
||||||
|
notifications by pushing back the thread in the job queue. This
|
||||||
|
mechanism has been modified so now thread sleep 1 ms before being
|
||||||
|
pushed back into the job queue.
|
||||||
|
|
||||||
|
Removing DEFAULT_SCHED_PARAM parameter and use
|
||||||
|
sched_get_priority_min(DEFAULT_POLICY) instead.
|
||||||
|
|
||||||
|
2010-09-22 Fabrice Fontaine <fabrice.fontaine(at)orange-ftgroup.com>
|
||||||
|
|
||||||
|
Bug fix on M-SEARCH response
|
||||||
|
|
||||||
|
Devices must respond to M-SEARCH requests for any supported version and the
|
||||||
|
response should specify the same version as was contained in the search target.
|
||||||
|
Previously, the device did not answer if the M-SEARCH request did not
|
||||||
|
contain the same version number than the version number of the device.
|
||||||
|
|
||||||
|
2010-09-21 Fabrice Fontaine <fabrice.fontaine(at)orange-ftgroup.com>
|
||||||
|
|
||||||
|
Add Content-Language iff Accept-Language
|
||||||
|
|
||||||
|
Add Content-Language header in the response if and only if there is an
|
||||||
|
Accept-Language header in the request.
|
||||||
|
|
||||||
|
2010-09-21 Fabrice Fontaine <fabrice.fontaine(at)orange-ftgroup.com>
|
||||||
|
|
||||||
|
Addition of WEB_SERVER_CONTENT_LANGUAGE parameter
|
||||||
|
|
||||||
|
This patch adds the WEB_SERVER_CONTENT_LANGUAGE parameter so the user can specify
|
||||||
|
the language used by the device during Description and Presentation steps of UPnP
|
||||||
|
through the HTTP CONTENT-LANGUAGE header.
|
||||||
|
By default, the WEB_SERVER_CONTENT_LANGUAGE is an empty string so no
|
||||||
|
CONTENT-LANGUAGE is added.
|
||||||
|
|
||||||
|
2010-09-18 Fabrice Fontaine <fabrice.fontaine(at)orange-ftgroup.com>
|
||||||
|
|
||||||
|
Customize the stack size of the threads used by pupnp through the new
|
||||||
|
THREAD_STACK_SIZE variable.
|
||||||
|
|
||||||
|
This patch allows a user to customize the stack size of the threads used by
|
||||||
|
pupnp through the new THREAD_STACK_SIZE variable. This is especially useful
|
||||||
|
on embedded systems with limited memory where the user can set THREAD_STACK_SIZE
|
||||||
|
to ITHREAD_STACK_MIN.
|
||||||
|
|
||||||
|
However, as this modification can have side effects, I set 0 as the default
|
||||||
|
value, so threads will continue to use the default stack size of the system
|
||||||
|
(which varies greatly as stated in
|
||||||
|
https://computing.llnl.gov/tutorials/pthreads/).
|
||||||
|
|
||||||
|
2010-09-16 Fabrice Fontaine <fabrice.fontaine(at)orange-ftgroup.com>
|
||||||
|
|
||||||
|
Broken IPv6.
|
||||||
|
IPv6 is currently broken in latest release of branch-1.6.x, so find a
|
||||||
|
patch attached that correct the issue (small fixes on define, undef and
|
||||||
|
retVal).
|
||||||
|
|
||||||
|
2010-09-10 Warwick Harvey <warwick.harvey(at)tieto.com>
|
||||||
|
Patch to take notice of UPNP_USE_RWLOCK flag
|
||||||
|
|
||||||
|
The configure.ac file included with UPnP checks for the presence of the
|
||||||
|
pthread_rwlock_t type, and then sets the value of the UPNP_USE_RWLOCK
|
||||||
|
flag appropriately. However, this flag is not referenced at all in the
|
||||||
|
source code, and thus the code does not compile on systems that don't
|
||||||
|
have the pthread_rwlock_t type (such as Android).
|
||||||
|
|
||||||
|
Please find attached a patch (against the current 1.6.x head) that checks
|
||||||
|
the value of this flag and falls back on using mutexes if read-write
|
||||||
|
locks are not available.
|
||||||
|
|
||||||
|
2010-09-10 Jean Sigwald <jean.sigwald(at)orange-ftgroup.com>
|
||||||
|
I discovered a reliable denial-of-service issue on the last stable
|
||||||
|
release of libupnp (1.6.6) remotely triggerable by any
|
||||||
|
unauthenticated user. The issue is related with a bad parsing of
|
||||||
|
malformed XML.
|
||||||
|
|
||||||
|
2010-09-10 Chandra Penke <chandrapenke(at)mcntech.com>
|
||||||
|
* SF Patch Tracker [ 2854711 ] Patch for Solaris10 compilation and usage
|
||||||
|
Submitted By: zephyrus ( zephyrus00jp )
|
||||||
|
|
||||||
|
Patch for Solaris10 compilation and usage.
|
||||||
|
|
||||||
|
2010-09-10 Chandra Penke <chandrapenke(at)mcntech.com>
|
||||||
|
Add support for conditionally enabling ipv6.
|
||||||
|
|
||||||
|
2010-09-10 Chandra Penke <chandrapenke(at)mcntech.com>
|
||||||
|
Fix for compilation in debug builds.
|
||||||
|
|
||||||
|
Ensure internal methods are declared as static since debug builds don't inline.
|
||||||
|
|
||||||
|
2010-09-09 Chandra Penke <chandrapenke(at)mcntech.com>
|
||||||
|
Fix for regression in SSDP code to send/receive messages over UDP
|
||||||
|
|
||||||
|
Sending messages over UDP is broken in some Apple OSes
|
||||||
|
such as OS X and iOS. This might be broken in other OSes to but didn't
|
||||||
|
verify.
|
||||||
|
|
||||||
|
The fix is to modify the socket lenght argument of sendto to use the correct
|
||||||
|
sockaddr lenght dependng on whether the socket is IPV4 or IPV6.
|
||||||
|
|
||||||
|
Also added some error checks and debugging related to the issue
|
||||||
|
|
||||||
|
2010-09-07 Marcelo Jimenez <mroberto(at)users.sourceforge.net>
|
||||||
|
Using UpnpReadHttpGet to download large files causes the application to
|
||||||
|
crash. This happens when the file being downloaded exceeds the device
|
||||||
|
memory - entirely possible when transferring video files.
|
||||||
|
The programmatic cause is that the logic implemented in the function
|
||||||
|
http_ReadHttpGet (which UpnpReadHttpGet calls) reads the entire file
|
||||||
|
into memory. The fix modifies the existing logic to discard data after
|
||||||
|
it's been read; there's no reason to keep it around since the caller
|
||||||
|
of UpnpReadHttpGet already has a copy of it.
|
||||||
|
|
||||||
|
This issue exists in 1.6.6 as well as the latest sources.
|
||||||
|
|
||||||
|
Patch submitted by Chandra (inactiveneurons).
|
||||||
|
|
||||||
|
2010-09-07 Marcelo Jimenez <mroberto(at)users.sourceforge.net>
|
||||||
|
In the latest sources, http_RequestAndResponse and other methods that
|
||||||
|
use connect() are broken. More specifically, connect() in these methods
|
||||||
|
is returning with an EINVAL. The programatic cause is that the address_len
|
||||||
|
argument passed to connect() is different in IPV4 vs IPV6 (as described in:
|
||||||
|
http://www.opengroup.org/onlinepubs/009695399/functions/connect.html).
|
||||||
|
The current code always uses the IPV6 size. The fix modifies each use of
|
||||||
|
connect() to use the correct size based on the address family being used.
|
||||||
|
|
||||||
|
Patch submitted by Chandra (inactiveneurons).
|
||||||
|
|
||||||
|
2010-09-07 Marcelo Jimenez <mroberto(at)users.sourceforge.net>
|
||||||
|
Fix compilation error in upnp/src/gena/gena_ctrlpt.c (this is most
|
||||||
|
likely an error on all platforms).
|
||||||
|
|
||||||
|
Patch submitted by Chandra (inactiveneurons).
|
||||||
|
|
||||||
|
2010-09-07 Marcelo Jimenez <mroberto(at)users.sourceforge.net>
|
||||||
|
Fix compilation error in upnp/src/inc/ssdplib.h when compiling in OS X
|
||||||
|
(the netinet/* headers are not available).
|
||||||
|
|
||||||
|
Patch submitted by Chandra (inactiveneurons).
|
||||||
|
|
||||||
|
2010-09-07 Marcelo Jimenez <mroberto(at)users.sourceforge.net>
|
||||||
|
Fix compilation error in ixml/inc/ixml.h when compiling with an
|
||||||
|
Objective-C compiler (when cross-compiling for iPhone devices).
|
||||||
|
|
||||||
|
Patch submitted by Chandra (inactiveneurons).
|
||||||
|
|
||||||
|
2010-08-21 Marcelo Jimenez <mroberto(at)users.sourceforge.net>
|
||||||
|
* Issue regarding the GENA notifications. A string termination indicator
|
||||||
|
was added at the end of the notification ("\r\n") in
|
||||||
|
notify_send_and_recv() in upnp/src/gena/gena_device.c.
|
||||||
|
Patch by Fabrice Fontaine.
|
||||||
|
|
||||||
2010-08-21 Marcelo Jimenez <mroberto(at)users.sourceforge.net>
|
2010-08-21 Marcelo Jimenez <mroberto(at)users.sourceforge.net>
|
||||||
* The last part of Ronan Menard's patch.
|
* The last part of Ronan Menard's patch.
|
||||||
|
|
||||||
|
2
README
2
README
@@ -1,7 +1,7 @@
|
|||||||
Portable SDK for UPnP* Devices (libupnp)
|
Portable SDK for UPnP* Devices (libupnp)
|
||||||
|
|
||||||
Copyright (c) 2000-2003 Intel Corporation - All Rights Reserved.
|
Copyright (c) 2000-2003 Intel Corporation - All Rights Reserved.
|
||||||
Copyright (c) 2005-2006 R<EFBFBD>mi Turboult <r3mi@users.sourceforge.net>
|
Copyright (c) 2005-2006 Rémi Turboult <r3mi@users.sourceforge.net>
|
||||||
Copyright (c) 2006 Michel Pfeiffer and others <virtual_worlds@gmx.de>
|
Copyright (c) 2006 Michel Pfeiffer and others <virtual_worlds@gmx.de>
|
||||||
|
|
||||||
See LICENSE for details.
|
See LICENSE for details.
|
||||||
|
1
THANKS
1
THANKS
@@ -13,6 +13,7 @@ exempt of errors.
|
|||||||
- Arno Willig
|
- Arno Willig
|
||||||
- Bob Ciora
|
- Bob Ciora
|
||||||
- Carlo Parata
|
- Carlo Parata
|
||||||
|
- Chandra (inactiveneurons)
|
||||||
- Chaos
|
- Chaos
|
||||||
- Charles Nepveu (cnepveu)
|
- Charles Nepveu (cnepveu)
|
||||||
- Chris Pickel
|
- Chris Pickel
|
||||||
|
@@ -1,86 +1,101 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////
|
/**************************************************************************
|
||||||
//
|
*
|
||||||
// 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 INTERNAL_CONFIG_H
|
#ifndef INTERNAL_CONFIG_H
|
||||||
#define INTERNAL_CONFIG_H
|
#define INTERNAL_CONFIG_H
|
||||||
|
|
||||||
|
|
||||||
#include "autoconfig.h"
|
#include "autoconfig.h"
|
||||||
|
|
||||||
|
|
||||||
/** @name Compile time configuration options
|
/*!
|
||||||
|
* \name Compile time configuration options
|
||||||
|
*
|
||||||
* The Linux SDK for UPnP Devices contains some compile-time parameters
|
* The Linux SDK for UPnP Devices contains some compile-time parameters
|
||||||
* that effect the behavior of the SDK. All configuration options are
|
* that effect the behavior of the SDK. All configuration options are
|
||||||
* located in {\tt src/inc/config.h}.
|
* located in {\tt src/inc/config.h}.
|
||||||
|
*
|
||||||
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//@{
|
|
||||||
|
|
||||||
/** @name THREAD_IDLE_TIME
|
/*!
|
||||||
|
* \name THREAD_IDLE_TIME
|
||||||
|
*
|
||||||
* The {\tt THREAD_IDLE_TIME} constant determines when a thread will be
|
* The {\tt THREAD_IDLE_TIME} constant determines when a thread will be
|
||||||
* removed from the thread pool and returned to the operating system. When
|
* removed from the thread pool and returned to the operating system. When
|
||||||
* a thread in the thread pool has been idle for this number of milliseconds
|
* a thread in the thread pool has been idle for this number of milliseconds
|
||||||
* the thread will be released from the thread pool. The default value is
|
* the thread will be released from the thread pool. The default value is
|
||||||
* 5000 milliseconds (5 seconds).
|
* 5000 milliseconds (5 seconds).
|
||||||
|
*
|
||||||
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//@{
|
|
||||||
#define THREAD_IDLE_TIME 5000
|
#define THREAD_IDLE_TIME 5000
|
||||||
//@}
|
/* @} */
|
||||||
|
|
||||||
/** @name JOBS_PER_THREAD
|
|
||||||
|
/*!
|
||||||
|
* \name JOBS_PER_THREAD
|
||||||
|
*
|
||||||
* The {\tt JOBS_PER_THREAD} constant determines when a new thread will be
|
* The {\tt JOBS_PER_THREAD} constant determines when a new thread will be
|
||||||
* allocated to the thread pool inside the SDK. The thread pool will
|
* allocated to the thread pool inside the SDK. The thread pool will
|
||||||
* try and maintain this jobs/thread ratio. When the jobs/thread ratio
|
* try and maintain this jobs/thread ratio. When the jobs/thread ratio
|
||||||
* becomes greater than this, then a new thread (up to the max) will be
|
* becomes greater than this, then a new thread (up to the max) will be
|
||||||
* allocated to the thread pool. The default ratio is 10 jobs/thread.
|
* allocated to the thread pool. The default ratio is 10 jobs/thread.
|
||||||
|
*
|
||||||
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//@{
|
|
||||||
#define JOBS_PER_THREAD 10
|
#define JOBS_PER_THREAD 10
|
||||||
//@}
|
/* @} */
|
||||||
|
|
||||||
/** @name MIN_THREADS
|
|
||||||
|
/*!
|
||||||
|
* \name MIN_THREADS
|
||||||
|
*
|
||||||
* The {\tt MIN_THREADS} constant defines the minimum number of threads the
|
* The {\tt MIN_THREADS} constant defines the minimum number of threads the
|
||||||
* thread pool inside the SDK will create. The thread pool will
|
* thread pool inside the SDK will create. The thread pool will
|
||||||
* always have this number of threads. These threads are used
|
* always have this number of threads. These threads are used
|
||||||
* for both callbacks into applications built on top of the SDK and also
|
* for both callbacks into applications built on top of the SDK and also
|
||||||
* for making connections to other control points and devices. This number
|
* for making connections to other control points and devices. This number
|
||||||
* includes persistent threads. The default value is two threads.
|
* includes persistent threads. The default value is two threads.
|
||||||
|
*
|
||||||
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//@{
|
|
||||||
#define MIN_THREADS 2
|
#define MIN_THREADS 2
|
||||||
//@}
|
/* @} */
|
||||||
|
|
||||||
/** @name MAX_THREADS
|
|
||||||
|
/*!
|
||||||
|
* \name MAX_THREADS
|
||||||
|
*
|
||||||
* The {\tt MAX_THREADS} constant defines the maximum number of threads the
|
* The {\tt MAX_THREADS} constant defines the maximum number of threads the
|
||||||
* thread pool inside the SDK will create. These threads are used
|
* thread pool inside the SDK will create. These threads are used
|
||||||
* for both callbacks into applications built on top of the library and also
|
* for both callbacks into applications built on top of the library and also
|
||||||
@@ -89,60 +104,111 @@
|
|||||||
* necessary for correct operation. This value can be increased for greater
|
* necessary for correct operation. This value can be increased for greater
|
||||||
* performance in operation at the expense of greater memory overhead. The
|
* performance in operation at the expense of greater memory overhead. The
|
||||||
* default value is 12.
|
* default value is 12.
|
||||||
|
*
|
||||||
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//@{
|
|
||||||
#define MAX_THREADS 12
|
#define MAX_THREADS 12
|
||||||
//@}
|
/* @} */
|
||||||
|
|
||||||
/** @name MAX_JOBS_TOTAL
|
|
||||||
|
/*!
|
||||||
|
* \name THREAD_STACK_SIZE
|
||||||
|
*
|
||||||
|
* The {\tt THREAD_STACK_SIZE} constant defines the minimum stack size (in
|
||||||
|
* bytes) allocated for the stack of each thread the thread pool inside the
|
||||||
|
* SDK will create. These threads are used for both callbacks into
|
||||||
|
* applications built on top of the library and also for making connections
|
||||||
|
* to other control points and devices. This value will not be used if it
|
||||||
|
* is lower than ITHREAD_STACK_MIN or greater than a system-imposed limit.
|
||||||
|
* This value can be used to lower memory overhead in embedded systems.
|
||||||
|
* The default value is 0 (so it is not used by default).
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define THREAD_STACK_SIZE 0
|
||||||
|
/* @} */
|
||||||
|
|
||||||
|
|
||||||
|
/*! \name MAX_JOBS_TOTAL
|
||||||
|
*
|
||||||
* The {\tt MAX_JOBS_TOTAL} constant determines the maximum number of jobs
|
* The {\tt MAX_JOBS_TOTAL} constant determines the maximum number of jobs
|
||||||
* that can be queued. If this limit is reached further jobs will be thrown
|
* that can be queued. If this limit is reached further jobs will be thrown
|
||||||
* to avoid memory exhaustion. The default value 100.
|
* to avoid memory exhaustion. The default value 100.
|
||||||
* (Added by Axis.)
|
* (Added by Axis.)
|
||||||
|
*
|
||||||
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//@{
|
|
||||||
#define MAX_JOBS_TOTAL 100
|
#define MAX_JOBS_TOTAL 100
|
||||||
//@}
|
/* @} */
|
||||||
|
|
||||||
/** @name DEFAULT_SOAP_CONTENT_LENGTH
|
|
||||||
|
/*!
|
||||||
|
* \name DEFAULT_SOAP_CONTENT_LENGTH
|
||||||
|
*
|
||||||
* SOAP messages will read at most {\tt DEFAULT_SOAP_CONTENT_LENGTH} bytes.
|
* SOAP messages will read at most {\tt DEFAULT_SOAP_CONTENT_LENGTH} bytes.
|
||||||
* This prevents devices that have a misbehaving web server to send
|
* This prevents devices that have a misbehaving web server to send
|
||||||
* a large amount of data to the control point causing it to crash.
|
* a large amount of data to the control point causing it to crash.
|
||||||
* This can be adjusted dynamically with {\tt UpnpSetMaxContentLength}.
|
* This can be adjusted dynamically with {\tt UpnpSetMaxContentLength}.
|
||||||
|
*
|
||||||
|
* @{
|
||||||
*/
|
*/
|
||||||
//@{
|
|
||||||
#define DEFAULT_SOAP_CONTENT_LENGTH 16000
|
#define DEFAULT_SOAP_CONTENT_LENGTH 16000
|
||||||
//@}
|
/* @} */
|
||||||
|
|
||||||
/** @name NUM_SSDP_COPY
|
|
||||||
|
/*!
|
||||||
|
* \name NUM_SSDP_COPY
|
||||||
|
*
|
||||||
* This configuration parameter determines how many copies of each SSDP
|
* This configuration parameter determines how many copies of each SSDP
|
||||||
* advertisement and search packets will be sent. By default it will send two
|
* advertisement and search packets will be sent. By default it will send two
|
||||||
* copies of every packet.
|
* copies of every packet.
|
||||||
|
*
|
||||||
|
* @{
|
||||||
*/
|
*/
|
||||||
//@{
|
|
||||||
#define NUM_SSDP_COPY 2
|
#define NUM_SSDP_COPY 2
|
||||||
//@}
|
/* @} */
|
||||||
|
|
||||||
/** @name SSDP_PAUSE
|
|
||||||
|
/*!
|
||||||
|
* \name SSDP_PAUSE
|
||||||
|
*
|
||||||
* This configuration parameter determines the pause between identical SSDP
|
* This configuration parameter determines the pause between identical SSDP
|
||||||
* advertisement and search packets. The pause is measured in milliseconds
|
* advertisement and search packets. The pause is measured in milliseconds
|
||||||
* and defaults to 100.
|
* and defaults to 100.
|
||||||
|
*
|
||||||
|
* @{
|
||||||
*/
|
*/
|
||||||
//@{
|
|
||||||
#define SSDP_PAUSE 100
|
#define SSDP_PAUSE 100
|
||||||
//@}
|
/* @} */
|
||||||
|
|
||||||
/** @name WEB_SERVER_BUF_SIZE
|
/*!
|
||||||
|
* \name WEB_SERVER_BUF_SIZE
|
||||||
|
*
|
||||||
* This configuration parameter sets the maximum buffer size for the
|
* This configuration parameter sets the maximum buffer size for the
|
||||||
* webserver. The default value is 1MB.
|
* webserver. The default value is 1MB.
|
||||||
|
*
|
||||||
|
* @{
|
||||||
*/
|
*/
|
||||||
//@{
|
|
||||||
#define WEB_SERVER_BUF_SIZE (1024*1024)
|
#define WEB_SERVER_BUF_SIZE (1024*1024)
|
||||||
//@}
|
/* @} */
|
||||||
|
|
||||||
/** @name AUTO_RENEW_TIME
|
/*!
|
||||||
|
* \name WEB_SERVER_CONTENT_LANGUAGE
|
||||||
|
*
|
||||||
|
* This configuration parameter sets the value of the Content-Language
|
||||||
|
* header for the webserver. Thanks to this parameter, the use can advertize
|
||||||
|
* the language used by the device in the description (friendlyName) and
|
||||||
|
* presentation steps of UPnP. The default value is empty string so no
|
||||||
|
* Content-Language header is added.
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define WEB_SERVER_CONTENT_LANGUAGE ""
|
||||||
|
/* @} */
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \name AUTO_RENEW_TIME
|
||||||
|
*
|
||||||
* The {\tt AUTO_RENEW_TIME} is the time, in seconds, before a subscription
|
* The {\tt AUTO_RENEW_TIME} is the time, in seconds, before a subscription
|
||||||
* expires that the SDK automatically resubscribes. The default
|
* expires that the SDK automatically resubscribes. The default
|
||||||
* value is 10 seconds. Setting this value too low can result in the
|
* value is 10 seconds. Setting this value too low can result in the
|
||||||
@@ -150,71 +216,87 @@
|
|||||||
* subscription to timeout. In order to avoid continually resubscribing
|
* subscription to timeout. In order to avoid continually resubscribing
|
||||||
* the minimum subscription time is five seconds more than the auto renew
|
* the minimum subscription time is five seconds more than the auto renew
|
||||||
* time.
|
* time.
|
||||||
|
*
|
||||||
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//@{
|
|
||||||
#define AUTO_RENEW_TIME 10
|
#define AUTO_RENEW_TIME 10
|
||||||
//@}
|
/* @} */
|
||||||
|
|
||||||
/** @name CP_MINIMUM_SUBSCRIPTION_TIME
|
/*!
|
||||||
|
* \name CP_MINIMUM_SUBSCRIPTION_TIME
|
||||||
|
*
|
||||||
* The {\tt CP_MINIMUM_SUBSCRIPTION_TIME} is the minimum subscription time
|
* The {\tt CP_MINIMUM_SUBSCRIPTION_TIME} is the minimum subscription time
|
||||||
* allowed for a control point using the SDK. Subscribing for less than
|
* allowed for a control point using the SDK. Subscribing for less than
|
||||||
* this time automatically results in a subscription for this amount. The
|
* this time automatically results in a subscription for this amount. The
|
||||||
* default value is 5 seconds more than the {\tt AUTO_RENEW_TIME}, or 15
|
* default value is 5 seconds more than the {\tt AUTO_RENEW_TIME}, or 15
|
||||||
* seconds.
|
* seconds.
|
||||||
|
*
|
||||||
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//@{
|
|
||||||
#define CP_MINIMUM_SUBSCRIPTION_TIME (AUTO_RENEW_TIME + 5)
|
#define CP_MINIMUM_SUBSCRIPTION_TIME (AUTO_RENEW_TIME + 5)
|
||||||
//@}
|
/* @} */
|
||||||
|
|
||||||
/** @name MAX_SEARCH_TIME
|
|
||||||
|
/*!
|
||||||
|
* \name MAX_SEARCH_TIME
|
||||||
|
*
|
||||||
* The {\tt MAX_SEARCH_TIME} is the maximum time
|
* The {\tt MAX_SEARCH_TIME} is the maximum time
|
||||||
* allowed for an SSDP search by a control point. Searching for greater than
|
* allowed for an SSDP search by a control point. Searching for greater than
|
||||||
* this time automatically results in a search for this amount. The default
|
* this time automatically results in a search for this amount. The default
|
||||||
* value is 80 seconds.
|
* value is 80 seconds.
|
||||||
|
*
|
||||||
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//@{
|
|
||||||
#define MAX_SEARCH_TIME 80
|
#define MAX_SEARCH_TIME 80
|
||||||
//@}
|
/* @} */
|
||||||
|
|
||||||
/** @name MIN_SEARCH_TIME
|
|
||||||
|
/*!
|
||||||
|
* \name MIN_SEARCH_TIME
|
||||||
|
*
|
||||||
* The {\tt MIN_SEARCH_TIME} is the minimumm time
|
* The {\tt MIN_SEARCH_TIME} is the minimumm time
|
||||||
* allowed for an SSDP search by a control point. Searching for less than
|
* allowed for an SSDP search by a control point. Searching for less than
|
||||||
* this time automatically results in a search for this amount. The default
|
* this time automatically results in a search for this amount. The default
|
||||||
* value is 2 seconds.
|
* value is 2 seconds.
|
||||||
|
*
|
||||||
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//@{
|
|
||||||
#define MIN_SEARCH_TIME 2
|
#define MIN_SEARCH_TIME 2
|
||||||
//@}
|
/* @} */
|
||||||
|
|
||||||
|
|
||||||
/** @name AUTO_ADVERTISEMENT_TIME
|
/*!
|
||||||
|
* \name AUTO_ADVERTISEMENT_TIME
|
||||||
|
*
|
||||||
* The {\tt AUTO_ADVERTISEMENT_TIME} is the time, in seconds, before an
|
* The {\tt AUTO_ADVERTISEMENT_TIME} is the time, in seconds, before an
|
||||||
* device advertisements expires before a renewed advertisement is sent.
|
* device advertisements expires before a renewed advertisement is sent.
|
||||||
* The default time is 30 seconds.
|
* The default time is 30 seconds.
|
||||||
|
*
|
||||||
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//@{
|
|
||||||
#define AUTO_ADVERTISEMENT_TIME 30
|
#define AUTO_ADVERTISEMENT_TIME 30
|
||||||
//@}
|
/* @} */
|
||||||
|
|
||||||
/** @name SSDP_PACKET_DISTRIBUTE
|
|
||||||
|
/*!
|
||||||
|
* \name SSDP_PACKET_DISTRIBUTE
|
||||||
|
*
|
||||||
* The {\tt SSDP_PACKET_DISTRIBUTE} enables the SSDP packets to be sent
|
* The {\tt SSDP_PACKET_DISTRIBUTE} enables the SSDP packets to be sent
|
||||||
* at an interval equal to half of the expiration time of SSDP packets
|
* at an interval equal to half of the expiration time of SSDP packets
|
||||||
* minus the AUTO_ADVERTISEMENT_TIME. This is used to increase
|
* minus the AUTO_ADVERTISEMENT_TIME. This is used to increase
|
||||||
* the probability of SSDP packets reaching to control points.
|
* the probability of SSDP packets reaching to control points.
|
||||||
* It is recommended that this flag be turned on for embedded wireless
|
* It is recommended that this flag be turned on for embedded wireless
|
||||||
* devices.
|
* devices.
|
||||||
|
*
|
||||||
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//@{
|
|
||||||
#define SSDP_PACKET_DISTRIBUTE 1
|
#define SSDP_PACKET_DISTRIBUTE 1
|
||||||
//@}
|
/* @} */
|
||||||
|
|
||||||
/** @name Module Exclusion
|
|
||||||
|
/*!
|
||||||
|
* \name Module Exclusion
|
||||||
|
*
|
||||||
* Depending on the requirements, the user can selectively discard any of
|
* Depending on the requirements, the user can selectively discard any of
|
||||||
* the major modules like SOAP, GENA, SSDP or the Internal web server. By
|
* the major modules like SOAP, GENA, SSDP or the Internal web server. By
|
||||||
* default everything is included inside the SDK. By setting any of
|
* default everything is included inside the SDK. By setting any of
|
||||||
@@ -230,9 +312,8 @@
|
|||||||
* \item {\tt EXCLUDE_JNI[0,1]}
|
* \item {\tt EXCLUDE_JNI[0,1]}
|
||||||
* \end{itemize}
|
* \end{itemize}
|
||||||
*
|
*
|
||||||
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//@{
|
|
||||||
#define EXCLUDE_SSDP 0
|
#define EXCLUDE_SSDP 0
|
||||||
#define EXCLUDE_SOAP 0
|
#define EXCLUDE_SOAP 0
|
||||||
#define EXCLUDE_GENA 0
|
#define EXCLUDE_GENA 0
|
||||||
@@ -244,24 +325,28 @@
|
|||||||
#else
|
#else
|
||||||
# define EXCLUDE_JNI 1
|
# define EXCLUDE_JNI 1
|
||||||
#endif
|
#endif
|
||||||
//@}
|
/* @} */
|
||||||
|
|
||||||
|
|
||||||
/** @name DEBUG_TARGET
|
/*!
|
||||||
|
* \name DEBUG_TARGET
|
||||||
|
*
|
||||||
* The user has the option to redirect the library output debug messages
|
* The user has the option to redirect the library output debug messages
|
||||||
* to either the screen or to a log file. All the output messages with
|
* to either the screen or to a log file. All the output messages with
|
||||||
* debug level 0 will go to {\tt upnp.err} and messages with debug level
|
* debug level 0 will go to {\tt upnp.err} and messages with debug level
|
||||||
* greater than zero will be redirected to {\tt upnp.out}.
|
* greater than zero will be redirected to {\tt upnp.out}.
|
||||||
|
*
|
||||||
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//@{
|
|
||||||
#define DEBUG_TARGET 1
|
#define DEBUG_TARGET 1
|
||||||
//@}
|
/* @} */
|
||||||
|
|
||||||
|
|
||||||
/** @name Other debugging features
|
/*!
|
||||||
The UPnP SDK contains other features to aid in debugging:
|
* \name Other debugging features
|
||||||
see <upnp/inc/upnpdebug.h>
|
*
|
||||||
|
* The UPnP SDK contains other features to aid in debugging:
|
||||||
|
* see <upnp/inc/upnpdebug.h>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define DEBUG_ALL 1
|
#define DEBUG_ALL 1
|
||||||
@@ -274,36 +359,44 @@
|
|||||||
#define DEBUG_HTTP 0
|
#define DEBUG_HTTP 0
|
||||||
#define DEBUG_API 0
|
#define DEBUG_API 0
|
||||||
|
|
||||||
//@} // Compile time configuration options
|
|
||||||
|
/*
|
||||||
|
* @} Compile time configuration options
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
* Do not change, Internal purpose only!!!
|
* Do not change, Internal purpose only!!!
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
//@{
|
/*!
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set additional defines based on requested configuration
|
* Set additional defines based on requested configuration
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// configure --enable-client
|
|
||||||
|
/* configure --enable-client */
|
||||||
#if UPNP_HAVE_CLIENT
|
#if UPNP_HAVE_CLIENT
|
||||||
# define INCLUDE_CLIENT_APIS 1
|
# define INCLUDE_CLIENT_APIS 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// configure --enable-device
|
|
||||||
|
/* configure --enable-device */
|
||||||
#if UPNP_HAVE_DEVICE
|
#if UPNP_HAVE_DEVICE
|
||||||
# define INCLUDE_DEVICE_APIS 1
|
# define INCLUDE_DEVICE_APIS 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// configure --enable-webserver --enable-device
|
|
||||||
|
/* configure --enable-webserver --enable-device */
|
||||||
#if UPNP_HAVE_WEBSERVER
|
#if UPNP_HAVE_WEBSERVER
|
||||||
# define INTERNAL_WEB_SERVER 1
|
# define INTERNAL_WEB_SERVER 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#undef EXCLUDE_WEB_SERVER
|
#undef EXCLUDE_WEB_SERVER
|
||||||
#undef EXCLUDE_MINISERVER
|
#undef EXCLUDE_MINISERVER
|
||||||
#ifdef INTERNAL_WEB_SERVER
|
#ifdef INTERNAL_WEB_SERVER
|
||||||
@@ -314,6 +407,7 @@
|
|||||||
# define EXCLUDE_MINISERVER 1
|
# define EXCLUDE_MINISERVER 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#if EXCLUDE_GENA == 1 && EXCLUDE_SOAP == 1 && EXCLUDE_WEB_SERVER == 1
|
#if EXCLUDE_GENA == 1 && EXCLUDE_SOAP == 1 && EXCLUDE_WEB_SERVER == 1
|
||||||
# undef EXCLUDE_MINISERVER
|
# undef EXCLUDE_MINISERVER
|
||||||
# define EXCLUDE_MINISERVER 1
|
# define EXCLUDE_MINISERVER 1
|
||||||
@@ -322,6 +416,7 @@
|
|||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#if EXCLUDE_GENA == 0 || EXCLUDE_SOAP == 0 || EXCLUDE_WEB_SERVER == 0
|
#if EXCLUDE_GENA == 0 || EXCLUDE_SOAP == 0 || EXCLUDE_WEB_SERVER == 0
|
||||||
# undef EXCLUDE_MINISERVER
|
# undef EXCLUDE_MINISERVER
|
||||||
# define EXCLUDE_MINISERVER 0
|
# define EXCLUDE_MINISERVER 0
|
||||||
@@ -331,13 +426,9 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
#ifdef INCLUDE_CLIENT_APIS
|
#endif /* INTERNAL_CONFIG_H */
|
||||||
# define CLIENTONLY(x) x
|
|
||||||
#else
|
|
||||||
# define CLIENTONLY(x)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//@}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
10
configure.ac
10
configure.ac
@@ -256,6 +256,16 @@ if test "x$enable_tools" = xyes ; then
|
|||||||
AC_DEFINE(UPNP_HAVE_TOOLS, 1, [see upnpconfig.h])
|
AC_DEFINE(UPNP_HAVE_TOOLS, 1, [see upnpconfig.h])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
RT_BOOL_ARG_ENABLE([ipv6], [no], [ipv6 support])
|
||||||
|
if test "x$enable_ipv6" = xyes ; then
|
||||||
|
AC_DEFINE(UPNP_ENABLE_IPV6, 1, [see upnpconfig.h])
|
||||||
|
fi
|
||||||
|
|
||||||
|
RT_BOOL_ARG_ENABLE([notification_reordering], [yes], [GENA notification reordering in gena_device.c])
|
||||||
|
if test "x$enable_notification_reordering" = xyes ; then
|
||||||
|
AC_DEFINE(UPNP_ENABLE_NOTIFICATION_REORDERING, 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])
|
||||||
|
|
||||||
|
@@ -45,9 +45,13 @@
|
|||||||
|
|
||||||
#include "UpnpGlobal.h" /* For EXPORT_SPEC */
|
#include "UpnpGlobal.h" /* For EXPORT_SPEC */
|
||||||
|
|
||||||
|
/* Define BOOL. */
|
||||||
typedef int BOOL;
|
#ifndef __OBJC__
|
||||||
|
typedef int BOOL;
|
||||||
|
#else
|
||||||
|
/* For Objective C compilers, include objc.h which defines BOOL. */
|
||||||
|
#include <objc/objc.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief The type of DOM strings.
|
* \brief The type of DOM strings.
|
||||||
|
@@ -583,11 +583,14 @@ static int Parser_isValidEndElement(
|
|||||||
IXML_Node *newNode)
|
IXML_Node *newNode)
|
||||||
{
|
{
|
||||||
assert(xmlParser);
|
assert(xmlParser);
|
||||||
assert(xmlParser->pCurElement);
|
|
||||||
assert(xmlParser->pCurElement->element);
|
assert(xmlParser->pCurElement->element);
|
||||||
assert(newNode);
|
assert(newNode);
|
||||||
assert(newNode->nodeName);
|
assert(newNode->nodeName);
|
||||||
|
|
||||||
|
if (xmlParser->pCurElement == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
return strcmp(xmlParser->pCurElement->element, newNode->nodeName) == 0;
|
return strcmp(xmlParser->pCurElement->element, newNode->nodeName) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -115,6 +115,10 @@ typedef enum priority {
|
|||||||
#define DEFAULT_MAX_THREADS 10
|
#define DEFAULT_MAX_THREADS 10
|
||||||
|
|
||||||
|
|
||||||
|
/*! default stack size used by TPAttrInit */
|
||||||
|
#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
|
||||||
|
|
||||||
@@ -154,10 +158,6 @@ typedef int PolicyType;
|
|||||||
#define DEFAULT_POLICY SCHED_OTHER
|
#define DEFAULT_POLICY SCHED_OTHER
|
||||||
|
|
||||||
|
|
||||||
/*! Default priority */
|
|
||||||
#define DEFAULT_SCHED_PARAM 0
|
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: free_routine
|
* Name: free_routine
|
||||||
*
|
*
|
||||||
@@ -182,6 +182,10 @@ typedef struct THREADPOOLATTR
|
|||||||
/* maxThreads, 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;
|
||||||
|
|
||||||
|
/* stackSize (in bytes), this is the minimum stack size allocated for each
|
||||||
|
* thread */
|
||||||
|
size_t stackSize;
|
||||||
|
|
||||||
/* maxIdleTime (in milliseconds) this is the maximum time a thread will
|
/* maxIdleTime (in milliseconds) this is the maximum time a thread will
|
||||||
* remain idle before dying */
|
* remain idle before dying */
|
||||||
int maxIdleTime;
|
int maxIdleTime;
|
||||||
@@ -522,6 +526,20 @@ int TPAttrSetMaxThreads(ThreadPoolAttr *attr, int maxThreads);
|
|||||||
int TPAttrSetMinThreads(ThreadPoolAttr *attr, int minThreads);
|
int TPAttrSetMinThreads(ThreadPoolAttr *attr, int minThreads);
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Function: TPAttrSetStackSize
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Sets the stack size for the thread pool attributes.
|
||||||
|
* Parameters:
|
||||||
|
* attr - must be valid thread pool attributes.
|
||||||
|
* stackSize - value to set
|
||||||
|
* Returns:
|
||||||
|
* Always returns 0.
|
||||||
|
*****************************************************************************/
|
||||||
|
int TPAttrSetStackSize(ThreadPoolAttr *attr, size_t stackSize);
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Function: TPAttrSetIdleTime
|
* Function: TPAttrSetIdleTime
|
||||||
*
|
*
|
||||||
|
@@ -86,6 +86,9 @@ extern "C" {
|
|||||||
#define ITHREAD_CANCELED PTHREAD_CANCELED
|
#define ITHREAD_CANCELED PTHREAD_CANCELED
|
||||||
|
|
||||||
|
|
||||||
|
#define ITHREAD_STACK_MIN PTHREAD_STACK_MIN
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
* Name: ithread_t
|
* Name: ithread_t
|
||||||
*
|
*
|
||||||
@@ -171,7 +174,9 @@ typedef pthread_condattr_t ithread_condattr_t;
|
|||||||
* typedef to pthread_rwlockattr_t
|
* typedef to pthread_rwlockattr_t
|
||||||
* Internal Use Only
|
* Internal Use Only
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
#if UPNP_USE_RWLOCK
|
||||||
typedef pthread_rwlockattr_t ithread_rwlockattr_t;
|
typedef pthread_rwlockattr_t ithread_rwlockattr_t;
|
||||||
|
#endif /* UPNP_USE_RWLOCK */
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -182,7 +187,9 @@ typedef pthread_rwlockattr_t ithread_rwlockattr_t;
|
|||||||
* typedef to pthread_rwlock_t
|
* typedef to pthread_rwlock_t
|
||||||
* Internal Use Only
|
* Internal Use Only
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
#if UPNP_USE_RWLOCK
|
||||||
typedef pthread_rwlock_t ithread_rwlock_t;
|
typedef pthread_rwlock_t ithread_rwlock_t;
|
||||||
|
#endif /* UPNP_USE_RWLOCK */
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -443,7 +450,9 @@ static UPNP_INLINE int ithread_cleanup_thread(void) {
|
|||||||
* Always returns 0.
|
* Always returns 0.
|
||||||
* See man page for pthread_rwlockattr_init
|
* See man page for pthread_rwlockattr_init
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
#define ithread_rwlockattr_init pthread_rwlockattr_init
|
#if UPNP_USE_RWLOCK
|
||||||
|
#define ithread_rwlockattr_init pthread_rwlockattr_init
|
||||||
|
#endif /* UPNP_USE_RWLOCK */
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -459,7 +468,9 @@ static UPNP_INLINE int ithread_cleanup_thread(void) {
|
|||||||
* Always returns 0.
|
* Always returns 0.
|
||||||
* See man page for pthread_rwlockattr_destroy
|
* See man page for pthread_rwlockattr_destroy
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
#define ithread_rwlockattr_destroy pthread_rwlockattr_destroy
|
#if UPNP_USE_RWLOCK
|
||||||
|
#define ithread_rwlockattr_destroy pthread_rwlockattr_destroy
|
||||||
|
#endif /* UPNP_USE_RWLOCK */
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -480,7 +491,9 @@ 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_rwlockattr_setkind_np
|
* See man page for pthread_rwlockattr_setkind_np
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
#define ithread_rwlockatttr_setpshared pthread_rwlockatttr_setpshared
|
#if UPNP_USE_RWLOCK
|
||||||
|
#define ithread_rwlockatttr_setpshared pthread_rwlockatttr_setpshared
|
||||||
|
#endif /* UPNP_USE_RWLOCK */
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -501,7 +514,9 @@ static UPNP_INLINE int ithread_cleanup_thread(void) {
|
|||||||
* Always returns 0.
|
* Always returns 0.
|
||||||
* See man page for pthread_rwlockatttr_getpshared
|
* See man page for pthread_rwlockatttr_getpshared
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
#define ithread_rwlockatttr_getpshared pthread_rwlockatttr_getpshared
|
#if UPNP_USE_RWLOCK
|
||||||
|
#define ithread_rwlockatttr_getpshared pthread_rwlockatttr_getpshared
|
||||||
|
#endif /* UPNP_USE_RWLOCK */
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -519,7 +534,9 @@ static UPNP_INLINE int ithread_cleanup_thread(void) {
|
|||||||
* Always returns 0.
|
* Always returns 0.
|
||||||
* See man page for pthread_rwlock_init
|
* See man page for pthread_rwlock_init
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
#define ithread_rwlock_init pthread_rwlock_init
|
#if UPNP_USE_RWLOCK
|
||||||
|
#define ithread_rwlock_init pthread_rwlock_init
|
||||||
|
#endif /* UPNP_USE_RWLOCK */
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -536,7 +553,9 @@ static UPNP_INLINE int ithread_cleanup_thread(void) {
|
|||||||
* Always returns 0.
|
* Always returns 0.
|
||||||
* See man page for pthread_rwlock_rdlock
|
* See man page for pthread_rwlock_rdlock
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
#define ithread_rwlock_rdlock pthread_rwlock_rdlock
|
#if UPNP_USE_RWLOCK
|
||||||
|
#define ithread_rwlock_rdlock pthread_rwlock_rdlock
|
||||||
|
#endif /* UPNP_USE_RWLOCK */
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -553,7 +572,9 @@ static UPNP_INLINE int ithread_cleanup_thread(void) {
|
|||||||
* Always returns 0.
|
* Always returns 0.
|
||||||
* See man page for pthread_rwlock_wrlock
|
* See man page for pthread_rwlock_wrlock
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
#define ithread_rwlock_wrlock pthread_rwlock_wrlock
|
#if UPNP_USE_RWLOCK
|
||||||
|
#define ithread_rwlock_wrlock pthread_rwlock_wrlock
|
||||||
|
#endif /* UPNP_USE_RWLOCK */
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -571,7 +592,9 @@ static UPNP_INLINE int ithread_cleanup_thread(void) {
|
|||||||
* Always returns 0.
|
* Always returns 0.
|
||||||
* See man page for pthread_rwlock_unlock
|
* See man page for pthread_rwlock_unlock
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
#define ithread_rwlock_unlock pthread_rwlock_unlock
|
#if UPNP_USE_RWLOCK
|
||||||
|
#define ithread_rwlock_unlock pthread_rwlock_unlock
|
||||||
|
#endif /* UPNP_USE_RWLOCK */
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -590,7 +613,9 @@ static UPNP_INLINE int ithread_cleanup_thread(void) {
|
|||||||
* Always returns 0.
|
* Always returns 0.
|
||||||
* See man page for pthread_rwlock_destroy
|
* See man page for pthread_rwlock_destroy
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
#define ithread_rwlock_destroy pthread_rwlock_destroy
|
#if UPNP_USE_RWLOCK
|
||||||
|
#define ithread_rwlock_destroy pthread_rwlock_destroy
|
||||||
|
#endif /* UPNP_USE_RWLOCK */
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -704,6 +729,49 @@ static UPNP_INLINE int ithread_cleanup_thread(void) {
|
|||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
#define ithread_cond_destroy pthread_cond_destroy
|
#define ithread_cond_destroy pthread_cond_destroy
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Function: ithread_attr_init
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Initialises thread attribute object.
|
||||||
|
* Parameters:
|
||||||
|
* ithread_attr_t *attr (must be valid non NULL pointer to
|
||||||
|
* ithread_attr_t)
|
||||||
|
* Returns:
|
||||||
|
* 0 on success. Nonzero on failure.
|
||||||
|
* See man page for pthread_attr_init
|
||||||
|
***************************************************************************/
|
||||||
|
#define ithread_attr_init pthread_attr_init
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Function: ithread_attr_destroy
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Destroys thread attribute object.
|
||||||
|
* Parameters:
|
||||||
|
* ithread_attr_t *attr (must be valid non NULL pointer to
|
||||||
|
* ithread_attr_t)
|
||||||
|
* Returns:
|
||||||
|
* 0 on success. Nonzero on failure.
|
||||||
|
* See man page for pthread_attr_destroy
|
||||||
|
***************************************************************************/
|
||||||
|
#define ithread_attr_destroy pthread_attr_destroy
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Function: ithread_attr_setstacksize
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Sets stack size of a thread attribute object.
|
||||||
|
* Parameters:
|
||||||
|
* ithread_attr_t *attr (must be valid non NULL pointer to
|
||||||
|
* ithread_attr_t)
|
||||||
|
* size_t stacksize (value of stacksize must be greater than
|
||||||
|
* ITHREAD_STACK_MIN and lower than system-imposed limits
|
||||||
|
* Returns:
|
||||||
|
* 0 on success. Nonzero on failure.
|
||||||
|
* See man page for pthread_attr_setstacksize
|
||||||
|
***************************************************************************/
|
||||||
|
#define ithread_attr_setstacksize pthread_attr_setstacksize
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Function: ithread_create
|
* Function: ithread_create
|
||||||
@@ -713,7 +781,7 @@ static UPNP_INLINE int ithread_cleanup_thread(void) {
|
|||||||
* and argument.
|
* and argument.
|
||||||
* Parameters:
|
* Parameters:
|
||||||
* ithread_t * thread (must be valid non NULL pointer to pthread_t)
|
* ithread_t * thread (must be valid non NULL pointer to pthread_t)
|
||||||
* ithread_attr_t *attr, IGNORED
|
* ithread_attr_t *attr
|
||||||
* void * (start_routine) (void *arg) (start routine)
|
* void * (start_routine) (void *arg) (start routine)
|
||||||
* void * arg - argument.
|
* void * arg - argument.
|
||||||
* Returns:
|
* Returns:
|
||||||
|
@@ -246,7 +246,7 @@ static int SetPolicyType(PolicyType in)
|
|||||||
|
|
||||||
memset(¤t, 0, sizeof(current));
|
memset(¤t, 0, sizeof(current));
|
||||||
sched_getparam(0, ¤t);
|
sched_getparam(0, ¤t);
|
||||||
current.sched_priority = DEFAULT_SCHED_PARAM;
|
current.sched_priority = sched_get_priority_min(DEFAULT_POLICY);
|
||||||
sched_result = sched_setscheduler(0, in, ¤t);
|
sched_result = sched_setscheduler(0, in, ¤t);
|
||||||
retVal = (sched_result != -1 || errno == EPERM) ? 0 : errno;
|
retVal = (sched_result != -1 || errno == EPERM) ? 0 : errno;
|
||||||
#else
|
#else
|
||||||
@@ -609,12 +609,16 @@ static int CreateWorker(ThreadPool *tp)
|
|||||||
ithread_t temp;
|
ithread_t temp;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
int currentThreads = tp->totalThreads + 1;
|
int currentThreads = tp->totalThreads + 1;
|
||||||
|
ithread_attr_t attr;
|
||||||
|
|
||||||
if (tp->attr.maxThreads != INFINITE_THREADS &&
|
if (tp->attr.maxThreads != INFINITE_THREADS &&
|
||||||
currentThreads > tp->attr.maxThreads) {
|
currentThreads > tp->attr.maxThreads) {
|
||||||
return EMAXTHREADS;
|
return EMAXTHREADS;
|
||||||
}
|
}
|
||||||
rc = ithread_create(&temp, NULL, WorkerThread, tp);
|
ithread_attr_init(&attr);
|
||||||
|
ithread_attr_setstacksize(&attr, tp->attr.stackSize);
|
||||||
|
rc = ithread_create(&temp, &attr, WorkerThread, tp);
|
||||||
|
ithread_attr_destroy(&attr);
|
||||||
if (rc == 0) {
|
if (rc == 0) {
|
||||||
rc = ithread_detach(temp);
|
rc = ithread_detach(temp);
|
||||||
while (tp->totalThreads < currentThreads) {
|
while (tp->totalThreads < currentThreads) {
|
||||||
@@ -1174,6 +1178,7 @@ int TPAttrInit(ThreadPoolAttr *attr)
|
|||||||
attr->maxIdleTime = DEFAULT_IDLE_TIME;
|
attr->maxIdleTime = DEFAULT_IDLE_TIME;
|
||||||
attr->maxThreads = DEFAULT_MAX_THREADS;
|
attr->maxThreads = DEFAULT_MAX_THREADS;
|
||||||
attr->minThreads = DEFAULT_MIN_THREADS;
|
attr->minThreads = DEFAULT_MIN_THREADS;
|
||||||
|
attr->stackSize = DEFAULT_STACK_SIZE;
|
||||||
attr->schedPolicy = DEFAULT_POLICY;
|
attr->schedPolicy = DEFAULT_POLICY;
|
||||||
attr->starvationTime = DEFAULT_STARVATION_TIME;
|
attr->starvationTime = DEFAULT_STARVATION_TIME;
|
||||||
attr->maxJobsTotal = DEFAULT_MAX_JOBS_TOTAL;
|
attr->maxJobsTotal = DEFAULT_MAX_JOBS_TOTAL;
|
||||||
@@ -1298,6 +1303,28 @@ int TPAttrSetMinThreads(ThreadPoolAttr *attr, int minThreads)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Function: TPAttrSetStackSize
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Sets the stack size for the thread pool attributes.
|
||||||
|
* Parameters:
|
||||||
|
* attr - must be valid thread pool attributes.
|
||||||
|
* stackSize - value to set
|
||||||
|
* Returns:
|
||||||
|
* Always returns 0.
|
||||||
|
*****************************************************************************/
|
||||||
|
int TPAttrSetStackSize(ThreadPoolAttr *attr, size_t stackSize)
|
||||||
|
{
|
||||||
|
if (!attr) {
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
attr->stackSize = stackSize;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Function: TPAttrSetIdleTime
|
* Function: TPAttrSetIdleTime
|
||||||
*
|
*
|
||||||
|
@@ -24,6 +24,9 @@
|
|||||||
#include "UpnpGlobal.h" /* for EXPORT_SPEC */
|
#include "UpnpGlobal.h" /* for EXPORT_SPEC */
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdlib.h> /* for size_t */
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
@@ -76,11 +79,22 @@ EXPORT_SPEC void UpnpString_assign(
|
|||||||
*
|
*
|
||||||
* \return The length of the string.
|
* \return The length of the string.
|
||||||
* */
|
* */
|
||||||
EXPORT_SPEC int UpnpString_get_Length(
|
EXPORT_SPEC size_t UpnpString_get_Length(
|
||||||
/*! [in] The \em \b this pointer. */
|
/*! [in] The \em \b this pointer. */
|
||||||
const UpnpString *p);
|
const UpnpString *p);
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Truncates the string to the specified lenght, or does nothing
|
||||||
|
* if the current lenght is less than or equal to the requested length.
|
||||||
|
* */
|
||||||
|
EXPORT_SPEC void UpnpString_set_Length(
|
||||||
|
/*! [in] The \em \b this pointer. */
|
||||||
|
UpnpString *p,
|
||||||
|
/*! [in] The requested length. */
|
||||||
|
size_t n);
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Returns the pointer to char.
|
* \brief Returns the pointer to char.
|
||||||
*
|
*
|
||||||
@@ -94,7 +108,7 @@ EXPORT_SPEC const char *UpnpString_get_String(
|
|||||||
/*!
|
/*!
|
||||||
* \brief Sets the string from a pointer to char.
|
* \brief Sets the string from a pointer to char.
|
||||||
*/
|
*/
|
||||||
EXPORT_SPEC void UpnpString_set_String(
|
EXPORT_SPEC int UpnpString_set_String(
|
||||||
/*! [in] The \em \b this pointer. */
|
/*! [in] The \em \b this pointer. */
|
||||||
UpnpString *p,
|
UpnpString *p,
|
||||||
/*! [in] (char *) to copy from. */
|
/*! [in] (char *) to copy from. */
|
||||||
@@ -104,13 +118,13 @@ EXPORT_SPEC void UpnpString_set_String(
|
|||||||
/*!
|
/*!
|
||||||
* \brief Sets the string from a pointer to char using a maximum of N chars.
|
* \brief Sets the string from a pointer to char using a maximum of N chars.
|
||||||
*/
|
*/
|
||||||
EXPORT_SPEC void UpnpString_set_StringN(
|
EXPORT_SPEC int UpnpString_set_StringN(
|
||||||
/*! [in] The \em \b this pointer. */
|
/*! [in] The \em \b this pointer. */
|
||||||
UpnpString *p,
|
UpnpString *p,
|
||||||
/*! [in] (char *) to copy from. */
|
/*! [in] (char *) to copy from. */
|
||||||
const char *s,
|
const char *s,
|
||||||
/*! Maximum number of chars to copy.*/
|
/*! Maximum number of chars to copy.*/
|
||||||
int n);
|
size_t n);
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -121,6 +135,30 @@ EXPORT_SPEC void UpnpString_clear(
|
|||||||
UpnpString *p);
|
UpnpString *p);
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Compares two strings for equality. Case matters.
|
||||||
|
*
|
||||||
|
* \return The result of strcmp().
|
||||||
|
*/
|
||||||
|
EXPORT_SPEC int UpnpString_cmp(
|
||||||
|
/*! [in] The \em \b the first string. */
|
||||||
|
UpnpString *p,
|
||||||
|
/*! [in] The \em \b the second string. */
|
||||||
|
UpnpString *q);
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Compares two strings for equality. Case does not matter.
|
||||||
|
*
|
||||||
|
* \return The result of strcasecmp().
|
||||||
|
*/
|
||||||
|
EXPORT_SPEC int UpnpString_casecmp(
|
||||||
|
/*! [in] The \em \b the first string. */
|
||||||
|
UpnpString *p,
|
||||||
|
/*! [in] The \em \b the second string. */
|
||||||
|
UpnpString *q);
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
@@ -987,6 +987,7 @@ EXPORT_SPEC int UpnpInit(
|
|||||||
* \li \c UPNP_E_INVALID_INTERFACE: IfName is invalid or does not
|
* \li \c UPNP_E_INVALID_INTERFACE: IfName is invalid or does not
|
||||||
* have a valid IPv4 or IPv6 addresss configured.
|
* have a valid IPv4 or IPv6 addresss configured.
|
||||||
*/
|
*/
|
||||||
|
#ifdef UPNP_ENABLE_IPV6
|
||||||
EXPORT_SPEC int UpnpInit2(
|
EXPORT_SPEC int UpnpInit2(
|
||||||
/*! The interface name to use by the UPnP SDK operations.
|
/*! The interface name to use by the UPnP SDK operations.
|
||||||
* Examples: "eth0", "xl0", "Local Area Connection", \c NULL to
|
* Examples: "eth0", "xl0", "Local Area Connection", \c NULL to
|
||||||
@@ -995,6 +996,7 @@ EXPORT_SPEC int UpnpInit2(
|
|||||||
/*! Local Port to listen for incoming connections.
|
/*! Local Port to listen for incoming connections.
|
||||||
* \c NULL will pick an arbitrary free port. */
|
* \c NULL will pick an arbitrary free port. */
|
||||||
unsigned short DestPort);
|
unsigned short DestPort);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -1044,8 +1046,9 @@ EXPORT_SPEC unsigned short UpnpGetServerPort(void);
|
|||||||
* related requests.
|
* related requests.
|
||||||
* \li On error: 0 is returned if \b UpnpInit has not succeeded.
|
* \li On error: 0 is returned if \b UpnpInit has not succeeded.
|
||||||
*/
|
*/
|
||||||
|
#ifdef UPNP_ENABLE_IPV6
|
||||||
EXPORT_SPEC unsigned short UpnpGetServerPort6(void);
|
EXPORT_SPEC unsigned short UpnpGetServerPort6(void);
|
||||||
|
#endif
|
||||||
/*!
|
/*!
|
||||||
* \brief Returns the local IPv4 listening ip address.
|
* \brief Returns the local IPv4 listening ip address.
|
||||||
*
|
*
|
||||||
@@ -1071,10 +1074,11 @@ EXPORT_SPEC char *UpnpGetServerIpAddress(void);
|
|||||||
* listening for UPnP related requests.
|
* listening for UPnP related requests.
|
||||||
* \li On error: \c NULL is returned if \b UpnpInit has not succeeded.
|
* \li On error: \c NULL is returned if \b UpnpInit has not succeeded.
|
||||||
*/
|
*/
|
||||||
|
#ifdef UPNP_ENABLE_IPV6
|
||||||
EXPORT_SPEC char *UpnpGetServerIp6Address(void);
|
EXPORT_SPEC char *UpnpGetServerIp6Address(void);
|
||||||
|
|
||||||
EXPORT_SPEC char *UpnpGetServerUlaGuaIp6Address(void);
|
EXPORT_SPEC char *UpnpGetServerUlaGuaIp6Address(void);
|
||||||
|
#endif
|
||||||
/*!
|
/*!
|
||||||
* \brief Registers a device application with the UPnP Library.
|
* \brief Registers a device application with the UPnP Library.
|
||||||
*
|
*
|
||||||
@@ -1351,6 +1355,8 @@ EXPORT_SPEC int UpnpSetContentLength(
|
|||||||
* behaviour if the size of the incoming SOAP message exceeds the memory that
|
* behaviour if the size of the incoming SOAP message exceeds the memory that
|
||||||
* device can allocate.
|
* device can allocate.
|
||||||
*
|
*
|
||||||
|
* If set to 0 then checking will be disabled.
|
||||||
|
*
|
||||||
* The default maximum content-length is \c DEFAULT_SOAP_CONTENT_LENGTH
|
* The default maximum content-length is \c DEFAULT_SOAP_CONTENT_LENGTH
|
||||||
* = 16K bytes.
|
* = 16K bytes.
|
||||||
*
|
*
|
||||||
|
@@ -90,6 +90,9 @@
|
|||||||
* (i.e. configure --enable-tools) : <upnp/upnptools.h> file is available */
|
* (i.e. configure --enable-tools) : <upnp/upnptools.h> file is available */
|
||||||
#undef UPNP_HAVE_TOOLS
|
#undef UPNP_HAVE_TOOLS
|
||||||
|
|
||||||
|
/** Defined to 1 if the library has been compiled with ipv6 support
|
||||||
|
* (i.e. configure --enable-ipv6) */
|
||||||
|
#undef UPNP_ENABLE_IPV6
|
||||||
|
|
||||||
#endif /* UPNP_CONFIG_H */
|
#endif /* UPNP_CONFIG_H */
|
||||||
|
|
||||||
|
@@ -43,7 +43,8 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
int initialize = 1;
|
static int initialize_init = 1;
|
||||||
|
static int initialize_register = 1;
|
||||||
|
|
||||||
/*! Function pointers to use for displaying formatted strings.
|
/*! Function pointers to use for displaying formatted strings.
|
||||||
* Set on Initialization of device. */
|
* Set on Initialization of device. */
|
||||||
@@ -67,7 +68,7 @@ ithread_mutex_t display_mutex;
|
|||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
int SampleUtil_Initialize(print_string print_function)
|
int SampleUtil_Initialize(print_string print_function)
|
||||||
{
|
{
|
||||||
if (initialize) {
|
if (initialize_init) {
|
||||||
ithread_mutexattr_t attr;
|
ithread_mutexattr_t attr;
|
||||||
|
|
||||||
ithread_mutexattr_init(&attr);
|
ithread_mutexattr_init(&attr);
|
||||||
@@ -80,7 +81,7 @@ int SampleUtil_Initialize(print_string print_function)
|
|||||||
gPrintFun = print_function;
|
gPrintFun = print_function;
|
||||||
ithread_mutex_unlock(&display_mutex);
|
ithread_mutex_unlock(&display_mutex);
|
||||||
|
|
||||||
initialize = 0;
|
initialize_init = 0;
|
||||||
} else {
|
} else {
|
||||||
SampleUtil_Print("***** SampleUtil_Initialize was called multiple times!\n");
|
SampleUtil_Print("***** SampleUtil_Initialize was called multiple times!\n");
|
||||||
abort();
|
abort();
|
||||||
@@ -99,12 +100,9 @@ int SampleUtil_Initialize(print_string print_function)
|
|||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
int SampleUtil_RegisterUpdateFunction(state_update update_function)
|
int SampleUtil_RegisterUpdateFunction(state_update update_function)
|
||||||
{
|
{
|
||||||
/* Intialize only once. */
|
if (initialize_register) {
|
||||||
static int initialize = 1;
|
|
||||||
|
|
||||||
if (initialize) {
|
|
||||||
gStateUpdateFun = update_function;
|
gStateUpdateFun = update_function;
|
||||||
initialize = 0;
|
initialize_register = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return UPNP_E_SUCCESS;
|
return UPNP_E_SUCCESS;
|
||||||
@@ -123,7 +121,9 @@ int SampleUtil_Finish()
|
|||||||
{
|
{
|
||||||
ithread_mutex_destroy(&display_mutex);
|
ithread_mutex_destroy(&display_mutex);
|
||||||
gPrintFun = NULL;
|
gPrintFun = NULL;
|
||||||
initialize = 1;
|
gStateUpdateFun = NULL;
|
||||||
|
initialize_init = 1;
|
||||||
|
initialize_register = 1;
|
||||||
|
|
||||||
return UPNP_E_SUCCESS;
|
return UPNP_E_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@@ -1310,7 +1310,8 @@ int TvCtrlPointStart(print_string printFunctionPtr, state_update updateFunctionP
|
|||||||
SampleUtil_Print(
|
SampleUtil_Print(
|
||||||
"Initializing UPnP Sdk with\n"
|
"Initializing UPnP Sdk with\n"
|
||||||
"\tipaddress = %s port = %u\n",
|
"\tipaddress = %s port = %u\n",
|
||||||
ip_address, port);
|
ip_address ? ip_address : "{NULL}",
|
||||||
|
port);
|
||||||
|
|
||||||
rc = UpnpInit(ip_address, port);
|
rc = UpnpInit(ip_address, port);
|
||||||
if (rc != UPNP_E_SUCCESS) {
|
if (rc != UPNP_E_SUCCESS) {
|
||||||
|
@@ -1872,7 +1872,8 @@ TvDeviceStart( char *ip_address,
|
|||||||
SampleUtil_Print(
|
SampleUtil_Print(
|
||||||
"Initializing UPnP Sdk with\n"
|
"Initializing UPnP Sdk with\n"
|
||||||
"\tipaddress = %s port = %u\n",
|
"\tipaddress = %s port = %u\n",
|
||||||
ip_address, port );
|
ip_address ? ip_address : "{NULL}",
|
||||||
|
port);
|
||||||
|
|
||||||
ret = UpnpInit( ip_address, port );
|
ret = UpnpInit( ip_address, port );
|
||||||
if( ret != UPNP_E_SUCCESS ) {
|
if( ret != UPNP_E_SUCCESS ) {
|
||||||
@@ -1886,8 +1887,9 @@ TvDeviceStart( char *ip_address,
|
|||||||
|
|
||||||
SampleUtil_Print(
|
SampleUtil_Print(
|
||||||
"UPnP Initialized\n"
|
"UPnP Initialized\n"
|
||||||
"\tipaddress= %s port = %u\n",
|
"\tipaddress = %s port = %u\n",
|
||||||
ip_address, port );
|
ip_address ? ip_address : "{NULL}",
|
||||||
|
port);
|
||||||
|
|
||||||
if( desc_doc_name == NULL ) {
|
if( desc_doc_name == NULL ) {
|
||||||
desc_doc_name = "tvcombodesc.xml";
|
desc_doc_name = "tvcombodesc.xml";
|
||||||
|
@@ -1331,7 +1331,8 @@ int TvCtrlPointStart(print_string printFunctionPtr, state_update updateFunctionP
|
|||||||
SampleUtil_Print(
|
SampleUtil_Print(
|
||||||
"Initializing UPnP Sdk with\n"
|
"Initializing UPnP Sdk with\n"
|
||||||
"\tipaddress = %s port = %u\n",
|
"\tipaddress = %s port = %u\n",
|
||||||
ip_address, port);
|
ip_address ? ip_address : "{NULL}",
|
||||||
|
port);
|
||||||
|
|
||||||
rc = UpnpInit(ip_address, port);
|
rc = UpnpInit(ip_address, port);
|
||||||
if (rc != UPNP_E_SUCCESS) {
|
if (rc != UPNP_E_SUCCESS) {
|
||||||
@@ -1348,8 +1349,9 @@ int TvCtrlPointStart(print_string printFunctionPtr, state_update updateFunctionP
|
|||||||
|
|
||||||
SampleUtil_Print(
|
SampleUtil_Print(
|
||||||
"UPnP Initialized\n"
|
"UPnP Initialized\n"
|
||||||
"\tipaddress= %s port = %u\n",
|
"\tipaddress = %s port = %u\n",
|
||||||
ip_address, port);
|
ip_address ? ip_address : "{NULL}",
|
||||||
|
port);
|
||||||
|
|
||||||
SampleUtil_Print("Registering Control Point");
|
SampleUtil_Print("Registering Control Point");
|
||||||
rc = UpnpRegisterClient(TvCtrlPointCallbackEventHandler,
|
rc = UpnpRegisterClient(TvCtrlPointCallbackEventHandler,
|
||||||
|
@@ -28,6 +28,19 @@
|
|||||||
#include <string.h> /* for strlen(), strdup() */
|
#include <string.h> /* for strlen(), strdup() */
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#define strcasecmp stricmp
|
||||||
|
#else
|
||||||
|
/* Other systems have strncasecmp */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* strndup() is a GNU extension. Other systems must fix it with elif's. */
|
||||||
|
#ifdef __GNUC__
|
||||||
|
extern char *strndup(__const char *__string, size_t __n);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Internal implementation of the class UpnpString.
|
* \brief Internal implementation of the class UpnpString.
|
||||||
*
|
*
|
||||||
@@ -115,42 +128,78 @@ void UpnpString_assign(UpnpString *p, const UpnpString *q)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int UpnpString_get_Length(const UpnpString *p)
|
size_t UpnpString_get_Length(const UpnpString *p)
|
||||||
{
|
{
|
||||||
return ((struct SUpnpString *)p)->m_length;
|
return ((struct SUpnpString *)p)->m_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void UpnpString_set_Length(UpnpString *p, size_t n)
|
||||||
|
{
|
||||||
|
if (((struct SUpnpString *)p)->m_length > n) {
|
||||||
|
((struct SUpnpString *)p)->m_length = n;
|
||||||
|
/* No need to realloc now, will do later when needed. */
|
||||||
|
((struct SUpnpString *)p)->m_string[n] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const char *UpnpString_get_String(const UpnpString *p)
|
const char *UpnpString_get_String(const UpnpString *p)
|
||||||
{
|
{
|
||||||
return ((struct SUpnpString *)p)->m_string;
|
return ((struct SUpnpString *)p)->m_string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void UpnpString_set_String(UpnpString *p, const char *s)
|
int UpnpString_set_String(UpnpString *p, const char *s)
|
||||||
{
|
{
|
||||||
|
char *q = strdup(s);
|
||||||
|
if (!q) goto error_handler1;
|
||||||
free(((struct SUpnpString *)p)->m_string);
|
free(((struct SUpnpString *)p)->m_string);
|
||||||
((struct SUpnpString *)p)->m_length = strlen(s);
|
((struct SUpnpString *)p)->m_length = strlen(q);
|
||||||
((struct SUpnpString *)p)->m_string = strdup(s);
|
((struct SUpnpString *)p)->m_string = q;
|
||||||
|
|
||||||
|
error_handler1:
|
||||||
|
return q != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void UpnpString_set_StringN(UpnpString *p, const char *s, int n)
|
int UpnpString_set_StringN(UpnpString *p, const char *s, size_t n)
|
||||||
{
|
{
|
||||||
|
char *q = strndup(s, n);
|
||||||
|
if (!q) goto error_handler1;
|
||||||
free(((struct SUpnpString *)p)->m_string);
|
free(((struct SUpnpString *)p)->m_string);
|
||||||
((struct SUpnpString *)p)->m_length = n;
|
((struct SUpnpString *)p)->m_length = strlen(q);
|
||||||
((struct SUpnpString *)p)->m_string = (char *)malloc(n+1);
|
((struct SUpnpString *)p)->m_string = q;
|
||||||
strncpy(((struct SUpnpString *)p)->m_string, s, n);
|
|
||||||
((struct SUpnpString *)p)->m_string[n] = 0;
|
error_handler1:
|
||||||
|
return q != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void UpnpString_clear(UpnpString *p)
|
void UpnpString_clear(UpnpString *p)
|
||||||
{
|
{
|
||||||
((struct SUpnpString *)p)->m_length = 0;
|
((struct SUpnpString *)p)->m_length = 0;
|
||||||
// No need to realloc now, will do later when needed
|
/* No need to realloc now, will do later when needed. */
|
||||||
((struct SUpnpString *)p)->m_string[0] = 0;
|
((struct SUpnpString *)p)->m_string[0] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int UpnpString_cmp(UpnpString *p, UpnpString *q)
|
||||||
|
{
|
||||||
|
const char *cp = UpnpString_get_String(p);
|
||||||
|
const char *cq = UpnpString_get_String(q);
|
||||||
|
|
||||||
|
return strcmp(cp, cq);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int UpnpString_casecmp(UpnpString *p, UpnpString *q)
|
||||||
|
{
|
||||||
|
const char *cp = UpnpString_get_String(p);
|
||||||
|
const char *cq = UpnpString_get_String(q);
|
||||||
|
|
||||||
|
return strcasecmp(cp, cq);
|
||||||
|
}
|
||||||
|
|
||||||
/* @} UpnpString */
|
/* @} UpnpString */
|
||||||
|
|
||||||
|
@@ -282,6 +282,7 @@ static int UpnpInitThreadPools(void)
|
|||||||
TPAttrInit(&attr);
|
TPAttrInit(&attr);
|
||||||
TPAttrSetMaxThreads(&attr, MAX_THREADS);
|
TPAttrSetMaxThreads(&attr, MAX_THREADS);
|
||||||
TPAttrSetMinThreads(&attr, MIN_THREADS);
|
TPAttrSetMinThreads(&attr, MIN_THREADS);
|
||||||
|
TPAttrSetStackSize(&attr, THREAD_STACK_SIZE);
|
||||||
TPAttrSetJobsPerThread(&attr, JOBS_PER_THREAD);
|
TPAttrSetJobsPerThread(&attr, JOBS_PER_THREAD);
|
||||||
TPAttrSetIdleTime(&attr, THREAD_IDLE_TIME);
|
TPAttrSetIdleTime(&attr, THREAD_IDLE_TIME);
|
||||||
TPAttrSetMaxJobsTotal(&attr, MAX_JOBS_TOTAL);
|
TPAttrSetMaxJobsTotal(&attr, MAX_JOBS_TOTAL);
|
||||||
@@ -488,7 +489,7 @@ exit_function:
|
|||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef UPNP_ENABLE_IPV6
|
||||||
int UpnpInit2(const char *IfName, unsigned short DestPort)
|
int UpnpInit2(const char *IfName, unsigned short DestPort)
|
||||||
{
|
{
|
||||||
int retVal;
|
int retVal;
|
||||||
@@ -533,8 +534,9 @@ int UpnpInit2(const char *IfName, unsigned short DestPort)
|
|||||||
exit_function:
|
exit_function:
|
||||||
ithread_mutex_unlock(&gSDKInitMutex);
|
ithread_mutex_unlock(&gSDKInitMutex);
|
||||||
|
|
||||||
return UPNP_E_SUCCESS;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
int UpnpFinish(void)
|
int UpnpFinish(void)
|
||||||
@@ -620,7 +622,7 @@ unsigned short UpnpGetServerPort(void)
|
|||||||
return LOCAL_PORT_V4;
|
return LOCAL_PORT_V4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef UPNP_ENABLE_IPV6
|
||||||
unsigned short UpnpGetServerPort6(void)
|
unsigned short UpnpGetServerPort6(void)
|
||||||
{
|
{
|
||||||
if (UpnpSdkInit != 1) {
|
if (UpnpSdkInit != 1) {
|
||||||
@@ -629,6 +631,7 @@ unsigned short UpnpGetServerPort6(void)
|
|||||||
|
|
||||||
return LOCAL_PORT_V6;
|
return LOCAL_PORT_V6;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
char *UpnpGetServerIpAddress(void)
|
char *UpnpGetServerIpAddress(void)
|
||||||
@@ -777,8 +780,10 @@ int UpnpRegisterRootDevice(
|
|||||||
HInfo->DeviceList = NULL;
|
HInfo->DeviceList = NULL;
|
||||||
HInfo->ServiceList = NULL;
|
HInfo->ServiceList = NULL;
|
||||||
HInfo->DescDocument = NULL;
|
HInfo->DescDocument = NULL;
|
||||||
CLIENTONLY( ListInit(&HInfo->SsdpSearchList, NULL, NULL); )
|
#ifdef INCLUDE_CLIENT_APIS
|
||||||
CLIENTONLY( HInfo->ClientSubList = NULL; )
|
ListInit(&HInfo->SsdpSearchList, NULL, NULL);
|
||||||
|
HInfo->ClientSubList = NULL;
|
||||||
|
#endif /* INCLUDE_CLIENT_APIS */
|
||||||
HInfo->MaxSubscriptions = UPNP_INFINITE;
|
HInfo->MaxSubscriptions = UPNP_INFINITE;
|
||||||
HInfo->MaxSubscriptionTimeOut = UPNP_INFINITE;
|
HInfo->MaxSubscriptionTimeOut = UPNP_INFINITE;
|
||||||
HInfo->DeviceAf = AF_INET;
|
HInfo->DeviceAf = AF_INET;
|
||||||
@@ -788,7 +793,9 @@ int UpnpRegisterRootDevice(
|
|||||||
UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
|
UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
|
||||||
"UpnpRegisterRootDevice: error downloading Document: %d\n",
|
"UpnpRegisterRootDevice: error downloading Document: %d\n",
|
||||||
retVal);
|
retVal);
|
||||||
CLIENTONLY( ListDestroy(&HInfo->SsdpSearchList, 0); )
|
#ifdef INCLUDE_CLIENT_APIS
|
||||||
|
ListDestroy(&HInfo->SsdpSearchList, 0);
|
||||||
|
#endif /* INCLUDE_CLIENT_APIS */
|
||||||
FreeHandle(*Hnd);
|
FreeHandle(*Hnd);
|
||||||
goto exit_function;
|
goto exit_function;
|
||||||
}
|
}
|
||||||
@@ -800,7 +807,9 @@ int UpnpRegisterRootDevice(
|
|||||||
HInfo->DeviceList =
|
HInfo->DeviceList =
|
||||||
ixmlDocument_getElementsByTagName(HInfo->DescDocument, "device");
|
ixmlDocument_getElementsByTagName(HInfo->DescDocument, "device");
|
||||||
if (!HInfo->DeviceList) {
|
if (!HInfo->DeviceList) {
|
||||||
CLIENTONLY( ListDestroy(&HInfo->SsdpSearchList, 0); )
|
#ifdef INCLUDE_CLIENT_APIS
|
||||||
|
ListDestroy(&HInfo->SsdpSearchList, 0);
|
||||||
|
#endif /* INCLUDE_CLIENT_APIS */
|
||||||
ixmlDocument_free(HInfo->DescDocument);
|
ixmlDocument_free(HInfo->DescDocument);
|
||||||
FreeHandle(*Hnd);
|
FreeHandle(*Hnd);
|
||||||
UpnpPrintf(UPNP_CRITICAL, API, __FILE__, __LINE__,
|
UpnpPrintf(UPNP_CRITICAL, API, __FILE__, __LINE__,
|
||||||
@@ -936,8 +945,10 @@ int UpnpRegisterRootDevice2(
|
|||||||
HInfo->MaxAge = DEFAULT_MAXAGE;
|
HInfo->MaxAge = DEFAULT_MAXAGE;
|
||||||
HInfo->DeviceList = NULL;
|
HInfo->DeviceList = NULL;
|
||||||
HInfo->ServiceList = NULL;
|
HInfo->ServiceList = NULL;
|
||||||
CLIENTONLY( ListInit(&HInfo->SsdpSearchList, NULL, NULL); )
|
#ifdef INCLUDE_CLIENT_APIS
|
||||||
CLIENTONLY( HInfo->ClientSubList = NULL; )
|
ListInit(&HInfo->SsdpSearchList, NULL, NULL);
|
||||||
|
HInfo->ClientSubList = NULL;
|
||||||
|
#endif /* INCLUDE_CLIENT_APIS */
|
||||||
HInfo->MaxSubscriptions = UPNP_INFINITE;
|
HInfo->MaxSubscriptions = UPNP_INFINITE;
|
||||||
HInfo->MaxSubscriptionTimeOut = UPNP_INFINITE;
|
HInfo->MaxSubscriptionTimeOut = UPNP_INFINITE;
|
||||||
HInfo->DeviceAf = AF_INET;
|
HInfo->DeviceAf = AF_INET;
|
||||||
@@ -950,7 +961,9 @@ int UpnpRegisterRootDevice2(
|
|||||||
HInfo->DeviceList =
|
HInfo->DeviceList =
|
||||||
ixmlDocument_getElementsByTagName( HInfo->DescDocument, "device" );
|
ixmlDocument_getElementsByTagName( HInfo->DescDocument, "device" );
|
||||||
if (!HInfo->DeviceList) {
|
if (!HInfo->DeviceList) {
|
||||||
CLIENTONLY( ListDestroy(&HInfo->SsdpSearchList, 0); )
|
#ifdef INCLUDE_CLIENT_APIS
|
||||||
|
ListDestroy(&HInfo->SsdpSearchList, 0);
|
||||||
|
#endif /* INCLUDE_CLIENT_APIS */
|
||||||
ixmlDocument_free(HInfo->DescDocument);
|
ixmlDocument_free(HInfo->DescDocument);
|
||||||
FreeHandle(*Hnd);
|
FreeHandle(*Hnd);
|
||||||
UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
|
UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
|
||||||
@@ -1010,17 +1023,16 @@ int UpnpRegisterRootDevice3(
|
|||||||
struct Handle_Info *HInfo;
|
struct Handle_Info *HInfo;
|
||||||
int retVal = 0;
|
int retVal = 0;
|
||||||
int hasServiceTable = 0;
|
int hasServiceTable = 0;
|
||||||
|
int handler_index = 0;
|
||||||
|
|
||||||
HandleLock();
|
HandleLock();
|
||||||
|
|
||||||
UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
|
UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
|
||||||
"Inside UpnpRegisterRootDevice3\n");
|
"Inside UpnpRegisterRootDevice3\n");
|
||||||
|
|
||||||
if (UpnpSdkInit != 1) {
|
if (UpnpSdkInit != 1) {
|
||||||
retVal = UPNP_E_FINISH;
|
retVal = UPNP_E_FINISH;
|
||||||
goto exit_function;
|
goto exit_function;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Hnd == NULL ||
|
if (Hnd == NULL ||
|
||||||
Fun == NULL ||
|
Fun == NULL ||
|
||||||
DescUrl == NULL ||
|
DescUrl == NULL ||
|
||||||
@@ -1029,17 +1041,14 @@ int UpnpRegisterRootDevice3(
|
|||||||
retVal = UPNP_E_INVALID_PARAM;
|
retVal = UPNP_E_INVALID_PARAM;
|
||||||
goto exit_function;
|
goto exit_function;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Test for already regsitered IPV4. */
|
/* Test for already regsitered IPV4. */
|
||||||
if (AddressFamily == AF_INET && UpnpSdkDeviceRegisteredV4 == 1) {
|
if (AddressFamily == AF_INET && UpnpSdkDeviceRegisteredV4 == 1) {
|
||||||
retVal = UPNP_E_ALREADY_REGISTERED;
|
retVal = UPNP_E_ALREADY_REGISTERED;
|
||||||
goto exit_function;
|
goto exit_function;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Test for already registered IPV6. IPV6 devices might register on multiple
|
/* Test for already registered IPV6. IPV6 devices might register on multiple
|
||||||
* IPv6 addresses (link local and GUA or ULA), so we must to check the
|
* IPv6 addresses (link local and GUA or ULA), so we must to check the
|
||||||
* description URL in the HandleTable. */
|
* description URL in the HandleTable. */
|
||||||
int handler_index = 0;
|
|
||||||
while (handler_index < NUM_HANDLE && HandleTable[handler_index] != NULL) {
|
while (handler_index < NUM_HANDLE && HandleTable[handler_index] != NULL) {
|
||||||
if (strcmp(((struct Handle_Info *)HandleTable[handler_index])->DescURL, DescUrl)) {
|
if (strcmp(((struct Handle_Info *)HandleTable[handler_index])->DescURL, DescUrl)) {
|
||||||
retVal = UPNP_E_ALREADY_REGISTERED;
|
retVal = UPNP_E_ALREADY_REGISTERED;
|
||||||
@@ -1047,13 +1056,11 @@ int UpnpRegisterRootDevice3(
|
|||||||
}
|
}
|
||||||
handler_index++;
|
handler_index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
*Hnd = GetFreeHandle();
|
*Hnd = GetFreeHandle();
|
||||||
if (*Hnd == UPNP_E_OUTOF_HANDLE) {
|
if (*Hnd == UPNP_E_OUTOF_HANDLE) {
|
||||||
retVal = UPNP_E_OUTOF_MEMORY;
|
retVal = UPNP_E_OUTOF_MEMORY;
|
||||||
goto exit_function;
|
goto exit_function;
|
||||||
}
|
}
|
||||||
|
|
||||||
HInfo = (struct Handle_Info *)malloc(sizeof (struct Handle_Info));
|
HInfo = (struct Handle_Info *)malloc(sizeof (struct Handle_Info));
|
||||||
if (HInfo == NULL) {
|
if (HInfo == NULL) {
|
||||||
retVal = UPNP_E_OUTOF_MEMORY;
|
retVal = UPNP_E_OUTOF_MEMORY;
|
||||||
@@ -1062,7 +1069,6 @@ int UpnpRegisterRootDevice3(
|
|||||||
HandleTable[*Hnd] = HInfo;
|
HandleTable[*Hnd] = HInfo;
|
||||||
UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
|
UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
|
||||||
"Root device URL is %s\n", DescUrl);
|
"Root device URL is %s\n", DescUrl);
|
||||||
|
|
||||||
HInfo->aliasInstalled = 0;
|
HInfo->aliasInstalled = 0;
|
||||||
HInfo->HType = HND_DEVICE;
|
HInfo->HType = HND_DEVICE;
|
||||||
strcpy(HInfo->DescURL, DescUrl);
|
strcpy(HInfo->DescURL, DescUrl);
|
||||||
@@ -1072,15 +1078,18 @@ int UpnpRegisterRootDevice3(
|
|||||||
HInfo->DeviceList = NULL;
|
HInfo->DeviceList = NULL;
|
||||||
HInfo->ServiceList = NULL;
|
HInfo->ServiceList = NULL;
|
||||||
HInfo->DescDocument = NULL;
|
HInfo->DescDocument = NULL;
|
||||||
CLIENTONLY( ListInit(&HInfo->SsdpSearchList, NULL, NULL); )
|
#ifdef INCLUDE_CLIENT_APIS
|
||||||
CLIENTONLY( HInfo->ClientSubList = NULL; )
|
ListInit(&HInfo->SsdpSearchList, NULL, NULL);
|
||||||
|
HInfo->ClientSubList = NULL;
|
||||||
|
#endif /* INCLUDE_CLIENT_APIS */
|
||||||
HInfo->MaxSubscriptions = UPNP_INFINITE;
|
HInfo->MaxSubscriptions = UPNP_INFINITE;
|
||||||
HInfo->MaxSubscriptionTimeOut = UPNP_INFINITE;
|
HInfo->MaxSubscriptionTimeOut = UPNP_INFINITE;
|
||||||
HInfo->DeviceAf = AddressFamily;
|
HInfo->DeviceAf = AddressFamily;
|
||||||
|
|
||||||
retVal = UpnpDownloadXmlDoc(HInfo->DescURL, &(HInfo->DescDocument));
|
retVal = UpnpDownloadXmlDoc(HInfo->DescURL, &(HInfo->DescDocument));
|
||||||
if (retVal != UPNP_E_SUCCESS) {
|
if (retVal != UPNP_E_SUCCESS) {
|
||||||
CLIENTONLY( ListDestroy(&HInfo->SsdpSearchList, 0); )
|
#ifdef INCLUDE_CLIENT_APIS
|
||||||
|
ListDestroy(&HInfo->SsdpSearchList, 0);
|
||||||
|
#endif /* INCLUDE_CLIENT_APIS */
|
||||||
FreeHandle(*Hnd);
|
FreeHandle(*Hnd);
|
||||||
goto exit_function;
|
goto exit_function;
|
||||||
}
|
}
|
||||||
@@ -1092,7 +1101,9 @@ int UpnpRegisterRootDevice3(
|
|||||||
HInfo->DeviceList = ixmlDocument_getElementsByTagName(
|
HInfo->DeviceList = ixmlDocument_getElementsByTagName(
|
||||||
HInfo->DescDocument, "device");
|
HInfo->DescDocument, "device");
|
||||||
if (!HInfo->DeviceList) {
|
if (!HInfo->DeviceList) {
|
||||||
CLIENTONLY( ListDestroy(&HInfo->SsdpSearchList, 0); )
|
#ifdef INCLUDE_CLIENT_APIS
|
||||||
|
ListDestroy(&HInfo->SsdpSearchList, 0);
|
||||||
|
#endif /* INCLUDE_CLIENT_APIS */
|
||||||
ixmlDocument_free(HInfo->DescDocument);
|
ixmlDocument_free(HInfo->DescDocument);
|
||||||
FreeHandle(*Hnd);
|
FreeHandle(*Hnd);
|
||||||
UpnpPrintf(UPNP_CRITICAL, API, __FILE__, __LINE__,
|
UpnpPrintf(UPNP_CRITICAL, API, __FILE__, __LINE__,
|
||||||
@@ -1184,7 +1195,9 @@ int UpnpUnRegisterRootDevice(UpnpDevice_Handle Hnd)
|
|||||||
ixmlNodeList_free( HInfo->ServiceList );
|
ixmlNodeList_free( HInfo->ServiceList );
|
||||||
ixmlDocument_free( HInfo->DescDocument );
|
ixmlDocument_free( HInfo->DescDocument );
|
||||||
|
|
||||||
CLIENTONLY( ListDestroy( &HInfo->SsdpSearchList, 0 ); )
|
#ifdef INCLUDE_CLIENT_APIS
|
||||||
|
ListDestroy( &HInfo->SsdpSearchList, 0 );
|
||||||
|
#endif /* INCLUDE_CLIENT_APIS */
|
||||||
|
|
||||||
#ifdef INTERNAL_WEB_SERVER
|
#ifdef INTERNAL_WEB_SERVER
|
||||||
if( HInfo->aliasInstalled ) {
|
if( HInfo->aliasInstalled ) {
|
||||||
|
@@ -320,18 +320,18 @@ static int gena_subscribe(
|
|||||||
"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(
|
||||||
&request, 1, 1,
|
&request, 1, 1,
|
||||||
"q" "sssdsc" "sc" "sscc",
|
"q" "sssdsc" "sc" "sscc",
|
||||||
HTTPMETHOD_SUBSCRIBE, &dest_url,
|
HTTPMETHOD_SUBSCRIBE, &dest_url,
|
||||||
"CALLBACK: <http://[",
|
"CALLBACK: <http://[",
|
||||||
((IN6_IS_ADDR_LINKLOCAL(DestAddr6))||(strlen(gIF_IPV6_ULA_GUA) == 0 ))?
|
(IN6_IS_ADDR_LINKLOCAL(&DestAddr6->sin6_addr) || strlen(gIF_IPV6_ULA_GUA) == 0) ?
|
||||||
gIF_IPV6 : gIF_IPV6_ULA_GUA,
|
gIF_IPV6 : gIF_IPV6_ULA_GUA,
|
||||||
"]:", LOCAL_PORT_V6, "/>",
|
"]:", LOCAL_PORT_V6, "/>",
|
||||||
"NT: upnp:event",
|
"NT: upnp:event",
|
||||||
"TIMEOUT: Second-", timeout_str );
|
"TIMEOUT: Second-", timeout_str);
|
||||||
} else {
|
} else {
|
||||||
return_code = http_MakeMessage(
|
return_code = http_MakeMessage(
|
||||||
&request, 1, 1,
|
&request, 1, 1,
|
||||||
|
@@ -186,60 +186,66 @@ static UPNP_INLINE int notify_send_and_recv(
|
|||||||
int timeout;
|
int timeout;
|
||||||
SOCKINFO info;
|
SOCKINFO info;
|
||||||
|
|
||||||
// connect
|
/* connect */
|
||||||
UpnpPrintf( UPNP_ALL, GENA, __FILE__, __LINE__,
|
UpnpPrintf(UPNP_ALL, GENA, __FILE__, __LINE__,
|
||||||
"gena notify to: %.*s\n",
|
"gena notify to: %.*s\n",
|
||||||
(int)destination_url->hostport.text.size,
|
(int)destination_url->hostport.text.size,
|
||||||
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 conn_fd; // return UPNP error
|
/* return UPNP error */
|
||||||
|
|
||||||
|
return conn_fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( ( ret_code = sock_init( &info, conn_fd ) ) != 0 ) {
|
ret_code = sock_init(&info, conn_fd);
|
||||||
sock_destroy( &info, SD_BOTH );
|
if (ret_code) {
|
||||||
|
sock_destroy(&info, SD_BOTH);
|
||||||
|
|
||||||
return ret_code;
|
return ret_code;
|
||||||
}
|
}
|
||||||
// make start line and HOST header
|
/* make start line and HOST header */
|
||||||
membuffer_init( &start_msg );
|
membuffer_init(&start_msg);
|
||||||
if (http_MakeMessage(
|
if (http_MakeMessage(
|
||||||
&start_msg, 1, 1,
|
&start_msg, 1, 1,
|
||||||
"q" "s",
|
"q" "s",
|
||||||
HTTPMETHOD_NOTIFY, &url,
|
HTTPMETHOD_NOTIFY, &url,
|
||||||
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 = HTTP_DEFAULT_TIMEOUT;
|
timeout = HTTP_DEFAULT_TIMEOUT;
|
||||||
|
|
||||||
// send msg (note +1 for propertyset; null-terminator is also sent)
|
/* send msg (note: end of notification will contain "\r\n" twice) */
|
||||||
if( ( ret_code = http_SendMessage( &info, &timeout,
|
ret_code = http_SendMessage(&info, &timeout,
|
||||||
"bb",
|
"bbb",
|
||||||
start_msg.buf, start_msg.length,
|
start_msg.buf, start_msg.length,
|
||||||
propertySet,
|
propertySet, strlen(propertySet),
|
||||||
strlen( propertySet ) + 1 ) ) !=
|
"\r\n", 2);
|
||||||
0 ) {
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( ( ret_code = http_RecvMessage( &info, response,
|
ret_code = http_RecvMessage(&info, response,
|
||||||
HTTPMETHOD_NOTIFY, &timeout,
|
HTTPMETHOD_NOTIFY, &timeout, &err_code);
|
||||||
&err_code ) ) != 0 ) {
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
sock_destroy( &info, SD_BOTH ); //should shutdown completely
|
/* should shutdown completely when closing socket */
|
||||||
//when closing socket
|
sock_destroy(&info, SD_BOTH);
|
||||||
// sock_destroy( &info,SD_RECEIVE);
|
membuffer_destroy(&start_msg);
|
||||||
membuffer_destroy( &start_msg );
|
|
||||||
|
|
||||||
return UPNP_E_SUCCESS;
|
return UPNP_E_SUCCESS;
|
||||||
}
|
}
|
||||||
@@ -336,7 +342,12 @@ static void genaNotifyThread(
|
|||||||
struct Handle_Info *handle_info;
|
struct Handle_Info *handle_info;
|
||||||
ThreadPoolJob job;
|
ThreadPoolJob job;
|
||||||
|
|
||||||
HandleReadLock();
|
/* This should be a HandleLock and not a HandleReadLock otherwise if there
|
||||||
|
* is a lot of notifications, then multiple threads will acquire a read
|
||||||
|
* lock and the thread which sends the notification will be blocked forever
|
||||||
|
* on the HandleLock at the end of this function. */
|
||||||
|
//HandleReadLock();
|
||||||
|
HandleLock();
|
||||||
//validate context
|
//validate context
|
||||||
|
|
||||||
if( GetHandleInfo( in->device_handle, &handle_info ) != HND_DEVICE ) {
|
if( GetHandleInfo( in->device_handle, &handle_info ) != HND_DEVICE ) {
|
||||||
@@ -354,18 +365,27 @@ static void genaNotifyThread(
|
|||||||
HandleUnlock();
|
HandleUnlock();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#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
|
||||||
|
* 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. */
|
||||||
|
imillisleep( 1 );
|
||||||
|
|
||||||
ThreadPoolAdd( &gSendThreadPool, &job, NULL );
|
ThreadPoolAdd( &gSendThreadPool, &job, NULL );
|
||||||
|
|
||||||
freeSubscription( &sub_copy );
|
freeSubscription( &sub_copy );
|
||||||
HandleUnlock();
|
HandleUnlock();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
HandleUnlock();
|
HandleUnlock();
|
||||||
|
|
||||||
|
@@ -579,41 +579,59 @@ static int get_miniserver_sockets(
|
|||||||
{
|
{
|
||||||
char errorBuffer[ERROR_BUFFER_LEN];
|
char errorBuffer[ERROR_BUFFER_LEN];
|
||||||
struct sockaddr_storage __ss_v4;
|
struct sockaddr_storage __ss_v4;
|
||||||
struct sockaddr_storage __ss_v6;
|
|
||||||
struct sockaddr_in* serverAddr4 = (struct sockaddr_in*)&__ss_v4;
|
struct sockaddr_in* serverAddr4 = (struct sockaddr_in*)&__ss_v4;
|
||||||
|
SOCKET listenfd4 = INVALID_SOCKET;
|
||||||
|
unsigned short actual_port4;
|
||||||
|
#ifdef UPNP_ENABLE_IPV6
|
||||||
|
struct sockaddr_storage __ss_v6;
|
||||||
struct sockaddr_in6* serverAddr6 = (struct sockaddr_in6*)&__ss_v6;
|
struct sockaddr_in6* serverAddr6 = (struct sockaddr_in6*)&__ss_v6;
|
||||||
SOCKET listenfd4, listenfd6;
|
SOCKET listenfd6 = INVALID_SOCKET;
|
||||||
|
unsigned short actual_port6;
|
||||||
|
#endif
|
||||||
int ret_code;
|
int ret_code;
|
||||||
unsigned short actual_port4, actual_port6;
|
|
||||||
int reuseaddr_on = 0;
|
int reuseaddr_on = 0;
|
||||||
int sockError = UPNP_E_SUCCESS;
|
int sockError = UPNP_E_SUCCESS;
|
||||||
int errCode = 0;
|
int errCode = 0;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Initialize all the sockets to be invalid
|
||||||
|
//
|
||||||
|
out->miniServerSock4 = INVALID_SOCKET;
|
||||||
|
out->miniServerSock6 = INVALID_SOCKET;
|
||||||
|
|
||||||
// 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);
|
||||||
listenfd6 = socket(AF_INET6, SOCK_STREAM, 0);
|
if (listenfd4 == INVALID_SOCKET) {
|
||||||
if (listenfd4 == INVALID_SOCKET && listenfd6 == INVALID_SOCKET) {
|
|
||||||
return UPNP_E_OUTOF_SOCKET;
|
return UPNP_E_OUTOF_SOCKET;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef UPNP_ENABLE_IPV6
|
||||||
|
listenfd6 = socket(AF_INET6, SOCK_STREAM, 0);
|
||||||
|
if (listenfd6 == INVALID_SOCKET) {
|
||||||
|
return UPNP_E_OUTOF_SOCKET;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// As per the IANA specifications for the use of ports by applications
|
// As per the IANA specifications for the use of ports by applications
|
||||||
// override the listen port passed in with the first available
|
// override the listen port passed in with the first available
|
||||||
if (listen_port4 < APPLICATION_LISTENING_PORT) {
|
if (listen_port4 < APPLICATION_LISTENING_PORT) {
|
||||||
listen_port4 = APPLICATION_LISTENING_PORT;
|
listen_port4 = APPLICATION_LISTENING_PORT;
|
||||||
}
|
}
|
||||||
|
#ifdef UPNP_ENABLE_IPV6
|
||||||
if (listen_port6 < APPLICATION_LISTENING_PORT) {
|
if (listen_port6 < APPLICATION_LISTENING_PORT) {
|
||||||
listen_port6 = APPLICATION_LISTENING_PORT;
|
listen_port6 = APPLICATION_LISTENING_PORT;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
memset(&__ss_v4, 0, sizeof (__ss_v4));
|
memset(&__ss_v4, 0, sizeof (__ss_v4));
|
||||||
serverAddr4->sin_family = AF_INET;
|
serverAddr4->sin_family = AF_INET;
|
||||||
serverAddr4->sin_addr.s_addr = htonl(INADDR_ANY);
|
serverAddr4->sin_addr.s_addr = htonl(INADDR_ANY);
|
||||||
|
|
||||||
|
#ifdef UPNP_ENABLE_IPV6
|
||||||
memset(&__ss_v6, 0, sizeof (__ss_v6));
|
memset(&__ss_v6, 0, sizeof (__ss_v6));
|
||||||
serverAddr6->sin6_family = AF_INET6;
|
serverAddr6->sin6_family = AF_INET6;
|
||||||
serverAddr6->sin6_addr = in6addr_any;
|
serverAddr6->sin6_addr = in6addr_any;
|
||||||
|
#endif
|
||||||
// Getting away with implementation of re-using address:port and instead
|
// Getting away with implementation of re-using address:port and instead
|
||||||
// choosing to increment port numbers.
|
// choosing to increment port numbers.
|
||||||
// Keeping the re-use address code as an optional behaviour that can be
|
// Keeping the re-use address code as an optional behaviour that can be
|
||||||
@@ -633,8 +651,10 @@ static int get_miniserver_sockets(
|
|||||||
if (sockError == -1) {
|
if (sockError == -1) {
|
||||||
shutdown(listenfd4, SD_BOTH);
|
shutdown(listenfd4, SD_BOTH);
|
||||||
UpnpCloseSocket(listenfd4);
|
UpnpCloseSocket(listenfd4);
|
||||||
|
#ifdef UPNP_ENABLE_IPV6
|
||||||
shutdown(listenfd6, SD_BOTH);
|
shutdown(listenfd6, SD_BOTH);
|
||||||
UpnpCloseSocket(listenfd6);
|
UpnpCloseSocket(listenfd6);
|
||||||
|
#endif
|
||||||
return UPNP_E_SOCKET_BIND;
|
return UPNP_E_SOCKET_BIND;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -647,14 +667,17 @@ static int get_miniserver_sockets(
|
|||||||
errorBuffer);
|
errorBuffer);
|
||||||
shutdown(listenfd4, SD_BOTH);
|
shutdown(listenfd4, SD_BOTH);
|
||||||
UpnpCloseSocket(listenfd4);
|
UpnpCloseSocket(listenfd4);
|
||||||
|
#ifdef UPNP_ENABLE_IPV6
|
||||||
shutdown(listenfd6, SD_BOTH);
|
shutdown(listenfd6, SD_BOTH);
|
||||||
UpnpCloseSocket(listenfd6);
|
UpnpCloseSocket(listenfd6);
|
||||||
|
#endif
|
||||||
/* Bind failed */
|
/* Bind failed */
|
||||||
return UPNP_E_SOCKET_BIND;
|
return UPNP_E_SOCKET_BIND;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(listenfd6 != INVALID_SOCKET) {
|
#ifdef UPNP_ENABLE_IPV6
|
||||||
|
if (listenfd6 != INVALID_SOCKET) {
|
||||||
sockError = setsockopt(listenfd6, SOL_SOCKET, SO_REUSEADDR,
|
sockError = setsockopt(listenfd6, SOL_SOCKET, SO_REUSEADDR,
|
||||||
(const char *)&reuseaddr_on, sizeof (int));
|
(const char *)&reuseaddr_on, sizeof (int));
|
||||||
if (sockError == -1) {
|
if (sockError == -1) {
|
||||||
@@ -680,6 +703,7 @@ static int get_miniserver_sockets(
|
|||||||
return UPNP_E_SOCKET_BIND;
|
return UPNP_E_SOCKET_BIND;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif //IPv6
|
||||||
} else {
|
} else {
|
||||||
if (listenfd4 != INVALID_SOCKET) {
|
if (listenfd4 != INVALID_SOCKET) {
|
||||||
unsigned short orig_listen_port4 = listen_port4;
|
unsigned short orig_listen_port4 = listen_port4;
|
||||||
@@ -707,12 +731,15 @@ static int get_miniserver_sockets(
|
|||||||
errorBuffer);
|
errorBuffer);
|
||||||
shutdown(listenfd4, SD_BOTH);
|
shutdown(listenfd4, SD_BOTH);
|
||||||
UpnpCloseSocket(listenfd4);
|
UpnpCloseSocket(listenfd4);
|
||||||
|
#ifdef UPNP_ENABLE_IPV6
|
||||||
shutdown(listenfd6, SD_BOTH);
|
shutdown(listenfd6, SD_BOTH);
|
||||||
UpnpCloseSocket(listenfd6);
|
UpnpCloseSocket(listenfd6);
|
||||||
|
#endif
|
||||||
return UPNP_E_SOCKET_BIND; // bind failed
|
return UPNP_E_SOCKET_BIND; // bind failed
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef UPNP_ENABLE_IPV6
|
||||||
if (listenfd6 != INVALID_SOCKET) {
|
if (listenfd6 != INVALID_SOCKET) {
|
||||||
unsigned short orig_listen_port6 = listen_port6;
|
unsigned short orig_listen_port6 = listen_port6;
|
||||||
do {
|
do {
|
||||||
@@ -745,6 +772,7 @@ static int get_miniserver_sockets(
|
|||||||
return UPNP_E_SOCKET_BIND;
|
return UPNP_E_SOCKET_BIND;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
UpnpPrintf( UPNP_INFO, MSERV, __FILE__, __LINE__,
|
UpnpPrintf( UPNP_INFO, MSERV, __FILE__, __LINE__,
|
||||||
@@ -759,8 +787,10 @@ static int get_miniserver_sockets(
|
|||||||
errorBuffer);
|
errorBuffer);
|
||||||
shutdown(listenfd4, SD_BOTH);
|
shutdown(listenfd4, SD_BOTH);
|
||||||
UpnpCloseSocket(listenfd4);
|
UpnpCloseSocket(listenfd4);
|
||||||
|
#ifdef UPNP_ENABLE_IPV6
|
||||||
shutdown(listenfd6, SD_BOTH);
|
shutdown(listenfd6, SD_BOTH);
|
||||||
UpnpCloseSocket(listenfd6);
|
UpnpCloseSocket(listenfd6);
|
||||||
|
#endif
|
||||||
return UPNP_E_LISTEN;
|
return UPNP_E_LISTEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -768,14 +798,17 @@ static int get_miniserver_sockets(
|
|||||||
if (actual_port4 <= 0) {
|
if (actual_port4 <= 0) {
|
||||||
shutdown(listenfd4, SD_BOTH);
|
shutdown(listenfd4, SD_BOTH);
|
||||||
UpnpCloseSocket(listenfd4);
|
UpnpCloseSocket(listenfd4);
|
||||||
|
#ifdef UPNP_ENABLE_IPV6
|
||||||
shutdown(listenfd6, SD_BOTH);
|
shutdown(listenfd6, SD_BOTH);
|
||||||
UpnpCloseSocket(listenfd6);
|
UpnpCloseSocket(listenfd6);
|
||||||
|
#endif
|
||||||
return UPNP_E_INTERNAL_ERROR;
|
return UPNP_E_INTERNAL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
out->miniServerPort4 = actual_port4;
|
out->miniServerPort4 = actual_port4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef UPNP_ENABLE_IPV6
|
||||||
if (listenfd6 != INVALID_SOCKET) {
|
if (listenfd6 != INVALID_SOCKET) {
|
||||||
ret_code = listen(listenfd6, SOMAXCONN);
|
ret_code = listen(listenfd6, SOMAXCONN);
|
||||||
if (ret_code == -1) {
|
if (ret_code == -1) {
|
||||||
@@ -801,10 +834,11 @@ static int get_miniserver_sockets(
|
|||||||
|
|
||||||
out->miniServerPort6 = actual_port6;
|
out->miniServerPort6 = actual_port6;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
out->miniServerSock4 = listenfd4;
|
out->miniServerSock4 = listenfd4;
|
||||||
|
#ifdef UPNP_ENABLE_IPV6
|
||||||
out->miniServerSock6 = listenfd6;
|
out->miniServerSock6 = listenfd6;
|
||||||
|
#endif
|
||||||
return UPNP_E_SUCCESS;
|
return UPNP_E_SUCCESS;
|
||||||
}
|
}
|
||||||
#endif /* INTERNAL_WEB_SERVER */
|
#endif /* INTERNAL_WEB_SERVER */
|
||||||
|
@@ -72,7 +72,6 @@ static str_int_entry Http_Method_Table[NUM_HTTP_METHODS] = {
|
|||||||
{"SUBSCRIBE", HTTPMETHOD_SUBSCRIBE},
|
{"SUBSCRIBE", HTTPMETHOD_SUBSCRIBE},
|
||||||
{"UNSUBSCRIBE", HTTPMETHOD_UNSUBSCRIBE},
|
{"UNSUBSCRIBE", HTTPMETHOD_UNSUBSCRIBE},
|
||||||
{"POST", SOAPMETHOD_POST},
|
{"POST", SOAPMETHOD_POST},
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define NUM_HTTP_HEADER_NAMES 33
|
#define NUM_HTTP_HEADER_NAMES 33
|
||||||
@@ -113,9 +112,7 @@ str_int_entry Http_Header_Names[NUM_HTTP_HEADER_NAMES] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
|
|
||||||
/************* scanner *************/
|
/************* scanner *************/
|
||||||
|
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
|
|
||||||
#define TOKCHAR_CR 0xD
|
#define TOKCHAR_CR 0xD
|
||||||
@@ -134,9 +131,7 @@ str_int_entry Http_Header_Names[NUM_HTTP_HEADER_NAMES] = {
|
|||||||
*
|
*
|
||||||
* Note :
|
* Note :
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
static UPNP_INLINE void
|
static UPNP_INLINE void scanner_init(OUT scanner_t *scanner, IN membuffer *bufptr)
|
||||||
scanner_init( OUT scanner_t *scanner,
|
|
||||||
IN membuffer *bufptr )
|
|
||||||
{
|
{
|
||||||
scanner->cursor = 0;
|
scanner->cursor = 0;
|
||||||
scanner->msg = bufptr;
|
scanner->msg = bufptr;
|
||||||
@@ -155,10 +150,9 @@ scanner_init( OUT scanner_t *scanner,
|
|||||||
*
|
*
|
||||||
* Note :
|
* Note :
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
static UPNP_INLINE xboolean
|
static UPNP_INLINE xboolean is_separator_char(IN char c)
|
||||||
is_separator_char( IN char c )
|
|
||||||
{
|
{
|
||||||
return strchr( " \t()<>@,;:\\\"/[]?={}", c ) != NULL;
|
return strchr(" \t()<>@,;:\\\"/[]?={}", c) != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
@@ -173,10 +167,9 @@ is_separator_char( IN char c )
|
|||||||
*
|
*
|
||||||
* Note :
|
* Note :
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
static UPNP_INLINE xboolean
|
static UPNP_INLINE xboolean is_identifier_char(IN char c)
|
||||||
is_identifier_char( IN char c )
|
|
||||||
{
|
{
|
||||||
return ( c >= 32 && c <= 126 ) && !is_separator_char( c );
|
return c >= 32 && c <= 126 && !is_separator_char(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
@@ -191,10 +184,9 @@ is_identifier_char( IN char c )
|
|||||||
*
|
*
|
||||||
* Note :
|
* Note :
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
static UPNP_INLINE xboolean
|
static UPNP_INLINE xboolean is_control_char(IN char c)
|
||||||
is_control_char( IN char c )
|
|
||||||
{
|
{
|
||||||
return ( ( c >= 0 && c <= 31 ) || ( c == 127 ) );
|
return (c >= 0 && c <= 31) || c == 127;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
@@ -209,8 +201,7 @@ is_control_char( IN char c )
|
|||||||
*
|
*
|
||||||
* Note :
|
* Note :
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
static UPNP_INLINE xboolean
|
static UPNP_INLINE xboolean is_qdtext_char(IN char cc)
|
||||||
is_qdtext_char( IN char cc )
|
|
||||||
{
|
{
|
||||||
unsigned char c = ( unsigned char )cc;
|
unsigned char c = ( unsigned char )cc;
|
||||||
|
|
||||||
@@ -244,10 +235,10 @@ is_qdtext_char( IN char cc )
|
|||||||
*
|
*
|
||||||
* Note :
|
* Note :
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
static parse_status_t
|
static parse_status_t scanner_get_token(
|
||||||
scanner_get_token( INOUT scanner_t * scanner,
|
INOUT scanner_t *scanner,
|
||||||
OUT memptr * token,
|
OUT memptr *token,
|
||||||
OUT token_type_t * tok_type )
|
OUT token_type_t *tok_type)
|
||||||
{
|
{
|
||||||
char *cursor;
|
char *cursor;
|
||||||
char *null_terminator; // point to null-terminator in buffer
|
char *null_terminator; // point to null-terminator in buffer
|
||||||
@@ -388,57 +379,11 @@ scanner_get_token( INOUT scanner_t * scanner,
|
|||||||
*
|
*
|
||||||
* Note :
|
* Note :
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
static UPNP_INLINE char *
|
static UPNP_INLINE char *scanner_get_str(IN scanner_t * scanner)
|
||||||
scanner_get_str( IN scanner_t * scanner )
|
|
||||||
{
|
{
|
||||||
return scanner->msg->buf + scanner->cursor;
|
return scanner->msg->buf + scanner->cursor;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************
|
|
||||||
* Function : scanner_pushback
|
|
||||||
*
|
|
||||||
* Parameters :
|
|
||||||
* INOUT scanner_t* scanner ; Scanner Object
|
|
||||||
* IN size_t pushback_bytes ; Bytes to be moved back
|
|
||||||
*
|
|
||||||
* Description : Move back by a certain number of bytes.
|
|
||||||
* This is used to put back one or more tokens back into the input
|
|
||||||
*
|
|
||||||
* Return : void ;
|
|
||||||
*
|
|
||||||
* Note :
|
|
||||||
************************************************************************/
|
|
||||||
#ifdef WIN32
|
|
||||||
#pragma message ("The only use of the function 'scanner_pushback()' in the code is commented out.")
|
|
||||||
#pragma message ("'scanner_pushback()' is a candidate for removal.")
|
|
||||||
#else
|
|
||||||
#warning The only use of the function 'scanner_pushback()' in the code is commented out.
|
|
||||||
#warning 'scanner_pushback()' is a candidate for removal.
|
|
||||||
#endif
|
|
||||||
static UPNP_INLINE void
|
|
||||||
scanner_pushback( INOUT scanner_t * scanner,
|
|
||||||
IN size_t pushback_bytes )
|
|
||||||
{
|
|
||||||
scanner->cursor -= pushback_bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/***********************************************************************/
|
|
||||||
|
|
||||||
/************* end of scanner **************/
|
|
||||||
|
|
||||||
/***********************************************************************/
|
|
||||||
|
|
||||||
/***********************************************************************/
|
|
||||||
|
|
||||||
/************* parser **************/
|
|
||||||
|
|
||||||
/***********************************************************************/
|
|
||||||
|
|
||||||
/***********************************************************************/
|
|
||||||
|
|
||||||
/************* http_message_t **************/
|
|
||||||
|
|
||||||
/***********************************************************************/
|
|
||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
* Function : httpmsg_compare
|
* Function : httpmsg_compare
|
||||||
@@ -453,15 +398,14 @@ scanner_pushback( INOUT scanner_t * scanner,
|
|||||||
*
|
*
|
||||||
* Note :
|
* Note :
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
static int
|
static int httpmsg_compare(void *param1, void *param2)
|
||||||
httpmsg_compare( void *param1,
|
|
||||||
void *param2 )
|
|
||||||
{
|
{
|
||||||
assert( param1 != NULL );
|
assert( param1 != NULL );
|
||||||
assert( param2 != NULL );
|
assert( param2 != NULL );
|
||||||
|
|
||||||
return ( ( http_header_t * ) param1 )->name_id ==
|
return
|
||||||
( ( http_header_t * ) param2 )->name_id;
|
((http_header_t *)param1)->name_id ==
|
||||||
|
((http_header_t *)param2)->name_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
@@ -476,8 +420,7 @@ httpmsg_compare( void *param1,
|
|||||||
*
|
*
|
||||||
* Note :
|
* Note :
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
static void
|
static void httpheader_free(void *msg)
|
||||||
httpheader_free( void *msg )
|
|
||||||
{
|
{
|
||||||
http_header_t *hdr = ( http_header_t * ) msg;
|
http_header_t *hdr = ( http_header_t * ) msg;
|
||||||
|
|
||||||
@@ -498,8 +441,7 @@ httpheader_free( void *msg )
|
|||||||
*
|
*
|
||||||
* Note :
|
* Note :
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
void
|
void httpmsg_init(INOUT http_message_t *msg)
|
||||||
httpmsg_init( INOUT http_message_t * msg )
|
|
||||||
{
|
{
|
||||||
msg->initialized = 1;
|
msg->initialized = 1;
|
||||||
msg->entity.buf = NULL;
|
msg->entity.buf = NULL;
|
||||||
@@ -521,8 +463,7 @@ httpmsg_init( INOUT http_message_t * msg )
|
|||||||
*
|
*
|
||||||
* Note :
|
* Note :
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
void
|
void httpmsg_destroy( INOUT http_message_t * msg )
|
||||||
httpmsg_destroy( INOUT http_message_t * msg )
|
|
||||||
{
|
{
|
||||||
assert( msg != NULL );
|
assert( msg != NULL );
|
||||||
|
|
||||||
@@ -550,9 +491,9 @@ httpmsg_destroy( INOUT http_message_t * msg )
|
|||||||
*
|
*
|
||||||
* Note :
|
* Note :
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
http_header_t *
|
http_header_t *httpmsg_find_hdr_str(
|
||||||
httpmsg_find_hdr_str( IN http_message_t * msg,
|
IN http_message_t *msg,
|
||||||
IN const char *header_name )
|
IN const char *header_name)
|
||||||
{
|
{
|
||||||
http_header_t *header;
|
http_header_t *header;
|
||||||
|
|
||||||
@@ -587,27 +528,21 @@ httpmsg_find_hdr_str( IN http_message_t * msg,
|
|||||||
*
|
*
|
||||||
* Note :
|
* Note :
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
http_header_t *
|
http_header_t *httpmsg_find_hdr(
|
||||||
httpmsg_find_hdr( IN http_message_t * msg,
|
IN http_message_t *msg,
|
||||||
IN int header_name_id,
|
IN int header_name_id,
|
||||||
OUT memptr * value )
|
OUT memptr *value)
|
||||||
{
|
{
|
||||||
http_header_t header; // temp header for searching
|
http_header_t header; // temp header for searching
|
||||||
|
|
||||||
ListNode *node;
|
ListNode *node;
|
||||||
|
|
||||||
http_header_t *data;
|
http_header_t *data;
|
||||||
|
|
||||||
header.name_id = header_name_id;
|
header.name_id = header_name_id;
|
||||||
|
|
||||||
node = ListFind( &msg->headers, NULL, &header );
|
node = ListFind( &msg->headers, NULL, &header );
|
||||||
|
|
||||||
if( node == NULL ) {
|
if( node == NULL ) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
data = ( http_header_t * ) node->item;
|
data = ( http_header_t * ) node->item;
|
||||||
|
|
||||||
if( value != NULL ) {
|
if( value != NULL ) {
|
||||||
value->buf = data->value.buf;
|
value->buf = data->value.buf;
|
||||||
value->length = data->value.length;
|
value->length = data->value.length;
|
||||||
@@ -616,12 +551,6 @@ httpmsg_find_hdr( IN http_message_t * msg,
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************/
|
|
||||||
|
|
||||||
/************* http_parser_t **************/
|
|
||||||
|
|
||||||
/***********************************************************************/
|
|
||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
* Function : skip_blank_lines
|
* Function : skip_blank_lines
|
||||||
*
|
*
|
||||||
@@ -634,23 +563,20 @@ httpmsg_find_hdr( IN http_message_t * msg,
|
|||||||
*
|
*
|
||||||
* Note :
|
* Note :
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
static UPNP_INLINE int
|
static UPNP_INLINE int skip_blank_lines(INOUT scanner_t *scanner)
|
||||||
skip_blank_lines( INOUT scanner_t * scanner )
|
|
||||||
{
|
{
|
||||||
memptr token;
|
memptr token;
|
||||||
token_type_t tok_type;
|
token_type_t tok_type;
|
||||||
parse_status_t status;
|
parse_status_t status;
|
||||||
|
|
||||||
// skip ws, crlf
|
/* skip ws, crlf */
|
||||||
do {
|
do {
|
||||||
status = scanner_get_token( scanner, &token, &tok_type );
|
status = scanner_get_token(scanner, &token, &tok_type);
|
||||||
} while( status == PARSE_OK &&
|
} while (status == PARSE_OK &&
|
||||||
( tok_type == TT_WHITESPACE || tok_type == TT_CRLF ) );
|
(tok_type == TT_WHITESPACE || tok_type == TT_CRLF));
|
||||||
|
if (status == PARSE_OK) {
|
||||||
if( status == PARSE_OK ) {
|
/* pushback a non-whitespace token */
|
||||||
// pushback a non-whitespace token
|
|
||||||
scanner->cursor -= token.length;
|
scanner->cursor -= token.length;
|
||||||
//scanner_pushback( scanner, token.length );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
@@ -671,8 +597,7 @@ skip_blank_lines( INOUT scanner_t * scanner )
|
|||||||
*
|
*
|
||||||
* Note :
|
* Note :
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
static UPNP_INLINE int
|
static UPNP_INLINE int skip_lws(INOUT scanner_t *scanner)
|
||||||
skip_lws( INOUT scanner_t * scanner )
|
|
||||||
{
|
{
|
||||||
memptr token;
|
memptr token;
|
||||||
token_type_t tok_type;
|
token_type_t tok_type;
|
||||||
@@ -726,9 +651,9 @@ skip_lws( INOUT scanner_t * scanner )
|
|||||||
*
|
*
|
||||||
* Note :
|
* Note :
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
static UPNP_INLINE parse_status_t
|
static UPNP_INLINE parse_status_t match_non_ws_string(
|
||||||
match_non_ws_string( INOUT scanner_t * scanner,
|
INOUT scanner_t *scanner,
|
||||||
OUT memptr * str )
|
OUT memptr *str)
|
||||||
{
|
{
|
||||||
memptr token;
|
memptr token;
|
||||||
token_type_t tok_type;
|
token_type_t tok_type;
|
||||||
@@ -792,9 +717,9 @@ match_non_ws_string( INOUT scanner_t * scanner,
|
|||||||
*
|
*
|
||||||
* Note :
|
* Note :
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
static UPNP_INLINE parse_status_t
|
static UPNP_INLINE parse_status_t match_raw_value(
|
||||||
match_raw_value( INOUT scanner_t * scanner,
|
INOUT scanner_t * scanner,
|
||||||
OUT memptr * raw_value )
|
OUT memptr *raw_value)
|
||||||
{
|
{
|
||||||
memptr token;
|
memptr token;
|
||||||
token_type_t tok_type;
|
token_type_t tok_type;
|
||||||
@@ -883,10 +808,10 @@ match_raw_value( INOUT scanner_t * scanner,
|
|||||||
* PARSE_FAILURE -- bad input
|
* PARSE_FAILURE -- bad input
|
||||||
* PARSE_INCOMPLETE
|
* PARSE_INCOMPLETE
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
static UPNP_INLINE int
|
static UPNP_INLINE int match_int(
|
||||||
match_int( INOUT scanner_t * scanner,
|
INOUT scanner_t *scanner,
|
||||||
IN int base,
|
IN int base,
|
||||||
OUT int *value )
|
OUT int *value)
|
||||||
{
|
{
|
||||||
memptr token;
|
memptr token;
|
||||||
token_type_t tok_type;
|
token_type_t tok_type;
|
||||||
@@ -970,36 +895,6 @@ read_until_crlf( INOUT scanner_t * scanner,
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************
|
|
||||||
* Function: skip_to_end_of_header
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* INOUT scanner_t* scanner ; Scanner Object
|
|
||||||
*
|
|
||||||
* Description: Skip to end of header
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* PARSE_OK
|
|
||||||
* PARSE_FAILURE
|
|
||||||
* PARSE_INCOMPLETE
|
|
||||||
************************************************************************/
|
|
||||||
#ifdef WIN32
|
|
||||||
#pragma message("There are currently no uses of the function 'skip_to_end_of_header()' in the code.")
|
|
||||||
#pragma message("'skip_to_end_of_header()' is a candidate for removal.")
|
|
||||||
#else
|
|
||||||
#warning There are currently no uses of the function 'skip_to_end_of_header()' in the code.
|
|
||||||
#warning 'skip_to_end_of_header()' is a candidate for removal.
|
|
||||||
#endif
|
|
||||||
static UPNP_INLINE int
|
|
||||||
skip_to_end_of_header( INOUT scanner_t * scanner )
|
|
||||||
{
|
|
||||||
memptr dummy_raw_value;
|
|
||||||
parse_status_t status;
|
|
||||||
|
|
||||||
status = match_raw_value( scanner, &dummy_raw_value );
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
* Function: match_char
|
* Function: match_char
|
||||||
*
|
*
|
||||||
@@ -1754,140 +1649,6 @@ parser_parse_headers( INOUT http_parser_t * parser )
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////
|
|
||||||
#ifdef HIGHLY_UNLIKELY
|
|
||||||
// **************
|
|
||||||
static parse_status_t
|
|
||||||
parser_parse_headers_old( INOUT http_parser_t * parser )
|
|
||||||
{
|
|
||||||
parse_status_t status;
|
|
||||||
memptr token;
|
|
||||||
memptr hdr_value;
|
|
||||||
token_type_t tok_type;
|
|
||||||
scanner_t *scanner = &parser->scanner;
|
|
||||||
size_t save_pos;
|
|
||||||
http_header_t *header;
|
|
||||||
int header_id;
|
|
||||||
int ret = 0;
|
|
||||||
int index;
|
|
||||||
http_header_t *orig_header;
|
|
||||||
char save_char;
|
|
||||||
int ret2,
|
|
||||||
ret3;
|
|
||||||
|
|
||||||
assert( parser->position == POS_HEADERS ||
|
|
||||||
parser->ent_position == ENTREAD_CHUNKY_HEADERS );
|
|
||||||
|
|
||||||
while( TRUE ) {
|
|
||||||
save_pos = scanner->cursor;
|
|
||||||
|
|
||||||
//
|
|
||||||
// check end of headers
|
|
||||||
//
|
|
||||||
status = scanner_get_token( scanner, &token, &tok_type );
|
|
||||||
if( status != PARSE_OK ) {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( tok_type == TT_CRLF ) {
|
|
||||||
// end of headers
|
|
||||||
parser->position = POS_ENTITY; // read entity next
|
|
||||||
return PARSE_OK;
|
|
||||||
}
|
|
||||||
//
|
|
||||||
// not end; read header
|
|
||||||
//
|
|
||||||
if( tok_type != TT_IDENTIFIER ) {
|
|
||||||
return PARSE_FAILURE; // didn't see header name
|
|
||||||
}
|
|
||||||
|
|
||||||
status = match( scanner, " : %R%c", &hdr_value );
|
|
||||||
if( status != PARSE_OK ) {
|
|
||||||
// pushback tokens; useful only on INCOMPLETE error
|
|
||||||
scanner->cursor = save_pos;
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// add header
|
|
||||||
//
|
|
||||||
|
|
||||||
// find header
|
|
||||||
index = map_str_to_int( token.buf, token.length, Http_Header_Names,
|
|
||||||
NUM_HTTP_HEADER_NAMES, FALSE );
|
|
||||||
if( index != -1 ) {
|
|
||||||
header_id = Http_Header_Names[index].id;
|
|
||||||
|
|
||||||
orig_header =
|
|
||||||
httpmsg_find_hdr( &parser->msg, header_id, NULL );
|
|
||||||
} else {
|
|
||||||
header_id = HDR_UNKNOWN;
|
|
||||||
|
|
||||||
save_char = token.buf[token.length];
|
|
||||||
token.buf[token.length] = '\0';
|
|
||||||
|
|
||||||
orig_header = httpmsg_find_hdr_str( &parser->msg, token.buf );
|
|
||||||
|
|
||||||
token.buf[token.length] = save_char; // restore
|
|
||||||
}
|
|
||||||
|
|
||||||
if( orig_header == NULL ) {
|
|
||||||
//
|
|
||||||
// add new header
|
|
||||||
//
|
|
||||||
|
|
||||||
header = ( http_header_t * ) malloc( sizeof( http_header_t ) );
|
|
||||||
if( header == NULL ) {
|
|
||||||
parser->http_error_code = HTTP_INTERNAL_SERVER_ERROR;
|
|
||||||
return PARSE_FAILURE;
|
|
||||||
}
|
|
||||||
membuffer_init( &header->multi_hdr_buf );
|
|
||||||
|
|
||||||
header->name = token;
|
|
||||||
header->value = hdr_value;
|
|
||||||
header->name_id = header_id;
|
|
||||||
|
|
||||||
ret = dlist_append( &parser->msg.headers, header );
|
|
||||||
if( ret == UPNP_E_OUTOF_MEMORY ) {
|
|
||||||
parser->http_error_code = HTTP_INTERNAL_SERVER_ERROR;
|
|
||||||
return PARSE_FAILURE;
|
|
||||||
}
|
|
||||||
} else if( hdr_value.length > 0 ) {
|
|
||||||
//
|
|
||||||
// append value to existing header
|
|
||||||
//
|
|
||||||
|
|
||||||
if( orig_header->multi_hdr_buf.buf == NULL ) {
|
|
||||||
// store in buffer
|
|
||||||
ret = membuffer_append( &orig_header->multi_hdr_buf,
|
|
||||||
orig_header->value.buf,
|
|
||||||
orig_header->value.length );
|
|
||||||
}
|
|
||||||
// append space
|
|
||||||
ret2 =
|
|
||||||
membuffer_append( &orig_header->multi_hdr_buf, ", ", 2 );
|
|
||||||
|
|
||||||
// append continuation of header value
|
|
||||||
ret3 = membuffer_append( &orig_header->multi_hdr_buf,
|
|
||||||
hdr_value.buf, hdr_value.length );
|
|
||||||
|
|
||||||
if( ret == UPNP_E_OUTOF_MEMORY ||
|
|
||||||
ret2 == UPNP_E_OUTOF_MEMORY ||
|
|
||||||
ret3 == UPNP_E_OUTOF_MEMORY ) {
|
|
||||||
// not enuf mem
|
|
||||||
parser->http_error_code = HTTP_INTERNAL_SERVER_ERROR;
|
|
||||||
return PARSE_FAILURE;
|
|
||||||
}
|
|
||||||
// header value points to allocated buf
|
|
||||||
orig_header->value.buf = orig_header->multi_hdr_buf.buf;
|
|
||||||
orig_header->value.length = orig_header->multi_hdr_buf.length;
|
|
||||||
}
|
|
||||||
} // end while
|
|
||||||
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
// ******************************
|
|
||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
* Function: parser_parse_entity_using_clen
|
* Function: parser_parse_entity_using_clen
|
||||||
*
|
*
|
||||||
@@ -1909,9 +1670,9 @@ parser_parse_entity_using_clen( INOUT http_parser_t * parser )
|
|||||||
assert( parser->ent_position == ENTREAD_USING_CLEN );
|
assert( parser->ent_position == ENTREAD_USING_CLEN );
|
||||||
|
|
||||||
// determine entity (i.e. body) length so far
|
// determine entity (i.e. body) length so far
|
||||||
//entity_length = parser->msg.msg.length - parser->entity_start_position;
|
|
||||||
parser->msg.entity.length =
|
parser->msg.entity.length =
|
||||||
parser->msg.msg.length - parser->entity_start_position;
|
parser->msg.msg.length - parser->entity_start_position +
|
||||||
|
parser->msg.entity_offset;
|
||||||
|
|
||||||
if( parser->msg.entity.length < parser->content_length ) {
|
if( parser->msg.entity.length < parser->content_length ) {
|
||||||
// more data to be read
|
// more data to be read
|
||||||
@@ -1919,7 +1680,8 @@ parser_parse_entity_using_clen( INOUT http_parser_t * parser )
|
|||||||
} else {
|
} else {
|
||||||
if( parser->msg.entity.length > parser->content_length ) {
|
if( parser->msg.entity.length > parser->content_length ) {
|
||||||
// silently discard extra data
|
// silently discard extra data
|
||||||
parser->msg.msg.buf[parser->entity_start_position +
|
parser->msg.msg.buf[parser->entity_start_position -
|
||||||
|
parser->msg.entity_offset +
|
||||||
parser->content_length] = '\0';
|
parser->content_length] = '\0';
|
||||||
}
|
}
|
||||||
// save entity length
|
// save entity length
|
||||||
@@ -2304,6 +2066,7 @@ parser_response_init( OUT http_parser_t * parser,
|
|||||||
parser_init( parser );
|
parser_init( parser );
|
||||||
parser->msg.is_request = FALSE;
|
parser->msg.is_request = FALSE;
|
||||||
parser->msg.request_method = request_method;
|
parser->msg.request_method = request_method;
|
||||||
|
parser->msg.entity_offset = 0;
|
||||||
parser->position = POS_RESPONSE_LINE;
|
parser->position = POS_RESPONSE_LINE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2399,10 +2162,6 @@ parser_append( INOUT http_parser_t * parser,
|
|||||||
return parser_parse( parser );
|
return parser_parse( parser );
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************
|
|
||||||
********** end of parser ***********
|
|
||||||
************************************************************************/
|
|
||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
* Function: raw_to_int
|
* Function: raw_to_int
|
||||||
*
|
*
|
||||||
@@ -2415,9 +2174,7 @@ parser_append( INOUT http_parser_t * parser,
|
|||||||
* Returns:
|
* Returns:
|
||||||
* int
|
* int
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
int
|
int raw_to_int(IN memptr *raw_value, IN int base)
|
||||||
raw_to_int( IN memptr * raw_value,
|
|
||||||
IN int base )
|
|
||||||
{
|
{
|
||||||
long num;
|
long num;
|
||||||
char *end_ptr;
|
char *end_ptr;
|
||||||
@@ -2454,9 +2211,7 @@ raw_to_int( IN memptr * raw_value,
|
|||||||
* Returns:
|
* Returns:
|
||||||
* int - index at which the substring is found.
|
* int - index at which the substring is found.
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
int
|
int raw_find_str(IN memptr *raw_value, IN const char *str)
|
||||||
raw_find_str( IN memptr *raw_value,
|
|
||||||
IN const char *str )
|
|
||||||
{
|
{
|
||||||
char c;
|
char c;
|
||||||
char *ptr;
|
char *ptr;
|
||||||
@@ -2499,8 +2254,7 @@ raw_find_str( IN memptr *raw_value,
|
|||||||
* Returns:
|
* Returns:
|
||||||
* const char* ptr - Ptr to the HTTP Method
|
* const char* ptr - Ptr to the HTTP Method
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
const char *
|
const char *method_to_str(IN http_method_t method)
|
||||||
method_to_str( IN http_method_t method )
|
|
||||||
{
|
{
|
||||||
int index;
|
int index;
|
||||||
|
|
||||||
@@ -2544,5 +2298,5 @@ void print_http_headers(http_message_t *hmsg)
|
|||||||
/* NNS: node = dlist_next( &hmsg->headers, node ); */
|
/* NNS: node = dlist_next( &hmsg->headers, node ); */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif /* DEBUG */
|
||||||
|
|
||||||
|
@@ -92,6 +92,153 @@ const int CHUNK_TAIL_SIZE = 10;
|
|||||||
#define CHUNK_TAIL_SIZE 10
|
#define CHUNK_TAIL_SIZE 10
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef UPNP_BLOCKING_CONNECT
|
||||||
|
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* Function : Make_Socket_NoBlocking
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* IN int sock: socket
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* This function makes socket non-blocking.
|
||||||
|
*
|
||||||
|
* Returns: int
|
||||||
|
* 0 if successful else -1
|
||||||
|
***************************************************************************/
|
||||||
|
static int Make_Socket_NoBlocking(int sock)
|
||||||
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
u_long val = 1;
|
||||||
|
return ioctlsocket(sock, FIONBIO, &val);
|
||||||
|
#else
|
||||||
|
int val;
|
||||||
|
|
||||||
|
val = fcntl(sock, F_GETFL, 0);
|
||||||
|
if (fcntl(sock, F_SETFL, val | O_NONBLOCK) == -1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* Function : Make_Socket_Blocking
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* IN int sock: socket
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* This function makes socket blocking.
|
||||||
|
*
|
||||||
|
* Returns: int
|
||||||
|
* 0 if successful else -1
|
||||||
|
***************************************************************************/
|
||||||
|
static int Make_Socket_Blocking(int sock)
|
||||||
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
u_long val = 0;
|
||||||
|
return ioctlsocket(sock, FIONBIO, &val);
|
||||||
|
#else
|
||||||
|
int val;
|
||||||
|
|
||||||
|
val = fcntl(sock, F_GETFL, 0);
|
||||||
|
if (fcntl(sock, F_SETFL, val & ~O_NONBLOCK) == -1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* in seconds */
|
||||||
|
#define DEFAULT_TCP_CONNECT_TIMEOUT 5
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* Function : Check_Connect_And_Wait_Connection
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* IN int sock: socket
|
||||||
|
* IN int connect_res: result of connect
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* This function checks socket connection and wait if it is not connected
|
||||||
|
* It should be called just after connect
|
||||||
|
*
|
||||||
|
* Returns: int
|
||||||
|
* 0 if successful else -1
|
||||||
|
***************************************************************************/
|
||||||
|
static int Check_Connect_And_Wait_Connection(int sock, int connect_res)
|
||||||
|
{
|
||||||
|
struct timeval tmvTimeout = {DEFAULT_TCP_CONNECT_TIMEOUT, 0};
|
||||||
|
int result;
|
||||||
|
#ifdef WIN32
|
||||||
|
struct fd_set fdSet;
|
||||||
|
#else
|
||||||
|
fd_set fdSet;
|
||||||
|
#endif
|
||||||
|
FD_ZERO(&fdSet);
|
||||||
|
FD_SET(sock, &fdSet);
|
||||||
|
|
||||||
|
if (connect_res < 0) {
|
||||||
|
#ifdef WIN32
|
||||||
|
if (WSAEWOULDBLOCK == WSAGetLastError() ) {
|
||||||
|
#else
|
||||||
|
if (EINPROGRESS == errno ) {
|
||||||
|
#endif
|
||||||
|
result = select(sock + 1, NULL, &fdSet, NULL, &tmvTimeout);
|
||||||
|
if (result < 0) {
|
||||||
|
#ifdef WIN32
|
||||||
|
/* WSAGetLastError(); */
|
||||||
|
#else
|
||||||
|
/* errno */
|
||||||
|
#endif
|
||||||
|
return -1;
|
||||||
|
} else if (result == 0) {
|
||||||
|
/* timeout */
|
||||||
|
return -1;
|
||||||
|
#ifndef WIN32
|
||||||
|
} else {
|
||||||
|
int valopt = 0;
|
||||||
|
socklen_t len;
|
||||||
|
if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (void *) &valopt, &len) < 0) {
|
||||||
|
/* failed to read delayed error */
|
||||||
|
return -1;
|
||||||
|
} else if (valopt) {
|
||||||
|
/* delayed error = valopt */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif /* UPNP_BLOCKING_CONNECT */
|
||||||
|
|
||||||
|
static int private_connect(
|
||||||
|
int sockfd,
|
||||||
|
const struct sockaddr *serv_addr,
|
||||||
|
socklen_t addrlen)
|
||||||
|
{
|
||||||
|
#ifdef UPNP_BLOCKING_CONNECT
|
||||||
|
int ret = Make_Socket_NoBlocking(sockfd);
|
||||||
|
if (ret != - 1) {
|
||||||
|
ret = connect(sockfd, serv_addr, addrlen);
|
||||||
|
ret = Check_Connect_And_Wait_Connection(sockfd, ret);
|
||||||
|
if (ret != - 1) {
|
||||||
|
ret = Make_Socket_Blocking(sockfd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
#else
|
||||||
|
return connect(sockfd, serv_addr, addrlen);
|
||||||
|
#endif /* UPNP_BLOCKING_CONNECT */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
* Function: http_FixUrl
|
* Function: http_FixUrl
|
||||||
*
|
*
|
||||||
@@ -106,23 +253,19 @@ const int CHUNK_TAIL_SIZE = 10;
|
|||||||
* UPNP_E_INVALID_URL
|
* UPNP_E_INVALID_URL
|
||||||
* UPNP_E_SUCCESS
|
* UPNP_E_SUCCESS
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
int
|
int http_FixUrl(IN uri_type *url, OUT uri_type *fixed_url)
|
||||||
http_FixUrl( IN uri_type * url,
|
|
||||||
OUT uri_type * fixed_url )
|
|
||||||
{
|
{
|
||||||
char *temp_path = "/";
|
char *temp_path = "/";
|
||||||
|
|
||||||
*fixed_url = *url;
|
*fixed_url = *url;
|
||||||
|
if (token_string_casecmp(&fixed_url->scheme, "http") != 0) {
|
||||||
if( token_string_casecmp( &fixed_url->scheme, "http" ) != 0 ) {
|
|
||||||
return UPNP_E_INVALID_URL;
|
return UPNP_E_INVALID_URL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( fixed_url->hostport.text.size == 0 ) {
|
if( fixed_url->hostport.text.size == 0 ) {
|
||||||
return UPNP_E_INVALID_URL;
|
return UPNP_E_INVALID_URL;
|
||||||
}
|
}
|
||||||
// set pathquery to "/" if it is empty
|
/* set pathquery to "/" if it is empty */
|
||||||
if( fixed_url->pathquery.size == 0 ) {
|
if (fixed_url->pathquery.size == 0) {
|
||||||
fixed_url->pathquery.buff = temp_path;
|
fixed_url->pathquery.buff = temp_path;
|
||||||
fixed_url->pathquery.size = 1;
|
fixed_url->pathquery.size = 1;
|
||||||
}
|
}
|
||||||
@@ -146,18 +289,18 @@ http_FixUrl( IN uri_type * url,
|
|||||||
* UPNP_E_INVALID_URL
|
* UPNP_E_INVALID_URL
|
||||||
* UPNP_E_SUCCESS
|
* UPNP_E_SUCCESS
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
int
|
int http_FixStrUrl(
|
||||||
http_FixStrUrl( IN const char *urlstr,
|
IN const char *urlstr,
|
||||||
IN int urlstrlen,
|
IN int urlstrlen,
|
||||||
OUT uri_type * fixed_url )
|
OUT uri_type * fixed_url)
|
||||||
{
|
{
|
||||||
uri_type url;
|
uri_type url;
|
||||||
|
|
||||||
if( parse_uri( urlstr, urlstrlen, &url ) != HTTP_SUCCESS ) {
|
if (parse_uri(urlstr, urlstrlen, &url) != HTTP_SUCCESS) {
|
||||||
return UPNP_E_INVALID_URL;
|
return UPNP_E_INVALID_URL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return http_FixUrl( &url, fixed_url );
|
return http_FixUrl(&url, fixed_url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -176,27 +319,31 @@ http_FixStrUrl( IN const char *urlstr,
|
|||||||
* UPNP_E_OUTOF_SOCKET
|
* UPNP_E_OUTOF_SOCKET
|
||||||
* UPNP_E_SOCKET_CONNECT on error
|
* UPNP_E_SOCKET_CONNECT on error
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
int
|
int http_Connect(
|
||||||
http_Connect( IN uri_type * destination_url,
|
IN uri_type *destination_url,
|
||||||
OUT uri_type * url )
|
OUT uri_type *url)
|
||||||
{
|
{
|
||||||
int connfd;
|
int connfd;
|
||||||
|
int sockaddr_len;
|
||||||
|
int ret_connect;
|
||||||
|
|
||||||
http_FixUrl( destination_url, url );
|
http_FixUrl(destination_url, url);
|
||||||
|
|
||||||
connfd = socket( url->hostport.IPaddress.ss_family, SOCK_STREAM, 0 );
|
connfd = socket(url->hostport.IPaddress.ss_family, SOCK_STREAM, 0);
|
||||||
if( connfd == -1 ) {
|
if (connfd == -1) {
|
||||||
return UPNP_E_OUTOF_SOCKET;
|
return UPNP_E_OUTOF_SOCKET;
|
||||||
}
|
}
|
||||||
|
sockaddr_len = url->hostport.IPaddress.ss_family == AF_INET6 ?
|
||||||
if( connect( connfd, ( struct sockaddr * )&url->hostport.IPaddress,
|
sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in);
|
||||||
sizeof( url->hostport.IPaddress ) ) == -1 ) {
|
ret_connect = connect(connfd,
|
||||||
|
(struct sockaddr *)&url->hostport.IPaddress, sockaddr_len);
|
||||||
|
if (ret_connect == -1) {
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
UpnpPrintf(UPNP_CRITICAL, HTTP, __FILE__, __LINE__,
|
UpnpPrintf(UPNP_CRITICAL, HTTP, __FILE__, __LINE__,
|
||||||
"connect error: %d\n", WSAGetLastError());
|
"connect error: %d\n", WSAGetLastError());
|
||||||
#endif
|
#endif
|
||||||
shutdown( connfd, SD_BOTH );
|
shutdown(connfd, SD_BOTH);
|
||||||
UpnpCloseSocket( connfd );
|
UpnpCloseSocket(connfd);
|
||||||
return UPNP_E_SOCKET_CONNECT;
|
return UPNP_E_SOCKET_CONNECT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -252,7 +399,7 @@ int http_RecvMessage(
|
|||||||
"<<< (RECVD) <<<\n%s\n-----------------\n",
|
"<<< (RECVD) <<<\n%s\n-----------------\n",
|
||||||
parser->msg.msg.buf );
|
parser->msg.msg.buf );
|
||||||
print_http_headers( &parser->msg );
|
print_http_headers( &parser->msg );
|
||||||
if (parser->content_length > (unsigned int)g_maxContentLength) {
|
if (g_maxContentLength > 0 && parser->content_length > (unsigned int)g_maxContentLength) {
|
||||||
*http_error_code = HTTP_REQ_ENTITY_TOO_LARGE;
|
*http_error_code = HTTP_REQ_ENTITY_TOO_LARGE;
|
||||||
line = __LINE__;
|
line = __LINE__;
|
||||||
ret = UPNP_E_OUTOF_BOUNDS;
|
ret = UPNP_E_OUTOF_BOUNDS;
|
||||||
@@ -536,53 +683,55 @@ end:
|
|||||||
* Error Codes returned by http_SendMessage
|
* Error Codes returned by http_SendMessage
|
||||||
* Error Codes returned by http_RecvMessage
|
* Error Codes returned by http_RecvMessage
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
int
|
int http_RequestAndResponse(
|
||||||
http_RequestAndResponse( IN uri_type * destination,
|
IN uri_type *destination,
|
||||||
IN const char *request,
|
IN const char *request,
|
||||||
IN size_t request_length,
|
IN size_t request_length,
|
||||||
IN http_method_t req_method,
|
IN http_method_t req_method,
|
||||||
IN int timeout_secs,
|
IN int timeout_secs,
|
||||||
OUT http_parser_t * response )
|
OUT http_parser_t *response)
|
||||||
{
|
{
|
||||||
int tcp_connection;
|
int tcp_connection;
|
||||||
int ret_code;
|
int ret_code;
|
||||||
|
int sockaddr_len;
|
||||||
int http_error_code;
|
int http_error_code;
|
||||||
SOCKINFO info;
|
SOCKINFO info;
|
||||||
|
|
||||||
tcp_connection = socket( destination->hostport.IPaddress.ss_family, SOCK_STREAM, 0 );
|
tcp_connection = socket(
|
||||||
if( tcp_connection == -1 ) {
|
destination->hostport.IPaddress.ss_family, SOCK_STREAM, 0);
|
||||||
parser_response_init( response, req_method );
|
if (tcp_connection == -1) {
|
||||||
|
parser_response_init(response, req_method);
|
||||||
return UPNP_E_SOCKET_ERROR;
|
return UPNP_E_SOCKET_ERROR;
|
||||||
}
|
}
|
||||||
if( sock_init( &info, tcp_connection ) != UPNP_E_SUCCESS )
|
if (sock_init(&info, tcp_connection) != UPNP_E_SUCCESS) {
|
||||||
{
|
parser_response_init(response, req_method);
|
||||||
sock_destroy( &info, SD_BOTH );
|
ret_code = UPNP_E_SOCKET_ERROR;
|
||||||
parser_response_init( response, req_method );
|
goto end_function;
|
||||||
return UPNP_E_SOCKET_ERROR;
|
|
||||||
}
|
}
|
||||||
// connect
|
/* connect */
|
||||||
ret_code = connect( info.socket,
|
sockaddr_len = destination->hostport.IPaddress.ss_family == AF_INET6 ?
|
||||||
( struct sockaddr * )&destination->hostport.
|
sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in);
|
||||||
IPaddress, sizeof( struct sockaddr_storage ) );
|
ret_code = private_connect(info.socket,
|
||||||
|
(struct sockaddr *)&(destination->hostport.IPaddress), sockaddr_len);
|
||||||
|
if (ret_code == -1) {
|
||||||
|
parser_response_init(response, req_method);
|
||||||
|
ret_code = UPNP_E_SOCKET_CONNECT;
|
||||||
|
goto end_function;
|
||||||
|
}
|
||||||
|
/* send request */
|
||||||
|
ret_code = http_SendMessage(&info, &timeout_secs, "b",
|
||||||
|
request, request_length);
|
||||||
|
if (ret_code != 0) {
|
||||||
|
parser_response_init(response, req_method);
|
||||||
|
goto end_function;
|
||||||
|
}
|
||||||
|
/* recv response */
|
||||||
|
ret_code = http_RecvMessage(&info, response, req_method,
|
||||||
|
&timeout_secs, &http_error_code);
|
||||||
|
|
||||||
if( ret_code == -1 ) {
|
end_function:
|
||||||
sock_destroy( &info, SD_BOTH );
|
/* should shutdown completely */
|
||||||
parser_response_init( response, req_method );
|
sock_destroy(&info, SD_BOTH);
|
||||||
return UPNP_E_SOCKET_CONNECT;
|
|
||||||
}
|
|
||||||
// send request
|
|
||||||
ret_code = http_SendMessage( &info, &timeout_secs, "b",
|
|
||||||
request, request_length );
|
|
||||||
if( ret_code != 0 ) {
|
|
||||||
sock_destroy( &info, SD_BOTH );
|
|
||||||
parser_response_init( response, req_method );
|
|
||||||
return ret_code;
|
|
||||||
}
|
|
||||||
// recv response
|
|
||||||
ret_code = http_RecvMessage( &info, response, req_method,
|
|
||||||
&timeout_secs, &http_error_code );
|
|
||||||
|
|
||||||
sock_destroy( &info, SD_BOTH ); //should shutdown completely
|
|
||||||
|
|
||||||
return ret_code;
|
return ret_code;
|
||||||
}
|
}
|
||||||
@@ -1000,72 +1149,66 @@ http_CloseHttpPost( IN void *Handle,
|
|||||||
* UPNP_E_SOCKET_ERROR
|
* UPNP_E_SOCKET_ERROR
|
||||||
* UPNP_E_SOCKET_CONNECT
|
* UPNP_E_SOCKET_CONNECT
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
int
|
int http_OpenHttpPost(
|
||||||
http_OpenHttpPost( IN const char *url_str,
|
IN const char *url_str,
|
||||||
IN OUT void **Handle,
|
IN OUT void **Handle,
|
||||||
IN const char *contentType,
|
IN const char *contentType,
|
||||||
IN int contentLength,
|
IN int contentLength,
|
||||||
IN int timeout )
|
IN int timeout)
|
||||||
{
|
{
|
||||||
int ret_code;
|
int ret_code;
|
||||||
|
int sockaddr_len;
|
||||||
int tcp_connection;
|
int tcp_connection;
|
||||||
membuffer request;
|
membuffer request;
|
||||||
http_post_handle_t *handle = NULL;
|
http_post_handle_t *handle = NULL;
|
||||||
uri_type url;
|
uri_type url;
|
||||||
|
|
||||||
if( ( !url_str ) || ( !Handle ) || ( !contentType ) ) {
|
if ( !url_str || !Handle || !contentType) {
|
||||||
return UPNP_E_INVALID_PARAM;
|
return UPNP_E_INVALID_PARAM;
|
||||||
}
|
}
|
||||||
|
|
||||||
( *Handle ) = handle;
|
*Handle = handle;
|
||||||
|
|
||||||
if( ( ret_code =
|
ret_code = MakePostMessage(url_str, &request, &url,
|
||||||
MakePostMessage( url_str, &request, &url, contentLength,
|
contentLength, contentType);
|
||||||
contentType ) ) != UPNP_E_SUCCESS ) {
|
if (ret_code != UPNP_E_SUCCESS) {
|
||||||
return ret_code;
|
return ret_code;
|
||||||
}
|
}
|
||||||
|
handle = (http_post_handle_t *) malloc(sizeof(http_post_handle_t));
|
||||||
handle =
|
if (!handle) {
|
||||||
( http_post_handle_t * ) malloc( sizeof( http_post_handle_t ) );
|
|
||||||
|
|
||||||
if( handle == NULL ) {
|
|
||||||
return UPNP_E_OUTOF_MEMORY;
|
return UPNP_E_OUTOF_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
handle->contentLength = contentLength;
|
handle->contentLength = contentLength;
|
||||||
|
tcp_connection = socket(url.hostport.IPaddress.ss_family, SOCK_STREAM, 0);
|
||||||
tcp_connection = socket( url.hostport.IPaddress.ss_family, SOCK_STREAM, 0 );
|
if (tcp_connection == -1) {
|
||||||
if( tcp_connection == -1 ) {
|
|
||||||
ret_code = UPNP_E_SOCKET_ERROR;
|
ret_code = UPNP_E_SOCKET_ERROR;
|
||||||
goto errorHandler;
|
goto errorHandler;
|
||||||
}
|
}
|
||||||
|
if (sock_init(&handle->sock_info, tcp_connection) != UPNP_E_SUCCESS) {
|
||||||
if( sock_init( &handle->sock_info, tcp_connection ) != UPNP_E_SUCCESS )
|
|
||||||
{
|
|
||||||
sock_destroy( &handle->sock_info, SD_BOTH );
|
sock_destroy( &handle->sock_info, SD_BOTH );
|
||||||
ret_code = UPNP_E_SOCKET_ERROR;
|
ret_code = UPNP_E_SOCKET_ERROR;
|
||||||
goto errorHandler;
|
goto errorHandler;
|
||||||
}
|
}
|
||||||
|
sockaddr_len = url.hostport.IPaddress.ss_family == AF_INET6 ?
|
||||||
ret_code = connect( handle->sock_info.socket,
|
sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in);
|
||||||
( struct sockaddr * )&url.hostport.IPaddress,
|
ret_code = private_connect(handle->sock_info.socket,
|
||||||
sizeof( struct sockaddr_storage ) );
|
(struct sockaddr *)&(url.hostport.IPaddress), sockaddr_len);
|
||||||
|
if (ret_code == -1) {
|
||||||
if( ret_code == -1 ) {
|
sock_destroy(&handle->sock_info, SD_BOTH);
|
||||||
sock_destroy( &handle->sock_info, SD_BOTH );
|
|
||||||
ret_code = UPNP_E_SOCKET_CONNECT;
|
ret_code = UPNP_E_SOCKET_CONNECT;
|
||||||
goto errorHandler;
|
goto errorHandler;
|
||||||
}
|
}
|
||||||
// send request
|
/* send request */
|
||||||
ret_code = http_SendMessage( &handle->sock_info, &timeout, "b",
|
ret_code = http_SendMessage(&handle->sock_info, &timeout, "b",
|
||||||
request.buf, request.length );
|
request.buf, request.length);
|
||||||
if( ret_code != 0 ) {
|
if (ret_code != 0) {
|
||||||
sock_destroy( &handle->sock_info, SD_BOTH );
|
sock_destroy(&handle->sock_info, SD_BOTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
errorHandler:
|
errorHandler:
|
||||||
membuffer_destroy( &request );
|
membuffer_destroy(&request);
|
||||||
( *Handle ) = handle;
|
*Handle = handle;
|
||||||
|
|
||||||
return ret_code;
|
return ret_code;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1327,9 +1470,10 @@ http_ReadHttpGet( IN void *Handle,
|
|||||||
|
|
||||||
int ret_code = 0;
|
int ret_code = 0;
|
||||||
|
|
||||||
if( ( !handle ) || ( !size ) || ( ( ( *size ) > 0 ) && !buf )
|
if( !handle || !size || (*size > 0 && !buf) || *size < 0) {
|
||||||
|| ( ( *size ) < 0 ) ) {
|
if(size) {
|
||||||
if(size) ( *size ) = 0;
|
*size = 0;
|
||||||
|
}
|
||||||
return UPNP_E_INVALID_PARAM;
|
return UPNP_E_INVALID_PARAM;
|
||||||
}
|
}
|
||||||
//first parse what has already been gotten
|
//first parse what has already been gotten
|
||||||
@@ -1346,11 +1490,11 @@ http_ReadHttpGet( IN void *Handle,
|
|||||||
&& ( status != PARSE_CONTINUE_1 )
|
&& ( status != PARSE_CONTINUE_1 )
|
||||||
&& ( status != PARSE_INCOMPLETE ) ) {
|
&& ( status != PARSE_INCOMPLETE ) ) {
|
||||||
//error
|
//error
|
||||||
( *size ) = 0;
|
*size = 0;
|
||||||
return UPNP_E_BAD_RESPONSE;
|
return UPNP_E_BAD_RESPONSE;
|
||||||
}
|
}
|
||||||
//read more if necessary entity
|
//read more if necessary entity
|
||||||
while( ( ( handle->entity_offset + ( *size ) ) >
|
while( ( ( handle->response.msg.entity_offset + *size ) >
|
||||||
handle->response.msg.entity.length )
|
handle->response.msg.entity.length )
|
||||||
&& ( ! handle->cancel )
|
&& ( ! handle->cancel )
|
||||||
&& ( handle->response.position != POS_COMPLETE ) ) {
|
&& ( handle->response.position != POS_COMPLETE ) ) {
|
||||||
@@ -1365,7 +1509,7 @@ http_ReadHttpGet( IN void *Handle,
|
|||||||
// set failure status
|
// set failure status
|
||||||
handle->response.http_error_code =
|
handle->response.http_error_code =
|
||||||
HTTP_INTERNAL_SERVER_ERROR;
|
HTTP_INTERNAL_SERVER_ERROR;
|
||||||
( *size ) = 0;
|
*size = 0;
|
||||||
return PARSE_FAILURE;
|
return PARSE_FAILURE;
|
||||||
}
|
}
|
||||||
status = parser_parse_entity( &handle->response );
|
status = parser_parse_entity( &handle->response );
|
||||||
@@ -1376,7 +1520,7 @@ http_ReadHttpGet( IN void *Handle,
|
|||||||
&& ( status != PARSE_CONTINUE_1 )
|
&& ( status != PARSE_CONTINUE_1 )
|
||||||
&& ( status != PARSE_INCOMPLETE ) ) {
|
&& ( status != PARSE_INCOMPLETE ) ) {
|
||||||
//error
|
//error
|
||||||
( *size ) = 0;
|
*size = 0;
|
||||||
return UPNP_E_BAD_RESPONSE;
|
return UPNP_E_BAD_RESPONSE;
|
||||||
}
|
}
|
||||||
} else if( num_read == 0 ) {
|
} else if( num_read == 0 ) {
|
||||||
@@ -1387,31 +1531,33 @@ http_ReadHttpGet( IN void *Handle,
|
|||||||
handle->response.position = POS_COMPLETE;
|
handle->response.position = POS_COMPLETE;
|
||||||
} else {
|
} else {
|
||||||
// partial msg
|
// partial msg
|
||||||
( *size ) = 0;
|
*size = 0;
|
||||||
handle->response.http_error_code = HTTP_BAD_REQUEST; // or response
|
handle->response.http_error_code = HTTP_BAD_REQUEST; // or response
|
||||||
return UPNP_E_BAD_HTTPMSG;
|
return UPNP_E_BAD_HTTPMSG;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
( *size ) = 0;
|
*size = 0;
|
||||||
return num_read;
|
return num_read;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( ( handle->entity_offset + ( *size ) ) >
|
if ((handle->response.msg.entity_offset + *size) > handle->response.msg.entity.length) {
|
||||||
handle->response.msg.entity.length ) {
|
*size = handle->response.msg.entity.length - handle->response.msg.entity_offset;
|
||||||
( *size ) =
|
|
||||||
handle->response.msg.entity.length - handle->entity_offset;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy( buf,
|
memcpy(buf,
|
||||||
&handle->response.msg.msg.buf[handle->
|
&handle->response.msg.msg.buf[handle->response.entity_start_position],
|
||||||
response.entity_start_position +
|
*size);
|
||||||
handle->entity_offset],
|
if (*size > 0) {
|
||||||
( *size ) );
|
membuffer_delete(&handle->response.msg.msg,
|
||||||
handle->entity_offset += ( *size );
|
handle->response.entity_start_position,
|
||||||
|
*size);
|
||||||
|
}
|
||||||
|
|
||||||
if ( handle->cancel )
|
handle->response.msg.entity_offset += *size;
|
||||||
|
if (handle->cancel) {
|
||||||
return UPNP_E_CANCELED;
|
return UPNP_E_CANCELED;
|
||||||
|
}
|
||||||
|
|
||||||
return UPNP_E_SUCCESS;
|
return UPNP_E_SUCCESS;
|
||||||
}
|
}
|
||||||
@@ -1498,7 +1644,6 @@ http_CloseHttpGet( IN void *Handle )
|
|||||||
|
|
||||||
sock_destroy( &handle->sock_info, SD_BOTH ); //should shutdown completely
|
sock_destroy( &handle->sock_info, SD_BOTH ); //should shutdown completely
|
||||||
httpmsg_destroy( &handle->response.msg );
|
httpmsg_destroy( &handle->response.msg );
|
||||||
handle->entity_offset = 0;
|
|
||||||
free( handle );
|
free( handle );
|
||||||
return UPNP_E_SUCCESS;
|
return UPNP_E_SUCCESS;
|
||||||
}
|
}
|
||||||
@@ -1565,16 +1710,17 @@ http_OpenHttpGet( IN const char *url_str,
|
|||||||
* UPNP_E_SOCKET_ERROR
|
* UPNP_E_SOCKET_ERROR
|
||||||
* UPNP_E_BAD_RESPONSE
|
* UPNP_E_BAD_RESPONSE
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
int
|
int http_OpenHttpGetProxy(
|
||||||
http_OpenHttpGetProxy( IN const char *url_str,
|
IN const char *url_str,
|
||||||
IN const char *proxy_str,
|
IN const char *proxy_str,
|
||||||
IN OUT void **Handle,
|
IN OUT void **Handle,
|
||||||
IN OUT char **contentType,
|
IN OUT char **contentType,
|
||||||
OUT int *contentLength,
|
OUT int *contentLength,
|
||||||
OUT int *httpStatus,
|
OUT int *httpStatus,
|
||||||
IN int timeout )
|
IN int timeout)
|
||||||
{
|
{
|
||||||
int ret_code;
|
int ret_code;
|
||||||
|
int sockaddr_len;
|
||||||
int http_error_code;
|
int http_error_code;
|
||||||
memptr ctype;
|
memptr ctype;
|
||||||
int tcp_connection;
|
int tcp_connection;
|
||||||
@@ -1585,111 +1731,95 @@ http_OpenHttpGetProxy( IN const char *url_str,
|
|||||||
uri_type *peer;
|
uri_type *peer;
|
||||||
parse_status_t status;
|
parse_status_t status;
|
||||||
|
|
||||||
if( ( !url_str ) || ( !Handle ) || ( !contentType )
|
if (!url_str || !Handle || !contentType || !httpStatus ) {
|
||||||
|| ( !httpStatus ) ) {
|
|
||||||
return UPNP_E_INVALID_PARAM;
|
return UPNP_E_INVALID_PARAM;
|
||||||
}
|
}
|
||||||
|
|
||||||
( *httpStatus ) = 0;
|
*httpStatus = 0;
|
||||||
( *Handle ) = handle;
|
*Handle = handle;
|
||||||
( *contentType ) = NULL;
|
*contentType = NULL;
|
||||||
( *contentLength ) = 0;
|
*contentLength = 0;
|
||||||
|
|
||||||
if( ( ret_code =
|
ret_code = MakeGetMessage(url_str, proxy_str, &request, &url);
|
||||||
MakeGetMessage( url_str, proxy_str, &request, &url ) ) != UPNP_E_SUCCESS ) {
|
if (ret_code != UPNP_E_SUCCESS) {
|
||||||
return ret_code;
|
return ret_code;
|
||||||
}
|
}
|
||||||
if( proxy_str ) {
|
if (proxy_str) {
|
||||||
ret_code = http_FixStrUrl( ( char * )proxy_str, strlen( proxy_str ), &proxy );
|
ret_code = http_FixStrUrl((char *)proxy_str, strlen(proxy_str), &proxy);
|
||||||
peer = &proxy;
|
peer = &proxy;
|
||||||
} else {
|
} else {
|
||||||
peer = &url;
|
peer = &url;
|
||||||
}
|
}
|
||||||
|
handle = (http_get_handle_t *)malloc(sizeof(http_get_handle_t));
|
||||||
handle = ( http_get_handle_t * ) malloc( sizeof( http_get_handle_t ) );
|
if (!handle) {
|
||||||
|
|
||||||
if( handle == NULL ) {
|
|
||||||
return UPNP_E_OUTOF_MEMORY;
|
return UPNP_E_OUTOF_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
handle->entity_offset = 0;
|
|
||||||
handle->cancel = 0;
|
handle->cancel = 0;
|
||||||
parser_response_init( &handle->response, HTTPMETHOD_GET );
|
parser_response_init(&handle->response, HTTPMETHOD_GET);
|
||||||
|
tcp_connection = socket(peer->hostport.IPaddress.ss_family, SOCK_STREAM, 0);
|
||||||
tcp_connection = socket( peer->hostport.IPaddress.ss_family, SOCK_STREAM, 0 );
|
if (tcp_connection == -1) {
|
||||||
if( tcp_connection == -1 ) {
|
|
||||||
ret_code = UPNP_E_SOCKET_ERROR;
|
ret_code = UPNP_E_SOCKET_ERROR;
|
||||||
goto errorHandler;
|
goto errorHandler;
|
||||||
}
|
}
|
||||||
|
if (sock_init(&handle->sock_info, tcp_connection) != UPNP_E_SUCCESS) {
|
||||||
if( sock_init( &handle->sock_info, tcp_connection ) != UPNP_E_SUCCESS )
|
sock_destroy(&handle->sock_info, SD_BOTH);
|
||||||
{
|
|
||||||
sock_destroy( &handle->sock_info, SD_BOTH );
|
|
||||||
ret_code = UPNP_E_SOCKET_ERROR;
|
ret_code = UPNP_E_SOCKET_ERROR;
|
||||||
goto errorHandler;
|
goto errorHandler;
|
||||||
}
|
}
|
||||||
|
sockaddr_len = peer->hostport.IPaddress.ss_family == AF_INET6 ?
|
||||||
ret_code = connect( handle->sock_info.socket,
|
sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in);
|
||||||
( struct sockaddr * )&peer->hostport.IPaddress,
|
ret_code = private_connect(handle->sock_info.socket,
|
||||||
sizeof( struct sockaddr_storage ) );
|
(struct sockaddr *)&(peer->hostport.IPaddress), sockaddr_len);
|
||||||
|
if (ret_code == -1) {
|
||||||
if( ret_code == -1 ) {
|
sock_destroy(&handle->sock_info, SD_BOTH);
|
||||||
sock_destroy( &handle->sock_info, SD_BOTH );
|
|
||||||
ret_code = UPNP_E_SOCKET_CONNECT;
|
ret_code = UPNP_E_SOCKET_CONNECT;
|
||||||
goto errorHandler;
|
goto errorHandler;
|
||||||
}
|
}
|
||||||
// send request
|
/* send request */
|
||||||
ret_code = http_SendMessage( &handle->sock_info, &timeout, "b",
|
ret_code = http_SendMessage(&handle->sock_info, &timeout, "b",
|
||||||
request.buf, request.length );
|
request.buf, request.length);
|
||||||
if( ret_code != 0 ) {
|
if (ret_code) {
|
||||||
sock_destroy( &handle->sock_info, SD_BOTH );
|
sock_destroy(&handle->sock_info, SD_BOTH);
|
||||||
goto errorHandler;
|
goto errorHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
status =
|
status = ReadResponseLineAndHeaders(&handle->sock_info,
|
||||||
ReadResponseLineAndHeaders( &handle->sock_info, &handle->response,
|
&handle->response, &timeout, &http_error_code);
|
||||||
&timeout, &http_error_code );
|
if (status != PARSE_OK) {
|
||||||
|
ret_code = UPNP_E_BAD_RESPONSE;
|
||||||
if( status != PARSE_OK ) {
|
goto errorHandler;
|
||||||
|
}
|
||||||
|
status = parser_get_entity_read_method(&handle->response);
|
||||||
|
if (status != PARSE_CONTINUE_1 && status != PARSE_SUCCESS) {
|
||||||
ret_code = UPNP_E_BAD_RESPONSE;
|
ret_code = UPNP_E_BAD_RESPONSE;
|
||||||
goto errorHandler;
|
goto errorHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = parser_get_entity_read_method( &handle->response );
|
*httpStatus = handle->response.msg.status_code;
|
||||||
|
|
||||||
if( ( status != PARSE_CONTINUE_1 ) && ( status != PARSE_SUCCESS ) ) {
|
|
||||||
ret_code = UPNP_E_BAD_RESPONSE;
|
|
||||||
goto errorHandler;
|
|
||||||
}
|
|
||||||
|
|
||||||
( *httpStatus ) = handle->response.msg.status_code;
|
|
||||||
ret_code = UPNP_E_SUCCESS;
|
ret_code = UPNP_E_SUCCESS;
|
||||||
|
|
||||||
if( httpmsg_find_hdr( &handle->response.msg, HDR_CONTENT_TYPE, &ctype )
|
if (!httpmsg_find_hdr(&handle->response.msg, HDR_CONTENT_TYPE, &ctype)) {
|
||||||
== NULL ) {
|
/* no content-type */
|
||||||
*contentType = NULL; // no content-type
|
*contentType = NULL;
|
||||||
} else {
|
} else {
|
||||||
*contentType = ctype.buf;
|
*contentType = ctype.buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( handle->response.position == POS_COMPLETE ) {
|
if (handle->response.position == POS_COMPLETE) {
|
||||||
( *contentLength ) = 0;
|
*contentLength = 0;
|
||||||
} else if( handle->response.ent_position == ENTREAD_USING_CHUNKED ) {
|
} else if (handle->response.ent_position == ENTREAD_USING_CHUNKED) {
|
||||||
( *contentLength ) = UPNP_USING_CHUNKED;
|
*contentLength = UPNP_USING_CHUNKED;
|
||||||
} else if( handle->response.ent_position == ENTREAD_USING_CLEN ) {
|
} else if (handle->response.ent_position == ENTREAD_USING_CLEN) {
|
||||||
( *contentLength ) = handle->response.content_length;
|
*contentLength = handle->response.content_length;
|
||||||
} else if( handle->response.ent_position == ENTREAD_UNTIL_CLOSE ) {
|
} else if (handle->response.ent_position == ENTREAD_UNTIL_CLOSE) {
|
||||||
( *contentLength ) = UPNP_UNTIL_CLOSE;
|
*contentLength = UPNP_UNTIL_CLOSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
errorHandler:
|
errorHandler:
|
||||||
|
*Handle = handle;
|
||||||
( *Handle ) = handle;
|
membuffer_destroy(&request);
|
||||||
|
if (ret_code != UPNP_E_SUCCESS) {
|
||||||
membuffer_destroy( &request );
|
httpmsg_destroy(&handle->response.msg);
|
||||||
|
|
||||||
if( ret_code != UPNP_E_SUCCESS ) {
|
|
||||||
httpmsg_destroy( &handle->response.msg );
|
|
||||||
}
|
}
|
||||||
return ret_code;
|
return ret_code;
|
||||||
}
|
}
|
||||||
@@ -1778,6 +1908,9 @@ http_SendStatusResponse( IN SOCKINFO * info,
|
|||||||
* 'G': arg = range information // add range header
|
* 'G': arg = range information // add range header
|
||||||
* 'h': arg = off_t number // appends off_t number
|
* 'h': arg = off_t number // appends off_t number
|
||||||
* 'K': (no args) // add chunky header
|
* '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
|
* 'N': arg1 = off_t content_length // content-length header
|
||||||
* 'q': arg1 = http_method_t // request start line and HOST header
|
* 'q': arg1 = http_method_t // request start line and HOST header
|
||||||
* arg2 = (uri_type *)
|
* arg2 = (uri_type *)
|
||||||
@@ -1921,6 +2054,20 @@ http_MakeMessage( INOUT membuffer * buf,
|
|||||||
if( membuffer_append( buf, tempbuf, strlen( tempbuf ) ) != 0 ) {
|
if( membuffer_append( buf, tempbuf, strlen( tempbuf ) ) != 0 ) {
|
||||||
goto error_handler;
|
goto error_handler;
|
||||||
}
|
}
|
||||||
|
} else if ( c == 'L' ) {
|
||||||
|
// Add CONTENT-LANGUAGE header only if WEB_SERVER_CONTENT_LANGUAGE
|
||||||
|
// is not empty and if Accept-Language header is not empty
|
||||||
|
struct SendInstruction *RespInstr;
|
||||||
|
RespInstr = (struct SendInstruction *)
|
||||||
|
va_arg( argp, struct SendInstruction *);
|
||||||
|
assert( RespInstr );
|
||||||
|
if (strcmp( RespInstr->AcceptLanguageHeader, "" ) &&
|
||||||
|
strcmp( WEB_SERVER_CONTENT_LANGUAGE, "" ) && http_MakeMessage(
|
||||||
|
buf, http_major_version, http_minor_version,
|
||||||
|
"ssc",
|
||||||
|
"CONTENT-LANGUAGE: ", WEB_SERVER_CONTENT_LANGUAGE ) != 0 ) {
|
||||||
|
goto error_handler;
|
||||||
|
}
|
||||||
} else if( c == 'C' ) {
|
} else if( c == 'C' ) {
|
||||||
if( ( http_major_version > 1 ) ||
|
if( ( http_major_version > 1 ) ||
|
||||||
( http_major_version == 1 && http_minor_version == 1 )
|
( http_major_version == 1 && http_minor_version == 1 )
|
||||||
@@ -2201,147 +2348,125 @@ MakeGetMessageEx( const char *url_str,
|
|||||||
* UPNP_E_SOCKET_ERROR
|
* UPNP_E_SOCKET_ERROR
|
||||||
* UPNP_E_BAD_RESPONSE
|
* UPNP_E_BAD_RESPONSE
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
int
|
int http_OpenHttpGetEx(
|
||||||
http_OpenHttpGetEx( IN const char *url_str,
|
IN const char *url_str,
|
||||||
IN OUT void **Handle,
|
IN OUT void **Handle,
|
||||||
IN OUT char **contentType,
|
IN OUT char **contentType,
|
||||||
OUT int *contentLength,
|
OUT int *contentLength,
|
||||||
OUT int *httpStatus,
|
OUT int *httpStatus,
|
||||||
IN int lowRange,
|
IN int lowRange,
|
||||||
IN int highRange,
|
IN int highRange,
|
||||||
IN int timeout )
|
IN int timeout)
|
||||||
{
|
{
|
||||||
int http_error_code;
|
int http_error_code;
|
||||||
memptr ctype;
|
memptr ctype;
|
||||||
int tcp_connection;
|
int tcp_connection;
|
||||||
|
int sockaddr_len;
|
||||||
membuffer request;
|
membuffer request;
|
||||||
http_get_handle_t *handle = NULL;
|
http_get_handle_t *handle = NULL;
|
||||||
uri_type url;
|
uri_type url;
|
||||||
parse_status_t status;
|
parse_status_t status;
|
||||||
int errCode = UPNP_E_SUCCESS;
|
int errCode = UPNP_E_SUCCESS;
|
||||||
|
/* char rangeBuf[SIZE_RANGE_BUFFER]; */
|
||||||
// char rangeBuf[SIZE_RANGE_BUFFER];
|
|
||||||
struct SendInstruction rangeBuf;
|
struct SendInstruction rangeBuf;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
// Checking Input parameters
|
/* Checking Input parameters */
|
||||||
if( ( !url_str ) || ( !Handle ) ||
|
if (!url_str || !Handle || !contentType || !httpStatus ) {
|
||||||
( !contentType ) || ( !httpStatus ) ) {
|
|
||||||
errCode = UPNP_E_INVALID_PARAM;
|
errCode = UPNP_E_INVALID_PARAM;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// Initialize output parameters
|
|
||||||
( *httpStatus ) = 0;
|
|
||||||
( *Handle ) = handle;
|
|
||||||
( *contentType ) = NULL;
|
|
||||||
( *contentLength ) = 0;
|
|
||||||
|
|
||||||
if( lowRange > highRange ) {
|
/* Initialize output parameters */
|
||||||
|
*httpStatus = 0;
|
||||||
|
*Handle = handle;
|
||||||
|
*contentType = NULL;
|
||||||
|
*contentLength = 0;
|
||||||
|
|
||||||
|
if (lowRange > highRange) {
|
||||||
errCode = UPNP_E_INTERNAL_ERROR;
|
errCode = UPNP_E_INTERNAL_ERROR;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
memset(&rangeBuf, 0, sizeof(rangeBuf));
|
||||||
memset( &rangeBuf, 0, sizeof( rangeBuf ) );
|
sprintf(rangeBuf.RangeHeader,
|
||||||
sprintf( rangeBuf.RangeHeader, "Range: bytes=%d-%d\r\n",
|
"Range: bytes=%d-%d\r\n", lowRange, highRange);
|
||||||
lowRange, highRange );
|
membuffer_init(&request);
|
||||||
|
errCode = MakeGetMessageEx(url_str, &request, &url, &rangeBuf);
|
||||||
membuffer_init( &request );
|
if (errCode != UPNP_E_SUCCESS) {
|
||||||
|
|
||||||
if( ( errCode = MakeGetMessageEx( url_str,
|
|
||||||
&request, &url, &rangeBuf ) )
|
|
||||||
!= UPNP_E_SUCCESS ) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
handle = (http_get_handle_t *)malloc(sizeof(http_get_handle_t));
|
||||||
handle =
|
if (!handle) {
|
||||||
( http_get_handle_t * ) malloc( sizeof( http_get_handle_t ) );
|
|
||||||
if( handle == NULL ) {
|
|
||||||
errCode = UPNP_E_OUTOF_MEMORY;
|
errCode = UPNP_E_OUTOF_MEMORY;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
memset(handle, 0, sizeof(*handle));
|
||||||
memset( handle, 0, sizeof( *handle ) );
|
parser_response_init(&handle->response, HTTPMETHOD_GET);
|
||||||
|
tcp_connection = socket(url.hostport.IPaddress.ss_family, SOCK_STREAM, 0);
|
||||||
handle->entity_offset = 0;
|
if (tcp_connection == -1) {
|
||||||
parser_response_init( &handle->response, HTTPMETHOD_GET );
|
|
||||||
|
|
||||||
tcp_connection = socket( url.hostport.IPaddress.ss_family, SOCK_STREAM, 0 );
|
|
||||||
if( tcp_connection == -1 ) {
|
|
||||||
errCode = UPNP_E_SOCKET_ERROR;
|
errCode = UPNP_E_SOCKET_ERROR;
|
||||||
free( handle );
|
free(handle);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (sock_init(&handle->sock_info, tcp_connection) != UPNP_E_SUCCESS) {
|
||||||
if( sock_init( &handle->sock_info, tcp_connection ) !=
|
sock_destroy(&handle->sock_info, SD_BOTH);
|
||||||
UPNP_E_SUCCESS ) {
|
|
||||||
sock_destroy( &handle->sock_info, SD_BOTH );
|
|
||||||
errCode = UPNP_E_SOCKET_ERROR;
|
errCode = UPNP_E_SOCKET_ERROR;
|
||||||
free( handle );
|
free(handle);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
sockaddr_len = url.hostport.IPaddress.ss_family == AF_INET6 ?
|
||||||
errCode = connect( handle->sock_info.socket,
|
sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in);
|
||||||
( struct sockaddr * )&url.hostport.IPaddress,
|
errCode = private_connect(handle->sock_info.socket,
|
||||||
sizeof( struct sockaddr_storage ) );
|
(struct sockaddr *)&(url.hostport.IPaddress), sockaddr_len);
|
||||||
if( errCode == -1 ) {
|
if (errCode == -1) {
|
||||||
sock_destroy( &handle->sock_info, SD_BOTH );
|
sock_destroy(&handle->sock_info, SD_BOTH);
|
||||||
errCode = UPNP_E_SOCKET_CONNECT;
|
errCode = UPNP_E_SOCKET_CONNECT;
|
||||||
free( handle );
|
free(handle);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// send request
|
/* send request */
|
||||||
errCode = http_SendMessage( &handle->sock_info,
|
errCode = http_SendMessage(&handle->sock_info, &timeout,
|
||||||
&timeout,
|
"b", request.buf, request.length);
|
||||||
"b", request.buf, request.length );
|
if (errCode != UPNP_E_SUCCESS) {
|
||||||
|
sock_destroy(&handle->sock_info, SD_BOTH);
|
||||||
if( errCode != UPNP_E_SUCCESS ) {
|
free(handle);
|
||||||
sock_destroy( &handle->sock_info, SD_BOTH );
|
|
||||||
free( handle );
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
status = ReadResponseLineAndHeaders(&handle->sock_info,
|
||||||
status = ReadResponseLineAndHeaders( &handle->sock_info,
|
&handle->response, &timeout, &http_error_code);
|
||||||
&handle->response,
|
if (status != PARSE_OK) {
|
||||||
&timeout, &http_error_code );
|
|
||||||
|
|
||||||
if( status != PARSE_OK ) {
|
|
||||||
errCode = UPNP_E_BAD_RESPONSE;
|
errCode = UPNP_E_BAD_RESPONSE;
|
||||||
free( handle );
|
free(handle);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
status = parser_get_entity_read_method(&handle->response);
|
||||||
status = parser_get_entity_read_method( &handle->response );
|
if (status != PARSE_CONTINUE_1 && status != PARSE_SUCCESS) {
|
||||||
if( ( status != PARSE_CONTINUE_1 ) && ( status != PARSE_SUCCESS ) ) {
|
|
||||||
errCode = UPNP_E_BAD_RESPONSE;
|
errCode = UPNP_E_BAD_RESPONSE;
|
||||||
free( handle );
|
free(handle);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
*httpStatus = handle->response.msg.status_code;
|
||||||
( *httpStatus ) = handle->response.msg.status_code;
|
|
||||||
errCode = UPNP_E_SUCCESS;
|
errCode = UPNP_E_SUCCESS;
|
||||||
|
|
||||||
if( httpmsg_find_hdr( &handle->response.msg,
|
if (!httpmsg_find_hdr(&handle->response.msg, HDR_CONTENT_TYPE, &ctype)) {
|
||||||
HDR_CONTENT_TYPE, &ctype ) == NULL ) {
|
/* no content-type */
|
||||||
*contentType = NULL; // no content-type
|
*contentType = NULL;
|
||||||
} else {
|
} else {
|
||||||
*contentType = ctype.buf;
|
*contentType = ctype.buf;
|
||||||
}
|
}
|
||||||
|
if (handle->response.position == POS_COMPLETE) {
|
||||||
if( handle->response.position == POS_COMPLETE ) {
|
*contentLength = 0;
|
||||||
( *contentLength ) = 0;
|
} else if(handle->response.ent_position == ENTREAD_USING_CHUNKED) {
|
||||||
} else if( handle->response.ent_position == ENTREAD_USING_CHUNKED ) {
|
*contentLength = UPNP_USING_CHUNKED;
|
||||||
( *contentLength ) = UPNP_USING_CHUNKED;
|
} else if(handle->response.ent_position == ENTREAD_USING_CLEN) {
|
||||||
} else if( handle->response.ent_position == ENTREAD_USING_CLEN ) {
|
*contentLength = handle->response.content_length;
|
||||||
( *contentLength ) = handle->response.content_length;
|
} else if(handle->response.ent_position == ENTREAD_UNTIL_CLOSE) {
|
||||||
} else if( handle->response.ent_position == ENTREAD_UNTIL_CLOSE ) {
|
*contentLength = UPNP_UNTIL_CLOSE;
|
||||||
( *contentLength ) = UPNP_UNTIL_CLOSE;
|
|
||||||
}
|
}
|
||||||
|
*Handle = handle;
|
||||||
|
} while (0);
|
||||||
|
|
||||||
( *Handle ) = handle;
|
membuffer_destroy(&request);
|
||||||
|
|
||||||
} while( 0 );
|
|
||||||
|
|
||||||
membuffer_destroy( &request );
|
|
||||||
|
|
||||||
return errCode;
|
return errCode;
|
||||||
}
|
}
|
||||||
|
@@ -307,9 +307,10 @@ search_extension( IN const char *extension,
|
|||||||
* 0 - On Sucess
|
* 0 - On Sucess
|
||||||
* UPNP_E_OUTOF_MEMORY - on memory allocation failures
|
* UPNP_E_OUTOF_MEMORY - on memory allocation failures
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
UPNP_INLINE int
|
static UPNP_INLINE int
|
||||||
get_content_type( IN const char *filename,
|
get_content_type(
|
||||||
OUT DOMString * content_type )
|
IN const char *filename,
|
||||||
|
OUT DOMString *content_type)
|
||||||
{
|
{
|
||||||
const char *extension;
|
const char *extension;
|
||||||
const char *type;
|
const char *type;
|
||||||
@@ -1123,6 +1124,12 @@ CheckOtherHTTPHeaders( IN http_message_t * Req,
|
|||||||
return RetCode;
|
return RetCode;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case HDR_ACCEPT_LANGUAGE:
|
||||||
|
{
|
||||||
|
memcpy( RespInstr->AcceptLanguageHeader, TmpBuf,
|
||||||
|
sizeof( RespInstr->AcceptLanguageHeader ) - 1 );
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
/*
|
/*
|
||||||
TODO
|
TODO
|
||||||
@@ -1137,7 +1144,6 @@ CheckOtherHTTPHeaders( IN http_message_t * Req,
|
|||||||
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_ACCEPT_LANGUAGE://return 1;
|
|
||||||
case HDR_USER_AGENT: break;//return 1;
|
case HDR_USER_AGENT: break;//return 1;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -1397,10 +1403,11 @@ process_request( IN http_message_t * req,
|
|||||||
// Transfer-Encoding: chunked
|
// Transfer-Encoding: chunked
|
||||||
if (http_MakeMessage(
|
if (http_MakeMessage(
|
||||||
headers, resp_major, resp_minor,
|
headers, resp_major, resp_minor,
|
||||||
"R" "T" "GKD" "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
|
||||||
"LAST-MODIFIED: ",
|
"LAST-MODIFIED: ",
|
||||||
&finfo.last_modified,
|
&finfo.last_modified,
|
||||||
X_USER_AGENT,
|
X_USER_AGENT,
|
||||||
@@ -1412,11 +1419,12 @@ process_request( IN http_message_t * req,
|
|||||||
// Transfer-Encoding: chunked
|
// Transfer-Encoding: chunked
|
||||||
if (http_MakeMessage(
|
if (http_MakeMessage(
|
||||||
headers, resp_major, resp_minor,
|
headers, resp_major, resp_minor,
|
||||||
"R" "N" "T" "GD" "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
|
||||||
"LAST-MODIFIED: ",
|
"LAST-MODIFIED: ",
|
||||||
&finfo.last_modified,
|
&finfo.last_modified,
|
||||||
X_USER_AGENT,
|
X_USER_AGENT,
|
||||||
@@ -1429,9 +1437,10 @@ process_request( IN http_message_t * req,
|
|||||||
// Transfer-Encoding: chunked
|
// Transfer-Encoding: chunked
|
||||||
if (http_MakeMessage(
|
if (http_MakeMessage(
|
||||||
headers, resp_major, resp_minor,
|
headers, resp_major, resp_minor,
|
||||||
"RK" "TD" "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
|
||||||
"LAST-MODIFIED: ",
|
"LAST-MODIFIED: ",
|
||||||
&finfo.last_modified,
|
&finfo.last_modified,
|
||||||
X_USER_AGENT,
|
X_USER_AGENT,
|
||||||
@@ -1445,10 +1454,11 @@ process_request( IN http_message_t * req,
|
|||||||
// Transfer-Encoding: chunked
|
// Transfer-Encoding: chunked
|
||||||
if (http_MakeMessage(
|
if (http_MakeMessage(
|
||||||
headers, resp_major, resp_minor,
|
headers, resp_major, resp_minor,
|
||||||
"R" "N" "TD" "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
|
||||||
"LAST-MODIFIED: ",
|
"LAST-MODIFIED: ",
|
||||||
&finfo.last_modified,
|
&finfo.last_modified,
|
||||||
X_USER_AGENT,
|
X_USER_AGENT,
|
||||||
@@ -1460,9 +1470,10 @@ process_request( IN http_message_t * req,
|
|||||||
// Transfer-Encoding: chunked
|
// Transfer-Encoding: chunked
|
||||||
if (http_MakeMessage(
|
if (http_MakeMessage(
|
||||||
headers, resp_major, resp_minor,
|
headers, resp_major, resp_minor,
|
||||||
"R" "TD" "s" "tcS" "b" "Xc" "sCc",
|
"R" "TLD" "s" "tcS" "b" "Xc" "sCc",
|
||||||
HTTP_OK, // status code
|
HTTP_OK, // status code
|
||||||
finfo.content_type, // content type
|
finfo.content_type, // content type
|
||||||
|
RespInstr, // language info
|
||||||
"LAST-MODIFIED: ",
|
"LAST-MODIFIED: ",
|
||||||
&finfo.last_modified,
|
&finfo.last_modified,
|
||||||
X_USER_AGENT,
|
X_USER_AGENT,
|
||||||
@@ -1696,6 +1707,8 @@ web_server_callback( IN http_parser_t * parser,
|
|||||||
RespInstr.IsChunkActive = 0;
|
RespInstr.IsChunkActive = 0;
|
||||||
RespInstr.IsRangeActive = 0;
|
RespInstr.IsRangeActive = 0;
|
||||||
RespInstr.IsTrailers = 0;
|
RespInstr.IsTrailers = 0;
|
||||||
|
memset( RespInstr.AcceptLanguageHeader, 0,
|
||||||
|
sizeof( RespInstr.AcceptLanguageHeader ) );
|
||||||
// init
|
// init
|
||||||
membuffer_init( &headers );
|
membuffer_init( &headers );
|
||||||
membuffer_init( &filename );
|
membuffer_init( &filename );
|
||||||
@@ -1750,7 +1763,7 @@ web_server_callback( IN http_parser_t * parser,
|
|||||||
|
|
||||||
http_MakeMessage(
|
http_MakeMessage(
|
||||||
&headers, 1, 1,
|
&headers, 1, 1,
|
||||||
"RTDSXcCc",
|
"RTLSXcCc",
|
||||||
ret,
|
ret,
|
||||||
"text/html",
|
"text/html",
|
||||||
X_USER_AGENT );
|
X_USER_AGENT );
|
||||||
|
@@ -913,8 +913,10 @@ getServiceList( IXML_Node * node,
|
|||||||
( *end ) = current;
|
( *end ) = current;
|
||||||
|
|
||||||
return head;
|
return head;
|
||||||
} else
|
} else {
|
||||||
|
( *end ) = NULL;
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -960,6 +962,7 @@ getAllServiceList( IXML_Node * node,
|
|||||||
if( head ) {
|
if( head ) {
|
||||||
end->next =
|
end->next =
|
||||||
getServiceList( currentDevice, &next_end, URLBase );
|
getServiceList( currentDevice, &next_end, URLBase );
|
||||||
|
if ( next_end )
|
||||||
end = next_end;
|
end = next_end;
|
||||||
} else
|
} else
|
||||||
head = getServiceList( currentDevice, &end, URLBase );
|
head = getServiceList( currentDevice, &end, URLBase );
|
||||||
|
@@ -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.
|
||||||
//
|
*
|
||||||
///////////////////////////////////////////////////////////////////////////
|
**************************************************************************/
|
||||||
|
|
||||||
#ifndef INTERNAL_CONFIG_H
|
#ifndef INTERNAL_CONFIG_H
|
||||||
#define INTERNAL_CONFIG_H
|
#define INTERNAL_CONFIG_H
|
||||||
@@ -36,52 +36,66 @@
|
|||||||
#include "autoconfig.h"
|
#include "autoconfig.h"
|
||||||
|
|
||||||
|
|
||||||
/** @name Compile time configuration options
|
/*!
|
||||||
|
* \name Compile time configuration options
|
||||||
|
*
|
||||||
* The Linux SDK for UPnP Devices contains some compile-time parameters
|
* The Linux SDK for UPnP Devices contains some compile-time parameters
|
||||||
* that effect the behavior of the SDK. All configuration options are
|
* that effect the behavior of the SDK. All configuration options are
|
||||||
* located in {\tt src/inc/config.h}.
|
* located in {\tt src/inc/config.h}.
|
||||||
|
*
|
||||||
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//@{
|
|
||||||
|
|
||||||
/** @name THREAD_IDLE_TIME
|
/*!
|
||||||
|
* \name THREAD_IDLE_TIME
|
||||||
|
*
|
||||||
* The {\tt THREAD_IDLE_TIME} constant determines when a thread will be
|
* The {\tt THREAD_IDLE_TIME} constant determines when a thread will be
|
||||||
* removed from the thread pool and returned to the operating system. When
|
* removed from the thread pool and returned to the operating system. When
|
||||||
* a thread in the thread pool has been idle for this number of milliseconds
|
* a thread in the thread pool has been idle for this number of milliseconds
|
||||||
* the thread will be released from the thread pool. The default value is
|
* the thread will be released from the thread pool. The default value is
|
||||||
* 5000 milliseconds (5 seconds).
|
* 5000 milliseconds (5 seconds).
|
||||||
|
*
|
||||||
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//@{
|
|
||||||
#define THREAD_IDLE_TIME 5000
|
#define THREAD_IDLE_TIME 5000
|
||||||
//@}
|
/* @} */
|
||||||
|
|
||||||
/** @name JOBS_PER_THREAD
|
|
||||||
|
/*!
|
||||||
|
* \name JOBS_PER_THREAD
|
||||||
|
*
|
||||||
* The {\tt JOBS_PER_THREAD} constant determines when a new thread will be
|
* The {\tt JOBS_PER_THREAD} constant determines when a new thread will be
|
||||||
* allocated to the thread pool inside the SDK. The thread pool will
|
* allocated to the thread pool inside the SDK. The thread pool will
|
||||||
* try and maintain this jobs/thread ratio. When the jobs/thread ratio
|
* try and maintain this jobs/thread ratio. When the jobs/thread ratio
|
||||||
* becomes greater than this, then a new thread (up to the max) will be
|
* becomes greater than this, then a new thread (up to the max) will be
|
||||||
* allocated to the thread pool. The default ratio is 10 jobs/thread.
|
* allocated to the thread pool. The default ratio is 10 jobs/thread.
|
||||||
|
*
|
||||||
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//@{
|
|
||||||
#define JOBS_PER_THREAD 10
|
#define JOBS_PER_THREAD 10
|
||||||
//@}
|
/* @} */
|
||||||
|
|
||||||
/** @name MIN_THREADS
|
|
||||||
|
/*!
|
||||||
|
* \name MIN_THREADS
|
||||||
|
*
|
||||||
* The {\tt MIN_THREADS} constant defines the minimum number of threads the
|
* The {\tt MIN_THREADS} constant defines the minimum number of threads the
|
||||||
* thread pool inside the SDK will create. The thread pool will
|
* thread pool inside the SDK will create. The thread pool will
|
||||||
* always have this number of threads. These threads are used
|
* always have this number of threads. These threads are used
|
||||||
* for both callbacks into applications built on top of the SDK and also
|
* for both callbacks into applications built on top of the SDK and also
|
||||||
* for making connections to other control points and devices. This number
|
* for making connections to other control points and devices. This number
|
||||||
* includes persistent threads. The default value is two threads.
|
* includes persistent threads. The default value is two threads.
|
||||||
|
*
|
||||||
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//@{
|
|
||||||
#define MIN_THREADS 2
|
#define MIN_THREADS 2
|
||||||
//@}
|
/* @} */
|
||||||
|
|
||||||
/** @name MAX_THREADS
|
|
||||||
|
/*!
|
||||||
|
* \name MAX_THREADS
|
||||||
|
*
|
||||||
* The {\tt MAX_THREADS} constant defines the maximum number of threads the
|
* The {\tt MAX_THREADS} constant defines the maximum number of threads the
|
||||||
* thread pool inside the SDK will create. These threads are used
|
* thread pool inside the SDK will create. These threads are used
|
||||||
* for both callbacks into applications built on top of the library and also
|
* for both callbacks into applications built on top of the library and also
|
||||||
@@ -90,60 +104,111 @@
|
|||||||
* necessary for correct operation. This value can be increased for greater
|
* necessary for correct operation. This value can be increased for greater
|
||||||
* performance in operation at the expense of greater memory overhead. The
|
* performance in operation at the expense of greater memory overhead. The
|
||||||
* default value is 12.
|
* default value is 12.
|
||||||
|
*
|
||||||
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//@{
|
|
||||||
#define MAX_THREADS 12
|
#define MAX_THREADS 12
|
||||||
//@}
|
/* @} */
|
||||||
|
|
||||||
/** @name MAX_JOBS_TOTAL
|
|
||||||
|
/*!
|
||||||
|
* \name THREAD_STACK_SIZE
|
||||||
|
*
|
||||||
|
* The {\tt THREAD_STACK_SIZE} constant defines the minimum stack size (in
|
||||||
|
* bytes) allocated for the stack of each thread the thread pool inside the
|
||||||
|
* SDK will create. These threads are used for both callbacks into
|
||||||
|
* applications built on top of the library and also for making connections
|
||||||
|
* to other control points and devices. This value will not be used if it
|
||||||
|
* is lower than ITHREAD_STACK_MIN or greater than a system-imposed limit.
|
||||||
|
* This value can be used to lower memory overhead in embedded systems.
|
||||||
|
* The default value is 0 (so it is not used by default).
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define THREAD_STACK_SIZE 0
|
||||||
|
/* @} */
|
||||||
|
|
||||||
|
|
||||||
|
/*! \name MAX_JOBS_TOTAL
|
||||||
|
*
|
||||||
* The {\tt MAX_JOBS_TOTAL} constant determines the maximum number of jobs
|
* The {\tt MAX_JOBS_TOTAL} constant determines the maximum number of jobs
|
||||||
* that can be queued. If this limit is reached further jobs will be thrown
|
* that can be queued. If this limit is reached further jobs will be thrown
|
||||||
* to avoid memory exhaustion. The default value 100.
|
* to avoid memory exhaustion. The default value 100.
|
||||||
* (Added by Axis.)
|
* (Added by Axis.)
|
||||||
|
*
|
||||||
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//@{
|
|
||||||
#define MAX_JOBS_TOTAL 100
|
#define MAX_JOBS_TOTAL 100
|
||||||
//@}
|
/* @} */
|
||||||
|
|
||||||
/** @name DEFAULT_SOAP_CONTENT_LENGTH
|
|
||||||
|
/*!
|
||||||
|
* \name DEFAULT_SOAP_CONTENT_LENGTH
|
||||||
|
*
|
||||||
* SOAP messages will read at most {\tt DEFAULT_SOAP_CONTENT_LENGTH} bytes.
|
* SOAP messages will read at most {\tt DEFAULT_SOAP_CONTENT_LENGTH} bytes.
|
||||||
* This prevents devices that have a misbehaving web server to send
|
* This prevents devices that have a misbehaving web server to send
|
||||||
* a large amount of data to the control point causing it to crash.
|
* a large amount of data to the control point causing it to crash.
|
||||||
* This can be adjusted dynamically with {\tt UpnpSetMaxContentLength}.
|
* This can be adjusted dynamically with {\tt UpnpSetMaxContentLength}.
|
||||||
|
*
|
||||||
|
* @{
|
||||||
*/
|
*/
|
||||||
//@{
|
|
||||||
#define DEFAULT_SOAP_CONTENT_LENGTH 16000
|
#define DEFAULT_SOAP_CONTENT_LENGTH 16000
|
||||||
//@}
|
/* @} */
|
||||||
|
|
||||||
/** @name NUM_SSDP_COPY
|
|
||||||
|
/*!
|
||||||
|
* \name NUM_SSDP_COPY
|
||||||
|
*
|
||||||
* This configuration parameter determines how many copies of each SSDP
|
* This configuration parameter determines how many copies of each SSDP
|
||||||
* advertisement and search packets will be sent. By default it will send two
|
* advertisement and search packets will be sent. By default it will send two
|
||||||
* copies of every packet.
|
* copies of every packet.
|
||||||
|
*
|
||||||
|
* @{
|
||||||
*/
|
*/
|
||||||
//@{
|
|
||||||
#define NUM_SSDP_COPY 2
|
#define NUM_SSDP_COPY 2
|
||||||
//@}
|
/* @} */
|
||||||
|
|
||||||
/** @name SSDP_PAUSE
|
|
||||||
|
/*!
|
||||||
|
* \name SSDP_PAUSE
|
||||||
|
*
|
||||||
* This configuration parameter determines the pause between identical SSDP
|
* This configuration parameter determines the pause between identical SSDP
|
||||||
* advertisement and search packets. The pause is measured in milliseconds
|
* advertisement and search packets. The pause is measured in milliseconds
|
||||||
* and defaults to 100.
|
* and defaults to 100.
|
||||||
|
*
|
||||||
|
* @{
|
||||||
*/
|
*/
|
||||||
//@{
|
|
||||||
#define SSDP_PAUSE 100
|
#define SSDP_PAUSE 100
|
||||||
//@}
|
/* @} */
|
||||||
|
|
||||||
/** @name WEB_SERVER_BUF_SIZE
|
/*!
|
||||||
|
* \name WEB_SERVER_BUF_SIZE
|
||||||
|
*
|
||||||
* This configuration parameter sets the maximum buffer size for the
|
* This configuration parameter sets the maximum buffer size for the
|
||||||
* webserver. The default value is 1MB.
|
* webserver. The default value is 1MB.
|
||||||
|
*
|
||||||
|
* @{
|
||||||
*/
|
*/
|
||||||
//@{
|
|
||||||
#define WEB_SERVER_BUF_SIZE (1024*1024)
|
#define WEB_SERVER_BUF_SIZE (1024*1024)
|
||||||
//@}
|
/* @} */
|
||||||
|
|
||||||
/** @name AUTO_RENEW_TIME
|
/*!
|
||||||
|
* \name WEB_SERVER_CONTENT_LANGUAGE
|
||||||
|
*
|
||||||
|
* This configuration parameter sets the value of the Content-Language
|
||||||
|
* header for the webserver. Thanks to this parameter, the use can advertize
|
||||||
|
* the language used by the device in the description (friendlyName) and
|
||||||
|
* presentation steps of UPnP. The default value is empty string so no
|
||||||
|
* Content-Language header is added.
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define WEB_SERVER_CONTENT_LANGUAGE ""
|
||||||
|
/* @} */
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \name AUTO_RENEW_TIME
|
||||||
|
*
|
||||||
* The {\tt AUTO_RENEW_TIME} is the time, in seconds, before a subscription
|
* The {\tt AUTO_RENEW_TIME} is the time, in seconds, before a subscription
|
||||||
* expires that the SDK automatically resubscribes. The default
|
* expires that the SDK automatically resubscribes. The default
|
||||||
* value is 10 seconds. Setting this value too low can result in the
|
* value is 10 seconds. Setting this value too low can result in the
|
||||||
@@ -151,71 +216,87 @@
|
|||||||
* subscription to timeout. In order to avoid continually resubscribing
|
* subscription to timeout. In order to avoid continually resubscribing
|
||||||
* the minimum subscription time is five seconds more than the auto renew
|
* the minimum subscription time is five seconds more than the auto renew
|
||||||
* time.
|
* time.
|
||||||
|
*
|
||||||
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//@{
|
|
||||||
#define AUTO_RENEW_TIME 10
|
#define AUTO_RENEW_TIME 10
|
||||||
//@}
|
/* @} */
|
||||||
|
|
||||||
/** @name CP_MINIMUM_SUBSCRIPTION_TIME
|
/*!
|
||||||
|
* \name CP_MINIMUM_SUBSCRIPTION_TIME
|
||||||
|
*
|
||||||
* The {\tt CP_MINIMUM_SUBSCRIPTION_TIME} is the minimum subscription time
|
* The {\tt CP_MINIMUM_SUBSCRIPTION_TIME} is the minimum subscription time
|
||||||
* allowed for a control point using the SDK. Subscribing for less than
|
* allowed for a control point using the SDK. Subscribing for less than
|
||||||
* this time automatically results in a subscription for this amount. The
|
* this time automatically results in a subscription for this amount. The
|
||||||
* default value is 5 seconds more than the {\tt AUTO_RENEW_TIME}, or 15
|
* default value is 5 seconds more than the {\tt AUTO_RENEW_TIME}, or 15
|
||||||
* seconds.
|
* seconds.
|
||||||
|
*
|
||||||
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//@{
|
|
||||||
#define CP_MINIMUM_SUBSCRIPTION_TIME (AUTO_RENEW_TIME + 5)
|
#define CP_MINIMUM_SUBSCRIPTION_TIME (AUTO_RENEW_TIME + 5)
|
||||||
//@}
|
/* @} */
|
||||||
|
|
||||||
/** @name MAX_SEARCH_TIME
|
|
||||||
|
/*!
|
||||||
|
* \name MAX_SEARCH_TIME
|
||||||
|
*
|
||||||
* The {\tt MAX_SEARCH_TIME} is the maximum time
|
* The {\tt MAX_SEARCH_TIME} is the maximum time
|
||||||
* allowed for an SSDP search by a control point. Searching for greater than
|
* allowed for an SSDP search by a control point. Searching for greater than
|
||||||
* this time automatically results in a search for this amount. The default
|
* this time automatically results in a search for this amount. The default
|
||||||
* value is 80 seconds.
|
* value is 80 seconds.
|
||||||
|
*
|
||||||
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//@{
|
|
||||||
#define MAX_SEARCH_TIME 80
|
#define MAX_SEARCH_TIME 80
|
||||||
//@}
|
/* @} */
|
||||||
|
|
||||||
/** @name MIN_SEARCH_TIME
|
|
||||||
|
/*!
|
||||||
|
* \name MIN_SEARCH_TIME
|
||||||
|
*
|
||||||
* The {\tt MIN_SEARCH_TIME} is the minimumm time
|
* The {\tt MIN_SEARCH_TIME} is the minimumm time
|
||||||
* allowed for an SSDP search by a control point. Searching for less than
|
* allowed for an SSDP search by a control point. Searching for less than
|
||||||
* this time automatically results in a search for this amount. The default
|
* this time automatically results in a search for this amount. The default
|
||||||
* value is 2 seconds.
|
* value is 2 seconds.
|
||||||
|
*
|
||||||
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//@{
|
|
||||||
#define MIN_SEARCH_TIME 2
|
#define MIN_SEARCH_TIME 2
|
||||||
//@}
|
/* @} */
|
||||||
|
|
||||||
|
|
||||||
/** @name AUTO_ADVERTISEMENT_TIME
|
/*!
|
||||||
|
* \name AUTO_ADVERTISEMENT_TIME
|
||||||
|
*
|
||||||
* The {\tt AUTO_ADVERTISEMENT_TIME} is the time, in seconds, before an
|
* The {\tt AUTO_ADVERTISEMENT_TIME} is the time, in seconds, before an
|
||||||
* device advertisements expires before a renewed advertisement is sent.
|
* device advertisements expires before a renewed advertisement is sent.
|
||||||
* The default time is 30 seconds.
|
* The default time is 30 seconds.
|
||||||
|
*
|
||||||
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//@{
|
|
||||||
#define AUTO_ADVERTISEMENT_TIME 30
|
#define AUTO_ADVERTISEMENT_TIME 30
|
||||||
//@}
|
/* @} */
|
||||||
|
|
||||||
/** @name SSDP_PACKET_DISTRIBUTE
|
|
||||||
|
/*!
|
||||||
|
* \name SSDP_PACKET_DISTRIBUTE
|
||||||
|
*
|
||||||
* The {\tt SSDP_PACKET_DISTRIBUTE} enables the SSDP packets to be sent
|
* The {\tt SSDP_PACKET_DISTRIBUTE} enables the SSDP packets to be sent
|
||||||
* at an interval equal to half of the expiration time of SSDP packets
|
* at an interval equal to half of the expiration time of SSDP packets
|
||||||
* minus the AUTO_ADVERTISEMENT_TIME. This is used to increase
|
* minus the AUTO_ADVERTISEMENT_TIME. This is used to increase
|
||||||
* the probability of SSDP packets reaching to control points.
|
* the probability of SSDP packets reaching to control points.
|
||||||
* It is recommended that this flag be turned on for embedded wireless
|
* It is recommended that this flag be turned on for embedded wireless
|
||||||
* devices.
|
* devices.
|
||||||
|
*
|
||||||
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//@{
|
|
||||||
#define SSDP_PACKET_DISTRIBUTE 1
|
#define SSDP_PACKET_DISTRIBUTE 1
|
||||||
//@}
|
/* @} */
|
||||||
|
|
||||||
/** @name Module Exclusion
|
|
||||||
|
/*!
|
||||||
|
* \name Module Exclusion
|
||||||
|
*
|
||||||
* Depending on the requirements, the user can selectively discard any of
|
* Depending on the requirements, the user can selectively discard any of
|
||||||
* the major modules like SOAP, GENA, SSDP or the Internal web server. By
|
* the major modules like SOAP, GENA, SSDP or the Internal web server. By
|
||||||
* default everything is included inside the SDK. By setting any of
|
* default everything is included inside the SDK. By setting any of
|
||||||
@@ -231,9 +312,8 @@
|
|||||||
* \item {\tt EXCLUDE_JNI[0,1]}
|
* \item {\tt EXCLUDE_JNI[0,1]}
|
||||||
* \end{itemize}
|
* \end{itemize}
|
||||||
*
|
*
|
||||||
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//@{
|
|
||||||
#define EXCLUDE_SSDP 0
|
#define EXCLUDE_SSDP 0
|
||||||
#define EXCLUDE_SOAP 0
|
#define EXCLUDE_SOAP 0
|
||||||
#define EXCLUDE_GENA 0
|
#define EXCLUDE_GENA 0
|
||||||
@@ -245,24 +325,28 @@
|
|||||||
#else
|
#else
|
||||||
# define EXCLUDE_JNI 1
|
# define EXCLUDE_JNI 1
|
||||||
#endif
|
#endif
|
||||||
//@}
|
/* @} */
|
||||||
|
|
||||||
|
|
||||||
/** @name DEBUG_TARGET
|
/*!
|
||||||
|
* \name DEBUG_TARGET
|
||||||
|
*
|
||||||
* The user has the option to redirect the library output debug messages
|
* The user has the option to redirect the library output debug messages
|
||||||
* to either the screen or to a log file. All the output messages with
|
* to either the screen or to a log file. All the output messages with
|
||||||
* debug level 0 will go to {\tt upnp.err} and messages with debug level
|
* debug level 0 will go to {\tt upnp.err} and messages with debug level
|
||||||
* greater than zero will be redirected to {\tt upnp.out}.
|
* greater than zero will be redirected to {\tt upnp.out}.
|
||||||
|
*
|
||||||
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//@{
|
|
||||||
#define DEBUG_TARGET 1
|
#define DEBUG_TARGET 1
|
||||||
//@}
|
/* @} */
|
||||||
|
|
||||||
|
|
||||||
/** @name Other debugging features
|
/*!
|
||||||
The UPnP SDK contains other features to aid in debugging:
|
* \name Other debugging features
|
||||||
see <upnp/inc/upnpdebug.h>
|
*
|
||||||
|
* The UPnP SDK contains other features to aid in debugging:
|
||||||
|
* see <upnp/inc/upnpdebug.h>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define DEBUG_ALL 1
|
#define DEBUG_ALL 1
|
||||||
@@ -275,36 +359,44 @@
|
|||||||
#define DEBUG_HTTP 0
|
#define DEBUG_HTTP 0
|
||||||
#define DEBUG_API 0
|
#define DEBUG_API 0
|
||||||
|
|
||||||
//@} // Compile time configuration options
|
|
||||||
|
/*
|
||||||
|
* @} Compile time configuration options
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
* Do not change, Internal purpose only!!!
|
* Do not change, Internal purpose only!!!
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
//@{
|
/*!
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set additional defines based on requested configuration
|
* Set additional defines based on requested configuration
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// configure --enable-client
|
|
||||||
|
/* configure --enable-client */
|
||||||
#if UPNP_HAVE_CLIENT
|
#if UPNP_HAVE_CLIENT
|
||||||
# define INCLUDE_CLIENT_APIS 1
|
# define INCLUDE_CLIENT_APIS 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// configure --enable-device
|
|
||||||
|
/* configure --enable-device */
|
||||||
#if UPNP_HAVE_DEVICE
|
#if UPNP_HAVE_DEVICE
|
||||||
# define INCLUDE_DEVICE_APIS 1
|
# define INCLUDE_DEVICE_APIS 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// configure --enable-webserver --enable-device
|
|
||||||
|
/* configure --enable-webserver --enable-device */
|
||||||
#if UPNP_HAVE_WEBSERVER
|
#if UPNP_HAVE_WEBSERVER
|
||||||
# define INTERNAL_WEB_SERVER 1
|
# define INTERNAL_WEB_SERVER 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#undef EXCLUDE_WEB_SERVER
|
#undef EXCLUDE_WEB_SERVER
|
||||||
#undef EXCLUDE_MINISERVER
|
#undef EXCLUDE_MINISERVER
|
||||||
#ifdef INTERNAL_WEB_SERVER
|
#ifdef INTERNAL_WEB_SERVER
|
||||||
@@ -315,6 +407,7 @@
|
|||||||
# define EXCLUDE_MINISERVER 1
|
# define EXCLUDE_MINISERVER 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#if EXCLUDE_GENA == 1 && EXCLUDE_SOAP == 1 && EXCLUDE_WEB_SERVER == 1
|
#if EXCLUDE_GENA == 1 && EXCLUDE_SOAP == 1 && EXCLUDE_WEB_SERVER == 1
|
||||||
# undef EXCLUDE_MINISERVER
|
# undef EXCLUDE_MINISERVER
|
||||||
# define EXCLUDE_MINISERVER 1
|
# define EXCLUDE_MINISERVER 1
|
||||||
@@ -323,6 +416,7 @@
|
|||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#if EXCLUDE_GENA == 0 || EXCLUDE_SOAP == 0 || EXCLUDE_WEB_SERVER == 0
|
#if EXCLUDE_GENA == 0 || EXCLUDE_SOAP == 0 || EXCLUDE_WEB_SERVER == 0
|
||||||
# undef EXCLUDE_MINISERVER
|
# undef EXCLUDE_MINISERVER
|
||||||
# define EXCLUDE_MINISERVER 0
|
# define EXCLUDE_MINISERVER 0
|
||||||
@@ -332,13 +426,9 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
#ifdef INCLUDE_CLIENT_APIS
|
#endif /* INTERNAL_CONFIG_H */
|
||||||
# define CLIENTONLY(x) x
|
|
||||||
#else
|
|
||||||
# define CLIENTONLY(x)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//@}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
@@ -194,6 +194,7 @@ typedef struct // http_message_t
|
|||||||
// private fields
|
// private fields
|
||||||
membuffer msg; // entire raw message
|
membuffer msg; // entire raw message
|
||||||
char *urlbuf; // storage for url string
|
char *urlbuf; // storage for url string
|
||||||
|
size_t entity_offset;
|
||||||
} http_message_t;
|
} http_message_t;
|
||||||
|
|
||||||
typedef struct // http_parser_t
|
typedef struct // http_parser_t
|
||||||
|
@@ -6,6 +6,9 @@
|
|||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
|
|
||||||
|
#ifdef IPV6_
|
||||||
|
#define INET_IPV6
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "unixutil.h"
|
#include "unixutil.h"
|
||||||
|
|
||||||
|
@@ -55,9 +55,11 @@ typedef struct MServerSockArray {
|
|||||||
SOCKET miniServerPort4;
|
SOCKET miniServerPort4;
|
||||||
SOCKET miniServerPort6;
|
SOCKET miniServerPort6;
|
||||||
|
|
||||||
|
#ifdef INCLUDE_CLIENT_APIS
|
||||||
/* socket for sending search requests and receiving search replies */
|
/* socket for sending search requests and receiving search replies */
|
||||||
CLIENTONLY(SOCKET ssdpReqSock4;)
|
SOCKET ssdpReqSock4;
|
||||||
CLIENTONLY(SOCKET ssdpReqSock6;)
|
SOCKET ssdpReqSock6;
|
||||||
|
#endif /* INCLUDE_CLIENT_APIS */
|
||||||
} MiniServerSockArray;
|
} MiniServerSockArray;
|
||||||
|
|
||||||
|
|
||||||
|
@@ -1,133 +1,135 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////
|
/**************************************************************************
|
||||||
//
|
*
|
||||||
// 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 SOAPLIB_H
|
#ifndef SOAPLIB_H
|
||||||
#define SOAPLIB_H
|
#define SOAPLIB_H
|
||||||
|
|
||||||
|
|
||||||
// SOAP module API to be called in Upnp-Dk API
|
/* SOAP module API to be called in Upnp-Dk API */
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Function : soap_device_callback
|
* Function: soap_device_callback
|
||||||
*
|
*
|
||||||
* Parameters :
|
* Parameters:
|
||||||
* IN http_parser_t *parser : Parsed request received by the device
|
* IN http_parser_t *parser: Parsed request received by the device
|
||||||
* IN http_message_t* request : HTTP request
|
* IN http_message_t* request: HTTP request
|
||||||
* INOUT SOCKINFO *info : socket info
|
* INOUT SOCKINFO *info: socket info
|
||||||
*
|
*
|
||||||
* Description : This is a callback called by minisever after receiving
|
* Description: This is a callback called by minisever after receiving
|
||||||
* the request from the control point. This function will start
|
* the request from the control point. This function will start
|
||||||
* processing the request. It calls handle_invoke_action to handle the
|
* processing the request. It calls handle_invoke_action to handle the
|
||||||
* SOAP action
|
* SOAP action
|
||||||
*
|
*
|
||||||
* Return : void
|
* Return: void
|
||||||
*
|
*
|
||||||
* Note :
|
* Note:
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
void soap_device_callback(
|
void soap_device_callback(
|
||||||
IN http_parser_t *parser,
|
IN http_parser_t *parser,
|
||||||
IN http_message_t* request,
|
IN http_message_t* request,
|
||||||
INOUT SOCKINFO *info );
|
INOUT SOCKINFO *info);
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Function : SoapSendAction
|
* Function: SoapSendAction
|
||||||
*
|
*
|
||||||
* Parameters :
|
* Parameters:
|
||||||
* IN char* action_url : device contrl URL
|
* IN char* action_url: device contrl URL
|
||||||
* IN char *service_type : device service type
|
* IN char *service_type: device service type
|
||||||
* IN IXML_Document *action_node : SOAP action node
|
* IN IXML_Document *action_node: SOAP action node
|
||||||
* OUT IXML_Document **response_node : SOAP response node
|
* OUT IXML_Document **response_node: SOAP response node
|
||||||
*
|
*
|
||||||
* Description : This function is called by UPnP API to send the SOAP
|
* Description: This function is called by UPnP API to send the SOAP
|
||||||
* action request and waits till it gets the response from the device
|
* action request and waits till it gets the response from the device
|
||||||
* pass the response to the API layer
|
* pass the response to the API layer
|
||||||
*
|
*
|
||||||
* Return : int
|
* Return: int
|
||||||
* returns UPNP_E_SUCCESS if successful else returns appropriate error
|
* returns UPNP_E_SUCCESS if successful else returns appropriate error
|
||||||
* Note :
|
* Note:
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
int SoapSendAction(
|
int SoapSendAction(
|
||||||
IN char* action_url,
|
IN char* action_url,
|
||||||
IN char *service_type,
|
IN char *service_type,
|
||||||
IN IXML_Document *action_node,
|
IN IXML_Document *action_node,
|
||||||
OUT IXML_Document **response_node );
|
OUT IXML_Document **response_node);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Function : SoapSendActionEx
|
* Function: SoapSendActionEx
|
||||||
*
|
*
|
||||||
* Parameters :
|
* Parameters:
|
||||||
* IN char* action_url : device contrl URL
|
* IN char* action_url: device contrl URL
|
||||||
* IN char *service_type : device service type
|
* IN char *service_type: device service type
|
||||||
IN IXML_Document *Header: Soap header
|
* IN IXML_Document *Header: Soap header
|
||||||
* IN IXML_Document *action_node : SOAP action node ( SOAP body)
|
* IN IXML_Document *action_node: SOAP action node (SOAP body)
|
||||||
* OUT IXML_Document **response_node : SOAP response node
|
* OUT IXML_Document **response_node: SOAP response node
|
||||||
*
|
*
|
||||||
* Description : This function is called by UPnP API to send the SOAP
|
* Description: This function is called by UPnP API to send the SOAP
|
||||||
* action request and waits till it gets the response from the device
|
* action request and waits till it gets the response from the device
|
||||||
* pass the response to the API layer. This action is similar to the
|
* pass the response to the API layer. This action is similar to the
|
||||||
* the SoapSendAction with only difference that it allows users to
|
* the SoapSendAction with only difference that it allows users to
|
||||||
* pass the SOAP header along the SOAP body ( soap action request)
|
* pass the SOAP header along the SOAP body ( soap action request)
|
||||||
*
|
*
|
||||||
* Return : int
|
* Return: int
|
||||||
* returns UPNP_E_SUCCESS if successful else returns appropriate error
|
* returns UPNP_E_SUCCESS if successful else returns appropriate error
|
||||||
* Note :
|
* Note:
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
int SoapSendActionEx(
|
int SoapSendActionEx(
|
||||||
IN char * ActionURL,
|
IN char * ActionURL,
|
||||||
IN char *ServiceType,
|
IN char *ServiceType,
|
||||||
IN IXML_Document *Header,
|
IN IXML_Document *Header,
|
||||||
IN IXML_Document *ActNode ,
|
IN IXML_Document *ActNode,
|
||||||
OUT IXML_Document **RespNode) ;
|
OUT IXML_Document **RespNode);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Function : SoapGetServiceVarStatus
|
* Function: SoapGetServiceVarStatus
|
||||||
*
|
*
|
||||||
* Parameters :
|
* Parameters:
|
||||||
* IN char * action_url : Address to send this variable
|
* IN char * action_url: Address to send this variable query message.
|
||||||
* query message.
|
* IN char *var_name: Name of the variable.
|
||||||
* IN char *var_name : Name of the variable.
|
* OUT char **var_value: Output value.
|
||||||
* OUT char **var_value : Output value.
|
*
|
||||||
*
|
* Description: This function creates a status variable query message
|
||||||
* Description : This function creates a status variable query message
|
* send it to the specified URL. It also collect the response.
|
||||||
* send it to the specified URL. It also collect the response.
|
*
|
||||||
*
|
* Return: int
|
||||||
* Return : int
|
*
|
||||||
*
|
* Note:
|
||||||
* Note :
|
****************************************************************************/
|
||||||
****************************************************************************/
|
|
||||||
int SoapGetServiceVarStatus(
|
int SoapGetServiceVarStatus(
|
||||||
IN char * ActionURL,
|
IN char * ActionURL,
|
||||||
IN DOMString VarName,
|
IN DOMString VarName,
|
||||||
OUT DOMString *StVar) ;
|
OUT DOMString *StVar);
|
||||||
|
|
||||||
extern const char* ContentTypeHeader;
|
extern const char* ContentTypeHeader;
|
||||||
|
|
||||||
#endif //SOAPLIB_H
|
#endif /* SOAPLIB_H */
|
||||||
|
|
||||||
|
@@ -47,15 +47,17 @@
|
|||||||
|
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
#else
|
#else /* WIN32 */
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
#ifndef __APPLE__
|
||||||
#include <netinet/in_systm.h>
|
#include <netinet/in_systm.h>
|
||||||
#include <netinet/ip.h>
|
#include <netinet/ip.h>
|
||||||
#include <netinet/ip_icmp.h>
|
#include <netinet/ip_icmp.h>
|
||||||
|
#endif /* __APPLE__ */
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#endif
|
#endif /* WIN32 */
|
||||||
|
|
||||||
|
|
||||||
/* Enumeration to define all different types of ssdp searches */
|
/* Enumeration to define all different types of ssdp searches */
|
||||||
@@ -183,9 +185,12 @@ typedef struct
|
|||||||
|
|
||||||
/* globals */
|
/* globals */
|
||||||
|
|
||||||
CLIENTONLY(extern SOCKET gSsdpReqSocket4;);
|
#ifdef INCLUDE_CLIENT_APIS
|
||||||
CLIENTONLY(extern SOCKET gSsdpReqSocket6;);
|
extern SOCKET gSsdpReqSocket4;
|
||||||
|
#ifdef UPNP_ENABLE_IPV6
|
||||||
|
extern SOCKET gSsdpReqSocket6;
|
||||||
|
#endif /* UPNP_ENABLE_IPV6 */
|
||||||
|
#endif /* INCLUDE_CLIENT_APIS */
|
||||||
typedef int (*ParserFun)(char *, Event *);
|
typedef int (*ParserFun)(char *, Event *);
|
||||||
|
|
||||||
|
|
||||||
|
@@ -48,6 +48,7 @@ struct SendInstruction
|
|||||||
int IsRangeActive;
|
int IsRangeActive;
|
||||||
int IsTrailers;
|
int IsTrailers;
|
||||||
char RangeHeader[200];
|
char RangeHeader[200];
|
||||||
|
char AcceptLanguageHeader[200];
|
||||||
off_t RangeOffset;
|
off_t RangeOffset;
|
||||||
off_t ReadSendSize; // Read from local source and send on the network.
|
off_t ReadSendSize; // Read from local source and send on the network.
|
||||||
long RecvWriteSize; // Recv from the network and write into local file.
|
long RecvWriteSize; // Recv from the network and write into local file.
|
||||||
|
@@ -1,135 +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 SOAPLIB_H
|
|
||||||
#define SOAPLIB_H
|
|
||||||
|
|
||||||
|
|
||||||
//SOAP module API to be called in Upnp-Dk API
|
|
||||||
/****************************************************************************
|
|
||||||
* Function : soap_device_callback
|
|
||||||
*
|
|
||||||
* Parameters :
|
|
||||||
* 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(
|
|
||||||
IN http_parser_t *parser,
|
|
||||||
IN http_message_t* request,
|
|
||||||
INOUT SOCKINFO *info );
|
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Function : SoapSendAction
|
|
||||||
*
|
|
||||||
* Parameters :
|
|
||||||
* IN char* action_url : device contrl URL
|
|
||||||
* IN char *service_type : device service type
|
|
||||||
* IN IXML_Document *action_node : SOAP action node
|
|
||||||
* OUT IXML_Document **response_node : SOAP response node
|
|
||||||
*
|
|
||||||
* Description : This function is called by UPnP API to send the SOAP
|
|
||||||
* action request and waits till it gets the response from the device
|
|
||||||
* pass the response to the API layer
|
|
||||||
*
|
|
||||||
* Return : int
|
|
||||||
* returns UPNP_E_SUCCESS if successful else returns appropriate error
|
|
||||||
* Note :
|
|
||||||
****************************************************************************/
|
|
||||||
int SoapSendAction(
|
|
||||||
IN char* action_url,
|
|
||||||
IN char *service_type,
|
|
||||||
IN IXML_Document *action_node,
|
|
||||||
OUT IXML_Document **response_node );
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Function : SoapSendActionEx
|
|
||||||
*
|
|
||||||
* Parameters :
|
|
||||||
* IN char* action_url : device contrl URL
|
|
||||||
* IN char *service_type : device service type
|
|
||||||
IN IXML_Document *Header: Soap header
|
|
||||||
* IN IXML_Document *action_node : SOAP action node ( SOAP body)
|
|
||||||
* OUT IXML_Document **response_node : SOAP response node
|
|
||||||
*
|
|
||||||
* Description : This function is called by UPnP API to send the SOAP
|
|
||||||
* action request and waits till it gets the response from the device
|
|
||||||
* pass the response to the API layer. This action is similar to the
|
|
||||||
* the SoapSendAction with only difference that it allows users to
|
|
||||||
* pass the SOAP header along the SOAP body ( soap action request)
|
|
||||||
*
|
|
||||||
* Return : int
|
|
||||||
* returns UPNP_E_SUCCESS if successful else returns appropriate error
|
|
||||||
* Note :
|
|
||||||
****************************************************************************/
|
|
||||||
int SoapSendActionEx(
|
|
||||||
IN char * ActionURL,
|
|
||||||
IN char *ServiceType,
|
|
||||||
IN IXML_Document *Header,
|
|
||||||
IN IXML_Document *ActNode ,
|
|
||||||
OUT IXML_Document **RespNode) ;
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Function : SoapGetServiceVarStatus
|
|
||||||
*
|
|
||||||
* Parameters :
|
|
||||||
* IN char * action_url : Address to send this variable
|
|
||||||
* query message.
|
|
||||||
* IN char *var_name : Name of the variable.
|
|
||||||
* OUT char **var_value : Output value.
|
|
||||||
*
|
|
||||||
* Description : This function creates a status variable query message
|
|
||||||
* send it to the specified URL. It also collect the response.
|
|
||||||
*
|
|
||||||
* Return : int
|
|
||||||
*
|
|
||||||
* Note :
|
|
||||||
****************************************************************************/
|
|
||||||
int SoapGetServiceVarStatus(
|
|
||||||
IN char * ActionURL,
|
|
||||||
IN DOMString VarName,
|
|
||||||
OUT DOMString *StVar) ;
|
|
||||||
|
|
||||||
|
|
||||||
// extern form the HTTP parser.
|
|
||||||
extern const char* ContentTypeHeader;
|
|
||||||
|
|
||||||
#endif //SOAPLIB_H
|
|
@@ -510,7 +510,6 @@ int SearchByTarget(
|
|||||||
IN void *Cookie)
|
IN void *Cookie)
|
||||||
{
|
{
|
||||||
char errorBuffer[ERROR_BUFFER_LEN];
|
char errorBuffer[ERROR_BUFFER_LEN];
|
||||||
int socklen = sizeof( struct sockaddr_storage );
|
|
||||||
int *id = NULL;
|
int *id = NULL;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
char ReqBufv4[BUFSIZE];
|
char ReqBufv4[BUFSIZE];
|
||||||
@@ -595,12 +594,14 @@ int SearchByTarget(
|
|||||||
FD_SET(gSsdpReqSocket4, &wrSet);
|
FD_SET(gSsdpReqSocket4, &wrSet);
|
||||||
max_fd = max(max_fd, gSsdpReqSocket4);
|
max_fd = max(max_fd, gSsdpReqSocket4);
|
||||||
}
|
}
|
||||||
|
#ifdef UPNP_ENABLE_IPV6
|
||||||
if (gSsdpReqSocket6 != INVALID_SOCKET) {
|
if (gSsdpReqSocket6 != INVALID_SOCKET) {
|
||||||
setsockopt(gSsdpReqSocket6, IPPROTO_IPV6, IPV6_MULTICAST_IF,
|
setsockopt(gSsdpReqSocket6, IPPROTO_IPV6, IPV6_MULTICAST_IF,
|
||||||
(char *)&gIF_INDEX, sizeof (gIF_INDEX));
|
(char *)&gIF_INDEX, sizeof (gIF_INDEX));
|
||||||
FD_SET(gSsdpReqSocket6, &wrSet);
|
FD_SET(gSsdpReqSocket6, &wrSet);
|
||||||
max_fd = max(max_fd, gSsdpReqSocket6);
|
max_fd = max(max_fd, gSsdpReqSocket6);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
ret = select(max_fd + 1, NULL, &wrSet, NULL, NULL);
|
ret = select(max_fd + 1, NULL, &wrSet, NULL, NULL);
|
||||||
if (ret == -1) {
|
if (ret == -1) {
|
||||||
@@ -610,11 +611,13 @@ int SearchByTarget(
|
|||||||
errorBuffer);
|
errorBuffer);
|
||||||
shutdown(gSsdpReqSocket4, SD_BOTH);
|
shutdown(gSsdpReqSocket4, SD_BOTH);
|
||||||
UpnpCloseSocket(gSsdpReqSocket4);
|
UpnpCloseSocket(gSsdpReqSocket4);
|
||||||
|
#ifdef UPNP_ENABLE_IPV6
|
||||||
shutdown(gSsdpReqSocket6, SD_BOTH);
|
shutdown(gSsdpReqSocket6, SD_BOTH);
|
||||||
UpnpCloseSocket(gSsdpReqSocket6);
|
UpnpCloseSocket(gSsdpReqSocket6);
|
||||||
|
#endif
|
||||||
return UPNP_E_INTERNAL_ERROR;
|
return UPNP_E_INTERNAL_ERROR;
|
||||||
}
|
}
|
||||||
|
#ifdef UPNP_ENABLE_IPV6
|
||||||
if (gSsdpReqSocket6 != INVALID_SOCKET &&
|
if (gSsdpReqSocket6 != INVALID_SOCKET &&
|
||||||
FD_ISSET(gSsdpReqSocket6, &wrSet)) {
|
FD_ISSET(gSsdpReqSocket6, &wrSet)) {
|
||||||
int NumCopy = 0;
|
int NumCopy = 0;
|
||||||
@@ -622,28 +625,38 @@ int SearchByTarget(
|
|||||||
while (NumCopy < NUM_SSDP_COPY) {
|
while (NumCopy < NUM_SSDP_COPY) {
|
||||||
sendto(gSsdpReqSocket6,
|
sendto(gSsdpReqSocket6,
|
||||||
ReqBufv6UlaGua, strlen(ReqBufv6UlaGua), 0,
|
ReqBufv6UlaGua, strlen(ReqBufv6UlaGua), 0,
|
||||||
(struct sockaddr *)&__ss_v6, socklen);
|
(struct sockaddr *)&__ss_v6,
|
||||||
|
sizeof(struct sockaddr_in));
|
||||||
NumCopy++;
|
NumCopy++;
|
||||||
imillisleep(SSDP_PAUSE);
|
imillisleep(SSDP_PAUSE);
|
||||||
}
|
}
|
||||||
NumCopy = 0;
|
NumCopy = 0;
|
||||||
inet_pton(AF_INET6, SSDP_IPV6_LINKLOCAL, &destAddr6->sin6_addr);
|
inet_pton(AF_INET6, SSDP_IPV6_LINKLOCAL, &destAddr6->sin6_addr);
|
||||||
while (NumCopy < NUM_SSDP_COPY) {
|
while (NumCopy < NUM_SSDP_COPY) {
|
||||||
|
UpnpPrintf( UPNP_INFO, SSDP, __FILE__, __LINE__,
|
||||||
|
">>> SSDP SEND M-SEARCH >>>\n%s\n",
|
||||||
|
ReqBufv6);
|
||||||
sendto(gSsdpReqSocket6,
|
sendto(gSsdpReqSocket6,
|
||||||
ReqBufv6, strlen(ReqBufv6), 0,
|
ReqBufv6, strlen(ReqBufv6), 0,
|
||||||
(struct sockaddr *)&__ss_v6, socklen);
|
(struct sockaddr *)&__ss_v6,
|
||||||
|
sizeof(struct sockaddr_in6));
|
||||||
NumCopy++;
|
NumCopy++;
|
||||||
imillisleep(SSDP_PAUSE);
|
imillisleep(SSDP_PAUSE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif //IPv6
|
||||||
|
|
||||||
if (gSsdpReqSocket4 != INVALID_SOCKET &&
|
if (gSsdpReqSocket4 != INVALID_SOCKET &&
|
||||||
FD_ISSET(gSsdpReqSocket4, &wrSet)) {
|
FD_ISSET(gSsdpReqSocket4, &wrSet)) {
|
||||||
int NumCopy = 0;
|
int NumCopy = 0;
|
||||||
|
|
||||||
while (NumCopy < NUM_SSDP_COPY) {
|
while (NumCopy < NUM_SSDP_COPY) {
|
||||||
|
UpnpPrintf( UPNP_INFO, SSDP, __FILE__, __LINE__,
|
||||||
|
">>> SSDP SEND M-SEARCH >>>\n%s\n",
|
||||||
|
ReqBufv4);
|
||||||
sendto(gSsdpReqSocket4,
|
sendto(gSsdpReqSocket4,
|
||||||
ReqBufv4, strlen(ReqBufv4), 0,
|
ReqBufv4, strlen(ReqBufv4), 0,
|
||||||
(struct sockaddr *)&__ss_v4, socklen);
|
(struct sockaddr *)&__ss_v4,
|
||||||
|
sizeof(struct sockaddr_in));
|
||||||
NumCopy++;
|
NumCopy++;
|
||||||
imillisleep(SSDP_PAUSE);
|
imillisleep(SSDP_PAUSE);
|
||||||
}
|
}
|
||||||
|
@@ -229,6 +229,7 @@ NewRequestHandler( IN struct sockaddr *DestAddr,
|
|||||||
int ttl = 4; // a/c to UPNP Spec
|
int ttl = 4; // a/c to UPNP Spec
|
||||||
int hops = 1;
|
int hops = 1;
|
||||||
char buf_ntop[64];
|
char buf_ntop[64];
|
||||||
|
int ret = UPNP_E_SUCCESS;
|
||||||
|
|
||||||
ReplySock = socket( DestAddr->sa_family, SOCK_DGRAM, 0 );
|
ReplySock = socket( DestAddr->sa_family, SOCK_DGRAM, 0 );
|
||||||
if ( ReplySock == -1 ) {
|
if ( ReplySock == -1 ) {
|
||||||
@@ -247,6 +248,7 @@ NewRequestHandler( IN struct sockaddr *DestAddr,
|
|||||||
(char *)&replyAddr, sizeof (replyAddr) );
|
(char *)&replyAddr, sizeof (replyAddr) );
|
||||||
setsockopt( ReplySock, IPPROTO_IP, IP_MULTICAST_TTL,
|
setsockopt( ReplySock, IPPROTO_IP, IP_MULTICAST_TTL,
|
||||||
(char *)&ttl, sizeof (int) );
|
(char *)&ttl, sizeof (int) );
|
||||||
|
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));
|
||||||
@@ -257,6 +259,8 @@ NewRequestHandler( IN struct sockaddr *DestAddr,
|
|||||||
} else {
|
} else {
|
||||||
UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__,
|
UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__,
|
||||||
"Invalid destination address specified." );
|
"Invalid destination address specified." );
|
||||||
|
ret = UPNP_E_NETWORK_ERROR;
|
||||||
|
goto end_NewRequestHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
for( Index = 0; Index < NumPacket; Index++ ) {
|
for( Index = 0; Index < NumPacket; Index++ ) {
|
||||||
@@ -280,15 +284,27 @@ NewRequestHandler( IN struct sockaddr *DestAddr,
|
|||||||
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) {
|
||||||
|
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
|
||||||
|
UpnpPrintf( UPNP_INFO, SSDP, __FILE__, __LINE__,
|
||||||
|
"SSDP_LIB: New Request Handler:"
|
||||||
|
"Error in socket(): %s\n", errorBuffer );
|
||||||
|
ret = UPNP_E_SOCKET_WRITE;
|
||||||
|
goto end_NewRequestHandler;
|
||||||
|
}
|
||||||
|
|
||||||
imillisleep( SSDP_PAUSE );
|
imillisleep( SSDP_PAUSE );
|
||||||
|
|
||||||
++NumCopy;
|
++NumCopy;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
end_NewRequestHandler:
|
||||||
shutdown( ReplySock, SD_BOTH );
|
shutdown( ReplySock, SD_BOTH );
|
||||||
UpnpCloseSocket( ReplySock );
|
UpnpCloseSocket( ReplySock );
|
||||||
|
|
||||||
return UPNP_E_SUCCESS;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -405,6 +421,7 @@ 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;
|
||||||
if (msg_type == MSGTYPE_ADVERTISEMENT) {
|
if (msg_type == MSGTYPE_ADVERTISEMENT) {
|
||||||
nts = "ssdp:alive";
|
nts = "ssdp:alive";
|
||||||
} else {
|
} else {
|
||||||
@@ -413,7 +430,6 @@ void CreateServicePacket(
|
|||||||
}
|
}
|
||||||
/* 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. */
|
||||||
char *host = NULL;
|
|
||||||
if (AddressFamily == AF_INET) {
|
if (AddressFamily == AF_INET) {
|
||||||
host = SSDP_IP;
|
host = SSDP_IP;
|
||||||
} else {
|
} else {
|
||||||
|
@@ -50,26 +50,36 @@
|
|||||||
|
|
||||||
#define MAX_TIME_TOREAD 45
|
#define MAX_TIME_TOREAD 45
|
||||||
|
|
||||||
CLIENTONLY( SOCKET gSsdpReqSocket4 = INVALID_SOCKET; )
|
#ifdef INCLUDE_CLIENT_APIS
|
||||||
CLIENTONLY( SOCKET gSsdpReqSocket6 = INVALID_SOCKET; )
|
SOCKET gSsdpReqSocket4 = INVALID_SOCKET;
|
||||||
|
#ifdef UPNP_ENABLE_IPV6
|
||||||
|
SOCKET gSsdpReqSocket6 = INVALID_SOCKET;
|
||||||
|
#endif /* UPNP_ENABLE_IPV6 */
|
||||||
|
#endif /* INCLUDE_CLIENT_APIS */
|
||||||
|
|
||||||
void RequestHandler();
|
void RequestHandler();
|
||||||
int create_ssdp_sock_v4( SOCKET* ssdpSock );
|
int create_ssdp_sock_v4( SOCKET* ssdpSock );
|
||||||
|
#ifdef UPNP_ENABLE_IPV6
|
||||||
int create_ssdp_sock_v6( SOCKET* ssdpSock );
|
int create_ssdp_sock_v6( SOCKET* ssdpSock );
|
||||||
int create_ssdp_sock_v6_ula_gua( SOCKET* ssdpSock );
|
int create_ssdp_sock_v6_ula_gua( SOCKET* ssdpSock );
|
||||||
|
#endif
|
||||||
#if INCLUDE_CLIENT_APIS
|
#if INCLUDE_CLIENT_APIS
|
||||||
int create_ssdp_sock_reqv4( SOCKET* ssdpReqSock );
|
int create_ssdp_sock_reqv4( SOCKET* ssdpReqSock );
|
||||||
|
#ifdef UPNP_ENABLE_IPV6
|
||||||
int create_ssdp_sock_reqv6( SOCKET* ssdpReqSock );
|
int create_ssdp_sock_reqv6( SOCKET* ssdpReqSock );
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
Event ErrotEvt;
|
Event ErrotEvt;
|
||||||
|
|
||||||
enum Listener { Idle, Stopping, Running };
|
enum Listener { Idle, Stopping, Running };
|
||||||
|
|
||||||
struct SSDPSockArray {
|
struct SSDPSockArray {
|
||||||
// socket for incoming advertisments and search requests
|
/* socket for incoming advertisments and search requests */
|
||||||
SOCKET ssdpSock;
|
SOCKET ssdpSock;
|
||||||
// socket for sending search requests and receiving search replies
|
#ifdef INCLUDE_CLIENT_APIS
|
||||||
CLIENTONLY( int ssdpReqSock; )
|
/* socket for sending search requests and receiving search replies */
|
||||||
|
int ssdpReqSock;
|
||||||
|
#endif /* INCLUDE_CLIENT_APIS */
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef INCLUDE_DEVICE_APIS
|
#ifdef INCLUDE_DEVICE_APIS
|
||||||
@@ -258,7 +268,7 @@ int AdvertiseAndReply(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
case SSDP_DEVICETYPE: {
|
case SSDP_DEVICETYPE: {
|
||||||
if (!strncasecmp(DeviceType, devType, strlen(DeviceType))) {
|
if (!strncasecmp(DeviceType, devType, strlen(DeviceType)-2)) {
|
||||||
if (atoi(&DeviceType[strlen(DeviceType)-1]) <= atoi(&devType[strlen(devType)-1])) {
|
if (atoi(&DeviceType[strlen(DeviceType)-1]) <= atoi(&devType[strlen(devType)-1])) {
|
||||||
/* the requested version is lower than the device version
|
/* the requested version is lower than the device version
|
||||||
* must reply with the lower version number */
|
* must reply with the lower version number */
|
||||||
@@ -301,6 +311,7 @@ int AdvertiseAndReply(
|
|||||||
}
|
}
|
||||||
ixmlNodeList_free(nodeList);
|
ixmlNodeList_free(nodeList);
|
||||||
if (!tmpNode) {
|
if (!tmpNode) {
|
||||||
|
nodeList = NULL;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
nodeList = ixmlElement_getElementsByTagName(
|
nodeList = ixmlElement_getElementsByTagName(
|
||||||
@@ -732,26 +743,26 @@ start_event_handler( void *Data )
|
|||||||
* Returns: void
|
* Returns: void
|
||||||
*
|
*
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
static void
|
static void ssdp_event_handler_thread(void * the_data)
|
||||||
ssdp_event_handler_thread( void *the_data )
|
|
||||||
{
|
{
|
||||||
ssdp_thread_data *data = ( ssdp_thread_data * ) the_data;
|
ssdp_thread_data *data = (ssdp_thread_data *)the_data;
|
||||||
http_message_t *hmsg = &data->parser.msg;
|
http_message_t *hmsg = &data->parser.msg;
|
||||||
|
|
||||||
if( start_event_handler( the_data ) != 0 ) {
|
if (start_event_handler(the_data) != 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// send msg to device or ctrlpt
|
/* send msg to device or ctrlpt */
|
||||||
if( ( hmsg->method == HTTPMETHOD_NOTIFY ) ||
|
if (hmsg->method == HTTPMETHOD_NOTIFY ||
|
||||||
( hmsg->request_method == HTTPMETHOD_MSEARCH ) ) {
|
hmsg->request_method == HTTPMETHOD_MSEARCH) {
|
||||||
CLIENTONLY( ssdp_handle_ctrlpt_msg( hmsg,
|
#ifdef INCLUDE_CLIENT_APIS
|
||||||
(struct sockaddr*)&data->dest_addr, FALSE, NULL );)
|
ssdp_handle_ctrlpt_msg(hmsg, (struct sockaddr*)&data->dest_addr, FALSE, NULL);
|
||||||
|
#endif /* INCLUDE_CLIENT_APIS */
|
||||||
} else {
|
} else {
|
||||||
ssdp_handle_device_request( hmsg, (struct sockaddr*)&data->dest_addr );
|
ssdp_handle_device_request(hmsg, (struct sockaddr*)&data->dest_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// free data
|
/* free data */
|
||||||
free_ssdp_event_handler_data( data );
|
free_ssdp_event_handler_data(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
@@ -791,11 +802,20 @@ readFromSSDPSocket( SOCKET socket )
|
|||||||
//initialize parser
|
//initialize parser
|
||||||
|
|
||||||
#ifdef INCLUDE_CLIENT_APIS
|
#ifdef INCLUDE_CLIENT_APIS
|
||||||
|
#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
|
||||||
|
if( socket == gSsdpReqSocket4 ) {
|
||||||
|
parser_response_init( &data->parser, HTTPMETHOD_MSEARCH );
|
||||||
|
} else {
|
||||||
|
parser_request_init( &data->parser );
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
parser_request_init( &data->parser );
|
parser_request_init( &data->parser );
|
||||||
#endif
|
#endif
|
||||||
@@ -820,8 +840,10 @@ readFromSSDPSocket( SOCKET socket )
|
|||||||
|
|
||||||
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
|
||||||
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
|
||||||
else
|
else
|
||||||
strncpy( ntop_buf, "<Invalid address family>", sizeof(ntop_buf) );
|
strncpy( ntop_buf, "<Invalid address family>", sizeof(ntop_buf) );
|
||||||
|
|
||||||
@@ -876,6 +898,9 @@ int get_ssdp_sockets(MiniServerSockArray *out)
|
|||||||
{
|
{
|
||||||
int retVal;
|
int retVal;
|
||||||
|
|
||||||
|
out->ssdpReqSock4 = INVALID_SOCKET;
|
||||||
|
out->ssdpReqSock6 = INVALID_SOCKET;
|
||||||
|
|
||||||
#if INCLUDE_CLIENT_APIS
|
#if INCLUDE_CLIENT_APIS
|
||||||
/* Create the IPv4 socket for SSDP REQUESTS */
|
/* Create the IPv4 socket for SSDP REQUESTS */
|
||||||
if(strlen(gIF_IPV4) > 0) {
|
if(strlen(gIF_IPV4) > 0) {
|
||||||
@@ -890,6 +915,7 @@ int get_ssdp_sockets(MiniServerSockArray *out)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Create the IPv6 socket for SSDP REQUESTS */
|
/* Create the IPv6 socket for SSDP REQUESTS */
|
||||||
|
#ifdef UPNP_ENABLE_IPV6
|
||||||
if (strlen(gIF_IPV6) > 0) {
|
if (strlen(gIF_IPV6) > 0) {
|
||||||
retVal = create_ssdp_sock_reqv6(&out->ssdpReqSock6);
|
retVal = create_ssdp_sock_reqv6(&out->ssdpReqSock6);
|
||||||
if (retVal != UPNP_E_SUCCESS) {
|
if (retVal != UPNP_E_SUCCESS) {
|
||||||
@@ -902,6 +928,9 @@ int get_ssdp_sockets(MiniServerSockArray *out)
|
|||||||
} else {
|
} else {
|
||||||
out->ssdpReqSock6 = INVALID_SOCKET;
|
out->ssdpReqSock6 = INVALID_SOCKET;
|
||||||
}
|
}
|
||||||
|
#endif //IPv6
|
||||||
|
|
||||||
|
|
||||||
#endif /* INCLUDE_CLIENT_APIS */
|
#endif /* INCLUDE_CLIENT_APIS */
|
||||||
|
|
||||||
/* Create the IPv4 socket for SSDP */
|
/* Create the IPv4 socket for SSDP */
|
||||||
@@ -921,6 +950,7 @@ int get_ssdp_sockets(MiniServerSockArray *out)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Create the IPv6 socket for SSDP */
|
/* Create the IPv6 socket for SSDP */
|
||||||
|
#ifdef UPNP_ENABLE_IPV6
|
||||||
if (strlen(gIF_IPV6) > 0) {
|
if (strlen(gIF_IPV6) > 0) {
|
||||||
retVal = create_ssdp_sock_v6(&out->ssdpSock6);
|
retVal = create_ssdp_sock_v6(&out->ssdpSock6);
|
||||||
if (retVal != UPNP_E_SUCCESS) {
|
if (retVal != UPNP_E_SUCCESS) {
|
||||||
@@ -956,6 +986,8 @@ int get_ssdp_sockets(MiniServerSockArray *out)
|
|||||||
} else {
|
} else {
|
||||||
out->ssdpSock6UlaGua = INVALID_SOCKET;
|
out->ssdpSock6UlaGua = INVALID_SOCKET;
|
||||||
}
|
}
|
||||||
|
#endif //IPv6
|
||||||
|
|
||||||
|
|
||||||
return UPNP_E_SUCCESS;
|
return UPNP_E_SUCCESS;
|
||||||
}
|
}
|
||||||
@@ -1011,6 +1043,7 @@ int create_ssdp_sock_reqv4( SOCKET* ssdpReqSock )
|
|||||||
* Returns: void
|
* Returns: void
|
||||||
*
|
*
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
#ifdef UPNP_ENABLE_IPV6
|
||||||
int create_ssdp_sock_reqv6( SOCKET* ssdpReqSock )
|
int create_ssdp_sock_reqv6( SOCKET* ssdpReqSock )
|
||||||
{
|
{
|
||||||
char errorBuffer[ERROR_BUFFER_LEN];
|
char errorBuffer[ERROR_BUFFER_LEN];
|
||||||
@@ -1035,6 +1068,8 @@ int create_ssdp_sock_reqv6( SOCKET* ssdpReqSock )
|
|||||||
|
|
||||||
return UPNP_E_SUCCESS;
|
return UPNP_E_SUCCESS;
|
||||||
}
|
}
|
||||||
|
#endif // IPv6
|
||||||
|
|
||||||
#endif /* INCLUDE_CLIENT_APIS */
|
#endif /* INCLUDE_CLIENT_APIS */
|
||||||
|
|
||||||
|
|
||||||
@@ -1178,6 +1213,7 @@ int create_ssdp_sock_v4( SOCKET* ssdpSock )
|
|||||||
* Returns: void
|
* Returns: void
|
||||||
*
|
*
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
#ifdef UPNP_ENABLE_IPV6
|
||||||
int create_ssdp_sock_v6( SOCKET* ssdpSock )
|
int create_ssdp_sock_v6( SOCKET* ssdpSock )
|
||||||
{
|
{
|
||||||
char errorBuffer[ERROR_BUFFER_LEN];
|
char errorBuffer[ERROR_BUFFER_LEN];
|
||||||
@@ -1274,7 +1310,7 @@ int create_ssdp_sock_v6( SOCKET* ssdpSock )
|
|||||||
return UPNP_E_SUCCESS;
|
return UPNP_E_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // IPv6
|
||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
* Function : create_ssdp_sock_v6_ula_gua
|
* Function : create_ssdp_sock_v6_ula_gua
|
||||||
@@ -1288,6 +1324,7 @@ int create_ssdp_sock_v6( SOCKET* ssdpSock )
|
|||||||
* Returns: void
|
* Returns: void
|
||||||
*
|
*
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
#ifdef UPNP_ENABLE_IPV6
|
||||||
int create_ssdp_sock_v6_ula_gua(SOCKET *ssdpSock)
|
int create_ssdp_sock_v6_ula_gua(SOCKET *ssdpSock)
|
||||||
{
|
{
|
||||||
char errorBuffer[ERROR_BUFFER_LEN];
|
char errorBuffer[ERROR_BUFFER_LEN];
|
||||||
@@ -1385,7 +1422,7 @@ int create_ssdp_sock_v6_ula_gua(SOCKET *ssdpSock)
|
|||||||
|
|
||||||
return UPNP_E_SUCCESS;
|
return UPNP_E_SUCCESS;
|
||||||
}
|
}
|
||||||
|
#endif //IPv6
|
||||||
|
|
||||||
#endif /* EXCLUDE_SSDP */
|
#endif /* EXCLUDE_SSDP */
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user