?? upnpapi.c
字號:
/////////////////////////////////////////////////////////////////////////////// Copyright (c) 2000-2003 Intel Corporation // All rights reserved. //// Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: //// * Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // * Neither name of Intel Corporation nor the names of its contributors // may be used to endorse or promote products derived from this software // without specific prior written permission.// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY // OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.///////////////////////////////////////////////////////////////////////////////File upnpapi.c#include <assert.h>#include <signal.h>#include <stdlib.h>#include <string.h>#include <sys/stat.h>#include "config.h"#include "upnpapi.h"#include "httpreadwrite.h"#include "ssdplib.h"#include "soaplib.h"#include "ThreadPool.h"#include "membuffer.h"#include <sys/ioctl.h>#include <linux/if.h>#include <sys/utsname.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <unistd.h>#include "httpreadwrite.h"//************************************//Needed for GENA#include "gena.h"#include "service_table.h"#include "miniserver.h"//*******************************************/* ********************* */#ifdef INTERNAL_WEB_SERVER#include "webserver.h"#include "urlconfig.h"#endif // INTERNAL_WEB_SERVER/* ****************** *///Mutex to synchronize the subscription handling at the client sideCLIENTONLY( ithread_mutex_t GlobalClientSubscribeMutex; ) //Mutex to synchronize handles ( root device or control point handle) ithread_mutex_t GlobalHndMutex;//Mutex to synchronize the uuid creation process ithread_mutex_t gUUIDMutex; TimerThread gTimerThread; ThreadPool gRecvThreadPool; ThreadPool gSendThreadPool;//Flag to indicate the state of web server WebServerState bWebServerState = WEB_SERVER_DISABLED;// static buffer to store the local host ip address or host name char LOCAL_HOST[LINE_SIZE];// local port for the mini-server unsigned short LOCAL_PORT;// UPnP device and control point handle table void *HandleTable[NUM_HANDLE];//This structure is for virtual directory callbacks struct UpnpVirtualDirCallbacks virtualDirCallback;// a local dir which serves as webserver root extern membuffer gDocumentRootDir;// Maximum content-length that the SDK will process on an incoming packet. // Content-Length exceeding this size will be not processed and error 413 // (HTTP Error Code) will be returned to the remote end point. int g_maxContentLength = DEFAULT_SOAP_CONTENT_LENGTH;// Global variable to denote the state of Upnp SDK // = 0 if uninitialized, = 1 if initialized. int UpnpSdkInit = 0;// Global variable to denote the state of Upnp SDK device registration.// = 0 if unregistered, = 1 if registered. int UpnpSdkDeviceRegistered = 0;// Global variable to denote the state of Upnp SDK client registration.// = 0 if unregistered, = 1 if registered. int UpnpSdkClientRegistered = 0;/**************************************************************************** * Function: UpnpInit * * Parameters: * IN const char * HostIP: Local IP Address * IN short DestPort: Local Port to listen for incoming connections * Description: * Initializes * - Mutex objects, * - Handle Table * - Thread Pool and Thread Pool Attributes * - MiniServer(starts listening for incoming requests) * and WebServer (Sends request to the * Upper Layer after HTTP Parsing) * - Checks for IP Address passed as an argument. IF NULL, * gets local host name * - Sets GENA and SOAP Callbacks. * - Starts the timer thread. * * Returns: * UPNP_E_SUCCESS on success, nonzero on failure. * UPNP_E_INIT_FAILED if Initialization fails. * UPNP_E_INIT if UPnP is already initialized *****************************************************************************/ int UpnpInit( IN const char *HostIP, IN unsigned short DestPort ){ int retVal = 0; ThreadPoolAttr attr; if( UpnpSdkInit == 1 ) { // already initialized return UPNP_E_INIT; } membuffer_init( &gDocumentRootDir ); srand( time( NULL ) ); // needed by SSDP or other parts DBGONLY( if( InitLog( ) != UPNP_E_SUCCESS ) return UPNP_E_INIT_FAILED; ); DBGONLY( UpnpPrintf ( UPNP_INFO, API, __FILE__, __LINE__, "Inside UpnpInit \n" ); ) //initialize mutex if( ithread_mutex_init( &GlobalHndMutex, NULL ) != 0 ) { return UPNP_E_INIT_FAILED; } if( ithread_mutex_init( &gUUIDMutex, NULL ) != 0 ) { return UPNP_E_INIT_FAILED; } //initialize subscribe mutex CLIENTONLY( if ( ithread_mutex_init( &GlobalClientSubscribeMutex, NULL ) != 0 ) { return UPNP_E_INIT_FAILED;} ) HandleLock( ); if( HostIP != NULL ) strcpy( LOCAL_HOST, HostIP ); else { if( getlocalhostname( LOCAL_HOST ) != UPNP_E_SUCCESS ) { HandleUnlock( ); return UPNP_E_INIT_FAILED; } } if( UpnpSdkInit != 0 ) { HandleUnlock( ); return UPNP_E_INIT; } InitHandleList( ); HandleUnlock( ); TPAttrInit( &attr ); TPAttrSetMaxThreads( &attr, MAX_THREADS ); TPAttrSetMinThreads( &attr, MIN_THREADS ); TPAttrSetJobsPerThread( &attr, JOBS_PER_THREAD ); TPAttrSetIdleTime( &attr, THREAD_IDLE_TIME ); if( ThreadPoolInit( &gSendThreadPool, &attr ) != UPNP_E_SUCCESS ) { UpnpSdkInit = 0; UpnpFinish( ); return UPNP_E_INIT_FAILED; } if( ThreadPoolInit( &gRecvThreadPool, &attr ) != UPNP_E_SUCCESS ) { UpnpSdkInit = 0; UpnpFinish( ); return UPNP_E_INIT_FAILED; } UpnpSdkInit = 1;#if EXCLUDE_SOAP == 0 DEVICEONLY( SetSoapCallback( soap_device_callback ); );#endif#if EXCLUDE_GENA == 0 SetGenaCallback( genaCallback );#endif if( ( retVal = TimerThreadInit( &gTimerThread, &gSendThreadPool ) ) != UPNP_E_SUCCESS ) { UpnpSdkInit = 0; UpnpFinish( ); return retVal; }#if EXCLUDE_MINISERVER == 0 if( ( retVal = StartMiniServer( DestPort ) ) <= 0 ) { DBGONLY( UpnpPrintf( UPNP_CRITICAL, API, __FILE__, __LINE__, "Miniserver failed to start" ); ) UpnpFinish( ); UpnpSdkInit = 0; if( retVal != -1 ) return retVal; else // if miniserver is already running for unknown reasons! return UPNP_E_INIT_FAILED; }#endif DestPort = retVal; LOCAL_PORT = DestPort;#if EXCLUDE_WEB_SERVER == 0 if( ( retVal = UpnpEnableWebserver( WEB_SERVER_ENABLED ) ) != UPNP_E_SUCCESS ) { UpnpFinish( ); UpnpSdkInit = 0; return retVal; }#endif DBGONLY( UpnpPrintf( UPNP_INFO, API, __FILE__, __LINE__, "Host Ip: %s Host Port: %d\n", LOCAL_HOST, LOCAL_PORT ) ); DBGONLY( UpnpPrintf ( UPNP_INFO, API, __FILE__, __LINE__, "Exiting UpnpInit \n" ); ) return UPNP_E_SUCCESS;} /***************** end of UpnpInit ******************//**************************************************************************** * Function: UpnpFinish * * Parameters: NONE * * Description: * Checks for pending jobs and threads * Unregisters either the client or device * Shuts down the Timer Thread * Stops the Mini Server * Uninitializes the Thread Pool * For Win32 cleans up Winsock Interface * Cleans up mutex objects * * Return Values: * UPNP_E_SUCCESS on success, nonzero on failure. *****************************************************************************/intUpnpFinish( ){ DEVICEONLY( UpnpDevice_Handle device_handle; ) CLIENTONLY( UpnpClient_Handle client_handle; ) struct Handle_Info *temp; DBGONLY( ThreadPoolStats stats; ) if( UpnpSdkInit != 1 ) return UPNP_E_FINISH; DBGONLY( UpnpPrintf( UPNP_INFO, API, __FILE__, __LINE__, "Inside UpnpFinish : UpnpSdkInit is :%d:\n", UpnpSdkInit ); if( UpnpSdkInit == 1 ) { UpnpPrintf( UPNP_INFO, API, __FILE__, __LINE__, "UpnpFinish : UpnpSdkInit is ONE\n" );} ThreadPoolGetStats( &gRecvThreadPool, &stats ); UpnpPrintf( UPNP_INFO, API, __FILE__, __LINE__, "Recv Thread Pool \n High Jobs pending = %d" " \nMed Jobs Pending = %d\n Low Jobs Pending = %d \nWorker Threads" " = %d\nIdle Threads = %d\nPersistent Threads = %d\nAverage Time " "spent in High Q = %lf\nAverage Time spent in Med Q = %lf\nAverage" " Time spent in Low Q = %lf\nMax Threads Used: %d\nTotal Work Time" "= %lf\nTotal Idle Time = %lf\n", stats.currentJobsHQ, stats.currentJobsMQ, stats.currentJobsLQ, stats.persistentThreads, stats.avgWaitHQ, stats.avgWaitMQ, stats.avgWaitLQ, stats.maxThreads, stats.totalWorkTime, stats.totalIdleTime ); ThreadPoolGetStats( &gSendThreadPool, &stats ); UpnpPrintf( UPNP_INFO, API, __FILE__, __LINE__, "Send Thread Pool \n High Jobs pending = %d" " \nMed Jobs Pending = %d\n Low Jobs Pending = %d \nWorker Threads" " = %d\nIdle Threads = %d\nPersistent Threads = %d\nAverage Time " "spent in High Q = %lf\nAverage Time spent in Med Q = %lf\nAverage" " Time spent in Low Q = %lf\nMax Threads Used: %d\nTotal Work Time" "= %lf\nTotal Idle Time = %lf\n", stats.currentJobsHQ, stats.currentJobsMQ, stats.currentJobsLQ, stats.persistentThreads, stats.avgWaitHQ, stats.avgWaitMQ, stats.avgWaitLQ, stats.maxThreads, stats.totalWorkTime, stats.totalIdleTime ); )#ifdef INCLUDE_DEVICE_APIS if( GetDeviceHandleInfo( &device_handle, &temp ) == HND_DEVICE ) UpnpUnRegisterRootDevice( device_handle );#endif#ifdef INCLUDE_CLIENT_APIS if( GetClientHandleInfo( &client_handle, &temp ) == HND_CLIENT ) UpnpUnRegisterClient( client_handle );#endif TimerThreadShutdown( &gTimerThread ); StopMiniServer( );#if EXCLUDE_WEB_SERVER == 0 web_server_destroy( );#endif ThreadPoolShutdown( &gSendThreadPool ); ThreadPoolShutdown( &gRecvThreadPool ); DBGONLY( UpnpPrintf( UPNP_INFO, API, __FILE__, __LINE__, "Exiting UpnpFinish : UpnpSdkInit is :%d:\n", UpnpSdkInit ); ThreadPoolGetStats( &gRecvThreadPool, &stats ); UpnpPrintf( UPNP_INFO, API, __FILE__, __LINE__, "Recv Thread Pool \n High Jobs pending = %d" " \nMed Jobs Pending = %d\n Low Jobs Pending = %d \nWorker Threads" " = %d\nIdle Threads = %d\nPersistent Threads = %d\nAverage Time " "spent in High Q = %lf\nAverage Time spent in Med Q = %lf\nAverage" " Time spent in Low Q = %lf\nMax Threads Used: %d\nTotal Work Time" "= %lf\nTotal Idle Time = %lf\n", stats.currentJobsHQ, stats.currentJobsMQ, stats.currentJobsLQ, stats.persistentThreads, stats.avgWaitHQ, stats.avgWaitMQ, stats.avgWaitLQ, stats.maxThreads, stats.totalWorkTime, stats.totalIdleTime ); ThreadPoolGetStats( &gSendThreadPool, &stats ); UpnpPrintf( UPNP_INFO, API, __FILE__, __LINE__, "Send Thread Pool \n High Jobs pending = %d" " \nMed Jobs Pending = %d\n Low Jobs Pending = %d \nWorker Threads" " = %d\nIdle Threads = %d\nPersistent Threads = %d\nAverage Time " "spent in High Q = %lf\nAverage Time spent in Med Q = %lf\nAverage" " Time spent in Low Q = %lf\nMax Threads Used: %d\nTotal Work Time" "= %lf\nTotal Idle Time = %lf\n", stats.currentJobsHQ, stats.currentJobsMQ, stats.currentJobsLQ, stats.persistentThreads, stats.avgWaitHQ, stats.avgWaitMQ, stats.avgWaitLQ, stats.maxThreads, stats.totalWorkTime, stats.totalIdleTime ); ) // DBGONLY DBGONLY( CloseLog( ); ); CLIENTONLY( ithread_mutex_destroy( &GlobalClientSubscribeMutex ); ) ithread_mutex_destroy( &GlobalHndMutex ); ithread_mutex_destroy( &gUUIDMutex ); // remove all virtual dirs UpnpRemoveAllVirtualDirs( ); UpnpSdkInit = 0; return UPNP_E_SUCCESS;} /********************* End of UpnpFinish *************************//**************************************************************************** * Function: UpnpGetServerPort * * Parameters: NONE * * Description: * Gives back the miniserver port. * * Return Values: * local port on success, zero on failure. *****************************************************************************/unsigned shortUpnpGetServerPort( void ){ if( UpnpSdkInit != 1 ) return 0; return LOCAL_PORT;}/*************************************************************************** * Function: UpnpGetServerIpAddress * * Parameters: NONE
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -