Switch websocket-resources from ListenableFuture to CompletableFuture
This commit is contained in:
parent
7e4b572699
commit
0c81556b90
|
@ -1,8 +1,5 @@
|
||||||
package org.whispersystems.textsecuregcm.websocket;
|
package org.whispersystems.textsecuregcm.websocket;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.FutureCallback;
|
|
||||||
import com.google.common.util.concurrent.Futures;
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
|
||||||
import com.google.protobuf.InvalidProtocolBufferException;
|
import com.google.protobuf.InvalidProtocolBufferException;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
@ -10,7 +7,6 @@ import org.whispersystems.dispatch.DispatchChannel;
|
||||||
import org.whispersystems.textsecuregcm.entities.MessageProtos.ProvisioningUuid;
|
import org.whispersystems.textsecuregcm.entities.MessageProtos.ProvisioningUuid;
|
||||||
import org.whispersystems.textsecuregcm.storage.PubSubProtos.PubSubMessage;
|
import org.whispersystems.textsecuregcm.storage.PubSubProtos.PubSubMessage;
|
||||||
import org.whispersystems.websocket.WebSocketClient;
|
import org.whispersystems.websocket.WebSocketClient;
|
||||||
import org.whispersystems.websocket.messages.WebSocketResponseMessage;
|
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
|
@ -32,18 +28,11 @@ public class ProvisioningConnection implements DispatchChannel {
|
||||||
if (outgoingMessage.getType() == PubSubMessage.Type.DELIVER) {
|
if (outgoingMessage.getType() == PubSubMessage.Type.DELIVER) {
|
||||||
Optional<byte[]> body = Optional.of(outgoingMessage.getContent().toByteArray());
|
Optional<byte[]> body = Optional.of(outgoingMessage.getContent().toByteArray());
|
||||||
|
|
||||||
ListenableFuture<WebSocketResponseMessage> response = client.sendRequest("PUT", "/v1/message", null, body);
|
client.sendRequest("PUT", "/v1/message", null, body)
|
||||||
|
.thenAccept(response -> client.close(1001, "All you get."))
|
||||||
Futures.addCallback(response, new FutureCallback<WebSocketResponseMessage>() {
|
.exceptionally(throwable -> {
|
||||||
@Override
|
|
||||||
public void onSuccess(WebSocketResponseMessage webSocketResponseMessage) {
|
|
||||||
client.close(1001, "All you get.");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFailure(Throwable throwable) {
|
|
||||||
client.close(1001, "That's all!");
|
client.close(1001, "That's all!");
|
||||||
}
|
return null;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (InvalidProtocolBufferException e) {
|
} catch (InvalidProtocolBufferException e) {
|
||||||
|
|
|
@ -3,9 +3,6 @@ package org.whispersystems.textsecuregcm.websocket;
|
||||||
import com.codahale.metrics.Histogram;
|
import com.codahale.metrics.Histogram;
|
||||||
import com.codahale.metrics.MetricRegistry;
|
import com.codahale.metrics.MetricRegistry;
|
||||||
import com.codahale.metrics.SharedMetricRegistries;
|
import com.codahale.metrics.SharedMetricRegistries;
|
||||||
import com.google.common.util.concurrent.FutureCallback;
|
|
||||||
import com.google.common.util.concurrent.Futures;
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
|
||||||
import com.google.protobuf.ByteString;
|
import com.google.protobuf.ByteString;
|
||||||
import com.google.protobuf.InvalidProtocolBufferException;
|
import com.google.protobuf.InvalidProtocolBufferException;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -28,8 +25,6 @@ import org.whispersystems.textsecuregcm.util.Util;
|
||||||
import org.whispersystems.websocket.WebSocketClient;
|
import org.whispersystems.websocket.WebSocketClient;
|
||||||
import org.whispersystems.websocket.messages.WebSocketResponseMessage;
|
import org.whispersystems.websocket.messages.WebSocketResponseMessage;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
import javax.ws.rs.WebApplicationException;
|
import javax.ws.rs.WebApplicationException;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
@ -123,11 +118,8 @@ public class WebSocketConnection implements DispatchChannel {
|
||||||
body = Optional.ofNullable(new EncryptedOutgoingMessage(message, device.getSignalingKey()).toByteArray());
|
body = Optional.ofNullable(new EncryptedOutgoingMessage(message, device.getSignalingKey()).toByteArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
ListenableFuture<WebSocketResponseMessage> response = client.sendRequest("PUT", "/api/v1/message", Collections.singletonList(header), body);
|
client.sendRequest("PUT", "/api/v1/message", Collections.singletonList(header), body)
|
||||||
|
.thenAccept(response -> {
|
||||||
Futures.addCallback(response, new FutureCallback<WebSocketResponseMessage>() {
|
|
||||||
@Override
|
|
||||||
public void onSuccess(@Nullable WebSocketResponseMessage response) {
|
|
||||||
boolean isReceipt = message.getType() == Envelope.Type.RECEIPT;
|
boolean isReceipt = message.getType() == Envelope.Type.RECEIPT;
|
||||||
|
|
||||||
if (isSuccessResponse(response) && !isReceipt) {
|
if (isSuccessResponse(response) && !isReceipt) {
|
||||||
|
@ -141,16 +133,10 @@ public class WebSocketConnection implements DispatchChannel {
|
||||||
} else if (!isSuccessResponse(response) && !storedMessageInfo.isPresent()) {
|
} else if (!isSuccessResponse(response) && !storedMessageInfo.isPresent()) {
|
||||||
requeueMessage(message);
|
requeueMessage(message);
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
|
.exceptionally(throwable -> {
|
||||||
@Override
|
|
||||||
public void onFailure(@Nonnull Throwable throwable) {
|
|
||||||
if (!storedMessageInfo.isPresent()) requeueMessage(message);
|
if (!storedMessageInfo.isPresent()) requeueMessage(message);
|
||||||
}
|
return null;
|
||||||
|
|
||||||
private boolean isSuccessResponse(WebSocketResponseMessage response) {
|
|
||||||
return response != null && response.getStatus() >= 200 && response.getStatus() < 300;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
} catch (CryptoEncodingException e) {
|
} catch (CryptoEncodingException e) {
|
||||||
logger.warn("Bad signaling key", e);
|
logger.warn("Bad signaling key", e);
|
||||||
|
@ -179,6 +165,10 @@ public class WebSocketConnection implements DispatchChannel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isSuccessResponse(WebSocketResponseMessage response) {
|
||||||
|
return response != null && response.getStatus() >= 200 && response.getStatus() < 300;
|
||||||
|
}
|
||||||
|
|
||||||
private void processStoredMessages() {
|
private void processStoredMessages() {
|
||||||
OutgoingMessageEntityList messages = messagesManager.getMessagesForDevice(account.getNumber(), device.getId());
|
OutgoingMessageEntityList messages = messagesManager.getMessagesForDevice(account.getNumber(), device.getId());
|
||||||
Iterator<OutgoingMessageEntity> iterator = messages.getMessages().iterator();
|
Iterator<OutgoingMessageEntity> iterator = messages.getMessages().iterator();
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package org.whispersystems.textsecuregcm.tests.websocket;
|
package org.whispersystems.textsecuregcm.tests.websocket;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.SettableFuture;
|
|
||||||
import com.google.protobuf.ByteString;
|
import com.google.protobuf.ByteString;
|
||||||
import org.eclipse.jetty.websocket.api.UpgradeRequest;
|
import org.eclipse.jetty.websocket.api.UpgradeRequest;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
@ -39,6 +38,7 @@ import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
import io.dropwizard.auth.basic.BasicCredentials;
|
import io.dropwizard.auth.basic.BasicCredentials;
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
@ -134,14 +134,14 @@ public class WebSocketConnectionTest {
|
||||||
when(storedMessages.getMessagesForDevice(account.getNumber(), device.getId()))
|
when(storedMessages.getMessagesForDevice(account.getNumber(), device.getId()))
|
||||||
.thenReturn(outgoingMessagesList);
|
.thenReturn(outgoingMessagesList);
|
||||||
|
|
||||||
final List<SettableFuture<WebSocketResponseMessage>> futures = new LinkedList<>();
|
final List<CompletableFuture<WebSocketResponseMessage>> futures = new LinkedList<>();
|
||||||
final WebSocketClient client = mock(WebSocketClient.class);
|
final WebSocketClient client = mock(WebSocketClient.class);
|
||||||
|
|
||||||
when(client.sendRequest(eq("PUT"), eq("/api/v1/message"), ArgumentMatchers.nullable(List.class), ArgumentMatchers.<Optional<byte[]>>any()))
|
when(client.sendRequest(eq("PUT"), eq("/api/v1/message"), ArgumentMatchers.nullable(List.class), ArgumentMatchers.<Optional<byte[]>>any()))
|
||||||
.thenAnswer(new Answer<SettableFuture<WebSocketResponseMessage>>() {
|
.thenAnswer(new Answer<CompletableFuture<WebSocketResponseMessage>>() {
|
||||||
@Override
|
@Override
|
||||||
public SettableFuture<WebSocketResponseMessage> answer(InvocationOnMock invocationOnMock) throws Throwable {
|
public CompletableFuture<WebSocketResponseMessage> answer(InvocationOnMock invocationOnMock) throws Throwable {
|
||||||
SettableFuture<WebSocketResponseMessage> future = SettableFuture.create();
|
CompletableFuture<WebSocketResponseMessage> future = new CompletableFuture<>();
|
||||||
futures.add(future);
|
futures.add(future);
|
||||||
return future;
|
return future;
|
||||||
}
|
}
|
||||||
|
@ -158,10 +158,10 @@ public class WebSocketConnectionTest {
|
||||||
|
|
||||||
WebSocketResponseMessage response = mock(WebSocketResponseMessage.class);
|
WebSocketResponseMessage response = mock(WebSocketResponseMessage.class);
|
||||||
when(response.getStatus()).thenReturn(200);
|
when(response.getStatus()).thenReturn(200);
|
||||||
futures.get(1).set(response);
|
futures.get(1).complete(response);
|
||||||
|
|
||||||
futures.get(0).setException(new IOException());
|
futures.get(0).completeExceptionally(new IOException());
|
||||||
futures.get(2).setException(new IOException());
|
futures.get(2).completeExceptionally(new IOException());
|
||||||
|
|
||||||
verify(storedMessages, times(1)).delete(eq(account.getNumber()), eq(2L), eq(2L), eq(false));
|
verify(storedMessages, times(1)).delete(eq(account.getNumber()), eq(2L), eq(2L), eq(false));
|
||||||
verify(receiptSender, times(1)).sendReceipt(eq(account), eq("sender1"), eq(2222L));
|
verify(receiptSender, times(1)).sendReceipt(eq(account), eq("sender1"), eq(2222L));
|
||||||
|
@ -217,14 +217,14 @@ public class WebSocketConnectionTest {
|
||||||
when(storedMessages.getMessagesForDevice(account.getNumber(), device.getId()))
|
when(storedMessages.getMessagesForDevice(account.getNumber(), device.getId()))
|
||||||
.thenReturn(pendingMessagesList);
|
.thenReturn(pendingMessagesList);
|
||||||
|
|
||||||
final List<SettableFuture<WebSocketResponseMessage>> futures = new LinkedList<>();
|
final List<CompletableFuture<WebSocketResponseMessage>> futures = new LinkedList<>();
|
||||||
final WebSocketClient client = mock(WebSocketClient.class);
|
final WebSocketClient client = mock(WebSocketClient.class);
|
||||||
|
|
||||||
when(client.sendRequest(eq("PUT"), eq("/api/v1/message"), ArgumentMatchers.nullable(List.class), ArgumentMatchers.<Optional<byte[]>>any()))
|
when(client.sendRequest(eq("PUT"), eq("/api/v1/message"), ArgumentMatchers.nullable(List.class), ArgumentMatchers.<Optional<byte[]>>any()))
|
||||||
.thenAnswer(new Answer<SettableFuture<WebSocketResponseMessage>>() {
|
.thenAnswer(new Answer<CompletableFuture<WebSocketResponseMessage>>() {
|
||||||
@Override
|
@Override
|
||||||
public SettableFuture<WebSocketResponseMessage> answer(InvocationOnMock invocationOnMock) throws Throwable {
|
public CompletableFuture<WebSocketResponseMessage> answer(InvocationOnMock invocationOnMock) throws Throwable {
|
||||||
SettableFuture<WebSocketResponseMessage> future = SettableFuture.create();
|
CompletableFuture<WebSocketResponseMessage> future = new CompletableFuture<>();
|
||||||
futures.add(future);
|
futures.add(future);
|
||||||
return future;
|
return future;
|
||||||
}
|
}
|
||||||
|
@ -251,8 +251,8 @@ public class WebSocketConnectionTest {
|
||||||
|
|
||||||
WebSocketResponseMessage response = mock(WebSocketResponseMessage.class);
|
WebSocketResponseMessage response = mock(WebSocketResponseMessage.class);
|
||||||
when(response.getStatus()).thenReturn(200);
|
when(response.getStatus()).thenReturn(200);
|
||||||
futures.get(1).set(response);
|
futures.get(1).complete(response);
|
||||||
futures.get(0).setException(new IOException());
|
futures.get(0).completeExceptionally(new IOException());
|
||||||
|
|
||||||
verify(receiptSender, times(1)).sendReceipt(eq(account), eq("sender2"), eq(secondMessage.getTimestamp()));
|
verify(receiptSender, times(1)).sendReceipt(eq(account), eq("sender2"), eq(secondMessage.getTimestamp()));
|
||||||
verify(websocketSender, times(1)).queueMessage(eq(account), eq(device), any(Envelope.class));
|
verify(websocketSender, times(1)).queueMessage(eq(account), eq(device), any(Envelope.class));
|
||||||
|
@ -322,14 +322,14 @@ public class WebSocketConnectionTest {
|
||||||
when(storedMessages.getMessagesForDevice(account.getNumber(), device.getId()))
|
when(storedMessages.getMessagesForDevice(account.getNumber(), device.getId()))
|
||||||
.thenReturn(pendingMessagesList);
|
.thenReturn(pendingMessagesList);
|
||||||
|
|
||||||
final List<SettableFuture<WebSocketResponseMessage>> futures = new LinkedList<>();
|
final List<CompletableFuture<WebSocketResponseMessage>> futures = new LinkedList<>();
|
||||||
final WebSocketClient client = mock(WebSocketClient.class);
|
final WebSocketClient client = mock(WebSocketClient.class);
|
||||||
|
|
||||||
when(client.sendRequest(eq("PUT"), eq("/api/v1/message"), ArgumentMatchers.nullable(List.class), ArgumentMatchers.<Optional<byte[]>>any()))
|
when(client.sendRequest(eq("PUT"), eq("/api/v1/message"), ArgumentMatchers.nullable(List.class), ArgumentMatchers.<Optional<byte[]>>any()))
|
||||||
.thenAnswer(new Answer<SettableFuture<WebSocketResponseMessage>>() {
|
.thenAnswer(new Answer<CompletableFuture<WebSocketResponseMessage>>() {
|
||||||
@Override
|
@Override
|
||||||
public SettableFuture<WebSocketResponseMessage> answer(InvocationOnMock invocationOnMock) throws Throwable {
|
public CompletableFuture<WebSocketResponseMessage> answer(InvocationOnMock invocationOnMock) throws Throwable {
|
||||||
SettableFuture<WebSocketResponseMessage> future = SettableFuture.create();
|
CompletableFuture<WebSocketResponseMessage> future = new CompletableFuture<>();
|
||||||
futures.add(future);
|
futures.add(future);
|
||||||
return future;
|
return future;
|
||||||
}
|
}
|
||||||
|
@ -347,8 +347,8 @@ public class WebSocketConnectionTest {
|
||||||
|
|
||||||
WebSocketResponseMessage response = mock(WebSocketResponseMessage.class);
|
WebSocketResponseMessage response = mock(WebSocketResponseMessage.class);
|
||||||
when(response.getStatus()).thenReturn(200);
|
when(response.getStatus()).thenReturn(200);
|
||||||
futures.get(1).set(response);
|
futures.get(1).complete(response);
|
||||||
futures.get(0).setException(new IOException());
|
futures.get(0).completeExceptionally(new IOException());
|
||||||
|
|
||||||
verify(receiptSender, times(1)).sendReceipt(eq(account), eq("sender2"), eq(secondMessage.getTimestamp()));
|
verify(receiptSender, times(1)).sendReceipt(eq(account), eq("sender2"), eq(secondMessage.getTimestamp()));
|
||||||
verifyNoMoreInteractions(websocketSender);
|
verifyNoMoreInteractions(websocketSender);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/**
|
/*
|
||||||
* Copyright (C) 2014 Open WhisperSystems
|
* Copyright (C) 2014 Open WhisperSystems
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -16,8 +16,6 @@
|
||||||
*/
|
*/
|
||||||
package org.whispersystems.websocket;
|
package org.whispersystems.websocket;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
|
||||||
import com.google.common.util.concurrent.SettableFuture;
|
|
||||||
import org.eclipse.jetty.websocket.api.RemoteEndpoint;
|
import org.eclipse.jetty.websocket.api.RemoteEndpoint;
|
||||||
import org.eclipse.jetty.websocket.api.Session;
|
import org.eclipse.jetty.websocket.api.Session;
|
||||||
import org.eclipse.jetty.websocket.api.WebSocketException;
|
import org.eclipse.jetty.websocket.api.WebSocketException;
|
||||||
|
@ -34,6 +32,7 @@ import java.security.SecureRandom;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
|
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
|
||||||
public class WebSocketClient {
|
public class WebSocketClient {
|
||||||
|
@ -43,11 +42,11 @@ public class WebSocketClient {
|
||||||
private final Session session;
|
private final Session session;
|
||||||
private final RemoteEndpoint remoteEndpoint;
|
private final RemoteEndpoint remoteEndpoint;
|
||||||
private final WebSocketMessageFactory messageFactory;
|
private final WebSocketMessageFactory messageFactory;
|
||||||
private final Map<Long, SettableFuture<WebSocketResponseMessage>> pendingRequestMapper;
|
private final Map<Long, CompletableFuture<WebSocketResponseMessage>> pendingRequestMapper;
|
||||||
|
|
||||||
public WebSocketClient(Session session, RemoteEndpoint remoteEndpoint,
|
public WebSocketClient(Session session, RemoteEndpoint remoteEndpoint,
|
||||||
WebSocketMessageFactory messageFactory,
|
WebSocketMessageFactory messageFactory,
|
||||||
Map<Long, SettableFuture<WebSocketResponseMessage>> pendingRequestMapper)
|
Map<Long, CompletableFuture<WebSocketResponseMessage>> pendingRequestMapper)
|
||||||
{
|
{
|
||||||
this.session = session;
|
this.session = session;
|
||||||
this.remoteEndpoint = remoteEndpoint;
|
this.remoteEndpoint = remoteEndpoint;
|
||||||
|
@ -55,12 +54,12 @@ public class WebSocketClient {
|
||||||
this.pendingRequestMapper = pendingRequestMapper;
|
this.pendingRequestMapper = pendingRequestMapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ListenableFuture<WebSocketResponseMessage> sendRequest(String verb, String path,
|
public CompletableFuture<WebSocketResponseMessage> sendRequest(String verb, String path,
|
||||||
List<String> headers,
|
List<String> headers,
|
||||||
Optional<byte[]> body)
|
Optional<byte[]> body)
|
||||||
{
|
{
|
||||||
final long requestId = generateRequestId();
|
final long requestId = generateRequestId();
|
||||||
final SettableFuture<WebSocketResponseMessage> future = SettableFuture.create();
|
final CompletableFuture<WebSocketResponseMessage> future = new CompletableFuture<>();
|
||||||
|
|
||||||
pendingRequestMapper.put(requestId, future);
|
pendingRequestMapper.put(requestId, future);
|
||||||
|
|
||||||
|
@ -72,7 +71,7 @@ public class WebSocketClient {
|
||||||
public void writeFailed(Throwable x) {
|
public void writeFailed(Throwable x) {
|
||||||
logger.debug("Write failed", x);
|
logger.debug("Write failed", x);
|
||||||
pendingRequestMapper.remove(requestId);
|
pendingRequestMapper.remove(requestId);
|
||||||
future.setException(x);
|
future.completeExceptionally(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -81,7 +80,7 @@ public class WebSocketClient {
|
||||||
} catch (WebSocketException e) {
|
} catch (WebSocketException e) {
|
||||||
logger.debug("Write", e);
|
logger.debug("Write", e);
|
||||||
pendingRequestMapper.remove(requestId);
|
pendingRequestMapper.remove(requestId);
|
||||||
future.setException(e);
|
future.completeExceptionally(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
return future;
|
return future;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/**
|
/*
|
||||||
* Copyright (C) 2014 Open WhisperSystems
|
* Copyright (C) 2014 Open WhisperSystems
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -17,7 +17,6 @@
|
||||||
package org.whispersystems.websocket;
|
package org.whispersystems.websocket;
|
||||||
|
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import com.google.common.util.concurrent.SettableFuture;
|
|
||||||
import org.eclipse.jetty.server.RequestLog;
|
import org.eclipse.jetty.server.RequestLog;
|
||||||
import org.eclipse.jetty.websocket.api.RemoteEndpoint;
|
import org.eclipse.jetty.websocket.api.RemoteEndpoint;
|
||||||
import org.eclipse.jetty.websocket.api.Session;
|
import org.eclipse.jetty.websocket.api.Session;
|
||||||
|
@ -48,6 +47,7 @@ import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ public class WebSocketResourceProvider implements WebSocketListener {
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(WebSocketResourceProvider.class);
|
private static final Logger logger = LoggerFactory.getLogger(WebSocketResourceProvider.class);
|
||||||
|
|
||||||
private final Map<Long, SettableFuture<WebSocketResponseMessage>> requestMap = new ConcurrentHashMap<>();
|
private final Map<Long, CompletableFuture<WebSocketResponseMessage>> requestMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
private final Object authenticated;
|
private final Object authenticated;
|
||||||
private final WebSocketMessageFactory messageFactory;
|
private final WebSocketMessageFactory messageFactory;
|
||||||
|
@ -131,10 +131,10 @@ public class WebSocketResourceProvider implements WebSocketListener {
|
||||||
context.notifyClosed(statusCode, reason);
|
context.notifyClosed(statusCode, reason);
|
||||||
|
|
||||||
for (long requestId : requestMap.keySet()) {
|
for (long requestId : requestMap.keySet()) {
|
||||||
SettableFuture outstandingRequest = requestMap.remove(requestId);
|
CompletableFuture outstandingRequest = requestMap.remove(requestId);
|
||||||
|
|
||||||
if (outstandingRequest != null) {
|
if (outstandingRequest != null) {
|
||||||
outstandingRequest.setException(new IOException("Connection closed!"));
|
outstandingRequest.completeExceptionally(new IOException("Connection closed!"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -160,10 +160,10 @@ public class WebSocketResourceProvider implements WebSocketListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleResponse(WebSocketResponseMessage responseMessage) {
|
private void handleResponse(WebSocketResponseMessage responseMessage) {
|
||||||
SettableFuture<WebSocketResponseMessage> future = requestMap.remove(responseMessage.getRequestId());
|
CompletableFuture<WebSocketResponseMessage> future = requestMap.remove(responseMessage.getRequestId());
|
||||||
|
|
||||||
if (future != null) {
|
if (future != null) {
|
||||||
future.set(responseMessage);
|
future.complete(responseMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,7 +197,7 @@ public class WebSocketResourceProvider implements WebSocketListener {
|
||||||
error.getStatus(),
|
error.getStatus(),
|
||||||
"Error response",
|
"Error response",
|
||||||
headers,
|
headers,
|
||||||
Optional.<byte[]>empty());
|
Optional.empty());
|
||||||
|
|
||||||
remoteEndpoint.sendBytesByFuture(ByteBuffer.wrap(response.toByteArray()));
|
remoteEndpoint.sendBytesByFuture(ByteBuffer.wrap(response.toByteArray()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/**
|
/*
|
||||||
* Copyright (C) 2014 Open WhisperSystems
|
* Copyright (C) 2014 Open WhisperSystems
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
|
Loading…
Reference in New Issue