From 765fd6c2dacf687c09cf7585003c0d3437e4748e Mon Sep 17 00:00:00 2001 From: Masih Akbari Date: Fri, 15 Nov 2019 18:45:06 +0330 Subject: [PATCH] change command queue according to defold/extension-iap change --- cafebazaar-iap/src/iapc.cpp | 93 +++++++++------------------ cafebazaar-iap/src/iapc_private.cpp | 98 +++++++++++++++++++++++++++++ cafebazaar-iap/src/iapc_private.h | 50 +++++++++++++-- 3 files changed, 170 insertions(+), 71 deletions(-) diff --git a/cafebazaar-iap/src/iapc.cpp b/cafebazaar-iap/src/iapc.cpp index ac11186..c836a4d 100644 --- a/cafebazaar-iap/src/iapc.cpp +++ b/cafebazaar-iap/src/iapc.cpp @@ -9,22 +9,6 @@ #define LIB_NAME "iapc" -struct IAPC; - -#define CMD_PRODUCT_RESULT (0) -#define CMD_PURCHASE_RESULT (1) - -struct DM_ALIGNED(16) IAPCCommand -{ - IAPCCommand() - { - memset(this, 0, sizeof(IAPCCommand)); - } - uint32_t m_Command; - int32_t m_ResponseCode; - void* m_Data1; -}; - static JNIEnv* Attach() { JNIEnv* env; @@ -54,7 +38,7 @@ struct IAPC int m_Self; bool m_autoFinishTransactions; lua_State* m_L; - IAPCListener m_Listener; + IAPCListener m_Listener; jobject m_IAPC; jobject m_IAPCJNI; @@ -65,27 +49,14 @@ struct IAPC jmethodID m_ProcessPendingConsumables; jmethodID m_FinishTransaction; - dmArray m_CommandsQueue; - dmMutex::HMutex m_Mutex; + IAPCCommandQueue m_CommandQueue; }; static IAPC g_IAPC; -static void QueueCommand(IAPCCommand* cmd) -{ - DM_MUTEX_SCOPED_LOCK(g_IAPC.m_Mutex); - - if(g_IAPC.m_CommandsQueue.Full()) - { - g_IAPC.m_CommandsQueue.OffsetCapacity(2); - } - g_IAPC.m_CommandsQueue.Push(*cmd); -} - -static void VerifyCallback(lua_State* L) +static void ResetCallback(lua_State* L) { if (g_IAPC.m_Callback != LUA_NOREF) { - dmLogError("Unexpected callback set"); dmScript::Unref(L, LUA_REGISTRYINDEX, g_IAPC.m_Callback); dmScript::Unref(L, LUA_REGISTRYINDEX, g_IAPC.m_Self); g_IAPC.m_Callback = LUA_NOREF; @@ -97,7 +68,7 @@ static void VerifyCallback(lua_State* L) static int IAPC_List(lua_State* L) { int top = lua_gettop(L); - VerifyCallback(L); + ResetCallback(L); char* buf = IAPC_List_CreateBuffer(L); if( buf == 0 ) @@ -257,14 +228,14 @@ JNIEXPORT void JNICALL Java_com_defold_iapc_IapJNI_onProductsResult__ILjava_lang } IAPCCommand cmd; - cmd.m_Command = CMD_PRODUCT_RESULT; + cmd.m_Command = IAPC_PRODUCT_RESULT; cmd.m_ResponseCode = responseCode; if (pl) { - cmd.m_Data1 = strdup(pl); + cmd.m_Data = strdup(pl); env->ReleaseStringUTFChars(productList, pl); } - QueueCommand(&cmd); + IAPC_Queue_Push(&g_IAPC.m_CommandQueue, &cmd); } JNIEXPORT void JNICALL Java_com_defold_iapc_IapJNI_onPurchaseResult__ILjava_lang_String_2(JNIEnv* env, jobject, jint responseCode, jstring purchaseData) @@ -276,14 +247,14 @@ JNIEXPORT void JNICALL Java_com_defold_iapc_IapJNI_onPurchaseResult__ILjava_lang } IAPCCommand cmd; - cmd.m_Command = CMD_PURCHASE_RESULT; + cmd.m_Command = IAPC_PURCHASE_RESULT; cmd.m_ResponseCode = responseCode; if (pd) { - cmd.m_Data1 = strdup(pd); + cmd.m_Data = strdup(pd); env->ReleaseStringUTFChars(purchaseData, pd); } - QueueCommand(&cmd); + IAPC_Queue_Push(&g_IAPC.m_CommandQueue, &cmd); } #ifdef __cplusplus @@ -317,7 +288,7 @@ static void HandleProductResult(const IAPCCommand* cmd) if (cmd->m_ResponseCode == BILLING_RESPONSE_RESULT_OK) { dmJson::Document doc; - dmJson::Result r = dmJson::Parse((const char*) cmd->m_Data1, &doc); + dmJson::Result r = dmJson::Parse((const char*) cmd->m_Data, &doc); if (r == dmJson::RESULT_OK && doc.m_NodeCount > 0) { char err_str[128]; if (dmScript::JsonToLua(L, &doc, 0, err_str, sizeof(err_str)) < 0) { @@ -380,9 +351,9 @@ static void HandlePurchaseResult(const IAPCCommand* cmd) } if (cmd->m_ResponseCode == BILLING_RESPONSE_RESULT_OK) { - if (cmd->m_Data1 != 0) { + if (cmd->m_Data != 0) { dmJson::Document doc; - dmJson::Result r = dmJson::Parse((const char*) cmd->m_Data1, &doc); + dmJson::Result r = dmJson::Parse((const char*) cmd->m_Data, &doc); if (r == dmJson::RESULT_OK && doc.m_NodeCount > 0) { char err_str[128]; if (dmScript::JsonToLua(L, &doc, 0, err_str, sizeof(err_str)) < 0) { @@ -426,8 +397,7 @@ static dmExtension::Result InitializeIAPC(dmExtension::Params* params) // TODO: Life-cycle managaemnt is *budget*. No notion of "static initalization" // Extend extension functionality with per system initalization? if (g_IAPC.m_InitCount == 0) { - g_IAPC.m_CommandsQueue.SetCapacity(2); - g_IAPC.m_Mutex = dmMutex::New(); + IAPC_Queue_Create(&g_IAPC.m_CommandQueue); g_IAPC.m_autoFinishTransactions = dmConfigFile::GetInt(params->m_ConfigFile, "iap.auto_finish_transactions", 1) == 1; @@ -478,42 +448,35 @@ static dmExtension::Result InitializeIAPC(dmExtension::Params* params) return dmExtension::RESULT_OK; } -static dmExtension::Result UpdateIAPC(dmExtension::Params* params) +static void IAPC_OnCommand(IAPCCommand* cmd, void*) { - if (g_IAPC.m_CommandsQueue.Empty()) - { - return dmExtension::RESULT_OK; - } - - DM_MUTEX_SCOPED_LOCK(g_IAPC.m_Mutex); - - for(uint32_t i = 0; i != g_IAPC.m_CommandsQueue.Size(); ++i) + switch (cmd->m_Command) { - IAPCCommand& cmd = g_IAPC.m_CommandsQueue[i]; - switch (cmd.m_Command) - { - case CMD_PRODUCT_RESULT: - HandleProductResult(&cmd); + case IAPC_PRODUCT_RESULT: + HandleProductResult(cmd); break; - case CMD_PURCHASE_RESULT: - HandlePurchaseResult(&cmd); + case IAPC_PURCHASE_RESULT: + HandlePurchaseResult(cmd); break; default: assert(false); } - if (cmd.m_Data1) { - free(cmd.m_Data1); + if (cmd->m_Data) { + free(cmd->m_Data); } - } - g_IAPC.m_CommandsQueue.SetSize(0); +} + +static dmExtension::Result UpdateIAPC(dmExtension::Params* params) +{ + IAPC_Queue_Flush(&g_IAPC.m_CommandQueue, IAPC_OnCommand, 0); return dmExtension::RESULT_OK; } static dmExtension::Result FinalizeIAPC(dmExtension::Params* params) { - dmMutex::Delete(g_IAPC.m_Mutex); + IAPC_Queue_Destroy(&g_IAPC.m_CommandQueue); --g_IAPC.m_InitCount; if (params->m_L == g_IAPC.m_Listener.m_L && g_IAPC.m_Listener.m_Callback != LUA_NOREF) { diff --git a/cafebazaar-iap/src/iapc_private.cpp b/cafebazaar-iap/src/iapc_private.cpp index d6128c9..ec4cf73 100644 --- a/cafebazaar-iap/src/iapc_private.cpp +++ b/cafebazaar-iap/src/iapc_private.cpp @@ -7,6 +7,65 @@ #include #include + +IAPCListener::IAPCListener() { + IAPC_ClearCallback(this); +} + +void IAPC_ClearCallback(IAPCListener* callback) +{ + callback->m_L = 0; + callback->m_Callback = LUA_NOREF; + callback->m_Self = LUA_NOREF; +} + +void IAPC_RegisterCallback(lua_State* L, int index, IAPCListener* callback) +{ + luaL_checktype(L, index, LUA_TFUNCTION); + lua_pushvalue(L, index); + callback->m_Callback = dmScript::Ref(L, LUA_REGISTRYINDEX); + + dmScript::GetInstance(L); + callback->m_Self = dmScript::Ref(L, LUA_REGISTRYINDEX); + + callback->m_L = L; +} + +void IAPC_UnregisterCallback(IAPCListener* callback) +{ + if (LUA_NOREF != callback->m_Callback) + dmScript::Unref(callback->m_L, LUA_REGISTRYINDEX, callback->m_Callback); + if (LUA_NOREF != callback->m_Self) + dmScript::Unref(callback->m_L, LUA_REGISTRYINDEX, callback->m_Self); + callback->m_Callback = LUA_NOREF; + callback->m_Self = LUA_NOREF; + callback->m_L = 0; +} + +bool IAPC_SetupCallback(IAPCListener* callback) +{ + lua_State* L = callback->m_L; + lua_rawgeti(L, LUA_REGISTRYINDEX, callback->m_Callback); + + // Setup self + lua_rawgeti(L, LUA_REGISTRYINDEX, callback->m_Self); + lua_pushvalue(L, -1); + dmScript::SetInstance(L); + + if (!dmScript::IsInstanceValid(L)) + { + dmLogError("Could not run callback because the instance has been deleted."); + lua_pop(L, 2); + return false; + } + return true; +} + +bool IAPC_CallbackIsValid(IAPCListener* callback) +{ + return callback != 0 && callback->m_L != 0 && callback->m_Callback != LUA_NOREF && callback->m_Self != LUA_NOREF; +} + // Creates a comma separated string, given a table where all values are strings (or numbers) // Returns a malloc'ed string, which the caller must free char* IAPC_List_CreateBuffer(lua_State* L) @@ -91,4 +150,43 @@ void IAPC_PushConstants(lua_State* L) #undef SETCONSTANT } + +void IAPC_Queue_Create(IAPCCommandQueue* queue) +{ + queue->m_Mutex = dmMutex::New(); +} + +void IAPC_Queue_Destroy(IAPCCommandQueue* queue) +{ + dmMutex::Delete(queue->m_Mutex); +} + +void IAPC_Queue_Push(IAPCCommandQueue* queue, IAPCCommand* cmd) +{ + DM_MUTEX_SCOPED_LOCK(queue->m_Mutex); + + if(queue->m_Commands.Full()) + { + queue->m_Commands.OffsetCapacity(2); + } + queue->m_Commands.Push(*cmd); +} + +void IAPC_Queue_Flush(IAPCCommandQueue* queue, IAPCCommandFn fn, void* ctx) +{ + assert(fn != 0); + if (queue->m_Commands.Empty()) + { + return; + } + + DM_MUTEX_SCOPED_LOCK(queue->m_Mutex); + + for(uint32_t i = 0; i != queue->m_Commands.Size(); ++i) + { + fn(&queue->m_Commands[i], ctx); + } + queue->m_Commands.SetSize(0); +} + #endif // DM_PLATFORM_ANDROID diff --git a/cafebazaar-iap/src/iapc_private.h b/cafebazaar-iap/src/iapc_private.h index 9fd5056..75345ff 100644 --- a/cafebazaar-iap/src/iapc_private.h +++ b/cafebazaar-iap/src/iapc_private.h @@ -5,24 +5,62 @@ #include +// TODO: Rename Callback struct IAPCListener { - IAPCListener() - { - m_L = 0; - m_Callback = LUA_NOREF; - m_Self = LUA_NOREF; - } + IAPCListener(); + lua_State* m_L; int m_Callback; int m_Self; }; +enum EIAPCCommand +{ + IAPC_PRODUCT_RESULT, + IAPC_PURCHASE_RESULT, +}; + +struct DM_ALIGNED(16) IAPCCommand +{ + IAPCCommand() + { + memset(this, 0, sizeof(IAPCCommand)); + } + + // Used for storing eventual callback info (if needed) + IAPCListener m_Callback; + + // THe actual command payload + int32_t m_Command; + int32_t m_ResponseCode; + void* m_Data; +}; + +struct IAPCCommandQueue +{ + dmArray m_Commands; + dmMutex::HMutex m_Mutex; +}; + +void IAPC_ClearCallback(IAPCListener* callback); +void IAPC_RegisterCallback(lua_State* L, int index, IAPCListener* callback); +void IAPC_UnregisterCallback(IAPCListener* callback); +bool IAPC_SetupCallback(IAPCListener* callback); +bool IAPC_CallbackIsValid(IAPCListener* callback); char* IAPC_List_CreateBuffer(lua_State* L); void IAPC_PushError(lua_State* L, const char* error, int reason); void IAPC_PushConstants(lua_State* L); +typedef void (*IAPCCommandFn)(IAPCCommand* cmd, void* ctx); + +void IAPC_Queue_Create(IAPCCommandQueue* queue); +void IAPC_Queue_Destroy(IAPCCommandQueue* queue); +// The command is copied by value into the queue +void IAPC_Queue_Push(IAPCCommandQueue* queue, IAPCCommand* cmd); +void IAPC_Queue_Flush(IAPCCommandQueue* queue, IAPCCommandFn fn, void* ctx); + #endif #endif // DM_PLATFORM_ANDROID