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"?>
|
||||
<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"/>
|
||||
<storedRefactorings deprecationInfo="true" structuralOnly="false"/>
|
||||
<selectedProjects/>
|
||||
|
@@ -1,6 +1,6 @@
|
||||
name: PandacraftUtils
|
||||
main: net.mc_pandacraft.java.plugin.pandacraftutils.PandacraftUtils
|
||||
version: 3.4
|
||||
version: 3.5
|
||||
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ commands:
|
||||
aliases: [am]
|
||||
admin:
|
||||
description: Administration
|
||||
usage: /admin <reload|version>
|
||||
usage: /admin [reload [config|network]]
|
||||
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_limitPerChunks = 50;
|
||||
|
||||
|
||||
// TODO ajouter les valeurs par défaut dans config.yml
|
||||
NetworkAPI_passwd = "rgrgaethejtrvvzh47";
|
||||
|
||||
|
||||
|
||||
initChatAnalysisBadWord();
|
||||
@@ -147,6 +152,18 @@ public class ConfigManager {
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* NetworkAPI
|
||||
*/
|
||||
public String NetworkAPI_passwd;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* 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.EntitySpamManager;
|
||||
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 org.bukkit.entity.Player;
|
||||
@@ -87,9 +88,9 @@ public class PandacraftUtils extends JavaPlugin {
|
||||
tpsAnalysisManager = new TPSAnalysisManager();
|
||||
autoMessagesManager = new AutoMessagesManager();
|
||||
entitySpamManager = new EntitySpamManager();
|
||||
|
||||
|
||||
|
||||
NetworkAPI.loadNewInstance();
|
||||
|
||||
getServer().getScheduler().runTaskLater(this, new Runnable() {
|
||||
@Override public void run() { new PlayerDataCleaner(instance); }
|
||||
|
@@ -1,6 +1,8 @@
|
||||
package net.mc_pandacraft.java.plugin.pandacraftutils.commands;
|
||||
|
||||
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.command.Command;
|
||||
@@ -15,17 +17,31 @@ public class CommandAdmin extends AbstractCommandExecutor {
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command cmd, String label,
|
||||
String[] args) {
|
||||
if (args.length == 0) return false;
|
||||
|
||||
|
||||
if (args[0].equalsIgnoreCase("reload")) {
|
||||
ConfigManager.reloadConfig();
|
||||
sender.sendMessage(ChatColor.GREEN+"La configuration de PandacraftUtils viens d'être rechargée");
|
||||
if (args.length == 0){
|
||||
sender.sendMessage(ChatColor.GREEN+plugin.getDescription().getFullName());
|
||||
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;
|
||||
}
|
||||
if (args[0].equalsIgnoreCase("version")) {
|
||||
sender.sendMessage(ChatColor.GREEN+plugin.getDescription().getFullName());
|
||||
return true;
|
||||
|
||||
if (args[0].equalsIgnoreCase("reload") && args.length >= 2) {
|
||||
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