⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 upnpapi.c

📁 电驴下载工具eMule0.47aVeryCD的源代码,可作分析测试也可用于P2P软件的开发研究.
💻 C
📖 第 1 页 / 共 5 页
字号:
///////////////////////////////////////////////////////////////////////////
//
// 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"
#ifndef _WIN32
#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>
#else
#include <winsock2.h>
#include <Ws2tcpip.h>
#endif

#include "httpreadwrite.h"

//************************************
//Needed for GENA
#include "gena.h"
#include "gena_device.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 side
CLIENTONLY( 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;
#ifdef _WIN32
	WORD wVersionRequested;
	WSADATA wsaData;
	int err;
#endif

    if( UpnpSdkInit == 1 ) {
        // already initialized
        return UPNP_E_INIT;
    }

#ifdef _WIN32
	wVersionRequested = MAKEWORD( 2, 2 );

	err = WSAStartup( wVersionRequested, &wsaData );
	if ( err != 0 ) {
		/* Tell the user that we could not find a usable */
		/* WinSock DLL.                                  */
		return UPNP_E_INIT_FAILED;
	}

	/* Confirm that the WinSock DLL supports 2.2.*/
	/* Note that if the DLL supports versions greater    */
	/* than 2.2 in addition to 2.2, it will still return */
	/* 2.2 in wVersion since that is the version we      */
	/* requested.                                        */
	 
	if ( LOBYTE( wsaData.wVersion ) != 2 ||
			HIBYTE( wsaData.wVersion ) != 2 ) {
		/* Tell the user that we could not find a usable */
		/* WinSock DLL.                                  */
		WSACleanup( );
		return UPNP_E_INIT_FAILED; 
	}

	/* The WinSock DLL is acceptable. Proceed. */
#endif

    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.
 *****************************************************************************/
int
UpnpFinish(  )
{
    DEVICEONLY( UpnpDevice_Handle device_handle;
         )
        CLIENTONLY( UpnpClient_Handle client_handle;
         )
    struct Handle_Info *temp;

    DBGONLY( ThreadPoolStats stats;
         )

#ifdef _WIN32
//	WSACleanup( );
#endif

        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(  );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -