renamed modules dir

This commit is contained in:
2022-07-20 13:28:01 +02:00
parent 7dcd92f72d
commit d2ca501203
205 changed files with 12 additions and 12 deletions

22
pandalib-netapi/pom.xml Normal file
View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>pandalib-parent</artifactId>
<groupId>fr.pandacube.lib</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>pandalib-netapi</artifactId>
<dependencies>
<dependency>
<groupId>fr.pandacube.lib</groupId>
<artifactId>pandalib-util</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,29 @@
package fr.pandacube.lib.netapi.client;
import java.io.PrintStream;
public abstract class AbstractRequest {
private final String pass;
private final String command;
private String data;
protected AbstractRequest(String cmd, String p) {
if (cmd == null || cmd.isEmpty()) throw new IllegalArgumentException("Un message doit-être défini");
command = cmd;
pass = p;
}
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.getBytes().length + "\n");
out.print(data);
out.flush();
}
}

View File

@@ -0,0 +1,25 @@
package fr.pandacube.lib.netapi.client;
import java.io.IOException;
import java.io.PrintStream;
import java.net.InetSocketAddress;
import java.net.Socket;
public class NetworkAPISender {
public static ResponseAnalyser sendRequest(InetSocketAddress cible, AbstractRequest request) throws IOException {
Socket s = new Socket(cible.getAddress(), cible.getPort());
PrintStream out = new PrintStream(s.getOutputStream());
request.sendPacket(out);
s.shutdownOutput();
ResponseAnalyser response = new ResponseAnalyser(s);
s.close();
return response;
}
}

View File

@@ -0,0 +1,57 @@
package fr.pandacube.lib.netapi.client;
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();
if (line == null)
throw new IOException("Not enough data to read first line of response.");
good = line.equalsIgnoreCase("OK");
// lecture de la deuxième ligne
line = in.readLine();
if (line == null)
throw new IOException("Not enough data to read second line of response.");
int data_size;
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;
while ((nbC = in.read(c)) != -1)
sB_data.append(c, 0, nbC);
data = sB_data.toString();
if (data.getBytes().length != data_size) throw new RuntimeException("Réponse mal formée : " + data_size
+ " caractères annoncée dans la requête, mais " + data.getBytes().length + " s'y trouvent.");
}
}

View File

@@ -0,0 +1,43 @@
package fr.pandacube.lib.netapi.server;
import java.io.IOException;
import java.io.PrintStream;
import java.net.InetAddress;
import java.net.Socket;
import fr.pandacube.lib.util.Log;
public abstract class AbstractRequestExecutor {
public final String command;
public AbstractRequestExecutor(String cmd, NetworkAPIListener napiListener) {
command = cmd.toLowerCase();
napiListener.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");
try {
Response rep = run(socket.getInetAddress(), data);
rep.sendPacket(new PrintStream(socket.getOutputStream()));
} catch (Exception e) {
new Response(false, e.toString()).sendPacket(new PrintStream(socket.getOutputStream()));
Log.severe(e);
}
}
/**
*
* @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(InetAddress source, String data);
}

View File

@@ -0,0 +1,90 @@
package fr.pandacube.lib.netapi.server;
import java.io.IOException;
import java.net.ServerSocket;
import java.util.Arrays;
import java.util.HashMap;
import fr.pandacube.lib.util.Log;
public class NetworkAPIListener implements Runnable {
private final int port;
final String pass;
private ServerSocket serverSocket;
private final HashMap<String, AbstractRequestExecutor> requestExecutors = new HashMap<>();
private final String name;
/**
* Instencie le côté serveur du NetworkAPI
*
* @param n nom du networkAPI (permet l'identification dans les logs)
* @param p le port d'écoute
* @param pa le mot de passe réseau
*/
public NetworkAPIListener(String n, int p, String pa) {
port = p;
pass = pa;
name = n;
}
@Override
public void run() {
synchronized (this) {
try {
serverSocket = new ServerSocket(port);
} catch (IOException e) {
System.err.println(e.getMessage());
return;
}
}
Log.info("NetworkAPI '" + name + "' à l'écoute sur le port " + port);
try {
// réception des connexion client
while (!serverSocket.isClosed()) {
Thread t = new Thread(new PacketExecutor(serverSocket.accept(), this));
t.setDaemon(true);
t.start();
}
} catch (IOException ignored) {}
synchronized (this) {
try {
if (!serverSocket.isClosed())
serverSocket.close();
} catch (IOException ignored) {}
}
Log.info("NetworkAPI '" + name + "' ferme le port " + port);
}
/**
* Ferme le ServerSocket. Ceci provoque l'arrêt du thread associé à
* l'instance de la classe
*/
public synchronized void closeServerSocket() {
if (serverSocket != null) try {
serverSocket.close();
} catch (IOException ignored) {}
}
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());
}
}

