| 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.RoomParametersFetcher.RoomParametersFetcherEvents; | 13 import org.appspot.apprtc.RoomParametersFetcher.RoomParametersFetcherEvents; |
| 14 import org.appspot.apprtc.WebSocketChannelClient.WebSocketChannelEvents; | 14 import org.appspot.apprtc.WebSocketChannelClient.WebSocketChannelEvents; |
| 15 import org.appspot.apprtc.WebSocketChannelClient.WebSocketConnectionState; | 15 import org.appspot.apprtc.WebSocketChannelClient.WebSocketConnectionState; |
| 16 import org.appspot.apprtc.util.AsyncHttpURLConnection; | 16 import org.appspot.apprtc.util.AsyncHttpURLConnection; |
| 17 import org.appspot.apprtc.util.AsyncHttpURLConnection.AsyncHttpEvents; | 17 import org.appspot.apprtc.util.AsyncHttpURLConnection.AsyncHttpEvents; |
| 18 import org.appspot.apprtc.util.LooperExecutor; | 18 import org.appspot.apprtc.util.LooperExecutor; |
| 19 | 19 |
| 20 import android.util.Log; | 20 import android.util.Log; |
| 21 | 21 |
| 22 import org.json.JSONArray; |
| 22 import org.json.JSONException; | 23 import org.json.JSONException; |
| 23 import org.json.JSONObject; | 24 import org.json.JSONObject; |
| 24 import org.webrtc.IceCandidate; | 25 import org.webrtc.IceCandidate; |
| 25 import org.webrtc.SessionDescription; | 26 import org.webrtc.SessionDescription; |
| 26 | 27 |
| 27 /** | 28 /** |
| 28 * Negotiates signaling for chatting with apprtc.appspot.com "rooms". | 29 * Negotiates signaling for chatting with apprtc.appspot.com "rooms". |
| 29 * Uses the client<->server specifics of the apprtc AppEngine webapp. | 30 * Uses the client<->server specifics of the apprtc AppEngine webapp. |
| 30 * | 31 * |
| 31 * <p>To use: create an instance of this object (registering a message handler)
and | 32 * <p>To use: create an instance of this object (registering a message handler)
and |
| (...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 245 events.onRemoteIceCandidate(candidate); | 246 events.onRemoteIceCandidate(candidate); |
| 246 } | 247 } |
| 247 } else { | 248 } else { |
| 248 // Call receiver sends ice candidates to websocket server. | 249 // Call receiver sends ice candidates to websocket server. |
| 249 wsClient.send(json.toString()); | 250 wsClient.send(json.toString()); |
| 250 } | 251 } |
| 251 } | 252 } |
| 252 }); | 253 }); |
| 253 } | 254 } |
| 254 | 255 |
| 256 // Send removed Ice candidates to the other participant. |
| 257 @Override |
| 258 public void sendLocalIceCandidateRemovals(final IceCandidate[] candidates) { |
| 259 executor.execute(new Runnable() { |
| 260 @Override |
| 261 public void run() { |
| 262 JSONObject json = new JSONObject(); |
| 263 jsonPut(json, "type", "remove-candidates"); |
| 264 JSONArray jsonArray = new JSONArray(); |
| 265 for (final IceCandidate candidate : candidates) { |
| 266 jsonArray.put(toJsonCandidate(candidate)); |
| 267 } |
| 268 jsonPut(json, "candidates", jsonArray); |
| 269 if (initiator) { |
| 270 // Call initiator sends ice candidates to GAE server. |
| 271 if (roomState != ConnectionState.CONNECTED) { |
| 272 reportError("Sending ICE candidate removals in non connected state."
); |
| 273 return; |
| 274 } |
| 275 sendPostMessage(MessageType.MESSAGE, messageUrl, json.toString()); |
| 276 if (connectionParameters.loopback) { |
| 277 events.onRemoteIceCandidatesRemoved(candidates); |
| 278 } |
| 279 } else { |
| 280 // Call receiver sends ice candidates to websocket server. |
| 281 wsClient.send(json.toString()); |
| 282 } |
| 283 } |
| 284 }); |
| 285 } |
| 286 |
| 255 // -------------------------------------------------------------------- | 287 // -------------------------------------------------------------------- |
| 256 // WebSocketChannelEvents interface implementation. | 288 // WebSocketChannelEvents interface implementation. |
| 257 // All events are called by WebSocketChannelClient on a local looper thread | 289 // All events are called by WebSocketChannelClient on a local looper thread |
| 258 // (passed to WebSocket client constructor). | 290 // (passed to WebSocket client constructor). |
| 259 @Override | 291 @Override |
| 260 public void onWebSocketMessage(final String msg) { | 292 public void onWebSocketMessage(final String msg) { |
| 261 if (wsClient.getState() != WebSocketConnectionState.REGISTERED) { | 293 if (wsClient.getState() != WebSocketConnectionState.REGISTERED) { |
| 262 Log.e(TAG, "Got WebSocket message in non registered state."); | 294 Log.e(TAG, "Got WebSocket message in non registered state."); |
| 263 return; | 295 return; |
| 264 } | 296 } |
| 265 try { | 297 try { |
| 266 JSONObject json = new JSONObject(msg); | 298 JSONObject json = new JSONObject(msg); |
| 267 String msgText = json.getString("msg"); | 299 String msgText = json.getString("msg"); |
| 268 String errorText = json.optString("error"); | 300 String errorText = json.optString("error"); |
| 269 if (msgText.length() > 0) { | 301 if (msgText.length() > 0) { |
| 270 json = new JSONObject(msgText); | 302 json = new JSONObject(msgText); |
| 271 String type = json.optString("type"); | 303 String type = json.optString("type"); |
| 272 if (type.equals("candidate")) { | 304 if (type.equals("candidate")) { |
| 273 IceCandidate candidate = new IceCandidate( | 305 events.onRemoteIceCandidate(toJavaCandidate(json)); |
| 274 json.getString("id"), | 306 } else if (type.equals("remove-candidates")) { |
| 275 json.getInt("label"), | 307 JSONArray candidateArray = json.getJSONArray("candidates"); |
| 276 json.getString("candidate")); | 308 IceCandidate[] candidates = new IceCandidate[candidateArray.length()]; |
| 277 events.onRemoteIceCandidate(candidate); | 309 for (int i =0; i < candidateArray.length(); ++i) { |
| 310 candidates[i] = toJavaCandidate(candidateArray.getJSONObject(i)); |
| 311 } |
| 312 events.onRemoteIceCandidatesRemoved(candidates); |
| 278 } else if (type.equals("answer")) { | 313 } else if (type.equals("answer")) { |
| 279 if (initiator) { | 314 if (initiator) { |
| 280 SessionDescription sdp = new SessionDescription( | 315 SessionDescription sdp = new SessionDescription( |
| 281 SessionDescription.Type.fromCanonicalForm(type), | 316 SessionDescription.Type.fromCanonicalForm(type), |
| 282 json.getString("sdp")); | 317 json.getString("sdp")); |
| 283 events.onRemoteDescription(sdp); | 318 events.onRemoteDescription(sdp); |
| 284 } else { | 319 } else { |
| 285 reportError("Received answer for call initiator: " + msg); | 320 reportError("Received answer for call initiator: " + msg); |
| 286 } | 321 } |
| 287 } else if (type.equals("offer")) { | 322 } else if (type.equals("offer")) { |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 369 reportError("GAE POST error: " + result); | 404 reportError("GAE POST error: " + result); |
| 370 } | 405 } |
| 371 } catch (JSONException e) { | 406 } catch (JSONException e) { |
| 372 reportError("GAE POST JSON error: " + e.toString()); | 407 reportError("GAE POST JSON error: " + e.toString()); |
| 373 } | 408 } |
| 374 } | 409 } |
| 375 } | 410 } |
| 376 }); | 411 }); |
| 377 httpConnection.send(); | 412 httpConnection.send(); |
| 378 } | 413 } |
| 414 |
| 415 // Converts a Java candidate to a JSONObject. |
| 416 private JSONObject toJsonCandidate(final IceCandidate candidate) { |
| 417 JSONObject json = new JSONObject(); |
| 418 jsonPut(json, "label", candidate.sdpMLineIndex); |
| 419 jsonPut(json, "id", candidate.sdpMid); |
| 420 jsonPut(json, "candidate", candidate.sdp); |
| 421 return json; |
| 422 } |
| 423 |
| 424 // Converts a JSON candidate to a Java object. |
| 425 IceCandidate toJavaCandidate(JSONObject json) throws JSONException { |
| 426 return new IceCandidate(json.getString("id"), |
| 427 json.getInt("label"), |
| 428 json.getString("candidate")); |
| 429 } |
| 379 } | 430 } |
| OLD | NEW |