📄 ssdplib.c
字号:
Event * Evt = (Event *) malloc(sizeof(Event)); if ( Evt == NULL) { DBGONLY(UpnpPrintf(UPNP_CRITICAL,SSDP,__FILE__,__LINE__,"Error in memory allocation : \n")); return -1; } else Evt->ErrCode = NO_ERROR_FOUND; ReplySock = socket(AF_INET, SOCK_DGRAM, 0); RetVal = fcntl(ReplySock,F_GETFL,0); fcntl(ReplySock,F_SETFL,RetVal|O_NONBLOCK); if( ReplySock == -1 || RetVal == -1) { SendErrorEvent(UPNP_E_NETWORK_ERROR); DBGONLY(UpnpPrintf(UPNP_CRITICAL,SSDP,__FILE__,__LINE__,"Error in socket operation !!!\n")); free(Evt); } while(TryIdx < NUM_TRY) { FD_ZERO(&WrSet); FD_SET(ReplySock,&WrSet); tmout.tv_sec = 1; tmout.tv_usec = 1; sendto(ReplySock,szStr,strlen(szStr),0,(struct sockaddr *)DestAddr, socklen); if ( select(ReplySock+1,NULL,&WrSet,NULL,NULL) == -1) { DBGONLY(UpnpPrintf(UPNP_CRITICAL,SSDP,__FILE__,__LINE__,"Error in select !!!!!!!!\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");)} SendErrorEvent(UPNP_E_NETWORK_ERROR); free(Evt); break; } else if(FD_ISSET(ReplySock,&WrSet)) { RetVal= 1; break; } TryIdx++; } free(Evt); close(ReplySock); return 1; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Function : int NewRequestHandler(struct sockaddr_in * DestAddr, int NumPacket, char ** RqPacket) // 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 : RqPacket : Request packet in HTTP format. // DestAddr : Ip address, to send the reply. // NumPacket: Number of packet to be sent. // Return value: 1 if successfull. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// int NewRequestHandler(struct sockaddr_in * DestAddr, int NumPacket, char ** RqPacket) { int ReplySock, socklen=sizeof( struct sockaddr_in),RetVal,TryIdx=0; struct timeval tmout; fd_set WrSet; int NumCopy,Index; Event * Evt = (Event *) malloc(sizeof(Event)); if ( Evt == NULL) { DBGONLY(UpnpPrintf(UPNP_CRITICAL,SSDP,__FILE__,__LINE__,"Error in memory allocation : \n")); return UPNP_E_OUTOF_MEMORY; } else Evt->ErrCode = NO_ERROR_FOUND; ReplySock = socket(AF_INET, SOCK_DGRAM, 0); RetVal = fcntl(ReplySock,F_GETFL,0); fcntl(ReplySock,F_SETFL,RetVal|O_NONBLOCK); if( ReplySock == -1 || RetVal == -1) { SendErrorEvent(UPNP_E_NETWORK_ERROR); DBGONLY(UpnpPrintf(UPNP_CRITICAL,SSDP,__FILE__,__LINE__,"Error in socket operation !!!\n")); free(Evt); return UPNP_E_OUTOF_SOCKET; }//modified by dongheeNumPacket = 1;//end of modification for(Index=0;Index< NumPacket;Index++) { NumCopy =0; TryIdx =0; while(TryIdx < NUM_TRY && NumCopy < NUM_SSDP_COPY) { FD_ZERO(&WrSet); FD_SET(ReplySock,&WrSet); tmout.tv_sec = 1; tmout.tv_usec = 1; DBGONLY(UpnpPrintf(UPNP_PACKET,SSDP,__FILE__,__LINE__,"Sending reply %s\n",*(RqPacket+Index));) sendto(ReplySock,*(RqPacket+Index),strlen(*(RqPacket+Index)),0,(struct sockaddr *)DestAddr, socklen); if ( select(ReplySock+1,NULL,&WrSet,NULL,NULL) == -1) { DBGONLY(UpnpPrintf(UPNP_CRITICAL,SSDP,__FILE__,__LINE__,"Error in select !!!!!!!!\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");)} SendErrorEvent(UPNP_E_NETWORK_ERROR); break; } else if(FD_ISSET(ReplySock,&WrSet)) { ++NumCopy; } else TryIdx++; } } free(Evt); close(ReplySock); return UPNP_E_SUCCESS; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Function : void CreateServiceRequestPacket(int Notf,char *RqstBuf,char * NtSt,char *Usn,char *Server,char * S,char * Location,int Duration) // Description : This function creates a HTTP request packet. Depending on the input parameter it either creates a service advertisement // request or service shutdown request etc. // Parameters : Notf : Specify the type of notification, either advertisement or shutdown etc. // RqstBuf : Output buffer filled with HTTP statement. // RqstId : Same ID as send with the request HTTP statement. // ServType : Service Type or category // ServId :Service unique name or ID // Location : Location URL. // Duration : Service duration in sec. // Return value: None ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void CreateServiceRequestPacket(int Notf,char *RqstBuf,char * NtSt,char *Usn,char *Server,char * Location,int Duration) { char TempBuf[COMMAND_LEN]; int Port = SSDP_PORT; char Date[40]; struct utsname sys_info; //Note Notf=0 means service shutdown, Notf=1 means service advertisement, Notf =2 means reply currentTmToHttpDate(Date); memset(&sys_info,0x00,sizeof(sys_info)); uname(&sys_info); if(Notf ==2) { strcpy(RqstBuf,"HTTP/1.1 200 OK\r\n"); sprintf(TempBuf,"CACHE-CONTROL: max-age=%d\r\n",Duration); strcat(RqstBuf,TempBuf); strcat(RqstBuf,Date); strcat(RqstBuf,"EXT:\r\n"); sprintf(TempBuf,"LOCATION: %s\r\n",Location); strcat(RqstBuf,TempBuf); sprintf(TempBuf,"SERVER: %s/%s UPnP/1.0 Intel UPnP SDK/1.0\r\n", sys_info.sysname, sys_info.release); strcat(RqstBuf,TempBuf); sprintf(TempBuf,"ST: %s\r\n",NtSt); strcat(RqstBuf,TempBuf); } else if(Notf ==1) { strcpy(RqstBuf,"NOTIFY * HTTP/1.1\r\n"); strcpy(TempBuf,"HOST: "); strcat(TempBuf,SSDP_IP); sprintf(TempBuf,"%s:%d\r\n",TempBuf,Port); strcat(RqstBuf,TempBuf); sprintf(TempBuf,"CACHE-CONTROL: max-age=%d\r\n",Duration); strcat(RqstBuf,TempBuf); sprintf(TempBuf,"LOCATION: %s\r\n",Location); strcat(RqstBuf,TempBuf); sprintf(TempBuf,"NT: %s\r\n",NtSt); strcat(RqstBuf,TempBuf); strcat(RqstBuf,"NTS: ssdp:alive\r\n"); sprintf(TempBuf,"SERVER: %s/%s UPnP/1.0 Intel UPnP SDK/1.0\r\n", sys_info.sysname, sys_info.release); strcat(RqstBuf,TempBuf); } else if(Notf ==0) { strcpy(RqstBuf,"NOTIFY * HTTP/1.1\r\n"); strcpy(TempBuf,"HOST: "); strcat(TempBuf,SSDP_IP); sprintf(TempBuf,"%s:%d\r\n",TempBuf,Port); strcat(RqstBuf,TempBuf); // Following two header is added to interop with Windows Millenium but this is not // a part of UPNP spec 1.0 sprintf(TempBuf,"CACHE-CONTROL: max-age=%d\r\n",Duration); strcat(RqstBuf,TempBuf); sprintf(TempBuf,"LOCATION: %s\r\n",Location); strcat(RqstBuf,TempBuf); sprintf(TempBuf,"NT: %s\r\n",NtSt); strcat(RqstBuf,TempBuf); strcat(RqstBuf,"NTS: ssdp:byebye\r\n"); } sprintf(TempBuf,"USN: %s\r\n",Usn); strcat(RqstBuf,TempBuf); strcat(RqstBuf,"\r\n\r\n"); } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Function : int DeviceAdvertisement(int RootDev,char * Udn, char * DevType,char *Server,char * Location,int Duration) // Description : This function creates the device advertisement request based on the input parameter, and send it to the // multicast channel. // Parameters : RootDev : 1 means root device 0 means embedded device. // Udm : Device UDN // DevType : Device Type. // Location : Loaction of Device description document. // Duration : Life time of this device. // Return value: 1 if successfull. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// int DeviceAdvertisement(char * DevType, int RootDev,char * Udn, char *Server, char * Location, int Duration){ struct sockaddr_in DestAddr; char *szReq[3], Mil_Nt[LINE_SIZE], Mil_Usn[LINE_SIZE]; int RetVal; DBGONLY(UpnpPrintf(UPNP_ALL,SSDP,__FILE__,__LINE__,"In function SendDeviceAdvertisemenrt\n");) DestAddr.sin_family = AF_INET; DestAddr.sin_addr.s_addr = inet_addr(SSDP_IP); DestAddr.sin_port = htons(SSDP_PORT); if(RootDev) //If deviceis a root device , here we need to send 3 advertisement or reply { szReq[0] = (char*)malloc(BUFSIZE); szReq[1] = (char*)malloc(BUFSIZE); szReq[2] = (char*)malloc(BUFSIZE); if (szReq[0] == NULL || szReq[1] == NULL || szReq[2] == NULL) return UPNP_E_OUTOF_MEMORY ; strcpy(Mil_Nt,"upnp:rootdevice"); sprintf(Mil_Usn,"%s::upnp:rootdevice",Udn); CreateServiceRequestPacket(1,szReq[0],Mil_Nt,Mil_Usn,Server,Location,Duration); sprintf(Mil_Nt,"%s",Udn); sprintf(Mil_Usn,"%s",Udn); CreateServiceRequestPacket(1,szReq[1],Mil_Nt,Mil_Usn,Server,Location,Duration); sprintf(Mil_Nt,"%s",DevType); sprintf(Mil_Usn,"%s::%s",Udn,DevType); CreateServiceRequestPacket(1,szReq[2],Mil_Nt,Mil_Usn,Server,Location,Duration); RetVal = NewRequestHandler(&DestAddr,3, szReq) ; free(szReq[0]); free(szReq[1]); free(szReq[2]); } else //If device is not a root device then it is a sub-device., here we need to send 2 advertisement or reply { szReq[0] = (char*)malloc(BUFSIZE); szReq[1] = (char*)malloc(BUFSIZE); if (szReq[0] == NULL || szReq[1] == NULL ) return UPNP_E_OUTOF_MEMORY ; sprintf(Mil_Nt,"%s",Udn); sprintf(Mil_Usn,"%s",Udn); CreateServiceRequestPacket(1,szReq[0],Mil_Nt,Mil_Usn,Server,Location,Duration); sprintf(Mil_Nt,"%s",DevType); sprintf(Mil_Usn,"%s::%s",Udn,DevType); CreateServiceRequestPacket(1,szReq[1],Mil_Nt,Mil_Usn,Server,Location,Duration); RetVal = NewRequestHandler(&DestAddr,2, szReq); free(szReq[0]); free(szReq[1]); } return RetVal;} ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Function : int DeviceReply(int RootDev, char *DevType,char * Udn,struct sockaddr_in * DestAddr,char *Server,char * Location,int Duration) // Description : This function creates the reply packet based on the input parameter, and send it to the client addesss // given in its input parameter DestAddr. // Parameters : RootDev : 1 means root device 0 means embedded device. // Udn : Device UDN // DevType : Device Type. // Location : Loaction of Device description document. // Duration : Life time of this device. // DestAddr : destination IP address. // Return value: 1 if successfull.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -