mirror of
https://github.com/2006-Scape/2006Scape.git
synced 2026-10-01 18:07:49 +00:00
init, thx MrExtremez
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
package org.apollo.jagcached.net;
|
||||
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
|
||||
import org.apollo.jagcached.FileServer;
|
||||
import org.apollo.jagcached.dispatch.RequestDispatcher;
|
||||
import org.apollo.jagcached.net.jaggrab.JagGrabRequest;
|
||||
import org.apollo.jagcached.net.ondemand.OnDemandRequest;
|
||||
import org.apollo.jagcached.net.service.ServiceRequest;
|
||||
import org.apollo.jagcached.net.service.ServiceResponse;
|
||||
import org.jboss.netty.channel.ChannelHandlerContext;
|
||||
import org.jboss.netty.channel.ExceptionEvent;
|
||||
import org.jboss.netty.channel.MessageEvent;
|
||||
import org.jboss.netty.handler.codec.http.HttpRequest;
|
||||
import org.jboss.netty.handler.timeout.IdleStateAwareChannelUpstreamHandler;
|
||||
import org.jboss.netty.handler.timeout.IdleStateEvent;
|
||||
|
||||
/**
|
||||
* An {@link IdleStateAwareChannelUpstreamHandler} for the {@link FileServer}.
|
||||
* @author Graham
|
||||
*/
|
||||
public final class FileServerHandler extends IdleStateAwareChannelUpstreamHandler {
|
||||
|
||||
/**
|
||||
* The logger for this class.
|
||||
*/
|
||||
private static final Logger logger = Logger.getLogger(FileServerHandler.class.getName());
|
||||
|
||||
@Override
|
||||
public void channelIdle(ChannelHandlerContext ctx, IdleStateEvent e) throws Exception {
|
||||
e.getChannel().close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
|
||||
Object msg = e.getMessage();
|
||||
if (msg instanceof ServiceRequest) {
|
||||
ServiceRequest request = (ServiceRequest) msg;
|
||||
if (request.getId() != ServiceRequest.SERVICE_ONDEMAND) {
|
||||
e.getChannel().close();
|
||||
} else {
|
||||
e.getChannel().write(new ServiceResponse());
|
||||
}
|
||||
} else if (msg instanceof OnDemandRequest) {
|
||||
RequestDispatcher.dispatch(e.getChannel(), (OnDemandRequest) msg);
|
||||
} else if (msg instanceof JagGrabRequest) {
|
||||
RequestDispatcher.dispatch(e.getChannel(), (JagGrabRequest) msg);
|
||||
} else if (msg instanceof HttpRequest) {
|
||||
RequestDispatcher.dispatch(e.getChannel(), (HttpRequest) msg);
|
||||
} else {
|
||||
throw new Exception("unknown message type");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
|
||||
logger.log(Level.SEVERE, "Exception occured, closing channel...", e.getCause());
|
||||
e.getChannel().close();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package org.apollo.jagcached.net;
|
||||
|
||||
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.HttpChunkAggregator;
|
||||
import org.jboss.netty.handler.codec.http.HttpRequestDecoder;
|
||||
import org.jboss.netty.handler.codec.http.HttpResponseEncoder;
|
||||
import org.jboss.netty.handler.timeout.IdleStateHandler;
|
||||
import org.jboss.netty.util.Timer;
|
||||
|
||||
/**
|
||||
* A {@link ChannelPipelineFactory} for the HTTP protocol.
|
||||
* @author Graham
|
||||
*/
|
||||
public final class HttpPipelineFactory implements ChannelPipelineFactory {
|
||||
|
||||
/**
|
||||
* The maximum length of a request, in bytes.
|
||||
*/
|
||||
private static final int MAX_REQUEST_LENGTH = 8192;
|
||||
|
||||
/**
|
||||
* The file server event handler.
|
||||
*/
|
||||
private final FileServerHandler handler;
|
||||
|
||||
/**
|
||||
* The timer used for idle checking.
|
||||
*/
|
||||
private final Timer timer;
|
||||
|
||||
/**
|
||||
* Creates the HTTP pipeline factory.
|
||||
* @param handler The file server event handler.
|
||||
* @param timer The timer used for idle checking.
|
||||
*/
|
||||
public HttpPipelineFactory(FileServerHandler handler, Timer timer) {
|
||||
this.handler = handler;
|
||||
this.timer = timer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelPipeline getPipeline() throws Exception {
|
||||
ChannelPipeline pipeline = Channels.pipeline();
|
||||
|
||||
// decoders
|
||||
pipeline.addLast("decoder", new HttpRequestDecoder());
|
||||
pipeline.addLast("chunker", new HttpChunkAggregator(MAX_REQUEST_LENGTH));
|
||||
|
||||
// encoders
|
||||
pipeline.addLast("encoder", new HttpResponseEncoder());
|
||||
|
||||
// handler
|
||||
pipeline.addLast("timeout", new IdleStateHandler(timer, NetworkConstants.IDLE_TIME, 0, 0));
|
||||
pipeline.addLast("handler", handler);
|
||||
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package org.apollo.jagcached.net;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
|
||||
import org.apollo.jagcached.net.jaggrab.JagGrabRequestDecoder;
|
||||
import org.apollo.jagcached.net.jaggrab.JagGrabResponseEncoder;
|
||||
import org.jboss.netty.buffer.ChannelBuffer;
|
||||
import org.jboss.netty.buffer.ChannelBuffers;
|
||||
import org.jboss.netty.channel.ChannelPipeline;
|
||||
import org.jboss.netty.channel.ChannelPipelineFactory;
|
||||
import org.jboss.netty.channel.Channels;
|
||||
import org.jboss.netty.handler.codec.frame.DelimiterBasedFrameDecoder;
|
||||
import org.jboss.netty.handler.codec.string.StringDecoder;
|
||||
import org.jboss.netty.handler.timeout.IdleStateHandler;
|
||||
import org.jboss.netty.util.Timer;
|
||||
|
||||
/**
|
||||
* A {@link ChannelPipelineFactory} for the JAGGRAB protocol.
|
||||
* @author Graham
|
||||
*/
|
||||
public final class JagGrabPipelineFactory implements ChannelPipelineFactory {
|
||||
|
||||
/**
|
||||
* The maximum length of a request, in bytes.
|
||||
*/
|
||||
private static final int MAX_REQUEST_LENGTH = 8192;
|
||||
|
||||
/**
|
||||
* The character set used in the request.
|
||||
*/
|
||||
private static final Charset JAGGRAB_CHARSET = Charset.forName("US-ASCII");
|
||||
|
||||
/**
|
||||
* A buffer with two line feed (LF) characters in it.
|
||||
*/
|
||||
private static final ChannelBuffer DOUBLE_LINE_FEED_DELIMITER = ChannelBuffers.buffer(2);
|
||||
|
||||
/**
|
||||
* Populates the double line feed buffer.
|
||||
*/
|
||||
static {
|
||||
DOUBLE_LINE_FEED_DELIMITER.writeByte(10);
|
||||
DOUBLE_LINE_FEED_DELIMITER.writeByte(10);
|
||||
}
|
||||
|
||||
/**
|
||||
* The file server event handler.
|
||||
*/
|
||||
private final FileServerHandler handler;
|
||||
|
||||
/**
|
||||
* The timer used for idle checking.
|
||||
*/
|
||||
private final Timer timer;
|
||||
|
||||
/**
|
||||
* Creates a {@code JAGGRAB} pipeline factory.
|
||||
* @param handler The file server event handler.
|
||||
* @param timer The timer used for idle checking.
|
||||
*/
|
||||
public JagGrabPipelineFactory(FileServerHandler handler, Timer timer) {
|
||||
this.handler = handler;
|
||||
this.timer = timer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelPipeline getPipeline() throws Exception {
|
||||
ChannelPipeline pipeline = Channels.pipeline();
|
||||
|
||||
// decoders
|
||||
pipeline.addLast("framer", new DelimiterBasedFrameDecoder(MAX_REQUEST_LENGTH, DOUBLE_LINE_FEED_DELIMITER));
|
||||
pipeline.addLast("string-decoder", new StringDecoder(JAGGRAB_CHARSET));
|
||||
pipeline.addLast("jaggrab-decoder", new JagGrabRequestDecoder());
|
||||
|
||||
// encoders
|
||||
pipeline.addLast("jaggrab-encoder", new JagGrabResponseEncoder());
|
||||
|
||||
// handler
|
||||
pipeline.addLast("timeout", new IdleStateHandler(timer, NetworkConstants.IDLE_TIME, 0, 0));
|
||||
pipeline.addLast("handler", handler);
|
||||
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package org.apollo.jagcached.net;
|
||||
|
||||
/**
|
||||
* A class which holds network-related constants.
|
||||
* @author Graham
|
||||
*/
|
||||
public final class NetworkConstants {
|
||||
|
||||
/**
|
||||
* The HTTP port.
|
||||
*/
|
||||
public static final int HTTP_PORT = 80;
|
||||
|
||||
/**
|
||||
* The JAGGRAB port.
|
||||
*/
|
||||
public static final int JAGGRAB_PORT = 43595;
|
||||
|
||||
/**
|
||||
* The service port (which is also used for the 'on-demand' protocol).
|
||||
*/
|
||||
public static final int SERVICE_PORT = 43596;
|
||||
|
||||
/**
|
||||
* The number of seconds a channel can be idle before being closed
|
||||
* automatically.
|
||||
*/
|
||||
public static final int IDLE_TIME = 15;
|
||||
|
||||
/**
|
||||
* Default private constructor to prevent instantiaton.
|
||||
*/
|
||||
private NetworkConstants() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package org.apollo.jagcached.net;
|
||||
|
||||
|
||||
import org.apollo.jagcached.net.ondemand.OnDemandRequestDecoder;
|
||||
import org.apollo.jagcached.net.ondemand.OnDemandResponseEncoder;
|
||||
import org.apollo.jagcached.net.service.ServiceRequestDecoder;
|
||||
import org.apollo.jagcached.net.service.ServiceResponseEncoder;
|
||||
import org.jboss.netty.channel.ChannelPipeline;
|
||||
import org.jboss.netty.channel.ChannelPipelineFactory;
|
||||
import org.jboss.netty.channel.Channels;
|
||||
import org.jboss.netty.handler.timeout.IdleStateHandler;
|
||||
import org.jboss.netty.util.Timer;
|
||||
|
||||
/**
|
||||
* A {@link ChannelPipelineFactory} for the 'on-demand' protocol.
|
||||
* @author Graham
|
||||
*/
|
||||
public final class OnDemandPipelineFactory implements ChannelPipelineFactory {
|
||||
|
||||
/**
|
||||
* The file server event handler.
|
||||
*/
|
||||
private final FileServerHandler handler;
|
||||
|
||||
/**
|
||||
* The timer used for idle checking.
|
||||
*/
|
||||
private final Timer timer;
|
||||
|
||||
/**
|
||||
* Creates an 'on-demand' pipeline factory.
|
||||
* @param handler The file server event handler.
|
||||
* @param timer The timer used for idle checking.
|
||||
*/
|
||||
public OnDemandPipelineFactory(FileServerHandler handler, Timer timer) {
|
||||
this.handler = handler;
|
||||
this.timer = timer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelPipeline getPipeline() throws Exception {
|
||||
ChannelPipeline pipeline = Channels.pipeline();
|
||||
|
||||
// decoders
|
||||
pipeline.addLast("serviceDecoder", new ServiceRequestDecoder());
|
||||
pipeline.addLast("decoder", new OnDemandRequestDecoder());
|
||||
|
||||
// encoders
|
||||
pipeline.addLast("serviceEncoder", new ServiceResponseEncoder());
|
||||
pipeline.addLast("encoder", new OnDemandResponseEncoder());
|
||||
|
||||
// handler
|
||||
pipeline.addLast("timeout", new IdleStateHandler(timer, NetworkConstants.IDLE_TIME, 0, 0));
|
||||
pipeline.addLast("handler", handler);
|
||||
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package org.apollo.jagcached.net.jaggrab;
|
||||
|
||||
/**
|
||||
* Represents the request for a single file using the JAGGRAB protocol.
|
||||
* @author Graham
|
||||
*/
|
||||
public final class JagGrabRequest {
|
||||
|
||||
/**
|
||||
* The path to the file.
|
||||
*/
|
||||
private final String filePath;
|
||||
|
||||
/**
|
||||
* Creates the request.
|
||||
* @param filePath The file path.
|
||||
*/
|
||||
public JagGrabRequest(String filePath) {
|
||||
this.filePath = filePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the file path.
|
||||
* @return The file path.
|
||||
*/
|
||||
public String getFilePath() {
|
||||
return filePath;
|
||||
}
|
||||
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
package org.apollo.jagcached.net.jaggrab;
|
||||
|
||||
import org.jboss.netty.channel.Channel;
|
||||
import org.jboss.netty.channel.ChannelHandlerContext;
|
||||
import org.jboss.netty.handler.codec.oneone.OneToOneDecoder;
|
||||
|
||||
/**
|
||||
* A {@link OneToOneDecoder} for the JAGGRAB protocol.
|
||||
* @author Graham
|
||||
*/
|
||||
public final class JagGrabRequestDecoder extends OneToOneDecoder {
|
||||
|
||||
@Override
|
||||
protected Object decode(ChannelHandlerContext ctx, Channel c, Object msg) throws Exception {
|
||||
if (msg instanceof String) {
|
||||
String str = ((String) msg);
|
||||
if (str.startsWith("JAGGRAB /")) {
|
||||
String filePath = str.substring(8).trim();
|
||||
return new JagGrabRequest(filePath);
|
||||
} else {
|
||||
throw new Exception("corrupted request line");
|
||||
}
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package org.apollo.jagcached.net.jaggrab;
|
||||
|
||||
import org.jboss.netty.buffer.ChannelBuffer;
|
||||
|
||||
/**
|
||||
* Represents a single JAGGRAB reponse.
|
||||
* @author Graham
|
||||
*/
|
||||
public final class JagGrabResponse {
|
||||
|
||||
/**
|
||||
* The file data.
|
||||
*/
|
||||
private final ChannelBuffer fileData;
|
||||
|
||||
/**
|
||||
* Creates the response.
|
||||
* @param fileData The file data.
|
||||
*/
|
||||
public JagGrabResponse(ChannelBuffer fileData) {
|
||||
this.fileData = fileData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the file data.
|
||||
* @return The file data.
|
||||
*/
|
||||
public ChannelBuffer getFileData() {
|
||||
return fileData;
|
||||
}
|
||||
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
package org.apollo.jagcached.net.jaggrab;
|
||||
|
||||
import org.jboss.netty.channel.Channel;
|
||||
import org.jboss.netty.channel.ChannelHandlerContext;
|
||||
import org.jboss.netty.handler.codec.oneone.OneToOneEncoder;
|
||||
|
||||
/**
|
||||
* A {@link OneToOneEncoder} for the JAGGRAB protocol.
|
||||
* @author Graham
|
||||
*/
|
||||
public final class JagGrabResponseEncoder extends OneToOneEncoder {
|
||||
|
||||
@Override
|
||||
protected Object encode(ChannelHandlerContext ctx, Channel c, Object msg) throws Exception {
|
||||
if (msg instanceof JagGrabResponse) {
|
||||
JagGrabResponse resp = (JagGrabResponse) msg;
|
||||
return resp.getFileData();
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
package org.apollo.jagcached.net.ondemand;
|
||||
|
||||
import org.apollo.jagcached.fs.FileDescriptor;
|
||||
|
||||
/**
|
||||
* Represents a single 'on-demand' request.
|
||||
* @author Graham
|
||||
* @author Ryley Kimmel <ryley.kimmel@live.com>
|
||||
*/
|
||||
public final class OnDemandRequest implements Comparable<OnDemandRequest> {
|
||||
|
||||
/**
|
||||
* An enumeration containing the different request priorities.
|
||||
* @author Graham
|
||||
*/
|
||||
public enum Priority {
|
||||
|
||||
/**
|
||||
* High priority - used in-game when data is required immediately but
|
||||
* has not yet been received.
|
||||
*/
|
||||
HIGH,
|
||||
|
||||
/**
|
||||
* Medium priority - used while loading the 'bare minimum' required to
|
||||
* run the game.
|
||||
*/
|
||||
MEDIUM,
|
||||
|
||||
/**
|
||||
* Low priority - used when a file is not required urgently. The client
|
||||
* login screen says "loading extra files.." when low priority loading
|
||||
* is being performed.
|
||||
*/
|
||||
LOW;
|
||||
|
||||
/**
|
||||
* Converts the integer value to a priority.
|
||||
* @param v The integer value.
|
||||
* @return The priority.
|
||||
* @throws IllegalArgumentException if the value is outside of the
|
||||
* range 1-3 inclusive.
|
||||
*/
|
||||
public static Priority valueOf(int v) {
|
||||
switch (v) {
|
||||
case 0:
|
||||
return HIGH;
|
||||
case 1:
|
||||
return MEDIUM;
|
||||
case 2:
|
||||
return LOW;
|
||||
default:
|
||||
throw new IllegalArgumentException("priority out of range");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The file descriptor.
|
||||
*/
|
||||
private final FileDescriptor fileDescriptor;
|
||||
|
||||
/**
|
||||
* The request priority.
|
||||
*/
|
||||
private final Priority priority;
|
||||
|
||||
/**
|
||||
* Creates the 'on-demand' request.
|
||||
* @param fileDescriptor The file descriptor.
|
||||
* @param priority The priority.
|
||||
*/
|
||||
public OnDemandRequest(FileDescriptor fileDescriptor, Priority priority) {
|
||||
this.fileDescriptor = fileDescriptor;
|
||||
this.priority = priority;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the file descriptor.
|
||||
* @return The file descriptor.
|
||||
*/
|
||||
public FileDescriptor getFileDescriptor() {
|
||||
return fileDescriptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the priority.
|
||||
* @return The priority.
|
||||
*/
|
||||
public Priority getPriority() {
|
||||
return priority;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(OnDemandRequest o) {
|
||||
int thisPriority = priority.ordinal();
|
||||
int otherPriority = o.priority.ordinal();
|
||||
|
||||
if (thisPriority < otherPriority) {
|
||||
return 1;
|
||||
} else if (thisPriority == otherPriority) {
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
package org.apollo.jagcached.net.ondemand;
|
||||
|
||||
|
||||
import org.apollo.jagcached.fs.FileDescriptor;
|
||||
import org.apollo.jagcached.net.ondemand.OnDemandRequest.Priority;
|
||||
import org.jboss.netty.buffer.ChannelBuffer;
|
||||
import org.jboss.netty.channel.Channel;
|
||||
import org.jboss.netty.channel.ChannelHandlerContext;
|
||||
import org.jboss.netty.handler.codec.frame.FrameDecoder;
|
||||
|
||||
/**
|
||||
* A {@link FrameDecoder} for the 'on-demand' protocol.
|
||||
* @author Graham
|
||||
*/
|
||||
public final class OnDemandRequestDecoder extends FrameDecoder {
|
||||
|
||||
@Override
|
||||
protected Object decode(ChannelHandlerContext ctx, Channel c, ChannelBuffer buf) throws Exception {
|
||||
if (buf.readableBytes() >= 4) {
|
||||
int type = buf.readUnsignedByte() + 1;
|
||||
int file = buf.readUnsignedShort();
|
||||
int priority = buf.readUnsignedByte();
|
||||
|
||||
FileDescriptor desc = new FileDescriptor(type, file);
|
||||
Priority p = Priority.valueOf(priority);
|
||||
|
||||
return new OnDemandRequest(desc, p);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package org.apollo.jagcached.net.ondemand;
|
||||
|
||||
|
||||
import org.apollo.jagcached.fs.FileDescriptor;
|
||||
import org.jboss.netty.buffer.ChannelBuffer;
|
||||
|
||||
/**
|
||||
* Represents a single 'on-demand' response.
|
||||
* @author Graham
|
||||
*/
|
||||
public final class OnDemandResponse {
|
||||
|
||||
/**
|
||||
* The file descriptor.
|
||||
*/
|
||||
private final FileDescriptor fileDescriptor;
|
||||
|
||||
/**
|
||||
* The file size.
|
||||
*/
|
||||
private final int fileSize;
|
||||
|
||||
/**
|
||||
* The chunk id.
|
||||
*/
|
||||
private final int chunkId;
|
||||
|
||||
/**
|
||||
* The chunk data.
|
||||
*/
|
||||
private final ChannelBuffer chunkData;
|
||||
|
||||
/**
|
||||
* Creates the 'on-demand' response.
|
||||
* @param fileDescriptor The file descriptor.
|
||||
* @param fileSize The file size.
|
||||
* @param chunkId The chunk id.
|
||||
* @param chunkData The chunk data.
|
||||
*/
|
||||
public OnDemandResponse(FileDescriptor fileDescriptor, int fileSize, int chunkId, ChannelBuffer chunkData) {
|
||||
this.fileDescriptor = fileDescriptor;
|
||||
this.fileSize = fileSize;
|
||||
this.chunkId = chunkId;
|
||||
this.chunkData = chunkData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the file descriptor.
|
||||
* @return The file descriptor.
|
||||
*/
|
||||
public FileDescriptor getFileDescriptor() {
|
||||
return fileDescriptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the file size.
|
||||
* @return The file size.
|
||||
*/
|
||||
public int getFileSize() {
|
||||
return fileSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the chunk id.
|
||||
* @return The chunk id.
|
||||
*/
|
||||
public int getChunkId() {
|
||||
return chunkId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the chunk data.
|
||||
* @return The chunk data.
|
||||
*/
|
||||
public ChannelBuffer getChunkData() {
|
||||
return chunkData;
|
||||
}
|
||||
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
package org.apollo.jagcached.net.ondemand;
|
||||
|
||||
|
||||
import org.apollo.jagcached.fs.FileDescriptor;
|
||||
import org.jboss.netty.buffer.ChannelBuffer;
|
||||
import org.jboss.netty.buffer.ChannelBuffers;
|
||||
import org.jboss.netty.channel.Channel;
|
||||
import org.jboss.netty.channel.ChannelHandlerContext;
|
||||
import org.jboss.netty.handler.codec.oneone.OneToOneEncoder;
|
||||
|
||||
/**
|
||||
* A {@link OneToOneEncoder} for the 'on-demand' protocol.
|
||||
* @author Graham
|
||||
*/
|
||||
public final class OnDemandResponseEncoder extends OneToOneEncoder {
|
||||
|
||||
@Override
|
||||
protected Object encode(ChannelHandlerContext ctx, Channel c, Object msg) throws Exception {
|
||||
if (msg instanceof OnDemandResponse) {
|
||||
OnDemandResponse resp = (OnDemandResponse) msg;
|
||||
|
||||
FileDescriptor fileDescriptor = resp.getFileDescriptor();
|
||||
int fileSize = resp.getFileSize();
|
||||
int chunkId = resp.getChunkId();
|
||||
ChannelBuffer chunkData = resp.getChunkData();
|
||||
|
||||
ChannelBuffer buf = ChannelBuffers.buffer(6 + chunkData.readableBytes());
|
||||
buf.writeByte(fileDescriptor.getType() - 1);
|
||||
buf.writeShort(fileDescriptor.getFile());
|
||||
buf.writeShort(fileSize);
|
||||
buf.writeByte(chunkId);
|
||||
buf.writeBytes(chunkData);
|
||||
|
||||
return buf;
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package org.apollo.jagcached.net.service;
|
||||
|
||||
/**
|
||||
* Represents a service request message.
|
||||
* @author Graham
|
||||
*/
|
||||
public final class ServiceRequest {
|
||||
|
||||
/**
|
||||
* The game service id.
|
||||
*/
|
||||
public static final int SERVICE_GAME = 14;
|
||||
|
||||
/**
|
||||
* The 'on-demand' service id.
|
||||
*/
|
||||
public static final int SERVICE_ONDEMAND = 15;
|
||||
|
||||
/**
|
||||
* The service id.
|
||||
*/
|
||||
private final int id;
|
||||
|
||||
/**
|
||||
* Creates a service request.
|
||||
* @param id The service id.
|
||||
*/
|
||||
public ServiceRequest(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the service id.
|
||||
* @return The service id.
|
||||
*/
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
package org.apollo.jagcached.net.service;
|
||||
|
||||
import org.jboss.netty.buffer.ChannelBuffer;
|
||||
import org.jboss.netty.channel.Channel;
|
||||
import org.jboss.netty.channel.ChannelHandlerContext;
|
||||
import org.jboss.netty.channel.ChannelPipeline;
|
||||
import org.jboss.netty.handler.codec.frame.FrameDecoder;
|
||||
|
||||
/**
|
||||
* A {@link FrameDecoder} which decodes {@link ServiceRequest} messages.
|
||||
* @author Graham
|
||||
*/
|
||||
public final class ServiceRequestDecoder extends FrameDecoder {
|
||||
|
||||
/**
|
||||
* Creates the decoder, enabling the 'unfold' mechanism.
|
||||
*/
|
||||
public ServiceRequestDecoder() {
|
||||
super(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object decode(ChannelHandlerContext ctx, Channel c, ChannelBuffer buf) throws Exception {
|
||||
if (buf.readable()) {
|
||||
ServiceRequest request = new ServiceRequest(buf.readUnsignedByte());
|
||||
|
||||
ChannelPipeline pipeline = ctx.getPipeline();
|
||||
pipeline.remove(this);
|
||||
|
||||
if (buf.readable()) {
|
||||
return new Object[] { request, buf.readBytes(buf.readableBytes()) };
|
||||
} else {
|
||||
return request;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package org.apollo.jagcached.net.service;
|
||||
|
||||
/**
|
||||
* Represents a response to a service request.
|
||||
* @author Graham
|
||||
*/
|
||||
public final class ServiceResponse {
|
||||
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
package org.apollo.jagcached.net.service;
|
||||
|
||||
import org.jboss.netty.buffer.ChannelBuffer;
|
||||
import org.jboss.netty.buffer.ChannelBuffers;
|
||||
import org.jboss.netty.channel.Channel;
|
||||
import org.jboss.netty.channel.ChannelHandlerContext;
|
||||
import org.jboss.netty.handler.codec.oneone.OneToOneEncoder;
|
||||
|
||||
/**
|
||||
* A {@link OneToOneEncoder} which encodes {@link ServiceResponse} messages.
|
||||
* @author Graham
|
||||
*/
|
||||
public final class ServiceResponseEncoder extends OneToOneEncoder {
|
||||
|
||||
@Override
|
||||
protected Object encode(ChannelHandlerContext ctx, Channel c, Object msg) throws Exception {
|
||||
if (msg instanceof ServiceResponse) {
|
||||
ChannelBuffer buf = ChannelBuffers.buffer(8);
|
||||
buf.writeLong(0);
|
||||
return buf;
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user