diff --git a/src/codegen/gen_cpp_Message.ysl2 b/src/codegen/gen_cpp_Message.ysl2 index a951771..d154daf 100644 --- a/src/codegen/gen_cpp_Message.ysl2 +++ b/src/codegen/gen_cpp_Message.ysl2 @@ -17,6 +17,8 @@ tstylesheet { || #include #include + #include + #include #include #include "jniutils.hh" #include "throw_pEp_exception.hh" @@ -113,6 +115,143 @@ tstylesheet { return result; } + JNIEXPORT jbyteArray JNICALL Java_foundation_pEp_jniadapter_Message__1encodeASN1XER(JNIEnv *env, + jclass clazz, + jobject _msg) + { + pEpLog("called"); + message* msg = nullptr; + try { + msg = message_ptr(env, _msg); + } catch(...) { + jclass ex = env->FindClass("java/lang/IllegalStateException"); + assert(ex); + env->ThrowNew(ex, nullptr); + return NULL; + } + + // create ASN1Message + ASN1Message_t *msg_asn1 = ::ASN1Message_from_message(msg, NULL, true, 0); + if (msg_asn1 == nullptr) { + jclass ex = env->FindClass("java/lang/IllegalStateException"); + assert(ex); + env->ThrowNew(ex, nullptr); + return NULL; + } + + // encode PER + char *msg_per = nullptr; + size_t data_size_per = 0; + PEP_STATUS status = ::encode_ASN1Message_message(msg_asn1, &msg_per, &data_size_per); + free(msg_asn1); + if (status) { + throw_pEp_Exception(env, status); + return NULL; + } + if (msg_per == nullptr) { + jclass ex = env->FindClass("java/lang/IllegalStateException"); + assert(ex); + env->ThrowNew(ex, nullptr); + return NULL; + } + + // encode PER to XER + char *msg_xer = nullptr; + status = ::PER_to_XER_ASN1Message_msg(msg_per, data_size_per, &msg_xer); + free(msg_per); + if (status) { + throw_pEp_Exception(env, status); + return NULL; + } + if (msg_xer == nullptr) { + jclass ex = env->FindClass("java/lang/IllegalStateException"); + assert(ex); + env->ThrowNew(ex, nullptr); + return NULL; + } + + jbyteArray result = from_string(env, msg_xer); + return result; + } + + JNIEXPORT jobject JNICALL Java_foundation_pEp_jniadapter_Message__1decodeASN1XER(JNIEnv *env, + jclass clazz, + jbyteArray _msg_xer) + { + pEpLog("called"); + char *msg_xer = nullptr; + if(_msg_xer) { + msg_xer = to_string(env, _msg_xer); + } + // validate param msg_xer + if (msg_xer == nullptr) { + jclass ex = env->FindClass("java/lang/IllegalStateException"); + assert(ex); + env->ThrowNew(ex, nullptr); + return NULL; + } + + // convert XER to PER + char *msg_per = nullptr; + size_t msg_per_size = 0; + PEP_STATUS status = ::XER_to_PER_ASN1Message_msg(msg_xer, &msg_per, &msg_per_size); + free(msg_xer); + if (status) { + throw_pEp_Exception(env, status); + return NULL; + } + if (msg_per == nullptr) { + jclass ex = env->FindClass("java/lang/IllegalStateException"); + assert(ex); + env->ThrowNew(ex, nullptr); + return NULL; + } + + // decode PER to ASN1Message + ASN1Message *msg_asn1 = nullptr; + status = ::decode_ASN1Message_message(msg_per, msg_per_size, &msg_asn1); + free(msg_per); + if (status) { + throw_pEp_Exception(env, status); + return NULL; + } + if (msg_asn1 == nullptr) { + jclass ex = env->FindClass("java/lang/IllegalStateException"); + assert(ex); + env->ThrowNew(ex, nullptr); + return NULL; + } + + // convert ASN1Message to message + message *msg_out = nullptr; + msg_out = ::ASN1Message_to_message(msg_asn1, NULL, false, 0); + // msg_asn1 gets moved, so dont free it + if (msg_out == nullptr) { + jclass ex = env->FindClass("java/lang/IllegalStateException"); + assert(ex); + env->ThrowNew(ex, nullptr); + return NULL; + } + + // Convert message to java class Message + jobject msg_ = nullptr; + jclass clazz_dst_ = findClass(env, "foundation/pEp/jniadapter/Message"); + assert(clazz_dst_); + jmethodID constructor_dst_ = env->GetMethodID(clazz_dst_, "", "(J)V"); + assert(constructor_dst_); + msg_ = env->NewObject(clazz_dst_, constructor_dst_, reinterpret_cast(msg_out)); + + // msg_ will point to msg_out, so dont free it + if (msg_ == nullptr) { + jclass ex = env->FindClass("java/lang/IllegalStateException"); + assert(ex); + env->ThrowNew(ex, nullptr); + return NULL; + } + + return msg_; + } + || apply "*[name(.)!='enum']", 0, mode=entry { with "name", "@name"; diff --git a/src/codegen/gen_java_Message.ysl2 b/src/codegen/gen_java_Message.ysl2 index 8b13da8..7f8854c 100644 --- a/src/codegen/gen_java_Message.ysl2 +++ b/src/codegen/gen_java_Message.ysl2 @@ -64,6 +64,30 @@ tstylesheet { return Utils.toUTF16(_encodeMIME()); } + private native static byte[] _encodeASN1XER(Message msg) throws pEpException; + + public static String encodeASN1XER(Message msg) { + return Utils.toUTF16(_encodeASN1XER(msg)); + } + + public String toXER() { + return encodeASN1XER(this); + } + + private native static Message _decodeASN1XER(byte[] msgXER) throws pEpException; + + public static Message decodeASN1XER(String msgXER) { + byte[] _msgXER = new byte[0]; + if (msgXER != null) { + _msgXER = Utils.toUTF8(msgXER); + } + return _decodeASN1XER(_msgXER); + } + + public static Message fromXER(String msgXER) { + return decodeASN1XER(msgXER); + } + private «$cname»(long h) { handle = h; instanceCount.getAndIncrement(); @@ -102,6 +126,8 @@ tstylesheet { public interface «$cname»Interface { public String encodeMIME(); + public String toXER(); + `` apply "*[name(.)!='enum']", mode=interface } || diff --git a/test/java/foundation/pEp/jniadapter/test/jni167/Makefile b/test/java/foundation/pEp/jniadapter/test/jni167/Makefile new file mode 100644 index 0000000..c048f79 --- /dev/null +++ b/test/java/foundation/pEp/jniadapter/test/jni167/Makefile @@ -0,0 +1,34 @@ +include ../../../../../../../Makefile.conf +include ../Makefile.conf + +TEST_UNIT_NAME=jni167 + +JAVA_CLASSES+= \ + TestAlice.class + +.PHONY: pitytest compile alice test clean + +all: alice compile + +pitytest: + $(MAKE) -C $(PITYTEST_DIR) + +alice: compile clean-pep-home-alice + cd $(JAVA_CWD);pwd;HOME=$(JAVA_PEP_HOME_DIR_ALICE) $(JAVA) $(JAVA_PKG_BASENAME).$(TEST_UNIT_NAME).TestAlice + +compile: $(JAVA_CLASSES) pitytest + +%.class: %.java + cd $(JAVA_CWD);javac -cp $(CLASSPATH) $(JAVA_PKG_BASEPATH)/$(TEST_UNIT_NAME)/$< + +clean: + rm -f $(JAVA_CLASSES) + rm -f *.class + rm -f *.log + rm -Rf .gnupg + rm -Rf .lldb + +clean-pep-home: clean-pep-home-alice + +clean-pep-home-alice: + rm -rf $(PEP_HOME_DIR_ALICE)/.pEp diff --git a/test/java/foundation/pEp/jniadapter/test/jni167/TestAlice.java b/test/java/foundation/pEp/jniadapter/test/jni167/TestAlice.java new file mode 100644 index 0000000..8089d66 --- /dev/null +++ b/test/java/foundation/pEp/jniadapter/test/jni167/TestAlice.java @@ -0,0 +1,68 @@ +package foundation.pEp.jniadapter.test.jni167; + +import foundation.pEp.jniadapter.Message; +import foundation.pEp.jniadapter.test.utils.AdapterTestUtils; +import foundation.pEp.jniadapter.test.utils.CTXBase; +import foundation.pEp.pitytest.TestSuite; +import foundation.pEp.pitytest.TestUnit; +import foundation.pEp.pitytest.utils.TestUtils; + +import static foundation.pEp.pitytest.TestLogger.log; + + +/* +JNI-167 - ASN1 Support + +TODO: +just spot test that the encoding/decoding generally works. Dont test the whole codec. + +*/ + + +class TestAlice { + public static void main(String[] args) throws Exception { + TestSuite.getDefault().setVerbose(true); + TestSuite.getDefault().setTestColor(TestUtils.TermColor.GREEN); + + CTXBase ctxBase = new CTXBase(); + + new TestUnit("toXER", ctxBase, ctx -> { + log("fdfd"); + String tmp = ctx.msgAliceToAlice.toXER(); + log(tmp); + }); + + + new TestUnit("decodeASN1XER", ctxBase, ctx -> { + log("fdfd"); + String msgXER = "\n" + + " \n" + + "
alice@peptest.org
\n" + + " \n" + + " alice\n" + + " 0\n" + + " en\n" + + "
\n" + + " \n" + + " \n" + + "
bob@peptest.org
\n" + + " \n" + + " bob\n" + + " 0\n" + + " en\n" + + "
\n" + + "
\n" + + " Hi i am the shortMessage\n" + + " Hi i am the longMessage\n" + + "
\n"; + + Message m = Message.fromXER(msgXER); + log(AdapterTestUtils.msgToString(m, false)); + }); + + + TestSuite.getDefault().run(); + } +} + +