[tor-commits] [snowflake-mobile/master] Added WebRTC code
cohosh at torproject.org
cohosh at torproject.org
Tue Jun 16 14:34:48 UTC 2020
commit 31ad93897d022677ad1195365f166ba5e09370a6
Author: Hashik Donthineni <HashikDonthineni at gmail.com>
Date: Tue Jun 9 12:50:11 2020 +0530
Added WebRTC code
---
.../snowflake/MyPeerConnectionObserver.java | 97 ++++++++++++++++++++++
.../torproject/snowflake/MyPersistentService.java | 95 ++++++++++++++++++++-
.../interfaces/PeerConnectionObserverCallback.java | 18 ++++
3 files changed, 208 insertions(+), 2 deletions(-)
diff --git a/app/src/main/java/org/torproject/snowflake/MyPeerConnectionObserver.java b/app/src/main/java/org/torproject/snowflake/MyPeerConnectionObserver.java
new file mode 100644
index 0000000..5d96dae
--- /dev/null
+++ b/app/src/main/java/org/torproject/snowflake/MyPeerConnectionObserver.java
@@ -0,0 +1,97 @@
+package org.torproject.snowflake;
+
+import android.util.Log;
+
+import org.torproject.snowflake.interfaces.PeerConnectionObserverCallback;
+import org.webrtc.DataChannel;
+import org.webrtc.IceCandidate;
+import org.webrtc.MediaStream;
+import org.webrtc.PeerConnection;
+import org.webrtc.RtpReceiver;
+
+public class MyPeerConnectionObserver implements PeerConnection.Observer {
+ private final String TAG;
+ private PeerConnectionObserverCallback peerconnectionObserverCallback;
+
+ public MyPeerConnectionObserver(String tag, PeerConnectionObserverCallback callback) {
+ TAG = tag + ": MyPeerConnectionObserver: ";
+ this.peerconnectionObserverCallback = callback;
+ }
+
+ @Override
+ public void onSignalingChange(PeerConnection.SignalingState signalingState) {
+ Log.d(TAG, "onSignalingChange: " + signalingState);
+ }
+
+ @Override
+ public void onIceConnectionChange(PeerConnection.IceConnectionState iceConnectionState) {
+ Log.d(TAG, "onIceConnectionChange: " + iceConnectionState);
+ //TODO:Handle Connection Failure.
+ }
+
+ @Override
+ public void onIceConnectionReceivingChange(boolean b) {
+ Log.d(TAG, "onIceConnectionReceivingChange: ");
+ }
+
+ @Override
+ public void onIceGatheringChange(PeerConnection.IceGatheringState iceGatheringState) {
+ Log.d(TAG, "onIceGatheringChange: " + iceGatheringState);
+ if (iceGatheringState.compareTo(PeerConnection.IceGatheringState.COMPLETE) == 0)
+ peerconnectionObserverCallback.onIceGatheringFinish();
+ }
+
+ @Override
+ public void onIceCandidate(IceCandidate iceCandidate) {
+ //Fired after each ICE candidate is gathered. AKA ICE trickling.
+ Log.d(TAG, "onIceCandidate: SDP:" + iceCandidate.sdp);
+ }
+
+ @Override
+ public void onIceCandidatesRemoved(IceCandidate[] iceCandidates) {
+ Log.d(TAG, "onIceCandidatesRemoved: ");
+ }
+
+ @Override
+ public void onAddStream(MediaStream mediaStream) {
+ Log.d(TAG, "onAddStream: ");
+ }
+
+ @Override
+ public void onRemoveStream(MediaStream mediaStream) {
+ Log.d(TAG, "onRemoveStream: ");
+ }
+
+ @Override
+ public void onDataChannel(DataChannel dataChannel) {
+ Log.d(TAG, "onDataChannel: State: " + dataChannel.state() + " Registering Observer...");
+ dataChannel.registerObserver(new DataChannel.Observer() {
+ @Override
+ public void onBufferedAmountChange(long l) {
+
+ }
+
+ @Override
+ public void onStateChange() {
+ peerconnectionObserverCallback.dataChannelStateChange(dataChannel.state());
+ }
+
+ @Override
+ public void onMessage(DataChannel.Buffer buffer) {
+ Log.d(TAG, "onMessage: Received");
+ peerconnectionObserverCallback.onMessage(buffer);
+ }
+ });
+ peerconnectionObserverCallback.onDataChannel(dataChannel);
+ }
+
+ @Override
+ public void onRenegotiationNeeded() {
+ Log.d(TAG, "onRenegotiationNeeded: ");
+ }
+
+ @Override
+ public void onAddTrack(RtpReceiver rtpReceiver, MediaStream[] mediaStreams) {
+ Log.d(TAG, "onAddTrack: ");
+ }
+}
diff --git a/app/src/main/java/org/torproject/snowflake/MyPersistentService.java b/app/src/main/java/org/torproject/snowflake/MyPersistentService.java
index 564fe03..2a7c52d 100644
--- a/app/src/main/java/org/torproject/snowflake/MyPersistentService.java
+++ b/app/src/main/java/org/torproject/snowflake/MyPersistentService.java
@@ -13,12 +13,25 @@ import android.util.Log;
import androidx.annotation.Nullable;
import org.torproject.snowflake.constants.ForegroundServiceConstants;
+import org.torproject.snowflake.interfaces.PeerConnectionObserverCallback;
+import org.webrtc.DataChannel;
+import org.webrtc.PeerConnection;
+import org.webrtc.PeerConnectionFactory;
+
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+import java.util.LinkedList;
+import java.util.List;
/**
* Main Snowflake implementation of foreground service to relay data in the background.
*/
public class MyPersistentService extends Service {
private static final String TAG = "MyPersistentService";
+ //WebRTC vars
+ DataChannel mainDataChannel;
+ PeerConnection mainPeerConnection;
+ PeerConnectionFactory factory;
private SharedPreferences sharedPreferences;
private boolean isServiceStarted;
private PowerManager.WakeLock wakeLock;
@@ -121,7 +134,7 @@ public class MyPersistentService extends Service {
return builder.build();
}
- //Starting and stopping service
+ /////////////// Start/Stop Service ////////////////////////
/**
* Use to star/re-start the service
@@ -140,7 +153,7 @@ public class MyPersistentService extends Service {
wakeLock.acquire(); //WakeLock acquired for unlimited amount of time.
///
- //TODO: Start WebRTC connection.
+ startWebRTCConnection(); //Starting WebRTC
}
/**
@@ -160,5 +173,83 @@ public class MyPersistentService extends Service {
isServiceStarted = false;
}
+ /////////////// WebRTC ////////////////////////
+
+ /**
+ * Initializing and starting WebRTC connection.
+ */
+ private void startWebRTCConnection() {
+ initializePeerConnectionFactory(); //Android Specific, you can Ignore.
+ mainPeerConnection = createPeerConnection(factory); //Creating New Peer Connection.
+ //TODO: Fetch Offer from broker.
+ }
+
+ /**
+ * Initializing peer connection factory.
+ */
+ private void initializePeerConnectionFactory() {
+ Log.d(TAG, "initializePeerConnectionFactory: Started");
+ PeerConnectionFactory.InitializationOptions initializationOptions =
+ PeerConnectionFactory.InitializationOptions.builder(this)
+ .createInitializationOptions();
+ PeerConnectionFactory.initialize(initializationOptions);
+
+ PeerConnectionFactory.Options options = new PeerConnectionFactory.Options();
+ factory = PeerConnectionFactory.builder()
+ .setOptions(options)
+ .createPeerConnectionFactory();
+ Log.d(TAG, "initializePeerConnectionFactory: Finished");
+ }
+
+ /**
+ * Creating a new peer connection.
+ *
+ * @param factory PeerConnectionFactory
+ * @return New PeerConnection
+ */
+ private PeerConnection createPeerConnection(PeerConnectionFactory factory) {
+ Log.d(TAG, "createPeerConnection: Creating a new peer connection");
+ List<PeerConnection.IceServer> iceServers = new LinkedList<>();
+// iceServers.add(PeerConnection.IceServer.builder("stun:stun.l.google.com:19302").createIceServer()); To Add custom ICE servers.
+ PeerConnection.RTCConfiguration rtcConfiguration = new PeerConnection.RTCConfiguration(iceServers);
+ PeerConnection.Observer pcObserver = new MyPeerConnectionObserver(TAG, new PeerConnectionObserverCallback() {
+
+ @Override
+ public void onIceGatheringFinish() {
+ if (mainPeerConnection.connectionState() != PeerConnection.PeerConnectionState.CLOSED) {
+ Log.d(TAG, "onIceGatheringFinish: Ice Gathering Finished. Sending Answer to broker...\n" + mainPeerConnection.getLocalDescription().description);
+ //Sending the SDP Answer to the server.
+ //TODO:Send Answer
+ }
+ }
+
+ @Override
+ public void onMessage(DataChannel.Buffer buffer) {
+ //Relay it to WebSocket
+ ByteBuffer data = ByteBuffer.wrap("HELLO".getBytes(Charset.defaultCharset())); //Sending some temporary data to test.
+ mainDataChannel.send(new DataChannel.Buffer(data, false));
+ }
+
+ @Override
+ public void onDataChannel(DataChannel dataChannel) {
+ Log.d(TAG, "onDataChannel: Setting Data Channel");
+ mainDataChannel = dataChannel;
+ }
+
+ @Override
+ public void iceConnectionFailed() {
+ Log.d(TAG, "iceConnectionFailed: ");
+ //Figuring out with trac ticket.
+ }
+
+ @Override
+ public void dataChannelStateChange(final DataChannel.State STATE) {
+ Log.d(TAG, "dataChannelStateChange: Data Channel State: " + STATE);
+ }
+ });
+
+ Log.d(TAG, "createPeerConnection: Finished creating peer connection.");
+ return factory.createPeerConnection(rtcConfiguration, pcObserver);
+ }
/////////////////////////////////////
}
diff --git a/app/src/main/java/org/torproject/snowflake/interfaces/PeerConnectionObserverCallback.java b/app/src/main/java/org/torproject/snowflake/interfaces/PeerConnectionObserverCallback.java
new file mode 100644
index 0000000..56be3ff
--- /dev/null
+++ b/app/src/main/java/org/torproject/snowflake/interfaces/PeerConnectionObserverCallback.java
@@ -0,0 +1,18 @@
+package org.torproject.snowflake.interfaces;
+
+import org.webrtc.DataChannel;
+
+/**
+ * Callback to MyPersistentService when even happens form PeerConnectionObserver.
+ */
+public interface PeerConnectionObserverCallback {
+ void onIceGatheringFinish();
+
+ void onMessage(DataChannel.Buffer buffer);
+
+ void onDataChannel(DataChannel dataChannel);
+
+ void dataChannelStateChange(final DataChannel.State state);
+
+ void iceConnectionFailed();
+}
More information about the tor-commits
mailing list