OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2016 The WebRTC Project Authors. All rights reserved. | 2 * Copyright 2016 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 |
(...skipping 17 matching lines...) Expand all Loading... |
28 /** | 28 /** |
29 * Implementation of AppRTCClient that uses direct TCP connection as the signali
ng channel. | 29 * Implementation of AppRTCClient that uses direct TCP connection as the signali
ng channel. |
30 * This eliminates the need for an external server. This class does not support
loopback | 30 * This eliminates the need for an external server. This class does not support
loopback |
31 * connections. | 31 * connections. |
32 */ | 32 */ |
33 public class DirectRTCClient implements AppRTCClient, TCPChannelClient.TCPChanne
lEvents { | 33 public class DirectRTCClient implements AppRTCClient, TCPChannelClient.TCPChanne
lEvents { |
34 private static final String TAG = "DirectRTCClient"; | 34 private static final String TAG = "DirectRTCClient"; |
35 private static final int DEFAULT_PORT = 8888; | 35 private static final int DEFAULT_PORT = 8888; |
36 | 36 |
37 // Regex pattern used for checking if room id looks like an IP. | 37 // Regex pattern used for checking if room id looks like an IP. |
38 static final Pattern IP_PATTERN = Pattern.compile( | 38 static final Pattern IP_PATTERN = Pattern.compile("(" |
39 "(" | 39 // IPv4 |
40 // IPv4 | 40 + "((\\d+\\.){3}\\d+)|" |
41 + "((\\d+\\.){3}\\d+)|" | 41 // IPv6 |
42 // IPv6 | 42 + "\\[((([0-9a-fA-F]{1,4}:)*[0-9a-fA-F]{1,4})?::" |
43 + "\\[((([0-9a-fA-F]{1,4}:)*[0-9a-fA-F]{1,4})?::" | 43 + "(([0-9a-fA-F]{1,4}:)*[0-9a-fA-F]{1,4})?)\\]|" |
44 + "(([0-9a-fA-F]{1,4}:)*[0-9a-fA-F]{1,4})?)\\]|" | 44 + "\\[(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4})\\]|" |
45 + "\\[(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4})\\]|" | 45 // IPv6 without [] |
46 // IPv6 without [] | 46 + "((([0-9a-fA-F]{1,4}:)*[0-9a-fA-F]{1,4})?::(([0-9a-fA-F]{1,4}:)*[0-9a-fA
-F]{1,4})?)|" |
47 + "((([0-9a-fA-F]{1,4}:)*[0-9a-fA-F]{1,4})?::(([0-9a-fA-F]{1,4}:)*[0-9a-
fA-F]{1,4})?)|" | 47 + "(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4})|" |
48 + "(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4})|" | 48 // Literals |
49 // Literals | 49 + "localhost" |
50 + "localhost" | |
51 + ")" | 50 + ")" |
52 // Optional port number | 51 // Optional port number |
53 + "(:(\\d+))?" | 52 + "(:(\\d+))?"); |
54 ); | |
55 | 53 |
56 private final ExecutorService executor; | 54 private final ExecutorService executor; |
57 private final SignalingEvents events; | 55 private final SignalingEvents events; |
58 private TCPChannelClient tcpClient; | 56 private TCPChannelClient tcpClient; |
59 private RoomConnectionParameters connectionParameters; | 57 private RoomConnectionParameters connectionParameters; |
60 | 58 |
61 private enum ConnectionState { | 59 private enum ConnectionState { NEW, CONNECTED, CLOSED, ERROR } |
62 NEW, CONNECTED, CLOSED, ERROR | |
63 }; | |
64 | 60 |
65 // All alterations of the room state should be done from inside the looper thr
ead. | 61 // All alterations of the room state should be done from inside the looper thr
ead. |
66 private ConnectionState roomState; | 62 private ConnectionState roomState; |
67 | 63 |
68 public DirectRTCClient(SignalingEvents events) { | 64 public DirectRTCClient(SignalingEvents events) { |
69 this.events = events; | 65 this.events = events; |
70 | 66 |
71 executor = Executors.newSingleThreadExecutor(); | 67 executor = Executors.newSingleThreadExecutor(); |
72 roomState = ConnectionState.NEW; | 68 roomState = ConnectionState.NEW; |
73 } | 69 } |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
202 } | 198 } |
203 | 199 |
204 /** Send removed Ice candidates to the other participant. */ | 200 /** Send removed Ice candidates to the other participant. */ |
205 @Override | 201 @Override |
206 public void sendLocalIceCandidateRemovals(final IceCandidate[] candidates) { | 202 public void sendLocalIceCandidateRemovals(final IceCandidate[] candidates) { |
207 executor.execute(new Runnable() { | 203 executor.execute(new Runnable() { |
208 @Override | 204 @Override |
209 public void run() { | 205 public void run() { |
210 JSONObject json = new JSONObject(); | 206 JSONObject json = new JSONObject(); |
211 jsonPut(json, "type", "remove-candidates"); | 207 jsonPut(json, "type", "remove-candidates"); |
212 JSONArray jsonArray = new JSONArray(); | 208 JSONArray jsonArray = new JSONArray(); |
213 for (final IceCandidate candidate : candidates) { | 209 for (final IceCandidate candidate : candidates) { |
214 jsonArray.put(toJsonCandidate(candidate)); | 210 jsonArray.put(toJsonCandidate(candidate)); |
215 } | 211 } |
216 jsonPut(json, "candidates", jsonArray); | 212 jsonPut(json, "candidates", jsonArray); |
217 | 213 |
218 if (roomState != ConnectionState.CONNECTED) { | 214 if (roomState != ConnectionState.CONNECTED) { |
219 reportError("Sending ICE candidate removals in non connected state."); | 215 reportError("Sending ICE candidate removals in non connected state."); |
220 return; | 216 return; |
221 } | 217 } |
222 sendMessage(json.toString()); | 218 sendMessage(json.toString()); |
(...skipping 14 matching lines...) Expand all Loading... |
237 | 233 |
238 SignalingParameters parameters = new SignalingParameters( | 234 SignalingParameters parameters = new SignalingParameters( |
239 // Ice servers are not needed for direct connections. | 235 // Ice servers are not needed for direct connections. |
240 new LinkedList<PeerConnection.IceServer>(), | 236 new LinkedList<PeerConnection.IceServer>(), |
241 isServer, // Server side acts as the initiator on direct connections. | 237 isServer, // Server side acts as the initiator on direct connections. |
242 null, // clientId | 238 null, // clientId |
243 null, // wssUrl | 239 null, // wssUrl |
244 null, // wwsPostUrl | 240 null, // wwsPostUrl |
245 null, // offerSdp | 241 null, // offerSdp |
246 null // iceCandidates | 242 null // iceCandidates |
247 ); | 243 ); |
248 events.onConnectedToRoom(parameters); | 244 events.onConnectedToRoom(parameters); |
249 } | 245 } |
250 } | 246 } |
251 | 247 |
252 @Override | 248 @Override |
253 public void onTCPMessage(String msg) { | 249 public void onTCPMessage(String msg) { |
254 try { | 250 try { |
255 JSONObject json = new JSONObject(msg); | 251 JSONObject json = new JSONObject(msg); |
256 String type = json.optString("type"); | 252 String type = json.optString("type"); |
257 if (type.equals("candidate")) { | 253 if (type.equals("candidate")) { |
258 events.onRemoteIceCandidate(toJavaCandidate(json)); | 254 events.onRemoteIceCandidate(toJavaCandidate(json)); |
259 } else if (type.equals("remove-candidates")) { | 255 } else if (type.equals("remove-candidates")) { |
260 JSONArray candidateArray = json.getJSONArray("candidates"); | 256 JSONArray candidateArray = json.getJSONArray("candidates"); |
261 IceCandidate[] candidates = new IceCandidate[candidateArray.length()]; | 257 IceCandidate[] candidates = new IceCandidate[candidateArray.length()]; |
262 for (int i = 0; i < candidateArray.length(); ++i) { | 258 for (int i = 0; i < candidateArray.length(); ++i) { |
263 candidates[i] = toJavaCandidate(candidateArray.getJSONObject(i)); | 259 candidates[i] = toJavaCandidate(candidateArray.getJSONObject(i)); |
264 } | 260 } |
265 events.onRemoteIceCandidatesRemoved(candidates); | 261 events.onRemoteIceCandidatesRemoved(candidates); |
266 } else if (type.equals("answer")) { | 262 } else if (type.equals("answer")) { |
267 SessionDescription sdp = new SessionDescription( | 263 SessionDescription sdp = new SessionDescription( |
268 SessionDescription.Type.fromCanonicalForm(type), | 264 SessionDescription.Type.fromCanonicalForm(type), json.getString("sdp
")); |
269 json.getString("sdp")); | |
270 events.onRemoteDescription(sdp); | 265 events.onRemoteDescription(sdp); |
271 } else if (type.equals("offer")) { | 266 } else if (type.equals("offer")) { |
272 SessionDescription sdp = new SessionDescription( | 267 SessionDescription sdp = new SessionDescription( |
273 SessionDescription.Type.fromCanonicalForm(type), | 268 SessionDescription.Type.fromCanonicalForm(type), json.getString("sdp
")); |
274 json.getString("sdp")); | |
275 | 269 |
276 SignalingParameters parameters = new SignalingParameters( | 270 SignalingParameters parameters = new SignalingParameters( |
277 // Ice servers are not needed for direct connections. | 271 // Ice servers are not needed for direct connections. |
278 new LinkedList<PeerConnection.IceServer>(), | 272 new LinkedList<PeerConnection.IceServer>(), |
279 false, // This code will only be run on the client side. So, we are
not the initiator. | 273 false, // This code will only be run on the client side. So, we are
not the initiator. |
280 null, // clientId | 274 null, // clientId |
281 null, // wssUrl | 275 null, // wssUrl |
282 null, // wssPostUrl | 276 null, // wssPostUrl |
283 sdp, // offerSdp | 277 sdp, // offerSdp |
284 null // iceCandidates | 278 null // iceCandidates |
285 ); | 279 ); |
286 roomState = ConnectionState.CONNECTED; | 280 roomState = ConnectionState.CONNECTED; |
287 events.onConnectedToRoom(parameters); | 281 events.onConnectedToRoom(parameters); |
288 } else { | 282 } else { |
289 reportError("Unexpected TCP message: " + msg); | 283 reportError("Unexpected TCP message: " + msg); |
290 } | 284 } |
291 } catch (JSONException e) { | 285 } catch (JSONException e) { |
292 reportError("TCP message JSON parsing error: " + e.toString()); | 286 reportError("TCP message JSON parsing error: " + e.toString()); |
293 } | 287 } |
294 } | 288 } |
295 | 289 |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
340 private static JSONObject toJsonCandidate(final IceCandidate candidate) { | 334 private static JSONObject toJsonCandidate(final IceCandidate candidate) { |
341 JSONObject json = new JSONObject(); | 335 JSONObject json = new JSONObject(); |
342 jsonPut(json, "label", candidate.sdpMLineIndex); | 336 jsonPut(json, "label", candidate.sdpMLineIndex); |
343 jsonPut(json, "id", candidate.sdpMid); | 337 jsonPut(json, "id", candidate.sdpMid); |
344 jsonPut(json, "candidate", candidate.sdp); | 338 jsonPut(json, "candidate", candidate.sdp); |
345 return json; | 339 return json; |
346 } | 340 } |
347 | 341 |
348 // Converts a JSON candidate to a Java object. | 342 // Converts a JSON candidate to a Java object. |
349 private static IceCandidate toJavaCandidate(JSONObject json) throws JSONExcept
ion { | 343 private static IceCandidate toJavaCandidate(JSONObject json) throws JSONExcept
ion { |
350 return new IceCandidate(json.getString("id"), | 344 return new IceCandidate( |
351 json.getInt("label"), | 345 json.getString("id"), json.getInt("label"), json.getString("candidate"))
; |
352 json.getString("candidate")); | |
353 } | 346 } |
354 } | 347 } |
OLD | NEW |