Browse Source

Merged

JNI-44
Edouard Tisserant 10 years ago
parent
commit
d1320af156
  1. 4
      src/Makefile
  2. 94
      src/basic_api.cc
  3. 50
      src/gen_cpp_Engine.ysl2
  4. 41
      src/gen_java_Engine.ysl2
  5. 1
      src/jniutils.cc
  6. 79
      src/jniutils.hh
  7. 40
      src/org/pEp/jniadapter/AbstractEngine.java
  8. 120
      src/org_pEp_jniadapter_AbstractEngine.cc
  9. 6
      src/pEp.yml2
  10. 1
      src/types_java.ysl2

4
src/Makefile

@ -36,7 +36,7 @@ org_pEp_jniadapter_AbstractEngine.o: %.o: %.cc %.h throw_pEp_exception.hh jniuti
org_pEp_jniadapter_Engine.o org_pEp_jniadapter_Message.o: %.o: %.cc %.h org_pEp_jniadapter_Engine.o org_pEp_jniadapter_Message.o: %.o: %.cc %.h
$(LIBRARY): org_pEp_jniadapter_AbstractEngine.o org_pEp_jniadapter_Engine.o org_pEp_jniadapter_Message.o throw_pEp_exception.o jniutils.o $(LIBRARY): org_pEp_jniadapter_AbstractEngine.o org_pEp_jniadapter_Engine.o org_pEp_jniadapter_Message.o throw_pEp_exception.o jniutils.o basic_api.o
ar -r $@ *.o ar -r $@ *.o
org/pEp/jniadapter/pEpException.java: pEp.yml2 gen_java_exceptions.ysl2 org/pEp/jniadapter/pEpException.java: pEp.yml2 gen_java_exceptions.ysl2
@ -59,6 +59,8 @@ throw_pEp_exception.cc throw_pEp_exception.hh: pEp.yml2 gen_throw_pEp_exception.
throw_pEp_exception.o: throw_pEp_exception.cc throw_pEp_exception.hh throw_pEp_exception.o: throw_pEp_exception.cc throw_pEp_exception.hh
basic_api.o: basic_api.cc jniutils.hh throw_pEp_exception.hh
.PHONY: clean .PHONY: clean
clean: clean:

94
src/basic_api.cc

@ -0,0 +1,94 @@
#include <pEp/keymanagement.h>
#include "throw_pEp_exception.hh"
#include "jniutils.hh"
extern "C" {
using namespace pEp::JNIAdapter;
JNIEXPORT jobject JNICALL Java_org_pEp_jniadapter_Engine_trustwords(
JNIEnv *env,
jobject obj,
jobject ident
)
{
PEP_SESSION session = (PEP_SESSION) callLongMethod(env, obj, "getHandle");
pEp_identity *_ident = to_identity(env, ident);
char *words;
size_t wsize;
if (_ident->fpr == NULL || _ident->fpr[0] == 0) {
if (_ident->me)
::myself(session, _ident);
else
::update_identity(session, _ident);
}
if (_ident->fpr == NULL || _ident->fpr[0] == 0) {
throw_pEp_Exception(env, PEP_CANNOT_FIND_IDENTITY);
return NULL;
}
PEP_STATUS status = ::trustwords(session, _ident->fpr, _ident->lang, &words, &wsize, 10);
if (status != PEP_STATUS_OK) {
throw_pEp_Exception(env, status);
return NULL;
}
return from_string(env, words);
}
JNIEXPORT jobject JNICALL Java_org_pEp_jniadapter_Engine_myself(
JNIEnv *env,
jobject obj,
jobject ident
)
{
PEP_SESSION session = (PEP_SESSION) callLongMethod(env, obj, "getHandle");
pEp_identity *_ident = to_identity(env, ident);
::myself(session, _ident);
return from_identity(env, _ident);
}
JNIEXPORT jobject JNICALL Java_org_pEp_jniadapter_Engine_updateIdentity(
JNIEnv *env,
jobject obj,
jobject ident
)
{
PEP_SESSION session = (PEP_SESSION) callLongMethod(env, obj, "getHandle");
pEp_identity *_ident = to_identity(env, ident);
::update_identity(session, _ident);
return from_identity(env, _ident);
}
JNIEXPORT void JNICALL Java_org_pEp_jniadapter_Engine_keyCompromized(
JNIEnv *env,
jobject obj,
jobject ident
)
{
PEP_SESSION session = (PEP_SESSION) callLongMethod(env, obj, "getHandle");
pEp_identity *_ident = to_identity(env, ident);
if (_ident->fpr == NULL || _ident->fpr[0] == 0) {
if (_ident->me)
::myself(session, _ident);
else
::update_identity(session, _ident);
}
if (_ident->fpr == NULL || _ident->fpr[0] == 0) {
throw_pEp_Exception(env, PEP_CANNOT_FIND_IDENTITY);
return;
}
::key_compromized(session, _ident->fpr);
}
} // extern "C"

