📄 gena_device.c
字号:
if( return_code == UPNP_E_OUTOF_MEMORY ) { free( out->URLs ); free( out->parsedURLs ); out->URLs = NULL; out->parsedURLs = NULL; return return_code; } } } } } out->size = URLcount; return URLcount;}/***************************************************************************** Function : gena_process_subscription_request** Parameters :* IN SOCKINFO *info : socket info of the device * IN http_message_t* request : SUBSCRIPTION request from the control* point** Description : This function handles a subscription request from a * ctrl point. The socket is not closed on return.** Return : void** Note :****************************************************************************/voidgena_process_subscription_request( IN SOCKINFO * info, IN http_message_t * request ){ Upnp_SID temp_sid; int return_code = 1; int time_out = 1801; service_info *service; struct Upnp_Subscription_Request request_struct; subscription *sub; uuid_upnp uid; struct Handle_Info *handle_info; void *cookie; Upnp_FunPtr callback_fun; UpnpDevice_Handle device_handle; memptr nt_hdr; char *event_url_path = NULL; memptr callback_hdr; memptr timeout_hdr; DBGONLY( UpnpPrintf( UPNP_INFO, GENA, __FILE__, __LINE__, "Subscription Request Received:\n" ) ); if( httpmsg_find_hdr( request, HDR_NT, &nt_hdr ) == NULL ) { error_respond( info, HTTP_BAD_REQUEST, request ); return; } // check NT header //Windows Millenium Interoperability: //we accept either upnp:event, or upnp:propchange for the NT header if( memptr_cmp_nocase( &nt_hdr, "upnp:event" ) != 0 ) { error_respond( info, HTTP_PRECONDITION_FAILED, request ); return; } // if a SID is present then the we have a bad request // "incompatible headers" if( httpmsg_find_hdr( request, HDR_SID, NULL ) != NULL ) { error_respond( info, HTTP_BAD_REQUEST, request ); return; } //look up service by eventURL if( ( event_url_path = str_alloc( request->uri.pathquery.buff, request->uri.pathquery.size ) ) == NULL ) { error_respond( info, HTTP_INTERNAL_SERVER_ERROR, request ); return; } DBGONLY( UpnpPrintf( UPNP_INFO, GENA, __FILE__, __LINE__, "SubscriptionRequest for event URL path: %s\n", event_url_path ); ) HandleLock( ); // CURRENTLY, ONLY ONE DEVICE if( GetDeviceHandleInfo( &device_handle, &handle_info ) != HND_DEVICE ) { free( event_url_path ); error_respond( info, HTTP_INTERNAL_SERVER_ERROR, request ); HandleUnlock( ); return; } service = FindServiceEventURLPath( &handle_info->ServiceTable, event_url_path ); free( event_url_path ); if( service == NULL || !service->active ) { error_respond( info, HTTP_NOT_FOUND, request ); HandleUnlock( ); return; } DBGONLY( UpnpPrintf( UPNP_INFO, GENA, __FILE__, __LINE__, "Subscription Request: Number of Subscriptions already %d\n " "Max Subscriptions allowed: %d\n", service->TotalSubscriptions, handle_info->MaxSubscriptions ) ); // too many subscriptions if( handle_info->MaxSubscriptions != -1 && service->TotalSubscriptions >= handle_info->MaxSubscriptions ) { error_respond( info, HTTP_INTERNAL_SERVER_ERROR, request ); HandleUnlock( ); return; } // generate new subscription sub = ( subscription * ) malloc( sizeof( subscription ) ); if( sub == NULL ) { error_respond( info, HTTP_INTERNAL_SERVER_ERROR, request ); HandleUnlock( ); return; } sub->eventKey = 0; sub->ToSendEventKey = 0; sub->active = 0; sub->next = NULL; sub->DeliveryURLs.size = 0; sub->DeliveryURLs.URLs = NULL; sub->DeliveryURLs.parsedURLs = NULL; // check for valid callbacks if( httpmsg_find_hdr( request, HDR_CALLBACK, &callback_hdr ) == NULL || ( return_code = create_url_list( &callback_hdr, &sub->DeliveryURLs ) ) == 0 ) { error_respond( info, HTTP_PRECONDITION_FAILED, request ); freeSubscriptionList( sub ); HandleUnlock( ); return; } if( return_code == UPNP_E_OUTOF_MEMORY ) { error_respond( info, HTTP_INTERNAL_SERVER_ERROR, request ); freeSubscriptionList( sub ); HandleUnlock( ); return; } // set the timeout if( httpmsg_find_hdr( request, HDR_TIMEOUT, &timeout_hdr ) != NULL ) { if( matchstr( timeout_hdr.buf, timeout_hdr.length, "%iSecond-%d%0", &time_out ) == PARSE_OK ) { // nothing } else if( memptr_cmp_nocase( &timeout_hdr, "Second-infinite" ) == 0 ) { time_out = -1; // infinite timeout } else { time_out = DEFAULT_TIMEOUT; // default is > 1800 seconds } } // replace infinite timeout with max timeout, if possible if( handle_info->MaxSubscriptionTimeOut != -1 ) { if( time_out == -1 || time_out > handle_info->MaxSubscriptionTimeOut ) { time_out = handle_info->MaxSubscriptionTimeOut; } } if( time_out >= 0 ) { sub->expireTime = time( NULL ) + time_out; } else { sub->expireTime = 0; // infinite time } //generate SID uuid_create( &uid ); uuid_unpack( &uid, temp_sid ); sprintf( sub->sid, "uuid:%s", temp_sid ); // respond OK if( respond_ok( info, time_out, sub, request ) != UPNP_E_SUCCESS ) { freeSubscriptionList( sub ); HandleUnlock( ); return; } //add to subscription list sub->next = service->subscriptionList; service->subscriptionList = sub; service->TotalSubscriptions++; //finally generate callback for init table dump request_struct.ServiceId = service->serviceId; request_struct.UDN = service->UDN; strcpy( ( char * )request_struct.Sid, sub->sid ); //copy callback callback_fun = handle_info->Callback; cookie = handle_info->Cookie; HandleUnlock( ); //make call back with request struct //in the future should find a way of mainting //that the handle is not unregistered in the middle of a //callback callback_fun( UPNP_EVENT_SUBSCRIPTION_REQUEST, &request_struct, cookie );}/***************************************************************************** Function : gena_process_subscription_renewal_request** Parameters :* IN SOCKINFO *info : socket info of the device* IN http_message_t* request : subscription renewal request from the * control point** Description : This function handles a subscription renewal request * from a ctrl point. The connection is not destroyed on return.** Return : void** Note :****************************************************************************/voidgena_process_subscription_renewal_request( IN SOCKINFO * info, IN http_message_t * request ){ Upnp_SID sid; subscription *sub; int time_out = 1801; service_info *service; struct Handle_Info *handle_info; UpnpDevice_Handle device_handle; memptr temp_hdr; membuffer event_url_path; memptr timeout_hdr; // if a CALLBACK or NT header is present, then it is an error if( httpmsg_find_hdr( request, HDR_CALLBACK, NULL ) != NULL || httpmsg_find_hdr( request, HDR_NT, NULL ) != NULL ) { error_respond( info, HTTP_BAD_REQUEST, request ); return; } // get SID if( httpmsg_find_hdr( request, HDR_SID, &temp_hdr ) == NULL || temp_hdr.length > SID_SIZE ) { error_respond( info, HTTP_PRECONDITION_FAILED, request ); return; } memcpy( sid, temp_hdr.buf, temp_hdr.length ); sid[temp_hdr.length] = '\0'; // lookup service by eventURL membuffer_init( &event_url_path ); if( membuffer_append( &event_url_path, request->uri.pathquery.buff, request->uri.pathquery.size ) != 0 ) { error_respond( info, HTTP_INTERNAL_SERVER_ERROR, request ); return; } HandleLock( ); // CURRENTLY, ONLY SUPPORT ONE DEVICE if( GetDeviceHandleInfo( &device_handle, &handle_info ) != HND_DEVICE ) { error_respond( info, HTTP_PRECONDITION_FAILED, request ); membuffer_destroy( &event_url_path ); return; } service = FindServiceEventURLPath( &handle_info->ServiceTable, event_url_path.buf ); membuffer_destroy( &event_url_path ); // get subscription if( service == NULL || !service->active || ( ( sub = GetSubscriptionSID( sid, service ) ) == NULL ) ) { error_respond( info, HTTP_PRECONDITION_FAILED, request ); HandleUnlock( ); return; } DBGONLY( UpnpPrintf( UPNP_INFO, GENA, __FILE__, __LINE__, "Renew request: Number of subscriptions already: %d\n " "Max Subscriptions allowed:%d\n", service->TotalSubscriptions, handle_info->MaxSubscriptions ); ) // too many subscriptions if( handle_info->MaxSubscriptions != -1 && service->TotalSubscriptions > handle_info->MaxSubscriptions ) { error_respond( info, HTTP_INTERNAL_SERVER_ERROR, request ); RemoveSubscriptionSID( sub->sid, service ); HandleUnlock( ); return; } // set the timeout if( httpmsg_find_hdr( request, HDR_TIMEOUT, &timeout_hdr ) != NULL ) { if( matchstr( timeout_hdr.buf, timeout_hdr.length, "%iSecond-%d%0", &time_out ) == PARSE_OK ) { //nothing } else if( memptr_cmp_nocase( &timeout_hdr, "Second-infinite" ) == 0 ) { time_out = -1; // inifinite timeout } else { time_out = DEFAULT_TIMEOUT; // default is > 1800 seconds } } // replace infinite timeout with max timeout, if possible if( handle_info->MaxSubscriptionTimeOut != -1 ) { if( time_out == -1 || time_out > handle_info->MaxSubscriptionTimeOut ) { time_out = handle_info->MaxSubscriptionTimeOut; } } if( time_out == -1 ) { sub->expireTime = 0; } else { sub->expireTime = time( NULL ) + time_out; } if( respond_ok( info, time_out, sub, request ) != UPNP_E_SUCCESS ) { RemoveSubscriptionSID( sub->sid, service ); } HandleUnlock( );}/***************************************************************************** Function : gena_process_unsubscribe_request** Parameters :* IN SOCKINFO *info : socket info of the device* IN http_message_t* request : UNSUBSCRIBE request from the control * point** Description : This function Handles a subscription cancellation request * from a ctrl point. The connection is not destroyed on return.** Return : void** Note :****************************************************************************/voidgena_process_unsubscribe_request( IN SOCKINFO * info, IN http_message_t * request ){ Upnp_SID sid; service_info *service; struct Handle_Info *handle_info; UpnpDevice_Handle device_handle; memptr temp_hdr; membuffer event_url_path; // if a CALLBACK or NT header is present, then it is an error if( httpmsg_find_hdr( request, HDR_CALLBACK, NULL ) != NULL || httpmsg_find_hdr( request, HDR_NT, NULL ) != NULL ) { error_respond( info, HTTP_BAD_REQUEST, request ); return; } // get SID if( httpmsg_find_hdr( request, HDR_SID, &temp_hdr ) == NULL || temp_hdr.length > SID_SIZE ) { error_respond( info, HTTP_PRECONDITION_FAILED, request ); return; } memcpy( sid, temp_hdr.buf, temp_hdr.length ); sid[temp_hdr.length] = '\0'; // lookup service by eventURL membuffer_init( &event_url_path ); if( membuffer_append( &event_url_path, request->uri.pathquery.buff, request->uri.pathquery.size ) != 0 ) { error_respond( info, HTTP_INTERNAL_SERVER_ERROR, request ); return; } HandleLock( ); // CURRENTLY, ONLY SUPPORT ONE DEVICE if( GetDeviceHandleInfo( &device_handle, &handle_info ) != HND_DEVICE ) { error_respond( info, HTTP_PRECONDITION_FAILED, request ); membuffer_destroy( &event_url_path ); HandleUnlock( ); return; } service = FindServiceEventURLPath( &handle_info->ServiceTable, event_url_path.buf ); membuffer_destroy( &event_url_path ); // validate service if( service == NULL || !service->active || GetSubscriptionSID( sid, service ) == NULL ) //CheckSubscriptionSID(sid, service) == NULL ) { error_respond( info, HTTP_PRECONDITION_FAILED, request ); HandleUnlock( ); return; } RemoveSubscriptionSID( sid, service ); error_respond( info, HTTP_OK, request ); // success HandleUnlock( );}#endif // INCLUDE_DEVICE_APIS#endif // EXCLUDE_GENA
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -