org.atmosphere.socketio.transport.WebSocketTransport Maven / Gradle / Ivy
/*
* Copyright 2014 Sebastien Dionne
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.atmosphere.socketio.transport;
import static org.atmosphere.cpr.ApplicationConfig.SUSPENDED_ATMOSPHERE_RESOURCE_UUID;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import org.atmosphere.cpr.Action;
import org.atmosphere.cpr.AtmosphereHandler;
import org.atmosphere.cpr.AtmosphereRequest;
import org.atmosphere.cpr.AtmosphereResourceImpl;
import org.atmosphere.cpr.AtmosphereResponse;
import org.atmosphere.socketio.SocketIOException;
import org.atmosphere.socketio.SocketIOPacket;
import org.atmosphere.socketio.SocketIOSession;
import org.atmosphere.socketio.SocketIOSessionFactory;
import org.atmosphere.socketio.SocketIOWebSocketSessionWrapper;
import org.atmosphere.socketio.cpr.SocketIOAtmosphereHandler;
import org.atmosphere.socketio.cpr.SocketIOWebSocketEventListener;
import org.atmosphere.websocket.WebSocket;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author Sebastien Dionne : [email protected]
* @author Jeanfrancois Arcand
*/
public class WebSocketTransport extends AbstractTransport {
private static final Logger logger = LoggerFactory.getLogger(WebSocketTransport.class);
public static final String TRANSPORT_NAME = "websocket";
public WebSocketTransport() {
}
@Override
public String getName() {
return TRANSPORT_NAME;
}
@Override
public Action handle(AtmosphereResourceImpl resource, AtmosphereHandler atmosphereHandler, SocketIOSessionFactory sessionFactory) throws IOException {
AtmosphereRequest request = resource.getRequest();
Object obj = request.getAttribute(SESSION_KEY);
SocketIOSession session = null;
String sessionId = null;
if (obj != null) {
session = (SocketIOSession) obj;
} else {
sessionId = extractSessionId(request);
if (sessionId != null && sessionId.length() > 0) {
session = sessionFactory.getSession(sessionId);
}
}
boolean isDisconnectRequest = isDisconnectRequest(request);
if (!isDisconnectRequest) {
if ("GET".equals(request.getMethod()) && "WebSocket".equalsIgnoreCase(request.getHeader("Upgrade"))) {
session = sessionFactory.getSession(sessionId);
request.setAttribute(SUSPENDED_ATMOSPHERE_RESOURCE_UUID, session.getSessionId());
request.setAttribute(SocketIOAtmosphereHandler.SOCKETIO_SESSION_ID, session.getSessionId());
// add a default websocketListener
SocketIOWebSocketEventListener socketioEventListener = new SocketIOWebSocketEventListener();
resource.addEventListener(socketioEventListener);
SocketIOWebSocketSessionWrapperImpl sessionWrapper = new SocketIOWebSocketSessionWrapperImpl(session, socketioEventListener);
socketioEventListener.setSessionWrapper(sessionWrapper);
request.setAttribute(SocketIOAtmosphereHandler.SOCKETIO_SESSION_OUTBOUND, sessionWrapper);
resource.suspend(-1);
}
} else {
session = sessionFactory.getSession(sessionId);
session.getTransportHandler().disconnect();
}
return Action.CANCELLED;
}
public class SocketIOWebSocketSessionWrapperImpl implements SocketIOWebSocketSessionWrapper {
public final SocketIOSession session;
public final SocketIOWebSocketEventListener socketioEventListener;
public boolean initiated = false;
public WebSocket webSocket;
SocketIOWebSocketSessionWrapperImpl(SocketIOSession session, SocketIOWebSocketEventListener socketioEventListener) {
this.session = session;
this.socketioEventListener = socketioEventListener;
this.socketioEventListener.setSessionWrapper(this);
}
/*
* (non-Javadoc)
* @see org.eclipse.jetty.websocket.WebSocket#onDisconnect()
*/
@Override
public void onDisconnect() {
logger.trace("calling from " + this.getClass().getName() + " : " + "onDisconnect");
session.onShutdown();
}
/*
* (non-Javadoc)
* @see org.eclipse.jetty.websocket.WebSocket#onMessage(byte, java.lang.String)
*/
@Override
public void onMessage(byte frame, String message) {
logger.trace("calling from " + this.getClass().getName() + " : " + "onMessage");
throw new RuntimeException();
}
/*
* (non-Javadoc)
* @see org.eclipse.jetty.websocket.WebSocket#onMessage(byte, byte[], int, int)
*/
@Override
public void onMessage(byte frame, byte[] data, int offset, int length) {
logger.trace("calling from " + this.getClass().getName() + " : " + "onMessage frame, data, offest, length");
try {
onMessage(frame, new String(data, offset, length, "UTF-8"));
} catch (UnsupportedEncodingException e) {
// Do nothing for now.
}
}
/*
* (non-Javadoc)
* @see com.glines.socketio.SocketIOInbound.SocketIOOutbound#disconnect()
*/
@Override
public void disconnect() {
logger.trace("calling from " + this.getClass().getName() + " : " + "disconnect");
session.onDisconnect(DisconnectReason.DISCONNECT);
webSocket.close();
}
@Override
public void close() {
logger.trace("calling from " + this.getClass().getName() + " : " + "close");
session.startClose();
}
@Override
public void sendMessage(SocketIOPacket packet) throws SocketIOException {
if (packet != null) {
sendMessage(packet.toString());
}
}
@Override
public void sendMessage(List messages) throws SocketIOException {
if (messages != null) {
for (SocketIOPacketImpl msg : messages) {
switch (msg.getFrameType()) {
case MESSAGE:
case JSON:
case EVENT:
case ACK:
case ERROR:
msg.setPadding(messages.size() > 1);
sendMessage(msg.toString());
break;
default:
logger.error("Unknown SocketIOEvent msg = " + msg);
}
}
}
}
/*
* (non-Javadoc)
* @see com.glines.socketio.SocketIOInbound.SocketIOOutbound#sendMessage(java.lang.String)
*/
@Override
public void sendMessage(String message) throws SocketIOException {
logger.trace("calling from " + this.getClass().getName() + " : " + "sendMessage(string) = " + message);
if (webSocket != null) {
try {
webSocket.write(message);
logger.trace("WRITE SUCCESS : calling from " + this.getClass().getName() + " : " + "sendMessage(string) = " + message);
} catch (IOException e) {
throw new SocketIOException(e);
}
} else {
logger.warn("WebSOCKET NULL");
}
}
/*
* (non-Javadoc)
* @see com.glines.socketio.SocketIOSession.SocketIOSessionOutbound#handle(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, com.glines.socketio.SocketIOSession)
*/
@Override
public Action handle(AtmosphereRequest request, AtmosphereResponse response, SocketIOSession session) throws IOException {
logger.trace("calling from " + this.getClass().getName() + " : " + "handle");
response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Unexpected request on upgraded WebSocket connection");
return Action.CONTINUE;
}
@Override
public void abort() {
logger.trace("calling from " + this.getClass().getName() + " : " + "abort");
webSocket.close();
webSocket = null;
session.onShutdown();
}
@Override
public SocketIOSession getSession() {
return session;
}
@Override
public boolean isInitiated() {
return initiated;
}
@Override
public WebSocket webSocket() {
return webSocket;
}
@Override
public void setWebSocket(WebSocket websocket) {
this.webSocket = websocket;
}
@Override
public void initiated(boolean initiated) {
this.initiated = initiated;
}
@Override
public String getSessionId() {
return session.getSessionId();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy