* Got the basics working
This commit is contained in:
parent
6c07fd17d4
commit
98ae84bf58
|
|
@ -88,4 +88,10 @@ public class SharedProxy {
|
|||
return FMLServerHandler.instance().getServer();
|
||||
}
|
||||
|
||||
public void setMiniservClientPort(int port) {
|
||||
}
|
||||
|
||||
public void startMiniServClient() {
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,9 +22,7 @@ import net.minecraftforge.event.entity.item.ItemTossEvent;
|
|||
import net.minecraftforge.event.world.WorldEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.common.SidedProxy;
|
||||
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
|
||||
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
|
||||
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
|
||||
import net.minecraftforge.fml.common.event.*;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.gameevent.PlayerEvent;
|
||||
import net.minecraftforge.fml.common.network.NetworkRegistry;
|
||||
|
|
@ -36,6 +34,9 @@ import net.montoyo.wd.block.BlockScreen;
|
|||
import net.montoyo.wd.core.*;
|
||||
import net.montoyo.wd.entity.TileEntityScreen;
|
||||
import net.montoyo.wd.item.*;
|
||||
import net.montoyo.wd.miniserv.client.Client;
|
||||
import net.montoyo.wd.miniserv.server.Server;
|
||||
import net.montoyo.wd.net.CMessageServerInfo;
|
||||
import net.montoyo.wd.net.Messages;
|
||||
import net.montoyo.wd.utilities.Log;
|
||||
import net.montoyo.wd.utilities.Util;
|
||||
|
|
@ -183,7 +184,8 @@ public class WebDisplays {
|
|||
if(ev.getWorld().isRemote || ev.getWorld().provider.getDimension() != 0)
|
||||
return;
|
||||
|
||||
File f = new File(ev.getWorld().getSaveHandler().getWorldDirectory(), "wd_next.txt");
|
||||
File worldDir = ev.getWorld().getSaveHandler().getWorldDirectory();
|
||||
File f = new File(worldDir, "wd_next.txt");
|
||||
|
||||
if(f.exists()) {
|
||||
try {
|
||||
|
|
@ -203,6 +205,10 @@ public class WebDisplays {
|
|||
Log.warningEx("Could not read last minePad ID from %s. I'm afraid this might break all minePads.", t, f.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
Server sv = Server.getInstance();
|
||||
sv.setDirectory(new File(worldDir, "wd_filehost"));
|
||||
sv.start(); //TODO: Configure port
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
|
|
@ -254,6 +260,23 @@ public class WebDisplays {
|
|||
}
|
||||
}
|
||||
|
||||
@Mod.EventHandler
|
||||
public void onServerStop(FMLServerStoppingEvent ev) {
|
||||
Server.getInstance().stopServer();
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void onLogIn(PlayerEvent.PlayerLoggedInEvent ev) {
|
||||
if(!ev.player.world.isRemote && ev.player instanceof EntityPlayerMP)
|
||||
WebDisplays.NET_HANDLER.sendTo(new CMessageServerInfo(25566), (EntityPlayerMP) ev.player); //TODO: Port config
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void onLogOut(PlayerEvent.PlayerLoggedOutEvent ev) {
|
||||
if(!ev.player.world.isRemote)
|
||||
Server.getInstance().getClientManager().revokeClientKey(ev.player.getGameProfile().getId());
|
||||
}
|
||||
|
||||
private boolean hasPlayerAdvancement(EntityPlayerMP ply, ResourceLocation rl) {
|
||||
MinecraftServer server = PROXY.getServer();
|
||||
if(server == null)
|
||||
|
|
|
|||
|
|
@ -52,12 +52,15 @@ import net.montoyo.wd.core.JSServerRequest;
|
|||
import net.montoyo.wd.data.GuiData;
|
||||
import net.montoyo.wd.entity.TileEntityScreen;
|
||||
import net.montoyo.wd.item.ItemMulti;
|
||||
import net.montoyo.wd.miniserv.client.Client;
|
||||
import net.montoyo.wd.net.SMessagePadCtrl;
|
||||
import net.montoyo.wd.net.SMessageScreenCtrl;
|
||||
import net.montoyo.wd.utilities.*;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.lang.reflect.Field;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.util.*;
|
||||
|
||||
public class ClientProxy extends SharedProxy implements IResourceManagerReloadListener, IDisplayHandler, IJSQueryHandler {
|
||||
|
|
@ -84,6 +87,8 @@ public class ClientProxy extends SharedProxy implements IResourceManagerReloadLi
|
|||
private MinePadRenderer minePadRenderer;
|
||||
private JSQueryDispatcher jsDispatcher;
|
||||
private LaserPointerRenderer laserPointerRenderer;
|
||||
private int miniservPort;
|
||||
private boolean msClientStarted;
|
||||
|
||||
//Client-side advancement hack
|
||||
private final Field advancementToProgressField = findAdvancementToProgressField();
|
||||
|
|
@ -295,6 +300,34 @@ public class ClientProxy extends SharedProxy implements IResourceManagerReloadLi
|
|||
q.error(errCode, err);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMiniservClientPort(int port) {
|
||||
miniservPort = port;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startMiniServClient() {
|
||||
if(miniservPort <= 0) {
|
||||
Log.warning("Can't start miniserv client: miniserv is disabled");
|
||||
return;
|
||||
}
|
||||
|
||||
if(mc.player == null) {
|
||||
Log.warning("Can't start miniserv client: player is null");
|
||||
return;
|
||||
}
|
||||
|
||||
SocketAddress saddr = mc.player.connection.getNetworkManager().channel().remoteAddress();
|
||||
if(saddr == null || !(saddr instanceof InetSocketAddress)) {
|
||||
Log.warning("Miniserv client: remote address is not inet, assuming local address");
|
||||
saddr = new InetSocketAddress("127.0.0.1", 1234);
|
||||
}
|
||||
|
||||
InetSocketAddress msAddr = new InetSocketAddress(((InetSocketAddress) saddr).getAddress(), miniservPort);
|
||||
Client.getInstance().start(msAddr);
|
||||
msClientStarted = true;
|
||||
}
|
||||
|
||||
/**************************************** RESOURCE MANAGER METHODS ****************************************/
|
||||
|
||||
@Override
|
||||
|
|
@ -507,6 +540,12 @@ public class ClientProxy extends SharedProxy implements IResourceManagerReloadLi
|
|||
|
||||
//Handle JS queries
|
||||
jsDispatcher.handleQueries();
|
||||
|
||||
//Stop miniserv client
|
||||
if(mc.player == null && msClientStarted) {
|
||||
msClientStarted = false;
|
||||
Client.getInstance().stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
112
src/main/java/net/montoyo/wd/client/WDScheme.java
Normal file
112
src/main/java/net/montoyo/wd/client/WDScheme.java
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* Copyright (C) 2018 BARBOTIN Nicolas
|
||||
*/
|
||||
|
||||
package net.montoyo.wd.client;
|
||||
|
||||
import net.montoyo.mcef.api.IScheme;
|
||||
import net.montoyo.mcef.api.ISchemeResponseData;
|
||||
import net.montoyo.mcef.api.ISchemeResponseHeaders;
|
||||
import net.montoyo.mcef.api.SchemePreResponse;
|
||||
import net.montoyo.wd.WebDisplays;
|
||||
import net.montoyo.wd.miniserv.Constants;
|
||||
import net.montoyo.wd.miniserv.client.Client;
|
||||
import net.montoyo.wd.miniserv.client.ClientTaskGetFile;
|
||||
import net.montoyo.wd.utilities.Util;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class WDScheme implements IScheme {
|
||||
|
||||
private ClientTaskGetFile task;
|
||||
|
||||
@Override
|
||||
public SchemePreResponse processRequest(String url) {
|
||||
url = url.substring("wd://".length());
|
||||
|
||||
int pos = url.indexOf('/');
|
||||
if(pos < 0)
|
||||
return SchemePreResponse.NOT_HANDLED;
|
||||
|
||||
String uuidStr = url.substring(0, pos);
|
||||
String fileStr = url.substring(pos + 1);
|
||||
|
||||
if(uuidStr.isEmpty() || Util.isFileNameInvalid(fileStr))
|
||||
return SchemePreResponse.NOT_HANDLED;
|
||||
|
||||
UUID uuid;
|
||||
try {
|
||||
uuid = UUID.fromString(uuidStr);
|
||||
} catch(IllegalArgumentException ex) {
|
||||
return SchemePreResponse.NOT_HANDLED; //Invalid UUID
|
||||
}
|
||||
|
||||
task = new ClientTaskGetFile(uuid, fileStr);
|
||||
return Client.getInstance().addTask(task) ? SchemePreResponse.HANDLED_CONTINUE : SchemePreResponse.NOT_HANDLED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getResponseHeaders(ISchemeResponseHeaders resp) {
|
||||
int status = task.waitForResponse();
|
||||
|
||||
if(status == 0) {
|
||||
//OK
|
||||
int extPos = task.getFileName().lastIndexOf('.');
|
||||
if(extPos >= 0) {
|
||||
String mime = ((ClientProxy) WebDisplays.PROXY).getMCEF().mimeTypeFromExtension(task.getFileName().substring(extPos + 1));
|
||||
|
||||
if(mime != null)
|
||||
resp.setMimeType(mime);
|
||||
}
|
||||
|
||||
resp.setStatus(200);
|
||||
resp.setStatusText("OK");
|
||||
resp.setResponseLength(-1);
|
||||
} else if(status == Constants.GETF_STATUS_NOT_FOUND) {
|
||||
resp.setStatus(404);
|
||||
resp.setStatusText("Not Found");
|
||||
resp.setResponseLength(0);
|
||||
} else {
|
||||
resp.setStatus(500);
|
||||
resp.setStatusText("Internal Server Error");
|
||||
resp.setResponseLength(0);
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] dataToWrite;
|
||||
private int dataOffset;
|
||||
private int amountToWrite;
|
||||
|
||||
@Override
|
||||
public boolean readResponse(ISchemeResponseData data) {
|
||||
if(dataToWrite == null) {
|
||||
dataToWrite = task.waitForData();
|
||||
dataOffset = 3; //packet ID + size
|
||||
amountToWrite = task.getDataLength();
|
||||
|
||||
if(amountToWrite <= 0) {
|
||||
dataToWrite = null;
|
||||
data.setAmountRead(0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int toWrite = data.getBytesToRead();
|
||||
if(toWrite > amountToWrite)
|
||||
toWrite = amountToWrite;
|
||||
|
||||
System.arraycopy(dataToWrite, dataOffset, data.getDataArray(), 0, toWrite);
|
||||
data.setAmountRead(toWrite);
|
||||
|
||||
dataOffset += toWrite;
|
||||
amountToWrite -= toWrite;
|
||||
|
||||
if(amountToWrite <= 0) {
|
||||
task.nextData();
|
||||
dataToWrite = null;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -28,7 +28,7 @@ public abstract class AbstractClient {
|
|||
private final Method[] packetHandlers = new Method[PacketID.values().length];
|
||||
protected SocketChannel socket;
|
||||
protected Selector selector;
|
||||
private SelectionKey writeKey;
|
||||
protected SelectionKey selKey;
|
||||
|
||||
public AbstractClient() {
|
||||
sendBuffer.limit(0);
|
||||
|
|
@ -67,13 +67,17 @@ public abstract class AbstractClient {
|
|||
|
||||
if(pid >= packetHandlers.length)
|
||||
Log.error("Caught invalid packet ID %d", pid);
|
||||
else if(packetHandlers[pid] != null) {
|
||||
try {
|
||||
packetHandlers[pid].invoke(this, dis); //This is slow, I know... sorry
|
||||
} catch(IllegalAccessException ex) {
|
||||
Log.errorEx("This shouldn't have happened", ex);
|
||||
} catch(InvocationTargetException ex) {
|
||||
Log.warningEx("Caught exception while handling packet %d", ex.getTargetException(), pid);
|
||||
else {
|
||||
Log.info("Received PID %s", PacketID.fromInt(pid).toString());
|
||||
|
||||
if(packetHandlers[pid] != null) {
|
||||
try {
|
||||
packetHandlers[pid].invoke(this, dis); //This is slow, I know... sorry
|
||||
} catch(IllegalAccessException ex) {
|
||||
Log.errorEx("This shouldn't have happened", ex);
|
||||
} catch(InvocationTargetException ex) {
|
||||
Log.warningEx("Caught exception while handling packet %d", ex.getTargetException(), pid);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch(IOException ex) {
|
||||
|
|
@ -88,8 +92,13 @@ public abstract class AbstractClient {
|
|||
|
||||
public void readyWrite() throws Throwable {
|
||||
if(sendBuffer.remaining() > 0 || fillSendBuffer()) {
|
||||
if(socket.write(sendBuffer) < 0)
|
||||
int sent = socket.write(sendBuffer);
|
||||
Log.info("Sent %d bytes", sent);
|
||||
|
||||
if(sent < 0) {
|
||||
Log.error("Error when sending data");
|
||||
onWriteError();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -103,12 +112,8 @@ public abstract class AbstractClient {
|
|||
pkt = sendQueue.poll();
|
||||
|
||||
if(pkt == null) {
|
||||
if(writeKey != null) {
|
||||
writeKey.cancel();
|
||||
writeKey = null;
|
||||
}
|
||||
|
||||
return sendBuffer.remaining() > 0;
|
||||
selKey.interestOps(SelectionKey.OP_READ); //Remove write op
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -116,19 +121,19 @@ public abstract class AbstractClient {
|
|||
}
|
||||
} while(sendBuffer.remaining() > 0);
|
||||
|
||||
return true;
|
||||
int pos = sendBuffer.position();
|
||||
sendBuffer.position(0);
|
||||
sendBuffer.limit(pos);
|
||||
return pos > 0;
|
||||
}
|
||||
|
||||
public void sendPacket(OutgoingPacket pkt) {
|
||||
synchronized(sendQueue) {
|
||||
sendQueue.offer(pkt);
|
||||
|
||||
if(writeKey == null) {
|
||||
try {
|
||||
writeKey = socket.register(selector, SelectionKey.OP_WRITE);
|
||||
} catch(ClosedChannelException ex) {
|
||||
Log.warningEx("Couldn't send packet", ex);
|
||||
}
|
||||
if((selKey.interestOps() & SelectionKey.OP_WRITE) == 0) {
|
||||
selKey.interestOps(SelectionKey.OP_READ | SelectionKey.OP_WRITE);
|
||||
selector.wakeup(); //Is this needed?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -149,4 +154,11 @@ public abstract class AbstractClient {
|
|||
return packetReader.getPacketData();
|
||||
}
|
||||
|
||||
protected void clearSendQueue() {
|
||||
synchronized(sendQueue) {
|
||||
packetWriter.clear();
|
||||
sendQueue.clear();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
24
src/main/java/net/montoyo/wd/miniserv/Constants.java
Normal file
24
src/main/java/net/montoyo/wd/miniserv/Constants.java
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Copyright (C) 2018 BARBOTIN Nicolas
|
||||
*/
|
||||
|
||||
package net.montoyo.wd.miniserv;
|
||||
|
||||
public abstract class Constants {
|
||||
|
||||
public static int FUPA_STATUS_BAD_NAME = 1;
|
||||
public static int FUPA_STATUS_INVALID_SIZE = 2;
|
||||
public static int FUPA_STATUS_EXCEEDS_QUOTA = 3;
|
||||
public static int FUPA_STATUS_OCCUPIED = 4;
|
||||
public static int FUPA_STATUS_FILE_EXISTS = 5;
|
||||
public static int FUPA_STATUS_INTERNAL_ERROR = 6;
|
||||
public static int FUPA_STATUS_USER_ABORT = 7;
|
||||
public static int FUPA_STATUS_LIER = 8;
|
||||
public static int FUPA_STATUS_CONNECTION_LOST = 9;
|
||||
|
||||
public static int GETF_STATUS_BAD_NAME = 1;
|
||||
public static int GETF_STATUS_NOT_FOUND = 2;
|
||||
public static int GETF_STATUS_INTERNAL_ERROR = 3;
|
||||
public static int GETF_STATUS_CONNECTION_LOST = 4;
|
||||
|
||||
}
|
||||
|
|
@ -18,6 +18,12 @@ public final class OutgoingPacket {
|
|||
dos = new DataOutputStream(baos);
|
||||
}
|
||||
|
||||
public final void writeLong(long l) {
|
||||
try {
|
||||
dos.writeLong(l);
|
||||
} catch(IOException ex) {}
|
||||
}
|
||||
|
||||
public final void writeInt(int i) {
|
||||
try {
|
||||
dos.writeInt(i);
|
||||
|
|
|
|||
|
|
@ -28,12 +28,16 @@ public final class PacketReader {
|
|||
return true; //Abort packet reading
|
||||
}
|
||||
|
||||
packetSize -= 4;
|
||||
packetData = new byte[packetSize];
|
||||
Log.info("Awaiting packet of size %d", packetSize);
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
|
||||
return readByteArray(packetData, buf);
|
||||
boolean ret = readByteArray(packetData, buf);
|
||||
Log.info("Read %d out of %d, ok = %s", pos, packetData.length, ret ? "true" : "false");
|
||||
return ret;
|
||||
}
|
||||
|
||||
private boolean readByteArray(byte[] dst, ByteBuffer src) {
|
||||
|
|
|
|||
|
|
@ -53,4 +53,10 @@ public final class PacketWriter {
|
|||
needToWriteSize = true;
|
||||
}
|
||||
|
||||
public final void clear() {
|
||||
packet = null;
|
||||
pos = 0;
|
||||
needToWriteSize = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
package net.montoyo.wd.miniserv.client;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.montoyo.wd.miniserv.*;
|
||||
import net.montoyo.wd.net.SMessageMiniservConnect;
|
||||
import net.montoyo.wd.utilities.Log;
|
||||
|
|
@ -20,6 +21,8 @@ import java.nio.channels.Selector;
|
|||
import java.nio.channels.SocketChannel;
|
||||
import java.security.*;
|
||||
import java.security.interfaces.RSAPublicKey;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.UUID;
|
||||
|
||||
public class Client extends AbstractClient implements Runnable {
|
||||
|
||||
|
|
@ -36,10 +39,14 @@ public class Client extends AbstractClient implements Runnable {
|
|||
private KeyPair keyPair;
|
||||
private byte[] key;
|
||||
private SocketAddress address;
|
||||
private boolean running = true;
|
||||
private volatile boolean running;
|
||||
private volatile boolean connected;
|
||||
private final ByteBuffer readBuffer = ByteBuffer.allocateDirect(8192);
|
||||
private final Thread thread = new Thread(this);
|
||||
private boolean authenticated = false;
|
||||
private volatile Thread thread;
|
||||
private final UUID clientUUID = Minecraft.getMinecraft().player.getGameProfile().getId();
|
||||
private final ArrayDeque<ClientTask> tasks = new ArrayDeque<>();
|
||||
private ClientTask currentTask;
|
||||
private volatile boolean authenticated;
|
||||
|
||||
public SMessageMiniservConnect beginConnection() {
|
||||
if(keyPair == null) {
|
||||
|
|
@ -74,7 +81,7 @@ public class Client extends AbstractClient implements Runnable {
|
|||
return false;
|
||||
}
|
||||
|
||||
public byte[] authenticate(byte[] challenge) {
|
||||
private byte[] authenticate(byte[] challenge) {
|
||||
try {
|
||||
Mac mac = Mac.getInstance(KeyParameters.MAC_ALGORITHM);
|
||||
mac.init(new SecretKeySpec(key, KeyParameters.MAC_ALGORITHM));
|
||||
|
|
@ -89,25 +96,85 @@ public class Client extends AbstractClient implements Runnable {
|
|||
}
|
||||
|
||||
public void start(SocketAddress addr) {
|
||||
if(getRunning()) {
|
||||
Log.warning("Called Client.start() twice");
|
||||
return;
|
||||
}
|
||||
|
||||
address = addr;
|
||||
thread = new Thread(this);
|
||||
thread.setName("MiniServClient");
|
||||
thread.setDaemon(true);
|
||||
|
||||
synchronized(this) {
|
||||
running = true;
|
||||
connected = false;
|
||||
}
|
||||
|
||||
thread.start();
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
if(getRunning()) {
|
||||
Thread thread = this.thread;
|
||||
synchronized(this) {
|
||||
running = false;
|
||||
|
||||
if(connected)
|
||||
selector.wakeup();
|
||||
}
|
||||
|
||||
while(thread.isAlive()) {
|
||||
try {
|
||||
thread.join();
|
||||
} catch(InterruptedException ex) { }
|
||||
}
|
||||
|
||||
Log.info("Miniserv client stopped");
|
||||
}
|
||||
}
|
||||
|
||||
private boolean getRunning() {
|
||||
boolean ret;
|
||||
synchronized(this) {
|
||||
ret = running;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
selector = Selector.open();
|
||||
socket = SocketChannel.open();
|
||||
socket.connect(address);
|
||||
socket.configureBlocking(false);
|
||||
|
||||
selector = Selector.open();
|
||||
socket.register(selector, SelectionKey.OP_READ);
|
||||
selKey = socket.register(selector, SelectionKey.OP_READ);
|
||||
} catch(IOException ex) {
|
||||
Log.errorEx("Couldn't start client", ex);
|
||||
|
||||
synchronized(this) {
|
||||
running = false;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
while(running) {
|
||||
synchronized(this) {
|
||||
connected = true;
|
||||
}
|
||||
|
||||
Log.info("Miniserv client connected!");
|
||||
|
||||
OutgoingPacket connPacket = new OutgoingPacket();
|
||||
connPacket.writeByte(PacketID.INIT_CONN.ordinal());
|
||||
connPacket.writeLong(clientUUID.getMostSignificantBits());
|
||||
connPacket.writeLong(clientUUID.getLeastSignificantBits());
|
||||
sendPacket(connPacket);
|
||||
|
||||
while(getRunning()) {
|
||||
try {
|
||||
unsafeLoop();
|
||||
} catch(Throwable t) {
|
||||
|
|
@ -116,22 +183,51 @@ public class Client extends AbstractClient implements Runnable {
|
|||
}
|
||||
}
|
||||
|
||||
Util.silentClose(socket);
|
||||
synchronized(this) {
|
||||
connected = false;
|
||||
running = false;
|
||||
authenticated = false;
|
||||
}
|
||||
|
||||
Util.silentClose(selector);
|
||||
Util.silentClose(socket);
|
||||
selector = null;
|
||||
socket = null;
|
||||
|
||||
if(currentTask != null) {
|
||||
currentTask.abort();
|
||||
currentTask.onFinished();
|
||||
currentTask = null;
|
||||
}
|
||||
|
||||
synchronized(tasks) {
|
||||
ClientTask task;
|
||||
|
||||
while((task = tasks.poll()) != null) {
|
||||
task.abort();
|
||||
task.onFinished();
|
||||
}
|
||||
}
|
||||
|
||||
clearSendQueue();
|
||||
thread = null;
|
||||
}
|
||||
|
||||
private void unsafeLoop() throws Throwable {
|
||||
selector.select();
|
||||
|
||||
if(currentTask == null)
|
||||
nextTask();
|
||||
|
||||
for(SelectionKey key: selector.selectedKeys()) {
|
||||
if(key.isReadable()) {
|
||||
readBuffer.clear();
|
||||
int rd = socket.read(readBuffer);
|
||||
|
||||
if(rd <= 0) {
|
||||
if(rd < 0) {
|
||||
Log.warning("Connection was closed, stopping...");
|
||||
running = false;
|
||||
} else {
|
||||
} else if(rd > 0) {
|
||||
readBuffer.position(0);
|
||||
readBuffer.limit(rd);
|
||||
readyRead(readBuffer);
|
||||
|
|
@ -156,8 +252,78 @@ public class Client extends AbstractClient implements Runnable {
|
|||
}
|
||||
|
||||
@PacketHandler(PacketID.AUTHENTICATE)
|
||||
public void handleAuth(DataInputStream dis) {
|
||||
//TODO: Do some stuff
|
||||
public void handleAuth(DataInputStream dis) throws IOException {
|
||||
int len = dis.readByte();
|
||||
byte[] challenge = new byte[len];
|
||||
dis.readFully(challenge);
|
||||
byte[] mac = authenticate(challenge);
|
||||
|
||||
OutgoingPacket pkt = new OutgoingPacket();
|
||||
pkt.writeByte(PacketID.AUTHENTICATE.ordinal());
|
||||
pkt.writeByte(mac.length);
|
||||
pkt.writeBytes(mac);
|
||||
sendPacket(pkt);
|
||||
|
||||
Log.info("Miniserv client authenticated");
|
||||
|
||||
synchronized(this) {
|
||||
authenticated = true;
|
||||
}
|
||||
}
|
||||
|
||||
@PacketHandler(PacketID.BEGIN_FILE_UPLOAD)
|
||||
public void handleBeginUpload(DataInputStream dis) throws IOException {
|
||||
if(currentTask instanceof ClientTaskUploadFile)
|
||||
((ClientTaskUploadFile) currentTask).onReceivedUploadStatus(dis.readByte());
|
||||
}
|
||||
|
||||
@PacketHandler(PacketID.FILE_STATUS)
|
||||
public void handleFileStatus(DataInputStream dis) throws IOException {
|
||||
if(currentTask instanceof ClientTaskUploadFile)
|
||||
((ClientTaskUploadFile) currentTask).onUploadFinishedStatus(dis.readByte());
|
||||
}
|
||||
|
||||
@PacketHandler(PacketID.GET_FILE)
|
||||
public void handleGetFile(DataInputStream dis) throws IOException {
|
||||
if(currentTask instanceof ClientTaskGetFile)
|
||||
((ClientTaskGetFile) currentTask).onGetFileResponse(dis.readByte());
|
||||
}
|
||||
|
||||
@PacketHandler(PacketID.FILE_PART)
|
||||
public void handleFilePart(DataInputStream dis) throws IOException {
|
||||
if(currentTask instanceof ClientTaskGetFile) {
|
||||
int len = dis.readShort() & 0xFFFF;
|
||||
((ClientTaskGetFile) currentTask).onData(getCurrentPacketRawData(), len);
|
||||
}
|
||||
}
|
||||
|
||||
public void nextTask() {
|
||||
if(currentTask != null)
|
||||
currentTask.onFinished();
|
||||
|
||||
synchronized(tasks) {
|
||||
currentTask = tasks.poll();
|
||||
}
|
||||
|
||||
if(currentTask != null)
|
||||
currentTask.start();
|
||||
}
|
||||
|
||||
public boolean addTask(ClientTask task) {
|
||||
boolean cancel;
|
||||
synchronized(this) {
|
||||
cancel = !running || !authenticated;
|
||||
}
|
||||
|
||||
if(cancel)
|
||||
return false;
|
||||
|
||||
synchronized(tasks) {
|
||||
tasks.offer(task);
|
||||
}
|
||||
|
||||
selector.wakeup();
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
27
src/main/java/net/montoyo/wd/miniserv/client/ClientTask.java
Normal file
27
src/main/java/net/montoyo/wd/miniserv/client/ClientTask.java
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright (C) 2018 BARBOTIN Nicolas
|
||||
*/
|
||||
|
||||
package net.montoyo.wd.miniserv.client;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public abstract class ClientTask {
|
||||
|
||||
private Consumer<ClientTask> finishCallback;
|
||||
protected final Client client = Client.getInstance();
|
||||
|
||||
public abstract void start();
|
||||
public abstract void abort();
|
||||
|
||||
public void onFinished() {
|
||||
//Called by Client, don't call it from a ClientTask!
|
||||
if(finishCallback != null)
|
||||
finishCallback.accept(this);
|
||||
}
|
||||
|
||||
public void setFinishCallback(Consumer<ClientTask> finishCallback) {
|
||||
this.finishCallback = finishCallback;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
* Copyright (C) 2018 BARBOTIN Nicolas
|
||||
*/
|
||||
|
||||
package net.montoyo.wd.miniserv.client;
|
||||
|
||||
import net.montoyo.wd.miniserv.Constants;
|
||||
import net.montoyo.wd.miniserv.OutgoingPacket;
|
||||
import net.montoyo.wd.miniserv.PacketID;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.locks.Condition;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
public class ClientTaskGetFile extends ClientTask {
|
||||
|
||||
private final UUID uuid;
|
||||
private final String fname;
|
||||
|
||||
private int response;
|
||||
private boolean hasResponse;
|
||||
private final ReentrantLock responseLock = new ReentrantLock();
|
||||
private final Condition gotResponse = responseLock.newCondition();
|
||||
|
||||
private final ReentrantLock dataLock = new ReentrantLock();
|
||||
private final Condition dataChanged = dataLock.newCondition();
|
||||
private byte[] data;
|
||||
private int dataLen;
|
||||
|
||||
public ClientTaskGetFile(UUID id, String name) {
|
||||
uuid = id;
|
||||
fname = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
OutgoingPacket pkt = new OutgoingPacket();
|
||||
pkt.writeByte(PacketID.GET_FILE.ordinal());
|
||||
pkt.writeLong(uuid.getMostSignificantBits());
|
||||
pkt.writeLong(uuid.getLeastSignificantBits());
|
||||
pkt.writeString(fname);
|
||||
|
||||
client.sendPacket(pkt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void abort() {
|
||||
responseLock.lock();
|
||||
if(!hasResponse) {
|
||||
response = Constants.GETF_STATUS_CONNECTION_LOST;
|
||||
hasResponse = true;
|
||||
gotResponse.signal();
|
||||
}
|
||||
|
||||
responseLock.unlock();
|
||||
onData(new byte[0], -1); //This will trigger an error
|
||||
}
|
||||
|
||||
public void onGetFileResponse(int status) {
|
||||
boolean triggerError = false;
|
||||
responseLock.lock();
|
||||
|
||||
if(hasResponse) {
|
||||
if(status != 0)
|
||||
triggerError = true;
|
||||
} else {
|
||||
response = status;
|
||||
hasResponse = true;
|
||||
gotResponse.signal();
|
||||
}
|
||||
|
||||
responseLock.unlock();
|
||||
|
||||
if(triggerError)
|
||||
onData(new byte[0], -1);
|
||||
}
|
||||
|
||||
public int waitForResponse() {
|
||||
responseLock.lock();
|
||||
while(!hasResponse) {
|
||||
try {
|
||||
gotResponse.await();
|
||||
} catch(InterruptedException ex) {}
|
||||
}
|
||||
|
||||
responseLock.unlock();
|
||||
return response;
|
||||
}
|
||||
|
||||
public void onData(byte[] data, int len) {
|
||||
dataLock.lock();
|
||||
while(this.data != null) {
|
||||
try {
|
||||
dataChanged.await();
|
||||
} catch(InterruptedException ex) {}
|
||||
}
|
||||
|
||||
this.data = data;
|
||||
dataLen = len;
|
||||
dataChanged.signal();
|
||||
dataLock.unlock();
|
||||
|
||||
if(len <= 0)
|
||||
client.nextTask();
|
||||
}
|
||||
|
||||
public byte[] waitForData() {
|
||||
dataLock.lock();
|
||||
while(this.data == null) {
|
||||
try {
|
||||
dataChanged.await();
|
||||
} catch(InterruptedException ex) {}
|
||||
}
|
||||
|
||||
dataLock.unlock(); //This won't change until data is null again
|
||||
return data;
|
||||
}
|
||||
|
||||
public int getDataLength() {
|
||||
return dataLen;
|
||||
}
|
||||
|
||||
public void nextData() {
|
||||
dataLock.lock();
|
||||
data = null;
|
||||
dataChanged.signal();
|
||||
dataLock.unlock();
|
||||
}
|
||||
|
||||
public String getFileName() {
|
||||
return fname;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
* Copyright (C) 2018 BARBOTIN Nicolas
|
||||
*/
|
||||
|
||||
package net.montoyo.wd.miniserv.client;
|
||||
|
||||
import net.montoyo.wd.miniserv.Constants;
|
||||
import net.montoyo.wd.miniserv.OutgoingPacket;
|
||||
import net.montoyo.wd.miniserv.PacketID;
|
||||
import net.montoyo.wd.utilities.Log;
|
||||
import net.montoyo.wd.utilities.Util;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class ClientTaskUploadFile extends ClientTask implements Consumer<OutgoingPacket> {
|
||||
|
||||
private static final byte[] UPLOAD_BUFFER = new byte[65536];
|
||||
|
||||
private final File file;
|
||||
private final long size;
|
||||
private FileInputStream fis;
|
||||
private boolean abortFupa;
|
||||
private int uploadStatus;
|
||||
|
||||
public ClientTaskUploadFile(File fle) throws IOException {
|
||||
file = fle;
|
||||
size = Files.size(fle.toPath());
|
||||
fis = new FileInputStream(fle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
OutgoingPacket pkt = new OutgoingPacket();
|
||||
pkt.writeByte(PacketID.BEGIN_FILE_UPLOAD.ordinal());
|
||||
pkt.writeString(file.getName());
|
||||
pkt.writeLong(size);
|
||||
|
||||
client.sendPacket(pkt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void abort() {
|
||||
abortFupa = true;
|
||||
setUploadStatus(Constants.FUPA_STATUS_CONNECTION_LOST);
|
||||
Util.silentClose(fis);
|
||||
}
|
||||
|
||||
public void onReceivedUploadStatus(int status) {
|
||||
if(status == 0) {
|
||||
//Begin upload
|
||||
Log.info("Now uploading %s", file.getName());
|
||||
accept(null);
|
||||
} else {
|
||||
Util.silentClose(fis);
|
||||
setUploadStatus(status);
|
||||
client.nextTask();
|
||||
}
|
||||
}
|
||||
|
||||
public void onUploadFinishedStatus(int status) {
|
||||
abortFupa = true; //This isn't necessary, but just in case...
|
||||
setUploadStatus(status);
|
||||
client.nextTask();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(OutgoingPacket nocare) {
|
||||
if(abortFupa)
|
||||
return;
|
||||
|
||||
int rd;
|
||||
|
||||
do {
|
||||
try {
|
||||
rd = fis.read(UPLOAD_BUFFER);
|
||||
} catch(IOException ex) {
|
||||
Log.warningEx("Caught IOException while sending some file", ex);
|
||||
rd = 0; //This will cause a FUPA_STATUS_USER_ABORT
|
||||
break;
|
||||
}
|
||||
} while(rd == 0);
|
||||
|
||||
if(rd >= 0) { //If rd < 0, end of file, we're done.
|
||||
OutgoingPacket pkt = new OutgoingPacket();
|
||||
pkt.writeByte(PacketID.FILE_PART.ordinal());
|
||||
pkt.writeShort(rd);
|
||||
pkt.writeBytes(UPLOAD_BUFFER, 0, rd);
|
||||
client.sendPacket(pkt);
|
||||
|
||||
if(rd > 0) {
|
||||
pkt.setOnFinishAction(this);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Util.silentClose(file);
|
||||
}
|
||||
|
||||
private void setUploadStatus(int val) {
|
||||
synchronized(this) {
|
||||
uploadStatus = val;
|
||||
}
|
||||
}
|
||||
|
||||
public int getUploadStatus() {
|
||||
int ret;
|
||||
synchronized(this) {
|
||||
ret = uploadStatus;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -42,7 +42,11 @@ public class ClientManager {
|
|||
}
|
||||
|
||||
public byte[] getClientKey(UUID uuid) {
|
||||
return keys.get(uuid);
|
||||
keyLock.readLock().lock();
|
||||
byte[] ret = keys.get(uuid);
|
||||
keyLock.readLock().unlock();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public void revokeClientKey(UUID id) {
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ import java.nio.channels.SocketChannel;
|
|||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class Server extends Thread {
|
||||
public class Server implements Runnable {
|
||||
|
||||
private static Server instance;
|
||||
|
||||
|
|
@ -37,40 +37,97 @@ public class Server extends Thread {
|
|||
private final ClientManager clientMgr = new ClientManager();
|
||||
private File directory;
|
||||
private long maxQuota = 1024 * 1024; //1 MiB max
|
||||
private volatile boolean running;
|
||||
private volatile Thread thread;
|
||||
|
||||
public Server() {
|
||||
setDaemon(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
thread = new Thread(this);
|
||||
thread.setName("MiniServServer");
|
||||
thread.setDaemon(true);
|
||||
|
||||
try {
|
||||
server = ServerSocketChannel.open();
|
||||
server.bind(new InetSocketAddress(port));
|
||||
server.configureBlocking(false);
|
||||
} catch(Throwable t) {
|
||||
t.printStackTrace();
|
||||
Util.silentClose(server);
|
||||
server = null;
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
selector = Selector.open();
|
||||
server.register(selector, SelectionKey.OP_ACCEPT);
|
||||
} catch(Throwable t) {
|
||||
t.printStackTrace();
|
||||
Util.silentClose(selector);
|
||||
Util.silentClose(server);
|
||||
selector = null;
|
||||
server = null;
|
||||
return;
|
||||
}
|
||||
|
||||
super.start();
|
||||
synchronized(this) {
|
||||
running = true;
|
||||
}
|
||||
|
||||
thread.start();
|
||||
}
|
||||
|
||||
public void stopServer() {
|
||||
if(getRunning()) {
|
||||
Thread thread = this.thread;
|
||||
|
||||
synchronized(this) {
|
||||
running = false;
|
||||
selector.wakeup();
|
||||
}
|
||||
|
||||
while(thread.isAlive()) {
|
||||
try {
|
||||
thread.join();
|
||||
} catch(InterruptedException ex) { }
|
||||
}
|
||||
|
||||
Log.info("Miniserv server stopped");
|
||||
}
|
||||
}
|
||||
|
||||
private boolean getRunning() {
|
||||
boolean ret;
|
||||
synchronized(this) {
|
||||
ret = running;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
boolean running = true;
|
||||
|
||||
while(running) {
|
||||
while(getRunning()) {
|
||||
try {
|
||||
loopUnsafe();
|
||||
} catch(Throwable t) {
|
||||
t.printStackTrace();
|
||||
running = false;
|
||||
Log.errorEx("Miniserv Server crashed", t);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
synchronized(this) {
|
||||
running = false;
|
||||
}
|
||||
|
||||
for(ServerClient cli: clientList)
|
||||
Util.silentClose(cli.getChannel());
|
||||
|
||||
clientList.clear();
|
||||
clientMap.clear();
|
||||
Util.silentClose(selector);
|
||||
Util.silentClose(server);
|
||||
selector = null;
|
||||
server = null;
|
||||
thread = null;
|
||||
}
|
||||
|
||||
private void loopUnsafe() throws Throwable {
|
||||
|
|
@ -89,9 +146,8 @@ public class Server extends Thread {
|
|||
|
||||
if(chan != null) {
|
||||
chan.configureBlocking(false);
|
||||
chan.register(selector, SelectionKey.OP_READ);
|
||||
|
||||
ServerClient toAdd = new ServerClient(chan, selector);
|
||||
|
||||
clientMap.put(chan, toAdd);
|
||||
clientList.add(toAdd);
|
||||
toAdd.onConnect();
|
||||
|
|
@ -110,7 +166,7 @@ public class Server extends Thread {
|
|||
|
||||
if(read < 0)
|
||||
cli.setShouldRemove(); //End of stream
|
||||
else {
|
||||
else if(read > 0) {
|
||||
readBuffer.position(0);
|
||||
readBuffer.limit(read);
|
||||
cli.readyRead(readBuffer);
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ import net.montoyo.wd.utilities.Log;
|
|||
import net.montoyo.wd.utilities.Util;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.channels.ClosedChannelException;
|
||||
import java.nio.channels.SelectionKey;
|
||||
import java.nio.channels.Selector;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.util.UUID;
|
||||
|
|
@ -32,6 +34,10 @@ public class ServerClient extends AbstractClient {
|
|||
ServerClient(SocketChannel s, Selector ss) {
|
||||
socket = s;
|
||||
selector = ss;
|
||||
|
||||
try {
|
||||
selKey = socket.register(selector, SelectionKey.OP_READ);
|
||||
} catch(ClosedChannelException ex) {}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -92,6 +98,7 @@ public class ServerClient extends AbstractClient {
|
|||
|
||||
int len = dis.readByte() & 0xFF;
|
||||
byte[] mac = new byte[len];
|
||||
dis.readFully(mac);
|
||||
|
||||
if(Server.getInstance().getClientManager().verifyClient(uuid, challenge, mac)) {
|
||||
Log.info("Client with UUID %s authenticated successfully", uuid.toString());
|
||||
|
|
@ -136,21 +143,21 @@ public class ServerClient extends AbstractClient {
|
|||
OutgoingPacket rep = new OutgoingPacket();
|
||||
rep.writeByte(PacketID.BEGIN_FILE_UPLOAD.ordinal());
|
||||
|
||||
if(isFileNameInvalid(fname)) {
|
||||
if(Util.isFileNameInvalid(fname)) {
|
||||
Log.warning("Client %s tried to upload a file with a bad name", uuid.toString());
|
||||
rep.writeByte(1);
|
||||
rep.writeByte(Constants.FUPA_STATUS_BAD_NAME);
|
||||
} else if(size <= 0) {
|
||||
Log.warning("Client %s tried to upload a file an invalid size", uuid.toString());
|
||||
rep.writeByte(2);
|
||||
rep.writeByte(Constants.FUPA_STATUS_INVALID_SIZE);
|
||||
} else if(quota + size > Server.getInstance().getMaxQuota())
|
||||
rep.writeByte(3);
|
||||
rep.writeByte(Constants.FUPA_STATUS_EXCEEDS_QUOTA);
|
||||
else if(currentFile != null || sendingFile)
|
||||
rep.writeByte(4);
|
||||
rep.writeByte(Constants.FUPA_STATUS_OCCUPIED);
|
||||
else {
|
||||
File fle = new File(userDir, fname);
|
||||
|
||||
if(fle.exists())
|
||||
rep.writeByte(5);
|
||||
rep.writeByte(Constants.FUPA_STATUS_FILE_EXISTS);
|
||||
else {
|
||||
try {
|
||||
currentFile = new FileOutputStream(fle);
|
||||
|
|
@ -160,7 +167,7 @@ public class ServerClient extends AbstractClient {
|
|||
rep.writeByte(0); //OK
|
||||
} catch(IOException ex) {
|
||||
Log.warningEx("IOException while uploading file %s from user %s", ex, fname, uuid.toString());
|
||||
rep.writeByte(6);
|
||||
rep.writeByte(Constants.FUPA_STATUS_INTERNAL_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -175,14 +182,14 @@ public class ServerClient extends AbstractClient {
|
|||
int len = dis.readShort() & 0xFFFF;
|
||||
if(len <= 0) {
|
||||
//Aborted by user
|
||||
finishUpload(1);
|
||||
finishUpload(Constants.FUPA_STATUS_USER_ABORT);
|
||||
return;
|
||||
}
|
||||
|
||||
currentFileSize += (long) len;
|
||||
if(currentFileSize > currentFileExpectedSize) {
|
||||
//Exceeded expected size
|
||||
finishUpload(2);
|
||||
finishUpload(Constants.FUPA_STATUS_LIER);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -190,7 +197,7 @@ public class ServerClient extends AbstractClient {
|
|||
currentFile.write(getCurrentPacketRawData(), 3, len);
|
||||
} catch(IOException ex) {
|
||||
Log.warningEx("Client %s encountered an IOException while uploading some file", ex, uuid.toString());
|
||||
finishUpload(3);
|
||||
finishUpload(Constants.FUPA_STATUS_INTERNAL_ERROR);
|
||||
currentFileSize -= (long) len;
|
||||
return;
|
||||
}
|
||||
|
|
@ -210,8 +217,8 @@ public class ServerClient extends AbstractClient {
|
|||
OutgoingPacket rep = new OutgoingPacket();
|
||||
rep.writeByte(PacketID.GET_FILE.ordinal());
|
||||
|
||||
if(isFileNameInvalid(fname))
|
||||
rep.writeByte(1);
|
||||
if(Util.isFileNameInvalid(fname))
|
||||
rep.writeByte(Constants.GETF_STATUS_BAD_NAME);
|
||||
else {
|
||||
UUID user = new UUID(msb, lsb);
|
||||
File fle = new File(Server.getInstance().getDirectory(), user.toString() + File.separatorChar + fname);
|
||||
|
|
@ -220,7 +227,7 @@ public class ServerClient extends AbstractClient {
|
|||
rep.setOnFinishAction(new SendFileCallback(fle));
|
||||
sendingFile = true;
|
||||
} catch(FileNotFoundException ex) {
|
||||
rep.writeByte(2);
|
||||
rep.writeByte(Constants.GETF_STATUS_NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -228,10 +235,6 @@ public class ServerClient extends AbstractClient {
|
|||
}
|
||||
}
|
||||
|
||||
private static boolean isFileNameInvalid(String fname) {
|
||||
return fname.isEmpty() || fname.length() > 64 || fname.charAt(0) == '.' || fname.indexOf('/') >= 0 || fname.indexOf('\\') >= 0;
|
||||
}
|
||||
|
||||
private void finishUpload(int status) {
|
||||
if(currentFile != null) {
|
||||
OutgoingPacket pkt = new OutgoingPacket();
|
||||
|
|
@ -274,7 +277,7 @@ public class ServerClient extends AbstractClient {
|
|||
|
||||
OutgoingPacket pkt = new OutgoingPacket();
|
||||
pkt.writeByte(PacketID.GET_FILE.ordinal());
|
||||
pkt.writeByte(3); //Read error
|
||||
pkt.writeByte(Constants.GETF_STATUS_INTERNAL_ERROR); //Read error
|
||||
sendPacket(pkt);
|
||||
|
||||
Util.silentClose(fis);
|
||||
|
|
@ -292,7 +295,7 @@ public class ServerClient extends AbstractClient {
|
|||
|
||||
pkt.writeByte(PacketID.FILE_PART.ordinal());
|
||||
pkt.writeShort(rd);
|
||||
pkt.writeBytes(FILE_UPLOAD_BUFFER);
|
||||
pkt.writeBytes(FILE_UPLOAD_BUFFER, 0, rd);
|
||||
sendPacket(pkt);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,12 +6,13 @@ package net.montoyo.wd.net;
|
|||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
|
||||
import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler;
|
||||
import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.montoyo.wd.WebDisplays;
|
||||
import net.montoyo.wd.miniserv.client.Client;
|
||||
import net.montoyo.wd.utilities.Log;
|
||||
|
||||
@Message(messageId = 11, side = Side.CLIENT)
|
||||
public class CMessageMiniservKey implements IMessage {
|
||||
public class CMessageMiniservKey implements IMessage, Runnable {
|
||||
|
||||
private byte[] encryptedKey;
|
||||
|
||||
|
|
@ -24,24 +25,22 @@ public class CMessageMiniservKey implements IMessage {
|
|||
|
||||
@Override
|
||||
public void fromBytes(ByteBuf buf) {
|
||||
encryptedKey = new byte[buf.readByte() & 0xFF];
|
||||
encryptedKey = new byte[buf.readShort() & 0xFFFF];
|
||||
buf.readBytes(encryptedKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toBytes(ByteBuf buf) {
|
||||
buf.writeByte(encryptedKey.length);
|
||||
buf.writeShort(encryptedKey.length);
|
||||
buf.writeBytes(encryptedKey);
|
||||
}
|
||||
|
||||
public static class Handler implements IMessageHandler<CMessageMiniservKey, IMessage> {
|
||||
|
||||
@Override
|
||||
public IMessage onMessage(CMessageMiniservKey message, MessageContext ctx) {
|
||||
//TODO: Start client thread
|
||||
return null;
|
||||
@Override
|
||||
public void run() {
|
||||
if(Client.getInstance().decryptKey(encryptedKey)) {
|
||||
Log.info("Successfully received and decrypted key, starting miniserv client...");
|
||||
WebDisplays.PROXY.startMiniServClient();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
43
src/main/java/net/montoyo/wd/net/CMessageServerInfo.java
Normal file
43
src/main/java/net/montoyo/wd/net/CMessageServerInfo.java
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright (C) 2018 BARBOTIN Nicolas
|
||||
*/
|
||||
|
||||
package net.montoyo.wd.net;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.montoyo.wd.WebDisplays;
|
||||
import net.montoyo.wd.miniserv.client.Client;
|
||||
|
||||
@Message(messageId = 12, side = Side.CLIENT)
|
||||
public class CMessageServerInfo implements IMessage, Runnable {
|
||||
|
||||
private int miniservPort;
|
||||
|
||||
public CMessageServerInfo() {
|
||||
}
|
||||
|
||||
public CMessageServerInfo(int msPort) {
|
||||
miniservPort = msPort;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromBytes(ByteBuf buf) {
|
||||
miniservPort = buf.readShort() & 0xFFFF;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toBytes(ByteBuf buf) {
|
||||
buf.writeShort(miniservPort);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
WebDisplays.PROXY.setMiniservClientPort(miniservPort);
|
||||
|
||||
if(miniservPort > 0)
|
||||
WebDisplays.NET_HANDLER.sendToServer(Client.getInstance().beginConnection());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -29,6 +29,7 @@ public abstract class Messages {
|
|||
l.add(CMessageJSResponse.class);
|
||||
l.add(SMessageMiniservConnect.class);
|
||||
l.add(CMessageMiniservKey.class);
|
||||
l.add(CMessageServerInfo.class);
|
||||
|
||||
messages = l.toArray(new Class[0]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
|
|||
import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler;
|
||||
import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.montoyo.wd.miniserv.server.ClientManager;
|
||||
import net.montoyo.wd.miniserv.server.Server;
|
||||
|
||||
@Message(messageId = 10, side = Side.SERVER)
|
||||
public class SMessageMiniservConnect implements IMessage {
|
||||
|
|
@ -26,29 +28,31 @@ public class SMessageMiniservConnect implements IMessage {
|
|||
|
||||
@Override
|
||||
public void fromBytes(ByteBuf buf) {
|
||||
int sz = buf.readByte() & 0xFF;
|
||||
int sz = buf.readShort() & 0xFFFF;
|
||||
modulus = new byte[sz];
|
||||
buf.readBytes(modulus);
|
||||
|
||||
sz = buf.readByte() & 0xFF;
|
||||
sz = buf.readShort() & 0xFFFF;
|
||||
exponent = new byte[sz];
|
||||
buf.readBytes(exponent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toBytes(ByteBuf buf) {
|
||||
buf.writeByte(modulus.length);
|
||||
buf.writeShort(modulus.length);
|
||||
buf.writeBytes(modulus);
|
||||
buf.writeByte(exponent.length);
|
||||
buf.writeShort(exponent.length);
|
||||
buf.writeBytes(exponent);
|
||||
}
|
||||
|
||||
public static class Handler implements IMessageHandler<SMessageMiniservConnect, IMessage> {
|
||||
|
||||
@Override
|
||||
public IMessage onMessage(SMessageMiniservConnect message, MessageContext ctx) {
|
||||
//TODO: Generate key
|
||||
return null;
|
||||
public IMessage onMessage(SMessageMiniservConnect msg, MessageContext ctx) {
|
||||
ClientManager cliMgr = Server.getInstance().getClientManager();
|
||||
byte[] encKey = cliMgr.encryptClientKey(ctx.getServerHandler().player.getGameProfile().getId(), msg.modulus, msg.exponent);
|
||||
|
||||
return encKey == null ? null : new CMessageMiniservKey(encKey);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -224,4 +224,7 @@ public abstract class Util {
|
|||
return str.contains("://") ? str : ("http://" + str);
|
||||
}
|
||||
|
||||
public static boolean isFileNameInvalid(String fname) {
|
||||
return fname.isEmpty() || fname.length() > 64 || fname.charAt(0) == '.' || fname.indexOf('/') >= 0 || fname.indexOf('\\') >= 0;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user