static void service_lock(void)
{
	ithread_mutex_lock(&transport_mutex);
	if (transport_service_.last_change) {
		UPnPLastChangeCollector_start(transport_service_.last_change);
	}
}
Example #2
0
static void service_lock(void)
{
	ithread_mutex_lock(&control_mutex);
	if (control_service_.last_change) {
		UPnPLastChangeCollector_start(control_service_.last_change);
	}
}
Example #3
0
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;
}