1 /*
2 * Copyright 2017 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include <memory>
12
13 #include <limits>
14
15 #include "api/data_channel_interface.h"
16 #include "rtc_base/logging.h"
17 #include "sdk/android/generated_peerconnection_jni/DataChannel_jni.h"
18 #include "sdk/android/native_api/jni/java_types.h"
19 #include "sdk/android/src/jni/jni_helpers.h"
20 #include "sdk/android/src/jni/pc/data_channel.h"
21
22 namespace webrtc {
23 namespace jni {
24
25 namespace {
26 // Adapter for a Java DataChannel$Observer presenting a C++ DataChannelObserver
27 // and dispatching the callback from C++ back to Java.
28 class DataChannelObserverJni : public DataChannelObserver {
29 public:
30 DataChannelObserverJni(JNIEnv* jni, const JavaRef<jobject>& j_observer);
~DataChannelObserverJni()31 ~DataChannelObserverJni() override {}
32
33 void OnBufferedAmountChange(uint64_t previous_amount) override;
34 void OnStateChange() override;
35 void OnMessage(const DataBuffer& buffer) override;
36
37 private:
38 const ScopedJavaGlobalRef<jobject> j_observer_global_;
39 };
40
DataChannelObserverJni(JNIEnv * jni,const JavaRef<jobject> & j_observer)41 DataChannelObserverJni::DataChannelObserverJni(
42 JNIEnv* jni,
43 const JavaRef<jobject>& j_observer)
44 : j_observer_global_(jni, j_observer) {}
45
OnBufferedAmountChange(uint64_t previous_amount)46 void DataChannelObserverJni::OnBufferedAmountChange(uint64_t previous_amount) {
47 JNIEnv* env = AttachCurrentThreadIfNeeded();
48 Java_Observer_onBufferedAmountChange(env, j_observer_global_,
49 previous_amount);
50 }
51
OnStateChange()52 void DataChannelObserverJni::OnStateChange() {
53 JNIEnv* env = AttachCurrentThreadIfNeeded();
54 Java_Observer_onStateChange(env, j_observer_global_);
55 }
56
OnMessage(const DataBuffer & buffer)57 void DataChannelObserverJni::OnMessage(const DataBuffer& buffer) {
58 JNIEnv* env = AttachCurrentThreadIfNeeded();
59 ScopedJavaLocalRef<jobject> byte_buffer = NewDirectByteBuffer(
60 env, const_cast<char*>(buffer.data.data<char>()), buffer.data.size());
61 ScopedJavaLocalRef<jobject> j_buffer =
62 Java_Buffer_Constructor(env, byte_buffer, buffer.binary);
63 Java_Observer_onMessage(env, j_observer_global_, j_buffer);
64 }
65
ExtractNativeDC(JNIEnv * jni,const JavaParamRef<jobject> & j_dc)66 DataChannelInterface* ExtractNativeDC(JNIEnv* jni,
67 const JavaParamRef<jobject>& j_dc) {
68 return reinterpret_cast<DataChannelInterface*>(
69 Java_DataChannel_getNativeDataChannel(jni, j_dc));
70 }
71
72 } // namespace
73
JavaToNativeDataChannelInit(JNIEnv * env,const JavaRef<jobject> & j_init)74 DataChannelInit JavaToNativeDataChannelInit(JNIEnv* env,
75 const JavaRef<jobject>& j_init) {
76 DataChannelInit init;
77 init.ordered = Java_Init_getOrdered(env, j_init);
78 init.maxRetransmitTime = Java_Init_getMaxRetransmitTimeMs(env, j_init);
79 init.maxRetransmits = Java_Init_getMaxRetransmits(env, j_init);
80 init.protocol = JavaToStdString(env, Java_Init_getProtocol(env, j_init));
81 init.negotiated = Java_Init_getNegotiated(env, j_init);
82 init.id = Java_Init_getId(env, j_init);
83 return init;
84 }
85
WrapNativeDataChannel(JNIEnv * env,rtc::scoped_refptr<DataChannelInterface> channel)86 ScopedJavaLocalRef<jobject> WrapNativeDataChannel(
87 JNIEnv* env,
88 rtc::scoped_refptr<DataChannelInterface> channel) {
89 if (!channel)
90 return nullptr;
91 // Channel is now owned by Java object, and will be freed from there.
92 return Java_DataChannel_Constructor(env, jlongFromPointer(channel.release()));
93 }
94
JNI_DataChannel_RegisterObserver(JNIEnv * jni,const JavaParamRef<jobject> & j_dc,const JavaParamRef<jobject> & j_observer)95 static jlong JNI_DataChannel_RegisterObserver(
96 JNIEnv* jni,
97 const JavaParamRef<jobject>& j_dc,
98 const JavaParamRef<jobject>& j_observer) {
99 auto observer = std::make_unique<DataChannelObserverJni>(jni, j_observer);
100 ExtractNativeDC(jni, j_dc)->RegisterObserver(observer.get());
101 return jlongFromPointer(observer.release());
102 }
103
JNI_DataChannel_UnregisterObserver(JNIEnv * jni,const JavaParamRef<jobject> & j_dc,jlong native_observer)104 static void JNI_DataChannel_UnregisterObserver(
105 JNIEnv* jni,
106 const JavaParamRef<jobject>& j_dc,
107 jlong native_observer) {
108 ExtractNativeDC(jni, j_dc)->UnregisterObserver();
109 delete reinterpret_cast<DataChannelObserverJni*>(native_observer);
110 }
111
JNI_DataChannel_Label(JNIEnv * jni,const JavaParamRef<jobject> & j_dc)112 static ScopedJavaLocalRef<jstring> JNI_DataChannel_Label(
113 JNIEnv* jni,
114 const JavaParamRef<jobject>& j_dc) {
115 return NativeToJavaString(jni, ExtractNativeDC(jni, j_dc)->label());
116 }
117
JNI_DataChannel_Id(JNIEnv * jni,const JavaParamRef<jobject> & j_dc)118 static jint JNI_DataChannel_Id(JNIEnv* jni, const JavaParamRef<jobject>& j_dc) {
119 int id = ExtractNativeDC(jni, j_dc)->id();
120 RTC_CHECK_LE(id, std::numeric_limits<int32_t>::max())
121 << "id overflowed jint!";
122 return static_cast<jint>(id);
123 }
124
JNI_DataChannel_State(JNIEnv * jni,const JavaParamRef<jobject> & j_dc)125 static ScopedJavaLocalRef<jobject> JNI_DataChannel_State(
126 JNIEnv* jni,
127 const JavaParamRef<jobject>& j_dc) {
128 return Java_State_fromNativeIndex(jni, ExtractNativeDC(jni, j_dc)->state());
129 }
130
JNI_DataChannel_BufferedAmount(JNIEnv * jni,const JavaParamRef<jobject> & j_dc)131 static jlong JNI_DataChannel_BufferedAmount(JNIEnv* jni,
132 const JavaParamRef<jobject>& j_dc) {
133 uint64_t buffered_amount = ExtractNativeDC(jni, j_dc)->buffered_amount();
134 RTC_CHECK_LE(buffered_amount, std::numeric_limits<int64_t>::max())
135 << "buffered_amount overflowed jlong!";
136 return static_cast<jlong>(buffered_amount);
137 }
138
JNI_DataChannel_Close(JNIEnv * jni,const JavaParamRef<jobject> & j_dc)139 static void JNI_DataChannel_Close(JNIEnv* jni,
140 const JavaParamRef<jobject>& j_dc) {
141 ExtractNativeDC(jni, j_dc)->Close();
142 }
143
JNI_DataChannel_Send(JNIEnv * jni,const JavaParamRef<jobject> & j_dc,const JavaParamRef<jbyteArray> & data,jboolean binary)144 static jboolean JNI_DataChannel_Send(JNIEnv* jni,
145 const JavaParamRef<jobject>& j_dc,
146 const JavaParamRef<jbyteArray>& data,
147 jboolean binary) {
148 std::vector<int8_t> buffer = JavaToNativeByteArray(jni, data);
149 bool ret = ExtractNativeDC(jni, j_dc)->Send(
150 DataBuffer(rtc::CopyOnWriteBuffer(buffer.data(), buffer.size()), binary));
151 return ret;
152 }
153
154 } // namespace jni
155 } // namespace webrtc
156