50
src/gen_cpp_Engine.ysl2

@ -12,6 +12,7 @@ tstylesheet {
#include <assert.h> #include <assert.h>
#include <pEp/message_api.h> #include <pEp/message_api.h>
#include "org_pEp_jniadapter_«@name».h" #include "org_pEp_jniadapter_«@name».h"
#include "throw_pEp_exception.hh"
#include "jniutils.hh" #include "jniutils.hh"
using namespace pEp::JNIAdapter; using namespace pEp::JNIAdapter;
@ -41,6 +42,11 @@ tstylesheet {
`` apply "parm[creates|returns]", mode=out `` apply "parm[creates|returns]", mode=out
PEP_STATUS status = ::«@name»(session`apply "parm", mode=call``if "@name = 'encrypt_message'" > , PEP_enc_PEP`); PEP_STATUS status = ::«@name»(session`apply "parm", mode=call``if "@name = 'encrypt_message'" > , PEP_enc_PEP`);
if ((status > PEP_STATUS_OK && status < PEP_UNENCRYPTED) |`> |`
status >= PEP_TRUSTWORD_NOT_FOUND) {
throw_pEp_Exception(env, status);
return NULL;
}
|| ||
@ -93,8 +99,16 @@ tstylesheet {
const "name", "name(*[3])"; const "name", "name(*[3])";
|| ||
jfieldID «$name»_field = getFieldID(env, "«$jtype»", jfieldID «$name»_field = getFieldID(env, "«$jtype»",
"«$name»", "«$sig»"); "«$name»", "«$sig»");
env->SetObjectField(result_, «$name»_field, «$name»_); if («$name»_)
env->SetObjectField(result_, «$name»_field, «$name»_);
||
if "$name = 'dst'"
||
else
env->SetObjectField(result_, «$name»_field, src);
||
||
|| ||
} }
@ -120,20 +134,32 @@ tstylesheet {
choose { choose {
when "$jnitype = 'jbyteArray'" when "$jnitype = 'jbyteArray'"
|| ||
jobject «$name»_ = from_stringlist(env, _«$retname»); jobject «$name»_ = NULL;
if (_«$retname»)
«$name»_ = from_stringlist(env, _«$retname»);
|| ||
otherwise { otherwise {
|| | jobject «$name»_ = NULL;
jclass clazz_«$name»_ = findClass(env, "org/pEp/jniadapter/«$jtype»"); indent(0);
jmethodID constructor_«$name»_ = env->GetMethodID(clazz_«$name»_, "<init>", "«$sig»"); if "$retname != 'result'" > if (_«$retname»)
assert(constructor_«$name»_); > {\n
|| ||
indent(0); jclass clazz_«$name»_ = findClass(env, "org/pEp/jniadapter/«$jtype»");
> jobject «$name»_ = env->NewObject(clazz_«$name»_, constructor_«$name»_ jmethodID constructor_«$name»_ = env->GetMethodID(clazz_«$name»_, "<init>", "«$sig»");
if "$jnitype != ''" > , («$jnitype») _«$retname» assert(constructor_«$name»_);
> );\n\n ||
indent(1);
> «$name»_ = env->NewObject(clazz_«$name»_, constructor_«$name»_
if "$jnitype != ''" > , («$jnitype») _«$retname»
> );\n
||
}
||
} }
} }
} }

