• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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