use implicit descriptions for WebRTC
using the parameter-free form of setLocalDescription() solves some potential race conditions that can occur - especially once we introduce restartIce()
This commit is contained in:
parent
b5786787f0
commit
fda45a7c86
|
@ -537,9 +537,10 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
|
||||||
try {
|
try {
|
||||||
this.webRTCWrapper.setRemoteDescription(sdp).get();
|
this.webRTCWrapper.setRemoteDescription(sdp).get();
|
||||||
addIceCandidatesFromBlackLog();
|
addIceCandidatesFromBlackLog();
|
||||||
org.webrtc.SessionDescription webRTCSessionDescription = this.webRTCWrapper.createAnswer().get();
|
org.webrtc.SessionDescription webRTCSessionDescription = this.webRTCWrapper.setLocalDescription().get();
|
||||||
prepareSessionAccept(webRTCSessionDescription);
|
prepareSessionAccept(webRTCSessionDescription);
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
|
//TODO sending the error text is worthwhile as well. Especially for FailureToSet exceptions
|
||||||
failureToAcceptSession(e);
|
failureToAcceptSession(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -569,7 +570,7 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
|
||||||
new FutureCallback<RtpContentMap>() {
|
new FutureCallback<RtpContentMap>() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(final RtpContentMap outgoingContentMap) {
|
public void onSuccess(final RtpContentMap outgoingContentMap) {
|
||||||
sendSessionAccept(outgoingContentMap, webRTCSessionDescription);
|
sendSessionAccept(outgoingContentMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -581,7 +582,7 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendSessionAccept(final RtpContentMap rtpContentMap, final org.webrtc.SessionDescription webRTCSessionDescription) {
|
private void sendSessionAccept(final RtpContentMap rtpContentMap) {
|
||||||
if (isTerminated()) {
|
if (isTerminated()) {
|
||||||
Log.w(Config.LOGTAG, id.account.getJid().asBareJid() + ": preparing session accept was too slow. already terminated. nothing to do.");
|
Log.w(Config.LOGTAG, id.account.getJid().asBareJid() + ": preparing session accept was too slow. already terminated. nothing to do.");
|
||||||
return;
|
return;
|
||||||
|
@ -589,11 +590,6 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
|
||||||
transitionOrThrow(State.SESSION_ACCEPTED);
|
transitionOrThrow(State.SESSION_ACCEPTED);
|
||||||
final JinglePacket sessionAccept = rtpContentMap.toJinglePacket(JinglePacket.Action.SESSION_ACCEPT, id.sessionId);
|
final JinglePacket sessionAccept = rtpContentMap.toJinglePacket(JinglePacket.Action.SESSION_ACCEPT, id.sessionId);
|
||||||
send(sessionAccept);
|
send(sessionAccept);
|
||||||
try {
|
|
||||||
webRTCWrapper.setLocalDescription(webRTCSessionDescription).get();
|
|
||||||
} catch (Exception e) {
|
|
||||||
failureToAcceptSession(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private ListenableFuture<RtpContentMap> prepareOutgoingContentMap(final RtpContentMap rtpContentMap) {
|
private ListenableFuture<RtpContentMap> prepareOutgoingContentMap(final RtpContentMap rtpContentMap) {
|
||||||
|
@ -841,9 +837,10 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
org.webrtc.SessionDescription webRTCSessionDescription = this.webRTCWrapper.createOffer().get();
|
org.webrtc.SessionDescription webRTCSessionDescription = this.webRTCWrapper.setLocalDescription().get();
|
||||||
prepareSessionInitiate(webRTCSessionDescription, targetState);
|
prepareSessionInitiate(webRTCSessionDescription, targetState);
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
|
//TODO sending the error text is worthwhile as well. Especially for FailureToSet exceptions
|
||||||
failureToInitiateSession(e, targetState);
|
failureToInitiateSession(e, targetState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -877,7 +874,7 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
|
||||||
Futures.addCallback(outgoingContentMapFuture, new FutureCallback<RtpContentMap>() {
|
Futures.addCallback(outgoingContentMapFuture, new FutureCallback<RtpContentMap>() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(final RtpContentMap outgoingContentMap) {
|
public void onSuccess(final RtpContentMap outgoingContentMap) {
|
||||||
sendSessionInitiate(outgoingContentMap, webRTCSessionDescription, targetState);
|
sendSessionInitiate(outgoingContentMap, targetState);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -887,7 +884,7 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
|
||||||
}, MoreExecutors.directExecutor());
|
}, MoreExecutors.directExecutor());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendSessionInitiate(final RtpContentMap rtpContentMap, final org.webrtc.SessionDescription webRTCSessionDescription, final State targetState) {
|
private void sendSessionInitiate(final RtpContentMap rtpContentMap, final State targetState) {
|
||||||
if (isTerminated()) {
|
if (isTerminated()) {
|
||||||
Log.w(Config.LOGTAG, id.account.getJid().asBareJid() + ": preparing session was too slow. already terminated. nothing to do.");
|
Log.w(Config.LOGTAG, id.account.getJid().asBareJid() + ": preparing session was too slow. already terminated. nothing to do.");
|
||||||
return;
|
return;
|
||||||
|
@ -895,11 +892,6 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
|
||||||
this.transitionOrThrow(targetState);
|
this.transitionOrThrow(targetState);
|
||||||
final JinglePacket sessionInitiate = rtpContentMap.toJinglePacket(JinglePacket.Action.SESSION_INITIATE, id.sessionId);
|
final JinglePacket sessionInitiate = rtpContentMap.toJinglePacket(JinglePacket.Action.SESSION_INITIATE, id.sessionId);
|
||||||
send(sessionInitiate);
|
send(sessionInitiate);
|
||||||
try {
|
|
||||||
this.webRTCWrapper.setLocalDescription(webRTCSessionDescription).get();
|
|
||||||
} catch (Exception e) {
|
|
||||||
failureToInitiateSession(e, targetState);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private ListenableFuture<RtpContentMap> encryptSessionInitiate(final RtpContentMap rtpContentMap) {
|
private ListenableFuture<RtpContentMap> encryptSessionInitiate(final RtpContentMap rtpContentMap) {
|
||||||
|
|
|
@ -403,70 +403,36 @@ public class WebRTCWrapper {
|
||||||
videoTrack.setEnabled(enabled);
|
videoTrack.setEnabled(enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
ListenableFuture<SessionDescription> createOffer() {
|
ListenableFuture<SessionDescription> setLocalDescription() {
|
||||||
return Futures.transformAsync(getPeerConnectionFuture(), peerConnection -> {
|
return Futures.transformAsync(getPeerConnectionFuture(), peerConnection -> {
|
||||||
final SettableFuture<SessionDescription> future = SettableFuture.create();
|
final SettableFuture<SessionDescription> future = SettableFuture.create();
|
||||||
peerConnection.createOffer(new CreateSdpObserver() {
|
|
||||||
@Override
|
|
||||||
public void onCreateSuccess(SessionDescription sessionDescription) {
|
|
||||||
future.set(sessionDescription);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreateFailure(String s) {
|
|
||||||
future.setException(new IllegalStateException("Unable to create offer: " + s));
|
|
||||||
}
|
|
||||||
}, new MediaConstraints());
|
|
||||||
return future;
|
|
||||||
}, MoreExecutors.directExecutor());
|
|
||||||
}
|
|
||||||
|
|
||||||
ListenableFuture<SessionDescription> createAnswer() {
|
|
||||||
return Futures.transformAsync(getPeerConnectionFuture(), peerConnection -> {
|
|
||||||
final SettableFuture<SessionDescription> future = SettableFuture.create();
|
|
||||||
peerConnection.createAnswer(new CreateSdpObserver() {
|
|
||||||
@Override
|
|
||||||
public void onCreateSuccess(SessionDescription sessionDescription) {
|
|
||||||
future.set(sessionDescription);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreateFailure(String s) {
|
|
||||||
future.setException(new IllegalStateException("Unable to create answer: " + s));
|
|
||||||
}
|
|
||||||
}, new MediaConstraints());
|
|
||||||
return future;
|
|
||||||
}, MoreExecutors.directExecutor());
|
|
||||||
}
|
|
||||||
|
|
||||||
ListenableFuture<Void> setLocalDescription(final SessionDescription sessionDescription) {
|
|
||||||
Log.d(EXTENDED_LOGGING_TAG, "setting local description:");
|
|
||||||
for (final String line : sessionDescription.description.split(eu.siacs.conversations.xmpp.jingle.SessionDescription.LINE_DIVIDER)) {
|
|
||||||
Log.d(EXTENDED_LOGGING_TAG, line);
|
|
||||||
}
|
|
||||||
return Futures.transformAsync(getPeerConnectionFuture(), peerConnection -> {
|
|
||||||
final SettableFuture<Void> future = SettableFuture.create();
|
|
||||||
peerConnection.setLocalDescription(new SetSdpObserver() {
|
peerConnection.setLocalDescription(new SetSdpObserver() {
|
||||||
@Override
|
@Override
|
||||||
public void onSetSuccess() {
|
public void onSetSuccess() {
|
||||||
future.set(null);
|
final SessionDescription description = peerConnection.getLocalDescription();
|
||||||
|
Log.d(EXTENDED_LOGGING_TAG, "set local description:");
|
||||||
|
logDescription(description);
|
||||||
|
future.set(description);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSetFailure(final String s) {
|
public void onSetFailure(final String message) {
|
||||||
future.setException(new IllegalArgumentException("unable to set local session description: " + s));
|
future.setException(new FailureToSetDescriptionException(message));
|
||||||
|
|
||||||
}
|
}
|
||||||
}, sessionDescription);
|
});
|
||||||
return future;
|
return future;
|
||||||
}, MoreExecutors.directExecutor());
|
}, MoreExecutors.directExecutor());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void logDescription(final SessionDescription sessionDescription) {
|
||||||
|
for (final String line : sessionDescription.description.split(eu.siacs.conversations.xmpp.jingle.SessionDescription.LINE_DIVIDER)) {
|
||||||
|
Log.d(EXTENDED_LOGGING_TAG, line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ListenableFuture<Void> setRemoteDescription(final SessionDescription sessionDescription) {
|
ListenableFuture<Void> setRemoteDescription(final SessionDescription sessionDescription) {
|
||||||
Log.d(EXTENDED_LOGGING_TAG, "setting remote description:");
|
Log.d(EXTENDED_LOGGING_TAG, "setting remote description:");
|
||||||
for (final String line : sessionDescription.description.split(eu.siacs.conversations.xmpp.jingle.SessionDescription.LINE_DIVIDER)) {
|
logDescription(sessionDescription);
|
||||||
Log.d(EXTENDED_LOGGING_TAG, line);
|
|
||||||
}
|
|
||||||
return Futures.transformAsync(getPeerConnectionFuture(), peerConnection -> {
|
return Futures.transformAsync(getPeerConnectionFuture(), peerConnection -> {
|
||||||
final SettableFuture<Void> future = SettableFuture.create();
|
final SettableFuture<Void> future = SettableFuture.create();
|
||||||
peerConnection.setRemoteDescription(new SetSdpObserver() {
|
peerConnection.setRemoteDescription(new SetSdpObserver() {
|
||||||
|
@ -476,9 +442,8 @@ public class WebRTCWrapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSetFailure(String s) {
|
public void onSetFailure(final String message) {
|
||||||
future.setException(new IllegalArgumentException("unable to set remote session description: " + s));
|
future.setException(new FailureToSetDescriptionException(message));
|
||||||
|
|
||||||
}
|
}
|
||||||
}, sessionDescription);
|
}, sessionDescription);
|
||||||
return future;
|
return future;
|
||||||
|
@ -619,6 +584,12 @@ public class WebRTCWrapper {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class FailureToSetDescriptionException extends IllegalArgumentException {
|
||||||
|
public FailureToSetDescriptionException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static class CapturerChoice {
|
private static class CapturerChoice {
|
||||||
private final CameraVideoCapturer cameraVideoCapturer;
|
private final CameraVideoCapturer cameraVideoCapturer;
|
||||||
private final CameraEnumerationAndroid.CaptureFormat captureFormat;
|
private final CameraEnumerationAndroid.CaptureFormat captureFormat;
|
||||||
|
|
Loading…
Reference in New Issue