Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions front-js/src/app/dashboard/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -157,9 +157,10 @@ export default function Dashboard() {
</Grid2>
<Grid2 size={4}>
<Card
title="TCP"
description="Testez une connexion TCP"
title="Ping TCP"
description="Expérimentez l'envoi de paquets avec le protocole TCP."
image="/modules_assets/tcp.svg"
onClick={() => router.push("/modules/tcp")}
/>
</Grid2>
<Grid2 size={4}>
Expand Down
49 changes: 49 additions & 0 deletions front-js/src/app/modules/tcp/Cours.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import Title from "@/components/Title";
import Text from "@/components/Text";
import React from "react";
import Space from "@/components/Space";
import Box from "@/components/Box";

const Cours: React.FC = () => {
return (
<>
<Space space="1rem">
<Title level={2}>Introduction</Title>
<Text>
TCP (Transmission Control Protocol) est un protocole de communication
qui assure la transmission de données entre deux machines. Il garantit
que les données envoyées par une machine arrivent bien à l&rsquo;autre
machine, dans le bon ordre et sans erreur.
</Text>
<Title level={2} margin={{ top: "2rem" }}>
Fonctionnement TCP
</Title>
<Text>
TCP fonctionne en établissant une connexion entre deux machines avant
de transmettre des données. Cette connexion est appelée{" "}
<b>connexion TCP</b>. Elle est établie en trois étapes :
<Box margin={{ top: "1rem", left: "2rem" }}>
<ol>
<li>
<b>Établissement de la connexion :</b> Les deux machines
s&rsquo;échangent des paquets pour s&rsquo;assurer
qu&rsquo;elles sont prêtes à communiquer.
</li>
<li>
<b>Transfert des données :</b> Les données sont envoyées en
plusieurs paquets, chacun étant numéroté pour être reconstitué
dans le bon ordre.
</li>
<li>
<b>Fin de la connexion :</b> Les deux machines s&rsquo;échangent
des paquets pour clôturer la connexion.
</li>
</ol>
</Box>
</Text>
</Space>
</>
);
};

export default Cours;
171 changes: 171 additions & 0 deletions front-js/src/app/modules/tcp/TcpSandbox.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
import Title from "@/components/Title";
import Button from "@/components/Button";
import Input from "@/components/Input";
import Space from "@/components/Space";
import React from "react";
import { useState } from "react";
import axios from "@/axiosConfig";
import Cookies from "js-cookie";
import { AxiosError } from "axios";
import { Alert, CircularProgress } from "@mui/material";
import Box from "@/components/Box";

const TcpSandbox: React.FC = () => {
const [res, setRes] = useState("");
const [ping, setPing] = useState<{
rtt_ms: number;
packet_size: number;
ttl: number;
source: string;
destination: string;
} | null>(null);
const [command, setCommand] = useState<string>("");
const [error, setError] = useState<string>("");
const [isLoading, setIsLoading] = useState(false);

const handlePing = async (e: { preventDefault: () => void }) => {
setIsLoading(true);
e.preventDefault();
const parts = command.split(" ");
if (parts.length < 2 || parts.length > 2) {
setError("Commande invalide");
setRes("");
setIsLoading(false);
return;
}
if (parts[0] !== "ping") {
setError("Commande invalide");
setRes("");
setIsLoading(false);
return;
}
try {
const ip_port = parts[1].split(":");
if (ip_port.length < 2 || ip_port.length > 2) {
setError("Commande invalide");
setRes("");
setIsLoading(false);
return;
}
const ip = ip_port[0];
const port = ip_port[1];

const response = await axios.get("/scapy/tcp-test/" + ip + "/" + port, {
headers: {
Authorization: `Bearer ${Cookies.get("access_token")}`,
},
});
const data = response.data;
if (response.status === 200) {
setRes(data.message);
const formattedPing = {
rtt_ms: data.details.rtt_ms,
packet_size: data.details.packet_size,
ttl: data.details.ttl,
source: data.details.source,
destination: data.details.destination,
};
setPing(formattedPing);
setError("");
}
} catch (error: unknown) {
const axiosError = error as AxiosError;
if (axiosError.response?.status === 404) {
setRes("");
setError("Impossible de résoudre l'adresse");
} else {
setError("Erreur lors du ping TCP");
setRes("");
}
}
setIsLoading(false);
};

return (
<>
<Space space="50px" direction="vertical" margin={{ bottom: "100px" }}>
<form onSubmit={handlePing}>
<Title level={2}>Ping TCP</Title>

<Input
type="text"
placeholder="ping 145.242.11.100:80 ou ping impots.gouv.fr:443"
value={command}
margin={{ bottom: "20px" }}
onChange={(e) => setCommand(e.target.value)}
required
label="Commande ping"
/>
<Button
text="Ping"
primary
form="submit"
type="input"
margin={{ top: "20px" }}
disabled={!command}
onClick={(e) => {
handlePing(e);
}}
/>
{isLoading && (
<Box align="center" margin={{ top: "20px" }}>
{" "}
<CircularProgress />
</Box>
)}
{!isLoading && res && ping ? (
<Box margin={{ top: "20px", bottom: "20px" }}>
<Alert
severity="success"
variant="outlined"
style={{ borderRadius: "10px" }}
>
Résultat : {res}
<Space />
<table style={{ borderCollapse: "collapse", width: "100%" }}>
<tbody>
<tr style={{ borderBottom: "1px solid black" }}>
<th style={{ paddingRight: "1.5em" }}>Source</th>
<td>{ping.source}</td>
</tr>
<tr style={{ borderBottom: "1px solid black" }}>
<th style={{ paddingRight: "1.5em" }}>Destination</th>
<td>{ping.destination}</td>
</tr>
<tr style={{ borderBottom: "1px solid black" }}>
<th style={{ paddingRight: "1.5em" }}>TTL</th>
<td>{ping.ttl}</td>
</tr>
<tr style={{ borderBottom: "1px solid black" }}>
<th style={{ paddingRight: "1.5em" }}>RTT (ms)</th>
<td>{ping.rtt_ms}</td>
</tr>
<tr style={{ borderBottom: "1px solid black" }}>
<th style={{ paddingRight: "1.5em" }}>
Taille du paquet
</th>
<td>{ping.packet_size}</td>
</tr>
</tbody>
</table>
</Alert>
</Box>
) : null}
{!isLoading && error ? (
<Box margin={{ top: "20px", bottom: "20px" }}>
<Alert
severity="error"
variant="outlined"
style={{ borderRadius: "10px" }}
>
{error}
</Alert>
</Box>
) : null}
</form>
</Space>
</>
);
};

export default TcpSandbox;
14 changes: 14 additions & 0 deletions front-js/src/app/modules/tcp/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import type { Metadata } from "next";

export const metadata: Metadata = {
title: "Ping TCP",
description: "Networkers",
};

export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return <body>{children}</body>;
}
90 changes: 90 additions & 0 deletions front-js/src/app/modules/tcp/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
"use client";

