mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2025-09-25 12:53:19 +02:00
haze: tear down sessions on suspension
This commit is contained in:
parent
a1175feab1
commit
d0364c31cc
@ -45,12 +45,16 @@ namespace haze {
|
||||
int idx;
|
||||
|
||||
while (true) {
|
||||
/* Wait for up to 1 frame delay time to be cancelled. */
|
||||
Waiter cancel_waiter = waiterForUEvent(std::addressof(m_cancel_event));
|
||||
Result rc = waitObjects(std::addressof(idx), std::addressof(cancel_waiter), 1, FrameDelayNs);
|
||||
|
||||
/* Finish if we were cancelled. */
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Otherwise, signal the console update event. */
|
||||
if (svc::ResultTimedOut::Includes(rc)) {
|
||||
ueventSignal(std::addressof(m_event));
|
||||
}
|
||||
@ -154,13 +158,91 @@ namespace haze {
|
||||
|
||||
/* If the plus button is held, request immediate exit. */
|
||||
if (padGetButtonsDown(std::addressof(m_pad)) & HidNpadButton_Plus) {
|
||||
m_reactor->RequestStop();
|
||||
m_reactor->SetResult(haze::ResultStopRequested());
|
||||
}
|
||||
|
||||
/* Pump applet event loop. */
|
||||
/* Pump applet events, and check if exit was requested. */
|
||||
if (!appletMainLoop()) {
|
||||
m_reactor->RequestStop();
|
||||
m_reactor->SetResult(haze::ResultStopRequested());
|
||||
}
|
||||
|
||||
/* Check if focus was lost. */
|
||||
if (appletGetFocusState() == AppletFocusState_Background) {
|
||||
m_reactor->SetResult(haze::ResultFocusLost());
|
||||
}
|
||||
}
|
||||
private:
|
||||
static bool SuspendAndWaitForFocus() {
|
||||
/* Enable suspension with resume notification. */
|
||||
appletSetFocusHandlingMode(AppletFocusHandlingMode_SuspendHomeSleepNotify);
|
||||
|
||||
/* Pump applet events. */
|
||||
while (appletMainLoop()) {
|
||||
/* Check if focus was regained. */
|
||||
if (appletGetFocusState() != AppletFocusState_Background) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/* Exit was requested. */
|
||||
return false;
|
||||
}
|
||||
public:
|
||||
static void RunApplication() {
|
||||
/* Declare the object heap, to hold the database for an active session. */
|
||||
PtpObjectHeap ptp_object_heap;
|
||||
|
||||
/* Declare the event reactor, and components which use it. */
|
||||
EventReactor event_reactor;
|
||||
PtpResponder ptp_responder;
|
||||
ConsoleMainLoop console_main_loop;
|
||||
|
||||
/* Initialize the console.*/
|
||||
consoleInit(nullptr);
|
||||
|
||||
while (true) {
|
||||
/* Disable suspension. */
|
||||
appletSetFocusHandlingMode(AppletFocusHandlingMode_NoSuspend);
|
||||
|
||||
/* Declare result from serving to use. */
|
||||
Result rc;
|
||||
{
|
||||
/* Ensure we don't go to sleep while transferring files. */
|
||||
appletSetAutoSleepDisabled(true);
|
||||
|
||||
/* Clear the event reactor. */
|
||||
event_reactor.SetResult(ResultSuccess());
|
||||
|
||||
/* Configure the PTP responder and console main loop. */
|
||||
ptp_responder.Initialize(std::addressof(event_reactor), std::addressof(ptp_object_heap));
|
||||
console_main_loop.Initialize(std::addressof(event_reactor), std::addressof(ptp_object_heap));
|
||||
|
||||
/* Ensure we maintain a clean state on exit. */
|
||||
ON_SCOPE_EXIT {
|
||||
/* Finalize the console main loop and PTP responder. */
|
||||
console_main_loop.Finalize();
|
||||
ptp_responder.Finalize();
|
||||
|
||||
/* Restore auto sleep setting. */
|
||||
appletSetAutoSleepDisabled(false);
|
||||
};
|
||||
|
||||
/* Begin processing requests. */
|
||||
rc = ptp_responder.LoopProcess();
|
||||
}
|
||||
|
||||
/* If focus was lost, try to pump the applet main loop until we receive focus again. */
|
||||
if (haze::ResultFocusLost::Includes(rc) && SuspendAndWaitForFocus()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Otherwise, enable suspension and finish. */
|
||||
appletSetFocusHandlingMode(AppletFocusHandlingMode_SuspendHomeSleep);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Finalize the console. */
|
||||
consoleExit(nullptr);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -30,15 +30,15 @@ namespace haze {
|
||||
EventConsumer *m_consumers[svc::ArgumentHandleCountMax];
|
||||
Waiter m_waiters[svc::ArgumentHandleCountMax];
|
||||
s32 m_num_wait_objects;
|
||||
bool m_stop_requested;
|
||||
Result m_result;
|
||||
public:
|
||||
constexpr explicit EventReactor() : m_consumers(), m_waiters(), m_num_wait_objects(), m_stop_requested() { /* ... */ }
|
||||
constexpr explicit EventReactor() : m_consumers(), m_waiters(), m_num_wait_objects(), m_result(ResultSuccess()) { /* ... */ }
|
||||
|
||||
bool AddConsumer(EventConsumer *consumer, Waiter waiter);
|
||||
void RemoveConsumer(EventConsumer *consumer);
|
||||
public:
|
||||
void RequestStop() { m_stop_requested = true; }
|
||||
bool GetStopRequested() const { return m_stop_requested; }
|
||||
void SetResult(Result r) { m_result = r; }
|
||||
Result GetResult() const { return m_result; }
|
||||
public:
|
||||
template <typename... Args>
|
||||
Result WaitFor(s32 *out_arg_waiter, Args &&... arg_waiters) {
|
||||
|
@ -45,7 +45,7 @@ namespace haze {
|
||||
const Result rc = func(std::forward<Args>(args)...);
|
||||
|
||||
/* If the event loop was stopped, return that here. */
|
||||
R_UNLESS(!m_reactor->GetStopRequested(), haze::ResultStopRequested());
|
||||
R_TRY(m_reactor->GetResult());
|
||||
|
||||
/* Otherwise, return the call result. */
|
||||
R_RETURN(rc);
|
||||
|
@ -40,9 +40,10 @@ namespace haze {
|
||||
Result Initialize(EventReactor *reactor, PtpObjectHeap *object_heap);
|
||||
void Finalize();
|
||||
public:
|
||||
Result HandleRequest();
|
||||
Result LoopProcess();
|
||||
private:
|
||||
/* Request handling. */
|
||||
Result HandleRequest();
|
||||
Result HandleRequestImpl();
|
||||
Result HandleCommandRequest(PtpDataParser &dp);
|
||||
void ForceCloseSession();
|
||||
|
@ -26,16 +26,16 @@ namespace haze {
|
||||
R_DEFINE_ERROR_RESULT(NotConfigured, 2);
|
||||
R_DEFINE_ERROR_RESULT(TransferFailed, 3);
|
||||
R_DEFINE_ERROR_RESULT(StopRequested, 4);
|
||||
R_DEFINE_ERROR_RESULT(EndOfTransmission, 5);
|
||||
R_DEFINE_ERROR_RESULT(UnknownPacketType, 6);
|
||||
R_DEFINE_ERROR_RESULT(SessionNotOpen, 7);
|
||||
R_DEFINE_ERROR_RESULT(OutOfMemory, 8);
|
||||
R_DEFINE_ERROR_RESULT(InvalidObjectId, 9);
|
||||
R_DEFINE_ERROR_RESULT(InvalidStorageId, 10);
|
||||
R_DEFINE_ERROR_RESULT(OperationNotSupported, 11);
|
||||
R_DEFINE_ERROR_RESULT(UnknownRequestType, 12);
|
||||
R_DEFINE_ERROR_RESULT(UnknownPropertyCode, 13);
|
||||
R_DEFINE_ERROR_RESULT(InvalidPropertyValue, 14);
|
||||
R_DEFINE_ERROR_RESULT(GeneralFailure, 15);
|
||||
R_DEFINE_ERROR_RESULT(FocusLost, 5);
|
||||
R_DEFINE_ERROR_RESULT(EndOfTransmission, 6);
|
||||
R_DEFINE_ERROR_RESULT(UnknownPacketType, 7);
|
||||
R_DEFINE_ERROR_RESULT(SessionNotOpen, 8);
|
||||
R_DEFINE_ERROR_RESULT(OutOfMemory, 9);
|
||||
R_DEFINE_ERROR_RESULT(InvalidObjectId, 10);
|
||||
R_DEFINE_ERROR_RESULT(InvalidStorageId, 11);
|
||||
R_DEFINE_ERROR_RESULT(OperationNotSupported, 12);
|
||||
R_DEFINE_ERROR_RESULT(UnknownRequestType, 13);
|
||||
R_DEFINE_ERROR_RESULT(UnknownPropertyCode, 14);
|
||||
R_DEFINE_ERROR_RESULT(InvalidPropertyValue, 15);
|
||||
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ namespace haze {
|
||||
HAZE_ASSERT(m_num_wait_objects + num_arg_waiters <= svc::ArgumentHandleCountMax);
|
||||
|
||||
while (true) {
|
||||
R_UNLESS(!m_stop_requested, haze::ResultStopRequested());
|
||||
R_TRY(m_result);
|
||||
|
||||
/* Insert waiters from argument list. */
|
||||
for (s32 i = 0; i < num_arg_waiters; i++) {
|
||||
|
@ -17,38 +17,8 @@
|
||||
#include <haze/console_main_loop.hpp>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
/* Declare the object heap, to hold the database for an active session. */
|
||||
haze::PtpObjectHeap ptp_object_heap;
|
||||
|
||||
/* Declare the event reactor, and components which use it. */
|
||||
haze::EventReactor event_reactor;
|
||||
haze::PtpResponder ptp_responder;
|
||||
haze::ConsoleMainLoop console_main_loop;
|
||||
|
||||
/* Initialize the console.*/
|
||||
consoleInit(nullptr);
|
||||
|
||||
/* Ensure we don't go to sleep while transferring files. */
|
||||
appletSetAutoSleepDisabled(true);
|
||||
|
||||
/* Configure the PTP responder and console main loop. */
|
||||
ptp_responder.Initialize(std::addressof(event_reactor), std::addressof(ptp_object_heap));
|
||||
console_main_loop.Initialize(std::addressof(event_reactor), std::addressof(ptp_object_heap));
|
||||
|
||||
/* Process events until the user requests exit. */
|
||||
while (!event_reactor.GetStopRequested()) {
|
||||
ptp_responder.HandleRequest();
|
||||
}
|
||||
|
||||
/* Finalize the console main loop and PTP responder. */
|
||||
console_main_loop.Finalize();
|
||||
ptp_responder.Finalize();
|
||||
|
||||
/* Restore auto sleep setting. */
|
||||
appletSetAutoSleepDisabled(false);
|
||||
|
||||
/* Finalize the console. */
|
||||
consoleExit(nullptr);
|
||||
/* Run the application. */
|
||||
haze::ConsoleMainLoop::RunApplication();
|
||||
|
||||
/* Return to the loader. */
|
||||
return 0;
|
||||
|
@ -191,6 +191,25 @@ namespace haze {
|
||||
m_fs.Finalize();
|
||||
}
|
||||
|
||||
Result PtpResponder::LoopProcess() {
|
||||
while (true) {
|
||||
/* Try to handle a request. */
|
||||
R_TRY_CATCH(this->HandleRequest()) {
|
||||
R_CATCH(haze::ResultStopRequested, haze::ResultFocusLost) {
|
||||
/* If we encountered a stop condition, we're done.*/
|
||||
R_THROW(R_CURRENT_RESULT);
|
||||
}
|
||||
R_CATCH_ALL() {
|
||||
/* On other failures, try to handle another request. */
|
||||
continue;
|
||||
}
|
||||
} R_END_TRY_CATCH;
|
||||
|
||||
/* Otherwise, handle the next request. */
|
||||
/* ... */
|
||||
}
|
||||
}
|
||||
|
||||
Result PtpResponder::HandleRequest() {
|
||||
ON_RESULT_FAILURE {
|
||||
/* For general failure modes, the failure is unrecoverable. Close the session. */
|
||||
@ -223,9 +242,6 @@ namespace haze {
|
||||
/* Errors from fs are typically recoverable. */
|
||||
R_TRY(this->WriteResponse(PtpResponseCode_GeneralError));
|
||||
}
|
||||
R_CATCH_ALL() {
|
||||
R_THROW(haze::ResultGeneralFailure());
|
||||
}
|
||||
} R_END_TRY_CATCH;
|
||||
|
||||
R_SUCCEED();
|
||||
|
Loading…
Reference in New Issue
Block a user