📄 ssdp_server.c
字号:
* which handles the ssdp request msg * * Returns: int * 0 if successful -1 if error ***************************************************************************/static UPNP_INLINE 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 ) { 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 ) { 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 { 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; socklen_t 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'; UpnpPrintf( UPNP_INFO, SSDP, __FILE__, __LINE__, "Start of received response ----------------------------------------------------\n" "%s\n" "End of received response ------------------------------------------------------\n" "From host %s\n", requestBuf, inet_ntoa( clientAddr.sin_addr ) ); UpnpPrintf( UPNP_PACKET, SSDP, __FILE__, __LINE__, "Start of received multicast packet --------------------------------------------\n" "%s\n" "End of received multicast packet ----------------------------------------------\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 ){ char errorBuffer[ERROR_BUFFER_LEN]; int onOff = 1; u_char ttl = 4; struct ip_mreq ssdpMcastAddr; struct sockaddr_in ssdpAddr; int option = 1; int ret = 0; struct in_addr addr; SOCKET ssdpSock;#if INCLUDE_CLIENT_APIS SOCKET ssdpReqSock; ssdpReqSock = socket( AF_INET, SOCK_DGRAM, 0 ); if ( ssdpReqSock == -1 ) { strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__, "Error in socket(): %s\n", errorBuffer ); return UPNP_E_OUTOF_SOCKET; } ret = setsockopt( ssdpReqSock, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof (ttl) ); // just do it, regardless if fails or not. Make_Socket_NoBlocking( ssdpReqSock ); gSsdpReqSocket = ssdpReqSock;#endif /* INCLUDE_CLIENT_APIS */ ssdpSock = socket( AF_INET, SOCK_DGRAM, 0 ); if ( ssdpSock == -1 ) { strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__, "Error in socket(): %s\n", errorBuffer ); CLIENTONLY( shutdown( ssdpReqSock, SD_BOTH ); ) CLIENTONLY( UpnpCloseSocket( ssdpReqSock ); ) return UPNP_E_OUTOF_SOCKET; } onOff = 1; ret = setsockopt( ssdpSock, SOL_SOCKET, SO_REUSEADDR, (char *)&onOff, sizeof(onOff) ); if ( ret == -1) { strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__, "Error in setsockopt() SO_REUSEADDR: %s\n", errorBuffer ); CLIENTONLY( shutdown( ssdpReqSock, SD_BOTH ); ) CLIENTONLY( UpnpCloseSocket( ssdpReqSock ); ) shutdown( ssdpSock, SD_BOTH ); UpnpCloseSocket( ssdpSock ); return UPNP_E_SOCKET_ERROR; } #if defined(__FreeBSD__) || defined(__OSX__) || defined(__APPLE__) ret = setsockopt( ssdpSock, SOL_SOCKET, SO_REUSEPORT, (char *)&onOff, sizeof (onOff) ); if ( ret == -1 ) { strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__, "Error in setsockopt() SO_REUSEPORT: %s\n", errorBuffer ); CLIENTONLY( shutdown( ssdpReqSock, SD_BOTH ); ) CLIENTONLY( UpnpCloseSocket( ssdpReqSock ); ) shutdown( ssdpSock, SD_BOTH ); UpnpCloseSocket( ssdpSock ); return UPNP_E_SOCKET_ERROR; }#endif /* __FreeBSD__ */ 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 ); ret = bind( ssdpSock, (struct sockaddr *)&ssdpAddr, sizeof (ssdpAddr) ); if ( ret == -1 ) { strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__, "Error in bind(), addr=0x%08X, port=%d: %s\n", INADDR_ANY, SSDP_PORT, errorBuffer ); 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 = inet_addr( LOCAL_HOST ); ssdpMcastAddr.imr_multiaddr.s_addr = inet_addr( SSDP_IP ); ret = setsockopt( ssdpSock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&ssdpMcastAddr, sizeof (struct ip_mreq) ); if ( ret == -1 ) { strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__, "Error in setsockopt() IP_ADD_MEMBERSHIP (join multicast group): %s\n", errorBuffer ); shutdown( ssdpSock, SD_BOTH ); CLIENTONLY( shutdown( ssdpReqSock, SD_BOTH ); ) UpnpCloseSocket( ssdpSock ); CLIENTONLY( UpnpCloseSocket( ssdpReqSock ); ) return UPNP_E_SOCKET_ERROR; } /* Set multicast interface. */ memset( (void *)&addr, 0, sizeof (struct in_addr) ); addr.s_addr = inet_addr(LOCAL_HOST); ret = setsockopt(ssdpSock, IPPROTO_IP, IP_MULTICAST_IF, (char *)&addr, sizeof addr); if ( ret == -1 ) { strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); UpnpPrintf( UPNP_INFO, SSDP, __FILE__, __LINE__, "Error in setsockopt() IP_MULTICAST_IF (set multicast interface): %s\n", errorBuffer ); /* This is probably not a critical error, so let's continue. */ } /* result is not checked becuase it will fail in WinMe and Win9x. */ ret = setsockopt( ssdpSock, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof (ttl) ); ret = setsockopt( ssdpSock, SOL_SOCKET, SO_BROADCAST, (char *)&option, sizeof (option) ); if( ret == -1) { strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__, "Error in setsockopt() SO_BROADCAST (set broadcast): %s\n", errorBuffer ); 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 + -