📄 upnpapi.c
字号:
/////////////////////////////////////////////////////////////////////////////// Copyright (c) 2000 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.///////////////////////////////////////////////////////////////////////////////// $Revision: 1.1.1.6 $// $Date: 2001/06/15 00:22:15 $// //File upnpapi.c#include "../../inc/tools/config.h"#include <assert.h>#include <signal.h>#include "upnpapi.h"#include "../inc/genlib/tpool/interrupts.h"#include "../inc/genlib/tpool/scheduler.h"#include <stdlib.h>#include<string.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>//************************************//Needed for GENA#include "../inc/gena/gena.h"#include "../inc/genlib/service_table/service_table.h"#include "../inc/genlib/miniserver/miniserver.h"//*******************************************/* ********************* */#ifdef INTERNAL_WEB_SERVER#include "../inc/genlib/net/http/server.h"#include "../inc/urlconfig/urlconfig.h"#endif /* INTERNAL_WEB_SERVER *//* ****************** */pthread_mutex_t GlobalHndMutex = PTHREAD_MUTEX_INITIALIZER;#include "../inc/genlib/timer_thread/timer_thread.h"int UpnpSdkInit = 0; // Global variable to denote the state of Upnp SDK // = 0 if uninitialized, = 1 if initialized.int UpnpInit(IN const char *HostIP, IN unsigned short DestPort){ int retVal=0; DBGONLY(if( InitLog() != UPNP_E_SUCCESS) return UPNP_E_INIT_FAILED;); DBGONLY(UpnpPrintf(UPNP_INFO,API,__FILE__,__LINE__,"Inside UpnpInit \n");) 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(); tpool_SetMaxThreads(MAX_THREADS + 3); // 3 threads are required for running // miniserver, ssdp. if (tintr_Init(SIGUSR1) != 0) return UPNP_E_INIT_FAILED; UpnpSdkInit = 1; #if EXCLUDE_SOAP == 0 InitSoap(); #endif #if EXCLUDE_GENA == 0 SetGenaCallback(genaCallback); #endif if ((retVal= InitTimerThread(&GLOBAL_TIMER_THREAD))!=UPNP_E_SUCCESS) { UpnpSdkInit=0; UpnpFinish(); return retVal; } #if EXCLUDE_SSDP == 0 if ((retVal = InitSsdpLib(SsdpCallbackEventHandler)) != UPNP_E_SUCCESS) { UpnpSdkInit = 0; if (retVal != -1) return retVal; else // if ssdp is already running for unknown reasons! return UPNP_E_INIT_FAILED; } #endif #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; 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 ******************/ int UpnpFinish(){ DEVICEONLY(UpnpDevice_Handle device_handle;) CLIENTONLY(UpnpClient_Handle client_handle;) struct Handle_Info * temp; DBGONLY( int retVal1 = 1; int retVal2 = 1;) 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"); } UpnpPrintf(UPNP_INFO,API,__FILE__,__LINE__,"Jobs pending = %d : Threads running = %d\n", tpool_GetNumJobsPending(), tpool_GetNumThreadsRunning());) UpnpSdkInit = 0; #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 StopTimerThread(&GLOBAL_TIMER_THREAD); #if EXCLUDE_SSDP == 0 DeInitSsdpLib(); #endif sleep(3); StopMiniServer(); tintr_Done(); DBGONLY( UpnpPrintf(UPNP_INFO,API,__FILE__,__LINE__,"Exiting UpnpFinish : UpnpSdkInit is :%d:\n", UpnpSdkInit); while (retVal1 || retVal2) { sleep(3); retVal1 = tpool_GetNumJobsPending(); retVal2 = tpool_GetNumThreadsRunning(); UpnpPrintf(UPNP_INFO,API,__FILE__,__LINE__,"Jobs pending = %d : Threads running = %d\n",retVal1, retVal2); break; }) DBGONLY(CloseLog();); return UPNP_E_SUCCESS;} /********************* End of UpnpFinish *************************/#ifdef INCLUDE_DEVICE_APISint UpnpRegisterRootDevice ( IN const char *DescUrl, IN Upnp_FunPtr Fun, IN const void * Cookie, OUT UpnpDevice_Handle *Hnd ){ struct Handle_Info * HInfo; int retVal=0; DBGONLY( UpnpPrintf(UPNP_INFO,API,__FILE__,__LINE__,"Inside UpnpRegisterRootDevice \n");) if(UpnpSdkInit != 1) { HandleUnlock(); return UPNP_E_FINISH; } if (Hnd == NULL || Fun == NULL || DescUrl == NULL || strlen(DescUrl) == 0) return UPNP_E_INVALID_PARAM; HandleLock(); if ((*Hnd = GetFreeHandle()) == UPNP_E_OUTOF_HANDLE) { HandleUnlock(); return UPNP_E_OUTOF_MEMORY; } HInfo = (struct Handle_Info *) malloc (sizeof(struct Handle_Info)); if (HInfo == NULL) { HandleUnlock(); return UPNP_E_OUTOF_MEMORY; } HandleTable[*Hnd] = HInfo; DBGONLY(UpnpPrintf(UPNP_INFO,API,__FILE__,__LINE__,"Root device URL is %s\n", DescUrl);) HInfo->HType = HND_DEVICE; strcpy(HInfo->DescURL,DescUrl); HInfo->Callback = Fun; HInfo->Cookie = (void *) Cookie; HInfo->MaxAge = DEFAULT_MAXAGE; HInfo->DeviceList = NULL; HInfo->ServiceList = NULL; HInfo->DescDocument = NULL; CLIENTONLY(HInfo->ClientSubList=NULL;) HInfo->MaxSubscriptions=UPNP_INFINITE; HInfo->MaxSubscriptionTimeOut=UPNP_INFINITE; if ((retVal=UpnpDownloadXmlDoc(HInfo->DescURL, &(HInfo->DescDocument))) != UPNP_E_SUCCESS) { FreeHandle(*Hnd); HandleUnlock(); return retVal; } DBGONLY(UpnpPrintf(UPNP_ALL,API,__FILE__,__LINE__,"UpnpRegisterRootDevice: Valid Description\n"); UpnpPrintf(UPNP_INFO,API,__FILE__,__LINE__,"UpnpRegisterRootDevice: DescURL : %s\n", HInfo->DescURL);) HInfo->DeviceList = UpnpDocument_getElementsByTagName(HInfo->DescDocument , "device"); if (HInfo->DeviceList == NULL) { FreeHandle(*Hnd); HandleUnlock(); DBGONLY(UpnpPrintf(UPNP_CRITICAL,API,__FILE__,__LINE__,"UpnpRegisterRootDevice: No devices found for RootDevice\n");) return UPNP_E_INVALID_DESC; } HInfo->ServiceList = UpnpDocument_getElementsByTagName(HInfo->DescDocument , "serviceList"); if (HInfo->ServiceList == NULL) { FreeHandle(*Hnd); HandleUnlock(); DBGONLY(UpnpPrintf(UPNP_CRITICAL,API,__FILE__,__LINE__,"UpnpRegisterRootDevice: No services found for RootDevice\n");) return UPNP_E_INVALID_DESC; } DBGONLY(UpnpPrintf(UPNP_ALL,API,__FILE__,__LINE__,"UpnpRegisterRootDevice: Gena Check\n");) //******************************* //GENA SET UP //******************************* if (getServiceTable(HInfo->DescDocument, &HInfo->ServiceTable, HInfo->DescURL)) { DBGONLY( UpnpPrintf(UPNP_INFO,API,__FILE__,__LINE__,"UpnpRegisterRootDevice: GENA Service Table \n"); UpnpPrintf(UPNP_INFO,API,__FILE__,__LINE__,"Here are the known services: \n"); printServiceTable(&HInfo->ServiceTable,UPNP_INFO,API);) } else { DBGONLY(UpnpPrintf(UPNP_INFO,API,__FILE__,__LINE__,"\nUpnpRegisterRootDevice: No Eventing Support Found \n");) } HandleUnlock(); DBGONLY(UpnpPrintf(UPNP_INFO,API,__FILE__,__LINE__,"Exiting RegisterRootDevice Successfully\n");) return UPNP_E_SUCCESS;} /****************** End of UpnpRegisterRootDevice *********************/#endif // INCLUDE_DEVICE_APIS#ifdef INCLUDE_DEVICE_APISint UpnpUnRegisterRootDevice(IN UpnpDevice_Handle Hnd){ int retVal = 0; struct Handle_Info *HInfo; struct Handle_Info *info; DBGONLY(UpnpPrintf(UPNP_INFO,API,__FILE__,__LINE__,"Inside UpnpUnRegisterRootDevice \n");) #if EXCLUDE_GENA == 0 if (genaUnregisterDevice(Hnd) != UPNP_E_SUCCESS) return UPNP_E_INVALID_HANDLE; #endif HandleLock(); if (GetHandleInfo(Hnd, &HInfo) == UPNP_E_INVALID_HANDLE) { HandleUnlock(); return UPNP_E_INVALID_HANDLE; } HandleUnlock(); #if EXCLUDE_SSDP == 0 retVal = AdvertiseAndReply(-1, Hnd, 0, (struct sockaddr_in *) NULL, (char *) NULL, (char *) NULL, (char *) NULL, HInfo->MaxAge); #endif info = (struct Handle_Info *) HandleTable[Hnd]; UpnpNodeList_free( info->DeviceList ); UpnpNodeList_free( info->ServiceList ); UpnpDocument_free( info->DescDocument ); #ifdef INTERNAL_WEB_SERVER if ( info->aliasInstalled ) { http_RemoveAlias( info->DescAlias ); } #endif // INTERNAL_WEB_SERVER HandleLock(); FreeHandle(Hnd); HandleUnlock(); DBGONLY(UpnpPrintf(UPNP_INFO,API,__FILE__,__LINE__,"Exiting UpnpUnRegisterRootDevice \n");) return retVal;} /****************** End of UpnpUnRegisterRootDevice *********************/#endif //INCLUDE_DEVICE_APIS// *************************************************************#ifdef INCLUDE_DEVICE_APIS#ifdef INTERNAL_WEB_SERVER// determines alias for given name which is a file name or URL.//// return codes:// UPNP_E_SUCCESS// UPNP_E_EXT_NOT_XMLstatic int GetNameForAlias( IN char *name, OUT char** alias ){ char *ext; char *al; ext = strrchr( name, '.' ); if ( ext == NULL || strcasecmp(ext, ".xml") != 0 ) { return UPNP_E_EXT_NOT_XML; } al = strrchr( name, '/' ); if ( al == NULL ) { *alias = name; } else { *alias = al; } return UPNP_E_SUCCESS;}static void get_server_addr( OUT struct sockaddr_in* serverAddr ){ memset( serverAddr, 0, sizeof(struct sockaddr_in) ); serverAddr->sin_family = AF_INET; serverAddr->sin_port = htons( LOCAL_PORT ); //inet_aton( LOCAL_HOST, &serverAddr->sin_addr ); serverAddr->sin_addr.s_addr = inet_addr(LOCAL_HOST);}// return codes:// UPNP_E_SUCCESS// UPNP_E_OUTOF_MEMORY// UPNP_E_URL_TOO_BIG// UPNP_E_INVALID_PARAM// UPNP_E_FILE_NOT_FOUND// UPNP_E_FILE_READ_ERROR// UPNP_E_INVALID_URL// UPNP_E_INVALID_DESC// UPNP_E_EXT_NOT_XML// UPNP_E_NETWORK_ERROR// UPNP_E_SOCKET_WRITE// UPNP_E_SOCKET_READ// UPNP_E_SOCKET_BIND// UPNP_E_SOCKET_CONNECT// UPNP_E_OUTOF_SOCKETstatic int GetDescDocumentAndURL( IN Upnp_DescType descriptionType, IN char* description, IN unsigned int bufferLen, IN int config_baseURL, OUT Upnp_Document* xmlDoc,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -