Cliente Tyrus websocket @OnMessage nunca chamado - Storj Open source project

9

Estou trabalhando em um projeto de código aberto, o Storj. Estou escrevendo um cliente Java que se conecta a um backend websocket do Node.js. O cliente usa o Tyrus. A comunicação deve ser a seguinte:

  • Conectar
  • O cliente envia o token de autenticação (texto).
  • O servidor envia um arquivo de volta (binário).
  • O servidor fecha a conexão.

Estou tendo problemas porque meu @OnMessage nunca é chamado. Eu tentei com um simples cliente javascript online aqui para o mesmo URL e com o mesmo token: link

Eu recebo uma resposta usando isso, o que me diz que algo está errado com o projeto Java.

Antes de poder baixar o arquivo, em um estágio anterior, posso fazer o upload do arquivo sem problemas. No entanto, essa etapa não exige que uma @OnMessage seja chamada (ela apenas carrega o arquivo e, em seguida, o servidor se desconecta com uma mensagem), portanto, não tenho certeza se meu @OnMessage já está funcionando.

Aqui está o código relevante para o Websocket (também disponível no Github): link

package storj.io.client.websockets;

import com.google.gson.Gson;
import storj.io.restclient.model.FilePointer;

import javax.websocket.*;
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;

import java.util.concurrent.CountDownLatch;
import java.util.logging.Logger;

/**
 * Created by steve on 12/07/2016.
 */
@ClientEndpoint
public class WebsocketFileRetriever {

    private Logger logger = Logger.getLogger(this.getClass().getName());
    private Gson gson = new Gson();
    private FilePointer filePointer;
    private File outputFile;
    private AuthorizationModel authModel;
    private CountDownLatch latch;

    public WebsocketFileRetriever(FilePointer filePointer, File outputFile, CountDownLatch latch){
        this.filePointer = filePointer;
        this.latch = latch;
        this.outputFile = outputFile;
        authModel = new AuthorizationModel();
        authModel.setToken(filePointer.getToken());
        authModel.setOperation(filePointer.getOperation());
        authModel.setHash(filePointer.getHash());
    }

    @OnMessage
    public void onMessage(String s){
        logger.info("Received ... " + s);
    }

    @OnMessage
    public void onMessage(ByteBuffer message, Session session) {
        logger.info("Received ...." + message);
    }

    @OnOpen
    public void onOpen(Session session, EndpointConfig endpointConfig) {
        logger.info("Opened");
        try {
            session.getBasicRemote().sendText(gson.toJson(authModel), true);
        } catch (IOException e) {
            e.printStackTrace();
        }

        logger.info("sent: " + gson.toJson(authModel));
    }

    @OnClose
    public void onClose(Session session, CloseReason closeReason) {
        logger.info("Closed Websocket: " + closeReason.getCloseCode() + " " + closeReason.getReasonPhrase());
        //latch.countDown();
    }

    @OnError
    public void onError(Session session, Throwable t) {
        t.printStackTrace();
    }
}

E o código que inicia este websocket, disponível aqui link :

        CountDownLatch latch;
        latch = new CountDownLatch(1);
        ClientManager wsClient = ClientManager.createClient();
        try {
            wsClient.setDefaultMaxBinaryMessageBufferSize(Integer.MAX_VALUE);
            wsClient.setDefaultMaxTextMessageBufferSize(Integer.MAX_VALUE);
            logger.info("CONNECTING TO: " + "ws://" + pointer.getFarmer().getAddress() + ":" + pointer.getFarmer().getPort());
            final ClientEndpointConfig cec = ClientEndpointConfig.Builder.create().build();

            wsClient.connectToServer(new WebsocketFileRetriever(pointer, encryptedOutputFile, latch), cec, new URI("ws://" + pointer.getFarmer().getAddress() + ":" + pointer.getFarmer().getPort()));
            latch.await();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

Eu também tentei atualizar o Tyrus para a versão mais recente, e recebo o mesmo resultado. Alguma idéia?

A saída deste código é:

    Aug 25, 2016 8:55:31 PM storj.io.client.DefaultStorjClient downloadFile
INFO: CONNECTING TO: ws://164.storj.eu:8607
Aug 25, 2016 8:55:35 PM storj.io.client.websockets.WebsocketFileRetriever onOpen
INFO: Opened
Aug 25, 2016 8:55:35 PM storj.io.client.websockets.WebsocketFileRetriever onOpen
INFO: sent: {"token":"06c36d4bac4f07ee1751068b5b2230f22e884b38","hash":"837b79bec927a1d8fa7fedd2ea0bb276e0d86e0f","operation":"PULL"}
Aug 25, 2016 8:56:11 PM storj.io.client.websockets.WebsocketFileRetriever onClose
INFO: Closed Websocket: NORMAL_CLOSURE Closing

Depois de enviar a mensagem, ela é interrompida por algum tempo antes da mensagem "NORMAL_CLOSURE" do @OnClose.

Atualização: uma maneira muito fácil de executar isso para reproduzir o problema

Eu adicionei um nome de usuário e uma senha de teste ao repositório git, então o código disponível está aqui: link

Para executá-lo, você só precisa executar o storj.io.client.main.MainTest

Um rápido resumo do que faz. Primeiro, ele enviará algumas solicitações HTTP para obter um token. Ele usará esse token para se conectar à máquina de alguém por meio de um websocket e enviará esse token como texto. Em resposta, ele deve receber um arquivo como bytes.

Antes de se conectar, ele imprime o token e o endereço para o qual está prestes a se conectar. Ele irá travar um pouco antes de ser fechado e nenhum método onMessage será chamado. Para testar, se você colocar um System.exit lá (Uncomment Line 152 em DefaultStorjClient.java), ele não se conectará para que você possa usar esse token em outro cliente. Eu testei usando o link (certifique-se de que seu navegador permitirá URLs inseguros, pois não é "wss", para fazer isso em Chrome, você precisa clicar no escudo no canto superior direito. Eu posso ver o servidor responder:

Isso mostra que um blob é realmente enviado em resposta à mensagem de texto, mas o @OnMessage no Tyrus nunca é acionado.

    
por ThePerson 25.08.2016 в 22:15
fonte

1 resposta

2

No final, mudei para o TallNate e este problema não existe.

Encontrei depois de cronometrar que sempre me desconectava depois de 30 segundos. Normalmente, as respostas são mais rápidas do que nos 30s, por isso não tenho a certeza por que razão estava pendurado e depois desligando. Eu tentei definir o tempo limite em Tyrus, mas ainda assim desconectado na marca dos 30s. No final, eu tentei TallNate para ver se eu poderia definir o tempo limite lá ... e fora da caixa, só funcionou.

link

    
por ThePerson 28.08.2016 / 14:34
fonte