📄 ssdplib.c
字号:
{ if ( ListenerState == Idle ) { break; } DBGONLY(UpnpPrintf(UPNP_INFO,SSDP,__FILE__,__LINE__,"Sending interrupt\n");) code = tintr_Interrupt( ListenerThread ); if (code < 0) { DBGONLY(UpnpPrintf(UPNP_CRITICAL,SSDP,__FILE__,__LINE__,"Interrupt Failed............");) } if(ListenerState == Idle) { break; } sleep( 1 ); // pause before sending signals again } }////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Function : int InitSsdpLib(SsdpFunPtr Fn) // Description : This is the first function to be called in the SSDP library, it creates the multicats socket and starts // the multicast listener thread. // Parameters : FunPtr: Callback function which will receive all the responses. // // Return value: Less than zero if fails, UPNP_E_SUCCESS otherwise. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// int InitSsdpLib(SsdpFunPtr Fn) { int SsdpSock,On=1,val; u_char Ttl=4; struct ip_mreq SsdpMcastAddr; struct sockaddr_in SelfAddr; StartupTime = time(NULL); InitParser(); if ( ListenerState != Idle ) { return -1; // already running } SsdpSock = socket(AF_INET, SOCK_DGRAM, 0); val = fcntl(SsdpSock,F_GETFL,0); fcntl(SsdpSock,F_SETFL,val|O_NONBLOCK); if ( SsdpSock == -1 || val == -1) { SendErrorEvent(UPNP_E_NETWORK_ERROR); DBGONLY(UpnpPrintf(UPNP_CRITICAL,SSDP,__FILE__,__LINE__,"Error in socket operation !!!\n");) return UPNP_E_OUTOF_SOCKET; } if ( setsockopt(SsdpSock, SOL_SOCKET, SO_REUSEADDR, &On, sizeof(On)) == -1) return UPNP_E_OUTOF_SOCKET; bzero(&SsdpMcastAddr, sizeof(struct ip_mreq )); SsdpMcastAddr.imr_interface.s_addr = htonl(INADDR_ANY); SsdpMcastAddr.imr_multiaddr.s_addr = inet_addr(SSDP_IP); bzero((char *)&SelfAddr, sizeof(struct sockaddr_in)); SelfAddr.sin_family = AF_INET; SelfAddr.sin_addr.s_addr = inet_addr(SSDP_IP); SelfAddr.sin_port = htons(SSDP_PORT); if (bind( SsdpSock, (struct sockaddr *) &SelfAddr, sizeof(SelfAddr)) != 0) { SendErrorEvent(UPNP_E_NETWORK_ERROR); DBGONLY(UpnpPrintf(UPNP_CRITICAL,SSDP,__FILE__,__LINE__,"Error in binding !!!\n");) return UPNP_E_SOCKET_BIND; } setsockopt(SsdpSock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &SsdpMcastAddr, sizeof(struct ip_mreq)); setsockopt(SsdpSock, IPPROTO_IP, IP_MULTICAST_TTL, &Ttl, sizeof(Ttl)); tpool_Schedule((ScheduleFunc)ListenMulticastChannel, (void*)SsdpSock); CallBackFn = Fn; // wait SSDP to Start while(ListenerState != Running ) { sleep(1); } return UPNP_E_SUCCESS ; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Function : void RequestHandler(ThreadData *ThData) // Description : This function works as a request handler which passes the HTTP request string to multicast channel then // wait for the response. Once it is received, it is passed back to callback function. // Parameters : ThData : Data Packet which contains all the parameter which is requied to send the request on the // multicatst channel. // // Return value: None ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void RequestHandler(ThreadData *ThData) { int socklen=sizeof( struct sockaddr_in),RetVal,TryIdx=0, RqstSock, ByteReceived,TimeTillRead; struct timeval tmout; fd_set WrSet,RdSet; struct sockaddr_in DestAddr; char RequestBuf[BUFSIZE]; u_char Ttl=4; time_t StartTime,CurrentTime,ElapsedTime; Event * Evt = (Event *)malloc(sizeof(Event)); if(Evt == NULL) { SendErrorEvent( UPNP_E_OUTOF_MEMORY); return; } RqstSock = socket(AF_INET, SOCK_DGRAM, 0); setsockopt(RqstSock, IPPROTO_IP, IP_MULTICAST_TTL, &Ttl, sizeof(Ttl)); RetVal = fcntl(RqstSock,F_GETFL,0); fcntl(RqstSock,F_SETFL,RetVal|O_NONBLOCK); if ( RqstSock == -1 || RetVal == -1) { SendErrorEvent(UPNP_E_NETWORK_ERROR); DBGONLY(UpnpPrintf(UPNP_CRITICAL,SSDP,__FILE__,__LINE__,"Error in creating socket !!!\n");) return; } TimeTillRead = ThData->Mx; if (TimeTillRead <= 1) TimeTillRead = 2; else if (TimeTillRead > MAX_TIME_TOREAD) TimeTillRead = MAX_TIME_TOREAD ; Evt->ErrCode = NO_ERROR_FOUND; bzero((char *)&DestAddr, sizeof(struct sockaddr_in)); if(ThData->DestAddr.sin_port == 0) { DestAddr.sin_family = AF_INET; DestAddr.sin_addr.s_addr = inet_addr(SSDP_IP); DestAddr.sin_port = htons(SSDP_PORT); } else { DestAddr.sin_family = ThData->DestAddr.sin_family; DestAddr.sin_addr.s_addr = ThData->DestAddr.sin_addr.s_addr; DestAddr.sin_port = ThData->DestAddr.sin_port; } while(TryIdx < NUM_TRY) { FD_ZERO(&WrSet); FD_SET(RqstSock,&WrSet); tmout.tv_sec = 1; tmout.tv_usec = 1; DBGONLY(UpnpPrintf(UPNP_PACKET,SSDP,__FILE__,__LINE__,"Sending packet : \n%s\n",ThData->Data);) sendto(RqstSock,ThData->Data,strlen(ThData->Data),0,(struct sockaddr *)&DestAddr, socklen); if ( select(RqstSock+1,NULL,&WrSet,NULL,NULL) == -1) { 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");)} SendErrorEvent(UPNP_E_NETWORK_ERROR); RemoveThreadData(ThData); free(Evt); close(RqstSock); return; } else if(FD_ISSET(RqstSock,&WrSet)) { RetVal= 1; break; } TryIdx++; } StartTime = time(NULL); CurrentTime = StartTime; ElapsedTime = 0; while(ElapsedTime < TimeTillRead+2) { FD_ZERO(&RdSet); FD_SET(RqstSock,&RdSet); CurrentTime = time(NULL); ElapsedTime = CurrentTime-StartTime; tmout.tv_sec = TimeTillRead+2-ElapsedTime; tmout.tv_usec = TimeTillRead+2-ElapsedTime; if ( select(RqstSock+1,&RdSet,NULL,NULL,&tmout) == -1) { DBGONLY(UpnpPrintf(UPNP_CRITICAL,SSDP,__FILE__,__LINE__,"Error in select call!!!!!!!!");) Evt->ErrCode = E_SOCKET; RemoveThreadData(ThData); free(Evt); return; } else if(FD_ISSET(RqstSock,&RdSet)) { socklen = sizeof(struct sockaddr_in); ByteReceived = recvfrom(RqstSock, RequestBuf, BUFSIZE, 0,(struct sockaddr*)&DestAddr, &socklen); if(ByteReceived > 0 ) { RequestBuf[ByteReceived] = '\0'; DBGONLY(UpnpPrintf(UPNP_PACKET,SSDP,__FILE__,__LINE__,"Received buffer%s\n",RequestBuf);) if( AnalyzeCommand(RequestBuf,Evt) >=0) { Evt->Cookie = ThData->Cookie; CallBackFn(Evt); } } } } Evt->Cookie = ThData->Cookie; Evt->Cmd=TIMEOUT; CallBackFn(Evt); RemoveThreadData(ThData); free(Evt); close(RqstSock); return; }#ifdef INCLUDE_CLIENT_APIS ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Function : void CreateClientRequestPacket(char * RqstBuf,int Mx, char *SearchTarget) // Description : This function creates a HTTP search request packet depending on the input parameter. // Parameters : RqstBuf : Output string in HTTP format. // SearchTarget : Search Taget // Mx : Number of seconds to wait to collect all the responses. // // Return value: None ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void CreateClientRequestPacket(char * RqstBuf,int Mx, char *SearchTarget) { char TempBuf[COMMAND_LEN]; int Port; strcpy( RqstBuf,"M-SEARCH * HTTP/1.1\r\n"); Port = SSDP_PORT; strcpy(TempBuf,"HOST:"); strcat(TempBuf,SSDP_IP); sprintf(TempBuf,"%s:%d\r\n",TempBuf,Port); strcat(RqstBuf,TempBuf); strcat(RqstBuf,"MAN:\"ssdp:discover\"\r\n"); if ( Mx > 0) { sprintf(TempBuf,"MX:%d\r\n",Mx); strcat(RqstBuf,TempBuf); } if (SearchTarget != NULL) { sprintf(TempBuf,"ST:%s\r\n", SearchTarget); strcat(RqstBuf,TempBuf); } strcat(RqstBuf,"\r\n"); } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Function : int SearchByTarget() // Description : Creates and send the search request. // Parameters : Mx : Number of seconds to wait, to collect all the responses. // St : Search target. // Return value: 1 if successfull. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// int SearchByTarget(int Mx, char * St, void * Cookie) { char * ReqBuf; ThreadData *ThData; ReqBuf = (char *)malloc(BUFSIZE); if (ReqBuf == NULL) return UPNP_E_OUTOF_MEMORY; CreateClientRequestPacket(ReqBuf,Mx,St); DBGONLY(UpnpPrintf(UPNP_PACKET,SSDP,__FILE__,__LINE__,"Sending request buffer = \n%s\n",ReqBuf);) ThData = (ThreadData *)malloc(sizeof(struct TData)); if (ThData == NULL) return UPNP_E_OUTOF_MEMORY; PutThreadData(ThData,ReqBuf, NULL, Mx); ThData->Cookie = Cookie; tpool_Schedule((ScheduleFunc)RequestHandler,ThData); free(ReqBuf); return 1; }#endif#ifdef INCLUDE_DEVICE_APIS ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Function : int ServiceRequestHandler(struct sockaddr_in * DestAddr, char * szStr) // Description : This function works as a request handler which passes the HTTP request string to multicast channel then // wait for the response, once it received, it is passed back to callback function. // Parameters : szSt : Response string in HTTP format. // DestAddr : Ip address, to send the reply. // // Return value: 1 if successfull. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// int ServiceRequestHandler(struct sockaddr_in * DestAddr, char * szStr) { int ReplySock, socklen=sizeof( struct sockaddr_in),RetVal,TryIdx=0; struct timeval tmout; fd_set WrSet;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -