diff --git a/gemp-lotr/gemp-lotr-async/pom.xml b/gemp-lotr/gemp-lotr-async/pom.xml new file mode 100644 index 000000000..4717560c7 --- /dev/null +++ b/gemp-lotr/gemp-lotr-async/pom.xml @@ -0,0 +1,25 @@ + + + + gemp-lotr + com.gempukku.lotro + 1.0-SNAPSHOT + + 4.0.0 + com.gempukku.lotro + gemp-lotr-async + 1.0-SNAPSHOT + + + ${project.groupId} + gemp-lotr-web-server + ${project.version} + + + io.netty + netty + 3.6.1.Final + + + \ No newline at end of file diff --git a/gemp-lotr/gemp-lotr-async/src/main/java/com/gempukku/lotro/async/HttpRequestHandler.java b/gemp-lotr/gemp-lotr-async/src/main/java/com/gempukku/lotro/async/HttpRequestHandler.java new file mode 100644 index 000000000..6867f0eba --- /dev/null +++ b/gemp-lotr/gemp-lotr-async/src/main/java/com/gempukku/lotro/async/HttpRequestHandler.java @@ -0,0 +1,104 @@ +package com.gempukku.lotro.async; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.jboss.netty.buffer.ChannelBuffers; +import org.jboss.netty.channel.*; +import org.jboss.netty.handler.codec.http.*; +import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.CONTENT_LENGTH; +import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.CONTENT_TYPE; +import static org.jboss.netty.handler.codec.http.HttpHeaders.is100ContinueExpected; +import static org.jboss.netty.handler.codec.http.HttpHeaders.isKeepAlive; +import static org.jboss.netty.handler.codec.http.HttpResponseStatus.*; +import static org.jboss.netty.handler.codec.http.HttpVersion.HTTP_1_1; +import org.jboss.netty.util.CharsetUtil; + +import java.lang.reflect.Type; +import java.util.List; +import java.util.Map; + +public class HttpRequestHandler extends SimpleChannelUpstreamHandler { + + private HttpRequest _request; + private boolean _readingChunks; + private String _uri; + private Map _objects; + + public HttpRequestHandler(Map objects) { + _objects = objects; + } + + @Override + public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { + _request = (HttpRequest) e.getMessage(); + + if (is100ContinueExpected(_request)) { + send100Continue(e); + } + + String uri = _request.getUri(); + + if (uri.indexOf("?")>-1) + _uri = uri.substring(0, uri.indexOf("?")); + else + _uri = uri; + + QueryStringDecoder queryStringDecoder = new QueryStringDecoder(_request.getUri()); + Map> queryStringParams = queryStringDecoder.getParameters(); + + HttpMethod httpMethod = _request.getMethod(); + + if (_request.isChunked()) { + send400Error(e); + } else { + ChannelBuffer content = _request.getContent(); + if (content.readable()) { + } + writeResponse(e); + } + } + + private void writeResponse(MessageEvent e) { + // Decide whether to close the connection or not. + boolean keepAlive = isKeepAlive(_request); + + // Build the response object. + HttpResponse response = new DefaultHttpResponse(HTTP_1_1, OK); + response.setContent(ChannelBuffers.copiedBuffer("Response: " + _uri, CharsetUtil.UTF_8)); + response.setHeader(CONTENT_TYPE, "text/plain; charset=UTF-8"); + + if (keepAlive) { + // Add 'Content-Length' header only for a keep-alive connection. + response.setHeader(CONTENT_LENGTH, response.getContent().readableBytes()); + } + + // Write the response. + ChannelFuture future = e.getChannel().write(response); + + // Close the non-keep-alive connection after the write operation is done. + if (!keepAlive) { + future.addListener(ChannelFutureListener.CLOSE); + } + } + + private void send400Error(MessageEvent e) { + boolean keepAlive = isKeepAlive(_request); + + HttpResponse response = new DefaultHttpResponse(HTTP_1_1, BAD_REQUEST); + ChannelFuture future = e.getChannel().write(response); + if (!keepAlive) { + future.addListener(ChannelFutureListener.CLOSE); + } + } + + private void send100Continue(MessageEvent e) { + HttpResponse response = new DefaultHttpResponse(HTTP_1_1, CONTINUE); + e.getChannel().write(response); + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) + throws Exception { + e.getCause().printStackTrace(); + e.getChannel().close(); + } +} diff --git a/gemp-lotr/gemp-lotr-async/src/main/java/com/gempukku/lotro/async/HttpServerPipelineFactory.java b/gemp-lotr/gemp-lotr-async/src/main/java/com/gempukku/lotro/async/HttpServerPipelineFactory.java new file mode 100644 index 000000000..e5f23336d --- /dev/null +++ b/gemp-lotr/gemp-lotr-async/src/main/java/com/gempukku/lotro/async/HttpServerPipelineFactory.java @@ -0,0 +1,44 @@ +package com.gempukku.lotro.async; + +import com.gempukku.lotro.packs.PacksStorage; +import com.gempukku.lotro.server.provider.DaoBuilder; +import com.gempukku.lotro.server.provider.PacksStorageBuilder; +import com.gempukku.lotro.server.provider.ServerBuilder; +import org.jboss.netty.channel.ChannelPipeline; +import org.jboss.netty.channel.ChannelPipelineFactory; +import org.jboss.netty.channel.Channels; +import org.jboss.netty.handler.codec.http.HttpContentCompressor; +import org.jboss.netty.handler.codec.http.HttpRequestDecoder; +import org.jboss.netty.handler.codec.http.HttpResponseEncoder; + +import java.lang.reflect.Type; +import java.util.HashMap; +import java.util.Map; + +public class HttpServerPipelineFactory implements ChannelPipelineFactory { + public ChannelPipeline getPipeline() throws Exception { + // Create a default pipeline implementation. + ChannelPipeline pipeline = Channels.pipeline(); + + // Uncomment the following line if you want HTTPS + //SSLEngine engine = SecureChatSslContextFactory.getServerContext().createSSLEngine(); + //engine.setUseClientMode(false); + //pipeline.addLast("ssl", new SslHandler(engine)); + + pipeline.addLast("decoder", new HttpRequestDecoder()); + // Uncomment the following line if you don't want to handle HttpChunks. + //pipeline.addLast("aggregator", new HttpChunkAggregator(1048576)); + pipeline.addLast("encoder", new HttpResponseEncoder()); + // Remove the following line if you don't want automatic content compression. + pipeline.addLast("deflater", new HttpContentCompressor()); + + Map objects = new HashMap(); + objects.put(PacksStorage.class, PacksStorageBuilder.createPacksStorage()); + DaoBuilder.fillObjectMap(objects); + ServerBuilder.fillObjectMap(objects); + ServerBuilder.constructObjects(objects); + + pipeline.addLast("handler", new HttpRequestHandler(objects)); + return pipeline; + } +} diff --git a/gemp-lotr/gemp-lotr-async/src/main/java/com/gempukku/lotro/async/LotroAsyncServer.java b/gemp-lotr/gemp-lotr-async/src/main/java/com/gempukku/lotro/async/LotroAsyncServer.java new file mode 100644 index 000000000..091832203 --- /dev/null +++ b/gemp-lotr/gemp-lotr-async/src/main/java/com/gempukku/lotro/async/LotroAsyncServer.java @@ -0,0 +1,26 @@ +package com.gempukku.lotro.async; + +import org.jboss.netty.bootstrap.ServerBootstrap; +import org.jboss.netty.channel.ChannelFactory; +import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory; + +import java.net.InetSocketAddress; +import java.util.concurrent.Executors; + +public class LotroAsyncServer { + public static void main(String[] server) { + ChannelFactory factory = + new NioServerSocketChannelFactory( + Executors.newCachedThreadPool(), + Executors.newCachedThreadPool()); + + + ServerBootstrap bootstrap = new ServerBootstrap(factory); + + bootstrap.setPipelineFactory(new HttpServerPipelineFactory()); + + bootstrap.setOption("child.tcpNoDelay", true); + bootstrap.setOption("child.keepAlive", true); + bootstrap.bind(new InetSocketAddress(8080)); + } +} diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/GameEvent.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/GameEvent.java index 870dc3883..1467f36fa 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/GameEvent.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/GameEvent.java @@ -7,6 +7,7 @@ import com.gempukku.lotro.game.PhysicalCard; import com.gempukku.lotro.logic.decisions.AwaitingDecision; import com.gempukku.lotro.logic.timing.GameStats; +import java.util.Date; import java.util.List; public class GameEvent { @@ -18,9 +19,10 @@ public class GameEvent { AT, RT, M, W, GS, - CAC, EP, CA, D + CAC, EP, CA, D, CH } + private Date _date; private String _message; private String _side; private Type _type; @@ -43,6 +45,15 @@ public class GameEvent { _type = type; } + public Date getDate() { + return _date; + } + + public GameEvent date(Date date) { + _date = date; + return this; + } + public Integer getIndex() { return _index; }