Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 75 additions & 24 deletions src/native/CallbackWrapper.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
#ifndef CALLBACK_WRAPPER_H
#define CALLBACK_WRAPPER_H

#ifndef SIZE_MAX
#define SIZE_MAX ((size_t)(-1))
#endif
Expand All @@ -10,51 +13,99 @@ typedef std::wstring STRING;
typedef std::string STRING;
#endif

class CallbackWrapper : public Napi::AsyncWorker
struct CallbackData
{
public:
CallbackWrapper(Napi::Function &callback) : Napi::AsyncWorker(callback)
{
}
uint32_t status;
virtual ~CallbackData() = default;
};

private:
void Execute()
struct StatusCallbackData : public CallbackData
{
StatusCallbackData(uint32_t s)
{
status = s;
}
};

struct ReleaseUpdateCallbackData : public CallbackData
{
STRING releaseJson;
void *userData;

void OnOK()
ReleaseUpdateCallbackData(uint32_t s, const STRING &json, void *ud)
: releaseJson(json), userData(ud)
{
Napi::HandleScope scope(Env());
Callback().Call({Napi::Number::New(Env(), status)});
status = s;
}
};

class ReleaseUpdateCallbackWrapper : public Napi::AsyncWorker
class CallbackWrapper
{
public:
ReleaseUpdateCallbackWrapper(Napi::Function &callback) : Napi::AsyncWorker(callback)
CallbackWrapper(Napi::Env env, Napi::Function callback)
{
tsfn = Napi::ThreadSafeFunction::New(
env,
callback,
"LexActivatorCallback",
0, // Unlimited queue
1 // Initial thread count
);
}

~CallbackWrapper()
{
tsfn.Abort();
tsfn.Release();
}

void Call(uint32_t status)
{
auto *data = new StatusCallbackData(status);
napi_status napiStatus = tsfn.NonBlockingCall(data, InvokeStatusCallback);
if (napiStatus != napi_ok)
{
delete data;
}
}

void Call(uint32_t status, const STRING &releaseJson, void *userData)
{
auto *data = new ReleaseUpdateCallbackData(status, releaseJson, userData);
napi_status napiStatus = tsfn.NonBlockingCall(data, InvokeReleaseUpdateCallback);
if (napiStatus != napi_ok)
{
delete data;
}
}
uint32_t status;
STRING releaseJson;
void* userData;

private:
void Execute()
Napi::ThreadSafeFunction tsfn;

static void InvokeStatusCallback(Napi::Env env, Napi::Function jsCallback, StatusCallbackData *data)
{
if (env != nullptr && jsCallback != nullptr && data != nullptr)
{
Napi::HandleScope scope(env);
jsCallback.Call({Napi::Number::New(env, data->status)});
}
delete data;
}

void OnOK()
static void InvokeReleaseUpdateCallback(Napi::Env env, Napi::Function jsCallback, ReleaseUpdateCallbackData *data)
{
Napi::HandleScope scope(Env());
if (env != nullptr && jsCallback != nullptr && data != nullptr)
{
Napi::HandleScope scope(env);
#ifdef _WIN32
// convert STRING to utf16 encoded string
const wchar_t *releaseJsonPtr = releaseJson.c_str();
const char16_t *utf16StringPtr = reinterpret_cast<const char16_t *>(releaseJsonPtr);
Callback().Call({Napi::Number::New(Env(), status), Napi::String::New(Env(), utf16StringPtr), Napi::External<void>::New(Env(), userData)});
const wchar_t *releaseJsonPtr = data->releaseJson.c_str();
const char16_t *utf16StringPtr = reinterpret_cast<const char16_t *>(releaseJsonPtr);
jsCallback.Call({Napi::Number::New(env, data->status), Napi::String::New(env, utf16StringPtr),Napi::External<void>::New(env, data->userData)});
#else
Callback().Call({Napi::Number::New(Env(), status), Napi::String::New(Env(), releaseJson), Napi::External<void>::New(Env(), userData)});
jsCallback.Call({Napi::Number::New(env, data->status), Napi::String::New(env, data->releaseJson), Napi::External<void>::New(env, data->userData)});
#endif
}
delete data;
}
};
};
#endif // CALLBACK_WRAPPER_H
77 changes: 61 additions & 16 deletions src/native/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <string>
#include <locale>
#include <map>
#include <mutex>

using namespace ::std;

Expand All @@ -23,8 +24,9 @@ const char *MISSING_LICENSE_KEY = "License key not set";

map<STRING, CallbackWrapper *> LicenseCallbacks;
map<STRING, CallbackWrapper *> ReleaseCallbacks;
map<STRING, ReleaseUpdateCallbackWrapper *> ReleaseUpdateCallbacks;
map<STRING, CallbackWrapper *> ReleaseUpdateCallbacks;

std::mutex callbackMutex;

