Ajout du NetworkAPI
This commit is contained in:
parent
6819ff2ee7
commit
1a8a911a12
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émenté dans le package `net.mc_pandacraft.java.plugin.pandacraftutils.network_api`
|
||||||
|
|
||||||
|
Il servira à 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é (loopback, VNP) entre les systèmes composant le serveur, il n'est pas vraiment nécessaire de crypter les connexions. En d'autres termes, les clients effectuant les requêtes ne correspondent pas aux utilisateurs finaux, se trouvant sur les réseaux d'accès.
|
||||||
|
|
||||||
|
## Sécurité
|
||||||
|
Même si le cryptage ne semble pas nécessaire, il faut tout de même sécuriser avec un système de "mot de passe", qui sera décrit en dessous
|
||||||
|
|
||||||
|
## Structure d'une requête
|
||||||
|
La requête est construite en mode texte, sur plusieurs lignes. Chaque ligne se fini par un '\n' :
|
||||||
|
|
||||||
|
- Mot de passe alphanumérique + '\n'
|
||||||
|
- Commande principale + '\n'
|
||||||
|
- Longueur des données, en octets + '\n'
|
||||||
|
- Valeur/données (pas de '\n' à la fin)
|
||||||
|
|
||||||
|
Pour que l'analyse de la requête côté serveur puisse s'effectuer côté serveur, le flux qui va du client vers le serveur doit être fermée après envoi des données.
|
||||||
|
|
||||||
|
### Exemple de paquet
|
||||||
|
ervg1e3r2c
|
||||||
|
command
|
||||||
|
12
|
||||||
|
say Salut :)
|
||||||
|
|
||||||
|
|
||||||
|
### Les commandes principaux
|
||||||
|
|
||||||
|
#### `command`
|
||||||
|
Exécute la commande passée dans la partie **donnée** de la requête, comme si elle avait été exécutée par la console (`ConsoleCommandSender` dans Bukkit). Le résultat de l'exécution de la commande (valeur de retour de CommandExecutor.onCommand()) ne peux pas être retourné en réponse. Cependant, la non exécution de la commande sera indiqué dans la console du serveur
|
||||||
|
|
||||||
|
#### `command_async`
|
||||||
|
Pareil que `command` mais cette fois, celle-ci n'est pas forcément exécuté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é.
|
||||||
|
Le message passé dans la partie **donnée** est diffusé tel quel dans le chat et sur la console (attention à la bonne utilisation des codes couleurs)
|
||||||
|
|
||||||
|
#### `player_list`
|
||||||
|
Renvoi la liste des joueurs connectés. La valeur passé dans la partie **donné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ées
|
||||||
|
- Données, si nécessaire,ou message d'erreur, si status != `ok`
|
||||||
|
|
||||||
|
### Exemple de paquets
|
||||||
|
Réponse à une requête sans résultat qui a bien été exécuté
|
||||||
|
|
||||||
|
OK
|
||||||
|
0
|
||||||
|
----
|
||||||
|
Réponse à une commande inexistante
|
||||||
|
|
||||||
|
ERROR
|
||||||
|
24
|
||||||
|
command_not_exists
|
||||||
|
----
|
||||||
|
Réponse à une requête de type `player_list`
|
||||||
|
|
||||||
|
OK
|
||||||
|
56
|
||||||
|
player\0disp_name
|
||||||
|
marcbal\0§f[§4Admin§f]§4marcbal§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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user