From 4c302ac983a5bc263da80d09873f49de22c480f5 Mon Sep 17 00:00:00 2001 From: Nikita Date: Sat, 7 Apr 2012 12:56:55 +0400 Subject: [PATCH] origin header usage --- .../socketio/HeartbeatHandler.java | 17 +++++++----- .../socketio/SocketIORouter.java | 8 +++--- .../socketio/transport/XHRPollingClient.java | 26 +++++++++++-------- .../transport/XHRPollingTransport.java | 24 ++++++++++------- 4 files changed, 43 insertions(+), 32 deletions(-) diff --git a/src/main/java/com/corundumstudio/socketio/HeartbeatHandler.java b/src/main/java/com/corundumstudio/socketio/HeartbeatHandler.java index adc13a2..73d4015 100644 --- a/src/main/java/com/corundumstudio/socketio/HeartbeatHandler.java +++ b/src/main/java/com/corundumstudio/socketio/HeartbeatHandler.java @@ -51,7 +51,7 @@ public class HeartbeatHandler { }, heartbeatIntervalSecs, TimeUnit.SECONDS); } - public void cancelHeartbeatCheck(final SocketIOClient client) { + public void cancelHeartbeatCheck(SocketIOClient client) { Future future = scheduledHeartbeatFutures.remove(client.getSessionId()); if (future != null) { future.cancel(false); @@ -62,16 +62,19 @@ public class HeartbeatHandler { client.send(new Packet(PacketType.HEARTBEAT)); scheduleHeartbeatCheck(client.getSessionId(), new Runnable() { public void run() { - client.disconnect(); - UUID sessionId = client.getSessionId(); - scheduledHeartbeatFutures.remove(sessionId); - log.debug("Client with sessionId: {} disconnected due to heartbeat timeout", sessionId); + try { + client.disconnect(); + } finally { + UUID sessionId = client.getSessionId(); + scheduledHeartbeatFutures.remove(sessionId); + log.debug("Client with sessionId: {} disconnected due to heartbeat timeout", sessionId); + } } }); } - public void scheduleHeartbeatCheck(final UUID sessionId, Runnable runnable) { - Future future = executorService.schedule(runnable, heartbeatTimeoutSecs+2, TimeUnit.SECONDS); + public void scheduleHeartbeatCheck(UUID sessionId, Runnable runnable) { + Future future = executorService.schedule(runnable, heartbeatTimeoutSecs, TimeUnit.SECONDS); scheduledHeartbeatFutures.put(sessionId, future); } diff --git a/src/main/java/com/corundumstudio/socketio/SocketIORouter.java b/src/main/java/com/corundumstudio/socketio/SocketIORouter.java index 0114ffb..b34c861 100644 --- a/src/main/java/com/corundumstudio/socketio/SocketIORouter.java +++ b/src/main/java/com/corundumstudio/socketio/SocketIORouter.java @@ -138,10 +138,10 @@ public class SocketIORouter { String transports = "xhr-polling"; String hs = sessionId + ":" + heartbeatTimeout + ":" + closeTimeoutSecs + ":" + transports; - List jsonp = params.get("jsonp"); - if (jsonp != null) { - hs = "io.j[" + jsonp.get(0) + "](" + objectMapper.writeValueAsString(hs) + ");"; - client.sendJsonp(hs); + List jsonpParam = params.get("jsonp"); + if (jsonpParam != null) { + String jsonpResponse = "io.j[" + jsonpParam.get(0) + "](" + objectMapper.writeValueAsString(hs) + ");"; + client.sendJsonp(jsonpResponse); } else { client.sendUnencoded(hs); } diff --git a/src/main/java/com/corundumstudio/socketio/transport/XHRPollingClient.java b/src/main/java/com/corundumstudio/socketio/transport/XHRPollingClient.java index 32bbc85..e23fe03 100644 --- a/src/main/java/com/corundumstudio/socketio/transport/XHRPollingClient.java +++ b/src/main/java/com/corundumstudio/socketio/transport/XHRPollingClient.java @@ -10,9 +10,8 @@ */ package com.corundumstudio.socketio.transport; -import static org.jboss.netty.handler.codec.http.HttpHeaders.isKeepAlive; -import static org.jboss.netty.handler.codec.http.HttpHeaders.setContentLength; -import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.CONTENT_TYPE; +import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.*; +import static org.jboss.netty.handler.codec.http.HttpHeaders.Values.*; import static org.jboss.netty.handler.codec.http.HttpVersion.HTTP_1_1; import java.io.IOException; @@ -26,6 +25,7 @@ import org.jboss.netty.channel.Channel; import org.jboss.netty.channel.ChannelFuture; import org.jboss.netty.channel.ChannelFutureListener; import org.jboss.netty.handler.codec.http.DefaultHttpResponse; +import org.jboss.netty.handler.codec.http.HttpHeaders; import org.jboss.netty.handler.codec.http.HttpRequest; import org.jboss.netty.handler.codec.http.HttpResponse; import org.jboss.netty.handler.codec.http.HttpResponseStatus; @@ -48,6 +48,7 @@ public class XHRPollingClient implements SocketIOClient { private final List messages = new LinkedList(); private final UUID sessionId; + private String origin; private boolean isKeepAlive; private boolean connected; private Channel channel; @@ -66,13 +67,14 @@ public class XHRPollingClient implements SocketIOClient { } public void doReconnect(Channel channel, HttpRequest req) { - isKeepAlive = isKeepAlive(req); + this.isKeepAlive = HttpHeaders.isKeepAlive(req); + this.origin = req.getHeader(HttpHeaders.Names.ORIGIN); this.channel = channel; this.connected = true; sendPayload(); } - private ChannelFuture sendPayload() { + private synchronized ChannelFuture sendPayload() { if(!connected || messages.isEmpty()) { return NullChannelFuture.INSTANCE; } @@ -85,19 +87,21 @@ public class XHRPollingClient implements SocketIOClient { HttpResponse res = new DefaultHttpResponse(HTTP_1_1, HttpResponseStatus.OK); res.addHeader(CONTENT_TYPE, "text/plain; charset=UTF-8"); - res.addHeader("Access-Control-Allow-Origin", "*"); - res.addHeader("Access-Control-Allow-Credentials", "true"); - res.addHeader("Connection", "keep-alive"); + res.addHeader(CONNECTION, KEEP_ALIVE); + if (origin != null) { + res.addHeader("Access-Control-Allow-Origin", origin); + res.addHeader("Access-Control-Allow-Credentials", "true"); + } if (jsonp) { - res.addHeader("Content-Type", "application/javascript"); + res.addHeader(CONTENT_TYPE, "application/javascript"); } res.setContent(ChannelBuffers.copiedBuffer(message, CharsetUtil.UTF_8)); - setContentLength(res, res.getContent().readableBytes()); - + HttpHeaders.setContentLength(res, res.getContent().readableBytes()); connected = false; jsonp = false; + origin = null; if(channel.isOpen()) { log.trace("Sending message: {} to client with sessionId: {}", new Object[] {message, sessionId}); diff --git a/src/main/java/com/corundumstudio/socketio/transport/XHRPollingTransport.java b/src/main/java/com/corundumstudio/socketio/transport/XHRPollingTransport.java index 8fb5fc5..868a8b7 100644 --- a/src/main/java/com/corundumstudio/socketio/transport/XHRPollingTransport.java +++ b/src/main/java/com/corundumstudio/socketio/transport/XHRPollingTransport.java @@ -79,7 +79,7 @@ public class XHRPollingTransport implements SocketIOTransport { } } - private void onPost(QueryStringDecoder queryDecoder, Channel channel, HttpRequest msg) { + private void onPost(QueryStringDecoder queryDecoder, Channel channel, HttpRequest req) { String path = queryDecoder.getPath(); if (!path.startsWith(pollingPath)) { log.warn("Wrong POST request path: {}, from ip: {}. Channel closed!", @@ -98,7 +98,7 @@ public class XHRPollingTransport implements SocketIOTransport { return; } - String content = msg.getContent().toString(CharsetUtil.UTF_8); + String content = req.getContent().toString(CharsetUtil.UTF_8); log.trace("Request content: {}", content); try { List packets = decoder.decodePayload(content); @@ -108,12 +108,16 @@ public class XHRPollingTransport implements SocketIOTransport { } catch (IOException e) { } - HttpHeaders.setKeepAlive(msg, false); + HttpHeaders.setKeepAlive(req, false); //send a response that allows for cross domain access HttpResponse resp = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); - resp.addHeader("Access-Control-Allow-Origin", "*"); - sendHttpResponse(channel, msg, resp); + String origin = req.getHeader(HttpHeaders.Names.ORIGIN); + if (origin != null) { + resp.addHeader("Access-Control-Allow-Origin", origin); + resp.addHeader("Access-Control-Allow-Credentials", "true"); + } + sendHttpResponse(channel, req, resp); } else { log.warn("Wrong POST request path: {}, from ip: {}. Channel closed!", new Object[] {path, channel.getRemoteAddress()}); @@ -121,7 +125,7 @@ public class XHRPollingTransport implements SocketIOTransport { } } - private void onGet(QueryStringDecoder queryDecoder, Channel channel, HttpRequest msg) throws IOException { + private void onGet(QueryStringDecoder queryDecoder, Channel channel, HttpRequest req) throws IOException { String path = queryDecoder.getPath(); if (!path.startsWith(pollingPath)) { log.warn("Wrong GET request path: {}, from ip: {}. Channel closed!", @@ -138,12 +142,12 @@ public class XHRPollingTransport implements SocketIOTransport { if (client == null) { client = createClient(sessionId); } - client.doReconnect(channel, msg); + client.doReconnect(channel, req); if (queryDecoder.getParameters().containsKey("disconnect")) { disconnect(sessionId); } } else { - sendError(channel, msg, sessionId); + sendError(channel, req, sessionId); } } else { log.warn("Wrong GET request path: {}, from ip: {}. Channel closed!", @@ -161,14 +165,14 @@ public class XHRPollingTransport implements SocketIOTransport { return client; } - private void sendError(Channel channel, HttpRequest msg, UUID sessionId) { + private void sendError(Channel channel, HttpRequest req, UUID sessionId) { log.debug("Client with sessionId: {} was not found! Reconnect error response sended", sessionId); XHRPollingClient client = new XHRPollingClient(encoder, socketIORouter, null); Packet packet = new Packet(PacketType.ERROR); packet.setReason(ErrorReason.CLIENT_NOT_HANDSHAKEN); packet.setAdvice(ErrorAdvice.RECONNECT); client.send(packet); - client.doReconnect(channel, msg); + client.doReconnect(channel, req); } private void sendHttpResponse(Channel channel, HttpRequest req, HttpResponse res) {