STRING toEncodedString(Napi::String input)
{
Expand All @@ -44,8 +46,14 @@ void licenseCallback(uint32_t status)
{
return;
}
LicenseCallbacks[STRING(licenseKey)]->status = status;
LicenseCallbacks[STRING(licenseKey)]->Queue();
{
std::lock_guard<std::mutex> lock(callbackMutex);
auto it = LicenseCallbacks.find(STRING(licenseKey));
if (it != LicenseCallbacks.end() && it->second != nullptr)
{
it->second->Call(status);
}
}
}

void softwareReleaseUpdateCallback(uint32_t status)
Expand All @@ -55,21 +63,31 @@ void softwareReleaseUpdateCallback(uint32_t status)
{
return;
}
ReleaseCallbacks[STRING(licenseKey)]->status = status;
ReleaseCallbacks[STRING(licenseKey)]->Queue();
{
std::lock_guard<std::mutex> lock(callbackMutex);
auto it = ReleaseCallbacks.find(STRING(licenseKey));
if (it != ReleaseCallbacks.end() && it->second != nullptr)
{
it->second->Call(status);
}
}
}

void releaseUpdateCallback(uint32_t status, CONST_CHARTYPE releaseJson, void* userData)
{
{
CHARTYPE licenseKey[256];
if (GetLicenseKey(licenseKey, 256) != LA_OK)
{
return;
}
ReleaseUpdateCallbacks[STRING(licenseKey)]->status = status;
ReleaseUpdateCallbacks[STRING(licenseKey)]->releaseJson.assign(releaseJson);
ReleaseUpdateCallbacks[STRING(licenseKey)]->userData = NULL;
ReleaseUpdateCallbacks[STRING(licenseKey)]->Queue();
{
std::lock_guard<std::mutex> lock(callbackMutex);
auto it = ReleaseUpdateCallbacks.find(STRING(licenseKey));
if (it != ReleaseUpdateCallbacks.end() && it->second != nullptr)
{
it->second->Call(status, STRING(releaseJson), userData);
}
}
}

Napi::Value setProductFile(const Napi::CallbackInfo &info)
Expand Down Expand Up @@ -257,8 +275,17 @@ Napi::Value setLicenseCallback(const Napi::CallbackInfo &info)
Napi::Error::New(env, MISSING_LICENSE_KEY).ThrowAsJavaScriptException();
return env.Null();
}
LicenseCallbacks[STRING(licenseKey)] = new CallbackWrapper(callback);
LicenseCallbacks[STRING(licenseKey)]->SuppressDestruct();
STRING key(licenseKey);
// Clean up existing callback if present
{
std::lock_guard<std::mutex> lock(callbackMutex);
auto it = LicenseCallbacks.find(key);
if (it != LicenseCallbacks.end() && it->second != nullptr)
{
delete it->second;
}
LicenseCallbacks[key] = new CallbackWrapper(env, callback);
}
return Napi::Number::New(env, SetLicenseCallback(licenseCallback));
}

Expand Down Expand Up @@ -1355,8 +1382,17 @@ Napi::Value checkReleaseUpdate(const Napi::CallbackInfo &info)
Napi::Error::New(env, MISSING_LICENSE_KEY).ThrowAsJavaScriptException();
return env.Null();
}
ReleaseUpdateCallbacks[STRING(licenseKey)] = new ReleaseUpdateCallbackWrapper(callback);
ReleaseUpdateCallbacks[STRING(licenseKey)]->SuppressDestruct();
STRING key(licenseKey);
// Clean up existing callback if present
{
std::lock_guard<std::mutex> lock(callbackMutex);
auto it = ReleaseUpdateCallbacks.find(key);
if (it != ReleaseUpdateCallbacks.end() && it->second != nullptr)
{
delete it->second;
}
ReleaseUpdateCallbacks[key] = new CallbackWrapper(env, callback);
}
return Napi::Number::New(env, CheckReleaseUpdateInternal(releaseUpdateCallback, arg1, NULL));
}

Expand Down Expand Up @@ -1399,8 +1435,17 @@ Napi::Value checkForReleaseUpdate(const Napi::CallbackInfo &info)
Napi::Error::New(env, MISSING_LICENSE_KEY).ThrowAsJavaScriptException();
return env.Null();
}
ReleaseCallbacks[STRING(licenseKey)] = new CallbackWrapper(callback);
ReleaseCallbacks[STRING(licenseKey)]->SuppressDestruct();
STRING key(licenseKey);
// Clean up existing callback if present
{
std::lock_guard<std::mutex> lock(callbackMutex);
auto it = ReleaseCallbacks.find(key);
if (it != ReleaseCallbacks.end() && it->second != nullptr)
{
delete it->second;
}
ReleaseCallbacks[key] = new CallbackWrapper(env, callback);
}
return Napi::Number::New(env, CheckForReleaseUpdate(arg0.c_str(), arg1.c_str(), arg2.c_str(), softwareReleaseUpdateCallback));
}

Expand Down