Determine server push communication type

Hello everybody,

When reading through the
server push topic
in the book of vaadin, I’ve a question about following quote:



The server-client communication is done by default with a WebSocket connection if the browser and the server support it.
If not, Vaadin will fall back to a method supported by the browser.

So different communication methods can be used by Vaadin/Atmosphere, depending on the server and browser. Is it possible to determine programmatically which communication method is used in the current session? I would like to display the communication method in my UI, so the user can see if the server push is currently working in the most optimal way.

Thanks in advance!!!
Bart Butenaers

It seems that Atmosphere reads the transport type from the X-Atmosphere-Transport header variable, that is contained in the arriving AtmosphereRequest instance. This happens in the AtmosphereResourceImpl class:

[font=arial]
[i]
[size=1]
private TRANSPORT configureTransport() {
if (req == null) return TRANSPORT.UNDEFINED;

    String s = req.getHeader(HeaderConfig.X_ATMOSPHERE_TRANSPORT);
    if (s == null) return TRANSPORT.UNDEFINED;

    s = s.replace("-", "_").toUpperCase();
    if (TRANSPORT.POLLING.name().equals(s)) {
        return TRANSPORT.POLLING;
    } else if (TRANSPORT.LONG_POLLING.name().equals(s)) {
        return TRANSPORT.LONG_POLLING;
    } else if (TRANSPORT.STREAMING.name().equals(s)) {
        return TRANSPORT.STREAMING;
    } else if (TRANSPORT.JSONP.name().equals(s)) {
        return TRANSPORT.JSONP;
    } else if (TRANSPORT.WEBSOCKET.name().equals(s)) {
        return TRANSPORT.WEBSOCKET;
    } else if (TRANSPORT.SSE.name().equals(s)) {
        return TRANSPORT.SSE;
    } else if (TRANSPORT.AJAX.name().equals(s)) {
        return TRANSPORT.AJAX;
    } else {
        return TRANSPORT.UNDEFINED;
    }
}

[/size]
[/i]
[/font]

The result is stored in the ‘transport’ field of the AtmosphereResource, where it is read e.g. by Vaadin’s PushHandler class. So I assume I have to read the transport type from either the request or the resource. If anybody else has a better idea, I would appreciate to hear from you! I can verify this information in Vaadin’s debug window (see attachment).

But now I have an extra problem: in the beginning I receive a request with the WEBSOCKET type and afterwards I get a request with the LONG_POLLING type. I assume that Atmosphere has switched to the fallback type (in the atmosphere.min.js script perhaps ??) for some obscure reason. So if I want to give my users feedback on the transport type, I have two extra questions:

  • Can the transport type still change again afterwards, or is it determined once for a session ?
  • If atmosphere switches to a fallback type, can I determine why? E.g. is it a browser issue or a server issue? In other words, could anybody give me tip where this logic is implemented ?

Any help is welcome!!!
Thanks in advance,
Bart
15716.jpg

Atmosphere seems to start with websockets and then it does a negotiation between client and server to determine which transport type it will use eventually. If I’m not mistaken, the server part of the negotiation is called in the handleRequest method of the PushRequestHandler class:


