📄 ssdplib.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.2 $// $Date: 2001/08/15 18:17:31 $// #include "../../inc/tools/config.h"#include "ssdplib.h"#include <stdio.h>#include "../inc/genlib/tpool/scheduler.h"#include "../inc/genlib/tpool/interrupts.h"#include "../inc/interface.h"#include <sys/utsname.h>#define MAX_TIME_TOREAD 45void RequestHandler();Event ErrotEvt;enum Listener{Idle,Stopping,Running}ListenerState=Idle;pthread_t ListenerThread = 0;static long StartupTime; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Function : int GetLocalHost(char * Ip) // Description : Returns the local IP address string. // Parameters : Ip : Local IP address. // // Return value: None //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////#if EXCLUDE_SSDP == 0 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Function : void SendErrorEvent(int ErrCode) // Description : This function is used to send the critical error notification to the callback function like memory // allocation, network error etc. // // Parameters : ErrCode : Error code to be passed back to the callback function // // Return value: None ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void SendErrorEvent(int ErrCode) { DBGONLY(UpnpPrintf(UPNP_CRITICAL,SSDP,__FILE__,__LINE__,"Error in memory allocation !!!\n");) ErrotEvt.ErrCode = ErrCode; CallBackFn((Event *)&ErrotEvt); } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Function : void GetRandomNumber(int Max) // Description : This function generates a milisecond delay random no. // // Parameters : Max : Max delay in seconds. // // Return value: Randon number. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// int GetRandomNumber(int Max) { unsigned long MaxLt; MaxLt = Max*1000000; gettimeofday(&trt,NULL); StartupTime = trt.tv_usec - 500000 ; srand(StartupTime); return (rand() % MaxLt); } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Function : void RemoveThreadData(ThreadData *ThData) // Description : This function does the cleanup job, it removes any data allocated by fn PutThreadData(). // // Parameters : ThData : Data packet to be passed back to the Thread. // // Return value: None ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void RemoveThreadData(ThreadData *ThData) { free(ThData->Data); free(ThData); } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Function : int PutThreadData(ThreadData *ThData,char * Rqst, struct sockaddr_in * DestAddr, int Mx) // Description : This function stored the data to be used by the independent thread. // // Parameters : ThData : Data packet to be passed back to the Thread. // // Return value: 1 if successfull , -1 otherwise. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// int PutThreadData(ThreadData *ThData,char * Rqst, struct sockaddr_in * DestAddr, int Mx) { ThData->Data = (char *)malloc(strlen(Rqst)+1); if( ThData->Data == NULL) { SendErrorEvent( UPNP_E_OUTOF_MEMORY); return -1; } strcpy(ThData->Data,Rqst); ThData->Mx = Mx; if(DestAddr != NULL) { ThData->DestAddr.sin_family = DestAddr->sin_family; ThData->DestAddr.sin_addr.s_addr = DestAddr->sin_addr.s_addr; ThData->DestAddr.sin_port = DestAddr->sin_port; } else ThData->DestAddr.sin_port =0; return 1; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Function : void TransferResEvent( ThreadData *ThData) // Description : This function process the HTTP data packet received by the multicast channel and pass it back to the // callback function. // // Parameters : ThData : Data packet to be passed back to the Thread. // // Return value: None //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////void TransferResEvent( ThreadData *ThData){ Event * Evt = (Event *)malloc(sizeof(Event)); Evt->ErrCode = NO_ERROR_FOUND; if( Evt == NULL) { SendErrorEvent( UPNP_E_OUTOF_MEMORY); return; } else { if (ThData->Data != NULL) { Evt->DestAddr = &(ThData->DestAddr); if (AnalyzeCommand(ThData->Data,Evt) > 0) { if(Evt->Cmd == SEARCH) { if (Evt->Mx < 0 || !strlen(Evt->Man)) { DBGONLY(UpnpPrintf(UPNP_CRITICAL,SSDP,__FILE__,__LINE__,"Error in parsing !!!\n");) goto end; } } if(Evt->Cmd == SEARCH && Evt->Mx > 1) { DBGONLY(UpnpPrintf(UPNP_ALL,SSDP,__FILE__,__LINE__,"Sleeping for %d milisecond!!!!!!!\n",GetRandomNumber(Evt->Mx));) //modified by donghee usleep(GetRandomNumber(1)); //usleep(GetRandomNumber(Evt->Mx)); //end of modification } CallBackFn(Evt); } else { DBGONLY(UpnpPrintf(UPNP_CRITICAL,SSDP,__FILE__,__LINE__,"Error in parsing !!!\n");) } } }end: RemoveThreadData(ThData); free(Evt); return; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Function : int StartEventHandler(char *EventBuf, struct sockaddr_in * DestAddr) // Description : This function starts the TransferResEvent thread, which later process this Event packet. // // Parameters : EventBuf : Raw HTTP packet received in multicast channel. // DestAddr : Address of the client from which this packet is received. // Return value: 1 if successfull , -1 otherwise. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// int StartEventHandler(char *EventBuf, struct sockaddr_in * DestAddr) { ThreadData *ThData; ThData = (ThreadData *)malloc(sizeof(struct TData)); if(ThData == NULL) { SendErrorEvent( UPNP_E_OUTOF_MEMORY); return -1; } PutThreadData(ThData,EventBuf,DestAddr,0); tpool_Schedule((ScheduleFunc)TransferResEvent,ThData); return 1; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Function : void ListenMulticastChannel() // Description : This function run as a independent thread listen for the response coming on the multicast channel. // It starts during the lib initialization and run until closed by the DeInit() functin call. // Parameters : SsdpSock : Multicast Socket on which it will listen for the request. // // Return value: None ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void ListenMulticastChannel(int SsdpSock) { int socklen,ByteReceived; struct sockaddr_in ClientAddr; fd_set RdSet; char RequestBuf[BUFSIZE]; ListenerThread = pthread_self(); ListenerState = Running; DBGONLY(UpnpPrintf(UPNP_INFO,SSDP,__FILE__,__LINE__,"Multicast listener started...\n");) bzero((char *)&RequestBuf, BUFSIZE); bzero((char *)&ClientAddr, sizeof(struct sockaddr_in)); for(;;) { FD_ZERO(&RdSet); FD_SET(SsdpSock,&RdSet); if (ListenerState == Stopping) break; if (select(SsdpSock+1,&RdSet,NULL,NULL,NULL) == -1) { if (errno == EINTR && ListenerState == Stopping ) { DBGONLY(UpnpPrintf(UPNP_INFO,SSDP,__FILE__,__LINE__,"SSDP got stop signal, Exiting!!!!!!!!!!!!!!\n");) break; } else { DBGONLY(UpnpPrintf(UPNP_CRITICAL,SSDP,__FILE__,__LINE__,"Error in select call !!!!!!!!!!!! \n");) if ( errno == EBADF) {DBGONLY(UpnpPrintf(UPNP_CRITICAL,SSDP,__FILE__,__LINE__,"An invalid file descriptor was givenin one of the sets. \n");)} else if ( errno == EINTR) {DBGONLY(UpnpPrintf(UPNP_CRITICAL,SSDP,__FILE__,__LINE__,"A non blocked signal was caught. \n");)} else if ( errno == EINVAL ) {DBGONLY(UpnpPrintf(UPNP_CRITICAL,SSDP,__FILE__,__LINE__,"n is negative. \n");)} else if ( errno == ENOMEM ) {DBGONLY(UpnpPrintf(UPNP_CRITICAL,SSDP,__FILE__,__LINE__,"Select was unable to allocate memory for internal tables.\n");)} break; } } else { if(FD_ISSET(SsdpSock,&RdSet)) { socklen = sizeof(struct sockaddr_in); ByteReceived = recvfrom(SsdpSock, RequestBuf, BUFSIZE, 0,(struct sockaddr*)&ClientAddr, &socklen); if(ByteReceived > 0 ) { RequestBuf[ByteReceived] = '\0'; DBGONLY(UpnpPrintf(UPNP_INFO,SSDP,__FILE__,__LINE__,"Received response !!! %s From host %s \n", RequestBuf,inet_ntoa(ClientAddr.sin_addr));) DBGONLY(UpnpPrintf(UPNP_PACKET,SSDP,__FILE__,__LINE__,"Received multicast packet: \n %s\n",RequestBuf);) StartEventHandler(RequestBuf,&ClientAddr ); } } } } close(SsdpSock); ListenerState = Idle; return; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Function : void DeInitSsdpLib() // Description : This function stops the multicast thread. // Parameters : None // // Return value: None ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void DeInitSsdpLib() { int code; if ( ListenerState == Idle ) return; // not running ListenerState = Stopping; // keep sending signals until server stops while ( 1 )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -