Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions webrtc/src/main/java/dev/onvoid/webrtc/client/Whep.java
Original file line number Diff line number Diff line change
Expand Up @@ -170,8 +170,15 @@ public CompletableFuture<Session> play(WebRtc rtc) {

PeerImpl peer = (PeerImpl) rtc.createPeer(options.build());

return peer.toPublic(HttpSession.negotiate(rtc, peer, endpoint, bearerToken, timeout)
.thenApply(resource -> new Session(rtc, peer, resource, bearerToken, timeout)));
try {
return peer.toPublic(HttpSession.negotiate(rtc, peer, endpoint, bearerToken, timeout)
.thenApply(resource -> new Session(rtc, peer, resource, bearerToken, timeout)));
}
catch (RuntimeException | Error e) {
// Until the session has it, no one else would close the peer.
peer.close();
throw e;
}
}
}
}
28 changes: 22 additions & 6 deletions webrtc/src/main/java/dev/onvoid/webrtc/client/Whip.java
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,9 @@ public Builder timeout(Duration timeout) {
* fails if the endpoint refuses the offer or the peer does not connect
* in time, with nothing left behind on the server.
*
* @throws IllegalStateException if no track was given.
* @throws IllegalStateException if no track was given.
* @throws IllegalArgumentException if a track was not created by the
* runtime.
*/
public CompletableFuture<Session> publish(WebRtc rtc) {
requireNonNull(rtc, "rtc");
Expand All @@ -156,6 +158,13 @@ public CompletableFuture<Session> publish(WebRtc rtc) {
throw new IllegalStateException("Give at least one track to publish");
}

// Before the peer exists, so that a wrong track leaves nothing behind.
for (LocalTrack track : tracks) {
if (!(track instanceof LocalTrackImpl) || ((LocalTrackImpl) track).rtc != rtc) {
throw new IllegalArgumentException("The track " + track + " was not created by the runtime");
}
}

PeerOptions.Builder options = PeerOptions.builder()
.name("whip-" + endpoint.getHost())
.negotiation(Negotiation.MANUAL);
Expand All @@ -166,12 +175,19 @@ public CompletableFuture<Session> publish(WebRtc rtc) {

PeerImpl peer = (PeerImpl) rtc.createPeer(options.build());

for (LocalTrack track : tracks) {
peer.addTrack(track);
}
try {
for (LocalTrack track : tracks) {
peer.addTrack(track);
}

return peer.toPublic(HttpSession.negotiate(rtc, peer, endpoint, bearerToken, timeout)
.thenApply(resource -> new Session(rtc, peer, resource, bearerToken, timeout)));
return peer.toPublic(HttpSession.negotiate(rtc, peer, endpoint, bearerToken, timeout)
.thenApply(resource -> new Session(rtc, peer, resource, bearerToken, timeout)));
}
catch (RuntimeException | Error e) {
// Until the session has it, no one else would close the peer.
peer.close();
throw e;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.function.UnaryOperator;
Expand Down Expand Up @@ -139,6 +140,48 @@ void refusedOfferLeavesNothing() throws Exception {
}
}

@Test
void foreignTrackLeavesNothing() throws Exception {
WebRtc other = clientRuntime(UnaryOperator.identity());

try (TestHttpEndpoint endpoint = receivingEndpoint()) {
Whip.Builder whip = Whip.to(endpoint.uri()).track(video).track(other.media().customVideo("other"));

assertThrows(IllegalArgumentException.class, () -> whip.publish(rtc));
assertTrue(rtc.peers().isEmpty(), () -> "Peers left: " + rtc.peers());
assertTrue(endpoint.requests.isEmpty());
}
finally {
other.close();
}
}

@Test
void failedStartClosesPeer() throws Exception {
// The session's deadline cannot be scheduled, after the peer was created.
ManualTimer timer = new ManualTimer();
WebRtc client = clientRuntime(builder -> builder.timer(timer));

try (TestHttpEndpoint endpoint = receivingEndpoint()) {
CustomVideo track = client.media().customVideo("video");
timer.shutdown();

assertThrows(RejectedExecutionException.class,
() -> Whip.to(endpoint.uri()).track(track).publish(client));
assertThrows(RejectedExecutionException.class, () -> Whep.from(endpoint.uri()).play(client));

for (Peer peer : client.peers()) {
PeerImpl impl = (PeerImpl) peer;
assertTrue(impl.isClosing(), () -> "Not closing: " + peer);
impl.closeInternal().get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
}
assertTrue(client.peers().isEmpty(), () -> "Peers left: " + client.peers());
}
finally {
client.close();
}
}

@Test
void lateAnswerDeleted() throws Exception {
// The session times out while the offer is out. The server created a
Expand Down
Loading