text: #ifndef UPNP_H
  #define UPNP_H
  
  /*******************************************************************************
   *
   * Copyright (c) 2000-2003 Intel Corporation 
   * All rights reserved. 
   * Copyright (C) 2011-2012 France Telecom 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.
   *
   ******************************************************************************/
  
  /*!
   * \defgroup UPnPAPI UPnP API
   * 
   * @{
   *
   * \file
   */
  
  #include "upnpconfig.h"
  #include "UpnpGlobal.h"
  #include "UpnpInet.h"
  
  /*
   * \todo Document the exact reason of these include files and solve this
   * include mess in an include file like UpnpTime.h
   */
  #ifdef WIN32
  	#include <time.h>
  	#ifdef UPNP_USE_MSVCPP
  		#include <sys/types.h>	/* needed for off_t */
  	#endif
  #elif (defined(BSD) && BSD >= 199306)
  	#include <time.h>
  #else
  	/* Other systems ??? */
  #endif
  
  #define LINE_SIZE  (size_t)180
  #define NAME_SIZE  (size_t)256
  #define MNFT_NAME_SIZE  64
  #define MODL_NAME_SIZE  32
  #define SERL_NUMR_SIZE  64
  #define MODL_DESC_SIZE  64
  #define UPNP_INFINITE		-1
  #define UPNP_USING_CHUNKED	-3
  #define UPNP_UNTIL_CLOSE	-4
  
  /*!
   * \name Error codes 
   *
   * The functions in the SDK API can return a variety of error 
   * codes to describe problems encountered during execution.  This section 
   * lists the error codes and provides a brief description of what each error 
   * code means.  Refer to the documentation for each function for a 
   * description of what an error code means in that context.
   *
   * @{
   */
  
  /*!
   * \brief The operation completed successfully.
   *
   * For asynchronous functions, this only means that the packet generated by 
   * the operation was successfully transmitted on the network.  The result of 
   * the entire operation comes as part of the callback for that operation.
   */
  #define UPNP_E_SUCCESS			0
  
  /*!
   * \brief The handle passed to a function is not a recognized as a valid handle.
   */
  #define UPNP_E_INVALID_HANDLE		-100
  
  /*!
   * \brief One or more of the parameters passed to the function is not valid.
   *
   * Refer to the documentation for each function for more information on the
   * valid ranges of the parameters.
   */
  #define UPNP_E_INVALID_PARAM		-101
  
  /*!
   * \brief The SDK does not have any more space for additional handles.
   *
   * The SDK allocates space for only a few handles in order to conserve memory.
   */
  #define UPNP_E_OUTOF_HANDLE		-102
  
  #define UPNP_E_OUTOF_CONTEXT		-103
  
  /*!
   * \brief Not enough resources are currently available to complete the operation.
   *
   * Most operations require some free memory in order to complete their work.
   */
  #define UPNP_E_OUTOF_MEMORY		-104
  
  /*!
   * \brief The SDK has already been initialized.
   *
   * The SDK needs to be initialied only once per process. Any additional
   * initialization attempts simply return this error with no other ill effects.
   */
  #define UPNP_E_INIT			-105
  
  #define UPNP_E_BUFFER_TOO_SMALL		-106
  
  /*!
   * \brief The description document passed to \b UpnpRegisterRootDevice,
   * \b UpnpRegisterRootDevice2 \b UpnpRegisterRootDevice3 or
   * \b UpnpRegisterRootDevice4 is invalid.
   */
  #define UPNP_E_INVALID_DESC		-107
  
  /*!
   * \brief An URL passed into the function is invalid.
   *
   * The actual cause is function specific, but in general, the URL itself
   * might be malformed (e.g. have invalid characters in it) or the host might
   * be unreachable.
   */
  #define UPNP_E_INVALID_URL		-108
  
  #define UPNP_E_INVALID_SID		-109
  
  #define UPNP_E_INVALID_DEVICE		-110
  
  /*!
   * \brief The device ID/service ID pair does not refer to a valid service.
   *
   * Returned only by \b UpnpNotify, \b UpnpNotifyExt, \b UpnpAcceptSubscription,
   * and \b UpnpAcceptSubscriptionExt.
   */
  #define UPNP_E_INVALID_SERVICE		-111
  
  /*!
   * \brief The response received from the remote side of a connection is not correct
   * for the protocol.
   *
   * This applies to the GENA, SOAP, and HTTP protocols.
   */
  #define UPNP_E_BAD_RESPONSE		-113
  
  #define UPNP_E_BAD_REQUEST		-114
  
  /*!
   * \brief The SOAP action message is invalid.
   *
   * This can be because the DOM document passed to the function was malformed or
   * the action message is not correct for the given action.
   */
  #define UPNP_E_INVALID_ACTION		-115
  
  /*!
   * \brief \b UpnpInit has not been called, or \b UpnpFinish has already been called.
   *
   * None of the API functions operate until \b UpnpInit successfully completes.
   */
  #define UPNP_E_FINISH			-116
  
  /*!
   * \brief \b UpnpInit cannot complete.  
   *
   * The typical reason is failure to allocate sufficient resources.
   */
  #define UPNP_E_INIT_FAILED		-117
  
  /*!
   * \brief The URL passed into a function is too long.
   *
   * The SDK limits URLs to 180 characters in length.  
   */
  #define UPNP_E_URL_TOO_BIG		-118
  
  /*!
   * \brief The HTTP message contains invalid message headers.
   *
   * The error always refers to the HTTP message header received from the remote
   * host.  The main areas where this occurs are in SOAP control messages (e.g.
   * \b UpnpSendAction), GENA subscription message (e.g. \b UpnpSubscribe),
   * GENA event notifications (e.g. \b UpnpNotify), and HTTP transfers (e.g.
   * \b UpnpDownloadXmlDoc).
   */
  #define UPNP_E_BAD_HTTPMSG		-119
  
  /*!
   * \brief A client or a device is already registered.
   *
   * The SDK currently has a limit of one registered client and one registered
   * device per process.
   */
  #define UPNP_E_ALREADY_REGISTERED	-120
  
  /*!
   * \brief The interface provided to \b UpnpInit2 is unknown or does not have a valid
   * IPv4 or IPv6 address configured.
   */
  #define UPNP_E_INVALID_INTERFACE	-121
  
  /*!
   * \brief A network error occurred.
   *
   * It is the generic error code for network problems that are not covered under
   * one of the more specific error codes.  The typical meaning is the SDK failed
   * to read the local IP address or had problems configuring one of the sockets.
   */
  #define UPNP_E_NETWORK_ERROR		-200
  
  /*!
   * \brief An error happened while writing to a socket.
   *
   * This occurs in any function that makes network connections, such as discovery
   * (e.g. \b UpnpSearchAsync or \b UpnpSendAdvertisement), control (e.g. 
   * \b UpnpSendAction), eventing (e.g. \b UpnpNotify), and HTTP functions (e.g.
   * \b UpnpDownloadXmlDoc).
   */
  #define UPNP_E_SOCKET_WRITE		-201
  
  /*!
   * \brief An error happened while reading from a socket.
   *
   * This occurs in any function that makes network connections, such as discovery
   * (e.g. \b UpnpSearchAsync or \b UpnpSendAdvertisement), control (e.g.
   * \b UpnpSendAction), eventing (e.g. \b UpnpNotify), and HTTP functions (e.g.
   * \b UpnpDownloadXmlDoc).
   */
  #define UPNP_E_SOCKET_READ		-202
  
  /*!
   * \brief The SDK had a problem binding a socket to a network interface.
   *
   * This occurs in any function that makes network connections, such as discovery
   * (e.g. \b UpnpSearchAsync or \b UpnpSendAdvertisement), control (e.g.
   * \b UpnpSendAction), eventing (e.g. \b UpnpNotify), and HTTP functions (e.g. 
   * \b UpnpDownloadXmlDoc).
   */
  #define UPNP_E_SOCKET_BIND		-203
  
  /*!
   * \brief The SDK had a problem connecting to a remote host.
   *
   * This occurs in any function that makes network connections, such as discovery
   * (e.g. \b UpnpSearchAsync or \b UpnpSendAdvertisement), control (e.g.
   * \b UpnpSendAction), eventing (e.g. \b UpnpNotify), and HTTP functions (e.g. 
   * \b UpnpDownloadXmlDoc).
   */
  #define UPNP_E_SOCKET_CONNECT		-204
  
  /*!
   * \brief The SDK cannot create any more sockets.
   *
   * This occurs in any function that makes network connections, such as discovery
   * (e.g. \b UpnpSearchAsync or \b UpnpSendAdvertisement), control (e.g.
   * \b UpnpSendAction), eventing (e.g. \b UpnpNotify), and HTTP functions (e.g. 
   * \b UpnpDownloadXmlDoc).
   */
  #define UPNP_E_OUTOF_SOCKET		-205
  
  /*!
   * \brief The SDK had a problem setting the socket to listen for incoming
   * connections.
   *
   * This error only happens during initialization (i.e. \b UpnpInit).
   */
  #define UPNP_E_LISTEN			-206
  
  /*!
   * \brief Too much time elapsed before the required number of bytes were sent
   * or received over a socket.
   *
   * This error can be returned by any function that performs network operations.
   */
  #define UPNP_E_TIMEDOUT			-207
  
  /*!
   * \brief Generic socket error code for conditions not covered by other error
   * codes.
   *
   * This error can be returned by any function that performs network operations.
   */
  #define UPNP_E_SOCKET_ERROR		-208
  
  #define UPNP_E_FILE_WRITE_ERROR		-209
  
  /*! \brief The operation was canceled.
   *
   * This error can be returned by any function that allows for external cancelation.
   */
  #define UPNP_E_CANCELED			-210
  
  #define UPNP_E_EVENT_PROTOCOL		-300
  
  /*!
   * \brief A subscription request was rejected from the remote side.  
   */
  #define UPNP_E_SUBSCRIBE_UNACCEPTED	-301
  
  /*!
   * \brief An unsubscribe request was rejected from the remote side.
   */
  #define UPNP_E_UNSUBSCRIBE_UNACCEPTED	-302
  
  /*!
   * \brief The remote host did not accept the notify sent from the local device.
   */
  #define UPNP_E_NOTIFY_UNACCEPTED	-303
  
  /*!
   * \brief One or more of the parameters passed to a function is invalid.
   *
   * Refer to the individual function descriptions for the acceptable ranges for
   * parameters.
   */
  #define UPNP_E_INVALID_ARGUMENT		-501
  
  /*!
   * \brief The filename passed to one of the device registration functions was
   * not found or was not accessible.
   */
  #define UPNP_E_FILE_NOT_FOUND		-502
  
  /*!
   * \brief An error happened while reading a file.
   */
  #define UPNP_E_FILE_READ_ERROR		-503
  
  /*!
   * \brief The file name of the description document passed to
   * \b UpnpRegisterRootDevice2 does not end in ".xml".
   */
  #define UPNP_E_EXT_NOT_XML		-504
  
  #define UPNP_E_NO_WEB_SERVER		-505
  #define UPNP_E_OUTOF_BOUNDS		-506
  
  /*!
   * \brief The response to a SOAP request did not contain the required XML
   * constructs.  
   */
  #define UPNP_E_NOT_FOUND		-507
  
  /*!
   * \brief Generic error code for internal conditions not covered by other
   * error codes.
   */
  #define UPNP_E_INTERNAL_ERROR		-911
  
  /* SOAP-related error codes */
  #define UPNP_SOAP_E_INVALID_ACTION	401
  #define UPNP_SOAP_E_INVALID_ARGS	402
  #define UPNP_SOAP_E_OUT_OF_SYNC		403
  #define UPNP_SOAP_E_INVALID_VAR		404
  #define UPNP_SOAP_E_ACTION_FAILED	501
  
  /* @} ErrorCodes */
  
  #if UPNP_VERSION >= 10800
  /* 
   * Opaque data structures. The following includes are data structures that
   * must be externally visible. Since version 1.8.0, only an opaque typedef
   * is visible from the outside world. Any operation on these data types
   * must be done using the appropriate interface functions.
   *
   * This policy has the great advantage that it is now possible to change
   * the internal implementation of these data structures without breaking
   * the API.
   */
  #include "ActionComplete.h"
  #include "ActionRequest.h"
  #include "Discovery.h"
  #include "Event.h"
  #include "EventSubscribe.h"
  #include "FileInfo.h"
  #include "StateVarComplete.h"
  #include "StateVarRequest.h"
  #include "SubscriptionRequest.h"
  #endif /* UPNP_VERSION >= 10800 */
  
  /*!
   * \name Constants and Types
   *
   * @{
   */
  
  enum UpnpOpenFileMode
  {
  	UPNP_READ,
  	UPNP_WRITE
  };
  
  /*!
   * \brief Returned when a control point application registers with
   * \b UpnpRegisterClient.
   *
   * Client handles can only be used with functions that operate with a client
   * handle.
   */
  typedef int  UpnpClient_Handle;
  
  /*!
   * \brief Returned when a device application registers with
   * \b UpnpRegisterRootDevice, \b UpnpRegisterRootDevice2,
   * \b UpnpRegisterRootDevice3 or \b UpnpRegisterRootDevice4.
   *
   * Device handles can only be used with functions that operate with a device
   * handle.
   */
  typedef int  UpnpDevice_Handle;
  
  /*!
   * \brief The reason code for an event callback.
   *
   * The \b Event parameter will be different depending on the reason for the
   * callback. The descriptions for each event type describe the contents of the
   * \b Event parameter.
   */
  enum Upnp_EventType_e {
  	/*
  	 * Control callbacks
  	 */
  
  	/*! Received by a device when a control point issues a control
  	 * request.  The \b Event parameter contains a pointer to a \b
  	 * UpnpActionRequest structure containing the action.  The application
  	 * stores the results of the action in this structure. */
  	UPNP_CONTROL_ACTION_REQUEST,
  
  	/*! A \b UpnpSendActionAsync call completed. The \b Event
  	 * parameter contains a pointer to a \b UpnpActionComplete structure
  	 * with the results of the action.  */
  	UPNP_CONTROL_ACTION_COMPLETE,
  
  	/*! Received by a device when a query for a single service variable
  	 * arrives.  The \b Event parameter contains a pointer to a \b
  	 * UpnpStateVarRequest structure containing the name of the variable
  	 * and value.  */
  	UPNP_CONTROL_GET_VAR_REQUEST,
  
  	/*! A \b UpnpGetServiceVarStatus call completed. The \b Event
  	 * parameter contains a pointer to a \b UpnpStateVarComplete structure
  	 * containing the value for the variable.  */
  	UPNP_CONTROL_GET_VAR_COMPLETE,
  
  	/*
  	 * Discovery callbacks
  	 */
  
  	/*! Received by a control point when a new device or service is available.  
  	 * The \b Event parameter contains a pointer to a \b
  	 * UpnpDiscovery structure with the information about the device
  	 * or service.  */
  	UPNP_DISCOVERY_ADVERTISEMENT_ALIVE,
  
  	/*! Received by a control point when a device or service shuts down. The \b
  	 * Event parameter contains a pointer to a \b UpnpDiscovery
  	 * structure containing the information about the device or
  	 * service.  */
  	UPNP_DISCOVERY_ADVERTISEMENT_BYEBYE,
  
  	/*! Received by a control point when a matching device or service responds.
  	 * The \b Event parameter contains a pointer to a \b
  	 * UpnpDiscovery structure containing the information about
  	 * the reply to the search request.  */
  	UPNP_DISCOVERY_SEARCH_RESULT,
  
  	/*! Received by a control point when the search timeout expires.  The
  	 * SDK generates no more callbacks for this search after this 
  	 * event.  The \b Event parameter is \c NULL.  */
  	UPNP_DISCOVERY_SEARCH_TIMEOUT,
  
  	/*
  	 * Eventing callbacks
  	 */
  
  	/*! Received by a device when a subscription arrives.
  	 * The \b Event parameter contains a pointer to a \b
  	 * UpnpSubscriptionRequest structure.  At this point, the
  	 * subscription has already been accepted.  \b UpnpAcceptSubscription
  	 * needs to be called to confirm the subscription and transmit the
  	 * initial state table.  This can be done during this callback.  The SDK
  	 * generates no events for a subscription unless the device 
  	 * application calls \b UpnpAcceptSubscription.
  	 */
  	UPNP_EVENT_SUBSCRIPTION_REQUEST,
  
  	/*! Received by a control point when an event arrives. The \b
  	 * Event parameter contains a \b UpnpEvent structure
  	 * with the information about the event.  */
  	UPNP_EVENT_RECEIVED,
  
  	/*! A \b UpnpRenewSubscriptionAsync call completed. The status of
  	 * the renewal is in the \b Event parameter as a \b
  	 * Upnp_Event_Subscription structure.  */
  	UPNP_EVENT_RENEWAL_COMPLETE,
  
  	/*! A \b UpnpSubscribeAsync call completed. The status of the
  	 * subscription is in the \b Event parameter as a \b
  	 * Upnp_Event_Subscription structure.  */
  	UPNP_EVENT_SUBSCRIBE_COMPLETE,
  
  	/*! A \b UpnpUnSubscribeAsync call completed. The status of the
  	 * subscription is in the \b Event parameter as a \b
  	 * UpnpEventSubscribe structure.  */
  	UPNP_EVENT_UNSUBSCRIBE_COMPLETE,
  
  	/*! The auto-renewal of a client subscription failed.   
  	 * The \b Event parameter is a \b UpnpEventSubscribe structure 
  	 * with the error code set appropriately. The subscription is no longer 
  	 * valid. */
  	UPNP_EVENT_AUTORENEWAL_FAILED,
  
  	/*! A client subscription has expired. This will only occur 
  	 * if auto-renewal of subscriptions is disabled.
  	 * The \b Event parameter is a \b UpnpEventSubscribe
  	 * structure. The subscription is no longer valid. */
  	UPNP_EVENT_SUBSCRIPTION_EXPIRED
  };
  
  typedef enum Upnp_EventType_e Upnp_EventType;
  
  /*!
   * \brief Holds the subscription identifier for a subscription between a
   * client and a device.
   *
   * The SID is a string representation of a globally unique id (GUID) and should
   * not be modified.
   */
  typedef char Upnp_SID[44];
  
  /*!
   * \brief Represents the different types of searches that can be performed
   * using the SDK for UPnP Devices API.
   *
   * By specifying these different values to \b UpnpSearchAsync, the control
   * point application can control the scope of the search from all devices
   * to specific devices or services.
   */
  enum Upnp_SType_e {
  	/*! Search for all devices and services on the network. */
  	UPNP_S_ALL,    
  
  	/*! Search for all root devices on the network. */
  	UPNP_S_ROOT,   
  
  	/*! Search for a particular device type or a particular device instance. */
  	UPNP_S_DEVICE, 
  
  	/*! Search for a particular service type, possibly on a particular
  	 *  device type or device instance.  */
  	UPNP_S_SERVICE 
  };
  
  typedef enum Upnp_SType_e Upnp_SType;
  
  /*!
   * \brief Specifies the type of description in \b UpnpRegisterRootDevice2.
   *
   * These values control how \b UpnpRegisterRootDevice2 interprets the
   * \b description parameter.
   */
  enum Upnp_DescType_e { 
  	/*! The description is the URL to the description document. */
  	UPNPREG_URL_DESC, 
  	
  	/*! The description is a file name on the local file system 
  	    containing the description of the device. */
  	UPNPREG_FILENAME_DESC,
      
  	/*! The description is a pointer to a character array containing 
  	    the XML description document. */
  	UPNPREG_BUF_DESC 
  };
  
  typedef enum Upnp_DescType_e Upnp_DescType;
  
  #if UPNP_VERSION < 10800
  /** Returned as part of a {\bf UPNP_CONTROL_ACTION_COMPLETE} callback.  */
  
  struct Upnp_State_Var_Complete
  {
    /** The result of the operation. */
    int ErrCode;
  
    /** The control URL for the service. */
    char CtrlUrl[NAME_SIZE];
  
    /** The name of the variable. */
    char StateVarName[NAME_SIZE];
  };
  
  /** Returned along with a {\bf UPNP_EVENT_RECEIVED} callback.  */
  
  struct Upnp_Event
  {
    /** The subscription ID for this subscription. */
    Upnp_SID Sid;
  
    /** The event sequence number. */
    int EventKey;
  };
  
  /*
   * This typedef is required by Doc++ to parse the last entry of the 
   * Upnp_Discovery structure correctly.
   */
  
  
  /** Returned in a {\bf UPNP_DISCOVERY_RESULT} callback. */
  struct Upnp_Discovery
  {
  	/** The result code of the {\bf UpnpSearchAsync} call. */
  	int  ErrCode;                  
  				     
  	/** The unique device identifier. */
  	char UID[LINE_SIZE];
  
  	/** The device type. */
  	char DeviceType[LINE_SIZE];    
  
  	/** The URL to the UPnP description document for the device. */
  	char Location[LINE_SIZE];      
  
  	/** The host address of the device responding to the search. */
  	struct sockaddr_storage DestAddr;
  };
  
  /** Returned along with a {\bf UPNP_EVENT_SUBSCRIBE_COMPLETE} or {\bf
   * UPNP_EVENT_UNSUBSCRIBE_COMPLETE} callback.  */
  
  struct Upnp_Event_Subscribe {
  
    /** The SID for this subscription.  For subscriptions, this only
     *  contains a valid SID if the {\bf Upnp_EventSubscribe.result} field
     *  contains a {\tt UPNP_E_SUCCESS} result code.  For unsubscriptions,
     *  this contains the SID from which the subscription is being
     *  unsubscribed.  */
  
    Upnp_SID Sid;            
  
    /** The result of the operation. */
    int ErrCode;              
  
    /** The event URL being subscribed to or removed from. */
    char PublisherUrl[NAME_SIZE]; 
  
    /** The actual subscription time (for subscriptions only). */
    int TimeOut;              
                                
  };
    
  /** Returned along with a {\bf UPNP_EVENT_SUBSCRIPTION_REQUEST}
   *  callback.  */
  
  struct Upnp_Subscription_Request
  {
    /** The identifier for the service being subscribed to. */
    char *ServiceId; 
  
    /** Universal device name. */
    char *UDN;       
  
    /** The assigned subscription ID for this subscription. */
    Upnp_SID Sid;
  
  };
  
  struct File_Info
  {
  	/** The length of the file. A length less than 0 indicates the size 
  	*  is unknown, and data will be sent until 0 bytes are returned from
  	*  a read call. */
  	off_t file_length;
  
  	/** The time at which the contents of the file was modified;
  	*  The time system is always local (not GMT). */
  	time_t last_modified;
  
  	/** If the file is a directory, {\bf is_directory} contains
  	* a non-zero value. For a regular file, it should be 0. */
  	int is_directory;
  
  	/** If the file or directory is readable, this contains 
  	* a non-zero value. If unreadable, it should be set to 0. */
  	int is_readable;
  };
  #endif /* UPNP_VERSION < 10800 */
  
  /*!
   *  All callback functions share the same prototype, documented below.
   *  Note that any memory passed to the callback function
   *  is valid only during the callback and should be copied if it
   *  needs to persist.  This callback function needs to be thread
   *  safe.  The context of the callback is always on a valid thread 
   *  context and standard synchronization methods can be used.  Note, 
   *  however, because of this the callback cannot call SDK functions
   *  unless explicitly noted.
   *
   *  \verbatim
        int CallbackFxn(Upnp_EventType EventType, void *Event, void *Cookie);
      \endverbatim 
   *
   *  where \b EventType is the event that triggered the callback, 
   *  \b Event is a structure that denotes event-specific information for that
   *  event, and \b Cookie is the user data passed when the callback was
   *  registered.
   *
   *  See \b Upnp_EventType for more information on the callback values and
   *  the associated \b Event parameter.  
   *
   *  The return value of the callback is currently ignored. It may be used
   *  in the future to communicate results back to the SDK.
   */
  typedef int (*Upnp_FunPtr)(
  	/*! [in] .*/
  	Upnp_EventType EventType,
  	/*! [in] .*/
  	void *Event,
  	/*! [in] .*/
  	void *Cookie);
  
  /* @} Constants and Types */
  
  #ifdef __cplusplus
  extern "C" {
  #endif /* __cplusplus */
  
  /*!
   * \name Initialization and Registration
   *
   * @{
   */
  
  /*!
   * \brief Initializes the Linux SDK for UPnP Devices (IPv4 only).
   *
   * \deprecated Kept for backwards compatibility. Use UpnpInit2 for new
   * implementations or where IPv6 is required.
   *
   * This function must be called before any other API function can be called.
   * It should be called only once. Subsequent calls to this API return a
   * \c UPNP_E_INIT error code.
   *
   * Optionally, the application can specify a host IPv4 address (in the
   * case of a multi-homed configuration) and a port number to use for
   * all UPnP operations.  Since a port number can be used only by one
   * process, multiple processes using the SDK must specify
   * different port numbers.
   *
   * If unspecified, the SDK will use the first IPv4-capable adapter's IP address
   * and an arbitrary port.
   *
   * This call is synchronous.
   *
   * \return An integer representing one of the following:
   *     \li \c UPNP_E_SUCCESS: The operation completed successfully.
   *     \li \c UPNP_E_OUTOF_MEMORY: Insufficient resources exist 
   *             to initialize the SDK.
   *     \li \c UPNP_E_INIT: The SDK is already initialized. 
   *     \li \c UPNP_E_INIT_FAILED: The SDK initialization 
   *             failed for an unknown reason.
   *     \li \c UPNP_E_SOCKET_BIND: An error occurred binding a socket.
   *     \li \c UPNP_E_LISTEN: An error occurred listening to a socket.
   *     \li \c UPNP_E_OUTOF_SOCKET: An error ocurred creating a socket.
   *     \li \c UPNP_E_INTERNAL_ERROR: An internal error ocurred.
   */
  EXPORT_SPEC int UpnpInit(
  	/*! The host local IPv4 address to use, in string format, for example
  	 * "192.168.0.1", or \c NULL to use the first IPv4 adapter's IP address. */
  	const char *HostIP,
  	/*! Local Port to listen for incoming connections
  	 * \c NULL will pick an arbitrary free port. */
  	unsigned short DestPort);
  
  /*!
   * \brief Initializes the Linux SDK for UPnP Devices (IPv4 or IPv6).
   *
   * This function must be called before any other API function can be called.
   * It should be called only once. Subsequent calls to this API return a
   * \c UPNP_E_INIT error code.
   *
   * Optionally, the application can specify an interface name (in the
   * case of a multi-homed configuration) and a port number to use for
   * all UPnP operations.  Since a port number can be used only by one
   * process, multiple processes using the SDK must specify
   * different port numbers.
   *
   * If unspecified, the SDK will use the first suitable interface and an 
   * arbitrary port.
   *
   * This call is synchronous.
   *
   * \return An integer representing one of the following:
   *     \li \c UPNP_E_SUCCESS: The operation completed successfully.
   *     \li \c UPNP_E_OUTOF_MEMORY: Insufficient resources exist 
   *             to initialize the SDK.
   *     \li \c UPNP_E_INIT: The SDK is already initialized. 
   *     \li \c UPNP_E_INIT_FAILED: The SDK initialization 
   *             failed for an unknown reason.
   *     \li \c UPNP_E_SOCKET_BIND: An error occurred binding a socket.
   *     \li \c UPNP_E_LISTEN: An error occurred listening to a socket.
   *     \li \c UPNP_E_OUTOF_SOCKET: An error ocurred creating a socket.
   *     \li \c UPNP_E_INTERNAL_ERROR: An internal error ocurred.
   *     \li \c UPNP_E_INVALID_INTERFACE: IfName is invalid or does not
   *             have a valid IPv4 or IPv6 addresss configured.
   */
  #ifdef UPNP_ENABLE_IPV6
  EXPORT_SPEC int UpnpInit2( 
  	/*! The interface name to use by the UPnP SDK operations.
  	 * Examples: "eth0", "xl0", "Local Area Connection", \c NULL to
  	 * use the first suitable interface. */
  	const char *IfName,
  	/*!  Local Port to listen for incoming connections.
  	 * \c NULL will pick an arbitrary free port. */
  	unsigned short DestPort);
  #endif
  
  /*!
   * \brief Terminates the Linux SDK for UPnP Devices.
   *
   * \li Checks for pending jobs and threads
   * \li Unregisters either the client or device 
   * \li Shuts down the Timer Thread
   * \li Stops the Mini Server
   * \li Uninitializes the Thread Pool
   * \li For Win32 cleans up Winsock Interface 
   * \li Cleans up mutex objects
   *
   * This function must be the last API function called. It should be called only
   * once. Subsequent calls to this API return a \c UPNP_E_FINISH error code.
   *
   *  \return An integer representing one of the following:
   *      \li \c UPNP_E_SUCCESS: The operation completed successfully.
   *      \li \c UPNP_E_FINISH: The SDK is already terminated or 
   *                                 it is not initialized. 
   */
  EXPORT_SPEC int UpnpFinish(void);
  
  /*!
   * \brief Returns the internal server IPv4 UPnP listening port.
   *
   * If '0' is used as the port number in \b UpnpInit, then this function can be
   * used to retrieve the actual port allocated to the SDK.
   *
   * \return
   * 	\li On success: The port on which an internal server is listening for IPv4 UPnP
   *		related requests.
   *	\li On error: 0 is returned if \b UpnpInit has not succeeded.
   */
  EXPORT_SPEC unsigned short UpnpGetServerPort(void);
  
  /*!
   * \brief Returns the internal server IPv6 UPnP listening port.
   *
   * If '0' is used as the port number in \b UpnpInit, then this function can be
   * used to retrieve the actual port allocated to the SDK.
   *
   * \return
   * 	\li On success: The port on which an internal server is listening for IPv6 UPnP
   *		related requests.
   *	\li On error: 0 is returned if \b UpnpInit has not succeeded.
   */
  #ifdef UPNP_ENABLE_IPV6
  EXPORT_SPEC unsigned short UpnpGetServerPort6(void);
  #endif
  /*!
   * \brief Returns the local IPv4 listening ip address.
   *
   * If \c NULL is used as the IPv4 address in \b UpnpInit, then this function can
   * be used to retrieve the actual interface address on which device is running.
   *
   * \return
   * 	\li On success: The IPv4 address on which an internal server is
   * 		listening for UPnP related requests.
   * 	\li On error: \c NULL is returned if \b UpnpInit has not succeeded.
   */
  EXPORT_SPEC char *UpnpGetServerIpAddress(void);
  
  /*!
   * \brief Returns the local IPv6 listening ip address.
   *
   * If \c NULL is used as the IPv6 address in \b UpnpInit, then this function can
   * be used to retrieve the actual interface address on which device is running.
   *
   * \return
   * 	\li On success: The IPv6 address on which an internal server is
   * 		listening for UPnP related requests.
   * 	\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 *UpnpGetServerUlaGuaIp6Address(void);
  #endif
  /*!
   * \brief Registers a device application with the UPnP Library.
   *
   * A device application cannot make any other API calls until it registers
   * using this function.
   *
   * Device applications can also register as control points (see 
   * \b UpnpRegisterClient to get a control point handle to perform control
   * point functionality).
   *
   * This is a synchronous call and does not generate any callbacks. Callbacks
   * can occur as soon as this function returns.
   *
   *  \return An integer representing one of the following:
   *      \li \c UPNP_E_SUCCESS: The operation completed successfully.
   *      \li \c UPNP_E_FINISH: The SDK is already terminated or is not
   *		initialized.
   *      \li \c UPNP_E_INVALID_DESC: The description document was not 
   *		a valid device description.
   *      \li \c UPNP_E_INVALID_URL: The URL for the description document 
   *              is not valid.
   *      \li \c UPNP_E_INVALID_PARAM: Either \b Callback or \b Hnd 
   *              is not a valid pointer or \b DescURL is \c NULL.
   *      \li \c UPNP_E_NETWORK_ERROR: A network error occurred.
   *      \li \c UPNP_E_SOCKET_WRITE: An error or timeout occurred writing 
   *              to a socket.
   *      \li \c UPNP_E_SOCKET_READ: An error or timeout occurred reading 
   *              from a socket.
   *      \li \c UPNP_E_SOCKET_BIND: An error occurred binding a socket.
   *      \li \c UPNP_E_SOCKET_CONNECT: An error occurred connecting the 
   *              socket.
   *      \li \c UPNP_E_OUTOF_SOCKET: Too many sockets are currently 
   *              allocated.
   *      \li \c UPNP_E_OUTOF_MEMORY: There are insufficient resources to 
   *              register this root device.
   */
  EXPORT_SPEC int UpnpRegisterRootDevice(
  	/*! [in] Pointer to a string containing the description URL for this root device
  	 * instance. */
  	const char *DescUrl,
  	/*! [in] Pointer to the callback function for receiving asynchronous events. */
  	Upnp_FunPtr Callback,
  	/*! [in] Pointer to user data returned with the callback function when invoked. */
  	const void *Cookie,
  	/*! [out] Pointer to a variable to store the new device handle. */
  	UpnpDevice_Handle *Hnd);
  
  /*!
   * \brief Registers a device application with the UPnP Library. Similar to
   * \b UpnpRegisterRootDevice, except that it also allows the description
   * document to be specified as a file or a memory buffer.
   *
   * The description can also be configured to have the correct IP and port
   * address.
   *
   * NOTE: For the configuration to be functional, the internal web server
   * MUST be present. In addition, the web server MUST be activated
   * (using \b UpnpSetWebServerRootDir) before calling this function.
   * The only condition where the web server can be absent is if the 
   * description document is specified as a URL and no configuration is 
   * required (i.e. <tt>config_baseURL = 0</tt>.)
   *
   * This is a synchronous call and does not generate any callbacks. Callbacks
   * can occur as soon as this function returns.
   *
   * Examples of using different types of description documents:
   * \verbatim
     1) Description specified as a URL:
           descriptionType == UPNPREG_URL_DESC
           description is the URL
           bufferLen = 0 (ignored)
     2) Description specified as a file:
           descriptionType == UPNPREG_FILENAME_DESC
           description is a filename
           bufferLen = 0 (ignored)
     3) Description specified as a memory buffer:
           descriptionType == UPNPREG_BUF_DESC
           description is pointer to a memory buffer
           bufferLen == length of memory buffer
     \endverbatim
   *
   * \return An integer representing one of the following:
   *     \li \c UPNP_E_SUCCESS: The operation completed successfully.
   *     \li \c UPNP_E_FINISH: The SDK is already terminated or 
   *                                is not initialized.
   *     \li \c UPNP_E_INVALID_DESC: The description document is not 
   *             a valid device description.
   *     \li \c UPNP_E_INVALID_PARAM: Either \b Callback or \b Hnd 
   *             is not a valid pointer or \b DescURL is \c NULL.
   *     \li \c UPNP_E_NETWORK_ERROR: A network error occurred.
   *     \li \c UPNP_E_SOCKET_WRITE: An error or timeout occurred writing 
   *             to a socket.
   *     \li \c UPNP_E_SOCKET_READ: An error or timeout occurred reading 
   *             from a socket.
   *     \li \c UPNP_E_SOCKET_BIND: An error occurred binding a socket.
   *     \li \c UPNP_E_SOCKET_CONNECT: An error occurred connecting the 
   *             socket.
   *     \li \c UPNP_E_OUTOF_SOCKET: Too many sockets are currently 
   *             allocated.
   *     \li \c UPNP_E_OUTOF_MEMORY: There are insufficient resources to 
   *             register this root device.
   *     \li \c UPNP_E_URL_TOO_BIG: Length of the URL is bigger than the 
   *             internal buffer.
   *     \li \c UPNP_E_FILE_NOT_FOUND: The description file could not 
   *             be found.
   *     \li \c UPNP_E_FILE_READ_ERROR: An error occurred reading the 
   *             description file.
   *     \li \c UPNP_E_INVALID_URL: The URL to the description document 
   *             is invalid.
   *     \li \c UPNP_E_EXT_NOT_XML: The URL to the description document 
   *             or file should have a <tt>.xml</tt> extension.
   *     \li \c UPNP_E_NO_WEB_SERVER: The internal web server has been 
   *             compiled out; the SDK cannot configure itself from the 
   *             description document.
   */
  EXPORT_SPEC int UpnpRegisterRootDevice2(
  	/*! [in] The type of the description document. */
  	Upnp_DescType descriptionType,
  	/*! [in] Treated as a URL, file name or memory buffer depending on
  	 * description type. */
  	const char* description,
  	/*! [in] The length of memory buffer if passing a description in a buffer,
  	 * otherwise it is ignored. */
  	size_t bufferLen,
  	/*! [in] If nonzero, \c URLBase of description document is configured and
  	 * the description is served using the internal web server. */
  	int config_baseURL,
  	/*! [in] Pointer to the callback function for receiving asynchronous events. */
  	Upnp_FunPtr Fun,
  	/*! [in] Pointer to user data returned with the callback function when
  	 * invoked. */
  	const void* Cookie,
  	/*! [out] Pointer to a variable to store the new device handle. */
  	UpnpDevice_Handle* Hnd);
  
  /*!
   * \brief Registers a device application for a specific address family with
   * the UPnP library.
   *
   * A device application cannot make any other API calls until it registers
   * using this function. Device applications can also register as control
   * points (see \b UpnpRegisterClient to get a control point handle to perform
   * control point functionality).
   *
   * This is synchronous and does not generate any callbacks. Callbacks can occur
   * as soon as this function returns.
   *
   * \return An integer representing one of the following:
   *     \li \c UPNP_E_SUCCESS: The operation completed successfully.
   *     \li \c UPNP_E_FINISH: The SDK is already terminated or 
   *                                is not initialized. 
   *     \li \c UPNP_E_INVALID_DESC: The description document was not 
   *             a valid device description.
   *     \li \c UPNP_E_INVALID_URL: The URL for the description document 
   *             is not valid.
   *     \li \c UPNP_E_INVALID_PARAM: Either \b Callback or \b Hnd 
   *             is not a valid pointer or \b DescURL is \c NULL.
   *     \li \c UPNP_E_NETWORK_ERROR: A network error occurred.
   *     \li \c UPNP_E_SOCKET_WRITE: An error or timeout occurred writing 
   *             to a socket.
   *     \li \c UPNP_E_SOCKET_READ: An error or timeout occurred reading 
   *             from a socket.
   *     \li \c UPNP_E_SOCKET_BIND: An error occurred binding a socket.
   *     \li \c UPNP_E_SOCKET_CONNECT: An error occurred connecting the 
   *             socket.
   *     \li \c UPNP_E_OUTOF_SOCKET: Too many sockets are currently 
   *             allocated.
   *     \li \c UPNP_E_OUTOF_MEMORY: There are insufficient resources to 
   *             register this root device.
   */
  EXPORT_SPEC int UpnpRegisterRootDevice3(
  	/*! [in] Pointer to a string containing the description URL for this root
  	 * device instance. */
  	const char *DescUrl,
  	/*! [in] Pointer to the callback function for receiving asynchronous events. */
  	Upnp_FunPtr Callback,
  	/*! [in] Pointer to user data returned with the callback function when invoked. */
  	const void *Cookie,
  	/*! [out] Pointer to a variable to store the new device handle. */
  	UpnpDevice_Handle *Hnd,
  	/*! [in] Address family of this device. Can be AF_INET for an IPv4 device, or
  	 * AF_INET6 for an IPv6 device. Defaults to AF_INET. */
  	int  AddressFamily);
  
  /*!
   * \brief Registers a device application for a specific address family with
   * the UPnP library. This function can also be used to specify a dedicated
   * description URL to be returned for legacy CPs.
   *
   * A device application cannot make any other API calls until it registers
   * using this function. Device applications can also register as control
   * points (see \b UpnpRegisterClient to get a control point handle to perform
   * control point functionality).
   *
   * This is synchronous and does not generate any callbacks. Callbacks can occur
   * as soon as this function returns.
   *
   * \return An integer representing one of the following:
   *     \li \c UPNP_E_SUCCESS: The operation completed successfully.
   *     \li \c UPNP_E_FINISH: The SDK is already terminated or
   *                                is not initialized.
   *     \li \c UPNP_E_INVALID_DESC: The description document was not
   *             a valid device description.
   *     \li \c UPNP_E_INVALID_URL: The URL for the description document
   *             is not valid.
   *     \li \c UPNP_E_INVALID_PARAM: Either \b Callback or \b Hnd
   *             is not a valid pointer or \b DescURL is \c NULL.
   *     \li \c UPNP_E_NETWORK_ERROR: A network error occurred.
   *     \li \c UPNP_E_SOCKET_WRITE: An error or timeout occurred writing
   *             to a socket.
   *     \li \c UPNP_E_SOCKET_READ: An error or timeout occurred reading
   *             from a socket.
   *     \li \c UPNP_E_SOCKET_BIND: An error occurred binding a socket.
   *     \li \c UPNP_E_SOCKET_CONNECT: An error occurred connecting the
   *             socket.
   *     \li \c UPNP_E_OUTOF_SOCKET: Too many sockets are currently
   *             allocated.
   *     \li \c UPNP_E_OUTOF_MEMORY: There are insufficient resources to
   *             register this root device.
   */
  EXPORT_SPEC int UpnpRegisterRootDevice4(
  	/*! [in] Pointer to a string containing the description URL for this root
  	 * device instance. */
  	const char *DescUrl,
  	/*! [in] Pointer to the callback function for receiving asynchronous events. */
  	Upnp_FunPtr Callback,
  	/*! [in] Pointer to user data returned with the callback function when invoked. */
  	const void *Cookie,
  	/*! [out] Pointer to a variable to store the new device handle. */
  	UpnpDevice_Handle *Hnd,
  	/*! [in] Address family of this device. Can be AF_INET for an IPv4 device, or
  	 * AF_INET6 for an IPv6 device. Defaults to AF_INET. */
  	int  AddressFamily,
  	/*! [in] Pointer to a string containing the description URL to be returned for
  	 * legacy CPs for this root device instance. */
  	const char *LowerDescUrl);
  
  /*!
   * \brief Unregisters a root device registered with \b UpnpRegisterRootDevice,
   * \b UpnpRegisterRootDevice2, \b UpnpRegisterRootDevice3 or
   * \b UpnpRegisterRootDevice4.
   *
   * After this call, the \b UpnpDevice_Handle is no longer valid. For all
   * advertisements that have not yet expired, the SDK sends a device unavailable
   * message automatically.
   *
   * This is a synchronous call and generates no callbacks. Once this call
   * returns, the SDK will no longer generate callbacks to the application.
   *
   * \return An integer representing one of the following:
   *     \li \c UPNP_E_SUCCESS: The operation completed successfully.
   *     \li \c UPNP_E_INVALID_HANDLE: The handle is not a valid device handle.
   */
  EXPORT_SPEC int UpnpUnRegisterRootDevice(
  	/*! [in] The handle of the root device instance to unregister. */
  	UpnpDevice_Handle Hnd);
  
  /*!
   * \brief Unregisters a root device registered with \b UpnpRegisterRootDevice,
   * \b UpnpRegisterRootDevice2, \b UpnpRegisterRootDevice3 or
   * \b UpnpRegisterRootDevice4.
   *
   * After this call, the \b UpnpDevice_Handle is no longer valid. For all
   * advertisements that have not yet expired, the SDK sends a device unavailable
   * message automatically.
   *
   * This is a synchronous call and generates no callbacks. Once this call
   * returns, the SDK will no longer generate callbacks to the application.
   *
   * This function allow a device to specify the SSDP extensions defined by UPnP
   * Low Power.
   *
   * \return An integer representing one of the following:
   *     \li \c UPNP_E_SUCCESS: The operation completed successfully.
   *     \li \c UPNP_E_INVALID_HANDLE: The handle is not a valid device handle.
   */
  EXPORT_SPEC int UpnpUnRegisterRootDeviceLowPower(
          /*! [in] The handle of the root device instance to unregister. */
          UpnpDevice_Handle Hnd,
          /*! PowerState as defined by UPnP Low Power. */
          int PowerState,
          /*! SleepPeriod as defined by UPnP Low Power. */
          int SleepPeriod,
          /*! RegistrationState as defined by UPnP Low Power. */
          int RegistrationState);
  
  /*!
   * \brief Registers a control point application with the UPnP Library.
   *
   * A control point application cannot make any other API calls until it
   * registers using this function.
   *
   * \b UpnpRegisterClient is a synchronous call and generates no callbacks.
   * Callbacks can occur as soon as this function returns.
   *
   * \return An integer representing one of the following:
   *      \li \c UPNP_E_SUCCESS: The operation completed successfully.
   *      \li \c UPNP_E_FINISH: The SDK is already terminated or 
   *                            is not initialized. 
   *      \li \c UPNP_E_INVALID_PARAM: Either \b Callback or \b Hnd 
   *              is not a valid pointer.
   *      \li \c UPNP_E_OUTOF_MEMORY: Insufficient resources exist to 
   *              register this control point.
   */
  EXPORT_SPEC int UpnpRegisterClient(
  	/*! [in] Pointer to a function for receiving asynchronous events. */
  	Upnp_FunPtr Callback,
  	/*! [in] Pointer to user data returned with the callback function when invoked. */
  	const void *Cookie,
  	/*! [out] Pointer to a variable to store the new control point handle. */
  	UpnpClient_Handle *Hnd);
  
  /*!
   * \brief Unregisters a control point application, unsubscribing all active
   * subscriptions.
   *
   * This function unregisters a client registered with UpnpRegisterclient or
   * UpnpRegisterclient2. After this call, the \b UpnpClient_Handle is no longer
   * valid. The UPnP Library generates no more callbacks after this function
   * returns.
   *
   * \b UpnpUnRegisterClient is a synchronous call and generates no
   * callbacks.
   *
   * \return An integer representing one of the following:
   *     \li \c UPNP_E_SUCCESS: The operation completed successfully.
   *     \li \c UPNP_E_INVALID_HANDLE: The handle is not a valid control point handle.
   */
  EXPORT_SPEC int UpnpUnRegisterClient(
  	/*! [in] The handle of the control point instance to unregister. */
  	UpnpClient_Handle Hnd);
  
  /*!
   * \deprecated Use \b UpnpSetMaxContentLength instead.
   *
   * Warning: the Handle argument provided here is not used, so the effect
   * of this function is global to the SDK (= same as \b UpnpSetMaxContentLength).
   */
  EXPORT_SPEC int UpnpSetContentLength(
  	/*! [in] The handle of the device instance for which the coincoming content
  	 * length needs to be set. */
  	UpnpClient_Handle Hnd,
  	/*! [in] Permissible content length */
  	size_t contentLength);
  
  /*!
   * \brief Sets the maximum content-length that the SDK will process on an
   * incoming SOAP requests or responses.
   *
   * This API allows devices that have memory constraints to exhibit consistent
   * behaviour if the size of the incoming SOAP message exceeds the memory that
   * device can allocate.
   *
   * If set to 0 then checking will be disabled.
   *
   * The default maximum content-length is \c DEFAULT_SOAP_CONTENT_LENGTH 
   * = 16K bytes.
   *  
   * \return An integer representing one of the following:
   *     \li \c UPNP_E_SUCCESS: The operation completed successfully.
   */
  EXPORT_SPEC int UpnpSetMaxContentLength(
  	/*! [in] The maximum permissible content length for incoming SOAP actions,
  	 * in bytes. */
  	size_t contentLength);
  
  /* @} Initialization and Registration */
  
  /******************************************************************************
   ******************************************************************************
   *                                                                            *
   *                        D I S C O V E R Y                                   *
   *                                                                            *
   ******************************************************************************
   ******************************************************************************/
  
  /*!
   * \name Discovery
   *
   * @{
   */
  
  /*!
   * \brief Searches for devices matching the given search target.
   *
   * The function returns immediately and the SDK calls the default callback
   * function, registered during the \b UpnpRegisterClient call, for each
   * matching root device, device, or service. The application specifies the
   * search type by the \b Target parameter.  
   *
   * This function searches for the devices for the provided maximum time.
   * It is an asynchronous function. It schedules a search job and returns. 
   * The client is notified about the search results after search timer.
   *
   * Note that there is no way for the SDK to distinguish which client
   * instance issued a particular search.  Therefore, the client can get
   * search callbacks that do not match the original criteria of the search.
   * Also, the application will receive multiple callbacks for each search.
   *
   * \return An integer representing one of the following:
   *     \li \c UPNP_E_SUCCESS: The operation completed successfully.
   *     \li \c UPNP_E_INVALID_HANDLE: The handle is not a valid control 
   *             point handle.
   *     \li \c UPNP_E_INVALID_PARAM: \b Target is \c NULL.
   */
  EXPORT_SPEC int UpnpSearchAsync(
  	/*! The handle of the client performing the search. */
  	UpnpClient_Handle Hnd,
  	/*! The time, in seconds, to wait for responses. If the time is greater
  	 * than \c MAX_SEARCH_TIME then the time is set to \c MAX_SEARCH_TIME.
  	 * If the time is less than \c MIN_SEARCH_TIME then the time is set to
  	 * \c MIN_SEARCH_TIME. */ 
  	int Mx,
  	/*! The search target as defined in the UPnP Device Architecture v1.0
  	 * specification. */
  	const char *TTarget_constarget_const,
  	/*! The user data to pass when the callback function is invoked. */
  	const void *Cookie_const); 
  
  /*!
   * \brief Sends out the discovery announcements for all devices and services
   * for a device.
   *
   * Each announcement is made with the same expiration time.
   *
   * This is a synchronous call.
   *
   * \return An integer representing one of the following:
   *     \li \c UPNP_E_SUCCESS: The operation completed successfully.
   *     \li \c UPNP_E_INVALID_HANDLE: The handle is not a valid 
   *             device handle.
   *     \li \c UPNP_E_OUTOF_MEMORY: There are insufficient resources to 
   *             send future advertisements.
   */
  EXPORT_SPEC int UpnpSendAdvertisement(
  	/*! The device handle for which to send out the announcements. */
  	UpnpDevice_Handle Hnd,
  	/*! The expiration age, in seconds, of the announcements. */
  	int Exp);
  
  /*!
   * \brief Sends out the discovery announcements for all devices and services
   * for a device.
   *
   * Each announcement is made with the same expiration time.
   *
   * This is a synchronous call.
   *
   * This function allow a device to specify the SSDP extensions defined by UPnP
   * Low Power.
   *
   * \return An integer representing one of the following:
   *     \li \c UPNP_E_SUCCESS: The operation completed successfully.
   *     \li \c UPNP_E_INVALID_HANDLE: The handle is not a valid
   *             device handle.
   *     \li \c UPNP_E_OUTOF_MEMORY: There are insufficient resources to
   *             send future advertisements.
   */
  EXPORT_SPEC int UpnpSendAdvertisementLowPower(
          /*! The device handle for which to send out the announcements. */
          UpnpDevice_Handle Hnd,
          /*! The expiration age, in seconds, of the announcements. */
          int Exp,
          /*! PowerState as defined by UPnP Low Power. */
          int PowerState,
          /*! SleepPeriod as defined by UPnP Low Power. */
          int SleepPeriod,
          /*! RegistrationState as defined by UPnP Low Power. */
          int RegistrationState);
  
  /* @} Discovery */
  
  /******************************************************************************
   ******************************************************************************
   *                                                                            *
   *                            C O N T R O L                                   *
   *                                                                            *
   ******************************************************************************
   ******************************************************************************/
  
  /*!
   * \name Control
   *
   * @{
   */
  
  
  /*!
   * \brief Sends a message to change a state variable in a service, generating a
   * callback when the operation is complete.
   * 
   * See \b UpnpSendAction for comments on positive return values. These 
   * positive return values are sent in the event struct associated with the
   * \c UPNP_CONTROL_ACTION_COMPLETE event.
   *
   * \return An integer representing one of the following:
   *     \li \c UPNP_E_SUCCESS: The operation completed successfully.
   *     \li \c UPNP_E_INVALID_HANDLE: The handle is not a valid control 
   *             point handle.
   *     \li \c UPNP_E_INVALID_URL: \b ActionUrl is an invalid URL.
   *     \li \c UPNP_E_INVALID_DEVICE: \b DevUDN is an invalid device.
   *     \li \c UPNP_E_INVALID_PARAM: Either \b Fun is not a valid 
   *             callback function or \b ServiceType, \b Act, or 
   *             \b ActionUrl is \c NULL.
   *     \li \c UPNP_E_INVALID_ACTION: This action is not valid.
   *     \li \c UPNP_E_OUTOF_MEMORY: Insufficient resources exist to 
   *             complete this operation.
   */
  EXPORT_SPEC int UpnpSendActionAsync(
  	/*! [in] The handle of the control point sending the action. */
  	UpnpClient_Handle Hnd,
  	/*! [in] The action URL of the service. */
  	const char *ActionURL,
  	/*! [in] The type of the service. */
  	const char *ServiceType,
  	/*! [in] This parameter is ignored and must be \c NULL. */
  	const char *DevUDN,
  	/*! [in] Pointer to a callback function to be invoked when the operation
  	 * completes. */
  	Upnp_FunPtr Fun,
  	/*! [in] Pointer to user data that to be passed to the callback when
  	 * invoked. */
  	const void *Cookie);
  
  /*! @} Control */
  
  /******************************************************************************
   ******************************************************************************
   *                                                                            *
   *                        E V E N T I N G                                     *
   *                                                                            *
   ******************************************************************************
   ******************************************************************************/
  
  /*!
   * \name Eventing
   *
   * @{
   */
  
  /*!
   * \brief Accepts a subscription request and sends out the current state of the
   * eventable variables for a service.
   *
   * The device application should call this function when it receives a
   * \c UPNP_EVENT_SUBSCRIPTION_REQUEST callback.
   *
   * This function is synchronous and generates no callbacks.
   *
   * This function can be called during the execution of a callback function.
   *
   * \return An integer representing one of the following:
   *      \li \c UPNP_E_SUCCESS: The operation completed successfully.
   *      \li \c UPNP_E_INVALID_HANDLE: The handle is not a valid device 
   *              handle.
   *      \li \c UPNP_E_INVALID_SERVICE: The \b DevId/\b ServId 
   *              pair refers to an invalid service. 
   *      \li \c UPNP_E_INVALID_SID: The specified subscription ID is not 
   *              valid.
   *      \li \c UPNP_E_INVALID_PARAM: Either \b VarName, 
   *              \b NewVal, \b DevID, or \b ServID is not a valid 
   *              pointer or \b cVariables is less than zero.
   *      \li \c UPNP_E_OUTOF_MEMORY: Insufficient resources exist to 
   *              complete this operation.
   */
  EXPORT_SPEC int UpnpAcceptSubscription(
  	/*! [in] The handle of the device. */
  	UpnpDevice_Handle Hnd,
  	/*! [in] The device ID of the subdevice of the service generating the event. */
  	const char *DevID,
  	/*! [in] The unique service identifier of the service generating the event. */
  	const char *ServID,
  	/*! [in] Pointer to an array of event variables. */
  	const char **VarName,
  	/*! [in] Pointer to an array of values for the event variables. */
  	const char **NewVal,
  	/*! [in] The number of event variables in \b VarName. */
  	int cVariables,
  	/*! [in] The subscription ID of the newly registered control point. */
  	const Upnp_SID SubsId);
  
  /*!
   * \brief Sends out an event change notification to all control points
   * subscribed to a particular service.
   *
   * This function is synchronous and generates no callbacks.
   *
   * This function may be called during a callback function to send out a
   * notification.
   *
   * \return An integer representing one of the following:
   *     \li \c UPNP_E_SUCCESS: The operation completed successfully.
   *     \li \c UPNP_E_INVALID_HANDLE: The handle is not a valid device 
   *             handle.
   *     \li \c UPNP_E_INVALID_SERVICE: The \b DevId/\b ServId 
   *             pair refers to an invalid service.
   *     \li \c UPNP_E_INVALID_PARAM: Either \b VarName, \b NewVal, 
   *              \b DevID, or \b ServID is not a valid pointer or 
   *              \b cVariables is less than zero.
   *     \li \c UPNP_E_OUTOF_MEMORY: Insufficient resources exist to 
   *             complete this operation.
   */
  EXPORT_SPEC int UpnpNotify(
  	/*! [in] The handle to the device sending the event. */
  	UpnpDevice_Handle,
  	/*! [in] The device ID of the subdevice of the service generating the event. */
  	const char *DevID,
  	/*! [in] The unique identifier of the service generating the event. */
  	const char *ServID,
  	/*! [in] Pointer to an array of variables that have changed. */
  	const char **VarName,
  	/*! [in] Pointer to an array of new values for those variables. */
  	const char **NewVal,
  	/*! [in] The count of variables included in this notification. */
  	int cVariables);
  
  /*!
   * \brief Renews a subscription that is about to expire.
   *
   * This function is synchronous.
   *
   * \return An integer representing one of the following:
   *     \li \c UPNP_E_SUCCESS: The operation completed successfully.
   *     \li \c UPNP_E_INVALID_HANDLE: The handle is not a valid control 
   *             point handle.
   *     \li \c UPNP_E_INVALID_PARAM: \b Timeout is not a valid pointer.
   *     \li \c UPNP_E_INVALID_SID: The SID being passed to this function 
   *             is not a valid subscription ID.
   *     \li \c UPNP_E_NETWORK_ERROR: A network error occured. 
   *     \li \c UPNP_E_SOCKET_WRITE: An error or timeout occurred writing 
   *             to a socket.
   *     \li \c UPNP_E_SOCKET_READ: An error or timeout occurred reading 
   *             from a socket.
   *     \li \c UPNP_E_SOCKET_BIND: An error occurred binding a socket.  
   *     \li \c UPNP_E_SOCKET_CONNECT: An error occurred connecting to 
   *             \b PublisherUrl.
   *     \li \c UPNP_E_OUTOF_SOCKET: An error occurred creating a socket.
   *     \li \c UPNP_E_BAD_RESPONSE: An error occurred in response from 
   *             the publisher.
   *     \li \c UPNP_E_SUBSCRIBE_UNACCEPTED: The publisher refused 
   *             the subscription renew.
   *     \li \c UPNP_E_OUTOF_MEMORY: Insufficient resources exist to 
   *             complete this operation.
   */
  EXPORT_SPEC int UpnpRenewSubscription(
  	/*! [in] The handle of the control point that is renewing the subscription. */
  	UpnpClient_Handle Hnd,
  	/*! [in,out] Pointer to a variable containing the requested subscription time.
  	 * Upon return, it contains the actual renewal time. */
  	int *TimeOut,
  	/*! [in] The ID for the subscription to renew. */
  	const Upnp_SID SubsId);
  
  /*!
   * \brief Renews a subscription that is about to expire, generating a callback
   * when the operation is complete.
   *
   * Note that many of the error codes for this function are returned in
   * the \b UpnpEventSubscribe structure.  In those cases, the function
   * returns \c UPNP_E_SUCCESS and the appropriate error code will
   * be in the <b>UpnpEventSubscribe.ErrCode</b> field in the \b Event
   * structure passed to the callback.
   *
   * \return An integer representing one of the following:
   *     \li \c UPNP_E_SUCCESS: The operation completed successfully.
   *     \li \c UPNP_E_INVALID_HANDLE: The handle is not a valid control 
   *             point handle.
   *     \li \c UPNP_E_INVALID_SID: The \b SubsId is not a valid 
   *             subscription ID.
   *     \li \c UPNP_E_INVALID_PARAM: Either \b Fun is not a valid 
   *             callback function pointer or \b Timeout is less than zero 
   *             but is not \c UPNP_INFINITE.
   *     \li \c UPNP_E_OUTOF_MEMORY: Insufficient resources exist to 
   *             complete this operation.
   *     \li \c UPNP_E_NETWORK_ERROR: A network error occured (returned in 
   *             the <b>UpnpEventSubscribe.ErrCode</b> field as part of the 
   *             callback).
   *     \li \c UPNP_E_SOCKET_WRITE: An error or timeout occurred writing 
   *             to a socket (returned in the <b>UpnpEventSubscribe.ErrCode</b> 
   *             field as part of the callback).
   *     \li \c UPNP_E_SOCKET_READ: An error or timeout occurred reading  
   *             from a socket (returned in the 
   *             <b>UpnpEventSubscribe.ErrCode</b> field as part of the 
   *             callback).
   *     \li \c UPNP_E_SOCKET_BIND: An error occurred binding the socket 
   *             (returned in the <b>UpnpEventSubscribe.ErrCode</b> field as 
   *             part of the callback).
   *     \li \c UPNP_E_SOCKET_CONNECT: An error occurred connecting to 
   *             \b PublisherUrl (returned in the \b 
   *             UpnpEventSubscribe.ErrCode field as part of the callback).
   *     \li \c UPNP_E_OUTOF_SOCKET: An error occurred creating socket (
   *             returned in the <b>UpnpEventSubscribe.ErrCode</b> field as 
   *             part of the callback).
   *     \li \c UPNP_E_BAD_RESPONSE: An error occurred in response from 
   *             the publisher (returned in the \b 
   *             UpnpEventSubscribe.ErrCode field as part of the callback).
   *     \li \c UPNP_E_SUBSCRIBE_UNACCEPTED: The publisher refused 
   *             the subscription request (returned in the \b 
   *             UpnpEventSubscribe.ErrCode field as part of the callback).
   */
  EXPORT_SPEC int UpnpRenewSubscriptionAsync(
  	/*! [in] The handle of the control point that is renewing the subscription. */
  	UpnpClient_Handle Hnd,
  	/*! [in] The requested subscription time. The actual timeout value is
  	 * returned when the callback function is called. */
  	int TimeOut,
  	/*! [in] The ID for the subscription to renew. */
  	Upnp_SID SubsId,
  	/*! [in] Pointer to a callback function to be invoked when the renewal is
  	 * complete. */
  	Upnp_FunPtr Fun,
  	/*! [in] Pointer to user data passed to the callback function when invoked. */
  	const void *Cookie);
  
  /*!
   * \brief Sets the maximum number of subscriptions accepted per service.
   *
   * The default value accepts as many as system resources allow. If the number
   * of current subscriptions for a service is greater than the requested value,
   * the SDK accepts no new subscriptions or renewals, however, the SDK does not
   * remove any current subscriptions.
   *
   * \return An integer representing one of the following:
   *     \li \c UPNP_E_SUCCESS: The operation completed successfully.
   *     \li \c UPNP_E_INVALID_HANDLE: The handle is not a valid device 
   *             handle.
   */
  EXPORT_SPEC int UpnpSetMaxSubscriptions(  
  	/*! The handle of the device for which the maximum number of
  	 * subscriptions is being set. */
  	UpnpDevice_Handle Hnd,
  	/*! The maximum number of subscriptions to be allowed per service. */
  	int MaxSubscriptions);
  
  /*!
   * \brief Sets the maximum time-out accepted for a subscription request or
   * renewal.
   *
   * The default value accepts the time-out set by the control point.
   * If a control point requests a subscription time-out less than or equal to
   * the maximum, the SDK grants the value requested by the control point. If the
   * time-out is greater, the SDK returns the maximum value.
   *
   * \return An integer representing one of the following:
   *     \li \c UPNP_E_SUCCESS: The operation completed successfully.
   *     \li \c UPNP_E_INVALID_HANDLE: The handle is not a valid device 
   *             handle.
   */
  EXPORT_SPEC int UpnpSetMaxSubscriptionTimeOut(  
  	/*! The handle of the device for which the maximum subscription
  	 * time-out is being set. */
  	UpnpDevice_Handle Hnd,
  	/*! The maximum subscription time-out to be accepted. */
  	int MaxSubscriptionTimeOut);
  
  /*!
   * \brief Registers a control point to receive event notifications from another
   * device.
   *
   * This operation is synchronous.
   *
   * \return An integer representing one of the following:
   *     \li \c UPNP_E_SUCCESS: The operation completed successfully.
   *     \li \c UPNP_E_INVALID_HANDLE: The handle is not a valid control 
   *             point handle.
   *     \li \c UPNP_E_INVALID_URL: \b PublisherUrl is not a valid URL.
   *     \li \c UPNP_E_INVALID_PARAM: \b Timeout is not a valid pointer 
   *             or \b SubsId or \b PublisherUrl is \c NULL.
   *     \li \c UPNP_E_NETWORK_ERROR: A network error occured. 
   *     \li \c UPNP_E_SOCKET_WRITE: An error or timeout occurred writing 
   *             to a socket.
   *     \li \c UPNP_E_SOCKET_READ: An error or timeout occurred reading 
   *             from a socket.
   *     \li \c UPNP_E_SOCKET_BIND: An error occurred binding a socket.
   *     \li \c UPNP_E_SOCKET_CONNECT: An error occurred connecting to 
   *             \b PublisherUrl.
   *     \li \c UPNP_E_OUTOF_SOCKET: An error occurred creating a socket.
   *     \li \c UPNP_E_BAD_RESPONSE: An error occurred in response from 
   *             the publisher.
   *     \li \c UPNP_E_SUBSCRIBE_UNACCEPTED: The publisher refused 
   *             the subscription request.
   *     \li \c UPNP_E_OUTOF_MEMORY: Insufficient resources exist to 
   *             complete this operation.
   */
  EXPORT_SPEC int UpnpSubscribe(
  	/*! [in] The handle of the control point. */
  	UpnpClient_Handle Hnd,
  	/*! [in] The URL of the service to subscribe to. */
  	const char *PublisherUrl,
  	/*! [in,out]Pointer to a variable containing the requested subscription time.
  	 * Upon return, it contains the actual subscription time returned from
  	 * the service. */
  	int *TimeOut,
  	/*! [out] Pointer to a variable to receive the subscription ID (SID). */
  	Upnp_SID SubsId);
  
  /*!
   * \brief Performs the same operation as \b UpnpSubscribe, but returns
   * immediately and calls the registered callback function when the operation
   * is complete.
   *
   * Note that many of the error codes for this function are returned in
   * the \b UpnpEventSubscribe structure. In those cases, the function
   * returns \c UPNP_E_SUCCESS and the appropriate error code will
   * be in the <b>UpnpEventSubscribe.ErrCode</b> field in the \b Event
   * structure passed to the callback.
   *
   *  \return An integer representing one of the following:
   *      \li \c UPNP_E_SUCCESS: The operation completed successfully.
   *      \li \c UPNP_E_INVALID_HANDLE: The handle is not a valid control 
   *              point handle.
   *      \li \c UPNP_E_INVALID_URL: The \b PublisherUrl is not a valid 
   *              URL.
   *      \li \c UPNP_E_INVALID_PARAM: Either \b TimeOut or \b Fun or 
   *              \b PublisherUrl is not a valid pointer.
   *      \li \c UPNP_E_OUTOF_MEMORY: Insufficient resources exist to 
   *              complete this operation.
   *      \li \c UPNP_E_NETWORK_ERROR: A network error occured (returned in 
   *              the <b>UpnpEventSubscribe.ErrCode</b> field as part of the 
   *              callback).
   *      \li \c UPNP_E_SOCKET_WRITE: An error or timeout occurred writing 
   *              to a socket (returned in the 
   *              <b>UpnpEventSubscribe.ErrCode</b> field as part of the 
   *              callback).
   *      \li \c UPNP_E_SOCKET_READ: An error or timeout occurred reading 
   *              from a socket (returned in the 
   *              <b>UpnpEventSubscribe.ErrCode</b> field as part of the 
   *              callback).
   *      \li \c UPNP_E_SOCKET_BIND: An error occurred binding the socket 
   *              (returned in the <b>UpnpEventSubscribe.ErrCode</b> field as 
   *              part of the callback).
   *      \li \c UPNP_E_SOCKET_CONNECT: An error occurred connecting to 
   *              \b PublisherUrl (returned in the \b 
   *              UpnpEventSubscribe.ErrCode field as part of the callback).
   *      \li \c UPNP_E_OUTOF_SOCKET: An error occurred creating  the 
   *              socket (returned in the <b>UpnpEventSubscribe.ErrCode</b> 
   *              field as part of the callback).
   *      \li \c UPNP_E_BAD_RESPONSE: An error occurred in response from 
   *              the publisher (returned in the \b 
   *              UpnpEventSubscribe.ErrCode field as part of the callback).
   *      \li \c UPNP_E_SUBSCRIBE_UNACCEPTED: The publisher refused 
   *              the subscription request (returned in the \b 
   *              UpnpEventSubscribe.ErrCode field as part of the callback).
   */
  EXPORT_SPEC int UpnpSubscribeAsync(
  	/*! The handle of the control point that is subscribing. */
  	UpnpClient_Handle Hnd,
  	/*! The URL of the service to subscribe to. */
  	const char *PublisherUrl,
  	/*! The requested subscription time. Upon return, it contains the actual
  	 * subscription time returned from the service. */
  	int TimeOut,
  	/*! Pointer to the callback function for this subscribe request. */
  	Upnp_FunPtr Fun,
  	/*! A user data value passed to the callback function when invoked. */
  	const void *Cookie);
  
  /*!
   * \brief Removes the subscription of a control point from a service previously
   * subscribed to using \b UpnpSubscribe or \b UpnpSubscribeAsync.
   *
   * This is a synchronous call.
   *
   * \return An integer representing one of the following:
   *     \li \c UPNP_E_SUCCESS: The operation completed successfully.
   *     \li \c UPNP_E_INVALID_HANDLE: The handle is not a valid control 
   *             point handle.
   *     \li \c UPNP_E_INVALID_SID: The \b SubsId is not a valid 
   *             subscription ID.
   *     \li \c UPNP_E_NETWORK_ERROR: A network error occured. 
   *     \li \c UPNP_E_SOCKET_WRITE: An error or timeout occurred writing 
   *             to a socket.
   *     \li \c UPNP_E_SOCKET_READ: An error or timeout occurred reading 
   *             from a socket.
   *     \li \c UPNP_E_SOCKET_BIND: An error occurred binding a socket.
   *     \li \c UPNP_E_SOCKET_CONNECT: An error occurred connecting to 
   *             \b PublisherUrl.
   *     \li \c UPNP_E_OUTOF_SOCKET: An error ocurred creating a socket.
   *     \li \c UPNP_E_BAD_RESPONSE: An error occurred in response from 
   *             the publisher.
   *     \li \c UPNP_E_UNSUBSCRIBE_UNACCEPTED: The publisher refused 
   *             the unsubscribe request (the client is still unsubscribed and 
   *             no longer receives events).
   *     \li \c UPNP_E_OUTOF_MEMORY: Insufficient resources exist to 
   *             complete this operation.
   */
  EXPORT_SPEC int UpnpUnSubscribe(
  	/*! [in] The handle of the subscribed control point. */
  	UpnpClient_Handle Hnd,
  	/*! [in] The ID returned when the control point subscribed to the service. */
  	const Upnp_SID SubsId);
  
  /*!
   * \brief Removes a subscription of a control point from a service previously
   * subscribed to using \b UpnpSubscribe or \b UpnpSubscribeAsync, generating
   * a callback when the operation is complete.
   *
   * Note that many of the error codes for this function are returned in
   * the \b UpnpEventSubscribe structure.  In those cases, the function
   * returns \c UPNP_E_SUCCESS and the appropriate error code will
   * be in the <b>UpnpEventSubscribe.ErrCode</b> field in the \b Event
   * structure passed to the callback.
   *
   * \return An integer representing one of the following:
   *     \li \c UPNP_E_SUCCESS: The operation completed successfully.
   *     \li \c UPNP_E_INVALID_HANDLE: The handle is not a valid control 
   *             point handle.
   *     \li \c UPNP_E_INVALID_SID: The \b SubsId is not a valid SID.
   *     \li \c UPNP_E_INVALID_PARAM: \b Fun is not a valid callback 
   *             function pointer.
   *     \li \c UPNP_E_OUTOF_MEMORY: Insufficient resources exist to 
   *             complete this operation.
   *     \li \c UPNP_E_NETWORK_ERROR: A network error occured (returned in 
   *             the <b>UpnpEventSubscribe.ErrCode</b> field as part of the 
   *             callback).
   *     \li \c UPNP_E_SOCKET_WRITE: An error or timeout occurred writing 
   *             to a socket (returned in the <b>UpnpEventSubscribe.ErrCode</b>
   *             field as part of the callback).
   *     \li \c UPNP_E_SOCKET_READ: An error or timeout occurred reading 
   *             from a socket (returned in the 
   *             <b>UpnpEventSubscribe.ErrCode</b> field as part of the 
   *             callback).
   *     \li \c UPNP_E_SOCKET_BIND: An error occurred binding the socket 
   *             (returned in the <b>UpnpEventSubscribe.ErrCode</b> field as 
   *             part of the callback).
   *     \li \c UPNP_E_SOCKET_CONNECT: An error occurred connecting to 
   *             \b PublisherUrl (returned in the <b>UpnpEventSubscribe.ErrCode</b>
   *             field as part of the callback).
   *     \li \c UPNP_E_OUTOF_SOCKET: An error occurred creating a socket (
   *             returned in the <b>UpnpEventSubscribe.ErrCode</b> field as 
   *             part of the callback).
   *     \li \c UPNP_E_BAD_RESPONSE: An error occurred in response from 
   *             the publisher (returned in the <b>UpnpEventSubscribe.ErrCode</b>
   *             field as part of the callback).
   *     \li \c UPNP_E_UNSUBSCRIBE_UNACCEPTED: The publisher refused 
   *             the subscription request (returned in the
   *             <b>UpnpEventSubscribe.ErrCode</b> field as part of the callback).
   */
  EXPORT_SPEC int UpnpUnSubscribeAsync(
  	/*! [in] The handle of the subscribed control point. */
  	UpnpClient_Handle Hnd,
  	/*! [in] The ID returned when the control point subscribed to the service. */
  	Upnp_SID SubsId,
  	/*! [in] Pointer to a callback function to be called when the operation is
  	 * complete. */
  	Upnp_FunPtr Fun,
  	/*! [in] Pointer to user data to pass to the callback function when invoked. */
  	const void *Cookie);
  
  /*! @} Eventing */
  
  
  /******************************************************************************
   ******************************************************************************
   *                                                                            *
   *                        C L I E N T - A P I                                 *
   *                                                                            *
   ******************************************************************************
   ******************************************************************************/
  
  /*!
   * \name Control Point HTTP API
   *
   * @{
   */
  
  /*!
   * \brief Downloads a file specified in a URL.
   *
   * The SDK allocates the memory for \b outBuf and the application is
   * responsible for freeing this memory. Note that the item is passed as a
   * single buffer. Large items should not be transferred using this function.
   *
   *  \return An integer representing one of the following:
   *      \li \c UPNP_E_SUCCESS: The operation completed successfully.
   *      \li \c UPNP_E_INVALID_PARAM: Either \b url, \b outBuf 
   *              or \b contentType is not a valid pointer.
   *      \li \c UPNP_E_INVALID_URL: The \b url is not a valid 
   *              URL.
   *      \li \c UPNP_E_OUTOF_MEMORY: Insufficient resources exist to 
   *              download this file.
   *      \li \c UPNP_E_NETWORK_ERROR: A network error occurred.
   *      \li \c UPNP_E_SOCKET_WRITE: An error or timeout occurred writing 
   *              to a socket.
   *      \li \c UPNP_E_SOCKET_READ: An error or timeout occurred reading 
   *              from a socket.
   *      \li \c UPNP_E_SOCKET_BIND: An error occurred binding a socket.
   *      \li \c UPNP_E_SOCKET_CONNECT: An error occurred connecting a 
   *              socket.
   *      \li \c UPNP_E_OUTOF_SOCKET: Too many sockets are currently 
   *              allocated.
   */
  EXPORT_SPEC int UpnpDownloadUrlItem(
  	/*! [in] URL of an item to download. */
  	const char *url,
  	/*! [out] Buffer to store the downloaded item. */
  	char **outBuf,
  	/*! [out] HTTP header value content type if present. It should be at least
  	 * \c LINE_SIZE bytes in size. */
  	char *contentType);
  
  /*!
   * \brief Gets a file specified in a URL.
   *
   * The SDK allocates the memory for \b handle and \b contentType, the
   * application is responsible for freeing this memory.
   *
   * \return An integer representing one of the following:
   *     \li \c UPNP_E_SUCCESS: The operation completed successfully.
   *     \li \c UPNP_E_INVALID_PARAM: Either \b url, \b handle,  
   *             \b contentType, \b contentLength or \b httpStatus 
   *     	is not a valid pointer.
   *     \li \c UPNP_E_INVALID_URL: The \b url is not a valid 
   *             URL.
   *     \li \c UPNP_E_OUTOF_MEMORY: Insufficient resources exist to 
   *             download this file.
   *     \li \c UPNP_E_NETWORK_ERROR: A network error occurred.
   *     \li \c UPNP_E_SOCKET_WRITE: An error or timeout occurred writing 
   *             to a socket.
   *     \li \c UPNP_E_SOCKET_READ: An error or timeout occurred reading 
   *             from a socket.
   *     \li \c UPNP_E_SOCKET_BIND: An error occurred binding a socket.
   *     \li \c UPNP_E_SOCKET_CONNECT: An error occurred connecting a 
   *             socket.
   *     \li \c UPNP_E_OUTOF_SOCKET: Too many sockets are currently 
   *             allocated.
   *     \li \c UPNP_E_BAD_RESPONSE: A bad response was received from the 
   *             remote server.
   */
  EXPORT_SPEC int UpnpOpenHttpGet(
  	/*! [in] The URL of an item to get. */
  	const char *url,
  	/*! [in,out] A pointer to store the handle for this connection. */
  	void **handle,
  	/*! [in,out] A buffer to store the media type of the item. */
  	char **contentType,
  	/*! [in,out] A pointer to store the length of the item. */
  	int *contentLength,
  	/*! [in,out] The status returned on receiving a response message. */
  	int *httpStatus,
  	/*! [in] The time out value sent with the request during which a response
  	 * is expected from the server, failing which, an error is reported
  	 * back to the user. */		 
  	int timeout);
  
  /*!
   * \brief Gets a file specified in a URL through the specified proxy.
   *
   * The SDK allocates the memory for \b handle and \b contentType, the
   * application is responsible for freeing this memory.
   *
   * \return An integer representing one of the following:
   *     \li \c UPNP_E_SUCCESS: The operation completed successfully.
   *     \li \c UPNP_E_INVALID_PARAM: Either \b url, \b handle,  
   *             \b contentType, \b contentLength or \b httpStatus 
   *     	is not a valid pointer.
   *     \li \c UPNP_E_INVALID_URL: The \b url is not a valid 
   *             URL.
   *     \li \c UPNP_E_OUTOF_MEMORY: Insufficient resources exist to 
   *             download this file.
   *     \li \c UPNP_E_NETWORK_ERROR: A network error occurred.
   *     \li \c UPNP_E_SOCKET_WRITE: An error or timeout occurred writing 
   *             to a socket.
   *     \li \c UPNP_E_SOCKET_READ: An error or timeout occurred reading 
   *             from a socket.
   *     \li \c UPNP_E_SOCKET_BIND: An error occurred binding a socket.
   *     \li \c UPNP_E_SOCKET_CONNECT: An error occurred connecting a 
   *             socket.
   *     \li \c UPNP_E_OUTOF_SOCKET: Too many sockets are currently 
   *             allocated.
   *     \li \c UPNP_E_BAD_RESPONSE: A bad response was received from the 
   *	       remote server.
   */
  EXPORT_SPEC int UpnpOpenHttpGetProxy(
  	/*! [in] The URL of an item to get. */
  	const char *url,
  	/*! [in] The URL of the proxy. */
  	const char *proxy_str,
  	/*! [in,out] A pointer to store the handle for this connection. */
  	void **handle,
  	/*! [in,out] A buffer to store the media type of the item. */
  	char **contentType,
  	/*! [in,out] A pointer to store the length of the item. */
  	int *contentLength,
  	/*! [in,out] The status returned on receiving a response message. */
  	int *httpStatus,
  	/*! [in] The time out value sent with the request during which a response
  	 * is expected from the server, failing which, an error is reported
  	 * back to the user. */		 
  	int timeout);
  
  /*!
   * \brief Gets specified number of bytes from a file specified in the URL.
   *
   * The number of bytes is specified through a low count and a high count which
   * are passed as a range of bytes for the request. The SDK allocates the memory
   * for \b handle and \b contentType, the application is responsible for freeing
   * this memory.
   *
   *  \return An integer representing one of the following:
   *      \li \c UPNP_E_SUCCESS: The operation completed successfully.
   *      \li \c UPNP_E_INVALID_PARAM: Either \b url, \b handle,  
   *              \b contentType, \b contentLength or \b httpStatus 
   *		is not a valid pointer.
   *      \li \c UPNP_E_INVALID_URL: The \b url is not a valid 
   *              URL.
   *      \li \c UPNP_E_OUTOF_MEMORY: Insufficient resources exist to 
   *              download this file.
   *      \li \c UPNP_E_NETWORK_ERROR: A network error occurred.
   *      \li \c UPNP_E_SOCKET_WRITE: An error or timeout occurred writing 
   *              to a socket.
   *      \li \c UPNP_E_SOCKET_READ: An error or timeout occurred reading 
   *              from a socket.
   *      \li \c UPNP_E_SOCKET_BIND: An error occurred binding a socket.
   *      \li \c UPNP_E_SOCKET_CONNECT: An error occurred connecting a 
   *              socket.
   *      \li \c UPNP_E_OUTOF_SOCKET: Too many sockets are currently 
   *              allocated.
   *	\li \c UPNP_E_BAD_RESPONSE: A bad response was received from the 
   *	        remote server.
   */
  EXPORT_SPEC int UpnpOpenHttpGetEx(
  	/*! [in] The URL of the item to get. */
  	const char *url,
  	/*! [in,out] A pointer to store the handle for this connection. */
  	void **handle,
  	/*! [in,out] A buffer to store the media type of the item. */
  	char **contentType,
  	/*! [in,out] A buffer to store the length of the item. */
  	int *contentLength,
  	/*! [in,out] The status returned on receiving a response message from the remote server. */
  	int *httpStatus,
  	/*! [in] An integer value representing the low end of a range to retrieve. */
  	int lowRange,
  	/*! [in] An integer value representing the high end of a range to retrieve. */
  	int highRange,
  	/*! [in] A time out value sent with the request during which a response is
  	 * expected from the server, failing which, an error is reported back
  	 * to the user. */	
  	int timeout);
  
  /*!
   * \brief Gets specified number of bytes from a file specified in a URL. 
   *
   *  \return An integer representing one of the following:
   *      \li \c UPNP_E_SUCCESS: The operation completed successfully.
   *      \li \c UPNP_E_INVALID_PARAM: Either \b handle, \b buf 
   *              or \b size is not a valid pointer.
   *	    \li \c UPNP_E_BAD_RESPONSE: A bad response was received from the 
   *	            remote server.
   *      \li \c UPNP_E_BAD_HTTPMSG: Either the request or response was in 
   *              the incorrect format.
   *      \li \c UPNP_E_CANCELED: another thread called UpnpCancelHttpGet.
   *
   *  Note: In case of return values, the status code parameter of the passed 
   *        in handle value may provide additional information on the return 
   *        value.
   */
  EXPORT_SPEC int UpnpReadHttpGet(
  	/*! [in] The token created by the call to \b UpnpOpenHttpGet. */
  	void *handle,
  	/*! [in,out] The buffer to store the read item. */
  	char *buf,
  	/*! [in,out] The size of the buffer to be read. */
  	size_t *size,
  	/*! [in] The time out value sent with the request during which a response is
  	 * expected from the server, failing which, an error is reported back to
  	 * the user. */
  	int timeout);
  
  /*!
   * \brief Retrieve progress information of a http-get transfer. 
   *
   * \return An integer representing one of the following:
   *     \li \c UPNP_E_SUCCESS: The operation completed successfully.
   *     \li \c UPNP_E_INVALID_PARAM: Either \b handle, \b length 
   *		or \b total is not a valid pointer.
   */
  EXPORT_SPEC int UpnpHttpGetProgress(
  	/*! [in] The token created by the call to \b UpnpOpenHttpGet. */
  	void *handle,
  	/*! [out] The number of bytes received. */
  	size_t *length,
  	/*! [out] The content length. */
  	size_t *total);
  
  /*!
   * \brief Set the cancel flag of the \b handle parameter. 
   *
   * \return An integer representing one of the following:
   *      \li \c UPNP_E_SUCCESS: The operation completed successfully.
   *      \li \c UPNP_E_INVALID_PARAM: \b handle is not a valid pointer.
   */  
  EXPORT_SPEC int UpnpCancelHttpGet(
  	/*! [in] The handle of the connection created by the call to
  	 * \b UpnpOpenHttpGet. */
  	void *handle);
  
  /*!
   * \brief Closes the connection and frees memory that was allocated for the
   * \b handle parameter.
   *
   * \return An integer representing one of the following:
   *      \li \c UPNP_E_SUCCESS: The operation completed successfully.
   *      \li \c UPNP_E_INVALID_PARAM: \b handle is not a valid pointer.
   */  
  EXPORT_SPEC int UpnpCloseHttpGet(
  	/*! [in] The handle of the connection created by the call to
  	 * \b UpnpOpenHttpGet. */
  	void *handle);
  
  /*!
   * \brief Makes an HTTP POST request message, opens a connection to the server
   * and sends the POST request to the server if the connection to the server
   * succeeds.
   *
   * The SDK allocates the memory for \b handle and \b contentType, the
   * application is responsible for freeing this memory.
   *
   *  \return An integer representing one of the following:
   *      \li \c UPNP_E_SUCCESS: The operation completed successfully.
   *      \li \c UPNP_E_INVALID_PARAM: Either \b url, \b handle 
   *              or \b contentType is not a valid pointer.
   *      \li \c UPNP_E_INVALID_URL: The \b url is not a valid 
   *              URL.
   *      \li \c UPNP_E_OUTOF_MEMORY: Insufficient resources exist to 
   *              download this file.
   *      \li \c UPNP_E_SOCKET_ERROR: Error occured allocating a socket and 
   *		resources or an error occurred binding a socket.
   *      \li \c UPNP_E_SOCKET_WRITE: An error or timeout occurred writing 
   *              to a socket.
   *      \li \c UPNP_E_SOCKET_CONNECT: An error occurred connecting a 
   *              socket.
   *      \li \c UPNP_E_OUTOF_SOCKET: Too many sockets are currently 
   *              allocated.
   */
  EXPORT_SPEC int UpnpOpenHttpPost(
  	/*! [in] The URL in which to send the POST request. */
  	const char *url,
  	/*! [in,out] A pointer in which to store the handle for this connection. This
  	 * handle is required for futher operations over this connection. */
  	void **handle,
  	/*! [in] A buffer to store the media type of content being sent. */
  	const char *contentType,
  	/*! [in] The length of the content, in bytes, being posted. */
  	int contentLength,
  	/*! [in] The time out value sent with the request during which a response
  	 * is expected from the receiver, failing which, an error is reported. */
  	int timeout);
  
  /*!
   * \brief Sends a request to a server to copy the contents of a buffer to the
   * URI specified in the \b UpnpOpenHttpPost call.
   *
   *  \return An integer representing one of the following:
   *      \li \c UPNP_E_SUCCESS: The operation completed successfully.
   *      \li \c UPNP_E_INVALID_PARAM: Either \b handle, \b buf 
   *              or \b size is not a valid pointer.
   *      \li \c UPNP_E_SOCKET_WRITE: An error or timeout occurred writing 
   *              to a socket.
   *      \li \c UPNP_E_OUTOF_SOCKET: Too many sockets are currently 
   *              allocated.
   */
  EXPORT_SPEC int UpnpWriteHttpPost(
  	/*! [in] The handle of the connection created by the call to
  	 * \b UpnpOpenHttpPost. */
  	void *handle,
  	/*! [in] The buffer to be posted. */
  	char *buf,
  	/*! [in] The size, in bytes of \b buf. */
  	size_t *size,
  	/*! [in] A timeout value sent with the request during which a response is
  	 * expected from the server, failing which, an error is reported. */		 
  	int timeout);
  
  /*!
   * \brief Sends and receives any pending data, closes the connection with the
   * server, and frees memory allocated during the \b UpnpOpenHttpPost call.
   *
   * \return An integer representing one of the following:
   *     \li \c UPNP_E_SUCCESS: The operation completed successfully.
   *     \li \c UPNP_E_INVALID_PARAM: Either \b handle, or 
   *     			\b httpStatus is not a valid pointer.
   *     \li \c UPNP_E_SOCKET_READ: An error or timeout occurred reading 
   *             from a socket.
   *     \li \c UPNP_E_OUTOF_SOCKET: Too many sockets are currently 
   *             allocated.
   */
  EXPORT_SPEC int UpnpCloseHttpPost(
  	/*! [in] The handle of the connection to close, created by the call to
  	 * \b UpnpOpenHttpPost. */
  	void *handle,
  	/*! [in,out] A pointer to a buffer to store the final status of the connection. */
  	int *httpStatus,
  	/*! [in] A time out value sent with the request during which a response is
  	 * expected from the server, failing which, an error is reported. */		 
  	int timeout);
  
  /*! @} Control Point HTTP API */
  
  /******************************************************************************
   ******************************************************************************
   *                                                                            *
   *                    W E B  S E R V E R  A P I                               *
   *                                                                            *
   ******************************************************************************
   ******************************************************************************/
  
  /*!
   * \name Web Server API
   * 
   * @{
   */
  
  /*!
   * \brief Sets the document root directory for the internal web server.
   *
   * This directory is considered the root directory (i.e. "/") of the web server.
   *
   * This function also activates or deactivates the web server. To disable the
   * web server, pass \c NULL for \b rootDir; to activate, pass a valid directory
   * string.
   * 
   * \note This function is not available when the web server is not compiled
   * 	into the UPnP Library.
   *
   * \return An integer representing one of the following:
   *       \li \c UPNP_E_SUCCESS: The operation completed successfully.
   *       \li \c UPNP_E_INVALID_ARGUMENT: \b rootDir is an invalid directory.
   */
  EXPORT_SPEC int UpnpSetWebServerRootDir( 
  	/*! [in] Path of the root directory of the web server. */
  	const char *rootDir);
  
  /*!
   * \brief The type of handle returned by the web server for open requests.
   */
  typedef void *UpnpWebFileHandle;
  
  /*!
   * \brief Get-info callback function prototype.
   */
  typedef int (*VDCallback_GetInfo)(
  		/*! [in] The name of the file to query. */
  		const char *filename,
  		/*! [out] Pointer to a structure to store the information on the file. */
  #if UPNP_VERSION < 10800
  		struct File_Info *info
  #else
  		UpnpFileInfo *info
  #endif /* UPNP_VERSION < 10800 */
  		);
  
  /*!
   * \brief Sets the get_info callback function to be used to access a virtual
   * directory.
   * 
   * \return An integer representing one of the following:
   *       \li \c UPNP_E_SUCCESS: The operation completed successfully.
   *       \li \c UPNP_E_INVALID_ARGUMENT: \b callback is not a valid pointer.
   */
  EXPORT_SPEC int UpnpVirtualDir_set_GetInfoCallback(VDCallback_GetInfo callback);
  
  /*!
   * \brief Open callback function prototype.
   */
  typedef UpnpWebFileHandle (*VDCallback_Open)(
  		/*! [in] The name of the file to open. */ 
  		const char *filename,
  		/*! [in] The mode in which to open the file.
  		 * Valid values are \c UPNP_READ or \c UPNP_WRITE. */
  		enum UpnpOpenFileMode Mode);
  
  /*!
   * \brief Sets the open callback function to be used to access a virtual
   * directory.
   *
   * \return An integer representing one of the following:
   *       \li \c UPNP_E_SUCCESS: The operation completed successfully.
   *       \li \c UPNP_E_INVALID_ARGUMENT: \b callback is not a valid pointer.
   */
  EXPORT_SPEC int UpnpVirtualDir_set_OpenCallback(VDCallback_Open callback);
  
  /*!
   * \brief Read callback function prototype.
   */
  typedef int (*VDCallback_Read)(
  	/*! [in] The handle of the file to read. */
  	UpnpWebFileHandle fileHnd,
  	/*! [out] The buffer in which to place the data. */
  	char *buf,
  	/*! [in] The size of the buffer (i.e. the number of bytes to read). */
  	size_t buflen);
  
  /*! 
   * \brief Sets the read callback function to be used to access a virtual
   * directory.
   *
   *  \return An integer representing one of the following:
   *       \li \c UPNP_E_SUCCESS: The operation completed successfully.
   *       \li \c UPNP_E_INVALID_ARGUMENT: \b callback is not a valid pointer.
   */
  EXPORT_SPEC int UpnpVirtualDir_set_ReadCallback(VDCallback_Read callback);
  
  /*!
   * \brief Write callback function prototype.
   */
  typedef	int (*VDCallback_Write)(
  	/*! [in] The handle of the file to write. */
  	UpnpWebFileHandle fileHnd,
  	/*! [in] The buffer with the bytes to write. */
  	char *buf,
  	/*! [in] The number of bytes to write. */
  	size_t buflen);
  
  /*!
   * \brief Sets the write callback function to be used to access a virtual
   * directory.
   *
   * \return An integer representing one of the following:
   *       \li \c UPNP_E_SUCCESS: The operation completed successfully.
   *       \li \c UPNP_E_INVALID_ARGUMENT: \b callback is not a valid pointer.
   */
  EXPORT_SPEC int UpnpVirtualDir_set_WriteCallback(VDCallback_Write callback);
  
  /*!
   * \brief Seek callback function prototype.
   */
  typedef int (*VDCallback_Seek) (
  	/*! [in] The handle of the file to move the file pointer. */
  	UpnpWebFileHandle fileHnd,
  	/*! [in] The number of bytes to move in the file.  Positive values
  	 * move foward and negative values move backward.  Note that
  	 * this must be positive if the \b origin is \c SEEK_SET. */
  	off_t offset,
  	/*! [in] The position to move relative to.  It can be \c SEEK_CUR
  	 * to move relative to the current position, \c SEEK_END to
  	 * move relative to the end of the file, or \c SEEK_SET to
  	 * specify an absolute offset. */
  	int origin);
  
  /*!
   * \brief Sets the seek callback function to be used to access a virtual
   * directory.
   *
   *  \return An integer representing one of the following:
   *       \li \c UPNP_E_SUCCESS: The operation completed successfully.
   *       \li \c UPNP_E_INVALID_ARGUMENT: \b callback is not a valid pointer.
   */
  EXPORT_SPEC int UpnpVirtualDir_set_SeekCallback(VDCallback_Seek callback);
  
  /*!
   * \brief Close callback function prototype.
   */
  typedef int (*VDCallback_Close)(
  		/*! [in] The handle of the file to close. */
  		UpnpWebFileHandle fileHnd);
  
  /*!
   * \brief Sets the close callback function to be used to access a virtual
   * directory.
   *
   * \return An integer representing one of the following:
   *       \li \c UPNP_E_SUCCESS: The operation completed successfully.
   *       \li \c UPNP_E_INVALID_ARGUMENT: \b callback is not a valid pointer.
   */
  EXPORT_SPEC int UpnpVirtualDir_set_CloseCallback(VDCallback_Close callback);
  
  /*!
   * \brief The {\bf UpnpVirtualDirCallbacks} structure contains the pointers to
   *  file-related callback functions a device application can register to
   *  virtualize URLs.
   */
  struct UpnpVirtualDirCallbacks
  {
  	VDCallback_GetInfo get_info;
  	VDCallback_Open open;
  	VDCallback_Read read;
  	VDCallback_Write write;
  	VDCallback_Seek seek;
  	VDCallback_Close close;
  };
  
  /*!
   * \brief Enables or disables the webserver.
   *
   * \return An integer representing one of the following:
   *       \li \c UPNP_E_SUCCESS: The operation completed successfully.
   *       \li \c UPNP_E_INVALID_ARGUMENT: \b enable is not valid.
   */
  EXPORT_SPEC int UpnpEnableWebserver(
  	/*! [in] \c TRUE to enable, \c FALSE to disable. */
  	int enable);
  
  /*!
   * \brief Returns \c TRUE if the webserver is enabled, or \c FALSE if it is not.
   *
   *  \return An integer representing one of the following:
   *       \li \c TRUE: The webserver is enabled.
   *       \li \c FALSE: The webserver is not enabled
   */
  EXPORT_SPEC int UpnpIsWebserverEnabled(void);
  
  /*!
   *  \brief Sets the callback functions to be used to access a virtual directory.
   *
   *  \return An integer representing one of the following:
   *       \li \c UPNP_E_SUCCESS: The operation completed successfully.
   *       \li \c UPNP_E_INVALID_PARAM: one of the callbacks is not valid.
   */
  EXPORT_SPEC int UpnpSetVirtualDirCallbacks(
  	/*! [in] A structure that contains the callback functions. */
  	struct UpnpVirtualDirCallbacks *callbacks );
  
  /*!
   * \brief Adds a virtual directory mapping.
   *
   * All webserver requests containing the given directory are read using
   * functions contained in a \b VirtualDirCallbacks structure registered
   * via \b UpnpSetVirtualDirCallbacks.
   *
   * \note This function is not available when the web server is not
   * 	compiled into the UPnP Library.
   *
   * \return An integer representing one of the following:
   *       \li \c UPNP_E_SUCCESS: The operation completed successfully.
   *       \li \c UPNP_E_INVALID_ARGUMENT: \b dirName is not valid.
   */
  EXPORT_SPEC int UpnpAddVirtualDir(
  	/*! [in] The name of the new directory mapping to add. */
  	const char *dirName);
  
  /*!
   * \brief Removes a virtual directory mapping made with \b UpnpAddVirtualDir.
   *
   * \return An integer representing one of the following:
   *       \li \c UPNP_E_SUCCESS: The operation completed successfully.
   *       \li \c UPNP_E_INVALID_ARGUMENT: \b dirName is not valid.
   */
  EXPORT_SPEC int UpnpRemoveVirtualDir(
  	/*! [in] The name of the virtual directory mapping to remove. */
  	const char *dirName);
  
  /*!
   * \brief Removes all virtual directory mappings.
   */
  EXPORT_SPEC void UpnpRemoveAllVirtualDirs(void);
  
  /* @} Web Server API */
  
  #ifdef __cplusplus
  }
  #endif /* __cplusplus */
  
  /* @} UPnPAPI UPnP API */
  
  #endif /* UPNP_H */
  