atmosphere.doCometSupport(AtmosphereRequest…

Since I use an embbeded Jetty server with JRS356 activated, this method call will be handled by JSR356AsyncSupport (and eventually in the AsyncProcessor) where I found:



if (!Utils.properProtocol(req) || (Utils.webSocketEnabled(req) && !supportWebSocket())) {
res.setStatus(501);
res.addHeader(X_ATMOSPHERE_ERROR, “Websocket protocol not supported”);
res.flushBuffer();
return new Action();
}

Howevver, it gives no Atmosphere errors here. Does this mean my server is supporting websockets, but my client (Chrome browser) is not supporting websockets for some reason ??

Thx,
Bart

For the interested readers, it seems that ‘transport’ field of the AtmosphereResource is indeed the way to get the transport type (according to this stackoverflow
topic
, answered by the Atmosphere creator Jean-Francois Arcand). So the original question of this forum thread is answered …

But I’m still stuck with the failure of the preferred Websocket communication. Seems the VaadinPush.debug.js tries first to open a Websocket connection to the Jetty server, but this fails (so it starts the fallback method):



function _executeWebSocket(webSocketOpened) {
_response.transport = “websocket”;

_websocket = _getWebSocket(location); → creates a new WebSocket object

_websocket.onerror = function (message) {
clearTimeout(_request.id); → unfortunately I end up here with an

error


};


The error is "
Error during WebSocket handshake: Unexpected response code: 200
". The websocket protocol (
RFC 6455
) defines that a handshake should return a response 101 (Switching Protocols), which doesn’t happen in my case. Does anybody have a clue what I need to setup to get that 101 response (is this a problem in Jetty or in Atmosphere) ?

Thx, Bart

​Hi, Bart

did you have any clue about your iusse ?

I’m facing the same problem, I’m having this browser log on chrome

WebSocket connection to ‘ws://localhost:8080/webbap/ui/PUSH/?v-uiId=3&v-csrfToken=a93420cd-c6e7-4c4b-b323-cb3bfe50775d&X-Atmosphere-tracking-id=0&X-Atmosphere-Framework=2.2.6.vaadin4-jquery&X-Atmosphere-Transport=websocket&X-Atmosphere-TrackMessageSize=true&Content-Type=application/json;%20charset=UTF-8&X-atmo-protocol=true’ failed: Error during WebSocket handshake: Unexpected response code: 200

I’m pretty sure that I’m using a server with websocket, Tomcat 8.0.23

The very strange thing is that I got response code 200 after recompiling widgetset from vaadin 7.4.5 → 7.4.8
I have a running webapp with vaadin 7.4.5 that shows 101 response instead

Hi Bob,

That is already a some time ago, but if I’m not mistaken this is what I have done to solve the problem:

  • After a lot of debugging I found that the websocket handshake failed because the Vaadin URL ends on ‘/PUSH/’ while Jetty expected ‘/PUSH’ (i.e. without the trailing ‘/’).
  • I registered a ticket (
    https://dev.vaadin.com/ticket/14381
    )
  • Since I got no feedback at that time, I created a dirty hack (when starting up my embedded Jetty): I try to find the WebSocketUpgradeFilter in the filter chain, and then copy the mapping for “/PUSH” to “/PUSH/”. You can find my code snippet in comment 2 of the ticket to workaround this issue.
  • Afterwards Artur responded in the ticket that this issue should be resolved by now, but I didn’t have time yet to check his solution.

If that doesn’t help, I’m afraid you will have to start debugging. In my opinion the VaadinPush.debug.js (in Chrome) and the WebSocketUpgradeFilter (in your Java IDE) are a good place to start. With breakpoints in these both sides of your communication channel, you should get an idea where/why it stops handshaking.

And afterwards - when everything was up and running - I created another dirty hack to show the communication type (websocket, long polling, …) in my Vaadin UI:

[code]
String communicationType = “Unknown”;

    UI ui = getComponent().getUI();

    // Get the communication type from the Atmosphere (framework) connection, which is stored in the private resource ;-(
    if(ui != null) {
        try {
            if(ui.getPushConnection() instanceof AtmospherePushConnection) {
                AtmospherePushConnection atmospherePushConnection = (AtmospherePushConnection)ui.getPushConnection();
                Field field = atmospherePushConnection.getClass().getDeclaredField("resource");
                field.setAccessible(true);
                AtmosphereResource atmosphereResource = (AtmosphereResource)field.get(atmospherePushConnection);
                communicationType = atmosphereResource.transport().name();
            }
        }
        catch(Exception e) {
            // Cannot determine communication type, so it will remain 'Unknown'
        }
    }

[/code]Not a very elegant solution, but at least it does the job for me …
Good luck with your analysis !!

Bart Butenaers