diff --git a/privmx-endpoint/src/main/cpp/model_native_initializers.cpp b/privmx-endpoint/src/main/cpp/model_native_initializers.cpp index 2577819f..74ae9009 100644 --- a/privmx-endpoint/src/main/cpp/model_native_initializers.cpp +++ b/privmx-endpoint/src/main/cpp/model_native_initializers.cpp @@ -1394,5 +1394,63 @@ namespace privmx { ); } + // Stream + jobject streamRoom2Java( + JniContextUtils &ctx, + privmx::endpoint::stream::StreamRoom streamRoom_c + ) { + jclass itemCls = ctx->FindClass( + "com/simplito/java/privmx_endpoint/model/StreamRoom"); + jmethodID initItemMID = ctx->GetMethodID( + itemCls, + "", + "(" + "Ljava/lang/String;" // contextId + "Ljava/lang/String;" // streamRoomId + "Ljava/lang/Long;" // createDate + "Ljava/lang/String;" // creator + "Ljava/lang/Long;" // lastModificationDate + "Ljava/lang/String;" // lastModifier + "Ljava/util/List;" // users + "Ljava/util/List;" // managers + "Ljava/lang/Long;" // version + "[B" // publicMeta + "[B" // privateMeta + "Lcom/simplito/java/privmx_endpoint/model/ContainerPolicy;" // policy + "Ljava/lang/Long;" // statusCode + "Ljava/lang/Long;" // schemaVersion + ")V" + ); + + jbyteArray publicMeta = ctx->NewByteArray(streamRoom_c.publicMeta.size()); + jbyteArray privateMeta = ctx->NewByteArray(streamRoom_c.privateMeta.size()); + + ctx->SetByteArrayRegion(publicMeta, 0, streamRoom_c.publicMeta.size(), + (jbyte *) streamRoom_c.publicMeta.data()); + ctx->SetByteArrayRegion(privateMeta, 0, streamRoom_c.privateMeta.size(), + (jbyte *) streamRoom_c.privateMeta.data()); + + jobject users = vectorTojArray(ctx, streamRoom_c.users, string2jobject); + jobject managers = vectorTojArray(ctx, streamRoom_c.managers, string2jobject); + + return ctx->NewObject( + itemCls, + initItemMID, + ctx->NewStringUTF(streamRoom_c.contextId.c_str()), + ctx->NewStringUTF(streamRoom_c.streamRoomId.c_str()), + ctx.long2jLong(streamRoom_c.createDate), + ctx->NewStringUTF(streamRoom_c.creator.c_str()), + ctx.long2jLong(streamRoom_c.lastModificationDate), + ctx->NewStringUTF(streamRoom_c.lastModifier.c_str()), + users, + managers, + ctx.long2jLong(streamRoom_c.version), + publicMeta, + privateMeta, + containerPolicy2Java(ctx, streamRoom_c.policy), + ctx.long2jLong(streamRoom_c.statusCode), + ctx.long2jLong(streamRoom_c.schemaVersion) + ); + } } // wrapper } // privmx \ No newline at end of file diff --git a/privmx-endpoint/src/main/cpp/model_native_initializers.h b/privmx-endpoint/src/main/cpp/model_native_initializers.h index f83c7959..e200a3b6 100644 --- a/privmx-endpoint/src/main/cpp/model_native_initializers.h +++ b/privmx-endpoint/src/main/cpp/model_native_initializers.h @@ -14,6 +14,7 @@ #include #include "utils.hpp" +#include "parser.h" #include "privmx/endpoint/core/Connection.hpp" #include "privmx/endpoint/core/UserVerifierInterface.hpp" #include "privmx/endpoint/core/Types.hpp" @@ -34,6 +35,7 @@ #include "privmx/endpoint/crypto/ExtKey.hpp" #include "privmx/endpoint/kvdb/KvdbApi.hpp" #include "privmx/endpoint/kvdb/Types.hpp" +#include "privmx/endpoint/stream/StreamApi.hpp" namespace privmx { namespace wrapper { @@ -161,6 +163,8 @@ namespace privmx { jobject kvdbEntry2Java(JniContextUtils &ctx, privmx::endpoint::kvdb::KvdbEntry entry_c); + //Stream + jobject streamRoom2Java(JniContextUtils &ctx, privmx::endpoint::stream::StreamRoom streamRoom_c); } // wrapper } // privmx diff --git a/privmx-endpoint/src/main/cpp/modules/StreamApi.cpp b/privmx-endpoint/src/main/cpp/modules/StreamApi.cpp index 6cc1fbce..ebeafc27 100644 --- a/privmx-endpoint/src/main/cpp/modules/StreamApi.cpp +++ b/privmx-endpoint/src/main/cpp/modules/StreamApi.cpp @@ -56,4 +56,242 @@ Java_com_simplito_java_privmx_1endpoint_modules_stream_StreamApi_deinit( e.what() ); } +} + +extern "C" +JNIEXPORT jstring JNICALL +Java_com_simplito_java_privmx_1endpoint_modules_stream_StreamApi_createStreamRoom( + JNIEnv *env, + jobject thiz, + jstring context_id, + jobject users, + jobject managers, + jbyteArray public_meta, + jbyteArray private_meta, + jobject container_policies +) { + JniContextUtils ctx(env); + if (ctx.nullCheck(context_id, "Context ID") || + ctx.nullCheck(users, "Users list") || + ctx.nullCheck(managers, "Managers list") || + ctx.nullCheck(public_meta, "Public meta") || + ctx.nullCheck(private_meta, "Private meta")) { + return nullptr; + } + jstring result; + ctx.callResultEndpointApi( + &result, + [&ctx, &thiz, &context_id, &users, &managers, &public_meta, &private_meta, &container_policies]() { + std::vector managers_c = usersToVector( + ctx, + ctx.jObject2jArray(managers)); + std::vector users_c = usersToVector( + ctx, + ctx.jObject2jArray(users)); + auto container_policies_n = std::optional( + parseContainerPolicy(ctx, container_policies)); + return ctx->NewStringUTF( + getStreamApi(ctx, thiz)->createStreamRoom( + ctx.jString2string(context_id), + users_c, + managers_c, + core::Buffer::from(ctx.jByteArray2String(public_meta)), + core::Buffer::from(ctx.jByteArray2String(private_meta)), + container_policies_n + ).c_str()); + }); + if (ctx->ExceptionCheck()) { + return nullptr; + } + return result; +} + +extern "C" +JNIEXPORT void JNICALL +Java_com_simplito_java_privmx_1endpoint_modules_stream_StreamApi_updateStreamRoom( + JNIEnv *env, + jobject thiz, + jstring stream_room_id, + jobject users, + jobject managers, + jbyteArray public_meta, + jbyteArray private_meta, + jlong version, + jboolean force, + jboolean force_generate_new_key, + jobject container_policies +) { + JniContextUtils ctx(env); + if (ctx.nullCheck(stream_room_id, "Stream Room ID") || + ctx.nullCheck(users, "Users list") || + ctx.nullCheck(managers, "Managers list") || + ctx.nullCheck(public_meta, "Public meta") || + ctx.nullCheck(private_meta, "Private meta")) { + return; + } + ctx.callVoidEndpointApi( + [ + &ctx, + &thiz, + &stream_room_id, + &users, &managers, + &public_meta, + &private_meta, + &version, + &force, + &force_generate_new_key, + &container_policies + ]() { + std::vector users_c = usersToVector( + ctx, + ctx.jObject2jArray(users)); + std::vector managers_c = usersToVector( + ctx, + ctx.jObject2jArray(managers)); + auto container_policies_n = std::optional( + parseContainerPolicy(ctx, container_policies)); + + getStreamApi(ctx, thiz)->updateStreamRoom( + ctx.jString2string(stream_room_id), + users_c, + managers_c, + core::Buffer::from(ctx.jByteArray2String(public_meta)), + core::Buffer::from(ctx.jByteArray2String(private_meta)), + version, + force == JNI_TRUE, + force_generate_new_key == JNI_TRUE, + container_policies_n + ); + }); +} + +extern "C" +JNIEXPORT jobject JNICALL +Java_com_simplito_java_privmx_1endpoint_modules_stream_StreamApi_listStreamRooms( + JNIEnv *env, + jobject thiz, + jstring context_id, + jlong skip, + jlong limit, + jstring sort_order, + jstring last_id, + jstring query_as_json, + jstring sort_by +) { + JniContextUtils ctx(env); + if (ctx.nullCheck(sort_order, "Sort order") || + ctx.nullCheck(context_id, "Context ID")) { + return nullptr; + } + jobject result; + ctx.callResultEndpointApi( + &result, + [&ctx, &thiz, &context_id, &skip, &limit, &sort_order, &last_id, &query_as_json, &sort_by]() { + auto query = core::PagingQuery(); + query.skip = skip; + query.limit = limit; + query.sortOrder = ctx.jString2string(sort_order); + if (last_id != nullptr) { + query.lastId = ctx.jString2string(last_id); + } + if (query_as_json != nullptr) { + query.queryAsJson = ctx.jString2string(query_as_json); + } + if (sort_by != nullptr) { + query.sortBy = ctx.jString2string(sort_by); + } + auto streamRooms_c( + getStreamApi(ctx, thiz)->listStreamRooms( + ctx.jString2string(context_id), + query + ) + ); + + return pagingList2Java(ctx, streamRooms_c, long2jobject); + }); + if (ctx->ExceptionCheck()) { + return nullptr; + } + return result; +} + +extern "C" +JNIEXPORT jobject JNICALL +Java_com_simplito_java_privmx_1endpoint_modules_stream_StreamApi_getStreamRoom( + JNIEnv *env, + jobject thiz, + jstring stream_room_id +) { + JniContextUtils ctx(env); + if (ctx.nullCheck(stream_room_id, "Stream Room ID")) { + return nullptr; + } + jobject result; + ctx.callResultEndpointApi( + &result, + [&ctx, &thiz, &stream_room_id]() { + auto stream_c( + getStreamApi(ctx, thiz)->getStreamRoom( + ctx.jString2string(stream_room_id) + ) + ); + return privmx::wrapper::streamRoom2Java(ctx, stream_c); + }); + if (ctx->ExceptionCheck()) { + return nullptr; + } + return result; +} + +extern "C" +JNIEXPORT void JNICALL +Java_com_simplito_java_privmx_1endpoint_modules_stream_StreamApi_deleteStreamRoom( + JNIEnv *env, + jobject thiz, + jstring stream_room_id +) { + JniContextUtils ctx(env); + if (ctx.nullCheck(stream_room_id, "Stream Room ID")) { + return; + } + ctx.callVoidEndpointApi([&ctx, &thiz, &stream_room_id]() { + getStreamApi(ctx, thiz)->deleteStreamRoom( + ctx.jString2string(stream_room_id) + ); + }); +} + +extern "C" +JNIEXPORT void JNICALL +Java_com_simplito_java_privmx_1endpoint_modules_stream_StreamApi_joinRoom( + JNIEnv *env, + jobject thiz, + jstring stream_room_id +) { + JniContextUtils ctx(env); + if (ctx.nullCheck(stream_room_id, "Stream Room ID")) { + return; + } + ctx.callVoidEndpointApi([&ctx, &thiz, &stream_room_id]() { + getStreamApi(ctx, thiz)->joinRoom( + ctx.jString2string(stream_room_id) + ); + }); +} +extern "C" +JNIEXPORT void JNICALL +Java_com_simplito_java_privmx_1endpoint_modules_stream_StreamApi_leaveRoom( + JNIEnv *env, + jobject thiz, + jstring stream_room_id +) { + JniContextUtils ctx(env); + if (ctx.nullCheck(stream_room_id, "Stream Room ID")) { + return; + } + ctx.callVoidEndpointApi([&ctx, &thiz, &stream_room_id]() { + getStreamApi(ctx, thiz)->leaveRoom( + ctx.jString2string(stream_room_id) + ); + }); } \ No newline at end of file diff --git a/privmx-endpoint/src/main/java/com/simplito/java/privmx_endpoint/model/streams/StreamRoom.java b/privmx-endpoint/src/main/java/com/simplito/java/privmx_endpoint/model/streams/StreamRoom.java new file mode 100644 index 00000000..80e27998 --- /dev/null +++ b/privmx-endpoint/src/main/java/com/simplito/java/privmx_endpoint/model/streams/StreamRoom.java @@ -0,0 +1,54 @@ +package com.simplito.java.privmx_endpoint.model.streams; + +import com.simplito.java.privmx_endpoint.model.ContainerPolicy; + +import java.util.List; + +public class StreamRoom { + public String contextId; + public String streamRoomId; + public Long createDate; + public String creator; + public Long lastModificationDate; + public String lastModifier; + public List users; + public List managers; + public Long version; + public byte[] publicMeta; + public byte[] privateMeta; + public ContainerPolicy policy; + public Long statusCode; + public Long schemaVersion; + + public StreamRoom( + String contextId, + String streamRoomId, + Long createDate, + String creator, + Long lastModificationDate, + String lastModifier, + List users, + List managers, + Long version, + byte[] publicMeta, + byte[] privateMeta, + ContainerPolicy policy, + Long statusCode, + Long schemaVersion + ) { + this.contextId = contextId; + this.streamRoomId = streamRoomId; + this.createDate = createDate; + this.creator = creator; + this.lastModificationDate = lastModificationDate; + this.lastModifier = lastModifier; + this.users = users; + this.managers = managers; + this.version = version; + this.publicMeta = publicMeta; + this.privateMeta = privateMeta; + this.policy = policy; + this.statusCode = statusCode; + this.schemaVersion = schemaVersion; + } +} \ No newline at end of file diff --git a/privmx-endpoint/src/main/java/com/simplito/java/privmx_endpoint/modules/stream/StreamApi.java b/privmx-endpoint/src/main/java/com/simplito/java/privmx_endpoint/modules/stream/StreamApi.java index 6f7b512f..3a9f3b23 100644 --- a/privmx-endpoint/src/main/java/com/simplito/java/privmx_endpoint/modules/stream/StreamApi.java +++ b/privmx-endpoint/src/main/java/com/simplito/java/privmx_endpoint/modules/stream/StreamApi.java @@ -1,15 +1,21 @@ package com.simplito.java.privmx_endpoint.modules.stream; import com.simplito.java.privmx_endpoint.LibLoader; +import com.simplito.java.privmx_endpoint.model.ContainerPolicy; +import com.simplito.java.privmx_endpoint.model.PagingList; +import com.simplito.java.privmx_endpoint.model.UserWithPubKey; +import com.simplito.java.privmx_endpoint.model.streams.StreamRoom; import com.simplito.java.privmx_endpoint.modules.core.Connection; import com.simplito.java.privmx_endpoint.modules.event.EventApi; +import java.util.List; import java.util.Objects; public class StreamApi implements AutoCloseable { static { LibLoader.loadPrivmxLibraries(); } + @SuppressWarnings("FieldCanBeLocal") private final Long api; @@ -23,6 +29,91 @@ public StreamApi(Connection connection, EventApi eventApi) throws IllegalStateEx this.api = init(connection, eventApi); } + public native String createStreamRoom( + String contextId, + List users, + List managers, + byte[] publicMeta, + byte[] privateMeta, + ContainerPolicy policies + ); + + public String createStreamRoom( + String contextId, + List users, + List managers, + byte[] publicMeta, + byte[] privateMeta + ) { + return createStreamRoom(contextId, users, managers, publicMeta, privateMeta, null); + } + + public native void updateStreamRoom( + String streamRoomId, + List users, + List managers, + byte[] publicMeta, + byte[] privateMeta, + long version, + boolean force, + boolean forceGenerateNewKey, + ContainerPolicy policy + ); + + public void updateStreamRoom( + String streamRoomId, + List users, + List managers, + byte[] publicMeta, + byte[] privateMeta, + long version, + boolean force, + boolean forceGenerateNewKey + ) { + updateStreamRoom(streamRoomId, users, managers, publicMeta, privateMeta, version, force, forceGenerateNewKey, null); + } + + public void updateStreamRoom( + String streamRoomId, + List users, + List managers, + byte[] publicMeta, + byte[] privateMeta, + long version, + boolean force + ) { + updateStreamRoom(streamRoomId, users, managers, publicMeta, privateMeta, version, force, false, null); + } + + public void updateStreamRoom( + String streamRoomId, + List users, + List managers, + byte[] publicMeta, + byte[] privateMeta, + long version + ) { + updateStreamRoom(streamRoomId, users, managers, publicMeta, privateMeta, version, false, false, null); + } + + public native PagingList listStreamRooms( + String contextId, + long skip, + long limit, + String sortOrder, + String lastId, + String queryAsJson, + String sortBy + ); + + public native StreamRoom getStreamRoom(String streamRoomId); + + public native void deleteStreamRoom(String streamRoomId); + + public native void joinRoom(String streamRoomId); // required before createStream and openStream + + public native void leaveRoom(String streamRoomId); + @Override public void close() throws Exception { deinit();