org.atmosphere.socketio.transport.XHRTransport 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 org.atmosphere.cache.BroadcastMessage;
import org.atmosphere.cpr.Action;
import org.atmosphere.cpr.ApplicationConfig;
import org.atmosphere.cpr.AtmosphereHandler;
import org.atmosphere.cpr.AtmosphereRequest;
import org.atmosphere.cpr.AtmosphereResourceEvent;
import org.atmosphere.cpr.AtmosphereResourceEventListenerAdapter;
import org.atmosphere.cpr.AtmosphereResourceImpl;
import org.atmosphere.cpr.AtmosphereResponse;
import org.atmosphere.cpr.DefaultBroadcaster;
import org.atmosphere.socketio.SocketIOClosedException;
import org.atmosphere.socketio.SocketIOException;
import org.atmosphere.socketio.SocketIOPacket;
import org.atmosphere.socketio.SocketIOSession;
import org.atmosphere.socketio.SocketIOSessionFactory;
import org.atmosphere.socketio.SocketIOSessionOutbound;
import org.atmosphere.socketio.cpr.SocketIOAtmosphereHandler;
import org.atmosphere.socketio.transport.SocketIOPacketImpl.PacketType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;
/**
* @author Sebastien Dionne : [email protected]
* @author Jeanfrancois Arcand
*/
public abstract class XHRTransport extends AbstractTransport {
private static final Logger logger = LoggerFactory.getLogger(XHRTransport.class);
private final int bufferSize;
protected abstract class XHRSessionHelper implements SocketIOSessionOutbound {
private final ReentrantLock lock = new ReentrantLock();
protected final SocketIOSession session;
private volatile boolean is_open = false;
private final boolean isStreamingConnection;
XHRSessionHelper(SocketIOSession session, boolean isConnectionPersistant) {
this.session = session;
this.isStreamingConnection = isConnectionPersistant;
}
protected abstract void startSend(AtmosphereResponse response) throws IOException;
protected abstract void writeData(AtmosphereResponse response, String data) throws IOException;
protected abstract void finishSend(AtmosphereResponse response) throws IOException;
@Override
public void disconnect() {
synchronized (this) {
session.onDisconnect(DisconnectReason.DISCONNECT);
abort();
}
}
@Override
public void close() {
synchronized (this) {
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);
try {
sendMessage(msg.toString());
} catch (Exception e) {
AtmosphereResourceImpl resource = session.getAtmosphereResourceImpl();
// if BroadcastCache is available, add the message to the cache
if (resource != null && DefaultBroadcaster.class.isAssignableFrom(resource.getBroadcaster().getClass())) {
resource.getBroadcaster().getBroadcasterConfig().getBroadcasterCache().
addToCache(resource.getBroadcaster().getID(), resource.uuid(),
new BroadcastMessage(msg));
}
}
break;
default:
logger.error("Unknown SocketIOEvent msg = " + msg);
}
}
}
}
@Override
public void sendMessage(String message) throws SocketIOException {
logger.trace("Session[" + session.getSessionId() + "]: " + "sendMessage(String): " + message);
synchronized (this) {
if (is_open) {
AtmosphereResourceImpl resource = session.getAtmosphereResourceImpl();
logger.trace("Session[" + session.getSessionId() + "]: " + resource.getRequest().getMethod() + "sendMessage");
try {
writeData(resource.getResponse(), message);
} catch (Exception e) {
if (!resource.isCancelled()) {
logger.trace("calling from " + this.getClass().getName() + " : " + "sendMessage ON FORCE UN RESUME");
try {
finishSend(resource.getResponse());
} catch (IOException ex) {
logger.trace("", ex);
}
resource.resume();
}
throw new SocketIOException(e);
}
if (!isStreamingConnection) {
try {
finishSend(resource.getResponse());
} catch (IOException e) {
logger.trace("", e);
}
resource.resume();
} else {
logger.trace("calling from " + this.getClass().getName() + " : " + "sendMessage");
session.startHeartbeatTimer();
}
} else {
logger.trace("calling from " + this.getClass().getName() + " : " + "SocketIOClosedException sendMessage");
throw new SocketIOClosedException();
}
}
}
@Override
public Action handle(AtmosphereRequest request, final AtmosphereResponse response, SocketIOSession session) throws IOException {
logger.trace("Session id[" + session.getSessionId() + "] method=" + request.getMethod() + " response HashCode=" + response.hashCode());
AtmosphereResourceImpl resource = (AtmosphereResourceImpl) request.getAttribute(ApplicationConfig.ATMOSPHERE_RESOURCE);
if ("GET".equals(request.getMethod())) {
synchronized (this) {
if (!is_open) {
response.sendError(AtmosphereResponse.SC_NOT_FOUND);
} else {
if (!isStreamingConnection) {
if (resource != null) {
resource.getRequest().setAttribute(SocketIOAtmosphereHandler.SOCKETIO_SESSION_ID, session.getSessionId());
resource.getRequest().setAttribute(SocketIOAtmosphereHandler.SOCKETIO_SESSION_OUTBOUND, session.getTransportHandler());
session.setAtmosphereResourceImpl(resource);
resource.addEventListener(new AtmosphereResourceEventListenerAdapter() {
@Override
public void onResume(AtmosphereResourceEvent event) {
if (event.isResumedOnTimeout()) {
event.getResource().write(new SocketIOPacketImpl(PacketType.NOOP).toString());
}
}
});
session.clearTimeoutTimer();
request.setAttribute(SESSION_KEY, session);
boolean resume = false;
StringBuilder data = new StringBuilder();
// if there is a Broadcaster cache, retrieve the messages from the cache, and send them
if (DefaultBroadcaster.class.isAssignableFrom(resource.getBroadcaster().getClass())) {
List
© 2015 - 2025 Weber Informatics LLC | Privacy Policy