mirror of
https://github.com/2006-Scape/apollo.git
synced 2026-07-05 08:40:08 +00:00
Verify CRCs on login,
This commit is contained in:
@@ -122,8 +122,9 @@ public final class Server {
|
|||||||
public void init(String releaseClassName) throws Exception {
|
public void init(String releaseClassName) throws Exception {
|
||||||
Class<?> clazz = Class.forName(releaseClassName);
|
Class<?> clazz = Class.forName(releaseClassName);
|
||||||
Release release = (Release) clazz.newInstance();
|
Release release = (Release) clazz.newInstance();
|
||||||
|
int releaseNo = release.getReleaseNumber();
|
||||||
|
|
||||||
logger.info("Initialized release #" + release.getReleaseNumber() + ".");
|
logger.info("Initialized release #" + releaseNo + ".");
|
||||||
|
|
||||||
serviceBootstrap.group(loopGroup);
|
serviceBootstrap.group(loopGroup);
|
||||||
httpBootstrap.group(loopGroup);
|
httpBootstrap.group(loopGroup);
|
||||||
@@ -131,7 +132,8 @@ public final class Server {
|
|||||||
|
|
||||||
World world = new World();
|
World world = new World();
|
||||||
ServiceManager serviceManager = new ServiceManager(world);
|
ServiceManager serviceManager = new ServiceManager(world);
|
||||||
ServerContext context = new ServerContext(release, serviceManager);
|
IndexedFileSystem fs = new IndexedFileSystem(Paths.get("data/fs", Integer.toString(releaseNo)), true);
|
||||||
|
ServerContext context = new ServerContext(release, serviceManager, fs);
|
||||||
ApolloHandler handler = new ApolloHandler(context);
|
ApolloHandler handler = new ApolloHandler(context);
|
||||||
|
|
||||||
ChannelInitializer<SocketChannel> serviceInitializer = new ServiceChannelInitializer(handler);
|
ChannelInitializer<SocketChannel> serviceInitializer = new ServiceChannelInitializer(handler);
|
||||||
@@ -149,8 +151,6 @@ public final class Server {
|
|||||||
PluginManager manager = new PluginManager(world, new PluginContext(context));
|
PluginManager manager = new PluginManager(world, new PluginContext(context));
|
||||||
serviceManager.startAll();
|
serviceManager.startAll();
|
||||||
|
|
||||||
int releaseNo = release.getReleaseNumber();
|
|
||||||
IndexedFileSystem fs = new IndexedFileSystem(Paths.get("data/fs", Integer.toString(releaseNo)), true);
|
|
||||||
world.init(releaseNo, fs, manager);
|
world.init(releaseNo, fs, manager);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package org.apollo;
|
package org.apollo;
|
||||||
|
|
||||||
|
import org.apollo.fs.IndexedFileSystem;
|
||||||
import org.apollo.net.release.Release;
|
import org.apollo.net.release.Release;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -21,16 +22,22 @@ public final class ServerContext {
|
|||||||
*/
|
*/
|
||||||
private final ServiceManager serviceManager;
|
private final ServiceManager serviceManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The IndexedFileSystem.
|
||||||
|
*/
|
||||||
|
private final IndexedFileSystem fileSystem;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new server context.
|
* Creates a new server context.
|
||||||
*
|
*
|
||||||
* @param release The current release.
|
* @param release The current release.
|
||||||
* @param serviceManager The service manager.
|
* @param serviceManager The service manager.
|
||||||
*/
|
*/
|
||||||
ServerContext(Release release, ServiceManager serviceManager) {
|
ServerContext(Release release, ServiceManager serviceManager, IndexedFileSystem fileSystem) {
|
||||||
this.release = release;
|
this.release = release;
|
||||||
this.serviceManager = serviceManager;
|
this.serviceManager = serviceManager;
|
||||||
this.serviceManager.setContext(this);
|
this.serviceManager.setContext(this);
|
||||||
|
this.fileSystem = fileSystem;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -42,6 +49,15 @@ public final class ServerContext {
|
|||||||
return release;
|
return release;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the IndexeFileSystem
|
||||||
|
*
|
||||||
|
* @return The IndexedFileSystem.
|
||||||
|
*/
|
||||||
|
public IndexedFileSystem getFileSystem() {
|
||||||
|
return fileSystem;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a service. This method is shorthand for {@code getServiceManager().getService(...)}.
|
* Gets a service. This method is shorthand for {@code getServiceManager().getService(...)}.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ package org.apollo.login;
|
|||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
@@ -16,12 +18,11 @@ import org.apollo.net.codec.login.LoginRequest;
|
|||||||
import org.apollo.net.release.Release;
|
import org.apollo.net.release.Release;
|
||||||
import org.apollo.net.session.GameSession;
|
import org.apollo.net.session.GameSession;
|
||||||
import org.apollo.net.session.LoginSession;
|
import org.apollo.net.session.LoginSession;
|
||||||
|
import org.apollo.util.ThreadUtil;
|
||||||
import org.apollo.util.xml.XmlNode;
|
import org.apollo.util.xml.XmlNode;
|
||||||
import org.apollo.util.xml.XmlParser;
|
import org.apollo.util.xml.XmlParser;
|
||||||
import org.xml.sax.SAXException;
|
import org.xml.sax.SAXException;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The {@link LoginService} manages {@link LoginRequest}s.
|
* The {@link LoginService} manages {@link LoginRequest}s.
|
||||||
*
|
*
|
||||||
@@ -33,7 +34,7 @@ public final class LoginService extends Service {
|
|||||||
/**
|
/**
|
||||||
* The {@link ExecutorService} to which workers are submitted.
|
* The {@link ExecutorService} to which workers are submitted.
|
||||||
*/
|
*/
|
||||||
private final ExecutorService executor = Executors.newCachedThreadPool(new ThreadFactoryBuilder().setNameFormat("LoginService").build());
|
private final ExecutorService executor = Executors.newCachedThreadPool(ThreadUtil.build("LoginService"));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The current {@link PlayerSerializer}.
|
* The current {@link PlayerSerializer}.
|
||||||
@@ -79,9 +80,6 @@ public final class LoginService extends Service {
|
|||||||
this.serializer = (PlayerSerializer) clazz.getConstructor(World.class).newInstance(world);
|
this.serializer = (PlayerSerializer) clazz.getConstructor(World.class).newInstance(world);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Starts the login service.
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void start() {
|
public void start() {
|
||||||
|
|
||||||
@@ -92,15 +90,48 @@ public final class LoginService extends Service {
|
|||||||
*
|
*
|
||||||
* @param session The session submitting this request.
|
* @param session The session submitting this request.
|
||||||
* @param request The login request.
|
* @param request The login request.
|
||||||
|
* @throws IOException If some I/O exception occurs.
|
||||||
*/
|
*/
|
||||||
public void submitLoadRequest(LoginSession session, LoginRequest request) {
|
public void submitLoadRequest(LoginSession session, LoginRequest request) throws IOException {
|
||||||
|
int response = LoginConstants.STATUS_OK;
|
||||||
|
|
||||||
|
if (requiresUpdate(session, request)) {
|
||||||
|
response = LoginConstants.STATUS_GAME_UPDATED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response == LoginConstants.STATUS_OK) {
|
||||||
|
executor.submit(new PlayerLoaderWorker(serializer, session, request));
|
||||||
|
} else {
|
||||||
|
session.handlePlayerLoaderResponse(request, new PlayerLoaderResponse(response));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if an update is required whenever a {@link Player} submits a login request.
|
||||||
|
*
|
||||||
|
* @param session The login session.
|
||||||
|
* @param request The login request.
|
||||||
|
* @return {@code true} if an update is required, otherwise return {@code false}.
|
||||||
|
* @throws IOException If some I/O exception occurs.
|
||||||
|
*/
|
||||||
|
private boolean requiresUpdate(LoginSession session, LoginRequest request) throws IOException {
|
||||||
Release release = session.getRelease();
|
Release release = session.getRelease();
|
||||||
if (release.getReleaseNumber() != request.getReleaseNumber()) {
|
if (release.getReleaseNumber() != request.getReleaseNumber()) {
|
||||||
// TODO check archive 0 CRCs
|
return true;
|
||||||
session.handlePlayerLoaderResponse(request, new PlayerLoaderResponse(LoginConstants.STATUS_GAME_UPDATED));
|
|
||||||
} else {
|
|
||||||
executor.submit(new PlayerLoaderWorker(serializer, session, request));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ByteBuffer buffer = getContext().getFileSystem().getCrcTable();
|
||||||
|
|
||||||
|
int[] clientCrcs = request.getArchiveCrcs();
|
||||||
|
int[] serverCrcs = new int[clientCrcs.length];
|
||||||
|
|
||||||
|
Arrays.setAll(serverCrcs, crc -> buffer.getInt());
|
||||||
|
|
||||||
|
if (Arrays.equals(clientCrcs, serverCrcs)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ public final class ApolloHandler extends ChannelInboundHandlerAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void channelRead(ChannelHandlerContext ctx, Object message) {
|
public void channelRead(ChannelHandlerContext ctx, Object message) throws Exception {
|
||||||
try {
|
try {
|
||||||
Attribute<Session> attribute = ctx.attr(NetworkConstants.SESSION_KEY);
|
Attribute<Session> attribute = ctx.attr(NetworkConstants.SESSION_KEY);
|
||||||
Session session = attribute.get();
|
Session session = attribute.get();
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import io.netty.channel.ChannelFuture;
|
|||||||
import io.netty.channel.ChannelFutureListener;
|
import io.netty.channel.ChannelFutureListener;
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import org.apollo.ServerContext;
|
import org.apollo.ServerContext;
|
||||||
@@ -72,8 +73,9 @@ public final class LoginSession extends Session {
|
|||||||
* Handles a login request.
|
* Handles a login request.
|
||||||
*
|
*
|
||||||
* @param request The login request.
|
* @param request The login request.
|
||||||
|
* @throws IOException If some I/O exception occurs.
|
||||||
*/
|
*/
|
||||||
private void handleLoginRequest(LoginRequest request) {
|
private void handleLoginRequest(LoginRequest request) throws IOException {
|
||||||
LoginService loginService = serverContext.getService(LoginService.class);
|
LoginService loginService = serverContext.getService(LoginService.class);
|
||||||
loginService.submitLoadRequest(this, request);
|
loginService.submitLoadRequest(this, request);
|
||||||
}
|
}
|
||||||
@@ -135,7 +137,7 @@ public final class LoginSession extends Session {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void messageReceived(Object message) {
|
public void messageReceived(Object message) throws Exception {
|
||||||
if (message.getClass() == LoginRequest.class) {
|
if (message.getClass() == LoginRequest.class) {
|
||||||
handleLoginRequest((LoginRequest) message);
|
handleLoginRequest((LoginRequest) message);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,7 +42,8 @@ public abstract class Session {
|
|||||||
* Processes a message received from the channel.
|
* Processes a message received from the channel.
|
||||||
*
|
*
|
||||||
* @param message The message.
|
* @param message The message.
|
||||||
|
* @throws Exception If some error occurs.
|
||||||
*/
|
*/
|
||||||
public abstract void messageReceived(Object message);
|
public abstract void messageReceived(Object message) throws Exception;
|
||||||
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user