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 |