📄 ssdp_server.c
字号:
if( hmsg->method != HTTPMETHOD_NOTIFY && hmsg->method != HTTPMETHOD_MSEARCH && hmsg->request_method != HTTPMETHOD_MSEARCH ) { return FALSE; } if( hmsg->request_method != HTTPMETHOD_MSEARCH ) { // check PATH == * if( hmsg->uri.type != RELATIVE || strncmp( "*", hmsg->uri.pathquery.buff, hmsg->uri.pathquery.size ) != 0 ) { return FALSE; } // check HOST header if( ( httpmsg_find_hdr( hmsg, HDR_HOST, &hdr_value ) == NULL ) || ( memptr_cmp( &hdr_value, "239.255.255.250:1900" ) != 0 ) ) { return FALSE; } } return TRUE; // passed quick check}/************************************************************************* Function : start_event_handler * * Parameters: * IN void *the_data: ssdp_thread_data structure. This structure contains* SSDP request message.** Description: * This function parses the message and dispatches it to a handler * which handles the ssdp request msg** Returns: int* 0 if successful -1 if error***************************************************************************/static XINLINE intstart_event_handler( void *Data ){ http_parser_t *parser = NULL; parse_status_t status; ssdp_thread_data *data = ( ssdp_thread_data * ) Data; parser = &data->parser; status = parser_parse( parser ); if( status == PARSE_FAILURE ) { if( parser->msg.method != HTTPMETHOD_NOTIFY || !parser->valid_ssdp_notify_hack ) { DBGONLY( UpnpPrintf( UPNP_INFO, SSDP, __FILE__, __LINE__, "SSDP recvd bad msg code = %d\n", status ); ) // ignore bad msg, or not enuf mem goto error_handler; } // valid notify msg } else if( status != PARSE_SUCCESS ) { DBGONLY( UpnpPrintf( UPNP_INFO, SSDP, __FILE__, __LINE__, "SSDP recvd bad msg code = %d\n", status ); ) goto error_handler; } // check msg if( !valid_ssdp_msg( &parser->msg ) ) { goto error_handler; } return 0; //////// done; thread will free 'data' error_handler: free_ssdp_event_handler_data( data ); return -1;}/************************************************************************* Function : ssdp_event_handler_thread * * Parameters: * IN void *the_data: ssdp_thread_data structure. This structure contains* SSDP request message.** Description: * This function is a thread that handles SSDP requests.** Returns: void* ***************************************************************************/static voidssdp_event_handler_thread( void *the_data ){ ssdp_thread_data *data = ( ssdp_thread_data * ) the_data; http_message_t *hmsg = &data->parser.msg; if( start_event_handler( the_data ) != 0 ) { return; } // send msg to device or ctrlpt if( ( hmsg->method == HTTPMETHOD_NOTIFY ) || ( hmsg->request_method == HTTPMETHOD_MSEARCH ) ) { CLIENTONLY( ssdp_handle_ctrlpt_msg( hmsg, &data->dest_addr, FALSE, NULL ); ); } else { DEVICEONLY( ssdp_handle_device_request( hmsg, &data->dest_addr ); ); } // free data free_ssdp_event_handler_data( data );}/************************************************************************* Function : readFromSSDPSocket * * Parameters: * IN SOCKET socket: SSDP socket** Description: * This function reads the data from the ssdp socket.** Returns: void* ***************************************************************************/voidreadFromSSDPSocket( SOCKET socket ){ char *requestBuf = NULL; char staticBuf[BUFSIZE]; struct sockaddr_in clientAddr; ThreadPoolJob job; ssdp_thread_data *data = NULL; int socklen = 0; int byteReceived = 0; requestBuf = staticBuf; //in case memory //can't be allocated, still drain the //socket using a static buffer socklen = sizeof( struct sockaddr_in ); data = ( ssdp_thread_data * ) malloc( sizeof( ssdp_thread_data ) ); if( data != NULL ) { //initialize parser#ifdef INCLUDE_CLIENT_APIS if( socket == gSsdpReqSocket ) { parser_response_init( &data->parser, HTTPMETHOD_MSEARCH ); } else { parser_request_init( &data->parser ); }#else parser_request_init( &data->parser );#endif //set size of parser buffer if( membuffer_set_size( &data->parser.msg.msg, BUFSIZE ) == 0 ) { //use this as the buffer for recv requestBuf = data->parser.msg.msg.buf; } else { free( data ); data = NULL; } } byteReceived = recvfrom( socket, requestBuf, BUFSIZE - 1, 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 ); ) //add thread pool job to handle request if( data != NULL ) { data->parser.msg.msg.length += byteReceived; // null-terminate data->parser.msg.msg.buf[byteReceived] = 0; data->dest_addr = clientAddr; TPJobInit( &job, ( start_routine ) ssdp_event_handler_thread, data ); TPJobSetFreeFunction( &job, free_ssdp_event_handler_data ); TPJobSetPriority( &job, MED_PRIORITY ); if( ThreadPoolAdd( &gRecvThreadPool, &job, NULL ) != 0 ) { free_ssdp_event_handler_data( data ); } } } else { free_ssdp_event_handler_data( data ); }}/************************************************************************* Function : get_ssdp_sockets * * Parameters: * OUT MiniServerSockArray *out: Arrays of SSDP sockets** Description: * This function creates the ssdp sockets. It set their option to listen * for multicast traffic.** Returns: int* return UPNP_E_SUCCESS if successful else returns appropriate error***************************************************************************/intget_ssdp_sockets( MiniServerSockArray * out ){ SOCKET ssdpSock; CLIENTONLY( SOCKET ssdpReqSock; ) int onOff = 1; u_char ttl = 4; struct ip_mreq ssdpMcastAddr; struct sockaddr_in ssdpAddr; int option = 1; CLIENTONLY( if( ( ssdpReqSock = socket( AF_INET, SOCK_DGRAM, 0 ) ) == UPNP_INVALID_SOCKET ) { DBGONLY( UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__, "Error in socket operation !!!\n" ); ) return UPNP_E_OUTOF_SOCKET;} setsockopt( ssdpReqSock, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof( ttl ) ); // just do it, regardless if fails or not. Make_Socket_NoBlocking( ssdpReqSock ); gSsdpReqSocket = ssdpReqSock; ) //CLIENTONLY if( ( ssdpSock = socket( AF_INET, SOCK_DGRAM, 0 ) ) == UPNP_INVALID_SOCKET ) { DBGONLY( UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__, "Error in socket operation !!!\n" ); ) CLIENTONLY( shutdown( ssdpReqSock, SD_BOTH ) ); CLIENTONLY( UpnpCloseSocket( ssdpReqSock ) ); return UPNP_E_OUTOF_SOCKET; } onOff = 1; if( setsockopt( ssdpSock, SOL_SOCKET, SO_REUSEADDR, ( char * )&onOff, sizeof( onOff ) ) != 0 ) { DBGONLY( UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__, "Error in set reuse addr !!!\n" ); ) CLIENTONLY( shutdown( ssdpReqSock, SD_BOTH ) ); CLIENTONLY( UpnpCloseSocket( ssdpReqSock ) ); shutdown( ssdpSock, SD_BOTH ); UpnpCloseSocket( ssdpSock ); return UPNP_E_SOCKET_ERROR; } memset( ( void * )&ssdpAddr, 0, sizeof( struct sockaddr_in ) ); ssdpAddr.sin_family = AF_INET; // ssdpAddr.sin_addr.s_addr = inet_addr(LOCAL_HOST); ssdpAddr.sin_addr.s_addr = htonl( INADDR_ANY ); ssdpAddr.sin_port = htons( SSDP_PORT ); if( bind ( ssdpSock, ( struct sockaddr * )&ssdpAddr, sizeof( ssdpAddr ) ) != 0 ) { DBGONLY( UpnpPrintf ( UPNP_CRITICAL, SSDP, __FILE__, __LINE__, "Error in binding !!!\n" ); ) shutdown( ssdpSock, SD_BOTH ); UpnpCloseSocket( ssdpSock ); CLIENTONLY( shutdown( ssdpReqSock, SD_BOTH ) ); CLIENTONLY( UpnpCloseSocket( ssdpReqSock ) ); return UPNP_E_SOCKET_BIND; } memset( ( void * )&ssdpMcastAddr, 0, sizeof( struct ip_mreq ) ); ssdpMcastAddr.imr_interface.s_addr = htonl( INADDR_ANY ); ssdpMcastAddr.imr_multiaddr.s_addr = inet_addr( SSDP_IP ); if( setsockopt( ssdpSock, IPPROTO_IP, IP_ADD_MEMBERSHIP, ( char * )&ssdpMcastAddr, sizeof( struct ip_mreq ) ) != 0 ) { DBGONLY( UpnpPrintf ( UPNP_CRITICAL, SSDP, __FILE__, __LINE__, "Error in joining" " multicast group !!!\n" ); ) shutdown( ssdpSock, SD_BOTH ); CLIENTONLY( shutdown( ssdpReqSock, SD_BOTH ) ); UpnpCloseSocket( ssdpSock ); CLIENTONLY( UpnpCloseSocket( ssdpReqSock ) ); return UPNP_E_SOCKET_ERROR; } // result is not checked becuase it will fail in WinMe and Win9x. setsockopt( ssdpSock, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof( ttl ) ); if( setsockopt( ssdpSock, SOL_SOCKET, SO_BROADCAST, ( char * )&option, sizeof( option ) ) != 0 ) { DBGONLY( UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__, "Error in setting broadcast !!!\n" ); ) shutdown( ssdpSock, SD_BOTH ); CLIENTONLY( shutdown( ssdpReqSock, SD_BOTH ) ); UpnpCloseSocket( ssdpSock ); CLIENTONLY( UpnpCloseSocket( ssdpReqSock ) ); return UPNP_E_NETWORK_ERROR; } CLIENTONLY( out->ssdpReqSock = ssdpReqSock; ); out->ssdpSock = ssdpSock; return UPNP_E_SUCCESS;}#endif // EXCLUDE_SSDP
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -