static void service_lock(void) { ithread_mutex_lock(&transport_mutex); if (transport_service_.last_change) { UPnPLastChangeCollector_start(transport_service_.last_change); } }
static void service_lock(void) { ithread_mutex_lock(&control_mutex); if (control_service_.last_change) { UPnPLastChangeCollector_start(control_service_.last_change); } }
static int handle_action_request(struct upnp_device *priv, struct Upnp_Action_Request *ar_event) { struct service *event_service; struct action *event_action; event_service = find_service(priv->upnp_device_descriptor, ar_event->ServiceID); event_action = find_action(event_service, ar_event->ActionName); if (event_action == NULL) { Log_error("upnp", "Unknown action '%s' for service '%s'", ar_event->ActionName, ar_event->ServiceID); ar_event->ActionResult = NULL; ar_event->ErrCode = 401; return -1; } // We want to send the LastChange event only after the action is // finished - just to be conservative, we don't know how clients // react to get LastChange notifictions while in the middle of // issuing an action. // // So we nest the change collector level here, so that we only send the // LastChange after the action is finished (). // // Note, this is, in fact, only a preparation and not yet working as // described above: we are still in the middle // of executing the event-callback while sending the last change // event implicitly when calling UPnPLastChangeCollector_finish() below. // It would be good to enqueue the upnp_device_notify() after // the action event is finished. if (event_service->last_change) { ithread_mutex_lock(event_service->service_mutex); UPnPLastChangeCollector_start(event_service->last_change); ithread_mutex_unlock(event_service->service_mutex); } #ifdef ENABLE_ACTION_LOGGING { char *action_request_xml = NULL; if (ar_event->ActionRequest) { action_request_xml = ixmlDocumenttoString( ar_event->ActionRequest); } Log_info("upnp", "Action '%s'; Request: %s", ar_event->ActionName, action_request_xml); free(action_request_xml); } #endif if (event_action->callback) { struct action_event event; int rc; event.request = ar_event; event.status = 0; event.service = event_service; event.device = priv; rc = (event_action->callback) (&event); if (rc == 0) { ar_event->ErrCode = UPNP_E_SUCCESS; #ifdef ENABLE_ACTION_LOGGING if (ar_event->ActionResult) { char *action_result_xml = NULL; action_result_xml = ixmlDocumenttoString( ar_event->ActionResult); Log_info("upnp", "Action '%s' OK; Response %s", ar_event->ActionName, action_result_xml); free(action_result_xml); } else { Log_info("upnp", "Action '%s' OK", ar_event->ActionName); } #endif } if (ar_event->ActionResult == NULL) { ar_event->ActionResult = UpnpMakeActionResponse(ar_event->ActionName, event_service->service_type, 0, NULL); } } else { Log_error("upnp", "Got a valid action, but no handler defined (!)\n" " ErrCode: %d\n" " Socket: %d\n" " ErrStr: '%s'\n" " ActionName: '%s'\n" " DevUDN: '%s'\n" " ServiceID: '%s'\n", ar_event->ErrCode, ar_event->Socket, ar_event->ErrStr, ar_event->ActionName, ar_event->DevUDN, ar_event->ServiceID); ar_event->ErrCode = UPNP_E_SUCCESS; } if (event_service->last_change) { // See comment above. ithread_mutex_lock(event_service->service_mutex); UPnPLastChangeCollector_finish(event_service->last_change); ithread_mutex_unlock(event_service->service_mutex); } return 0; }