Skip to content

Commit 1239ef7

Browse files
committed
feat(async-worker): introduce a KerberosWorker using lambdas
This allows us to signifcantly reduce the amount of boilerplate required for async workers, by replacing the implementation with a single lambda. This should also make it much easier to split up implementation from definition in order to support both unix and windows implementations.
1 parent a110868 commit 1239ef7

File tree

3 files changed

+68
-31
lines changed

3 files changed

+68
-31
lines changed

src/common.h

+4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55
#include "kerberos_gss.h"
66

77
// Provide a default custom delter for the `gss_result` type
8+
inline void ResultDeleter(gss_result* result) {
9+
free(result);
10+
}
11+
812
struct FreeDeleter {
913
void operator()(void* result) {
1014
free(result);

src/kerberos.cc

+16-31
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "kerberos.h"
55
#include "kerberos_client.h"
66
#include "kerberos_server.h"
7+
#include "kerberos_worker.h"
78

89
using v8::FunctionTemplate;
910

@@ -159,44 +160,28 @@ NAN_METHOD(PrincipalDetails) {
159160
AsyncQueueWorker(new PrincipalDetailsWorker(service, hostname, callback));
160161
}
161162

162-
class CheckPasswordWorker : public Nan::AsyncWorker {
163-
public:
164-
CheckPasswordWorker(std::string username,
165-
std::string password,
166-
std::string service,
167-
std::string defaultRealm,
168-
Nan::Callback* callback)
169-
: AsyncWorker(callback, "kerberos:CheckPassword"),
170-
_username(username),
171-
_password(password),
172-
_service(service),
173-
_defaultRealm(defaultRealm) {}
174-
175-
virtual void Execute() {
176-
std::unique_ptr<gss_result, FreeDeleter> result(authenticate_user_krb5pwd(
177-
_username.c_str(), _password.c_str(), _service.c_str(), _defaultRealm.c_str()));
178-
179-
if (result->code == AUTH_GSS_ERROR) {
180-
SetErrorMessage(result->message);
181-
return;
182-
}
183-
}
184-
185-
private:
186-
std::string _username;
187-
std::string _password;
188-
std::string _service;
189-
std::string _defaultRealm;
190-
};
191-
192163
NAN_METHOD(CheckPassword) {
193164
std::string username(*Nan::Utf8String(info[0]));
194165
std::string password(*Nan::Utf8String(info[1]));
195166
std::string service(*Nan::Utf8String(info[2]));
196167
std::string defaultRealm(*Nan::Utf8String(info[3]));
197168
Nan::Callback* callback = new Nan::Callback(Nan::To<v8::Function>(info[4]).ToLocalChecked());
198169

199-
AsyncQueueWorker(new CheckPasswordWorker(username, password, service, defaultRealm, callback));
170+
KerberosWorker::Run(callback, "kerberos:CheckPassword", [=](KerberosWorker::SetOnFinishedHandler onFinished) {
171+
std::shared_ptr<gss_result> result(authenticate_user_krb5pwd(
172+
username.c_str(), password.c_str(), service.c_str(), defaultRealm.c_str()), ResultDeleter);
173+
174+
return onFinished([=](KerberosWorker* worker) {
175+
Nan::HandleScope scope;
176+
if (result->code == AUTH_GSS_ERROR) {
177+
v8::Local<v8::Value> argv[] = {Nan::New(result->message).ToLocalChecked(), Nan::Null()};
178+
worker->Call(2, argv);
179+
} else {
180+
v8::Local<v8::Value> argv[] = {Nan::Null(), Nan::Null()};
181+
worker->Call(2, argv);
182+
}
183+
});
184+
});
200185
}
201186

202187
NAN_MODULE_INIT(Init) {

src/kerberos_worker.h

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#ifndef ASYNC_WORKER_H
2+
#define ASYNC_WORKER_H
3+
4+
#include <functional>
5+
#include <nan.h>
6+
7+
class KerberosWorker : public Nan::AsyncWorker {
8+
public:
9+
typedef std::function<void(KerberosWorker*)> OnFinishedHandler;
10+
typedef std::function<void(OnFinishedHandler)> SetOnFinishedHandler;
11+
typedef std::function<void(SetOnFinishedHandler)> ExecuteHandler;
12+
13+
explicit KerberosWorker(Nan::Callback *callback, const char* resource_name, ExecuteHandler handler)
14+
: Nan::AsyncWorker(callback, resource_name), execute_handler(handler) {}
15+
16+
template <class... T>
17+
void Call(T... t) {
18+
callback->Call(t..., async_resource);
19+
}
20+
21+
virtual void Execute() {
22+
execute_handler([=] (OnFinishedHandler handler) {
23+
on_finished_handler = handler;
24+
});
25+
}
26+
27+
static void Run(Nan::Callback *callback, const char* resource_name, ExecuteHandler handler) {
28+
Nan::TryCatch tryCatch;
29+
if (tryCatch.HasCaught()) {
30+
tryCatch.ReThrow();
31+
return; // don't proceed in case there were any previous errors
32+
}
33+
34+
auto worker = new KerberosWorker(callback, resource_name, handler);
35+
Nan::AsyncQueueWorker(worker);
36+
}
37+
38+
protected:
39+
void HandleOKCallback() {
40+
on_finished_handler(this);
41+
}
42+
43+
private:
44+
ExecuteHandler execute_handler;
45+
OnFinishedHandler on_finished_handler;
46+
};
47+
48+
#endif // ASYNC_WORKER_H

0 commit comments

Comments
 (0)