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 |