Ajout du NetworkAPI
This commit is contained in:
79
NetworkAPI protocole.md
Normal file
79
NetworkAPI protocole.md
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
Protocole de NetworkAPI
|
||||||
|
====================
|
||||||
|
Ce fichier d<>fini simplement le fonctionnement du protocole qui sera impl<70>ment<6E> dans le package `net.mc_pandacraft.java.plugin.pandacraftutils.network_api`
|
||||||
|
|
||||||
|
Il servira <20> faire communiquer le serveur Minecraft avec l'interface d'administration ou le site internet
|
||||||
|
|
||||||
|
## Type de connexion
|
||||||
|
Connexion TCP
|
||||||
|
|
||||||
|
|
||||||
|
## Cryptage
|
||||||
|
Les communications devant rester dans un r<>seau priv<69> (loopback, VNP) entre les syst<73>mes composant le serveur, il n'est pas vraiment n<>cessaire de crypter les connexions. En d'autres termes, les clients effectuant les requ<71>tes ne correspondent pas aux utilisateurs finaux, se trouvant sur les r<>seaux d'acc<63>s.
|
||||||
|
|
||||||
|
## S<>curit<69>
|
||||||
|
M<EFBFBD>me si le cryptage ne semble pas n<>cessaire, il faut tout de m<>me s<>curiser avec un syst<73>me de "mot de passe", qui sera d<>crit en dessous
|
||||||
|
|
||||||
|
## Structure d'une requ<71>te
|
||||||
|
La requ<71>te est construite en mode texte, sur plusieurs lignes. Chaque ligne se fini par un '\n' :
|
||||||
|
|
||||||
|
- Mot de passe alphanum<75>rique + '\n'
|
||||||
|
- Commande principale + '\n'
|
||||||
|
- Longueur des donn<6E>es, en octets + '\n'
|
||||||
|
- Valeur/donn<6E>es (pas de '\n' <20> la fin)
|
||||||
|
|
||||||
|
Pour que l'analyse de la requ<71>te c<>t<EFBFBD> serveur puisse s'effectuer c<>t<EFBFBD> serveur, le flux qui va du client vers le serveur doit <20>tre ferm<72>e apr<70>s envoi des donn<6E>es.
|
||||||
|
|
||||||
|
### Exemple de paquet
|
||||||
|
ervg1e3r2c
|
||||||
|
command
|
||||||
|
12
|
||||||
|
say Salut :)
|
||||||
|
|
||||||
|
|
||||||
|
### Les commandes principaux
|
||||||
|
|
||||||
|
#### `command`
|
||||||
|
Ex<EFBFBD>cute la commande pass<73>e dans la partie **donn<6E>e** de la requ<71>te, comme si elle avait <20>t<EFBFBD> ex<65>cut<75>e par la console (`ConsoleCommandSender` dans Bukkit). Le r<>sultat de l'ex<65>cution de la commande (valeur de retour de CommandExecutor.onCommand()) ne peux pas <20>tre retourn<72> en r<>ponse. Cependant, la non ex<65>cution de la commande sera indiqu<71> dans la console du serveur
|
||||||
|
|
||||||
|
#### `command_async`
|
||||||
|
Pareil que `command` mais cette fois, celle-ci n'est pas forc<72>ment ex<65>cut<75>e dans le thread principal. Attention : certaines commandes ne peuvent pas fonctionner en asynchrone. Cette m<>thode est utile dans le cas o<> le thread principal ne r<>pond plus
|
||||||
|
|
||||||
|
#### `broadcast`
|
||||||
|
Affiche un message sur le chat pour tout le monde connect<63>.
|
||||||
|
Le message pass<73> dans la partie **donn<6E>e** est diffus<75> tel quel dans le chat et sur la console (attention <20> la bonne utilisation des codes couleurs)
|
||||||
|
|
||||||
|
#### `player_list`
|
||||||
|
Renvoi la liste des joueurs connect<63>s. La valeur pass<73> dans la partie **donn<6E>e** doit contenir, selon les besoins :
|
||||||
|
|
||||||
|
- `disp_name` pour donner les noms d'affichage du genre [Admin]Pseudo
|
||||||
|
- `location` pour donner la localisation du joueur
|
||||||
|
- `ip` pour donner l'IP du joueur
|
||||||
|
- ...
|
||||||
|
|
||||||
|
## Structure d'une r<>ponse
|
||||||
|
La r<>ponse est construite en mode texte, sur plusieurs lignes. Chaque ligne se fini par un '\n' :
|
||||||
|
|
||||||
|
- Status de r<>ponse (`OK` ou `ERROR`) + '\n'
|
||||||
|
- Longueur des donn<6E>es
|
||||||
|
- Donn<6E>es, si n<>cessaire,ou message d'erreur, si status != `ok`
|
||||||
|
|
||||||
|
### Exemple de paquets
|
||||||
|
R<EFBFBD>ponse <20> une requ<71>te sans r<>sultat qui a bien <20>t<EFBFBD> ex<65>cut<75>
|
||||||
|
|
||||||
|
OK
|
||||||
|
0
|
||||||
|
----
|
||||||
|
R<EFBFBD>ponse <20> une commande inexistante
|
||||||
|
|
||||||
|
ERROR
|
||||||
|
24
|
||||||
|
command_not_exists
|
||||||
|
----
|
||||||
|
R<EFBFBD>ponse <20> une requ<71>te de type `player_list`
|
||||||
|
|
||||||
|
OK
|
||||||
|
56
|
||||||
|
player\0disp_name
|
||||||
|
marcbal\0<>f[<5B>4Admin<69>f]<5D>4marcbal<61>r
|
||||||
|
|
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
<jardesc>
|
<jardesc>
|
||||||
<jar path="PandacraftUtils/jar_export/PandacraftUtils-3.4.jar"/>
|
<jar path="PandacraftUtils/jar_export/PandacraftUtils-3.5.jar"/>
|
||||||
<options buildIfNeeded="true" compress="true" descriptionLocation="/PandacraftUtils/make_jar.jardesc" exportErrors="true" exportWarnings="true" includeDirectoryEntries="false" overwrite="false" saveDescription="true" storeRefactorings="false" useSourceFolders="false"/>
|
<options buildIfNeeded="true" compress="true" descriptionLocation="/PandacraftUtils/make_jar.jardesc" exportErrors="true" exportWarnings="true" includeDirectoryEntries="false" overwrite="false" saveDescription="true" storeRefactorings="false" useSourceFolders="false"/>
|
||||||
<storedRefactorings deprecationInfo="true" structuralOnly="false"/>
|
<storedRefactorings deprecationInfo="true" structuralOnly="false"/>
|
||||||
<selectedProjects/>
|
<selectedProjects/>
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
name: PandacraftUtils
|
name: PandacraftUtils
|
||||||
main: net.mc_pandacraft.java.plugin.pandacraftutils.PandacraftUtils
|
main: net.mc_pandacraft.java.plugin.pandacraftutils.PandacraftUtils
|
||||||
version: 3.4
|
version: 3.5
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -67,7 +67,7 @@ commands:
|
|||||||
aliases: [am]
|
aliases: [am]
|
||||||
admin:
|
admin:
|
||||||
description: Administration
|
description: Administration
|
||||||
usage: /admin <reload|version>
|
usage: /admin [reload [config|network]]
|
||||||
permission: pandacraft.admin
|
permission: pandacraft.admin
|
||||||
|
|
||||||
|
|
||||||
|
@@ -101,9 +101,14 @@ public class ConfigManager {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// TODO ajouter les valeurs par défaut dans config.yml
|
||||||
EntitySpam_worlds = "creative"; // séparé avec des point-virgules
|
EntitySpam_worlds = "creative"; // séparé avec des point-virgules
|
||||||
EntitySpam_limitPerChunks = 50;
|
EntitySpam_limitPerChunks = 50;
|
||||||
|
|
||||||
|
|
||||||
|
// TODO ajouter les valeurs par défaut dans config.yml
|
||||||
|
NetworkAPI_passwd = "rgrgaethejtrvvzh47";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
initChatAnalysisBadWord();
|
initChatAnalysisBadWord();
|
||||||
@@ -147,6 +152,18 @@ public class ConfigManager {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NetworkAPI
|
||||||
|
*/
|
||||||
|
public String NetworkAPI_passwd;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Automessages
|
* Automessages
|
||||||
|
@@ -16,6 +16,7 @@ import net.mc_pandacraft.java.plugin.pandacraftutils.modules.WESelectionDisplayM
|
|||||||
import net.mc_pandacraft.java.plugin.pandacraftutils.modules.cheat_protect.CreativCheatManager;
|
import net.mc_pandacraft.java.plugin.pandacraftutils.modules.cheat_protect.CreativCheatManager;
|
||||||
import net.mc_pandacraft.java.plugin.pandacraftutils.modules.cheat_protect.EntitySpamManager;
|
import net.mc_pandacraft.java.plugin.pandacraftutils.modules.cheat_protect.EntitySpamManager;
|
||||||
import net.mc_pandacraft.java.plugin.pandacraftutils.modules.cheat_protect.NoPvpProtectManager;
|
import net.mc_pandacraft.java.plugin.pandacraftutils.modules.cheat_protect.NoPvpProtectManager;
|
||||||
|
import net.mc_pandacraft.java.plugin.pandacraftutils.network_api.NetworkAPI;
|
||||||
import net.mc_pandacraft.java.plugin.pandacraftutils.players.OnlinePlayerManager;
|
import net.mc_pandacraft.java.plugin.pandacraftutils.players.OnlinePlayerManager;
|
||||||
|
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
@@ -87,9 +88,9 @@ public class PandacraftUtils extends JavaPlugin {
|
|||||||
tpsAnalysisManager = new TPSAnalysisManager();
|
tpsAnalysisManager = new TPSAnalysisManager();
|
||||||
autoMessagesManager = new AutoMessagesManager();
|
autoMessagesManager = new AutoMessagesManager();
|
||||||
entitySpamManager = new EntitySpamManager();
|
entitySpamManager = new EntitySpamManager();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
NetworkAPI.loadNewInstance();
|
||||||
|
|
||||||
getServer().getScheduler().runTaskLater(this, new Runnable() {
|
getServer().getScheduler().runTaskLater(this, new Runnable() {
|
||||||
@Override public void run() { new PlayerDataCleaner(instance); }
|
@Override public void run() { new PlayerDataCleaner(instance); }
|
||||||
|
@@ -1,6 +1,8 @@
|
|||||||
package net.mc_pandacraft.java.plugin.pandacraftutils.commands;
|
package net.mc_pandacraft.java.plugin.pandacraftutils.commands;
|
||||||
|
|
||||||
import net.mc_pandacraft.java.plugin.pandacraftutils.ConfigManager;
|
import net.mc_pandacraft.java.plugin.pandacraftutils.ConfigManager;
|
||||||
|
import net.mc_pandacraft.java.plugin.pandacraftutils.network_api.NetworkAPI;
|
||||||
|
import net.mc_pandacraft.java.plugin.pandacraftutils.network_api.NetworkAPIListener;
|
||||||
|
|
||||||
import org.bukkit.ChatColor;
|
import org.bukkit.ChatColor;
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
@@ -15,17 +17,31 @@ public class CommandAdmin extends AbstractCommandExecutor {
|
|||||||
@Override
|
@Override
|
||||||
public boolean onCommand(CommandSender sender, Command cmd, String label,
|
public boolean onCommand(CommandSender sender, Command cmd, String label,
|
||||||
String[] args) {
|
String[] args) {
|
||||||
if (args.length == 0) return false;
|
|
||||||
|
|
||||||
|
|
||||||
if (args[0].equalsIgnoreCase("reload")) {
|
if (args.length == 0){
|
||||||
ConfigManager.reloadConfig();
|
sender.sendMessage(ChatColor.GREEN+plugin.getDescription().getFullName());
|
||||||
sender.sendMessage(ChatColor.GREEN+"La configuration de PandacraftUtils viens d'être rechargée");
|
NetworkAPIListener nwAPI = NetworkAPIListener.getInstance();
|
||||||
|
if (nwAPI.isAlive())
|
||||||
|
sender.sendMessage(ChatColor.GREEN+"NetworkAPI écoute au port "+NetworkAPIListener.getInstance().getPort());
|
||||||
|
else
|
||||||
|
sender.sendMessage(ChatColor.GREEN+"NetworkAPI n'est pas démarré. Voir la console pour les détails, ou faites /admin reload ");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (args[0].equalsIgnoreCase("version")) {
|
|
||||||
sender.sendMessage(ChatColor.GREEN+plugin.getDescription().getFullName());
|
if (args[0].equalsIgnoreCase("reload") && args.length >= 2) {
|
||||||
return true;
|
if (args[1].equalsIgnoreCase("config")) {
|
||||||
|
ConfigManager.reloadConfig();
|
||||||
|
sender.sendMessage(ChatColor.GREEN+"La configuration de PandacraftUtils viens d'être rechargée");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args[1].equalsIgnoreCase("network")) {
|
||||||
|
sender.sendMessage(ChatColor.GREEN+"Redémarrage de NetworkAPI");
|
||||||
|
NetworkAPI.loadNewInstance();
|
||||||
|
sender.sendMessage(ChatColor.GREEN+"Redémarrage terminée");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -0,0 +1,33 @@
|
|||||||
|
package net.mc_pandacraft.java.plugin.pandacraftutils.network_api;
|
||||||
|
|
||||||
|
import net.mc_pandacraft.java.plugin.pandacraftutils.network_api.request_executors.RequestExecutorBroadcast;
|
||||||
|
import net.mc_pandacraft.java.plugin.pandacraftutils.network_api.request_executors.RequestExecutorCommand;
|
||||||
|
import net.mc_pandacraft.java.plugin.pandacraftutils.network_api.request_executors.RequestExecutorCommandAsync;
|
||||||
|
|
||||||
|
public class NetworkAPI {
|
||||||
|
|
||||||
|
public static void loadNewInstance() {
|
||||||
|
|
||||||
|
|
||||||
|
NetworkAPIListener.loadNewInstance();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialisation des exécuteurs des commandes réseau
|
||||||
|
* LEs constructeurs s'occupent eux même de se référencer dans l'instance de la classe NetworkAPIListener
|
||||||
|
*/
|
||||||
|
new RequestExecutorCommand();
|
||||||
|
new RequestExecutorBroadcast();
|
||||||
|
new RequestExecutorCommandAsync();
|
||||||
|
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
public static void main(String[] args) throws Throwable {
|
||||||
|
loadNewInstance();
|
||||||
|
|
||||||
|
System.out.println(NetworkAPIListener.getInstance().getCommandList());
|
||||||
|
|
||||||
|
NetworkAPIListener.getInstance().join();
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,191 @@
|
|||||||
|
package net.mc_pandacraft.java.plugin.pandacraftutils.network_api;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.PrintStream;
|
||||||
|
import java.net.ServerSocket;
|
||||||
|
import java.net.Socket;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
|
|
||||||
|
import net.mc_pandacraft.java.plugin.pandacraftutils.PandacraftUtils;
|
||||||
|
import net.mc_pandacraft.java.plugin.pandacraftutils.network_api.RequestAnalyser.BadRequestException;
|
||||||
|
import net.mc_pandacraft.java.plugin.pandacraftutils.network_api.request_executors.AbstractRequestExecutor;
|
||||||
|
|
||||||
|
public class NetworkAPIListener extends Thread {
|
||||||
|
|
||||||
|
|
||||||
|
private static NetworkAPIListener instance;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retourne l'unique instance de la classe. Si elle n'existe pas, on tente de la créer.<br/>
|
||||||
|
* Cette classe étant un enfant de Thread, la création de l'instance provoque son exécution
|
||||||
|
* @return L'unique instance de la classe
|
||||||
|
*/
|
||||||
|
|
||||||
|
public synchronized static NetworkAPIListener getInstance() {
|
||||||
|
if (instance == null)
|
||||||
|
loadNewInstance();
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized static void loadNewInstance() {
|
||||||
|
if (instance != null && instance.isAlive()) {
|
||||||
|
instance.closeServerSocket(); // cet appel est censé provoquer l'arrêt du thread
|
||||||
|
try { instance.join(); } catch (InterruptedException e) { }
|
||||||
|
}
|
||||||
|
instance = new NetworkAPIListener();
|
||||||
|
instance.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private PandacraftUtils plugin = PandacraftUtils.getInstance();
|
||||||
|
private int port = plugin.getServer().getPort()+9;
|
||||||
|
private ServerSocket serverSocket;
|
||||||
|
private HashMap<String, AbstractRequestExecutor> requestExecutors = new HashMap<String, AbstractRequestExecutor>();
|
||||||
|
|
||||||
|
private NetworkAPIListener() {
|
||||||
|
super("NetworkAPI Listener");
|
||||||
|
System.setProperty("file.encoding", "UTF-8");
|
||||||
|
plugin.getServer().getLogger().info("System property 'file.encoding' was set to 'UTF-8'");
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
synchronized (this) {
|
||||||
|
try {
|
||||||
|
serverSocket = new ServerSocket(port);
|
||||||
|
} catch (IOException e) {
|
||||||
|
plugin.getServer().getLogger().severe(e.getMessage());
|
||||||
|
System.err.println(e.getMessage());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin.getServer().getLogger().info(ChatColor.GREEN+"NetworkAPIListener à l'écoute sur le port "+port);
|
||||||
|
|
||||||
|
int i=0;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// réception des connexion client
|
||||||
|
while (!serverSocket.isClosed()) {
|
||||||
|
Socket socketClient = serverSocket.accept();
|
||||||
|
new PacketExecutor(socketClient, i++).start();
|
||||||
|
}
|
||||||
|
} catch(IOException e) { }
|
||||||
|
|
||||||
|
synchronized (this) {
|
||||||
|
try {
|
||||||
|
if (!serverSocket.isClosed())
|
||||||
|
serverSocket.close();
|
||||||
|
} catch (IOException e) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin.getServer().getLogger().info(ChatColor.GREEN+"NetworkAPIListener ferme le port "+port);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ferme le ServerSocket. Ceci provoque l'arrêt du thread associé à l'instance de la classe
|
||||||
|
*/
|
||||||
|
private synchronized void closeServerSocket() {
|
||||||
|
if (serverSocket != null)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
serverSocket.close();
|
||||||
|
} catch (IOException e) { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public int getPort() { return port; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public void registerRequestExecutor(String command, AbstractRequestExecutor executor) {
|
||||||
|
requestExecutors.put(command, executor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AbstractRequestExecutor getRequestExecutor(String command) {
|
||||||
|
return requestExecutors.get(command);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String getCommandList() {
|
||||||
|
return Arrays.toString(requestExecutors.keySet().toArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prends en charge un socket client et le transmet au gestionnaire de paquet correspondant.<br/>
|
||||||
|
* La connexion est fermée après chaque requête du client (règle pouvant évoluer)
|
||||||
|
* @author Marc
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class PacketExecutor extends Thread {
|
||||||
|
private PandacraftUtils plugin = PandacraftUtils.getInstance();
|
||||||
|
private Socket socket;
|
||||||
|
|
||||||
|
public PacketExecutor(Socket s, int iteration) {
|
||||||
|
super("NetworkAPI Input Packet #"+iteration);
|
||||||
|
socket = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
|
||||||
|
// analyse de la requête
|
||||||
|
RequestAnalyser analyse = new RequestAnalyser(socket);
|
||||||
|
|
||||||
|
|
||||||
|
AbstractRequestExecutor executor = NetworkAPIListener.getInstance().getRequestExecutor(analyse.command);
|
||||||
|
|
||||||
|
executor.execute(analyse.data, socket);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
|
||||||
|
plugin.getServer().getLogger().severe("IOException "+e.getMessage());
|
||||||
|
} catch (BadRequestException e) {
|
||||||
|
Response rep = new Response();
|
||||||
|
rep.good = false;
|
||||||
|
rep.data = e.getMessage();
|
||||||
|
try {
|
||||||
|
rep.sendPacket(new PrintStream(socket.getOutputStream()));
|
||||||
|
} catch (IOException e1) { }
|
||||||
|
|
||||||
|
plugin.getServer().getLogger().severe("BadRequestException "+e.getMessage());
|
||||||
|
|
||||||
|
} catch(Throwable e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
socket.close();
|
||||||
|
} catch (Exception e) { }
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,87 @@
|
|||||||
|
package net.mc_pandacraft.java.plugin.pandacraftutils.network_api;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.net.Socket;
|
||||||
|
|
||||||
|
import net.mc_pandacraft.java.plugin.pandacraftutils.ConfigManager;
|
||||||
|
|
||||||
|
public class RequestAnalyser {
|
||||||
|
|
||||||
|
private NetworkAPIListener networkAPIListener = NetworkAPIListener.getInstance();
|
||||||
|
|
||||||
|
private final String pass = ConfigManager.getInstance().NetworkAPI_passwd;
|
||||||
|
|
||||||
|
public final String command;
|
||||||
|
public final String data;
|
||||||
|
|
||||||
|
public RequestAnalyser(Socket socket) throws IOException, BadRequestException {
|
||||||
|
if (socket == null || socket.isClosed() || socket.isInputShutdown()) throw new IllegalArgumentException("le socket doit être non null et doit être ouvert sur le flux d'entrée");
|
||||||
|
|
||||||
|
// on lis la réponse
|
||||||
|
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
|
||||||
|
|
||||||
|
String line;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// lecture de la première ligne
|
||||||
|
line = in.readLine();
|
||||||
|
if (line == null || !line.equals(pass))
|
||||||
|
throw new BadRequestException("wrong_password");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// lecture de la deuxième ligne
|
||||||
|
line = in.readLine();
|
||||||
|
if (line == null || networkAPIListener.getRequestExecutor(line) == null)
|
||||||
|
throw new BadRequestException("command_not_exists");
|
||||||
|
command = line;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// lecture de la troisième ligne
|
||||||
|
line = in.readLine();
|
||||||
|
|
||||||
|
int data_size = 0;
|
||||||
|
try {
|
||||||
|
data_size = Integer.parseInt(line);
|
||||||
|
} catch (NumberFormatException e) { throw new BadRequestException("wrong_data_size_format"); }
|
||||||
|
|
||||||
|
|
||||||
|
// lecture du reste
|
||||||
|
StringBuilder sB_data = new StringBuilder();
|
||||||
|
char[] c = new char[100];
|
||||||
|
int nbC = 0;
|
||||||
|
while((nbC = in.read(c)) != -1)
|
||||||
|
sB_data.append(c, 0, nbC);
|
||||||
|
|
||||||
|
data = sB_data.toString();
|
||||||
|
|
||||||
|
if (data.length() != data_size)
|
||||||
|
throw new BadRequestException("wrong_data_size");
|
||||||
|
|
||||||
|
|
||||||
|
socket.shutdownInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public class BadRequestException extends Exception {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public BadRequestException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,19 @@
|
|||||||
|
package net.mc_pandacraft.java.plugin.pandacraftutils.network_api;
|
||||||
|
|
||||||
|
import java.io.PrintStream;
|
||||||
|
|
||||||
|
public class Response {
|
||||||
|
public boolean good = true;
|
||||||
|
public String data = "";
|
||||||
|
|
||||||
|
|
||||||
|
public void sendPacket(PrintStream out) {
|
||||||
|
|
||||||
|
if (data == null) data = "";
|
||||||
|
|
||||||
|
out.print((good?"OK":"ERROR")+"\n");
|
||||||
|
out.print(data.length()+"\n");
|
||||||
|
out.print(data);
|
||||||
|
out.flush();
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,31 @@
|
|||||||
|
package net.mc_pandacraft.java.plugin.pandacraftutils.network_api.client_test;
|
||||||
|
|
||||||
|
import java.io.PrintStream;
|
||||||
|
|
||||||
|
public abstract class AbstractRequest {
|
||||||
|
|
||||||
|
private final String pass = "test";
|
||||||
|
private String command;
|
||||||
|
private String data;
|
||||||
|
|
||||||
|
|
||||||
|
protected AbstractRequest(String cmd) {
|
||||||
|
if (cmd == null || cmd.isEmpty()) throw new IllegalArgumentException("Un message doit-être défini");
|
||||||
|
command = cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected void setData(String d) {
|
||||||
|
if (d == null) d = "";
|
||||||
|
data = d;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void sendPacket(PrintStream out) {
|
||||||
|
out.print(pass+"\n");
|
||||||
|
out.print(command+"\n");
|
||||||
|
out.print(data.length()+"\n");
|
||||||
|
out.print(data);
|
||||||
|
out.flush();
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,37 @@
|
|||||||
|
package net.mc_pandacraft.java.plugin.pandacraftutils.network_api.client_test;
|
||||||
|
|
||||||
|
import java.io.PrintStream;
|
||||||
|
import java.net.Socket;
|
||||||
|
|
||||||
|
public class ClientTest {
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
System.out.println("--- connexion ...");
|
||||||
|
Socket s = new Socket("localhost", 12485);
|
||||||
|
System.out.println("--- connecté");
|
||||||
|
|
||||||
|
PrintStream out = new PrintStream(s.getOutputStream());
|
||||||
|
|
||||||
|
AbstractRequest request = new RequestCommand("say Salut :)");
|
||||||
|
|
||||||
|
request.sendPacket(out);
|
||||||
|
|
||||||
|
s.shutdownOutput();
|
||||||
|
|
||||||
|
System.out.println("--- requête envoyée");
|
||||||
|
request.sendPacket(System.out);
|
||||||
|
System.out.println();
|
||||||
|
|
||||||
|
System.out.println("--- réponse du serveur :");
|
||||||
|
ResponseAnalyser response = new ResponseAnalyser(s);
|
||||||
|
|
||||||
|
System.out.println(response.good);
|
||||||
|
System.out.println(response.data);
|
||||||
|
|
||||||
|
s.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@@ -0,0 +1,12 @@
|
|||||||
|
package net.mc_pandacraft.java.plugin.pandacraftutils.network_api.client_test;
|
||||||
|
|
||||||
|
public class RequestCommand extends AbstractRequest {
|
||||||
|
|
||||||
|
|
||||||
|
public RequestCommand(String command) {
|
||||||
|
super("command");
|
||||||
|
setData(command);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,63 @@
|
|||||||
|
package net.mc_pandacraft.java.plugin.pandacraftutils.network_api.client_test;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.net.Socket;
|
||||||
|
|
||||||
|
public class ResponseAnalyser {
|
||||||
|
/**
|
||||||
|
* Indique si la requête s'est bien exécutée (l'entête de la réponse est 'ok')
|
||||||
|
*/
|
||||||
|
public final boolean good;
|
||||||
|
|
||||||
|
|
||||||
|
public final String data;
|
||||||
|
|
||||||
|
|
||||||
|
public ResponseAnalyser(Socket socket) throws IOException {
|
||||||
|
if (socket == null || socket.isClosed() || socket.isInputShutdown()) throw new IllegalArgumentException("le socket doit être non null et doit être ouvert sur le flux d'entrée");
|
||||||
|
|
||||||
|
// on lis la réponse
|
||||||
|
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
|
||||||
|
|
||||||
|
String line;
|
||||||
|
|
||||||
|
|
||||||
|
// lecture de la première ligne
|
||||||
|
line = in.readLine();
|
||||||
|
good = line.equalsIgnoreCase("OK");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// lecture de la deuxième ligne
|
||||||
|
line = in.readLine();
|
||||||
|
|
||||||
|
int data_size = 0;
|
||||||
|
try {
|
||||||
|
data_size = Integer.parseInt(line);
|
||||||
|
} catch (NumberFormatException e) { throw new RuntimeException("Réponse mal formée : la deuxième ligne doit-être un nombre entier"); }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// lecture du reste
|
||||||
|
StringBuilder sB_data = new StringBuilder();
|
||||||
|
char[] c = new char[100];
|
||||||
|
int nbC = 0;
|
||||||
|
while((nbC = in.read(c)) != -1)
|
||||||
|
sB_data.append(c, 0, nbC);
|
||||||
|
data = sB_data.toString();
|
||||||
|
|
||||||
|
if (data.length() != data_size)
|
||||||
|
throw new RuntimeException("Réponse mal formée : "+data_size+" caractères annoncée dans la requête, mais "+data.length()+" s'y trouvent.");
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,48 @@
|
|||||||
|
package net.mc_pandacraft.java.plugin.pandacraftutils.network_api.request_executors;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.PrintStream;
|
||||||
|
import java.net.Socket;
|
||||||
|
|
||||||
|
import net.mc_pandacraft.java.plugin.pandacraftutils.PandacraftUtils;
|
||||||
|
import net.mc_pandacraft.java.plugin.pandacraftutils.network_api.NetworkAPIListener;
|
||||||
|
import net.mc_pandacraft.java.plugin.pandacraftutils.network_api.Response;
|
||||||
|
|
||||||
|
public abstract class AbstractRequestExecutor {
|
||||||
|
|
||||||
|
protected PandacraftUtils plugin = PandacraftUtils.getInstance();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public final String command;
|
||||||
|
|
||||||
|
|
||||||
|
public AbstractRequestExecutor(String cmd) {
|
||||||
|
command = cmd.toLowerCase();
|
||||||
|
NetworkAPIListener.getInstance().registerRequestExecutor(command, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public void execute(String data, Socket socket) throws IOException {
|
||||||
|
if (socket == null || socket.isClosed() || socket.isOutputShutdown()) throw new IllegalArgumentException("le socket doit être non null et doit être ouvert sur le flux d'entrée");
|
||||||
|
|
||||||
|
|
||||||
|
Response rep = run(data);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
rep.sendPacket(new PrintStream(socket.getOutputStream()));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param data La représentation sous forme de String des données envoyés dans la requête
|
||||||
|
* @return La réponse à retourner au client
|
||||||
|
*/
|
||||||
|
protected abstract Response run(String data);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,23 @@
|
|||||||
|
package net.mc_pandacraft.java.plugin.pandacraftutils.network_api.request_executors;
|
||||||
|
|
||||||
|
import net.mc_pandacraft.java.plugin.pandacraftutils.network_api.Response;
|
||||||
|
|
||||||
|
public class RequestExecutorBroadcast extends AbstractRequestExecutor {
|
||||||
|
|
||||||
|
public RequestExecutorBroadcast() {
|
||||||
|
super("broadcast");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Response run(String data) {
|
||||||
|
|
||||||
|
plugin.broadcast(data, false);
|
||||||
|
|
||||||
|
Response rep = new Response();
|
||||||
|
rep.good = true;
|
||||||
|
rep.data = "";
|
||||||
|
return rep;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,49 @@
|
|||||||
|
package net.mc_pandacraft.java.plugin.pandacraftutils.network_api.request_executors;
|
||||||
|
|
||||||
|
import net.mc_pandacraft.java.plugin.pandacraftutils.network_api.Response;
|
||||||
|
|
||||||
|
public class RequestExecutorCommand extends AbstractRequestExecutor {
|
||||||
|
|
||||||
|
public RequestExecutorCommand() {
|
||||||
|
super("command");
|
||||||
|
// TODO Auto-generated constructor stub
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Response run(String data) {
|
||||||
|
|
||||||
|
plugin.getServer().getScheduler().runTask(plugin, new Runnable() {
|
||||||
|
String command;
|
||||||
|
public void run() {
|
||||||
|
try
|
||||||
|
{
|
||||||
|
boolean succes = plugin.getServer().dispatchCommand(plugin.getServer().getConsoleSender(), command);
|
||||||
|
|
||||||
|
if (!succes)
|
||||||
|
plugin.getLogger().warning("Can't execute command");
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
plugin.getLogger().severe(e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public Runnable init(String cmd) {
|
||||||
|
command = cmd;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}.init(data));
|
||||||
|
|
||||||
|
Response rep = new Response();
|
||||||
|
rep.good = true;
|
||||||
|
rep.data = "";
|
||||||
|
|
||||||
|
|
||||||
|
return rep;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,36 @@
|
|||||||
|
package net.mc_pandacraft.java.plugin.pandacraftutils.network_api.request_executors;
|
||||||
|
|
||||||
|
import net.mc_pandacraft.java.plugin.pandacraftutils.network_api.Response;
|
||||||
|
|
||||||
|
public class RequestExecutorCommandAsync extends AbstractRequestExecutor {
|
||||||
|
|
||||||
|
public RequestExecutorCommandAsync() {
|
||||||
|
super("command_async");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Response run(String data) {
|
||||||
|
Response rep = new Response();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
rep.good = plugin.getServer().dispatchCommand(plugin.getServer().getConsoleSender(), data);
|
||||||
|
|
||||||
|
if (!rep.good)
|
||||||
|
{
|
||||||
|
plugin.getLogger().warning("Can't execute command");
|
||||||
|
rep.data = "command sent but CommandExecutor has not return success";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
plugin.getLogger().severe(e.getMessage());
|
||||||
|
rep.good = false;
|
||||||
|
rep.data = "Exception : "+e.getMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return rep;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Reference in New Issue
Block a user