Skip to content

Commit

Permalink
change command queue according to defold/extension-iap change
Browse files Browse the repository at this point in the history
  • Loading branch information
dev-masih committed Nov 15, 2019
1 parent 27c5435 commit 765fd6c
Show file tree
Hide file tree
Showing 3 changed files with 170 additions and 71 deletions.
93 changes: 28 additions & 65 deletions cafebazaar-iap/src/iapc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -65,27 +49,14 @@ struct IAPC
jmethodID m_ProcessPendingConsumables;
jmethodID m_FinishTransaction;

dmArray<IAPCCommand> 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;
Expand All @@ -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 )
Expand Down Expand Up @@ -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)
Expand All @@ -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
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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) {
Expand Down
98 changes: 98 additions & 0 deletions cafebazaar-iap/src/iapc_private.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,65 @@
#include <string.h>
#include <stdlib.h>


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)
Expand Down Expand Up @@ -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
50 changes: 44 additions & 6 deletions cafebazaar-iap/src/iapc_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,62 @@

#include <dmsdk/sdk.h>

// 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<IAPCCommand> 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

0 comments on commit 765fd6c

Please sign in to comment.