41
src/gen_java_Engine.ysl2

@ -18,11 +18,40 @@ tstylesheet {
public «$cname»() throws pEpException { } public «$cname»() throws pEpException { }
`` apply "method", mode=plain `` apply "method", mode=plain
`` apply "basic"
} }
|| ||
} }
template "basic" {
const "itype" call "toIntermediate" with "type", "@type";
const "jtype" call "toJava" with "type", "@type";
const "ptype", "name(parm/*[1])";
const "pitype" call "toIntermediate" with "type", "$ptype";
const "pjtype" call "toJava" with "type", "$ptype";
const "pname", "name(parm/*[2])";
||
private native «$itype» «@name»(«$pitype» «$pname»);
public «$jtype» «@name»(«$pjtype» «$pname») {
«$pitype» _«$pname» = new «$pitype»(«$pname»);
||
choose {
when "@type = 'void'"
|> «@name»(_«$pname»);
when "@type = 'identity'"
|> return new Identity(«@name»(_«$pname»));
otherwise
|> return AbstractEngine.toUTF16(«@name»(_«$pname»));
}
||
}
||
}
function "returnJava" { function "returnJava" {
const "returning", "count(parm/creates|parm/returns)"; const "returning", "count(parm/creates|parm/returns)";
const "returntype" call "toJava" with "type", "name(parm[creates|returns]/*[2])"; const "returntype" call "toJava" with "type", "name(parm[creates|returns]/*[2])";
@ -47,6 +76,7 @@ tstylesheet {
template "method", mode=plain { template "method", mode=plain {
const "convert", "count(parm/stringlist|parm/string|parm/identity) > 0"; const "convert", "count(parm/stringlist|parm/string|parm/identity) > 0";
const "convertreturn", "count(parm[returns]/stringlist|parm[returns]/string|parm[returns]/identity) > 0";
const "singlereturn", "count(parm/creates|parm/returns) = 1"; const "singlereturn", "count(parm/creates|parm/returns) = 1";
const "multireturn", "count(parm/creates|parm/returns) > 1"; const "multireturn", "count(parm/creates|parm/returns) > 1";
@ -85,7 +115,12 @@ tstylesheet {
| { | {
apply "parm", mode=convertIn; apply "parm", mode=convertIn;
if "$singlereturn" |> return _«@name»(`apply "parm[in]", mode=call;`); if "$singlereturn" choose {
when "$convertreturn"
|> return AbstractEngine.toUTF16(_«@name»(`apply "parm[in]", mode=call;`));
otherwise
|> return _«@name»(`apply "parm[in]", mode=call;`);
}
if "$multireturn" if "$multireturn"
|| ||
@ -97,9 +132,11 @@ tstylesheet {
|| ||
} }
|| ||
} }
||
||
} }
template "parm", mode=java { template "parm", mode=java {

1
src/jniutils.cc

@ -77,6 +77,7 @@ namespace pEp {
return env->CallIntMethod(obj, method); return env->CallIntMethod(obj, method);
} }
jlong callLongMethod( jlong callLongMethod(
JNIEnv *env, JNIEnv *env,
jobject obj, jobject obj,

79
src/jniutils.hh

@ -1,11 +1,90 @@
#pragma once #pragma once
#include <list>
#include <pthread.h>
#include <jni.h> #include <jni.h>
#include <pEp/stringpair.h> #include <pEp/stringpair.h>
#include <pEp/identity_list.h> #include <pEp/identity_list.h>
#include <pEp/bloblist.h> #include <pEp/bloblist.h>
namespace pEp { namespace pEp {
namespace utility {
using namespace std;
class mutex {
pthread_mutex_t _mutex;
public:
mutex() {
pthread_mutex_init(&_mutex, NULL);
}
~mutex() {
pthread_mutex_destroy(&_mutex);
}
void lock() {
pthread_mutex_lock(&_mutex);
}
void unlock() {
pthread_mutex_unlock(&_mutex);
}
};
template<class T> class lock_guard {
T& _mtx;
public:
lock_guard(T& mtx) : _mtx(mtx) {
_mtx.lock();
}
~lock_guard() {
_mtx.unlock();
}
};
template<class T> class locked_queue
{
mutex _mtx;
list<T> _q;
public:
T& back()
{
lock_guard<mutex> lg(_mtx);
return _q.back();
}
T& front()
{
lock_guard<mutex> lg(_mtx);
return _q.front();
}
void pop_back()
{
lock_guard<mutex> lg(_mtx);
_q.pop_back();
}
void pop_front()
{
lock_guard<mutex> lg(_mtx);
_q.pop_front();
}
void push_back(const T& data)
{
lock_guard<mutex> lg(_mtx);
_q.push_back(data);
}
void push_front(const T& data)
{
lock_guard<mutex> lg(_mtx);
_q.push_front(data);
}
size_t size()
{
lock_guard<mutex> lg(_mtx);
return _q.size();
}
};
}
namespace JNIAdapter { namespace JNIAdapter {
jclass findClass(JNIEnv *env, const char *classname); jclass findClass(JNIEnv *env, const char *classname);

40
src/org/pEp/jniadapter/AbstractEngine.java

@ -27,6 +27,12 @@ abstract class AbstractEngine implements AutoCloseable {
release(); release();
} }
private long keyserverThread;
private long queueThread;
public native void startKeyserverLookup();
public native void stopKeyserverLookup();
public static byte[] toUTF8(String str) { public static byte[] toUTF8(String str) {
try { try {
String _str = Normalizer.normalize(str, Normalizer.Form.NFC); String _str = Normalizer.normalize(str, Normalizer.Form.NFC);
@ -101,39 +107,5 @@ abstract class AbstractEngine implements AutoCloseable {
return result; return result;
} }
public class _Identity {
public byte[] address;
public byte[] fpr;
public byte[] user_id;
public byte[] username;
CommType comm_type;
public byte[] lang;
public boolean me;
public _Identity(Identity value) {
address = toUTF8(value.address);
fpr = toUTF8(value.fpr);
user_id = toUTF8(value.user_id);
username = toUTF8(value.username);
comm_type = value.comm_type;
lang = toUTF8(value.lang);
me = value.me;
}
public Identity getIdentity() {
Identity ident = new Identity(me);
ident.address = toUTF16(address);
ident.fpr = toUTF16(fpr);
ident.user_id = toUTF16(user_id);
ident.username = toUTF16(username);
ident.comm_type = comm_type;
ident.lang = toUTF16(lang);
ident.me = me;
return ident;
}
}
} }

120
src/org_pEp_jniadapter_AbstractEngine.cc

@ -1,14 +1,17 @@
#include "org_pEp_jniadapter_AbstractEngine.h" #include "org_pEp_jniadapter_AbstractEngine.h"
#include <stdexcept> #include <stdexcept>
#include <unistd.h>
#include <assert.h> #include <assert.h>
#include <pEp/pEpEngine.h> #include <pthread.h>
#include <pEp/keymanagement.h>
#include "throw_pEp_exception.hh" #include "throw_pEp_exception.hh"
#include "jniutils.hh" #include "jniutils.hh"
extern "C" { extern "C" {
using namespace pEp::JNIAdapter; using namespace pEp::JNIAdapter;
using namespace pEp::utility;
JNIEXPORT void JNICALL Java_org_pEp_jniadapter_Engine_init( JNIEXPORT void JNICALL Java_org_pEp_jniadapter_Engine_init(
JNIEnv *env, JNIEnv *env,
@ -62,5 +65,118 @@ extern "C" {
else else
env->SetLongField(me, handle, jlong(0)); env->SetLongField(me, handle, jlong(0));
} }
}
int examine_identity(pEp_identity *ident, void *arg)
{
locked_queue< pEp_identity * > *queue = (locked_queue< pEp_identity * > *) arg;
queue->push_back(identity_dup(ident));
return 0;
}
pEp_identity *retrieve_next_identity(void *arg)
{
locked_queue< pEp_identity * > *queue = (locked_queue< pEp_identity * > *) arg;
while (!queue->size())
usleep(100000);
pEp_identity *ident = queue->front();
queue->pop_front();
return ident;
}
static void *start_routine(void *arg)
{
PEP_STATUS status = do_keymanagement(retrieve_next_identity, arg);
locked_queue< pEp_identity * > *queue = (locked_queue< pEp_identity * > *) arg;
while (queue->size()) {
pEp_identity *ident = queue->front();
queue->pop_front();
free_identity(ident);
}
delete queue;
return (void *) status;
}
JNIEXPORT void JNICALL Java_org_pEp_jniadapter_AbstractEngine_startKeyserverLookup(
JNIEnv *env,
jobject obj
)
{
PEP_SESSION session = (PEP_SESSION) callLongMethod(env, obj, "getHandle");
pthread_t *thread = NULL;
locked_queue< pEp_identity * > *queue = NULL;
jfieldID thread_handle;
jfieldID queue_handle;
try {
thread_handle = getFieldID(env, "org/pEp/jniadapter/Engine", "keyserverThread", "J");
queue_handle = getFieldID(env, "org/pEp/jniadapter/Engine", "queueThread", "J");
}
catch (std::exception& ex) {
assert(0);
return;
}
thread = (pthread_t *) env->GetLongField(obj, thread_handle);
if (thread)
return;
thread = (pthread_t *) calloc(1, sizeof(pthread_t));
assert(thread);
env->SetLongField(obj, thread_handle, (jlong) thread);
queue = new locked_queue< pEp_identity * >();
env->SetLongField(obj, queue_handle, (jlong) queue);
pthread_create(thread, NULL, start_routine, (void *) queue);
register_examine_function(session, examine_identity, (void *) queue);
}
JNIEXPORT void JNICALL Java_org_pEp_jniadapter_AbstractEngine_stopKeyserverLookup(
JNIEnv *env,
jobject obj
)
{
PEP_SESSION session = (PEP_SESSION) callLongMethod(env, obj, "getHandle");
pthread_t *thread = NULL;
locked_queue< pEp_identity * > *queue = NULL;
jfieldID thread_handle;
jfieldID queue_handle;
try {
thread_handle = getFieldID(env, "org/pEp/jniadapter/Engine", "keyserverThread", "J");
queue_handle = getFieldID(env, "org/pEp/jniadapter/Engine", "queueThread", "J");
}
catch (std::exception& ex) {
assert(0);
return;
}
thread = (pthread_t *) env->GetLongField(obj, thread_handle);
if (!thread)
return;
queue = (locked_queue< pEp_identity * > *) env->GetLongField(obj, queue_handle);
env->SetLongField(obj, queue_handle, (jlong) 0);
env->SetLongField(obj, thread_handle, (jlong) 0);
register_examine_function(session, NULL, NULL);
queue->push_front(NULL);
pthread_join(*thread, NULL);
free(thread);
}
} // extern "C"

6
src/pEp.yml2

@ -4,6 +4,7 @@ decl interface @name;
decl exception @name; decl exception @name;
decl method @name; decl method @name;
decl struct @name; decl struct @name;
decl basic @type @name;
namespace pEp { namespace pEp {
exception pEp_status { exception pEp_status {
@ -86,6 +87,11 @@ namespace pEp {
in message msg, in message msg,
returns Color color returns Color color
); );
basic string trustwords(identity ident);
basic identity myself(identity ident);
basic identity updateIdentity(identity ident);
basic void keyCompromized(identity ident);
}; };
struct message { struct message {

1
src/types_java.ysl2

@ -12,6 +12,7 @@ function "toJava" {
when "$type='bloblist'" > Vector<Blob> when "$type='bloblist'" > Vector<Blob>
when "$type='stringpairlist'" > ArrayList<Pair<String, String>> when "$type='stringpairlist'" > ArrayList<Pair<String, String>>
when "$type='message'" > Message when "$type='message'" > Message
when "$type='void'" > void
otherwise call "CamelCase" with "text", "$type"; otherwise call "CamelCase" with "text", "$type";
} }

Loading…
Cancel
Save