| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2014 The WebRTC Project Authors. All rights reserved. | 2 * Copyright 2014 The WebRTC Project Authors. All rights reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 | 10 |
| 11 package org.appspot.apprtc; | 11 package org.appspot.apprtc; |
| 12 | 12 |
| 13 import org.appspot.apprtc.util.AsyncHttpURLConnection; | 13 import org.appspot.apprtc.util.AsyncHttpURLConnection; |
| 14 import org.appspot.apprtc.util.AsyncHttpURLConnection.AsyncHttpEvents; | 14 import org.appspot.apprtc.util.AsyncHttpURLConnection.AsyncHttpEvents; |
| 15 import org.appspot.apprtc.util.LooperExecutor; | |
| 16 | 15 |
| 16 import android.os.Handler; |
| 17 import android.util.Log; | 17 import android.util.Log; |
| 18 | 18 |
| 19 import de.tavendo.autobahn.WebSocket.WebSocketConnectionObserver; | 19 import de.tavendo.autobahn.WebSocket.WebSocketConnectionObserver; |
| 20 import de.tavendo.autobahn.WebSocketConnection; | 20 import de.tavendo.autobahn.WebSocketConnection; |
| 21 import de.tavendo.autobahn.WebSocketException; | 21 import de.tavendo.autobahn.WebSocketException; |
| 22 | 22 |
| 23 import org.json.JSONException; | 23 import org.json.JSONException; |
| 24 import org.json.JSONObject; | 24 import org.json.JSONObject; |
| 25 | 25 |
| 26 import java.net.URI; | 26 import java.net.URI; |
| 27 import java.net.URISyntaxException; | 27 import java.net.URISyntaxException; |
| 28 import java.util.LinkedList; | 28 import java.util.LinkedList; |
| 29 | 29 |
| 30 /** | 30 /** |
| 31 * WebSocket client implementation. | 31 * WebSocket client implementation. |
| 32 * | 32 * |
| 33 * <p>All public methods should be called from a looper executor thread | 33 * <p>All public methods should be called from a looper executor thread |
| 34 * passed in a constructor, otherwise exception will be thrown. | 34 * passed in a constructor, otherwise exception will be thrown. |
| 35 * All events are dispatched on the same thread. | 35 * All events are dispatched on the same thread. |
| 36 */ | 36 */ |
| 37 | 37 |
| 38 public class WebSocketChannelClient { | 38 public class WebSocketChannelClient { |
| 39 private static final String TAG = "WSChannelRTCClient"; | 39 private static final String TAG = "WSChannelRTCClient"; |
| 40 private static final int CLOSE_TIMEOUT = 1000; | 40 private static final int CLOSE_TIMEOUT = 1000; |
| 41 private final WebSocketChannelEvents events; | 41 private final WebSocketChannelEvents events; |
| 42 private final LooperExecutor executor; | 42 private final Handler handler; |
| 43 private WebSocketConnection ws; | 43 private WebSocketConnection ws; |
| 44 private WebSocketObserver wsObserver; | 44 private WebSocketObserver wsObserver; |
| 45 private String wsServerUrl; | 45 private String wsServerUrl; |
| 46 private String postServerUrl; | 46 private String postServerUrl; |
| 47 private String roomID; | 47 private String roomID; |
| 48 private String clientID; | 48 private String clientID; |
| 49 private WebSocketConnectionState state; | 49 private WebSocketConnectionState state; |
| 50 private final Object closeEventLock = new Object(); | 50 private final Object closeEventLock = new Object(); |
| 51 private boolean closeEvent; | 51 private boolean closeEvent; |
| 52 // WebSocket send queue. Messages are added to the queue when WebSocket | 52 // WebSocket send queue. Messages are added to the queue when WebSocket |
| (...skipping 10 matching lines...) Expand all Loading... |
| 63 /** | 63 /** |
| 64 * Callback interface for messages delivered on WebSocket. | 64 * Callback interface for messages delivered on WebSocket. |
| 65 * All events are dispatched from a looper executor thread. | 65 * All events are dispatched from a looper executor thread. |
| 66 */ | 66 */ |
| 67 public interface WebSocketChannelEvents { | 67 public interface WebSocketChannelEvents { |
| 68 void onWebSocketMessage(final String message); | 68 void onWebSocketMessage(final String message); |
| 69 void onWebSocketClose(); | 69 void onWebSocketClose(); |
| 70 void onWebSocketError(final String description); | 70 void onWebSocketError(final String description); |
| 71 } | 71 } |
| 72 | 72 |
| 73 public WebSocketChannelClient(LooperExecutor executor, WebSocketChannelEvents
events) { | 73 public WebSocketChannelClient(Handler handler, WebSocketChannelEvents events)
{ |
| 74 this.executor = executor; | 74 this.handler = handler; |
| 75 this.events = events; | 75 this.events = events; |
| 76 roomID = null; | 76 roomID = null; |
| 77 clientID = null; | 77 clientID = null; |
| 78 wsSendQueue = new LinkedList<String>(); | 78 wsSendQueue = new LinkedList<String>(); |
| 79 state = WebSocketConnectionState.NEW; | 79 state = WebSocketConnectionState.NEW; |
| 80 } | 80 } |
| 81 | 81 |
| 82 public WebSocketConnectionState getState() { | 82 public WebSocketConnectionState getState() { |
| 83 return state; | 83 return state; |
| 84 } | 84 } |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 197 } | 197 } |
| 198 } | 198 } |
| 199 } | 199 } |
| 200 } | 200 } |
| 201 } | 201 } |
| 202 Log.d(TAG, "Disconnecting WebSocket done."); | 202 Log.d(TAG, "Disconnecting WebSocket done."); |
| 203 } | 203 } |
| 204 | 204 |
| 205 private void reportError(final String errorMessage) { | 205 private void reportError(final String errorMessage) { |
| 206 Log.e(TAG, errorMessage); | 206 Log.e(TAG, errorMessage); |
| 207 executor.execute(new Runnable() { | 207 handler.post(new Runnable() { |
| 208 @Override | 208 @Override |
| 209 public void run() { | 209 public void run() { |
| 210 if (state != WebSocketConnectionState.ERROR) { | 210 if (state != WebSocketConnectionState.ERROR) { |
| 211 state = WebSocketConnectionState.ERROR; | 211 state = WebSocketConnectionState.ERROR; |
| 212 events.onWebSocketError(errorMessage); | 212 events.onWebSocketError(errorMessage); |
| 213 } | 213 } |
| 214 } | 214 } |
| 215 }); | 215 }); |
| 216 } | 216 } |
| 217 | 217 |
| 218 // Asynchronously send POST/DELETE to WebSocket server. | 218 // Asynchronously send POST/DELETE to WebSocket server. |
| 219 private void sendWSSMessage(final String method, final String message) { | 219 private void sendWSSMessage(final String method, final String message) { |
| 220 String postUrl = postServerUrl + "/" + roomID + "/" + clientID; | 220 String postUrl = postServerUrl + "/" + roomID + "/" + clientID; |
| 221 Log.d(TAG, "WS " + method + " : " + postUrl + " : " + message); | 221 Log.d(TAG, "WS " + method + " : " + postUrl + " : " + message); |
| 222 AsyncHttpURLConnection httpConnection = new AsyncHttpURLConnection( | 222 AsyncHttpURLConnection httpConnection = new AsyncHttpURLConnection( |
| 223 method, postUrl, message, new AsyncHttpEvents() { | 223 method, postUrl, message, new AsyncHttpEvents() { |
| 224 @Override | 224 @Override |
| 225 public void onHttpError(String errorMessage) { | 225 public void onHttpError(String errorMessage) { |
| 226 reportError("WS " + method + " error: " + errorMessage); | 226 reportError("WS " + method + " error: " + errorMessage); |
| 227 } | 227 } |
| 228 | 228 |
| 229 @Override | 229 @Override |
| 230 public void onHttpComplete(String response) { | 230 public void onHttpComplete(String response) { |
| 231 } | 231 } |
| 232 }); | 232 }); |
| 233 httpConnection.send(); | 233 httpConnection.send(); |
| 234 } | 234 } |
| 235 | 235 |
| 236 // Helper method for debugging purposes. Ensures that WebSocket method is | 236 // Helper method for debugging purposes. Ensures that WebSocket method is |
| 237 // called on a looper thread. | 237 // called on a looper thread. |
| 238 private void checkIfCalledOnValidThread() { | 238 private void checkIfCalledOnValidThread() { |
| 239 if (!executor.checkOnLooperThread()) { | 239 if (Thread.currentThread() != handler.getLooper().getThread()) { |
| 240 throw new IllegalStateException( | 240 throw new IllegalStateException( |
| 241 "WebSocket method is not called on valid thread"); | 241 "WebSocket method is not called on valid thread"); |
| 242 } | 242 } |
| 243 } | 243 } |
| 244 | 244 |
| 245 private class WebSocketObserver implements WebSocketConnectionObserver { | 245 private class WebSocketObserver implements WebSocketConnectionObserver { |
| 246 @Override | 246 @Override |
| 247 public void onOpen() { | 247 public void onOpen() { |
| 248 Log.d(TAG, "WebSocket connection opened to: " + wsServerUrl); | 248 Log.d(TAG, "WebSocket connection opened to: " + wsServerUrl); |
| 249 executor.execute(new Runnable() { | 249 handler.post(new Runnable() { |
| 250 @Override | 250 @Override |
| 251 public void run() { | 251 public void run() { |
| 252 state = WebSocketConnectionState.CONNECTED; | 252 state = WebSocketConnectionState.CONNECTED; |
| 253 // Check if we have pending register request. | 253 // Check if we have pending register request. |
| 254 if (roomID != null && clientID != null) { | 254 if (roomID != null && clientID != null) { |
| 255 register(roomID, clientID); | 255 register(roomID, clientID); |
| 256 } | 256 } |
| 257 } | 257 } |
| 258 }); | 258 }); |
| 259 } | 259 } |
| 260 | 260 |
| 261 @Override | 261 @Override |
| 262 public void onClose(WebSocketCloseNotification code, String reason) { | 262 public void onClose(WebSocketCloseNotification code, String reason) { |
| 263 Log.d(TAG, "WebSocket connection closed. Code: " + code | 263 Log.d(TAG, "WebSocket connection closed. Code: " + code |
| 264 + ". Reason: " + reason + ". State: " + state); | 264 + ". Reason: " + reason + ". State: " + state); |
| 265 synchronized (closeEventLock) { | 265 synchronized (closeEventLock) { |
| 266 closeEvent = true; | 266 closeEvent = true; |
| 267 closeEventLock.notify(); | 267 closeEventLock.notify(); |
| 268 } | 268 } |
| 269 executor.execute(new Runnable() { | 269 handler.post(new Runnable() { |
| 270 @Override | 270 @Override |
| 271 public void run() { | 271 public void run() { |
| 272 if (state != WebSocketConnectionState.CLOSED) { | 272 if (state != WebSocketConnectionState.CLOSED) { |
| 273 state = WebSocketConnectionState.CLOSED; | 273 state = WebSocketConnectionState.CLOSED; |
| 274 events.onWebSocketClose(); | 274 events.onWebSocketClose(); |
| 275 } | 275 } |
| 276 } | 276 } |
| 277 }); | 277 }); |
| 278 } | 278 } |
| 279 | 279 |
| 280 @Override | 280 @Override |
| 281 public void onTextMessage(String payload) { | 281 public void onTextMessage(String payload) { |
| 282 Log.d(TAG, "WSS->C: " + payload); | 282 Log.d(TAG, "WSS->C: " + payload); |
| 283 final String message = payload; | 283 final String message = payload; |
| 284 executor.execute(new Runnable() { | 284 handler.post(new Runnable() { |
| 285 @Override | 285 @Override |
| 286 public void run() { | 286 public void run() { |
| 287 if (state == WebSocketConnectionState.CONNECTED | 287 if (state == WebSocketConnectionState.CONNECTED |
| 288 || state == WebSocketConnectionState.REGISTERED) { | 288 || state == WebSocketConnectionState.REGISTERED) { |
| 289 events.onWebSocketMessage(message); | 289 events.onWebSocketMessage(message); |
| 290 } | 290 } |
| 291 } | 291 } |
| 292 }); | 292 }); |
| 293 } | 293 } |
| 294 | 294 |
| 295 @Override | 295 @Override |
| 296 public void onRawTextMessage(byte[] payload) { | 296 public void onRawTextMessage(byte[] payload) { |
| 297 } | 297 } |
| 298 | 298 |
| 299 @Override | 299 @Override |
| 300 public void onBinaryMessage(byte[] payload) { | 300 public void onBinaryMessage(byte[] payload) { |
| 301 } | 301 } |
| 302 } | 302 } |
| 303 | 303 |
| 304 } | 304 } |
| OLD | NEW |