Improve AppRTCDemo connection speed by sending all

http POST requests asynchronously.

R=jiayl@webrtc.org, tkchin@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/33499004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@7820 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
glaznev@webrtc.org 2014-12-05 20:11:06 +00:00
parent bd8cc0b914
commit e2a9261f3e

View File

@ -26,7 +26,6 @@
*/ */
package org.appspot.apprtc; package org.appspot.apprtc;
import android.os.AsyncTask;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.util.Log; import android.util.Log;
@ -36,7 +35,6 @@ import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.net.URL; import java.net.URL;
import java.util.LinkedList;
import java.util.Scanner; import java.util.Scanner;
import org.appspot.apprtc.RoomParametersFetcher.RoomParametersFetcherEvents; import org.appspot.apprtc.RoomParametersFetcher.RoomParametersFetcherEvents;
@ -64,6 +62,9 @@ public class WebSocketRTCClient implements AppRTCClient,
private enum ConnectionState { private enum ConnectionState {
NEW, CONNECTED, CLOSED, ERROR NEW, CONNECTED, CLOSED, ERROR
}; };
private enum MessageType {
MESSAGE, BYE
};
private final Handler uiHandler; private final Handler uiHandler;
private boolean loopback; private boolean loopback;
private boolean initiator; private boolean initiator;
@ -71,14 +72,12 @@ public class WebSocketRTCClient implements AppRTCClient,
private WebSocketChannelClient wsClient; private WebSocketChannelClient wsClient;
private RoomParametersFetcher fetcher; private RoomParametersFetcher fetcher;
private ConnectionState roomState; private ConnectionState roomState;
private LinkedList<PostMessage> postQueue;
private String postMessageUrl; private String postMessageUrl;
private String byeMessageUrl; private String byeMessageUrl;
public WebSocketRTCClient(SignalingEvents events) { public WebSocketRTCClient(SignalingEvents events) {
this.events = events; this.events = events;
uiHandler = new Handler(Looper.getMainLooper()); uiHandler = new Handler(Looper.getMainLooper());
postQueue = new LinkedList<PostMessage>();
} }
// -------------------------------------------------------------------- // --------------------------------------------------------------------
@ -222,8 +221,9 @@ public class WebSocketRTCClient implements AppRTCClient,
Log.d(TAG, "Disconnect. Room state: " + roomState); Log.d(TAG, "Disconnect. Room state: " + roomState);
if (roomState == ConnectionState.CONNECTED) { if (roomState == ConnectionState.CONNECTED) {
Log.d(TAG, "Closing room."); Log.d(TAG, "Closing room.");
sendGAEMessage(byeMessageUrl, ""); sendPostMessage(MessageType.BYE, byeMessageUrl, "");
} }
roomState = ConnectionState.CLOSED;
if (wsClient != null) { if (wsClient != null) {
wsClient.disconnect(); wsClient.disconnect();
} }
@ -236,10 +236,14 @@ public class WebSocketRTCClient implements AppRTCClient,
// we might want to filter elsewhere. // we might want to filter elsewhere.
@Override @Override
public void sendOfferSdp(final SessionDescription sdp) { public void sendOfferSdp(final SessionDescription sdp) {
if (roomState != ConnectionState.CONNECTED) {
reportError("Sending offer SDP in non connected state.");
return;
}
JSONObject json = new JSONObject(); JSONObject json = new JSONObject();
jsonPut(json, "sdp", sdp.description); jsonPut(json, "sdp", sdp.description);
jsonPut(json, "type", "offer"); jsonPut(json, "type", "offer");
sendGAEMessage(postMessageUrl, json.toString()); sendPostMessage(MessageType.MESSAGE, postMessageUrl, json.toString());
if (loopback) { if (loopback) {
// In loopback mode rename this offer to answer and route it back. // In loopback mode rename this offer to answer and route it back.
SessionDescription sdpAnswer = new SessionDescription( SessionDescription sdpAnswer = new SessionDescription(
@ -279,7 +283,7 @@ public class WebSocketRTCClient implements AppRTCClient,
reportError("Sending ICE candidate in non connected state."); reportError("Sending ICE candidate in non connected state.");
return; return;
} }
sendGAEMessage(postMessageUrl, json.toString()); sendPostMessage(MessageType.MESSAGE, postMessageUrl, json.toString());
if (loopback) { if (loopback) {
events.onRemoteIceCandidate(candidate); events.onRemoteIceCandidate(candidate);
} }
@ -317,50 +321,36 @@ public class WebSocketRTCClient implements AppRTCClient,
} }
private class PostMessage { private class PostMessage {
PostMessage(String postUrl, String message) { PostMessage(MessageType type, String postUrl, String message) {
this.messageType = type;
this.postUrl = postUrl; this.postUrl = postUrl;
this.message = message; this.message = message;
} }
public final MessageType messageType;
public final String postUrl; public final String postUrl;
public final String message; public final String message;
} }
// Queue a message for sending to the room and send it if already connected. // Queue a message for sending to the room and send it if already connected.
private synchronized void sendGAEMessage(String url, String message) { private synchronized void sendPostMessage(
synchronized (postQueue) { MessageType messageType, String url, String message) {
postQueue.add(new PostMessage(url, message)); final PostMessage postMessage = new PostMessage(messageType, url, message);
Runnable runDrain = new Runnable() {
public void run() {
sendPostMessageAsync(postMessage);
} }
(new AsyncTask<Void, Void, Void>() { };
public Void doInBackground(Void... unused) { new Thread(runDrain).start();
maybeDrainGAEPostQueue();
return null;
}
}).execute();
} }
// Send all queued messages if connected to the room. // Send all queued POST messages to app engine server.
private void maybeDrainGAEPostQueue() { private void sendPostMessageAsync(PostMessage postMessage) {
if (roomState != ConnectionState.CONNECTED) { if (postMessage.messageType == MessageType.BYE) {
return;
}
PostMessage postMessage = null;
while (true) {
synchronized (postQueue) {
postMessage = postQueue.poll();
}
if (postMessage == null) {
break;
}
try {
// Check if this is 'bye' message and update room connection state.
if (postMessage.postUrl.contains("bye")) {
roomState = ConnectionState.CLOSED;
Log.d(TAG, "C->GAE: " + postMessage.postUrl); Log.d(TAG, "C->GAE: " + postMessage.postUrl);
} else { } else {
Log.d(TAG, "C->GAE: " + postMessage.message); Log.d(TAG, "C->GAE: " + postMessage.message);
} }
try {
// Get connection. // Get connection.
HttpURLConnection connection = HttpURLConnection connection =
(HttpURLConnection) new URL(postMessage.postUrl).openConnection(); (HttpURLConnection) new URL(postMessage.postUrl).openConnection();
@ -387,7 +377,7 @@ public class WebSocketRTCClient implements AppRTCClient,
InputStream responseStream = connection.getInputStream(); InputStream responseStream = connection.getInputStream();
String response = drainStream(responseStream); String response = drainStream(responseStream);
responseStream.close(); responseStream.close();
if (roomState != ConnectionState.CLOSED) { if (postMessage.messageType == MessageType.MESSAGE) {
JSONObject roomJson = new JSONObject(response); JSONObject roomJson = new JSONObject(response);
String result = roomJson.getString("result"); String result = roomJson.getString("result");
if (!result.equals("SUCCESS")) { if (!result.equals("SUCCESS")) {
@ -400,7 +390,6 @@ public class WebSocketRTCClient implements AppRTCClient,
reportError("GAE POST JSON error: " + e.getMessage()); reportError("GAE POST JSON error: " + e.getMessage());
} }
} }
}
// Return the contents of an InputStream as a String. // Return the contents of an InputStream as a String.
private String drainStream(InputStream in) { private String drainStream(InputStream in) {