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 nativeObserver = 0; 127 } 128 label()129 public String label() { 130 checkDataChannelExists(); 131 return nativeLabel(); 132 } 133 id()134 public int id() { 135 checkDataChannelExists(); 136 return nativeId(); 137 } 138 state()139 public State state() { 140 checkDataChannelExists(); 141 return nativeState(); 142 } 143 144 /** 145 * Return the number of bytes of application data (UTF-8 text and binary data) 146 * that have been queued using SendBuffer but have not yet been transmitted 147 * to the network. 148 */ bufferedAmount()149 public long bufferedAmount() { 150 checkDataChannelExists(); 151 return nativeBufferedAmount(); 152 } 153 154 /** Close the channel. */ close()155 public void close() { 156 checkDataChannelExists(); 157 nativeClose(); 158 } 159 160 /** Send `data` to the remote peer; return success. */ send(Buffer buffer)161 public boolean send(Buffer buffer) { 162 checkDataChannelExists(); 163 // TODO(fischman): this could be cleverer about avoiding copies if the 164 // ByteBuffer is direct and/or is backed by an array. 165 byte[] data = new byte[buffer.data.remaining()]; 166 buffer.data.get(data); 167 return nativeSend(data, buffer.binary); 168 } 169 170 /** Dispose of native resources attached to this channel. */ dispose()171 public void dispose() { 172 checkDataChannelExists(); 173 JniCommon.nativeReleaseRef(nativeDataChannel); 174 nativeDataChannel = 0; 175 } 176 177 @CalledByNative getNativeDataChannel()178 long getNativeDataChannel() { 179 return nativeDataChannel; 180 } 181 checkDataChannelExists()182 private void checkDataChannelExists() { 183 if (nativeDataChannel == 0) { 184 throw new IllegalStateException("DataChannel has been disposed."); 185 } 186 } 187 nativeRegisterObserver(Observer observer)188 private native long nativeRegisterObserver(Observer observer); nativeUnregisterObserver(long observer)189 private native void nativeUnregisterObserver(long observer); nativeLabel()190 private native String nativeLabel(); nativeId()191 private native int nativeId(); nativeState()192 private native State nativeState(); nativeBufferedAmount()193 private native long nativeBufferedAmount(); nativeClose()194 private native void nativeClose(); nativeSend(byte[] data, boolean binary)195 private native boolean nativeSend(byte[] data, boolean binary); 196 }; 197