1 /*
2  *  Copyright 2013 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 package org.webrtc;
12 
13 import java.nio.ByteBuffer;
14 
15 /** Java wrapper for a C++ DataChannelInterface. */
16 public class DataChannel {
17   /** Java wrapper for WebIDL RTCDataChannel. */
18   public static class Init {
19     public boolean ordered = true;
20     // Optional unsigned short in WebIDL, -1 means unspecified.
21     public int maxRetransmitTimeMs = -1;
22     // Optional unsigned short in WebIDL, -1 means unspecified.
23     public int maxRetransmits = -1;
24     public String protocol = "";
25     public boolean negotiated;
26     // Optional unsigned short in WebIDL, -1 means unspecified.
27     public int id = -1;
28 
29     @CalledByNative("Init")
getOrdered()30     boolean getOrdered() {
31       return ordered;
32     }
33 
34     @CalledByNative("Init")
getMaxRetransmitTimeMs()35     int getMaxRetransmitTimeMs() {
36       return maxRetransmitTimeMs;
37     }
38 
39     @CalledByNative("Init")
getMaxRetransmits()40     int getMaxRetransmits() {
41       return maxRetransmits;
42     }
43 
44     @CalledByNative("Init")
getProtocol()45     String getProtocol() {
46       return protocol;
47     }
48 
49     @CalledByNative("Init")
getNegotiated()50     boolean getNegotiated() {
51       return negotiated;
52     }
53 
54     @CalledByNative("Init")
getId()55     int getId() {
56       return id;
57     }
58   }
59 
60   /** Java version of C++ DataBuffer.  The atom of data in a DataChannel. */
61   public static class Buffer {
62     /** The underlying data. */
63     public final ByteBuffer data;
64 
65     /**
66      * Indicates whether |data| contains UTF-8 text or "binary data"
67      * (i.e. anything else).
68      */
69     public final boolean binary;
70 
71     @CalledByNative("Buffer")
Buffer(ByteBuffer data, boolean binary)72     public Buffer(ByteBuffer data, boolean binary) {
73       this.data = data;
74       this.binary = binary;
75     }
76   }
77 
78   /** Java version of C++ DataChannelObserver. */
79   public interface Observer {
80     /** The data channel's bufferedAmount has changed. */
onBufferedAmountChange(long previousAmount)81     @CalledByNative("Observer") public void onBufferedAmountChange(long previousAmount);
82     /** The data channel state has changed. */
onStateChange()83     @CalledByNative("Observer") public void onStateChange();
84     /**
85      * A data buffer was successfully received.  NOTE: |buffer.data| will be
86      * freed once this function returns so callers who want to use the data
87      * asynchronously must make sure to copy it first.
88      */
onMessage(Buffer buffer)89     @CalledByNative("Observer") public void onMessage(Buffer buffer);
90   }
91 
92   /** Keep in sync with DataChannelInterface::DataState. */
93   public enum State {
94     CONNECTING,
95     OPEN,
96     CLOSING,
97     CLOSED;
98 
99     @CalledByNative("State")
fromNativeIndex(int nativeIndex)100     static State fromNativeIndex(int nativeIndex) {
101       return values()[nativeIndex];
102     }
103   }
104 
105   private long nativeDataChannel;
106   private long nativeObserver;
107 
108   @CalledByNative
DataChannel(long nativeDataChannel)109   public DataChannel(long nativeDataChannel) {
110     this.nativeDataChannel = nativeDataChannel;
111   }
112 
113   /** Register |observer|, replacing any previously-registered observer. */
registerObserver(Observer observer)114   public void registerObserver(Observer observer) {
115     checkDataChannelExists();
116     if (nativeObserver != 0) {
117       nativeUnregisterObserver(nativeObserver);
118     }
119     nativeObserver = nativeRegisterObserver(observer);
120   }
121 
122   /** Unregister the (only) observer. */
unregisterObserver()123   public void unregisterObserver() {
124     checkDataChannelExists();
125     nativeUnregisterObserver(nativeObserver);
126   }
127 
label()128   public String label() {
129     checkDataChannelExists();
130     return nativeLabel();
131   }
132 
id()133   public int id() {
134     checkDataChannelExists();
135     return nativeId();
136   }
137 
state()138   public State state() {
139     checkDataChannelExists();
140     return nativeState();
141   }
142 
143   /**
144    * Return the number of bytes of application data (UTF-8 text and binary data)
145    * that have been queued using SendBuffer but have not yet been transmitted
146    * to the network.
147    */
bufferedAmount()148   public long bufferedAmount() {
149     checkDataChannelExists();
150     return nativeBufferedAmount();
151   }
152 
153   /** Close the channel. */
close()154   public void close() {
155     checkDataChannelExists();
156     nativeClose();
157   }
158 
159   /** Send |data| to the remote peer; return success. */
send(Buffer buffer)160   public boolean send(Buffer buffer) {
161     checkDataChannelExists();
162     // TODO(fischman): this could be cleverer about avoiding copies if the
163     // ByteBuffer is direct and/or is backed by an array.
164     byte[] data = new byte[buffer.data.remaining()];
165     buffer.data.get(data);
166     return nativeSend(data, buffer.binary);
167   }
168 
169   /** Dispose of native resources attached to this channel. */
dispose()170   public void dispose() {
171     checkDataChannelExists();
172     JniCommon.nativeReleaseRef(nativeDataChannel);
173     nativeDataChannel = 0;
174   }
175 
176   @CalledByNative
getNativeDataChannel()177   long getNativeDataChannel() {
178     return nativeDataChannel;
179   }
180 
checkDataChannelExists()181   private void checkDataChannelExists() {
182     if (nativeDataChannel == 0) {
183       throw new IllegalStateException("DataChannel has been disposed.");
184     }
185   }
186 
nativeRegisterObserver(Observer observer)187   private native long nativeRegisterObserver(Observer observer);
nativeUnregisterObserver(long observer)188   private native void nativeUnregisterObserver(long observer);
nativeLabel()189   private native String nativeLabel();
nativeId()190   private native int nativeId();
nativeState()191   private native State nativeState();
nativeBufferedAmount()192   private native long nativeBufferedAmount();
nativeClose()193   private native void nativeClose();
nativeSend(byte[] data, boolean binary)194   private native boolean nativeSend(byte[] data, boolean binary);
195 };
196