* More work on miniserv
This commit is contained in:
parent
d77587ca38
commit
a83601b427
135
src/main/java/net/montoyo/wd/miniserv/AbstractClient.java
Normal file
135
src/main/java/net/montoyo/wd/miniserv/AbstractClient.java
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
/*
|
||||
* Copyright (C) 2018 BARBOTIN Nicolas
|
||||
*/
|
||||
|
||||
package net.montoyo.wd.miniserv;
|
||||
|
||||
import net.montoyo.wd.utilities.Log;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.ClosedChannelException;
|
||||
import java.nio.channels.SelectionKey;
|
||||
import java.nio.channels.Selector;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.util.ArrayDeque;
|
||||
|
||||
public abstract class AbstractClient {
|
||||
|
||||
private final ByteBuffer sendBuffer = ByteBuffer.allocateDirect(8192);
|
||||
private final ArrayDeque<OutgoingPacket> sendQueue = new ArrayDeque<>();
|
||||
private final PacketReader packetReader = new PacketReader();
|
||||
private final PacketWriter packetWriter = new PacketWriter();
|
||||
private final Method[] packetHandlers = new Method[PacketID.values().length];
|
||||
protected SocketChannel socket;
|
||||
protected Selector selector;
|
||||
private SelectionKey writeKey;
|
||||
|
||||
public AbstractClient() {
|
||||
sendBuffer.limit(0);
|
||||
|
||||
Method[] methods = getClass().getMethods();
|
||||
for(Method m: methods) {
|
||||
PacketHandler ph = m.getAnnotation(PacketHandler.class);
|
||||
|
||||
if(ph != null) {
|
||||
if(packetHandlers[ph.value().ordinal()] != null)
|
||||
Log.warning("AbstractClient: several packet handlers for %s, ignoring %s", ph.value().toString(), m.getName());
|
||||
else if(m.getParameterCount() != 1 || m.getParameterTypes()[0] != DataInputStream.class)
|
||||
Log.warning("AbstractClient: found invalid packet handler %s", m.getName());
|
||||
else
|
||||
packetHandlers[ph.value().ordinal()] = m;
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 0; i < packetHandlers.length; i++) {
|
||||
if(packetHandlers[i] == null)
|
||||
Log.warning("AbstractClient: no packet handler for %s", PacketID.fromInt(i).toString());
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void onWriteError();
|
||||
|
||||
public void readyRead(ByteBuffer bb) {
|
||||
while(bb.remaining() > 0) {
|
||||
if(packetReader.readFrom(bb)) { //End of packet
|
||||
byte[] pkt = packetReader.getPacketData();
|
||||
|
||||
if(pkt != null) {
|
||||
try {
|
||||
DataInputStream dis = new DataInputStream(new ByteArrayInputStream(pkt));
|
||||
int pid = dis.readByte() & 0xFF;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
} catch(IOException ex) {
|
||||
Log.warningEx("IOException while trying to handle packet", ex);
|
||||
}
|
||||
}
|
||||
|
||||
packetReader.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void readyWrite() throws Throwable {
|
||||
if(sendBuffer.remaining() > 0 || fillSendBuffer()) {
|
||||
if(socket.write(sendBuffer) < 0)
|
||||
onWriteError();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean fillSendBuffer() {
|
||||
sendBuffer.clear();
|
||||
|
||||
do {
|
||||
if(packetWriter.writeTo(sendBuffer)) {
|
||||
OutgoingPacket pkt;
|
||||
synchronized(sendQueue) {
|
||||
pkt = sendQueue.poll();
|
||||
|
||||
if(pkt == null) {
|
||||
if(writeKey != null) {
|
||||
writeKey.cancel();
|
||||
writeKey = null;
|
||||
}
|
||||
|
||||
return sendBuffer.remaining() > 0;
|
||||
}
|
||||
}
|
||||
|
||||
packetWriter.reset(pkt.finish());
|
||||
}
|
||||
} while(sendBuffer.remaining() > 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
15
src/main/java/net/montoyo/wd/miniserv/KeyParameters.java
Normal file
15
src/main/java/net/montoyo/wd/miniserv/KeyParameters.java
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* Copyright (C) 2018 BARBOTIN Nicolas
|
||||
*/
|
||||
|
||||
package net.montoyo.wd.miniserv;
|
||||
|
||||
public abstract class KeyParameters {
|
||||
|
||||
public static final int RSA_KEY_SIZE = 2048;
|
||||
public static final int KEY_SIZE = 32;
|
||||
public static final int CHALLENGE_SIZE = 32;
|
||||
public static final String MAC_ALGORITHM = "HmacSHA256";
|
||||
public static final String RSA_CIPHER = "RSA/ECB/PKCS1Padding";
|
||||
|
||||
}
|
||||
18
src/main/java/net/montoyo/wd/miniserv/PacketHandler.java
Normal file
18
src/main/java/net/montoyo/wd/miniserv/PacketHandler.java
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* Copyright (C) 2018 BARBOTIN Nicolas
|
||||
*/
|
||||
|
||||
package net.montoyo.wd.miniserv;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface PacketHandler {
|
||||
|
||||
PacketID value();
|
||||
|
||||
}
|
||||
|
|
@ -6,6 +6,7 @@ package net.montoyo.wd.miniserv;
|
|||
|
||||
public enum PacketID {
|
||||
|
||||
AUTHENTICATE, //C->S and S->C
|
||||
PING, //C->S and S->C
|
||||
BEGIN_FILE_UPLOAD, //C->S
|
||||
FILE_PART, //C->S and S->C
|
||||
|
|
|
|||
163
src/main/java/net/montoyo/wd/miniserv/client/Client.java
Normal file
163
src/main/java/net/montoyo/wd/miniserv/client/Client.java
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
/*
|
||||
* Copyright (C) 2018 BARBOTIN Nicolas
|
||||
*/
|
||||
|
||||
package net.montoyo.wd.miniserv.client;
|
||||
|
||||
import net.montoyo.wd.miniserv.*;
|
||||
import net.montoyo.wd.net.SMessageMiniservConnect;
|
||||
import net.montoyo.wd.utilities.Log;
|
||||
import net.montoyo.wd.utilities.Util;
|
||||
|
||||
import javax.crypto.*;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.SocketAddress;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.SelectionKey;
|
||||
import java.nio.channels.Selector;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.security.*;
|
||||
import java.security.interfaces.RSAPublicKey;
|
||||
|
||||
public class Client extends AbstractClient implements Runnable {
|
||||
|
||||
private static Client instance;
|
||||
|
||||
public static Client getInstance() {
|
||||
if(instance == null)
|
||||
instance = new Client();
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
private final SecureRandom random = new SecureRandom();
|
||||
private KeyPair keyPair;
|
||||
private byte[] key;
|
||||
private SocketAddress address;
|
||||
private boolean running = true;
|
||||
private final ByteBuffer readBuffer = ByteBuffer.allocateDirect(8192);
|
||||
private final Thread thread = new Thread(this);
|
||||
private boolean authenticated = false;
|
||||
|
||||
public SMessageMiniservConnect beginConnection() {
|
||||
if(keyPair == null) {
|
||||
try {
|
||||
KeyPairGenerator keygen = KeyPairGenerator.getInstance("RSA");
|
||||
keygen.initialize(KeyParameters.RSA_KEY_SIZE);
|
||||
keyPair = keygen.generateKeyPair();
|
||||
} catch(NoSuchAlgorithmException ex) {
|
||||
Log.warningEx("RSA is unsupported?!?!", ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
RSAPublicKey pubKey = (RSAPublicKey) keyPair.getPublic();
|
||||
return new SMessageMiniservConnect(pubKey.getModulus().toByteArray(), pubKey.getPublicExponent().toByteArray());
|
||||
}
|
||||
|
||||
public boolean decryptKey(byte[] encKey) {
|
||||
try {
|
||||
Cipher cipher = Cipher.getInstance(KeyParameters.RSA_CIPHER);
|
||||
cipher.init(Cipher.DECRYPT_MODE, keyPair.getPrivate(), random);
|
||||
key = cipher.doFinal(encKey);
|
||||
return true;
|
||||
} catch(NoSuchAlgorithmException | NoSuchPaddingException ex) {
|
||||
Log.warningEx("%s unsupported...", ex, KeyParameters.RSA_CIPHER);
|
||||
} catch(InvalidKeyException ex) {
|
||||
Log.warningEx("The generated key is invalid...", ex);
|
||||
} catch(IllegalBlockSizeException | BadPaddingException ex) {
|
||||
Log.warningEx("Could not decrypt key", ex);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public byte[] authenticate(byte[] challenge) {
|
||||
try {
|
||||
Mac mac = Mac.getInstance(KeyParameters.MAC_ALGORITHM);
|
||||
mac.init(new SecretKeySpec(key, KeyParameters.MAC_ALGORITHM));
|
||||
return mac.doFinal(challenge);
|
||||
} catch(NoSuchAlgorithmException ex) {
|
||||
Log.warningEx("%s unsupported...", ex, KeyParameters.MAC_ALGORITHM);
|
||||
} catch(InvalidKeyException ex) {
|
||||
Log.warningEx("The key given by the server is invalid", ex);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void start(SocketAddress addr) {
|
||||
address = addr;
|
||||
thread.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
socket = SocketChannel.open();
|
||||
socket.connect(address);
|
||||
socket.configureBlocking(false);
|
||||
|
||||
selector = Selector.open();
|
||||
socket.register(selector, SelectionKey.OP_READ);
|
||||
} catch(IOException ex) {
|
||||
Log.errorEx("Couldn't start client", ex);
|
||||
return;
|
||||
}
|
||||
|
||||
while(running) {
|
||||
try {
|
||||
unsafeLoop();
|
||||
} catch(Throwable t) {
|
||||
Log.errorEx("MiniServ Client crashed", t);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Util.silentClose(socket);
|
||||
Util.silentClose(selector);
|
||||
}
|
||||
|
||||
private void unsafeLoop() throws Throwable {
|
||||
selector.select();
|
||||
|
||||
for(SelectionKey key: selector.selectedKeys()) {
|
||||
if(key.isReadable()) {
|
||||
readBuffer.clear();
|
||||
int rd = socket.read(readBuffer);
|
||||
|
||||
if(rd <= 0) {
|
||||
Log.warning("Connection was closed, stopping...");
|
||||
running = false;
|
||||
} else {
|
||||
readBuffer.position(0);
|
||||
readBuffer.limit(rd);
|
||||
readyRead(readBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
if(key.isWritable()) {
|
||||
try {
|
||||
readyWrite();
|
||||
} catch(Throwable t) {
|
||||
Log.errorEx("Caught error while sending data to miniserv, stopping...", t);
|
||||
running = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onWriteError() {
|
||||
running = false;
|
||||
Log.error("Write error, stopping...");
|
||||
}
|
||||
|
||||
@PacketHandler(PacketID.AUTHENTICATE)
|
||||
public void handleAuth(DataInputStream dis) {
|
||||
//TODO: Do some stuff
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* Copyright (C) 2018 BARBOTIN Nicolas
|
||||
*/
|
||||
|
||||
package net.montoyo.wd.miniserv.server;
|
||||
|
||||
import net.montoyo.wd.miniserv.KeyParameters;
|
||||
import net.montoyo.wd.utilities.Log;
|
||||
|
||||
import javax.crypto.*;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.math.BigInteger;
|
||||
import java.security.*;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.security.spec.RSAPublicKeySpec;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
public class ClientManager {
|
||||
|
||||
private final SecureRandom random = new SecureRandom(); //SecureRandom is thread safe
|
||||
private final HashMap<UUID, byte[]> keys = new HashMap<>();
|
||||
private final ReentrantReadWriteLock keyLock = new ReentrantReadWriteLock();
|
||||
|
||||
public byte[] getClientKey(UUID uuid) {
|
||||
keyLock.readLock().lock();
|
||||
byte[] key = keys.get(uuid);
|
||||
keyLock.readLock().unlock();
|
||||
|
||||
if(key == null) {
|
||||
key = new byte[KeyParameters.KEY_SIZE];
|
||||
random.nextBytes(key);
|
||||
|
||||
keyLock.writeLock().lock();
|
||||
keys.put(uuid, key);
|
||||
keyLock.writeLock().unlock();
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
public void revokeClientKey(UUID id) {
|
||||
keyLock.writeLock().lock();
|
||||
keys.remove(id);
|
||||
keyLock.writeLock().unlock();
|
||||
}
|
||||
|
||||
public byte[] generateChallenge() {
|
||||
byte[] ret = new byte[KeyParameters.CHALLENGE_SIZE];
|
||||
random.nextBytes(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public boolean verifyClient(UUID client, byte[] challenge, byte[] hmac) {
|
||||
keyLock.readLock().lock();
|
||||
byte[] key = keys.get(client);
|
||||
keyLock.readLock().unlock();
|
||||
|
||||
if(challenge == null || hmac == null || key == null)
|
||||
return false;
|
||||
|
||||
try {
|
||||
Mac mac = Mac.getInstance(KeyParameters.MAC_ALGORITHM);
|
||||
mac.init(new SecretKeySpec(key, KeyParameters.MAC_ALGORITHM));
|
||||
byte[] result = mac.doFinal(challenge);
|
||||
|
||||
return Arrays.equals(hmac, result);
|
||||
} catch(NoSuchAlgorithmException ex) {
|
||||
Log.warningEx("%s is not supported?!?!", ex, KeyParameters.MAC_ALGORITHM);
|
||||
} catch(InvalidKeyException ex) {
|
||||
Log.warningEx("The generated key is invalid", ex);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public byte[] encryptClientKey(UUID client, byte[] modulus, byte[] exponent) {
|
||||
RSAPublicKeySpec keySpec = new RSAPublicKeySpec(new BigInteger(modulus), new BigInteger(exponent));
|
||||
|
||||
try {
|
||||
PublicKey key = KeyFactory.getInstance("RSA").generatePublic(keySpec);
|
||||
Cipher cipher = Cipher.getInstance(KeyParameters.RSA_CIPHER);
|
||||
|
||||
cipher.init(Cipher.ENCRYPT_MODE, key, random);
|
||||
return cipher.doFinal(getClientKey(client));
|
||||
} catch(NoSuchAlgorithmException | NoSuchPaddingException ex) {
|
||||
Log.warningEx("%s is not supported?!?!", ex, KeyParameters.RSA_CIPHER);
|
||||
} catch(InvalidKeySpecException | InvalidKeyException ex) {
|
||||
Log.warningEx("A client sent a malicious key", ex);
|
||||
} catch(IllegalBlockSizeException | BadPaddingException ex) {
|
||||
Log.warningEx("Could not encrypt client key", ex);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@
|
|||
package net.montoyo.wd.miniserv.server;
|
||||
|
||||
import net.montoyo.wd.utilities.Log;
|
||||
import net.montoyo.wd.utilities.Util;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.nio.ByteBuffer;
|
||||
|
|
@ -32,8 +33,8 @@ public class Server extends Thread {
|
|||
public void start() {
|
||||
try {
|
||||
server = ServerSocketChannel.open();
|
||||
server.bind(new InetSocketAddress(port));
|
||||
server.configureBlocking(false);
|
||||
server.socket().bind(new InetSocketAddress(port));
|
||||
|
||||
selector = Selector.open();
|
||||
server.register(selector, SelectionKey.OP_ACCEPT);
|
||||
|
|
@ -81,7 +82,9 @@ public class Server extends Thread {
|
|||
clientMap.put(chan, toAdd);
|
||||
clientList.add(toAdd);
|
||||
}
|
||||
} else if(key.isReadable()) {
|
||||
}
|
||||
|
||||
if(key.isReadable()) {
|
||||
ServerClient cli = clientMap.get(key.channel());
|
||||
|
||||
if(cli == null)
|
||||
|
|
@ -103,7 +106,9 @@ public class Server extends Thread {
|
|||
cli.setShouldRemove();
|
||||
}
|
||||
}
|
||||
} else if(key.isWritable()) {
|
||||
}
|
||||
|
||||
if(key.isWritable()) {
|
||||
ServerClient cli = clientMap.get(key.channel());
|
||||
|
||||
if(cli == null)
|
||||
|
|
@ -130,10 +135,7 @@ public class Server extends Thread {
|
|||
private void removeClient(ServerClient cli) {
|
||||
clientMap.remove(cli.getChannel());
|
||||
clientList.remove(cli);
|
||||
|
||||
try {
|
||||
cli.getChannel().close();
|
||||
} catch(Throwable t) {}
|
||||
Util.silentClose(cli.getChannel());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,95 +4,26 @@
|
|||
|
||||
package net.montoyo.wd.miniserv.server;
|
||||
|
||||
import net.montoyo.wd.miniserv.OutgoingPacket;
|
||||
import net.montoyo.wd.miniserv.PacketID;
|
||||
import net.montoyo.wd.miniserv.PacketReader;
|
||||
import net.montoyo.wd.miniserv.PacketWriter;
|
||||
import net.montoyo.wd.utilities.Log;
|
||||
import net.montoyo.wd.miniserv.*;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.ClosedChannelException;
|
||||
import java.nio.channels.SelectionKey;
|
||||
import java.nio.channels.Selector;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.util.ArrayDeque;
|
||||
|
||||
public class ServerClient {
|
||||
public class ServerClient extends AbstractClient {
|
||||
|
||||
private final SocketChannel socket;
|
||||
private final Selector selector;
|
||||
private SelectionKey writeKey;
|
||||
private boolean remove;
|
||||
private final ByteBuffer sendBuffer = ByteBuffer.allocateDirect(8192);
|
||||
private final ArrayDeque<OutgoingPacket> sendQueue = new ArrayDeque<>();
|
||||
private final PacketReader packetReader = new PacketReader();
|
||||
private final PacketWriter packetWriter = new PacketWriter();
|
||||
private boolean isAuthenticated;
|
||||
|
||||
ServerClient(SocketChannel s, Selector ss) {
|
||||
socket = s;
|
||||
selector = ss;
|
||||
sendBuffer.limit(0); //Set empty
|
||||
}
|
||||
|
||||
void readyRead(ByteBuffer bb) {
|
||||
while(bb.remaining() > 0) {
|
||||
if(packetReader.readFrom(bb)) { //End of packet
|
||||
byte[] pkt = packetReader.getPacketData();
|
||||
if(pkt != null) {
|
||||
try {
|
||||
handlePacket(pkt);
|
||||
} catch(IOException ex) {
|
||||
Log.warningEx("IOException while trying to handle packet", ex);
|
||||
}
|
||||
}
|
||||
|
||||
packetReader.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handlePacket(byte[] pkt) throws IOException {
|
||||
DataInputStream dis = new DataInputStream(new ByteArrayInputStream(pkt));
|
||||
PacketID pid = PacketID.fromInt(dis.readByte());
|
||||
|
||||
if(pid == null) {
|
||||
Log.warning("Caught packet with invalid ID from client");
|
||||
return;
|
||||
}
|
||||
|
||||
OutgoingPacket response = null;
|
||||
|
||||
switch(pid) {
|
||||
case PING:
|
||||
response = new OutgoingPacket();
|
||||
response.writeByte(PacketID.PING.ordinal());
|
||||
break;
|
||||
|
||||
case BEGIN_FILE_UPLOAD:
|
||||
break;
|
||||
|
||||
case FILE_PART:
|
||||
break;
|
||||
|
||||
case GET_FILE:
|
||||
break;
|
||||
}
|
||||
|
||||
if(response != null)
|
||||
sendPacket(response);
|
||||
}
|
||||
|
||||
void readyWrite() throws Throwable {
|
||||
if(sendBuffer.remaining() > 0 || fillSendBuffer()) {
|
||||
if(socket.write(sendBuffer) < 0)
|
||||
remove = true;
|
||||
} else if(writeKey != null) {
|
||||
writeKey.cancel();
|
||||
writeKey = null;
|
||||
}
|
||||
@Override
|
||||
protected void onWriteError() {
|
||||
remove = true;
|
||||
}
|
||||
|
||||
void setShouldRemove() {
|
||||
|
|
@ -107,32 +38,16 @@ public class ServerClient {
|
|||
return socket;
|
||||
}
|
||||
|
||||
private boolean fillSendBuffer() {
|
||||
sendBuffer.clear();
|
||||
|
||||
do {
|
||||
if(packetWriter.writeTo(sendBuffer)) {
|
||||
OutgoingPacket pkt = sendQueue.poll();
|
||||
if(pkt == null)
|
||||
return sendBuffer.remaining() > 0;
|
||||
|
||||
packetWriter.reset(pkt.finish());
|
||||
}
|
||||
} while(sendBuffer.remaining() > 0);
|
||||
|
||||
return true;
|
||||
@PacketHandler(PacketID.AUTHENTICATE)
|
||||
public void handleAuthPacket(DataInputStream dis) throws IOException {
|
||||
//TODO: Do some stuff
|
||||
}
|
||||
|
||||
public void sendPacket(OutgoingPacket pkt) {
|
||||
sendQueue.offer(pkt);
|
||||
|
||||
if(writeKey == null) {
|
||||
try {
|
||||
writeKey = socket.register(selector, SelectionKey.OP_WRITE);
|
||||
} catch(ClosedChannelException ex) {
|
||||
Log.warningEx("Couldn't send packet", ex);
|
||||
}
|
||||
}
|
||||
@PacketHandler(PacketID.PING)
|
||||
public void handlePing(DataInputStream dis) {
|
||||
OutgoingPacket pkt = new OutgoingPacket();
|
||||
pkt.writeByte(PacketID.PING.ordinal());
|
||||
sendPacket(pkt);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
47
src/main/java/net/montoyo/wd/net/CMessageMiniservKey.java
Normal file
47
src/main/java/net/montoyo/wd/net/CMessageMiniservKey.java
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* 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.common.network.simpleimpl.IMessageHandler;
|
||||
import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
|
||||
@Message(messageId = 11, side = Side.CLIENT)
|
||||
public class CMessageMiniservKey implements IMessage {
|
||||
|
||||
private byte[] encryptedKey;
|
||||
|
||||
public CMessageMiniservKey() {
|
||||
}
|
||||
|
||||
public CMessageMiniservKey(byte[] key) {
|
||||
encryptedKey = key;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromBytes(ByteBuf buf) {
|
||||
encryptedKey = new byte[buf.readByte() & 0xFF];
|
||||
buf.readBytes(encryptedKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toBytes(ByteBuf buf) {
|
||||
buf.writeByte(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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -11,7 +11,7 @@ import net.minecraftforge.fml.common.network.simpleimpl.SimpleNetworkWrapper;
|
|||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class Messages {
|
||||
public abstract class Messages {
|
||||
|
||||
private static DefaultHandler DEFAULT_HANDLER = new DefaultHandler();
|
||||
private static Class<? extends IMessage>[] messages;
|
||||
|
|
@ -27,6 +27,8 @@ public class Messages {
|
|||
l.add(SMessagePadCtrl.class);
|
||||
l.add(SMessageRedstoneCtrl.class);
|
||||
l.add(CMessageJSResponse.class);
|
||||
l.add(SMessageMiniservConnect.class);
|
||||
l.add(CMessageMiniservKey.class);
|
||||
|
||||
messages = l.toArray(new Class[0]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* 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.common.network.simpleimpl.IMessageHandler;
|
||||
import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
|
||||
@Message(messageId = 10, side = Side.SERVER)
|
||||
public class SMessageMiniservConnect implements IMessage {
|
||||
|
||||
private byte[] modulus;
|
||||
private byte[] exponent;
|
||||
|
||||
public SMessageMiniservConnect() {
|
||||
}
|
||||
|
||||
public SMessageMiniservConnect(byte[] mod, byte[] exp) {
|
||||
modulus = mod;
|
||||
exponent = exp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromBytes(ByteBuf buf) {
|
||||
int sz = buf.readByte() & 0xFF;
|
||||
modulus = new byte[sz];
|
||||
buf.readBytes(modulus);
|
||||
|
||||
sz = buf.readByte() & 0xFF;
|
||||
exponent = new byte[sz];
|
||||
buf.readBytes(exponent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toBytes(ByteBuf buf) {
|
||||
buf.writeByte(modulus.length);
|
||||
buf.writeBytes(modulus);
|
||||
buf.writeByte(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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user