import Layout from "@/components/Layout";
import Header from "@/components/Header";
import Title from "@/components/Title";
import Box from "@/components/Box";
import { useRouter } from "next/navigation";
import { useEffect, useState } from "react";
import Cookies from "js-cookie";
import axios from "@/axiosConfig";
import { Tabs, Tab } from "@mui/material";
import Cours from "./Cours";
import TcpSandbox from "./TcpSandbox";

export default function TCP() {
const router = useRouter();

const [, setHasAccessToken] = useState(false);

useEffect(() => {
const checkTokens = async () => {
const token = Cookies.get("access_token");
const refresh = Cookies.get("refresh_token");
if (!token && refresh) {
try {
const response = await axios.post("/auth/refresh", {
refresh_token: refresh,
});
const data = response.data;
if (response.status === 200) {
Cookies.set("access_token", data.access_token);
Cookies.set("refresh_token", refresh);
}
} catch {
Cookies.remove("access_token");
Cookies.remove("refresh_token");
}
}
setHasAccessToken(!!token);

if (!token && !refresh) {
router.push("/");
}
};

checkTokens();
}, [router]);

const [activeTab, setActiveTab] = useState("cours");

const handleTabChange = (tab: string) => {
setActiveTab(tab);
};

return (
<Layout type="logged">
<Box align="center" margin={{ top: "50px", bottom: "50px" }}>
<Header
tabs={{
dashboard: "Tableau de bord",
modules: "Mes modules",
profile: "Mon profil",
}}
activeTab="modules"
onClick={(tab) => router.push(`/${tab.toLowerCase()}`)}
onClickLogout={() => router.push("/auth/logout")}
onClickLogo={() => router.push("/")}
/>
</Box>
<Box align="center" margin={{ top: "50px", bottom: "50px" }}>
<Title level={1} align="center">
Ping TCP
</Title>
</Box>

<Tabs
value={activeTab}
onChange={(_, tab) => handleTabChange(tab)}
centered
>
<Tab label="Cours" value="cours" />
<Tab label="Bac à sable" value="sandbox" />
</Tabs>

<Box margin={{ top: "50px", bottom: "50px", left: "20%", right: "20%" }}>
{activeTab === "cours" ? <Cours /> : < TcpSandbox />}
</Box>
</Layout>
);
}