View File

@@ -0,0 +1,64 @@
package fr.pandacube.lib.netapi.server;
import java.io.IOException;
import java.io.PrintStream;
import java.net.Socket;
import fr.pandacube.lib.netapi.server.RequestAnalyser.BadRequestException;
import fr.pandacube.lib.util.Log;
/**
* 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 Baloup
*
*/
public class PacketExecutor implements Runnable {
private final Socket socket;
private final NetworkAPIListener networkAPIListener;
public PacketExecutor(Socket s, NetworkAPIListener napiListener) {
socket = s;
networkAPIListener = napiListener;
}
@Override
public void run() {
try {
// analyse de la requête
RequestAnalyser analyse = new RequestAnalyser(socket, networkAPIListener);
AbstractRequestExecutor executor = networkAPIListener.getRequestExecutor(analyse.command);
executor.execute(analyse.data, socket);
} catch (Throwable e) {
Response rep = new Response();
rep.good = false;
rep.data = e.toString();
try {
rep.sendPacket(new PrintStream(socket.getOutputStream()));
} catch (IOException ignored) {}
if (e instanceof IOException)
Log.warning("Unable to read packet from socket " + socket + ": " + e);
else if(e instanceof BadRequestException) {
if (e.getMessage().equals("wrong_password"))
Log.warning("Wrong password received from socket " + socket);
else if (e.getMessage().equals("command_not_exists"))
Log.severe("The command requested from the socket " + socket + " does not exist");
else
Log.severe(e);
}
else
Log.severe(e);
}
try {
socket.close();
} catch (Exception ignored) {}
}
}

View File

@@ -0,0 +1,65 @@
package fr.pandacube.lib.netapi.server;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
public class RequestAnalyser {
public final String command;
public final String data;
public RequestAnalyser(Socket socket, NetworkAPIListener napiListener) throws IOException, BadRequestException {
if (socket == null || socket.isClosed() || socket.isInputShutdown() || napiListener == null)
throw new IllegalArgumentException(
"le socket doit être non null et doit être ouvert sur le flux d'entrée et napiListener ne doit pas être null");
// 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(napiListener.pass)) throw new BadRequestException("wrong_password");
// lecture de la deuxième ligne
line = in.readLine();
if (line == null || napiListener.getRequestExecutor(line) == null)
throw new BadRequestException("command_not_exists");
command = line;
// lecture de la troisième ligne
line = in.readLine();
int data_size;
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;
while ((nbC = in.read(c)) != -1)
sB_data.append(c, 0, nbC);
data = sB_data.toString();
if (data.getBytes().length != data_size) throw new BadRequestException("wrong_data_size");
socket.shutdownInput();
}
public static class BadRequestException extends Exception {
public BadRequestException(String message) {
super(message);
}
}
}

View File

@@ -0,0 +1,29 @@
package fr.pandacube.lib.netapi.server;
import java.io.PrintStream;
public class Response {
public boolean good = true;
public String data = "";
public Response(boolean good, String data) {
this.good = good;
this.data = data;
}
/**
* Construit une réponse positive avec aucune donnée. Équivaut à
* <code>new Response(true, "")</code>
*/
public Response() {}
public void sendPacket(PrintStream out) {
if (data == null) data = "";
out.print((good ? "OK" : "ERROR") + "\n");
out.print(data.getBytes().length + "\n");
out.print(data);
out.flush();
}
}