void gena_process_unsubscribe_request( SOCKINFO *info, 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( info->foreign_sockaddr.ss_family, &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 ) { error_respond( info, HTTP_PRECONDITION_FAILED, request ); HandleUnlock(); return; } RemoveSubscriptionSID(sid, service); error_respond(info, HTTP_OK, request); /* success */ HandleUnlock(); }
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(); /* CURRENTLY, ONLY ONE DEVICE */ if (GetDeviceHandleInfo(info->foreign_sockaddr.ss_family , &device_handle, &handle_info) != HND_DEVICE) { free(event_url_path); error_respond(info, HTTP_INTERNAL_SERVER_ERROR, request); HandleUnlock(); goto exit_function; } 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(); 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->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) { 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); 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); }
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(); /* CURRENTLY, ONLY SUPPORT ONE DEVICE */ if( GetDeviceHandleInfo( info->foreign_sockaddr.ss_family, &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 ); /* 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(); }
/************************************************************************ * Function : ssdp_handle_device_request * * Parameters: * IN http_message_t* hmsg: SSDP search request from the control point * IN struct sockaddr_in* dest_addr: The address info of control point * * Description: * This function handles the search request. It do the sanity checks of * the request and then schedules a thread to send a random time reply ( * random within maximum time given by the control point to reply). * * Returns: void * * 1 if successful else appropriate error ***************************************************************************/ void ssdp_handle_device_request( IN http_message_t * hmsg, IN struct sockaddr_in *dest_addr ) { #define MX_FUDGE_FACTOR 10 int handle; struct Handle_Info *dev_info = NULL; memptr hdr_value; int mx; char save_char; SsdpEvent event; int ret_code; SsdpSearchReply *threadArg = NULL; ThreadPoolJob job; int replyTime; int maxAge; // check man hdr if( httpmsg_find_hdr( hmsg, HDR_MAN, &hdr_value ) == NULL || memptr_cmp( &hdr_value, "\"ssdp:discover\"" ) != 0 ) { return; // bad or missing hdr } // MX header if( httpmsg_find_hdr( hmsg, HDR_MX, &hdr_value ) == NULL || ( mx = raw_to_int( &hdr_value, 10 ) ) < 0 ) { return; } // ST header if( httpmsg_find_hdr( hmsg, HDR_ST, &hdr_value ) == NULL ) { return; } save_char = hdr_value.buf[hdr_value.length]; hdr_value.buf[hdr_value.length] = '\0'; ret_code = ssdp_request_type( hdr_value.buf, &event ); hdr_value.buf[hdr_value.length] = save_char; // restore if( ret_code == -1 ) { return; // bad ST header } HandleLock( ); // device info if( GetDeviceHandleInfo( &handle, &dev_info ) != HND_DEVICE ) { HandleUnlock( ); return; // no info found } maxAge = dev_info->MaxAge; HandleUnlock( ); DBGONLY( UpnpPrintf( UPNP_PACKET, API, __FILE__, __LINE__, "ssdp_handle_device_request with Cmd %d SEARCH\n", event.Cmd ); UpnpPrintf( UPNP_PACKET, API, __FILE__, __LINE__, "MAX-AGE = %d\n", maxAge ); UpnpPrintf( UPNP_PACKET, API, __FILE__, __LINE__, "MX = %d\n", event.Mx ); UpnpPrintf( UPNP_PACKET, API, __FILE__, __LINE__, "DeviceType = %s\n", event.DeviceType ); UpnpPrintf( UPNP_PACKET, API, __FILE__, __LINE__, "DeviceUuid = %s\n", event.UDN ); UpnpPrintf( UPNP_PACKET, API, __FILE__, __LINE__, "ServiceType = %s\n", event.ServiceType ); )
void ssdp_handle_device_request(http_message_t *hmsg, struct sockaddr_storage *dest_addr) { #define MX_FUDGE_FACTOR 10 int handle; struct Handle_Info *dev_info = NULL; memptr hdr_value; int mx; char save_char; SsdpEvent event; int ret_code; SsdpSearchReply *threadArg = NULL; ThreadPoolJob job; int replyTime; int maxAge; memset(&job, 0, sizeof(job)); /* check man hdr. */ if (httpmsg_find_hdr(hmsg, HDR_MAN, &hdr_value) == NULL || memptr_cmp(&hdr_value, "\"ssdp:discover\"") != 0) /* bad or missing hdr. */ return; /* MX header. */ if (httpmsg_find_hdr(hmsg, HDR_MX, &hdr_value) == NULL || (mx = raw_to_int(&hdr_value, 10)) < 0) return; /* ST header. */ if (httpmsg_find_hdr(hmsg, HDR_ST, &hdr_value) == NULL) return; save_char = hdr_value.buf[hdr_value.length]; hdr_value.buf[hdr_value.length] = '\0'; ret_code = ssdp_request_type(hdr_value.buf, &event); /* restore. */ hdr_value.buf[hdr_value.length] = save_char; if (ret_code == -1) /* bad ST header. */ return; HandleLock(); /* device info. */ switch (GetDeviceHandleInfo((int)dest_addr->ss_family, &handle, &dev_info)) { case HND_DEVICE: break; default: HandleUnlock(); /* no info found. */ return; } maxAge = dev_info->MaxAge; HandleUnlock(); UpnpPrintf(UPNP_PACKET, API, __FILE__, __LINE__, "MAX-AGE = %d\n", maxAge); UpnpPrintf(UPNP_PACKET, API, __FILE__, __LINE__, "MX = %d\n", event.Mx); UpnpPrintf(UPNP_PACKET, API, __FILE__, __LINE__, "DeviceType = %s\n", event.DeviceType); UpnpPrintf(UPNP_PACKET, API, __FILE__, __LINE__, "DeviceUuid = %s\n", event.UDN); UpnpPrintf(UPNP_PACKET, API, __FILE__, __LINE__, "ServiceType = %s\n", event.ServiceType); threadArg = (SsdpSearchReply *)malloc(sizeof(SsdpSearchReply)); if (threadArg == NULL) return; threadArg->handle = handle; memcpy(&threadArg->dest_addr, dest_addr, sizeof(threadArg->dest_addr)); threadArg->event = event; threadArg->MaxAge = maxAge; TPJobInit(&job, advertiseAndReplyThread, threadArg); TPJobSetFreeFunction(&job, (free_routine) free); /* Subtract a percentage from the mx to allow for network and processing * delays (i.e. if search is for 30 seconds, respond * within 0 - 27 seconds). */ if (mx >= 2) mx -= MAXVAL(1, mx / MX_FUDGE_FACTOR); if (mx < 1) mx = 1; replyTime = rand() % mx; TimerThreadSchedule(&gTimerThread, replyTime, REL_SEC, &job, SHORT_TERM, NULL); }
/** Function for 'devices' command. @param[in] ImageHandle Handle to the Image (NULL if Internal). @param[in] SystemTable Pointer to the System Table (NULL if Internal). **/ SHELL_STATUS EFIAPI ShellCommandRunDevices ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; LIST_ENTRY *Package; CHAR16 *ProblemParam; SHELL_STATUS ShellStatus; CHAR8 *Language; EFI_HANDLE *HandleList; EFI_HANDLE *HandleListWalker; CHAR16 Type; BOOLEAN Cfg; BOOLEAN Diag; UINTN Parents; UINTN Devices; UINTN Children; CHAR16 *Name; CONST CHAR16 *Lang; BOOLEAN SfoFlag; ShellStatus = SHELL_SUCCESS; Language = NULL; SfoFlag = FALSE; // // initialize the shell lib (we must be in non-auto-init...) // Status = ShellInitialize(); // ASSERT_EFI_ERROR(Status); Status = CommandInit(); // ASSERT_EFI_ERROR(Status); if (EFI_ERROR(Status)) { return SHELL_UNSUPPORTED; } // // parse the command line // Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE); if (EFI_ERROR(Status)) { if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDriver1HiiHandle, L"devices", ProblemParam); FreePool(ProblemParam); ShellStatus = SHELL_INVALID_PARAMETER; } /* else { ASSERT(FALSE); } */ } else { // // if more than 0 'value' parameters we have too many parameters // if (ShellCommandLineGetRawValue(Package, 1) != NULL){ // // error for too many parameters // ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDriver1HiiHandle, L"devices"); ShellStatus = SHELL_INVALID_PARAMETER; } else { // // get the language if necessary // Lang = ShellCommandLineGetValue(Package, L"-l"); if (Lang != NULL) { Language = AllocateZeroPool(StrSize(Lang)); AsciiSPrint(Language, StrSize(Lang), "%S", Lang); } else if (!ShellCommandLineGetFlag(Package, L"-l")){ ASSERT(Language == NULL); // Language = AllocateZeroPool(10); // AsciiSPrint(Language, 10, "en-us"); } else { ASSERT(Language == NULL); ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDriver1HiiHandle, L"devices", L"-l"); ShellCommandLineFreeVarList (Package); return (SHELL_INVALID_PARAMETER); } // // Print Header // if (ShellCommandLineGetFlag (Package, L"-sfo")) { ShellPrintHiiEx (-1, -1, Language, STRING_TOKEN (STR_GEN_SFO_HEADER), gShellDriver1HiiHandle, L"devices"); SfoFlag = TRUE; } else { ShellPrintHiiEx (-1, -1, Language, STRING_TOKEN (STR_DEVICES_HEADER_LINES), gShellDriver1HiiHandle); } // // loop through each handle // HandleList = GetHandleListByProtocol(NULL); ASSERT(HandleList != NULL); for (HandleListWalker = HandleList ; HandleListWalker != NULL && *HandleListWalker != NULL /*&& !EFI_ERROR(Status)*/ ; HandleListWalker++ ){ // // get all the info on each handle // Name = NULL; Status = GetDeviceHandleInfo(*HandleListWalker, &Type, &Cfg, &Diag, &Parents, &Devices, &Children, &Name, Language); if (Name != NULL && (Parents != 0 || Devices != 0 || Children != 0)) { ShellPrintHiiEx ( -1, -1, Language, SfoFlag?STRING_TOKEN (STR_DEVICES_ITEM_LINE_SFO):STRING_TOKEN (STR_DEVICES_ITEM_LINE), gShellDriver1HiiHandle, ConvertHandleToHandleIndex (*HandleListWalker), Type, Cfg?(SfoFlag?L'Y':L'X'):(SfoFlag?L'N':L'-'), Diag?(SfoFlag?L'Y':L'X'):(SfoFlag?L'N':L'-'), Parents, Devices, Children, Name!=NULL?Name:L"<UNKNOWN>"); } if (Name != NULL) { FreePool(Name); } if (ShellGetExecutionBreakFlag ()) { ShellStatus = SHELL_ABORTED; break; } } if (HandleList != NULL) { FreePool(HandleList); } } SHELL_FREE_NON_NULL(Language); ShellCommandLineFreeVarList (Package); } return (ShellStatus); }
/*! * \brief Retrives all the information needed to process the incoming SOAP * request. It finds the device and service info and also the callback * function to hand-over the request to the device application. * * \return UPNP_E_SUCCESS if successful else returns appropriate error. */ static int get_device_info( int iface, /*! [in] HTTP request. */ http_message_t *request, /*! [in] flag for a querry. */ int isQuery, /*! [in] Action request document. */ IXML_Document *actionDoc, /*! [in] . */ int AddressFamily, /*! [out] Device UDN string. */ OUT char device_udn[LINE_SIZE], /*! [out] Service ID string. */ char service_id[LINE_SIZE], /*! [out] callback function of the device application. */ Upnp_FunPtr *callback, /*! [out] cookie stored by device application. */ void **cookie) { struct Handle_Info *device_info; int device_hnd; service_info *serv_info; char save_char; /* error by default */ int ret_code = -1; const char *control_url; char *actionName = NULL; /* null-terminate pathquery of url */ control_url = request->uri.pathquery.buff; save_char = control_url[request->uri.pathquery.size]; ((char *)control_url)[request->uri.pathquery.size] = '\0'; HandleLock(); if (GetDeviceHandleInfo(iface, AddressFamily, &device_hnd, &device_info) != HND_DEVICE) goto error_handler; serv_info = FindServiceControlURLPath( &device_info->ServiceTable, control_url); if (!serv_info) goto error_handler; if (isQuery) { ret_code = check_soap_action_header(request, QUERY_STATE_VAR_URN, &actionName); if (ret_code != UPNP_E_SUCCESS && ret_code != UPNP_E_OUTOF_MEMORY) { ret_code = UPNP_E_INVALID_ACTION; goto error_handler; } /* check soap body */ ret_code = check_soap_body(actionDoc, QUERY_STATE_VAR_URN, actionName); free(actionName); if (ret_code != UPNP_E_SUCCESS) goto error_handler; } else { ret_code = check_soap_action_header(request, serv_info->serviceType, &actionName); if (ret_code != UPNP_E_SUCCESS && ret_code != UPNP_E_OUTOF_MEMORY) { ret_code = UPNP_E_INVALID_SERVICE; goto error_handler; } /* check soap body */ ret_code = check_soap_body(actionDoc, serv_info->serviceType, actionName); free(actionName); if (ret_code != UPNP_E_SUCCESS) { ret_code = UPNP_E_INVALID_SERVICE; goto error_handler; } } namecopy(service_id, serv_info->serviceId); namecopy(device_udn, serv_info->UDN); *callback = device_info->Callback; *cookie = device_info->Cookie; ret_code = 0; error_handler: /* restore */ ((char *)control_url)[request->uri.pathquery.size] = save_char; HandleUnlock(); return ret_code; }
/**************************************************************************** * Function : get_device_info * * Parameters : * IN http_message_t* request : HTTP request * IN int isQuery : flag for a querry * IN IXML_Document *actionDoc : action request document * OUT char device_udn[LINE_SIZE] : Device UDN string * OUT char service_id[LINE_SIZE] : Service ID string * OUT Upnp_FunPtr *callback : callback function of the device * application * OUT void** cookie : cookie stored by device application * * Description : This function retrives all the information needed to * process the incoming SOAP request. It finds the device and service info * and also the callback function to hand-over the request to the device * application. * * Return : int * UPNP_E_SUCCESS if successful else returns appropriate error * * Note : ****************************************************************************/ static int get_device_info( IN http_message_t * request, IN int isQuery, IN IXML_Document * actionDoc, OUT char device_udn[LINE_SIZE], OUT char service_id[LINE_SIZE], OUT Upnp_FunPtr * callback, OUT void **cookie ) { struct Handle_Info *device_info; int device_hnd; service_info *serv_info; char save_char; int ret_code = -1; // error by default const char *control_url; char *actionName = NULL; // null-terminate pathquery of url control_url = request->uri.pathquery.buff; save_char = control_url[request->uri.pathquery.size]; ((char *)control_url)[request->uri.pathquery.size] = '\0'; HandleLock(); if( GetDeviceHandleInfo( &device_hnd, &device_info ) != HND_DEVICE ) { goto error_handler; } if( ( serv_info = FindServiceControlURLPath( &device_info->ServiceTable, control_url ) ) == NULL ) { goto error_handler; } if( isQuery ) { ret_code = check_soap_action_header( request, QUERY_STATE_VAR_URN, &actionName ); if( ( ret_code != UPNP_E_SUCCESS ) && ( ret_code != UPNP_E_OUTOF_MEMORY ) ) { ret_code = UPNP_E_INVALID_ACTION; goto error_handler; } //check soap body ret_code = check_soap_body( actionDoc, QUERY_STATE_VAR_URN, actionName ); free( actionName ); if( ret_code != UPNP_E_SUCCESS ) { goto error_handler; } } else { ret_code = check_soap_action_header( request, serv_info->serviceType, &actionName ); if( ( ret_code != UPNP_E_SUCCESS ) && ( ret_code != UPNP_E_OUTOF_MEMORY ) ) { ret_code = UPNP_E_INVALID_SERVICE; goto error_handler; } //check soap body ret_code = check_soap_body( actionDoc, serv_info->serviceType, actionName ); free( actionName ); if( ret_code != UPNP_E_SUCCESS ) { ret_code = UPNP_E_INVALID_SERVICE; goto error_handler; } } namecopy( service_id, serv_info->serviceId ); namecopy( device_udn, serv_info->UDN ); *callback = device_info->Callback; *cookie = device_info->Cookie; ret_code = 0; error_handler: ((char *)control_url)[request->uri.pathquery.size] = save_char; // restore HandleUnlock(); return ret_code; }