/* this is run once a second. */ static void WANIPConnection_Update(timer_t t, PService psvc) { PWANIPConnectionData pdata = (PWANIPConnectionData) psvc->opaque; if (igd_config_generation != pdata->igd_generation) { pdata->igd_generation = igd_config_generation; mapmgr_update(); if (pdata->nportmappings != mapmgr_port_map_count()) { pdata->nportmappings = mapmgr_port_map_count(); mark_changed(psvc, VAR_PortMappingNumberOfEntries); } } update_external_address(psvc); update_connection_status(psvc); if ((psvc->flags & VAR_CHANGED) == VAR_CHANGED) { update_all_subscriptions(psvc); } }
/* Parse up the "Body>". The element immediately after that will be the name of the action to invoke, possibly preceded by a namespace. The action name may be followed by whitespace and other attributes, like namespace, etc., or it may immediatly by followed by the closing angle-bracket '>'. The elements contains within the action name are the arguments, also possibly preceded by a namespace (although the SOAP spec says they should not be) The list of argument will be terminated by a closing element that corresponds to the action name, also possibly preceded by a namespace. */ void soap_action(UFILE *up, PService psvc, char *soapaction, char *body) { char *ac, *u, *actstart, *colon; var_entry_t args[10]; int nargs = 0; char *argstart, *argend; char *valstart, *valend; char *sp, *eb; char pattern[80]; // split out the action name. if (soapaction != NULL && (ac = index(soapaction, '#')) != NULL) { ac++; snprintf(pattern, sizeof(pattern), ":Body>"); if ((u = strstr(body, pattern)) != NULL) { body = u + 1; if ((u = strstr(body, "<")) != NULL) { body = u + 1; actstart = body; sp = index(body, ' '); eb = index(body, '>'); if (sp && eb) { if (sp < eb) *sp = '\0'; body = eb + 1; if (body[-2] != '/') { snprintf(pattern, sizeof(pattern), "</%s", actstart); do { // parse each argument and put it into a list of <name, value> pointers. if ((argstart = strstr(body, "<")) == NULL) break; // if we are at the end of the argument list, // break out of the loop. if (strncmp(argstart, pattern, strlen(pattern)) == 0) break; argstart++; // advance over the '<' // although it is contrary to the spec, // some argument elements may have a namespace prefix. // in partcular, QueryStateVariable actions from windows XP // appear to do this but actions from Messenger do not. // In any case, be prepared to skip the namespace prefix. sp = index(argstart, ' '); eb = index(argstart, '>'); if (sp && eb && sp < eb) *sp = '\0'; *eb = '\0'; argend = eb; // DO NOT move this above the setting of argend to '/0'!!!! if ((colon = index(argstart, ':')) != NULL) argstart = colon + 1; if (argend[-1] == '/') { valstart = valend = argend; } else { valstart = argend + 1; if ((valend = index(valstart, '<')) == NULL) break; *valend = '\0'; } // put this argument into the arg list. args[nargs].name = argstart; args[nargs].value = valstart; nargs++; // point to the beginning of the next argument. body = valend + 1; } while (*body); } } } } // invoke that action UPNP_ACTION(psvc, ac, args, nargs); if ( strcmp(ac, "QueryStateVariable") == 0 ) { QueryStateVariable( up, psvc, ac, args, nargs); } else { dispatch( up, psvc, ac, args, nargs ); } if ((psvc->flags & VAR_CHANGED) == VAR_CHANGED) { update_all_subscriptions(psvc); } } else { soap_error( up, SOAP_INVALID_ACTION ); } }