void gena_process_subscription_renewal_request( SOCKINFO *info, 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(); if (GetDeviceHandleInfoForPath(event_url_path.buf, info->foreign_sockaddr.ss_family, &device_handle, &handle_info, &service) != HND_DEVICE ) { error_respond( info, HTTP_PRECONDITION_FAILED, request ); membuffer_destroy( &event_url_path ); HandleUnlock(); return; } 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; } 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(); }
int handle_mode(void) { if (!strcasecmp(req_param, "S")) return respond_ok(); return respond(504, 1, "Invalid parameter."); }
void gena_process_subscription_request( SOCKINFO *info, http_message_t *request) { UpnpSubscriptionRequest *request_struct = UpnpSubscriptionRequest_new(); Upnp_SID temp_sid; int return_code = 1; int time_out = 1801; service_info *service; 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; int rc = 0; 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); goto exit_function; } /* 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); goto exit_function; } /* 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); goto exit_function; } /* look up service by eventURL */ event_url_path = str_alloc(request->uri.pathquery.buff, request->uri.pathquery.size); if (event_url_path == NULL) { error_respond(info, HTTP_INTERNAL_SERVER_ERROR, request); goto exit_function; } UpnpPrintf(UPNP_INFO, GENA, __FILE__, __LINE__, "SubscriptionRequest for event URL path: %s\n", event_url_path); HandleLock(); if (GetDeviceHandleInfoForPath(event_url_path, info->foreign_sockaddr.ss_family, &device_handle, &handle_info, &service) != HND_DEVICE) { free(event_url_path); error_respond(info, HTTP_INTERNAL_SERVER_ERROR, request); HandleUnlock(); goto exit_function; } free(event_url_path); if (service == NULL || !service->active) { error_respond(info, HTTP_NOT_FOUND, request); HandleUnlock(); goto exit_function; } 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(); goto exit_function; } /* generate new subscription */ sub = (subscription *)malloc(sizeof (subscription)); if (sub == NULL) { error_respond(info, HTTP_INTERNAL_SERVER_ERROR, request); HandleUnlock(); goto exit_function; } sub->ToSendEventKey = 0; sub->active = 0; sub->next = NULL; sub->DeliveryURLs.size = 0; sub->DeliveryURLs.URLs = NULL; sub->DeliveryURLs.parsedURLs = NULL; if (ListInit(&sub->outgoing, 0, free) != 0) { error_respond(info, HTTP_INTERNAL_SERVER_ERROR, request); HandleUnlock(); goto exit_function; } /* check for valid callbacks */ if (httpmsg_find_hdr( request, HDR_CALLBACK, &callback_hdr) == NULL) { error_respond(info, HTTP_PRECONDITION_FAILED, request); freeSubscriptionList(sub); HandleUnlock(); goto exit_function; } return_code = create_url_list(&callback_hdr, &sub->DeliveryURLs); if (return_code == 0) { error_respond(info, HTTP_PRECONDITION_FAILED, request); freeSubscriptionList(sub); HandleUnlock(); goto exit_function; } if (return_code == UPNP_E_OUTOF_MEMORY) { error_respond(info, HTTP_INTERNAL_SERVER_ERROR, request); freeSubscriptionList(sub); HandleUnlock(); goto exit_function; } /* 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) { /* infinite timeout */ time_out = -1; } else { /* default is > 1800 seconds */ time_out = DEFAULT_TIMEOUT; } } /* 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 { /* infinite time */ sub->expireTime = 0; } /* generate SID */ uuid_create(&uid); upnp_uuid_unpack(&uid, temp_sid); rc = snprintf(sub->sid, sizeof(sub->sid), "uuid:%s", temp_sid); /* respond OK */ if (rc < 0 || (unsigned int) rc >= sizeof(sub->sid) || (respond_ok(info, time_out, sub, request) != UPNP_E_SUCCESS)) { freeSubscriptionList(sub); HandleUnlock(); goto exit_function; } /* add to subscription list */ sub->next = service->subscriptionList; service->subscriptionList = sub; service->TotalSubscriptions++; /* finally generate callback for init table dump */ UpnpSubscriptionRequest_strcpy_ServiceId(request_struct, service->serviceId); UpnpSubscriptionRequest_strcpy_UDN(request_struct, service->UDN); UpnpSubscriptionRequest_strcpy_SID(request_struct, 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); exit_function: UpnpSubscriptionRequest_delete(request_struct); }