Compare commits

..

66 Commits

Author SHA1 Message Date
xdrm-brackets 2d176987ea last fix std99 2017-05-19 09:45:15 +02:00
SeekDaSky d11649e9b9 Merge remote-tracking branch 'origin/master' 2017-05-19 09:35:53 +02:00
SeekDaSky 710a5def49 fix 2017-05-19 09:35:50 +02:00
xdrm-brackets 87509e8efe Fixed Makefile-s 2017-05-19 08:50:44 +02:00
xdrm-brackets 4636c79334 fixed socket reference conflicts in vTerm+cTerm as in plane 2017-05-19 08:49:05 +02:00
SeekDaSky c8da1b3ba6 ControlTerm - final 2017-05-18 20:43:32 +02:00
SeekDaSky 821808a420 fix compilation 2017-05-18 20:24:39 +02:00
xdrm-brackets f5232693d3 Merge branch 'source' 2017-05-18 00:14:37 +02:00
xdrm-brackets 1246fbbdc5 Removed c-emul 2017-05-18 00:14:33 +02:00
xdrm-brackets 110598780b Makefile update (input cleaned) + global makefile 2017-05-16 21:02:52 +02:00
xdrm-brackets 734de323d4 [update] Renamed main folders according to naming convention used in code/documentation 2017-05-07 14:46:20 +02:00
xdrm-brackets 486216f183 [+] Install/Uninstall service
[todo] Manage output log
2017-05-05 14:33:58 +02:00
xdrm-brackets 265feabb59 Replaced term_req 0x10 with TERMREQ_OFF flag constant 2017-05-05 13:51:07 +02:00
xdrm-brackets 6848840638 [update] Managing already used ports (so take next, 10 times max) 2017-05-04 17:34:03 +02:00
xdrm-brackets 87ed0fb7c9 [update] removed verbose ping 2017-05-04 13:13:39 +02:00
SeekDaSky b67ddecbab Merge remote-tracking branch 'origin/master' 2017-05-04 12:45:34 +02:00
SeekDaSky 139de56401 CommandTerm v1.1 (securing user input) 2017-05-04 12:45:29 +02:00
xdrm-brackets 919fac4d67 Merge branch 'master' of https://git.xdrm.io/xdrm-brackets/sysdis-project 2017-05-04 12:36:53 +02:00
xdrm-brackets b21565e682 Credits 2017-05-04 12:36:45 +02:00
SeekDaSky dc7016355a Merge remote-tracking branch 'origin/master' 2017-05-04 12:30:57 +02:00
SeekDaSky 01aeb922c4 ViewTerm v1.2 (implémentation du pingback) 2017-05-04 12:30:53 +02:00
xdrm-brackets 21cc53bc20 Fixed non verbose enough "cannot get response from plane ..." 2017-05-04 12:25:17 +02:00
SeekDaSky a2ab8d415e Merge remote-tracking branch 'origin/master' 2017-05-04 12:20:24 +02:00
SeekDaSky 54321deca2 CommandTerm v1 + fix timeout 2017-05-04 12:20:21 +02:00
xdrm-brackets 6017302007 Merge branch 'master' of https://git.xdrm.io/xdrm-brackets/sysdis-project 2017-05-04 12:19:08 +02:00
xdrm-brackets d6b2b82116 fixed shitty ping/request output 2017-05-04 12:18:58 +02:00
SeekDaSky 1668bca970 Merge remote-tracking branch 'origin/master' 2017-05-04 12:11:46 +02:00
SeekDaSky 6541012e04 ViewTerm 1.1 2017-05-04 12:11:42 +02:00
xdrm-brackets 5b7d7d5c80 [update] verbose timeout set up for udp COM sockets 2017-05-04 12:10:55 +02:00
xdrm-brackets 05a59c772c [update] verbose fix for ping flag 2017-05-04 12:04:58 +02:00
xdrm-brackets 9a6c480290 [update] ctrlTerm timeout to 10sec 2017-05-04 11:56:07 +02:00
xdrm-brackets 6fbd41542b [update] Updated verbose plane handler (SGCA) 2017-05-04 11:52:44 +02:00
xdrm-brackets 685d18df8f [update] Updated verbose plane info 2017-05-04 11:52:00 +02:00
xdrm-brackets 4b23207f74 [fix] Makefile `clean` check and returns EXIT_SUCCESS (non blocking) 2017-05-04 11:21:29 +02:00
xdrm-brackets f860c8af0a [update] Feedback management (to notice viewTerm crash) added (1 byte: 0x10) 2017-05-04 11:03:19 +02:00
xdrm-brackets c868ec22f4 minmod (text message) 2017-05-03 17:03:27 +02:00
xdrm-brackets 29393a0747 [update] Sending flag 0x10 when plane update request and offline/unreachable 2017-05-03 17:01:02 +02:00
xdrm-brackets c3fa24d747 fixed text message 2017-05-03 16:06:19 +02:00
xdrm-brackets 1501181420 [update][fix] fixed c-emul test + redesigned ctrlTerm update management without <Critical Section> 2017-05-03 15:45:19 +02:00
xdrm-brackets 7b3f8c101c Mutex management for plane socket used by ctlrTerm 2017-05-03 12:35:18 +02:00
xdrm-brackets 6cfa351c9a Cleaned context structure 2017-05-03 11:58:41 +02:00
xdrm-brackets c5e59ccbd8 finalisation emulation ctrlTerm 2017-05-02 18:32:22 +02:00
xdrm-brackets a31c97942b [fix] request switch management (plane thread let ctrlTerm use common socket) 2017-04-29 17:31:38 +02:00
xdrm-brackets 061893b35d [CREATED] ctrlTerm emulation in C 2017-04-29 17:09:47 +02:00
xdrm-brackets 4af2f8180c [Fix] ctrlTerm doesn't get DATA when flag TERMREQ_FBK absent 2017-04-29 17:09:31 +02:00
xdrm-brackets e4b9d5daa6 [FIX] ctrlTerm ok (ctrlTerm<->sgca<->plane) 2017-04-29 17:04:07 +02:00
xdrm-brackets a8a44d9941 [DONE] Gestion envoi de données pour ctrlTerm 2017-04-28 16:37:29 +02:00
xdrm-brackets cc78418a53 Now viewTerm has an "infinite" buffer and delegates the data/buffer creation from context to local function (next step: use it also for ctrlTerm) 2017-04-28 16:32:20 +02:00
xdrm-brackets e6c2bbcfa6 gitignore 2017-04-28 15:57:48 +02:00
xdrm-brackets 1a98172fca [done] ctrlTerm plane update procedure (v0.1) to be tested by SdS 2017-04-28 14:54:02 +02:00
xdrm-brackets e8e65f81fb makefile `make clean` fix 2017-04-26 23:48:15 +02:00
SeekDaSky face7b0f04 Fix suppression Avion 2017-04-26 23:40:45 +02:00
xdrm-brackets a356548965 minfix 2017-04-26 23:35:06 +02:00
xdrm-brackets e2fe1a7155 [done] Managing ONLINE/OFFLINE status for planes deconnected 2017-04-26 23:23:28 +02:00
xdrm-brackets b96e89bddb Merge branch 'master' of https://git.xdrm.io/xdrm-brackets/sysdis-project 2017-04-26 23:06:18 +02:00
SeekDaSky 3071b9debe ViewTerm V1.1 2017-04-26 23:04:36 +02:00
xdrm-brackets 19a513f207 minmod 2017-04-26 23:04:31 +02:00
SeekDaSky 5d2f912738 Merge remote-tracking branch 'origin/master' 2017-04-26 22:56:54 +02:00
xdrm-brackets 9614928bcf [fix] test1 to send port (err with old BIND_HEADER length) 2017-04-26 22:56:29 +02:00
SeekDaSky 0dbd88c1f8 ViewTerm v1 2017-04-26 20:12:43 +02:00
xdrm-brackets 79a1258a53 [BIG UPDATE] Dynamic local ip 2017-04-26 14:25:05 +02:00
xdrm-brackets 48f2b33728 fix 2017-04-26 13:13:53 +02:00
xdrm-brackets 3c241a2a95 [fixed] indianness sgca (plane viewTerm) 2017-04-26 13:10:35 +02:00
xdrm-brackets 80f0aa95f6 Plane indianness + Plane timeout misplaced 2017-04-25 16:34:04 +02:00
xdrm-brackets 387e55c092 Gestion viewTerm fonctionnel [todo] gestion envoi en plusieurs fois 2017-04-25 15:00:25 +02:00
xdrm-brackets a20cc18377 Refactor flags bind_header 2017-04-25 11:54:15 +02:00
63 changed files with 2548 additions and 2361 deletions

47
Makefile Normal file
View File

@ -0,0 +1,47 @@
default:
@echo "install - will compile and create executables";
@echo "clean - will remove executables and clean";
install-sgca:
@echo "(1) Compiling SGCA";
@make --directory=./sgca > /dev/null;
install-plane:
@echo "(2) Compiling PLANE";
@make --directory=./plane > /dev/null;
link-sgca:
@echo "(3) Linking SGCA executable";
@ln -fs ./sgca/boot x-sgca;
link-plane:
@echo "(4) Linking PLANE executable";
@ln -fs ./plane/boot x-plane;
link-viewTerm:
@echo "(4) Linking VIEW TERMINAL executable";
@echo -e "#!/bin/bash\n\njava -jar ./viewTerm/viewTerm.jar;\n" > ./x-viewTerm;
@chmod ug+x ./x-viewTerm;
link-ctrlTerm:
@echo "(5) Linking CTRL TERMINAL executable";
@echo -e "#!/bin/bash\n\njava -jar ./ctrlTerm/commandTerm.jar;\n" > ./x-ctrlTerm;
@chmod ug+x ./x-ctrlTerm;
install: install-sgca install-plane link-sgca link-plane link-viewTerm link-ctrlTerm
@echo;
@echo "*** Executables created:";
@ls -a . | grep -P "^x-*" | sed 's/^x-/ (*) x-/';
clean:
@find ./x-sgca > /dev/null 2>&1 && rm ./x-sgca || return 0;
@find ./x-plane > /dev/null 2>&1 && rm ./x-plane || return 0;
@find ./x-viewTerm > /dev/null 2>&1 && rm ./x-viewTerm || return 0;
@find ./x-ctrlTerm > /dev/null 2>&1 && rm ./x-ctrlTerm || return 0;
@make clean --directory=./sgca > /dev/null;
@make clean --directory=./plane > /dev/null;

View File

@ -1 +0,0 @@
.vscode

View File

@ -1,10 +0,0 @@
#!/bin/bash
# [1] Create service target (boot)
sudo ln -s $(pwd)/sgca /usr/sbin/sgca;
# [2] Create service unit
sudo ln -s $(pwd)/sgca.service /lib/systemd/system/sgca.service;
# [3] Enable service (optional if no [Install])
sudo systemctl enable sgca.service;

View File

@ -1,3 +0,0 @@
#!/bin/bash
echo -ne "\x3\x0\x0" | nc -u localhost 4446;

View File

@ -1,3 +0,0 @@
#!/bin/bash
echo -ne "abcdef\x1\x0\x0\x0\x2\x0\x0\x0\x3\x0\x0\x0\x4\x0\x0\x0\x5\x0\x0\x0" | nc localhost 20556;

View File

@ -1,3 +0,0 @@
#!/bin/bash
echo -ne "\x3\x0\x0" | nc -u localhost 4445;

View File

@ -1,3 +0,0 @@
#!/bin/bash
/home/xdrm-brackets/Desktop/git.xdrm.io/sysdis-project/central-manager/boot >> $1 2>&1;

View File

@ -1,351 +0,0 @@
/**************************
* Handler Dependency *
***************************
* Designed & Developed by *
* Adrien Marquès *
* <xdrm-brackets> *
***************************
* doowap31@gmail.com *
**************************/
#include "handler.h"
/* Gestion d'une connexion PLANE
*
* @THREADABLE_SOCKET<void*> SOCKET de la connexion client
*
* @history
* [1] Initialisation des variables
* @loop
* (2) Attente de requête
* (3) Gestion de la requête
* (4) Envoi de la réponse
* [5] On libère la mémoire
* [6] Fermeture de la connection (SOCKET)
* [n] Arrêt du THREAD
* 1. On met à jour "activeManagers"
* 2. On arrête le THREAD
*
*/
void* managePlane(void* THREADABLE_ARGS){
/* [1] Initialisation des variables
=========================================================*/
/* 1. Variables utiles */
int read, i, index, pindex; // compteurs
char buffer[MAX_BUF_LEN]; // buffer
struct plane data; // données de l'avion
int SOCKET; // Copie de la socket (évite les conflits de références)
/* 2. On récupère les arguments */
struct handler_arg* arg = THREADABLE_ARGS;
memcpy(&SOCKET, &arg->socket, sizeof(int));
if( DEBUGMOD&HDR ) printf("===== managePlane(%p, %p, %d, %p) =====\n", (void*) arg->managers, (void*) arg->activeManagers, arg->socket, (void*) arg->sgca);
/* 3. On récupère le rang du thread parmi les "managers" */
index = -1;
for( i = 0 ; i < MAX_TCP_THR ; i++ )
if( arg->managers[i] == pthread_self() ){ index = i; break; }
// Erreur de thread
if( index == -1 ){
if( DEBUGMOD&THR ) printf("{tcp_com}(%d) Unknown thread index. Aborting\n", index);
pthread_exit(NULL);
}
while( 1 ){
/* (2) Récupération de la requête
---------------------------------------------------------*/
/* 1. On lit sur la socket */
read = recv(SOCKET, buffer, MAX_BUF_LEN, 0);
/* 2.1. Si erreur reception (-1:erreur, 0:fermeture client propre) */
if( read <= 0 ){
if( DEBUGMOD&BUF ) printf("{tcp_com}(%d) read: %d -> must exit thread\n", index, read);
break;
}
/* 2.2. Si message trop court */
if( read < PLANE_LEN ){
if( DEBUGMOD&BUF ) printf("{tcp_com}(%d) read: %d (expected: %d)\n", index, read, (int) PLANE_LEN);
continue;
}
/* 3. On parse la requête*/
memcpy(&data.code, buffer+sizeof(char)*0+sizeof(int)*0, sizeof(char)*6);
memcpy(&data.x, buffer+sizeof(char)*6+sizeof(int)*0, sizeof(int));
memcpy(&data.y, buffer+sizeof(char)*6+sizeof(int)*1, sizeof(int));
memcpy(&data.z, buffer+sizeof(char)*6+sizeof(int)*2, sizeof(int));
memcpy(&data.spd, buffer+sizeof(char)*6+sizeof(int)*4, sizeof(int));
memcpy(&data.cap, buffer+sizeof(char)*6+sizeof(int)*3, sizeof(int));
/* (3) Gestion de la requête -> enregistrement
---------------------------------------------------------*/
pindex = -1;
/* 1. On regarde si l'avion existe */
for( i = 0 ; i < arg->sgca->n ; i++ ){
// Si l'avion existe -> on passe à la suite
if( strcmp(arg->sgca->data[i].code, data.code) == 0 ){
pindex = i;
break;
}
}
/* 2. Création si n'existe pas */
if( pindex == -1 ){
// On ajoute une entrée à data
pindex = arg->sgca->n;
arg->sgca->n++;
arg->sgca->data = (struct plane*) realloc(arg->sgca->data, sizeof(struct plane)*arg->sgca->n + 1);
printf("{tcp_com}(%d) plane '%s' (#%d) created\n", index, data.code, pindex);
}
/* 3. On copie les constantes */
memcpy(&arg->sgca->data[pindex], &data, sizeof(struct plane));
printf("{tcp_com}(%d) stored (%d)'%s': {x = %d; y = %d; z = %d; cap = %d; spd = %d}\n", index, pindex, arg->sgca->data[pindex].code, arg->sgca->data[pindex].x, arg->sgca->data[pindex].y, arg->sgca->data[pindex].z, arg->sgca->data[pindex].cap, arg->sgca->data[pindex].spd);
/* (4) On prépare la réponse
---------------------------------------------------------*/
/* 1. ACK data */
strcpy(data.code, arg->sgca->data[pindex].code);
data.x = arg->sgca->data[pindex].x;
data.y = arg->sgca->data[pindex].y;
data.z = arg->sgca->data[pindex].z;
data.cap = arg->sgca->data[pindex].cap;
data.spd = arg->sgca->data[pindex].spd;
/* 2. Vérification du FLAG (modifications) si requêtes d'update */
//TODO: Gestion arg->sgca->update[pindex].flags|UPD_SPEED etc.. pour ajout du flag+elements dans reponse
/* 3. On sérialise la réponse */
bzero(buffer, MAX_BUF_LEN*sizeof(char));
memcpy(buffer+sizeof(char)*0+sizeof(int)*0, &data.code, sizeof(char)*6);
memcpy(buffer+sizeof(char)*6+sizeof(int)*0, &data.x, sizeof(int));
memcpy(buffer+sizeof(char)*6+sizeof(int)*1, &data.y, sizeof(int));
memcpy(buffer+sizeof(char)*6+sizeof(int)*2, &data.z, sizeof(int));
memcpy(buffer+sizeof(char)*6+sizeof(int)*4, &data.spd, sizeof(int));
memcpy(buffer+sizeof(char)*6+sizeof(int)*3, &data.cap, sizeof(int));
/* (5) Envoi de la réponse
---------------------------------------------------------*/
read = send(SOCKET, buffer, PLANE_LEN/sizeof(char) + 1, 0);
}
/* [5] On libère la mémoire
=========================================================*/
/* [6] Fermeture de la connection (SOCKET)
=========================================================*/
printf("{tcp_com}(%d) Fermeture de la socket de communication!\n", index);
close(SOCKET);
/* [n] Arrêt du THREAD
============================================================================*/
/* 1. On met à jour "activeManagers" */
if( index != -1 )
arg->activeManagers[index] = 0;
/* 2. On arrête le THREAD */
if( DEBUGMOD&THR ) printf("{tcp_com}(%d) libéré\n", index);
pthread_exit(NULL);
}
/* Gestion d'une connexion TERMINAL
*
* @THREADABLE_SOCKET<void*> SOCKET de la connexion client
*
* @history
* [1] Initialisation des variables
* [2] Récupération de la requête
* [3] Traitement de la requête
* [4] Création de la réponse
* [5] Envoi de la réponse
* [6] On vide les buffers
* [7] Fermeture de la connection (SOCKET)
* [n] Arrêt du THREAD
* 1. On récupère le rang dans les "managers"
* 2. On met à jour "activeManagers"
* 3. On arrête le THREAD
*
*/
void* manageViewTerm(void* THREADABLE_ARGS){
/* [1] Initialisation des variables
=========================================================*/
int read; // compteur
struct sockaddr_in clientInfo;
socklen_t len;
char request[MAX_BUF_LEN]; // Requête
// char response[MAX_BUF_LEN]; // Réponse
/* 2. On récupère les arguments */
struct handler_arg* arg = THREADABLE_ARGS;
do{
printf("{udp_x-term}{udp_com} waiting for terminal request\n");
/* [2] Récupération de la requête
=========================================================*/
/* 1. On lit sur la socket */
len = sizeof(struct sockaddr_in);
read = recvfrom(arg->socket, request, MAX_BUF_LEN, 0, (struct sockaddr*) &clientInfo, &len);
/* 2. Si erreur reception */
if( DEBUGMOD&BUF ) printf("{udp_x-term}{udp_com} READ = %d\n", read);
if( read < 0 )
continue;
/* 3. On désérialise la requête*/
printf("{udp_x-term}{udp_com} TERMINAL Request(%d bytes) : '%s'\n", read, request);
/* [3] Gestion de la requête
=========================================================*/
/* [4] Envoi reponse
=========================================================*/
strcpy(request+strlen(request), "-bla\0");
send(arg->socket, request, strlen(request), 0);
}while( 0 );
/* [n] Arrêt du THREAD
============================================================================*/
/* 1. On récupère le rang dans les "managers" */
int i, index = -1;
for( i = 0 ; i < MAX_UDP_THR ; i++ )
if( arg->managers[i] == pthread_self() ){ index = i; break; }
/* 2. On met à jour "activeManagers" */
if( index != -1 )
arg->activeManagers[index] = 0;
/* 3. On arrête le THREAD */
if( DEBUGMOD&THR ) printf("{udp_x-term}{udp_com}(%d) libéré\n", index);
pthread_exit(NULL);
}
/* Gestion d'une connexion TERMINAL
*
* @THREADABLE_SOCKET<void*> SOCKET de la connexion client
*
* @history
* [1] Initialisation des variables
* [2] Récupération de la requête
* [3] Traitement de la requête
* [4] Création de la réponse
* [5] Envoi de la réponse
* [6] On vide les buffers
* [7] Fermeture de la connection (SOCKET)
* [n] Arrêt du THREAD
* 1. On récupère le rang dans les "managers"
* 2. On met à jour "activeManagers"
* 3. On arrête le THREAD
*
*/
void* manageCtrlTerm(void* THREADABLE_ARGS){
/* [1] Initialisation des variables
=========================================================*/
int read; // compteur
struct sockaddr_in clientInfo;
socklen_t len;
char request[MAX_BUF_LEN]; // Requête
// char response[MAX_BUF_LEN]; // Réponse
/* 2. On récupère les arguments */
struct handler_arg* arg = THREADABLE_ARGS;
do{
printf("{udp_x-term}{udp_com} waiting for terminal request\n");
/* [2] Récupération de la requête
=========================================================*/
/* 1. On lit sur la socket */
len = sizeof(struct sockaddr_in);
read = recvfrom(arg->socket, request, MAX_BUF_LEN, 0, (struct sockaddr*) &clientInfo, &len);
/* 2. Si erreur reception */
if( DEBUGMOD&BUF ) printf("{udp_x-term}{udp_com} READ = %d\n", read);
if( read < 0 )
continue;
/* 3. On désérialise la requête*/
printf("{udp_x-term}{udp_com} TERMINAL Request(%d bytes) : '%s'\n", read, request);
/* [3] Gestion de la requête
=========================================================*/
/* [4] Envoi reponse
=========================================================*/
strcpy(request+strlen(request), "-bla\0");
send(arg->socket, request, strlen(request), 0);
}while( 0 );
/* [n] Arrêt du THREAD
============================================================================*/
/* 1. On récupère le rang dans les "managers" */
int i, index = -1;
for( i = 0 ; i < MAX_UDP_THR ; i++ )
if( arg->managers[i] == pthread_self() ){ index = i; break; }
/* 2. On met à jour "activeManagers" */
if( index != -1 )
arg->activeManagers[index] = 0;
/* 3. On arrête le THREAD */
if( DEBUGMOD&THR ) printf("{udp_x-term}{udp_com}(%d) libéré\n", index);
pthread_exit(NULL);
}

View File

@ -1,114 +0,0 @@
/**************************
* Middleware Dependency *
***************************
* Designed & Developed by *
* Adrien Marquès *
* <xdrm-brackets> *
***************************
* doowap31@gmail.com *
**************************/
#include "middleware.h"
int multicastTerminal(struct middleware_arg* arg){
/* [0] Initialisation
=========================================================*/
struct sockaddr_in comInfo; // contiendra les infos de la socket COM
struct sockaddr_in clientInfo; // contiendra les infos client
socklen_t len; // taille de la socket
int read; // compteurs
char buffer[MAX_BUF_LEN+1]; // buffer requête
struct bind_header request; // requête parsée
/* 1. On attends une connection UDP */
len = sizeof(struct sockaddr_in);
read = recvfrom(arg->listenSock, buffer, MAX_BUF_LEN, 0, (struct sockaddr*) &clientInfo, &len);
/* 2. Si erreur reception ou taille incorrecte -> retour à l'écoute */
if( read < BINDHDR_LEN ){
if( DEBUGMOD&BUF ) printf("{%s} read('%s') = %d bytes (expected: %d)\n", arg->entity, buffer, read, (int) (BINDHDR_LEN) );
return -1;
}
/* 3. On récupère l'adresse IP du client */
if( DEBUGMOD&SCK ) printf("{%s} %s:%d connecté\n", arg->entity, inet_ntoa(clientInfo.sin_addr), ntohs(clientInfo.sin_port));
/* [1] Gestion de la requête
=========================================================*/
/* 1. On parse la requête */
memcpy(&request.flags, buffer, sizeof(char));
memcpy(&request.addr, buffer+sizeof(char), sizeof(char)*15);
memcpy(&request.port, buffer+sizeof(char)*16, sizeof(unsigned short));
printf("{%s} received: bind_header{flag = %d; addr = '%s'; port = %d}\n", arg->entity, (int) request.flags, request.addr, request.port);
/* (1) Création socket de communication (si demandé)
---------------------------------------------------------*/
/* 1. Si on veut un port de communicatin */
if( request.flags&BINDHEAD_SCK ){
/* 2. On bind une socket sur un port random */
if( DROP_UDP_SERVER(SERV_HOST, 0, arg->comSock, &comInfo, 0) < 0 ){
if( DEBUGMOD&SCK ) printf("{%s} Erreur de création de la socket COM\n", arg->entity);
/* 3. On ferme la socket et enleve le FLAG pour dire qu'on a pas pu ouvrir le port */
close(*arg->comSock);
request.flags -= BINDHEAD_SCK;
}
}
/* 2.2 Si on veut on port de communication */
/* (2) Récupération port random
---------------------------------------------------------*/
if( request.flags&BINDHEAD_SCK ){
/* 1. On récupère le port de la socket de communication */
len = sizeof(struct sockaddr_in);
if( getsockname(*arg->comSock, (struct sockaddr*) &comInfo, &len) < 0 ){
if( DEBUGMOD&SCK ) printf("{%s} Erreur de recherche du port COM ouvert\n", arg->entity);
/* 2. On ferme la socket et enleve le FLAG pour dire qu'on a pas pu ouvrir le port */
close(*arg->comSock);
request.flags -= BINDHEAD_SCK;
/* 3. Si on a le port -> on le met dans la reponse */
}else{
strcpy(request.addr, SERV_HOST);
request.port = comInfo.sin_port;
if( DEBUGMOD&SCK ) printf("{%s}{udp_com} socket opened on %s:%d\n", arg->entity, request.addr, ntohs(request.port));
}
}
/* [2] Envoi de la réponse
=========================================================*/
/* 1. On sérialise la réponse */
bzero(buffer, MAX_BUF_LEN*sizeof(char));
memcpy(buffer, &request.flags, sizeof(char));
memcpy(buffer+sizeof(char), &request.addr, sizeof(char)*15);
memcpy(buffer+sizeof(char)*16, &request.port, sizeof(unsigned short));
/* 2. On envoie la réponse*/
len = sizeof(struct sockaddr_in);
if( sendto(arg->listenSock, buffer, BINDHDR_LEN/sizeof(char) + 1, 0, (struct sockaddr*) &clientInfo, len) < 0 ){
printf("{%s} Impossible de répondre au client!\n", arg->entity);
return -2;
}
printf("{%s} sent: bind_header{flag = %d; addr = '%s'; port = %d}\n", arg->entity, (int) request.flags, request.addr, ntohs(request.port));
return 0;
}

View File

@ -1,73 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- You may freely edit this file. See commented blocks below for -->
<!-- some examples of how to customize the build. -->
<!-- (If you delete it and reopen the project it will be recreated.) -->
<!-- By default, only the Clean and Build commands use this build script. -->
<!-- Commands such as Run, Debug, and Test only use this build script if -->
<!-- the Compile on Save feature is turned off for the project. -->
<!-- You can turn off the Compile on Save (or Deploy on Save) setting -->
<!-- in the project's Project Properties dialog box.-->
<project name="CommandTerminal" default="default" basedir=".">
<description>Builds, tests, and runs the project CommandTerminal.</description>
<import file="nbproject/build-impl.xml"/>
<!--
There exist several targets which are by default empty and which can be
used for execution of your tasks. These targets are usually executed
before and after some main targets. They are:
-pre-init: called before initialization of project properties
-post-init: called after initialization of project properties
-pre-compile: called before javac compilation
-post-compile: called after javac compilation
-pre-compile-single: called before javac compilation of single file
-post-compile-single: called after javac compilation of single file
-pre-compile-test: called before javac compilation of JUnit tests
-post-compile-test: called after javac compilation of JUnit tests
-pre-compile-test-single: called before javac compilation of single JUnit test
-post-compile-test-single: called after javac compilation of single JUunit test
-pre-jar: called before JAR building
-post-jar: called after JAR building
-post-clean: called after cleaning build products
(Targets beginning with '-' are not intended to be called on their own.)
Example of inserting an obfuscator after compilation could look like this:
<target name="-post-compile">
<obfuscate>
<fileset dir="${build.classes.dir}"/>
</obfuscate>
</target>
For list of available properties check the imported
nbproject/build-impl.xml file.
Another way to customize the build is by overriding existing main targets.
The targets of interest are:
-init-macrodef-javac: defines macro for javac compilation
-init-macrodef-junit: defines macro for junit execution
-init-macrodef-debug: defines macro for class debugging
-init-macrodef-java: defines macro for class execution
-do-jar: JAR building
run: execution of project
-javadoc-build: Javadoc generation
test-report: JUnit report generation
An example of overriding the target for project execution could look like this:
<target name="run" depends="CommandTerminal-impl.jar">
<exec dir="bin" executable="launcher.exe">
<arg file="${dist.jar}"/>
</exec>
</target>
Notice that the overridden target depends on the jar target and not only on
the compile target as the regular run target does. Again, for a list of available
properties which you can use, check the target you are overriding in the
nbproject/build-impl.xml file.
-->
</project>

View File

@ -1,3 +0,0 @@
Manifest-Version: 1.0
X-COMMENT: Main-Class will be added automatically by build

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +0,0 @@
build.xml.data.CRC32=fdad8e2e
build.xml.script.CRC32=1cd81838
build.xml.stylesheet.CRC32=8064a381@1.74.1.48
# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
nbproject/build-impl.xml.data.CRC32=fdad8e2e
nbproject/build-impl.xml.script.CRC32=95faf5a3
nbproject/build-impl.xml.stylesheet.CRC32=876e7a8f@1.74.1.48

View File

@ -1,73 +0,0 @@
annotation.processing.enabled=true
annotation.processing.enabled.in.editor=false
annotation.processing.processor.options=
annotation.processing.processors.list=
annotation.processing.run.all.processors=true
annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output
build.classes.dir=${build.dir}/classes
build.classes.excludes=**/*.java,**/*.form
# This directory is removed when the project is cleaned:
build.dir=build
build.generated.dir=${build.dir}/generated
build.generated.sources.dir=${build.dir}/generated-sources
# Only compile against the classpath explicitly listed here:
build.sysclasspath=ignore
build.test.classes.dir=${build.dir}/test/classes
build.test.results.dir=${build.dir}/test/results
# Uncomment to specify the preferred debugger connection transport:
#debug.transport=dt_socket
debug.classpath=\
${run.classpath}
debug.test.classpath=\
${run.test.classpath}
# Files in build.classes.dir which should be excluded from distribution jar
dist.archive.excludes=
# This directory is removed when the project is cleaned:
dist.dir=dist
dist.jar=${dist.dir}/CommandTerminal.jar
dist.javadoc.dir=${dist.dir}/javadoc
excludes=
includes=**
jar.compress=false
javac.classpath=
# Space-separated list of extra javac options
javac.compilerargs=
javac.deprecation=false
javac.processorpath=\
${javac.classpath}
javac.source=1.8
javac.target=1.8
javac.test.classpath=\
${javac.classpath}:\
${build.classes.dir}
javac.test.processorpath=\
${javac.test.classpath}
javadoc.additionalparam=
javadoc.author=false
javadoc.encoding=${source.encoding}
javadoc.noindex=false
javadoc.nonavbar=false
javadoc.notree=false
javadoc.private=false
javadoc.splitindex=true
javadoc.use=true
javadoc.version=false
javadoc.windowtitle=
main.class=commandterminal.CommandTerminal
manifest.file=manifest.mf
meta.inf.dir=${src.dir}/META-INF
mkdist.disabled=false
platform.active=default_platform
run.classpath=\
${javac.classpath}:\
${build.classes.dir}
# Space-separated list of JVM arguments used when running the project.
# You may also define separate properties like run-sys-prop.name=value instead of -Dname=value.
# To set system properties for unit tests define test-sys-prop.name=value:
run.jvmargs=
run.test.classpath=\
${javac.test.classpath}:\
${build.test.classes.dir}
source.encoding=UTF-8
src.dir=src
test.src.dir=test

View File

@ -1,15 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://www.netbeans.org/ns/project/1">
<type>org.netbeans.modules.java.j2seproject</type>
<configuration>
<data xmlns="http://www.netbeans.org/ns/j2se-project/3">
<name>CommandTerminal</name>
<source-roots>
<root id="src.dir"/>
</source-roots>
<test-roots>
<root id="test.src.dir"/>
</test-roots>
</data>
</configuration>
</project>

View File

@ -1,69 +0,0 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package commandterminal;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
/**
*
* @author lmascaro
*/
public class CommandTerminal {
private final static int SGCA_MULTICAST_PORT = 4446;
private final static String SCGA_MULTICAST_ADDRESS = "224.0.0.3";
/**
* @param args the command line arguments
*/
public static void main(String[] args){
/*
* Handshake
*/
try {
DatagramSocket socket = new DatagramSocket();
ByteBuffer buf = ByteBuffer.allocate(21);
buf.clear();
buf.put((byte)(0x01|0x02));
DatagramPacket payload = new DatagramPacket(buf.array(),buf.array().length,InetAddress.getByName(SCGA_MULTICAST_ADDRESS),SGCA_MULTICAST_PORT);
socket.send(payload);
socket.receive(payload);
buf = ByteBuffer.wrap(payload.getData());
if(buf.get() == 3){
System.out.println("--Connection request successful");
byte address[] = new byte[15];
buf = buf.get(address,0,15);
String addressString = new String(address);
InetAddress sgcaAddress = InetAddress.getByName(addressString);
//emulate an unsigned short
char cast = buf.getChar();
int port = (int) cast;
System.out.println("----Address : "+sgcaAddress.getHostAddress());
System.out.println("----Port : "+port);
}
} catch ( IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

View File

@ -1,20 +0,0 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package commandterminal;
/**
*
* @author lmascaro
*/
public enum OpCode {
ISALIVE,
CAP,
ALT,
SPEED,
SUCCESS,
ERROR
}

BIN
ctrlTerm/commandTerm.jar Normal file

Binary file not shown.

View File

@ -0,0 +1,208 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package ControlTerminal;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Scanner;
import DatagramSocket.AsynchronousDatagramSocket;
/**
*
* @author lmascaro
*/
public class ControlTerminal {
private final static int SGCA_MULTICAST_PORT = 4446;
private final static String SCGA_MULTICAST_ADDRESS = "224.0.0.3";
/**
* @param args the command line arguments
*/
public static void main(String[] args){
System.out.println("\033[2J");
/*
* Handshake
*/
int port = 0;
String addressString = "0.0.0.0";
try {
DatagramSocket socket = new DatagramSocket();
ByteBuffer buf = ByteBuffer.allocate(21);
buf.clear();
buf.put((byte)(0x05));
DatagramPacket payload = new DatagramPacket(buf.array(),buf.array().length,InetAddress.getByName(SCGA_MULTICAST_ADDRESS),SGCA_MULTICAST_PORT);
socket.send(payload);
socket.receive(payload);
buf = ByteBuffer.wrap(payload.getData());
if(buf.get() == 5){
System.out.println("--Connection request successful");
byte address[] = new byte[4];
buf = buf.get(address,0,4);
InetAddress addressObj = InetAddress.getByAddress(address);
addressString = addressObj.getHostAddress();
//emulate an unsigned short
char cast = buf.getChar();
port = (int) cast;
System.out.println("----Address : "+addressString);
System.out.println("----Port : "+port);
}
} catch ( IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return;
}
/*
* Opening final socket
*/
try {
//create all objects
AsynchronousDatagramSocket socket = new AsynchronousDatagramSocket();
PlaneContainer container = new PlaneContainer();
Printer printer = new Printer();
Pinger pinger = new Pinger(socket,InetAddress.getByName(addressString),port);
//bind them
socket.bindContainer(container);
container.bindPrinter(printer);
container.bindSocket(socket);
printer.bindContainer(container);
//send first packet
InetAddress SGCAaddress = InetAddress.getByName(addressString);
DatagramPacket p = new DatagramPacket(new byte[13],13,SGCAaddress,port);
socket.send(p);
System.out.println("First packet sent");
//send first feedback packet
ByteBuffer buf = ByteBuffer.allocate(27);
buf.put((byte) 0x01);
p = new DatagramPacket(buf.array(),buf.array().length,SGCAaddress,port);
socket.send(p);
System.out.println("Feedback request sent");
System.out.println("length: "+"aze".getBytes().length);
//run Pinger
new Thread(pinger).start();
//now we let the objects do the job
Scanner s = new Scanner(System.in);
int planeNumber;
int data;
Plane plane;
ArrayList<String> keys;
byte flags;
while(true){
String input = s.nextLine();
if(input.length() == 0){
//if empty line, we send a feedback request
buf = ByteBuffer.allocate(27);
buf.put((byte) 0x01);
p = new DatagramPacket(buf.array(),buf.array().length,SGCAaddress,port);
socket.send(p);
System.out.println("Request sent, waiting for response");
}else if(input.equals("u")){
System.out.println("Please enter plane number");
try{
planeNumber = s.nextInt();
}catch(Exception e){
System.out.println("Wrong input please retry");
s.nextLine();
continue;
}
try{
keys = new ArrayList(container.getMap().keySet());
plane = container.getMap().get(keys.get(planeNumber-1));
}catch(Exception e){
System.out.println("Unknown plane please retry");
s.nextLine();
continue;
}
flags = 0x01;
while(true){
System.out.println("Enter the information you want to update (1: alt,2:cap,3:speed)");
try{
data = s.nextInt();
switch(data){
case 1:
System.out.println("Enter the new altitude");
data = s.nextInt();
plane.setZ(data);
flags = (byte) (flags|0x08);
break;
case 2:
System.out.println("Enter the new cap");
data = s.nextInt();
plane.setCap(data);
flags = (byte) (flags|0x02);
break;
case 3:
System.out.println("Enter the new speed");
data = s.nextInt();
plane.setSpeed(data);
flags = (byte) (flags|0x04);
break;
default:
System.out.println("Wrong input please retry");
s.nextLine();
break;
}
}catch(Exception e){
System.out.println("Wrong input please retry");
s.nextLine();
continue;
}
System.out.println("Do you want to update more data on this plane (y/n)");
if(s.next().equals("n")){
break;
}
}
container.setExpectedFlags(flags);
buf = ByteBuffer.allocate(27);
buf.put(flags);
buf.put(plane.toBytes());
p = new DatagramPacket(buf.array(),buf.array().length,SGCAaddress,port);
socket.send(p);
System.out.println("Request sent, waiting for response");
s.nextLine();
}else{
System.out.println("Unknown command, please retry");
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,18 @@
package ControlTerminal;
public class InvalidFlagException extends Exception {
/**
*
*/
private static final long serialVersionUID = 1L;
public InvalidFlagException(){
super();
}
public InvalidFlagException(String message){
super(message);
}
}

View File

@ -0,0 +1,46 @@
package ControlTerminal;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.nio.ByteBuffer;
import DatagramSocket.AsynchronousDatagramSocket;
public class Pinger implements Runnable{
private AsynchronousDatagramSocket socket;
private InetAddress addr;
private int port;
public Pinger(AsynchronousDatagramSocket socket,InetAddress addr,int port){
this.socket = socket;
this.addr = addr;
this.port = port;
}
@Override
public void run() {
DatagramPacket p;
ByteBuffer buf = ByteBuffer.allocate(27);
while(true){
try {
Thread.sleep(8000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
p = new DatagramPacket(buf.array(),buf.array().length,this.addr,this.port);
try {
this.socket.send(p);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}

View File

@ -0,0 +1,125 @@
package ControlTerminal;
import java.io.Serializable;
import java.nio.ByteBuffer;
public class Plane{
private String code;
private int x;
private int y;
private int z;
private int cap;
private int speed;
private boolean isDead;
public Plane(String code,int x, int y, int z, int cap, int speed){
this.code = code;
this.x = x;
this.y = y;
this.z = z;
this.cap = cap;
this.speed = speed;
this.isDead = false;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public int getZ() {
return z;
}
public void setZ(int z) {
this.z = z;
}
public int getCap() {
return cap;
}
public boolean isDead(){
return this.isDead;
}
public void setCap(int cap) {
this.cap = cap;
}
public int getSpeed() {
return speed;
}
public void setSpeed(int speed) {
this.speed = speed;
}
//Die Motherfucker
public void die(){
this.isDead = true;
}
public String getLine(int i){
switch(i){
case 0:
return "--------------------------------";
case 1:
if(this.isDead){
return "\033[4;37;41m Code: "+this.code+"\t\t\t|";
}else{
return "\033[4;37;42m Code: "+this.code+"\t\t\t|";
}
case 2:
return "\033[0m --Coords: {"+this.x+";"+this.y+";"+this.z+"} \t|";
case 3:
return "\033[0m --Cap: "+this.cap+"\t\t\t|";
case 4:
if(this.isDead){
return "\033[4;37;41m ATTENTION: avion hors ligne\t|\033[0m";
}else if(this.speed<300){
return "\033[5;37;41m --Speed: "+this.speed+"\t\t\t|\033[0m";
}else{
return "\033[0m --Speed: "+this.speed+"\t\t\t|";
}
default:
return "";
}
}
public byte[] toBytes(){
ByteBuffer buf = ByteBuffer.allocate(26);
buf.put(this.code.getBytes());
//EOL char
buf.put((byte)0);
buf.putInt(this.x);
buf.putInt(this.y);
buf.putInt(this.z);
buf.putInt(this.cap);
buf.putInt(this.speed);
return buf.array();
}
}

View File

@ -0,0 +1,119 @@
package ControlTerminal;
import java.net.DatagramPacket;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.HashMap;
import DatagramSocket.AsynchronousDatagramSocket;
public class PlaneContainer {
private HashMap<String,Plane> map;
private AsynchronousDatagramSocket socket;
private Printer printer;
private byte expectedFlags = 0x01;
public PlaneContainer(){
this.map = new HashMap<String,Plane>();
}
public void bindSocket(AsynchronousDatagramSocket s){
this.socket = s;
}
public void bindPrinter(Printer p){
this.printer = p;
}
public void setExpectedFlags(byte flags){
this.expectedFlags = flags;
}
public void notifyReceive() throws InvalidFlagException{
DatagramPacket packet = this.socket.synchronousReceive();
ByteBuffer buf = ByteBuffer.wrap(packet.getData());
byte flag;
byte nbrPlane;
ArrayList<String> codes;
flag = buf.get();
nbrPlane = buf.get();
codes = new ArrayList<String>(nbrPlane);
//System.out.println("Processing "+nbrPlane+" planes");
if(this.expectedFlags != flag){
if((this.expectedFlags&(byte)0x02) == 2 && (flag&(byte)0x02) != 2){
System.out.println("\033[5;37;41m Could not apply cap \033[0m");
}
if((this.expectedFlags&(byte)0x04) == 4 && (flag&(byte)0x04) != 4){
System.out.println("\033[5;37;41m Could not apply speed \033[0m");
}
if((this.expectedFlags&(byte)0x08) == 8 && (flag&(byte)0x08) != 8){
System.out.println("\033[5;37;41m Could not apply alt \033[0m");
}
System.out.println("\033[5;37;41m One or more fields could not be updated \033[0m");
if((flag&(byte)0x10) == 1){
System.out.println("\033[5;37;41m Plane crashed gracefully \033[0m");
}
try {
this.expectedFlags = 0x01;
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(flag == 0){
//this is a ping response
return;
}else if((flag&(byte)0x01) != 1){
throw new InvalidFlagException("Flag is not a feedback flag :"+flag);
}else{
String code;
byte rawCode[] = new byte[5];
Plane plane;
for(int i = 0;i<nbrPlane;i++){
//get plane code
buf = buf.get(rawCode,0,5);
code = new String(rawCode);
plane = this.map.get(code);
codes.add(code);
//remove EOL char
buf.get();
if(plane != null){
//fill the plane
plane.setX(buf.getInt());
plane.setY(buf.getInt());
plane.setZ(buf.getInt());
plane.setCap(buf.getInt());
plane.setSpeed(buf.getInt());
}else{
plane = new Plane(code,buf.getInt(),buf.getInt(),buf.getInt(),buf.getInt(),buf.getInt());
this.map.put(code, plane);
}
}
}
//check for dead planes
for(String code : this.map.keySet()){
if(!codes.contains(code)){
this.map.get(code).die();
}
}
this.printer.notifyReceive();
}
public HashMap<String,Plane> getMap(){
return this.map;
}
}

View File

@ -0,0 +1,54 @@
package ControlTerminal;
import java.util.HashMap;
public class Printer {
private PlaneContainer container;
public Printer(){
}
public void bindContainer(PlaneContainer c){
this.container = c;
}
public void notifyReceive(){
System.out.println("\033[2J \033[H");
HashMap<String,Plane> map = this.container.getMap();
int i = 0;
String lines[] = new String[5];
for(int k = 0;k<5;k++){
lines[k] = "";
}
if(map.keySet().size() == 0){
System.out.println("\033[37;43m No plane connected \033[0m");
}else{
for(String code : map.keySet()){
if(i <= 1){
for(int k = 0;k<5;k++){
lines[k] += map.get(code).getLine(k);
}
i++;
}else{
for(int k = 0;k<5;k++){
System.out.println(lines[k]);
lines[k] = "";
}
for(int k = 0;k<5;k++){
lines[k] += map.get(code).getLine(k);
}
i=1;
}
}
for(int k = 0;k<5;k++){
System.out.println(lines[k]);
}
}
System.out.println("Please enter your command (ENTER to update data, u to update a plane)");
}
}

View File

@ -0,0 +1,89 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package DatagramSocket;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
import java.util.logging.Level;
import java.util.logging.Logger;
import ControlTerminal.InvalidFlagException;
import ControlTerminal.PlaneContainer;
/**
*
* @author lmascaro
*/
public class AsynchronousDatagramSocket implements Runnable, AutoCloseable{
public final static int MAX_MESSAGE_SIZE = 300;
private SynchronizedBuffer<DatagramPacket> buf;
private DatagramSocket socket;
private PlaneContainer container;
public AsynchronousDatagramSocket() throws SocketException{
this.buf = new SynchronizedBuffer<>();
this.socket = new DatagramSocket();
new Thread(this).start();
}
public AsynchronousDatagramSocket(int port) throws SocketException{
this.buf = new SynchronizedBuffer<>();
this.socket = new DatagramSocket(port);
new Thread(this).start();
}
public void bindContainer(PlaneContainer c){
this.container = c;
}
public void send(DatagramPacket dp) throws IOException{
this.socket.send(dp);
}
public boolean asynchronousReceive(DatagramPacket dp){
if(this.buf.available() == 0){
return false;
}else{
dp = this.buf.removeElement(false);
return true;
}
}
public DatagramPacket synchronousReceive(){
return this.buf.removeElement(true);
}
public boolean available(){
return this.buf.available()>0;
}
@Override
public void close(){
this.socket.close();
}
@Override
public void run() {
DatagramPacket packet;
while(true){
packet = new DatagramPacket(new byte[MAX_MESSAGE_SIZE],MAX_MESSAGE_SIZE);
try {
this.socket.receive(packet);
this.buf.addElement(packet);
this.container.notifyReceive();
} catch (IOException ex) {
Logger.getLogger(AsynchronousDatagramSocket.class.getName()).log(Level.SEVERE, null, ex);
} catch (InvalidFlagException e) {
System.out.println("\033[01;31m Unexpected flag received \033[0m");
}
}
}
}

View File

@ -23,5 +23,5 @@ all: boot
# cleans the compiled files
clean:
rm boot;
rm ./lib/network/**/*.o
@rm ./lib/network/**/*.o;
@rm ./boot;

View File

@ -10,10 +10,11 @@
#include "client.h"
int TCP_CONNECT(int* pSocket, const char* pAddr, const int pPort, struct sockaddr_in* pInfo){
int TCP_CONNECT(int* pSocket, const in_addr_t pAddr, const int pPort, const time_t pTimeout, struct sockaddr_in* pInfo){
/* [0] Initialisation des variables
=========================================================*/
struct timeval timeout;
*pSocket = -1;
@ -26,6 +27,16 @@ int TCP_CONNECT(int* pSocket, const char* pAddr, const int pPort, struct sockadd
if( *pSocket < 0 )
return -1;
/* 3. Gestion timeout */
timeout.tv_sec = pTimeout;
timeout.tv_usec = 0;
if( setsockopt(*pSocket, SOL_SOCKET, SO_RCVTIMEO, (char*) &timeout, sizeof(struct timeval) ) < 0 ){
close(*pSocket);
return -1;
}
/* [2] On définit les infos de la socket
=========================================================*/
@ -35,7 +46,7 @@ int TCP_CONNECT(int* pSocket, const char* pAddr, const int pPort, struct sockadd
/* (2) On définit les infos */
pInfo->sin_family = AF_INET;
pInfo->sin_port = htons(pPort);
pInfo->sin_addr.s_addr = inet_addr(pAddr);
pInfo->sin_addr.s_addr = pAddr;
/* [3] On se connecte au serveur

View File

@ -18,8 +18,9 @@
/* Créée une socket TCP et la connecte + crée le sockaddr_in pour la suite
*
* ==IN==
* @pAddr<const char*> Adresse du serveur TCP
* @pAddr<const in_addr_t> Adresse du serveur TCP
* @pPort<const int> Port du serveur TCP
* @pTimeout<const time_t> Timeout de réception
*
* ==OUT==
* @pSocket<int*> Pointeur sur le <int> à remplir => contiendra un pointeur sur la socket créée
@ -34,6 +35,6 @@
* [3] On se connecte au serveur
*
*/
int TCP_CONNECT(int* pSocket, const char* pAddr, const int pPort, struct sockaddr_in* pInfo);
int TCP_CONNECT(int* pSocket, const in_addr_t pAddr, const int pPort, const time_t pTimeout, struct sockaddr_in* pInfo);
#endif

View File

@ -35,7 +35,13 @@ int DROP_MULTICAST_SERVER(const char* pAddr, const int pPort, int* pListenSock,
timeout.tv_sec = SOCK_TIMEOUT;
timeout.tv_usec = 0;
if( setsockopt(*pListenSock, SOL_SOCKET, SO_RCVTIMEO|SO_SNDTIMEO, (char*) &timeout, sizeof(struct timeval) ) < 0 ){
if( setsockopt(*pListenSock, SOL_SOCKET, SO_RCVTIMEO, (char*) &timeout, sizeof(struct timeval) ) < 0 ){
close(*pListenSock);
return -1;
}
if( setsockopt(*pListenSock, SOL_SOCKET, SO_SNDTIMEO, (char*) &timeout, sizeof(struct timeval) ) < 0 ){
close(*pListenSock);
return -1;
}

View File

@ -31,6 +31,7 @@ int open_communication(){
char buffer[MAX_BUF_LEN] = {0}; // buffer
int status;
struct bind_header request;
struct in_addr ip; // pour afficher l'ip en dot notation
/* [1] Socket Multicast UDP
=========================================================*/
@ -38,8 +39,13 @@ int open_communication(){
/* (1) Création socket multicast client* (écoute)
---------------------------------------------------------*/
if( DROP_MULTICAST_SERVER(MCST_HOST, MCST_PORT, &mcast_socket, &udp) < 0 )
if( DROP_MULTICAST_SERVER(MCST_HOST, MCST_PORT, &mcast_socket, &udp) < 0 ){
printf("/!\\ Cannot drop multicast server\n");
return 0;
}
printf("* Multicast server bound to multicast group\n");
// *un client multicast est en fait un serveur UDP, mais le terme persiste car le service est délivré par le CLIENT UDP
@ -52,26 +58,39 @@ int open_communication(){
/* 2. Gestion erreur */
if( status < 0 ){
close(mcast_socket);
printf("/!\\ Cannot get TCP credentials (ip/port)\n");
return 0;
}
/* 3. Vérification taille */
if( status < BINDHDR_LEN ){
close(mcast_socket);
printf("/!\\ Invalid TCP credentials (ip/port)\n");
return 0;
}
/* 4. On récupère les données */
bzero(&request, sizeof(struct bind_header));
memcpy(&request.addr, buffer, sizeof(char) );
memcpy(&request.addr, buffer+sizeof(char), sizeof(char)*INET_ADDRSTRLEN );
memcpy(&request.port, buffer+sizeof(char)*(1+INET_ADDRSTRLEN), sizeof(unsigned short) );
memcpy(&request.flags, buffer, sizeof(char) );
memcpy(&request.addr, buffer+sizeof(char), sizeof(in_addr_t) );
memcpy(&request.port, buffer+sizeof(char)+sizeof(in_addr_t), sizeof(unsigned short) );
// on indian-switch
request.addr = ntohl(request.addr);
request.port = ntohs(request.port);
ip.s_addr = request.addr;
/* 5. On vérifie les flags */
if( !(request.flags&BINDHEAD_TCP) || request.flags&BINDHEAD_UDP ){
close(mcast_socket);
printf("/!\\ Received incorrect TCP credentials (ip/port)\n");
return 0;
}
// printf("* hex("); for( int i = 0 ; i < BINDHDR_LEN/sizeof(char) ; i++ ) printf("\\x%02X", buffer[i]); printf(")\n");
printf("* received bind_header{flags = %d; addr = %s; port = %d;}\n\n", request.flags, request.addr, request.port);
printf("* Received TCP credentials (flags: %x, ip: %s:%d)\n", request.flags, inet_ntoa(ip), request.port);
@ -84,8 +103,12 @@ int open_communication(){
/* (1) Création socket TCP + connection
---------------------------------------------------------*/
/* 1. Création socket TCP + connection serveur */
if( TCP_CONNECT(&commu_socket, request.addr, request.port, &sgca) < 0 )
if( TCP_CONNECT(&commu_socket, request.addr, request.port, PAUSE, &sgca) < 0 ){
printf("/!\\ Can't connect to TCP socket\n");
return 0;
}
printf("* Connected to TCP server\n");
return 1;
}
@ -93,12 +116,25 @@ int open_communication(){
void close_communication(){
// fonction à implémenter qui permet de fermer la communication
// avec le gestionnaire de vols
if( commu_socket > -1 )
close(commu_socket);
printf("=== PLANE CRASHED ===\n");
}
void send_data(){
void send_data(char flags){
/* [0] Initialisation des variables
=========================================================*/
@ -106,7 +142,6 @@ void send_data(){
struct plane_data request;
int read;
/* [1] Envoi des caractéristiques
=========================================================*/
/* 1. Vérification socket */
@ -115,39 +150,29 @@ void send_data(){
/* 2. création objet */
strcpy(request.code, numero_vol);
request.x = crd.x;
request.y = crd.y;
request.z = crd.z;
request.cap = ctrl.cap;
request.spd = ctrl.speed;
request.x = htonl( crd.x );
request.y = htonl( crd.y );
request.z = htonl( crd.z );
request.cap = htonl( ctrl.cap );
request.spd = htonl( ctrl.speed );
/* 3. Copie buffer */
strcpy(buffer, request.code);
memcpy(buffer+sizeof(char)*0+sizeof(int)*0, &request.code, sizeof(char)*6 );
memcpy(buffer+sizeof(char)*6+sizeof(int)*0, &request.x, sizeof(int) );
memcpy(buffer+sizeof(char)*6+sizeof(int)*1, &request.y, sizeof(int) );
memcpy(buffer+sizeof(char)*6+sizeof(int)*2, &request.z, sizeof(int) );
memcpy(buffer+sizeof(char)*6+sizeof(int)*3, &request.cap, sizeof(int) );
memcpy(buffer+sizeof(char)*6+sizeof(int)*4, &request.spd, sizeof(int) );
memcpy(buffer+sizeof(char)*0+sizeof(int)*0, &flags, sizeof(char) );
memcpy(buffer+sizeof(char)*1+sizeof(int)*0, &request.code, sizeof(char)*6 );
memcpy(buffer+sizeof(char)*7+sizeof(int)*0, &request.x, sizeof(int) );
memcpy(buffer+sizeof(char)*7+sizeof(int)*1, &request.y, sizeof(int) );
memcpy(buffer+sizeof(char)*7+sizeof(int)*2, &request.z, sizeof(int) );
memcpy(buffer+sizeof(char)*7+sizeof(int)*3, &request.cap, sizeof(int) );
memcpy(buffer+sizeof(char)*7+sizeof(int)*4, &request.spd, sizeof(int) );
read = send(commu_socket, buffer, PLANE_DATA_LEN/sizeof(char) + 1, 0);
read = send(commu_socket, buffer, (1+PLANE_DATA_LEN)/sizeof(char), 0);
if( read <= 0 ){
printf("Erreur d'envoi\n");
printf("Cannot send\n");
return;
}
// printf("* hex("); for( int i = 0 ; i < PLANE_DATA_LEN/sizeof(char) ; i++ ) printf("\\x%02X", buffer[i]); printf(")\n");
/* 4. Récupération réponse */
read = recv(commu_socket, buffer, MAX_BUF_LEN, 0);
if( read < 0 ){
printf("Erreur de réception\n");
return;
}
/* 5. Gestion mise à jour */
//TODO: update_cap etc avec flags
}
@ -156,6 +181,10 @@ void send_data(){
********************************/
// initialise aléatoirement les paramètres initiaux de l'plane
void init_plane(){
// initialisation aléatoire du compteur aléatoire
time_t seed;
@ -181,28 +210,61 @@ void init_plane(){
}
// modifie la valeur de l'plane avec la valeur passée en paramètre
void update_speed(int speed){
if (speed < 0) ctrl.speed = speed;
int update_speed(int speed){
if( speed < 0 )
return -1;
if( speed > VITMAX )
return -1;
ctrl.speed = speed;
return 0;
}
// modifie le cap de l'plane avec la valeur passée en paramètre
void update_cap(int cap){
if ((cap >= 0) && (cap < 360))
int update_cap(int cap){
if( cap < 0 || cap >= 360 )
return -1;
ctrl.cap = cap;
return 0;
}
// modifie l'z de l'plane avec la valeur passée en paramètre
void update_z(int alt){
if (alt < 0)
int update_z(int alt){
if( alt < 0 )
return 01;
crd.z = alt;
return 0;
}
// affiche les caractéristiques courantes de l'plane
void display_data(){
printf("Avion %6s -> localisation : (%d,%d), altitude : %d, vitesse : %d, cap : %d\n", numero_vol, crd.x, crd.y, crd.z, ctrl.speed, ctrl.cap);
printf("| Plane %s | (%d,%d,%d) - speed: %d - cap: %d\n", numero_vol, crd.x, crd.y, crd.z, ctrl.speed, ctrl.cap);
}
// recalcule la localisation de l'plane en fonction de sa speed et de son cap
void calc_ctrl(){
float ctrl_x, ctrl_y;
@ -234,13 +296,67 @@ void calc_ctrl(){
}
// fonction principale : gère l'exécution de l'plane au fil du temps
void update(){
int received;
struct sgca_req request;
char buffer[MAX_BUF_LEN] = {0};
char persistentFlags = REQ_OFF;
while( 1 ){
sleep(PAUSE);
calc_ctrl();
send_data();
send_data(persistentFlags);
persistentFlags = REQ_OFF;
/* [1] Gestion réception avec timeout
=========================================================*/
/* 1. Attente de message */
received = recv(commu_socket, buffer, MAX_BUF_LEN, 0);
/* 2. Si rien -> on reboucle */
if( received != (sizeof(char)+3*sizeof(int)) )
continue;
printf("** Received update request **\n");
/* [2] Gestion de requête de mise à jour
=========================================================*/
/* 1. On parse la requête */
memcpy(&request.flags, buffer, sizeof(char) );
memcpy(&request.z, buffer+sizeof(char), sizeof(int) );
memcpy(&request.cap, buffer+sizeof(char)+sizeof(int), sizeof(int) );
memcpy(&request.spd, buffer+sizeof(char)+sizeof(int)*2, sizeof(int) );
/* 2. On indian-switch */
request.z = ntohl(request.z);
request.cap = ntohl(request.cap);
request.spd = ntohl(request.spd);
printf("Request received { flags = %d; z = %d; cap = %d; speed = %d }\n", request.flags, request.z, request.cap, request.spd);
/* 3. On essaie de mettre à jour en fonction des flags */
if( request.flags&REQ_ALT )
if( update_z(request.z) == -1 )
request.flags -= REQ_ALT;
if( request.flags&REQ_SPD )
if( update_speed(request.spd) == -1 )
request.flags -= REQ_SPD;
if( request.flags&REQ_CAP )
if( update_cap(request.cap) == -1 )
request.flags -= REQ_CAP;
/* [3] Gestion des flags persistents
=========================================================*/
/* 1. On remplit le champ */
persistentFlags = request.flags;
printf("Response flags : %d\n", request.flags);
}
@ -253,10 +369,14 @@ int main(){
display_data();
// on quitte si on arrive à pas contacter le gestionnaire de vols
printf("\n=== CONNECTION PROTOCOL ===\n");
if( !open_communication() ){
printf("/!\\ Cannot connect to SGCA.\n");
exit(1);
}
// on se déplace une fois toutes les initialisations faites
printf("\n=== COMMUNICATION PROTOCOL ===\n");
update();
return EXIT_SUCCESS;
}

View File

@ -49,14 +49,27 @@
int spd;
};
#define BINDHDR_LEN ( sizeof(char)*(1+INET_ADDRSTRLEN)+sizeof(unsigned short) )
#define BINDHEAD_CTL 0x01 // is command terminal (else: view terminal)
#define BINDHEAD_SCK 0x02 // ask for com socket
#define BINDHEAD_TCP 0x04 // ask TCP instead of UDP
#define REQ_FBK 0x01
#define REQ_CAP 0x02
#define REQ_SPD 0x04
#define REQ_ALT 0x08
#define REQ_OFF 0x10
struct sgca_req{
char flags;
int z;
int cap;
int spd;
};
#define BINDHDR_LEN ( sizeof(char)+sizeof(in_addr_t)+sizeof(unsigned short) )
#define BINDHEAD_UDP 0x01 // is terminal (ask for UDP socket)
#define BINDHEAD_TCP 0x02 // is plane (ask for TCP socket)
#define BINDHEAD_CTL 0x04 // is ctrlTerm (else: viewTerm)
struct bind_header{
char flags;
char addr[INET_ADDRSTRLEN];
in_addr_t addr;
unsigned short port;
};

3
sgca/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
.vscode
*.o
boot

View File

@ -21,10 +21,13 @@ lib/local/middleware.o: lib/header.h lib/local/middleware.h lib/local/middleware
lib/local/handler.o: lib/header.h lib/local/handler.h lib/local/handler.c
gcc $(CFLAGS) -c -o lib/local/handler.o lib/local/handler.c
lib/network/common.o: lib/header.h lib/network/common.h lib/network/common.c
gcc $(CFLAGS) -c -o lib/network/common.o lib/network/common.c
# Compiles the SGCA
boot: lib/network/tcp/server.o lib/network/udp/server.o lib/network/udp/client.o lib/local/middleware.o lib/local/handler.o central-manager.h central-manager.c
gcc $(CFLAGS) -o boot lib/network/udp/server.o lib/network/udp/client.o lib/network/tcp/server.o lib/local/middleware.o lib/local/handler.o central-manager.c
boot: lib/network/common.o lib/network/tcp/server.o lib/network/udp/server.o lib/network/udp/client.o lib/local/middleware.o lib/local/handler.o central-manager.h central-manager.c
gcc $(CFLAGS) -o boot lib/network/udp/server.o lib/network/udp/client.o lib/network/common.o lib/network/tcp/server.o lib/local/middleware.o lib/local/handler.o central-manager.c
# Run full compilation
@ -32,6 +35,7 @@ all: boot
# cleans the compiled files
clean:
rm boot;
rm lib/network/**/*.o;
rm lib/local/*.o;
@rm lib/network/*.o;
@rm lib/network/**/*.o;
@rm lib/local/*.o;
@rm boot;

View File

@ -17,60 +17,75 @@
* [0] Initialisation des variables
* [1] Lancement des THREADS d'écoute
* 1. On démarre le SERVEUR TCP d'écoute globale
* 2. On démarre le SERVEUR UDP d'écoute globale
* 2. On récupère l'IP locale
* 3. On démarre le SERVEUR UDP d'écoute globale
* [2] On attends la fin de tous les THREADS
* [3] On libère les variables globale
*
*/
int main(int argc, char* argv[]){
printf("**** Execution tree structure\n");
printf("** [procedureName]\n");
printf("** {threadName}\n");
printf("** [parent]{child}[subchild] Description\n\n\n");
printf("[Copyright (R) 2017]\n");
printf(" - Adrien Marquès aka. xdrm-brackets (C shit)\n");
printf(" - Lucas Mascaro aka. SeekDaSky (java shit)\n");
printf("* From the developers of the 'WebSocket' library for the UPPA University\n\n\n");
printf("Notice: {threadName}{subThread}(subThreadId)\n\n");
printf("**** Execution tree\n");
/* [0] Initialisation des variables
=========================================================*/
/* 1. Variables globales */
sgca.n = 0;
sgca.data = (struct plane*) malloc( sizeof(struct plane) );
sgca.unit = (struct context_unit*) malloc( sizeof(struct context_unit) );
struct in_addr* SERV_HOST;
/* 2. Variables locales */
struct listen_arg tcp_listn_arg = { SERV_HOST, TCP_LIST, NULL, &managePlane };
struct listen_arg udp_mcast_arg = { MCST_HOST, UDP_MCST, NULL, NULL };
struct listen_arg udp_vterm_arg = { MCST_VTER, UDP_VTER, &multicastTerminal, &manageViewTerm };
struct listen_arg udp_cterm_arg = { MCST_CTER, UDP_CTER, &multicastTerminal, &manageCtrlTerm };
/* 2. On récupère l'IP locale' */
SERV_HOST = GET_LOCAL_IP();
if( SERV_HOST == NULL ){
printf("/!\\ Cannot fetch local ip address. Aborting!\n");
free(sgca.unit);
return EXIT_FAILURE;
}
printf("LOCAL IP: %s\n", inet_ntoa(*SERV_HOST));
/* 3. Variables locales */
struct listen_arg tcp_listn_arg = { SERV_HOST->s_addr, TCP_LIST, NULL, &managePlane };
struct listen_arg udp_mcast_arg = { inet_addr(MCST_HOST), UDP_MCST, NULL, NULL };
struct listen_arg udp_vterm_arg = { inet_addr(MCST_VTER), UDP_VTER, &multicastTerminal, &manageViewTerm };
struct listen_arg udp_cterm_arg = { inet_addr(MCST_CTER), UDP_CTER, &multicastTerminal, &manageCtrlTerm };
/* [1] Lancement des THREADS d'écoute
=========================================================*/
/* (1) Ecoute TCP */
pthread_create(&listenManagers[0], NULL, LISTEN_TCP, (void*) &tcp_listn_arg);
if( DEBUGMOD&THR ) printf("{tcp_listn} démarré\n");
if( DEBUGMOD&THR ) printf("{tcp_listn} started\n");
/* (2) Ecoute UDP multicast */
pthread_create(&listenManagers[1], NULL, MCAST_PUBLISH, (void*) &udp_mcast_arg);
if( DEBUGMOD&THR ) printf("{udp_mcast} démarré\n");
if( DEBUGMOD&THR ) printf("{udp_mcast} started\n");
/* (3) Ecoute UDP viewTerm */
pthread_create(&listenManagers[2], NULL, LISTEN_UDP, (void*) &udp_vterm_arg);
if( DEBUGMOD&THR ) printf("{udp_vterm} démarré\n");
if( DEBUGMOD&THR ) printf("{udp_vterm} started\n");
/* (4) Ecoute UDP ctrlTerm */
pthread_create(&listenManagers[3], NULL, LISTEN_UDP, (void*) &udp_cterm_arg);
if( DEBUGMOD&THR ) printf("{udp_cterm} démarré\n");
if( DEBUGMOD&THR ) printf("{udp_cterm} started\n");
/* [2] On attends la fin de tous les THREADS
==========================================================*/
for( char i = 0 ; i < 4 ; i++ )
char i;
for( i = 0 ; i < 4 ; i++ )
pthread_join(listenManagers[(int)i], NULL);
/* [3] On libère les variables globales
==========================================================*/
free(sgca.data);
free(sgca.unit);
return EXIT_SUCCESS;
}
@ -96,7 +111,10 @@ void* LISTEN_TCP(void* THREADABLE_ARGS){
socklen_t len; // taille de la socket
int index, i; // compteurs
struct listen_arg* arg = THREADABLE_ARGS; // Addr + Port serveur
struct in_addr ip; // Pour afficher l'IP en dot notation
int rtnPort; // Port utilisé par le serveur
ip.s_addr = arg->addr;
// retour de @DROP_TCP_SERVER
int LISTENSOCK; // contiendra la socket d'écoute TCP
@ -104,12 +122,13 @@ void* LISTEN_TCP(void* THREADABLE_ARGS){
/* [1] On démarre le SERVEUR TCP d'écoute globale
==========================================================*/
if( DROP_TCP_SERVER(arg->port, &LISTENSOCK) < 0 ){
rtnPort = DROP_TCP_SERVER(arg->port, &LISTENSOCK);
if( rtnPort < 0 ){
if( DEBUGMOD&SCK ) printf("{tcp_listn} Erreur création socket d'écoute\n");
if( DEBUGMOD&SCK ) printf("{tcp_listn} Error creating listener socket\n");
// On ferme la SOCKET d'écoute globale
printf("{tcp_listn} FERMETURE SOCKET D'ECOUTE TCP!\n");
printf("{tcp_listn} Closing listener socket!\n");
close(LISTENSOCK);
return NULL;
@ -117,7 +136,9 @@ void* LISTEN_TCP(void* THREADABLE_ARGS){
printf("{tcp_listn} listen on %s:%d\n", arg->addr, arg->port);
printf("{tcp_listn} listen on %s:%d\n", inet_ntoa(ip), rtnPort);
if( rtnPort != arg->port )
printf("{tcp_listn} /!\\ Another SGCA might be running, port %d is already used\n", arg->port);
@ -139,7 +160,7 @@ void* LISTEN_TCP(void* THREADABLE_ARGS){
break;
}
if( DEBUGMOD&SCK ) printf("{tcp_listn} %s:%d connecté\n", inet_ntoa(clientInfo.sin_addr), ntohs(clientInfo.sin_port));
if( DEBUGMOD&SCK ) printf("{tcp_listn} %s:%d connected\n", inet_ntoa(clientInfo.sin_addr), ntohs(clientInfo.sin_port));
/* 4. On cherche un "manager" libre (inactif) */
for( i = 0 ; i < MAX_TCP_THR ; i++ )
@ -149,18 +170,18 @@ void* LISTEN_TCP(void* THREADABLE_ARGS){
if( index != -1 ){
// Construction arguments thread
struct handler_arg thread_args = { TCPManagers, activeTCPManagers, CLIENT_SOCKET, &sgca };
struct handler_arg thread_args = { TCPManagers, UDPManagers, activeTCPManagers, activeUDPManagers, CLIENT_SOCKET, &sgca };
/* 5. On lance un thread pour le traitement de ce client */
pthread_create(&TCPManagers[index], NULL, arg->handler, (void*) &thread_args);
if( DEBUGMOD&THR ) printf("{tcp_listn}{com}(%d) démarré\n", index);
if( DEBUGMOD&THR ) printf("{tcp_listn}{com}(%d) started\n", index);
/* 6. On signale que ce "manager" est maintenant actif */
activeTCPManagers[index] = 1;
}else
if( DEBUGMOD&THR ) printf("{tcp_listn} Aucun thread libre\n");
if( DEBUGMOD&THR ) printf("{tcp_listn} No available thread\n");
}
@ -173,7 +194,7 @@ void* LISTEN_TCP(void* THREADABLE_ARGS){
/* [4] On ferme la SOCKET d'écoute globale
==========================================================*/
printf("{tcp_listn} FERMETURE SOCKET D'ECOUTE TCP!\n");
printf("{tcp_listn} Closing listener socket\n");
close(LISTENSOCK);
return NULL;
@ -212,33 +233,45 @@ void* LISTEN_UDP(void* THREADABLE_ARGS){
char entity[10]; // identifiant pour debug
int returned; // Contrôle d'exécution middleware
struct middleware_arg marg; // paramètres pour middleware
struct in_addr ip; // Permet d'afficher les IP en dot notation
int rtnPort; // Returned port (if already used)
/* 2. On parse les arguments */
struct listen_arg* arg = THREADABLE_ARGS; // Addr + Port serveur
if( strcmp(arg->addr, MCST_VTER) == 0 && arg->port == UDP_VTER ) strcpy(entity, "udp_vterm");
if( strcmp(arg->addr, MCST_CTER) == 0 && arg->port == UDP_CTER ) strcpy(entity, "udp_cterm");
if( strcmp(arg->addr, MCST_HOST) == 0 && arg->port == UDP_MCST ) strcpy(entity, "udp_mcast");
if( arg->port == UDP_VTER ) strcpy(entity, "udp_vterm");
if( arg->port == UDP_CTER ) strcpy(entity, "udp_cterm");
if( arg->port == UDP_MCST ) strcpy(entity, "udp_mcast");
// retour de @DROP_UDP_SERVER
int SOCKET;
ip.s_addr = arg->addr;
/* [1] On démarre le SERVEUR UDP d'écoute globale
==========================================================*/
if( DROP_UDP_SERVER(arg->addr, arg->port, &SOCKET, &listenInfo, strcmp(arg->addr, SERV_HOST) != 0) < 0 ){
/* 1. On crée la socket */
rtnPort = DROP_UDP_SERVER(arg->addr, arg->port, &SOCKET, &listenInfo, 1);
if( rtnPort < 0 ){
if( DEBUGMOD&SCK ) printf("{%s} Erreur de création socket d'écoute\n", entity);
if( DEBUGMOD&SCK ) printf("{%s} Error creating listener socket\n", entity);
// On ferme la SOCKET d'écoute globale
printf("{%s} FERMETURE SOCKET D'ECOUTE UDP!\n", entity);
printf("{%s} Closing listener socket!\n", entity);
close(SOCKET);
return NULL;
}
printf("{%s} listen on %s:%d\n", entity, arg->addr, arg->port);
/* 2. On définit un timeout d'envoi */
setTimeout(SOCKET, SOCK_TIMEOUT, TIMEOUT_SEND);
if( DEBUGMOD&SCK ) printf("{%s} SEND timeout set to %d\n", entity, SOCK_TIMEOUT);
printf("{%s} listen on %s:%d\n", entity, inet_ntoa(ip), rtnPort);
if( rtnPort != arg->port )
printf("{%s} /!\\ Another SGCA might be running, port %d is already used\n", entity, arg->port);
@ -293,18 +326,19 @@ void* LISTEN_UDP(void* THREADABLE_ARGS){
if( index != -1 ){
// Construction arguments thread
struct handler_arg thread_args = { UDPManagers, activeUDPManagers, CLIENT_SOCKET, &sgca };
struct handler_arg thread_args = { TCPManagers, UDPManagers, activeTCPManagers, activeUDPManagers, CLIENT_SOCKET, &sgca };
/* 2.1. On lance un thread pour le traitement de ce client */
pthread_create(&UDPManagers[index], NULL, arg->handler, (void*) &thread_args);
if( DEBUGMOD&THR ) printf("{%s}{udp_com}(%d) démarré\n", entity, index);
if( DEBUGMOD&THR ) printf("{%s}{com}(%d) started\n", entity, index);
/* 2.2. On signale que ce "manager" est maintenant actif */
activeUDPManagers[index] = 1;
}else
if( DEBUGMOD&THR ) printf("{%s} Aucun thread UDP libre!\n", entity);
if( DEBUGMOD&THR ) printf("{%s} No available thread\n", entity);
}
@ -312,7 +346,7 @@ void* LISTEN_UDP(void* THREADABLE_ARGS){
/* [n] On ferme la SOCKET d'écoute globale
==========================================================*/
printf("{%s} FERMETURE SOCKET D'ECOUTE UDP!\n", entity);
printf("{%s} Closing listener socket\n", entity);
close(SOCKET);
return NULL;
@ -342,6 +376,7 @@ void* MCAST_PUBLISH(void* THREADABLE_ARGS){
struct sockaddr_in targetInfo; // contiendra les infos de la cible de la socket client
char buffer[MAX_BUF_LEN]; // buffer de requêtes (envois)
struct bind_header request; // requête brute
struct in_addr ip; // Permet d'afficher les IP en dot notation
/* 2. On parse les arguments */
struct listen_arg* arg = THREADABLE_ARGS; // Addr + Port serveur
@ -349,6 +384,8 @@ void* MCAST_PUBLISH(void* THREADABLE_ARGS){
// retour de @UDP_SOCKET
int SOCKET;
ip.s_addr = arg->addr;
/* [1] On initialise la socket CLIENT UDP
==========================================================*/
@ -363,7 +400,7 @@ void* MCAST_PUBLISH(void* THREADABLE_ARGS){
return NULL;
}
printf("{udp_mcast} bound to %s:%d\n", arg->addr, arg->port);
printf("{udp_mcast} bound to %s:%d\n", inet_ntoa(ip), arg->port);
/* [2] On construit la requête à envoyer
@ -371,15 +408,24 @@ void* MCAST_PUBLISH(void* THREADABLE_ARGS){
/* 1. Initialisation du buffer */
bzero(buffer, MAX_BUF_LEN*sizeof(char));
/* 2. Remplissage de la requête brute */
/* 2. On récupère l'IP locale */
struct in_addr* servip = GET_LOCAL_IP();
if( servip == NULL ){
printf("{udp_mcast} /!\\ Cannot fetch local ip address. Aborting!\n");// On ferme la SOCKET d'écoute globale
printf("{udp_mcast} Closing publisher socket!\n");
close(SOCKET);
return NULL;
}
/* 3. Remplissage de la requête brute */
request.flags = BINDHEAD_TCP;
strcpy(request.addr, SERV_HOST);
request.addr = htonl(servip->s_addr);
request.port = htons(TCP_LIST);
/* 3. Copie dans le buffer */
memcpy(buffer, &request.flags, sizeof(char));
memcpy(buffer+sizeof(char), &request.addr, sizeof(char)*INET_ADDRSTRLEN);
memcpy(buffer+sizeof(char)*(INET_ADDRSTRLEN+1), &request.port, sizeof(unsigned short));
/* 4. Copie dans le buffer */
memcpy(buffer, &request.flags, sizeof(char) );
memcpy(buffer+sizeof(char), &request.addr, sizeof(in_addr_t) );
memcpy(buffer+sizeof(char)+sizeof(in_addr_t), &request.port, sizeof(unsigned short) );
while( 1 ){
@ -392,7 +438,7 @@ void* MCAST_PUBLISH(void* THREADABLE_ARGS){
/* [4] On envoie les information de la socket TCP
=========================================================*/
if( sendto(SOCKET, buffer, BINDHDR_LEN / sizeof(char) + 1, 0, (struct sockaddr*) &targetInfo, sizeof(struct sockaddr_in)) < 0 ){
printf("{udp_mcast} Erreur d'envoi\n");
printf("{udp_mcast} Cannot publish credentials\n");
break;
}
@ -403,7 +449,7 @@ void* MCAST_PUBLISH(void* THREADABLE_ARGS){
/* [n] On ferme la SOCKET CLIENT UDP
==========================================================*/
printf("{udp_mcast} FERMETURE SOCKET CLIENT UDP!\n");
printf("{udp_mcast} Closing publisher socket\n");
close(SOCKET);
return NULL;

View File

@ -8,10 +8,12 @@
* doowap31@gmail.com *
**************************/
#include "lib/header.h"
#include <ifaddrs.h>
/* local dependencies */
#include "lib/network/common.h"
#include "lib/network/tcp/server.h"
#include "lib/network/udp/server.h"
#include "lib/network/udp/client.h"

21
sgca/install/install.sh Executable file
View File

@ -0,0 +1,21 @@
#!/bin/bash
# [1] Create script file
cd `pwd`/..;
make all;
cp boot install/sgca;
make clean;
cd install;
# [2] Create service target (boot)
sudo ln -s $(pwd)/sgca /usr/sbin/sgca;
# [3] Create service unit
sudo ln -s $(pwd)/sgca.service /lib/systemd/system/sgca.service;
# [4] Enable service (optional if no [Install])
sudo systemctl enable sgca.service;
# [5] Create log file
sudo touch /var/log/sgca;

View File

@ -5,6 +5,6 @@ Requires=network.target
[Service]
Type=simple
User=xdrm-brackets
Group=xdrm-brackets
ExecStart=/usr/sbin/sgca /var/log/sgca
User=root
Group=root
ExecStart=/usr/sbin/sgca

View File

@ -4,8 +4,12 @@
sudo rm /usr/sbin/sgca;
# [2] Disable service
sudo systemctl stop sgca.service;
sudo systemctl disable sgca.service;
# [3] Remove service unit
sudo rm /lib/systemd/system/sgca.service;
# [4] Remove log file
sudo rm /var/log/sgca;

View File

@ -17,6 +17,7 @@
#define TERMREQ_CAP 0x02
#define TERMREQ_SPD 0x04
#define TERMREQ_ALT 0x08
#define TERMREQ_OFF 0x10
#define PLANE_LEN ( sizeof(char)*6+sizeof(int)*5 )
struct plane{
@ -26,11 +27,21 @@
int z;
int cap;
int spd;
char online;
};
struct plane_update{
char flags;
int z;
int cap;
int spd;
char done;
};
#define TERMREQ_LEN ( sizeof(char)+PLANE_LEN )
struct term_req{
char flags;
struct plane udpate;
struct plane update;
};
struct term_res{
@ -40,14 +51,14 @@
};
#define BINDHDR_LEN ( sizeof(char)*(1+INET_ADDRSTRLEN)+sizeof(unsigned short) )
#define BINDHEAD_CTL 0x01 // is command terminal (else: view terminal)
#define BINDHEAD_SCK 0x02 // ask for com socket (terminal)
#define BINDHEAD_TCP 0x04 // ask TCP com socket (plane)
#define BINDHDR_LEN ( sizeof(char)+sizeof(in_addr_t)+sizeof(unsigned short) )
#define BINDHEAD_UDP 0x01 // is terminal (ask for UDP socket)
#define BINDHEAD_TCP 0x02 // is plane (ask for TCP socket)
#define BINDHEAD_CTL 0x04 // is ctrlTerm (else: viewTerm)
struct bind_header{
char flags;
char addr[INET_ADDRSTRLEN];
in_addr_t addr;
unsigned short port;
};

View File

@ -14,12 +14,16 @@
#define BUFFERS 0x04 // debug des BUFFERS
#define HEADERS 0x08 // debug des HEADERS de fonctions
#define THREADS 0x10 // debug des THREADS
#define COMMUNI 0x20 // debug des COMMUNICATIONS
#define SOCKADV 0x40 // debug des ADVANCED SOCKET
#define SCK 0x01 // FILTRE pour SOCKET
#define RVL 0x02 // FILTRE pour REVEALS
#define BUF 0x04 // FILTRE pour BUFFERS
#define HDR 0x08 // FILTRE pour HEADERS
#define THR 0x10 // FILTRE pour THREADS
#define COM 0x20 // FILTRE pour COMMUNICATIONS
#define SAD 0x40 // FILTRE pour ADVANCED SOCKET
// possibilité de cumuler les DEBUGMODES
#define DEBUGMOD ( SOCKETS | THREADS | BUFFERS ) // REVEALS + HEADER + THREADS

View File

@ -20,6 +20,7 @@
#include <pthread.h>
#include <stdint.h>
#include <errno.h>
#include <signal.h>
/* sys */
#include <sys/types.h>
@ -36,7 +37,6 @@
#include "data.h"
/* vars */
#define SERV_HOST "127.0.0.1" // adresse serveur
#define MCST_HOST "224.0.0.1" // adresse groupe multicast UDP -> plane
#define MCST_VTER "224.0.0.2" // adresse groupe multicast UDP -> viewTerm
#define MCST_CTER "224.0.0.3" // adresse groupe multicast UDP -> ctrlTerm
@ -52,13 +52,21 @@
#define maxHostLen 64
#define maxPortLen 6
#define SOCK_TIMEOUT 3 // 3sec timeout (1+ temps refresh plane)
#define CTRL_TIMEOUT 10 // 10sec timeout (pour ctrlTerm)
#define SOCK_TIMEOUT 4 // 4sec timeout (1+ temps refresh plane)
#define PUBL_TIMEOUT 2 // 2sec entre chaque publication sur multicast UDP (pour avions)
struct context_unit{
int socket; // socket associée à un avion
struct plane data; // données d'un avion
char thrId; // TCP thread index
char flags; // persistent flags
};
struct context{
unsigned int n; // nombre d'avions
struct plane* data; // buffer tes données avion
struct context_unit* unit; // les données des avions
};
struct middleware_arg{
@ -68,14 +76,16 @@
};
struct handler_arg{
pthread_t* managers;
int* activeManagers;
pthread_t* TCPManagers;
pthread_t* UDPManagers;
int* activeTCPManagers;
int* activeUDPManagers;
int socket;
struct context* sgca;
};
struct listen_arg{
const char addr[16]; // socket address
in_addr_t addr; // socket address
const unsigned short port; // socket port
int (*middleware)(struct middleware_arg*); // middleware function
void* (*handler)(void*); // management function (thread)

615
sgca/lib/local/handler.c Normal file
View File

@ -0,0 +1,615 @@
/**************************
* Handler Dependency *
***************************
* Designed & Developed by *
* Adrien Marquès *
* <xdrm-brackets> *
***************************
* doowap31@gmail.com *
**************************/
#include "handler.h"
/* Gestion d'une connexion PLANE
*
* @THREADABLE_SOCKET<void*> SOCKET de la connexion client
*
* @history
* [1] Initialisation des variables
* @loop
* (2) Attente de requête
* (3) Gestion de la requête
* (4) Envoi de la réponse
* [5] On notifie que l'avion est déconnecté (crash)
* [6] On libère la mémoire
* [7] Fermeture de la connection (SOCKET)
* [n] Arrêt du THREAD
* 1. On met à jour "activeManagers"
* 2. On arrête le THREAD
*
*/
void* managePlane(void* THREADABLE_ARGS){
/* [1] Initialisation des variables
=========================================================*/
/* 1. Variables utiles */
int read, i, index, pindex; // compteurs
char buffer[MAX_BUF_LEN]; // buffer
struct plane data; // données de l'avion
int SOCKET; // Copie de la socket (évite les conflits de références)
char tmpFlags;
/* 2. On récupère les arguments */
struct handler_arg* arg = THREADABLE_ARGS;
memcpy(&SOCKET, &arg->socket, sizeof(int));
if( DEBUGMOD&HDR ) printf("===== managePlane(%p, %p, %d, %p) =====\n", (void*) arg->TCPManagers, (void*) arg->activeTCPManagers, arg->socket, (void*) arg->sgca);
/* 3. On récupère le rang du thread parmi les "managers" */
index = -1;
for( i = 0 ; i < MAX_TCP_THR ; i++ )
if( arg->TCPManagers[i] == pthread_self() ){ index = i; break; }
// Erreur de thread
if( index == -1 ){
if( DEBUGMOD&THR ) printf("{tcp_com}(%d) Unknown thread index. Aborting\n", index);
pthread_exit(NULL);
}
pindex = -1; // on ne connait pas encore l'avion
while( 1 ){
/* (2) Récupération de la requête
---------------------------------------------------------*/
/* 1. On lit sur la socket */
read = recv(SOCKET, buffer, MAX_BUF_LEN, 0);
/* 2.1. Si erreur reception (-1:erreur, 0:fermeture client propre) */
if( read <= 0 ){
if( DEBUGMOD&BUF ) printf("{tcp_com}(%d) Error receiving (%d), must exit thread\n", index, read);
break;
}
/* 2.2. Si message trop court */
if( read != PLANE_LEN+1 ){
if( DEBUGMOD&BUF ) printf("{tcp_com}(%d) Error receiving (%d bytes, but %d expected)\n", index, read, (int) (PLANE_LEN+1) );
continue;
}
/* 3. On parse la requête (indianness: network order) */
memcpy(&tmpFlags, buffer+sizeof(char)*0+sizeof(int)*0, sizeof(char) );
memcpy(&data.code, buffer+sizeof(char)*1+sizeof(int)*0, sizeof(char)*6 );
memcpy(&data.x, buffer+sizeof(char)*7+sizeof(int)*0, sizeof(int) );
memcpy(&data.y, buffer+sizeof(char)*7+sizeof(int)*1, sizeof(int) );
memcpy(&data.z, buffer+sizeof(char)*7+sizeof(int)*2, sizeof(int) );
memcpy(&data.spd, buffer+sizeof(char)*7+sizeof(int)*4, sizeof(int) );
memcpy(&data.cap, buffer+sizeof(char)*7+sizeof(int)*3, sizeof(int) );
/* 4. Gestion de l'indianness */
data.x = ntohl(data.x);
data.y = ntohl(data.y);
data.z = ntohl(data.z);
data.cap = ntohl(data.cap);
data.spd = ntohl(data.spd);
data.online = 1;
/* (3) Gestion de la requête -> enregistrement
---------------------------------------------------------*/
/* 1. On cherche le rang de l'avion si on l'a pas déja */
if( pindex <= -1 ){
/* 2. On regarde si l'avion existe */
for( i = 0 ; i < arg->sgca->n ; i++ ){
// Si l'avion existe -> on passe à la suite
if( strcmp(arg->sgca->unit[i].data.code, data.code) == 0 ){
pindex = i;
break;
}
}
}
/* 3. Création si n'existe pas */
if( pindex <= -1 ){
// On ajoute une entrée à data + socket
pindex = arg->sgca->n;
arg->sgca->n++;
arg->sgca->unit = (struct context_unit*) realloc(arg->sgca->unit, sizeof(struct context_unit)*arg->sgca->n + 1);
arg->sgca->unit[pindex].socket = SOCKET;
arg->sgca->unit[pindex].thrId = 0xf0;
printf("{tcp_com}(%d) plane '%s' (#%d) created\n", index, data.code, pindex);
}
/* 4. On copie/met à jour les valeurs */
if( tmpFlags != TERMREQ_OFF ){ // gestion réponse ctrlTerm
arg->sgca->unit[pindex].flags = tmpFlags; // on met à jour les flags
while( arg->sgca->unit[pindex].thrId == 0xf0 ); // on attend le numéro de thread
printf("{tcp_com}(%d) Waking up UDP threaad@%d for ctrlTerm response\n", index, arg->sgca->unit[pindex].thrId);
pthread_kill(arg->UDPManagers[(int)arg->sgca->unit[pindex].thrId], SIGCONT); // on réveille le thread
arg->sgca->unit[pindex].thrId = 0xf0; // on laisse la place pour qqn d'autre
}
memcpy(&arg->sgca->unit[pindex].data, &data, sizeof(struct plane));
if( DEBUGMOD&COM ) printf("{tcp_com}(%d) stored (%d)'%s': {x = %d; y = %d; z = %d; cap = %d; spd = %d}\n", index, pindex, arg->sgca->unit[pindex].data.code, arg->sgca->unit[pindex].data.x, arg->sgca->unit[pindex].data.y, arg->sgca->unit[pindex].data.z, arg->sgca->unit[pindex].data.cap, arg->sgca->unit[pindex].data.spd);
}
/* [5] On notifie que l'avoin est déconnecté (crash)
=========================================================*/
/* 1. On notifie le crash */
arg->sgca->unit[pindex].data.online = 0;
arg->sgca->unit[pindex].socket = -1;
/* [6] On libère la mémoire
=========================================================*/
/* [7] Fermeture de la connection (SOCKET)
=========================================================*/
printf("{tcp_com}(%d) Closing communication socket\n", index);
close(SOCKET);
/* [n] Arrêt du THREAD
============================================================================*/
/* 1. On met à jour "activeManagers" */
if( index != -1 )
arg->activeTCPManagers[index] = 0;
/* 2. On arrête le THREAD */
if( DEBUGMOD&THR ) printf("{tcp_com}(%d) freed\n", index);
pthread_exit(NULL);
}
/* Gestion d'une connexion TERMINAL
*
* @THREADABLE_SOCKET<void*> SOCKET de la connexion client
*
* @history
* [1] Initialisation des variables
*
* @loop
* [2] Récupération des données
* [3] Construction de la requête
* [4] Envoi de la requête
* [5] Timeout
*
* [6] On vide les buffers
* [7] Fermeture de la connection (SOCKET)
* [n] Arrêt du THREAD
* 1. On récupère le rang dans les "managers"
* 2. On met à jour "activeManagers"
* 3. On arrête le THREAD
*
*/
void* manageViewTerm(void* THREADABLE_ARGS){
/* [1] Initialisation des variables
=========================================================*/
/* 1. Initialisation des variables */
struct sockaddr_in clientInfo;
socklen_t len;
char loop = 1;
size_t buflen;
int sent; // compteurs d'envoi
int i, index = -1; // Compteurs globaux
char* buffer = malloc(1); // Buffer d'envoi
int SOCKET;
/* 2. On récupère les arguments */
struct handler_arg* arg = THREADABLE_ARGS;
memcpy(&SOCKET, &arg->socket, sizeof(int));
/* 3. On récupère le rang dans les "managers" */
for( i = 0 ; i < MAX_UDP_THR ; i++ )
if( arg->UDPManagers[i] == pthread_self() ){ index = i; break; }
printf("{udp_vterm}{com}(%d) starting terminal routine (rate: %d sec)\n", index, PUBL_TIMEOUT);
/* 4. Attente d'un client */
len = sizeof(struct sockaddr_in);
if( recvfrom(SOCKET, buffer, MAX_BUF_LEN*sizeof(char), 0, (struct sockaddr*) &clientInfo, &len) < 0 ){
printf("{udp_vterm}{com}(%d) No terminal detected, exiting\n", index);
loop = 0;
}
if( loop ) printf("{udp_cterm}{com}(%d) Terminal connected\n", index);
while( loop ){
/* [2] Récupération des données
=========================================================*/
getPlaneData(&buffer, &buflen, arg->sgca);
/* [3] Envoi de la requête
=========================================================*/
/* 2. Envoi */
len = sizeof(struct sockaddr_in);
sent = sendto(SOCKET, buffer, buflen + 1, 0, (struct sockaddr*) &clientInfo, len);
/* 3. Gestion erreur */
if( sent <= 0 ){
printf("{udp_vterm}{com}(%d) Unable to send data\n", index);
break;
}
/* [4] Réception feedback
=========================================================*/
/* 1. Réception feedback (0x10) */
len = sizeof(struct sockaddr_in);
sent = recvfrom(SOCKET, buffer, 1, 0, (struct sockaddr*) &clientInfo, &len);
/* 2. Gestion erreur (erreur ou mauvais feedback != 0x10) */
if( sent <= 0 || buffer[0] != TERMREQ_OFF ){
printf("{udp_vterm}{com}(%d) Unable to recv feedback -> exiting\n", index);
break;
}
/* [4] Timeout
=========================================================*/
sleep(PUBL_TIMEOUT);
}
/* [n] Arrêt du THREAD
============================================================================*/
/* 1. On met à jour "activeManagers" */
if( index != -1 )
arg->activeUDPManagers[index] = 0;
/* 2. On ferme la socket + libère la mémoire */
close(SOCKET);
free(buffer);
/* 3. On arrête le THREAD */
if( DEBUGMOD&THR ) printf("{udp_vterm}{com}(%d) freed\n", index);
pthread_exit(NULL);
}
/* Gestion d'une connexion TERMINAL
*
* @THREADABLE_SOCKET<void*> SOCKET de la connexion client
*
* @history
* [1] Initialisation des variables
* [2] Récupération de la requête
* [3] Traitement de la requête
* [4] Création de la réponse
* [5] Envoi de la réponse
* [6] On vide les buffers
* [7] Fermeture de la connection (SOCKET)
* [n] Arrêt du THREAD
* 1. On récupère le rang dans les "managers"
* 2. On met à jour "activeManagers"
* 3. On arrête le THREAD
*
*/
void* manageCtrlTerm(void* THREADABLE_ARGS){
/* [1] Initialisation des variables
=========================================================*/
/* 1. Initialisation des variables */
struct sockaddr_in clientInfo;
socklen_t len;
size_t dataLen;
char loop = 1, update = 0, fbk = 0;
int count, last; // compteurs d'envoi
int i, index = -1; // Compteurs globaux
int pindex; // index of the current plane
char buffer[MAX_BUF_LEN]; // Buffer d'envoi
char* dataBuffer = malloc(1);
struct term_req request; // Requête
char flags;
int SOCKET;
struct in_addr* ip = malloc(sizeof(struct in_addr));
/* 2. On récupère les arguments */
struct handler_arg* arg = THREADABLE_ARGS;
memcpy(&SOCKET, &arg->socket, sizeof(int));
/* 3. On récupère le rang dans les "managers" */
for( i = 0 ; i < MAX_UDP_THR ; i++ )
if( arg->UDPManagers[i] == pthread_self() ){ index = i; break; }
printf("{udp_cterm}{com}(%d) starting terminal routine\n", index);
/* 4. Attente d'un client */
len = sizeof(struct sockaddr_in);
if( recvfrom(SOCKET, buffer, MAX_BUF_LEN*sizeof(char), 0, (struct sockaddr*) &clientInfo, &len) < 0 ){
printf("{udp_cterm}{com}(%d) No terminal detected, exiting\n", index);
loop = 0;
}else{
ip->s_addr = clientInfo.sin_addr.s_addr;
printf("{udp_cterm}{com}(%d) Terminal connected from %s:%d\n", index, inet_ntoa(*ip), ntohs(clientInfo.sin_port));
}
free(ip);
while( loop ){
pindex = -1;
/* [2] Récupération de la requête
=========================================================*/
/* 1. On lit sur la socket */
len = sizeof(struct sockaddr_in);
bzero(buffer, sizeof(char)*MAX_BUF_LEN);
count = recvfrom(SOCKET, buffer, MAX_BUF_LEN, 0, (struct sockaddr*) &clientInfo, &len);
/* 2. Si erreur reception */
if( count <= 0 ) // because of timeout or error
break;
if( count < TERMREQ_LEN ){
send(SOCKET, "\0\0", sizeof(char)*2, 0);
if( DEBUGMOD&BUF ) printf("{udp_cterm}{com}(%d) Error receiving request\n", index);
continue;
}
/* 3. On désérialise la requête*/
bzero(&request, sizeof(struct term_req));
count = 0; last = sizeof(char); memcpy(&request.flags, buffer+count, last );
count += last; last = sizeof(char)*6; memcpy(&request.update.code, buffer+count, last );
count += last; last = sizeof(int); memcpy(&request.update.x, buffer+count, last );
count += last; last = sizeof(int); memcpy(&request.update.y, buffer+count, last );
count += last; last = sizeof(int); memcpy(&request.update.z, buffer+count, last );
count += last; last = sizeof(int); memcpy(&request.update.cap, buffer+count, last );
count += last; last = sizeof(int); memcpy(&request.update.spd, buffer+count, last );
/* [3] Gestion de la requête
=========================================================*/
/* 1. On vérifie qu'il y a bien un update demandé (ou DATA) */
update = ( request.flags&TERMREQ_ALT || request.flags&TERMREQ_CAP || request.flags&TERMREQ_SPD );
fbk = request.flags&TERMREQ_FBK;
if( !( update || fbk ) ){
send(SOCKET, "\x00\0", sizeof(char)*2, 0);
if( request.flags != 0 )
printf("{udp_cterm}{com}(%d) Invalid flags\n", index);
continue;
}
printf("{udp_cterm}{com}(%d) Plane req { flags: %d; plane: #%s { z=%d; cap=%d; speed=%d } }\n", index, request.flags, request.update.code, ntohl(request.update.z), ntohl(request.update.cap), ntohl(request.update.spd));
/* [4] Gestion de la mise à jour de valeurs
=========================================================*/
while( update ){
/* (1) Recherche de l'avion
---------------------------------------------------------*/
/* 1. On cherche l'avion par code */
for( i = 0 ; i < arg->sgca->n ; i++ ){
/* 2. Si l'avion existe et online -> on passe à la suite */
if( strcmp(arg->sgca->unit[i].data.code, request.update.code) == 0 && arg->sgca->unit[i].data.online == 1 ){
pindex = i;
break;
}
}
/* 3. Si on a pas trouvé -> on quitte l'udpdate */
if( pindex <= -1 || arg->sgca->unit[pindex].socket <= -1 ){
printf("{udp_cterm}{com}(%d) Plane unknown or unreachable, passing\n", index);
request.flags = TERMREQ_OFF;
break;
}
/* (2) Transfert de la requête à l'avion
---------------------------------------------------------*/
/* 1. On prépare la requête */
bzero(buffer, sizeof(char)*MAX_BUF_LEN);
/* 2. On remplit le buffer d'envoi */
count = 0; last = sizeof(char); memcpy(buffer+count, &request.flags, last );
count += last; last = sizeof(int); memcpy(buffer+count, &request.update.z, last );
count += last; last = sizeof(int); memcpy(buffer+count, &request.update.cap, last );
count += last; last = sizeof(int); memcpy(buffer+count, &request.update.spd, last );
count += last;
/* 3. On envoie la requête à l'avion */
if( send(arg->sgca->unit[pindex].socket, buffer, count/sizeof(char), 0) <= 0 ){
printf("{udp_cterm}{com}(%d) Cannot send request to plane\n", index);
request.flags = TERMREQ_OFF;
break;
}
/* (3) Gestion de la réponse de l'avion
---------------------------------------------------------*/
// Attente du flag de réponse
arg->sgca->unit[pindex].thrId = index;
sleep(2);
flags = arg->sgca->unit[pindex].flags; // on récupère les flags
arg->sgca->unit[pindex].flags = TERMREQ_OFF; // on reset les flags
if( flags == TERMREQ_OFF ){
printf("{udp_cterm}{com}(%d) Cannot get response from plane %d bytes (%d expected)\n", index, count, (int) PLANE_LEN);
request.flags = TERMREQ_OFF;
break;
}
printf("{udp_cterm}{com}(%d) Plane res { flags: %d }\n", index, flags);
/* 2. Gestion de la validation de l'update */
if( !(flags&TERMREQ_ALT) && request.flags&TERMREQ_ALT )
request.flags -= TERMREQ_ALT;
if( !(flags&TERMREQ_CAP) && request.flags&TERMREQ_CAP )
request.flags -= TERMREQ_CAP;
if( !(flags&TERMREQ_SPD) && request.flags&TERMREQ_SPD )
request.flags -= TERMREQ_SPD;
/* 3. Si pas de demande des données -> on pré-remplie la requête */
if( !fbk ){
dataBuffer = realloc(dataBuffer, sizeof(char)*2 );
dataBuffer[0] = request.flags;
dataBuffer[1] = 0;
dataLen = 2;
}
break;
}
if( fbk ){
/* [5] Données des avions
=========================================================*/
/* 1. On récupère les données */
getPlaneData(&dataBuffer, &dataLen, arg->sgca);
/* 2. Si update, on mixe les flags */
if( update )
dataBuffer[0] |= request.flags;
}
/* [6] Réponse au terminal
=========================================================*/
printf("{udp_cterm}{com}(%d) Sending response { flags: %d; n: %d }\n", index, dataBuffer[0], dataBuffer[1]);
len = sizeof(struct sockaddr_in);
if( sendto(SOCKET, dataBuffer, dataLen, 0, (struct sockaddr*) &clientInfo, len) < 0 )
printf("{udp_cterm}{com}(%d) Cannot answer to terminal\n", index);
}
/* [n] Arrêt du THREAD
============================================================================*/
/* 1. On met à jour "activeManagers" */
if( index != -1 )
arg->activeUDPManagers[index] = 0;
/* 2. On ferme la socket */
close(SOCKET);
free(dataBuffer);
/* 3. On arrête le THREAD */
if( DEBUGMOD&THR ) printf("{udp_cterm}{com}(%d) freed\n", index);
pthread_exit(NULL);
}
void getPlaneData(char** pBuffer, size_t* pLen, struct context* pContext){
/* [1] Initialisation des variables
=========================================================*/
/* 1. Initialisation des variables */
int count, last, i, nb; // compteurs
struct term_res response; // Requête
/* [1] Récupération des données
=========================================================*/
/* 1. On initialise les variables utiles */
response.flags = TERMREQ_FBK;
nb = pContext->n;
response.n = 0; // nombre d'avions online
response.data = malloc( nb * sizeof(struct plane) + 1 );
/* 2. On récupère la liste des avions (network byte order) */
for( i = 0 ; i < nb ; i++ ){
memcpy(&response.data[i].code, &pContext->unit[i].data.code, sizeof(char)*6);
response.data[i].x = htonl( pContext->unit[i].data.x );
response.data[i].y = htonl( pContext->unit[i].data.y );
response.data[i].z = htonl( pContext->unit[i].data.z );
response.data[i].cap = htonl( pContext->unit[i].data.cap );
response.data[i].spd = htonl( pContext->unit[i].data.spd );
response.data[i].online = pContext->unit[i].data.online;
// Incrément du compte si online
response.n += response.data[i].online;
}
/* [3] Construction de la requête
=========================================================*/
/* 1. Initialisation du buffer */
*pBuffer = realloc(*pBuffer, sizeof(char)*2 + PLANE_LEN * response.n + sizeof(char));
/* 2. Copie des données globales */
count = 0; last = sizeof(char); memcpy(*pBuffer+count, &response.flags, last);
count += last; last = sizeof(char); memcpy(*pBuffer+count, &response.n, last);
/* 3. Copie des données des avions */
for( i = 0 ; i < nb ; i++ ){
// Ignore les avions offline
if( !response.data[i].online )
continue;
count += last; last = sizeof(char)*6; memcpy(*pBuffer+count, &response.data[i].code, last);
count += last; last = sizeof(int); memcpy(*pBuffer+count, &response.data[i].x, last);
count += last; last = sizeof(int); memcpy(*pBuffer+count, &response.data[i].y, last);
count += last; last = sizeof(int); memcpy(*pBuffer+count, &response.data[i].z, last);
count += last; last = sizeof(int); memcpy(*pBuffer+count, &response.data[i].cap, last);
count += last; last = sizeof(int); memcpy(*pBuffer+count, &response.data[i].spd, last);
}
*pLen = (count+last) / sizeof(char);
free(response.data);
}

View File

@ -19,5 +19,6 @@
void* manageViewTerm(void* THREADABLE_ARGS);
void* manageCtrlTerm(void* THREADABLE_ARGS);
void getPlaneData(char** pBuffer, size_t* pLen, struct context* pContext);
#endif

155
sgca/lib/local/middleware.c Normal file
View File

@ -0,0 +1,155 @@
/**************************
* Middleware Dependency *
***************************
* Designed & Developed by *
* Adrien Marquès *
* <xdrm-brackets> *
***************************
* doowap31@gmail.com *
**************************/
#include "middleware.h"
int multicastTerminal(struct middleware_arg* arg){
/* [0] Initialisation
=========================================================*/
/* 1. Initialisation des variables */
struct sockaddr_in comInfo; // contiendra les infos de la socket COM
struct sockaddr_in clientInfo; // contiendra les infos client
socklen_t len; // taille de la socket
int read; // compteurs
char buffer[MAX_BUF_LEN+1]; // buffer requête
struct bind_header request; // requête parsée
struct in_addr ip; // Pour afficher une ip en dot notation
/* 2. On récupère l'IP locale */
struct in_addr* SERV_IP = GET_LOCAL_IP();
if( SERV_IP == NULL ){
printf("{%s} /!\\ Cannot fetch local ip address. Aborting!\n", arg->entity);
return -2;
}
/* 3. On attends une connection UDP */
len = sizeof(struct sockaddr_in);
read = recvfrom(arg->listenSock, buffer, MAX_BUF_LEN, 0, (struct sockaddr*) &clientInfo, &len);
/* 4. Si erreur reception ou taille incorrecte -> retour à l'écoute */
if( read < BINDHDR_LEN ){
if( DEBUGMOD&BUF ) printf("{%s} read('%s') = %d bytes (expected: %d)\n", arg->entity, buffer, read, (int) (BINDHDR_LEN) );
return -1;
}
/* 5. On récupère l'adresse IP du client */
if( DEBUGMOD&SCK ) printf("{%s} %s:%d connecté\n", arg->entity, inet_ntoa(clientInfo.sin_addr), ntohs(clientInfo.sin_port));
/* [1] Gestion de la requête
=========================================================*/
/* 1. On parse la requête */
memcpy(&request.flags, buffer, sizeof(char));
memcpy(&request.addr, buffer+sizeof(char), sizeof(in_addr_t));
memcpy(&request.port, buffer+sizeof(char)+sizeof(in_addr_t), sizeof(unsigned short));
request.addr = ntohl(request.addr);
ip.s_addr = request.addr;
if( DEBUGMOD&COM ) printf("{%s} received: bind_header{flag = %d; addr = %x/'%s'; port = %d}\n", arg->entity, (int) request.flags, ntohl(request.addr), inet_ntoa(ip), request. port);
/* 2. Si mauvais flag (avion) */
if( request.flags&BINDHEAD_TCP || !(request.flags&BINDHEAD_UDP) ){
printf("{%s} Invalid flag\n", arg->entity);
return -1;
}
/* 3. Si mauvais flag (mauvais type de terminal) */
if( request.flags&BINDHEAD_CTL ){
// vterm avec flag cterm
if( strcmp(arg->entity, "udp_vterm") == 0 ){
printf("{%s} Invalid flag\n", arg->entity);
return -1;
}
// cterm avec flag vterm
}else if( strcmp(arg->entity, "udp_cterm") == 0 ){
printf("{%s} Invalid flag\n", arg->entity);
return -1;
}
/* (1) Création socket de communication (si demandé)
---------------------------------------------------------*/
/* 1. On bind une socket sur un port random */
if( DROP_UDP_SERVER(SERV_IP->s_addr, 0, arg->comSock, &comInfo, 0) < 0 ){
if( DEBUGMOD&SCK ) printf("{%s} Cannot create COMmunication socket\n", arg->entity);
/* 2. On ferme la socket et enleve le FLAG pour dire qu'on a pas pu ouvrir le port */
close(*arg->comSock);
request.flags -= BINDHEAD_UDP;
}
/* 3. On définit un timeout (si aucune connection) */
/* 3.1. Si viewTerm -> default timeout (4sec) */
if( strcmp(arg->entity, "udp_vterm") == 0 ){
if( setTimeout(*arg->comSock, SOCK_TIMEOUT, TIMEOUT_RECV|TIMEOUT_SEND) < 0 ){
if( DEBUGMOD&SCK ) printf("{%s} Cannot set RECV not SEND timeout\n", arg->entity);
}else
if( DEBUGMOD&SCK ) printf("{%s} SEND/RECV timeout set to %d\n", arg->entity, SOCK_TIMEOUT);
/* 3.2. Si ctrlTerm -> 10sec timeout */
}else
if( setTimeout(*arg->comSock, CTRL_TIMEOUT, TIMEOUT_RECV|TIMEOUT_SEND) < 0 ){
if( DEBUGMOD&SCK ) printf("{%s} Cannot set RECV not SEND timeout\n", arg->entity);
}else
if( DEBUGMOD&SCK ) printf("{%s} SEND/RECV timeout set to %d\n", arg->entity, CTRL_TIMEOUT);
/* (2) Récupération port random
---------------------------------------------------------*/
/* 1. On récupère le port de la socket de communication */
len = sizeof(struct sockaddr_in);
if( getsockname(*arg->comSock, (struct sockaddr*) &comInfo, &len) < 0 ){
if( DEBUGMOD&SCK ) printf("{%s} Cannot find opened port from socket\n", arg->entity);
/* 2. On ferme la socket et enleve le FLAG pour dire qu'on a pas pu ouvrir le port */
close(*arg->comSock);
request.flags -= BINDHEAD_UDP;
/* 3. Si on a le port -> on le met dans la reponse */
}else{
request.addr = SERV_IP->s_addr;
request.port = comInfo.sin_port;
if( DEBUGMOD&SCK ) printf("{%s}{com} socket opened on %s:%d\n", arg->entity, inet_ntoa(*SERV_IP), ntohs(request.port));
}
/* [2] Envoi de la réponse
=========================================================*/
/* 1. On sérialise la réponse */
bzero(buffer, MAX_BUF_LEN*sizeof(char));
memcpy(buffer, &request.flags, sizeof(char));
memcpy(buffer+sizeof(char), &request.addr, sizeof(in_addr_t));
memcpy(buffer+sizeof(char)+sizeof(in_addr_t), &request.port, sizeof(unsigned short));
/* 2. On envoie la réponse*/
len = sizeof(struct sockaddr_in);
if( sendto(arg->listenSock, buffer, BINDHDR_LEN/sizeof(char) + 1, 0, (struct sockaddr*) &clientInfo, len) < 0 ){
printf("{%s} Cannot answer to client\n", arg->entity);
return -2;
}
if( DEBUGMOD&COM ) printf("{%s} sent: bind_header{flag = %d; addr = %x/'%s'; port = %d}\n", arg->entity, (int) request.flags, ntohl(request.addr), inet_ntoa(*SERV_IP), ntohs(request.port));
return 0;
}

View File

@ -15,8 +15,8 @@
#include "../header.h"
#include "../network/udp/server.h"
#include "../network/common.h"
// int multicastPlanes(struct middleware_arg* ARGS);
int multicastTerminal(struct middleware_arg* ARGS);

118
sgca/lib/network/common.c Normal file
View File

@ -0,0 +1,118 @@
/**************************
* Network Common Depend. *
***************************
* Designed & Developed by *
* Adrien Marquès *
* <xdrm-brackets> *
***************************
* doowap31@gmail.com *
**************************/
#include "common.h"
struct in_addr* GET_LOCAL_IP(){
/* [0] Initialisation des variables
=========================================================*/
struct ifaddrs *list; // list of interfaces
struct ifaddrs *it; // interface iterator
struct sockaddr_in *info; // interface info
struct in_addr *result; // ip trouvée
result = malloc( sizeof(struct in_addr) );
/* [1] On récupère la liste des interfaces
=========================================================*/
getifaddrs(&list);
/* [2] Parcourt des interfaces
=========================================================*/
for( it = list ; it ; it = it->ifa_next ){
/* 1. Si "lo" -> suivant */
if( strcmp(it->ifa_name, "lo") == 0 )
continue;
/* 2. Si pas IPV4 -> suivant */
if( it->ifa_addr->sa_family != AF_INET )
continue;
/* 3. Si ok, on retourne l'ip */
info = (struct sockaddr_in*) it->ifa_addr;
memcpy(result, &info->sin_addr, sizeof(struct in_addr));
freeifaddrs(list);
return result;
}
/* [3] Cas échéant -> aucun résultat
=========================================================*/
freeifaddrs(list);
return NULL;
}
int setTimeout(int pSocket, const time_t pSec, char pFlags){
/* [1] Initialisation des variables
=========================================================*/
/* 1. Création de la variable */
struct timeval timeout;
/* 2. On définit le temps du timeout */
timeout.tv_sec = pSec;
timeout.tv_usec = 0;
/* [2] On applique à la socket
=========================================================*/
/* 1. Timeout de reception */
if( pFlags&TIMEOUT_RECV ){
if( setsockopt(pSocket, SOL_SOCKET, SO_RCVTIMEO, (char*) &timeout, sizeof(struct timeval) ) < 0 ){
close(pSocket);
return -1;
}
}
/* 2. Timeout d'envoi */
if( pFlags&TIMEOUT_SEND ){
if( setsockopt(pSocket, SOL_SOCKET, SO_SNDTIMEO, (char*) &timeout, sizeof(struct timeval) ) < 0 ){
close(pSocket);
return -1;
}
}
/* 3. Résultat de succès */
return 0;
}
int checkMulticastGroup(in_addr_t pAddr){
// printf("Checking if multicast '%d' is already used\n");
/* [0] Initialisation des variables
=========================================================*/
// int sock, nb;
/* [1] Création d'une socket UDP
=========================================================*/
return -1;
}

74
sgca/lib/network/common.h Normal file
View File

@ -0,0 +1,74 @@
/**************************
* Network Common Depend. *
***************************
* Designed & Developed by *
* Adrien Marquès *
* <xdrm-brackets> *
***************************
* doowap31@gmail.com *
**************************/
#ifndef _LIB_NETWORK_COMMON_H_
#define _LIB_NETWORK_COMMON_H_
#include "../header.h"
#include <ifaddrs.h>
/* Retourne l'adresse IP du serveur (première interface excepté "lo")
*
* @history
* [0] Initialisation des variables
* [1] On récupère la liste des interfaces
* [2] Parcourt des interfaces
* 1. Si "lo" -> suivant
* 2. Si pas IPV4 -> suivant
* 3. Si ok, on retourne l'ip
* [3] Cas échéant -> aucun résultat (NULL)
*
*/
struct in_addr* GET_LOCAL_IP();
#define TIMEOUT_RECV 0x01
#define TIMEOUT_SEND 0x02
/* Définit un timeout pour une socket données
*
* @in
* pSocket<int> Socket à modifier
* pSec<const time_t> Valeur en seconde du timeout
* pFlags<char> Si RECV et/ou SEND
*
* @out
* -1 en cas d'échec
* 0 sinon
*
* @history
* [1] Initialisation des variables
* [2] On applique le timeout à la socket
*
*/
int setTimeout(int pSocket, const time_t pSec, char pFlags);
/* Vérifie si un groupe multicast est déja utilisé
*
* @in
* pAddr<in_addr_t> Adresse du groupe multicast
*
* @out
* -1 en cas d'échec
* 0 sinon
*
* @history
* [1] Initialisation des variables
* [2] On Vérifie si le groupe a du traffic
*
*/
int checkMulticastGroup(in_addr_t pAddr);
#endif

View File

@ -22,7 +22,6 @@ int DROP_TCP_SERVER(const int pPort, int* pListenSock){
=========================================================*/
static struct sockaddr_in addr; // contiendra les infos du serveur
int STATUS; // status
struct timeval timeout;
*pListenSock = -1;
@ -37,15 +36,6 @@ int DROP_TCP_SERVER(const int pPort, int* pListenSock){
/* 2. Gestion erreur */
if( *pListenSock < 0 ) return -1;
/* 3. Timeout */
timeout.tv_sec = SOCK_TIMEOUT;
timeout.tv_usec = 0;
if( setsockopt(*pListenSock, SOL_SOCKET, SO_RCVTIMEO|SO_SNDTIMEO, (char*) &timeout, sizeof(struct timeval) ) < 0 ){
close(*pListenSock);
return -1;
}
/* [2] On définit les infos de la socket
=========================================================*/
@ -61,7 +51,13 @@ int DROP_TCP_SERVER(const int pPort, int* pListenSock){
/* [3] On publie la SOCKET
=======================================================*/
/* 1. Publication socket */
STATUS = bind(*pListenSock, (struct sockaddr*) &addr, sizeof(addr));
int count = -1;
do{
count++;
addr.sin_port = htons(pPort+count);
STATUS = bind(*pListenSock, (struct sockaddr*) &addr, sizeof(struct sockaddr_in));
if( DEBUGMOD&SAD ) printf("\tudp:%d used, trying udp:%d\n", pPort+count-1, pPort+count);
}while( STATUS < 0 && count < 10 );
if( DEBUGMOD&SCK && DEBUGMOD&HDR ) printf(" * [drop_tcp_server] bind: %d\n", STATUS);
@ -84,6 +80,6 @@ int DROP_TCP_SERVER(const int pPort, int* pListenSock){
/* [n] Code succès
=========================================================*/
return 0;
return pPort+count;
}

View File

@ -2,12 +2,11 @@
int UDP_SOCKET(int* pSocket, const char* pAddr, const int pPort, struct sockaddr_in* pInfo){
int UDP_SOCKET(int* pSocket, in_addr_t pAddr, const int pPort, struct sockaddr_in* pInfo){
/* [0] Initialisation des variables
=========================================================*/
*pSocket = -1;
struct timeval timeout;
/* [1] Création de la socket
@ -19,15 +18,6 @@ int UDP_SOCKET(int* pSocket, const char* pAddr, const int pPort, struct sockaddr
if( *pSocket < 0 )
return -1;
/* 3. Timeout */
timeout.tv_sec = SOCK_TIMEOUT;
timeout.tv_usec = 0;
if( setsockopt(*pSocket, SOL_SOCKET, SO_RCVTIMEO|SO_SNDTIMEO, (char*) &timeout, sizeof(struct timeval) ) < 0 ){
close(*pSocket);
return -1;
}
/* [2] On définit les infos de la socket
=========================================================*/
@ -37,7 +27,7 @@ int UDP_SOCKET(int* pSocket, const char* pAddr, const int pPort, struct sockaddr
/* (2) On définit les infos */
pInfo->sin_family = AF_INET;
pInfo->sin_port = htons(pPort);
pInfo->sin_addr.s_addr = inet_addr(pAddr);
pInfo->sin_addr.s_addr = pAddr;
/* [n] Code succès

View File

@ -26,7 +26,7 @@
/* Créée une socket UDP + crée le sockaddr_in pour la suite
*
* ==IN==
* @pAddr<const char*> Adresse du groupe multicast UDP
* @pAddr<in_addr_t> Adresse du groupe multicast UDP
* @pPort<const int> Port d'écoute UDP
*
* ==OUT==
@ -43,7 +43,7 @@
*
*
*/
int UDP_SOCKET(int* pSocket, const char* pAddr, const int pPort, struct sockaddr_in* pInfo);
int UDP_SOCKET(int* pSocket, in_addr_t pAddr, const int pPort, struct sockaddr_in* pInfo);

View File

@ -12,15 +12,15 @@
int DROP_UDP_SERVER(const char* pAddr, const int pPort, int* pListenSock, struct sockaddr_in* pInfo, const char pMcast){
if( DEBUGMOD&HDR ) printf("====== DROP_UDP_MCAST(%s, %d, %p, %p, %d) ======\n\n", pAddr, pPort, (void*) pListenSock, (void*) pInfo, (int) pMcast);
int DROP_UDP_SERVER(in_addr_t pAddr, const int pPort, int* pListenSock, struct sockaddr_in* pInfo, const char pMcast){
if( DEBUGMOD&HDR ) printf("====== DROP_UDP_MCAST(%x, %d, %p, %p, %d) ======\n\n", pAddr, pPort, (void*) pListenSock, (void*) pInfo, (int) pMcast);
/* [0] Initialisation des variables
=========================================================*/
int STATUS; // status
struct ip_mreq mcastReq;
*pListenSock = -1;
struct timeval timeout;
struct in_addr tmp;
/* [1] Création de la socket
@ -33,15 +33,6 @@ int DROP_UDP_SERVER(const char* pAddr, const int pPort, int* pListenSock, struct
/* 2. Gestion erreur */
if( *pListenSock < 0 ) return -1;
/* 3. Timeout */
timeout.tv_sec = SOCK_TIMEOUT;
timeout.tv_usec = 0;
if( setsockopt(*pListenSock, SOL_SOCKET, SO_RCVTIMEO|SO_SNDTIMEO, (char*) &timeout, sizeof(struct timeval) ) < 0 ){
close(*pListenSock);
return -1;
}
/* [2] On définit les infos de la socket
=========================================================*/
@ -57,7 +48,13 @@ int DROP_UDP_SERVER(const char* pAddr, const int pPort, int* pListenSock, struct
/* [3] On publie la SOCKET
=======================================================*/
/* 1. Publication socket */
int count = -1;
do{
count++;
pInfo->sin_port = htons(pPort+count);
STATUS = bind(*pListenSock, (struct sockaddr*) pInfo, sizeof(struct sockaddr_in));
if( DEBUGMOD&SAD ) printf("\tudp:%d used, trying udp:%d\n", pPort+count-1, pPort+count);
}while( STATUS < 0 && count < 10 );
if( DEBUGMOD&SCK && DEBUGMOD&HDR ) printf(" * [drop_udp_server] bind: %d\n", STATUS);
@ -67,8 +64,10 @@ int DROP_UDP_SERVER(const char* pAddr, const int pPort, int* pListenSock, struct
/* 3. Demande groupe multicast (si demandé) */
if( pMcast ){
if( DEBUGMOD&SCK && DEBUGMOD&HDR ) printf(" * [drop_udp_server] join mcast group: %s\n", pAddr);
mcastReq.imr_multiaddr.s_addr = inet_addr(pAddr);
tmp.s_addr = pAddr;
if( DEBUGMOD&SCK && DEBUGMOD&HDR ) printf(" * [drop_udp_server] join mcast group: %s\n", inet_ntoa(tmp));
mcastReq.imr_multiaddr.s_addr = pAddr;
mcastReq.imr_interface.s_addr = htonl(INADDR_ANY);
if( setsockopt(*pListenSock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mcastReq, sizeof(mcastReq)) < 0 ){
@ -81,6 +80,6 @@ int DROP_UDP_SERVER(const char* pAddr, const int pPort, int* pListenSock, struct
/* [n] Code succès
=========================================================*/
return 0;
return pPort+count;
}

View File

@ -20,7 +20,7 @@
/* Créé et met un serveur UDP d'écoute MULTICAST ou CLASSIQUE
*
* ==IN==
* @pAddr<const char*> Adresse du groupe multicast UDP
* @pAddr<in_addr_t> Adresse du groupe multicast UDP
* @pPort<const int> Port d'écoute UDP
* @pMcast<const char> Si multicast ou non
*
@ -38,7 +38,7 @@
* [n] On renvoie la socket par référence
*
*/
int DROP_UDP_SERVER(const char* pAddr, const int pPort, int* pListenSock, struct sockaddr_in* pInfo, const char pMcast);
int DROP_UDP_SERVER(in_addr_t pAddr, const int pPort, int* pListenSock, struct sockaddr_in* pInfo, const char pMcast);

View File

@ -13,16 +13,20 @@ import java.net.SocketException;
import java.util.logging.Level;
import java.util.logging.Logger;
import ViewTerminal.InvalidFlagException;
import ViewTerminal.PlaneContainer;
/**
*
* @author lmascaro
*/
public class AsynchronousDatagramSocket implements Runnable, AutoCloseable{
private final static int MAX_MESSAGE_SIZE = 300;
public final static int MAX_MESSAGE_SIZE = 300;
private SynchronizedBuffer<DatagramPacket> buf;
private DatagramSocket socket;
private PlaneContainer container;
public AsynchronousDatagramSocket() throws SocketException{
this.buf = new SynchronizedBuffer<>();
@ -36,6 +40,10 @@ public class AsynchronousDatagramSocket implements Runnable, AutoCloseable{
new Thread(this).start();
}
public void bindContainer(PlaneContainer c){
this.container = c;
}
public void send(DatagramPacket dp) throws IOException{
this.socket.send(dp);
}
@ -49,8 +57,8 @@ public class AsynchronousDatagramSocket implements Runnable, AutoCloseable{
}
}
public void synchronousReceive(DatagramPacket dp){
dp = this.buf.removeElement(true);
public DatagramPacket synchronousReceive(){
return this.buf.removeElement(true);
}
public boolean available(){
@ -64,12 +72,18 @@ public class AsynchronousDatagramSocket implements Runnable, AutoCloseable{
@Override
public void run() {
DatagramPacket packet = new DatagramPacket(new byte[MAX_MESSAGE_SIZE],MAX_MESSAGE_SIZE);
DatagramPacket packet;
while(true){
packet = new DatagramPacket(new byte[MAX_MESSAGE_SIZE],MAX_MESSAGE_SIZE);
try {
this.socket.receive(packet);
this.buf.addElement(packet);
this.container.notifyReceive();
} catch (IOException ex) {
Logger.getLogger(AsynchronousDatagramSocket.class.getName()).log(Level.SEVERE, null, ex);
} catch (InvalidFlagException e) {
System.out.println("\033[01;31m Unexpected flag received \033[0m");
}
}
}
}

View File

@ -0,0 +1,46 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package DatagramSocket;
import java.util.LinkedList;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author lmascaro
*/
public class SynchronizedBuffer<T>{
private LinkedList<T> elements = new LinkedList<T>();
public synchronized T removeElement(boolean sync){
if(!sync && this.elements.isEmpty()){
return null;
}
while(this.elements.isEmpty()){
try {
this.wait();
} catch (InterruptedException ex) {
Logger.getLogger(SynchronizedBuffer.class.getName()).log(Level.SEVERE, null, ex);
}
}
return this.elements.removeFirst();
}
public synchronized void addElement(T elem){
this.elements.add(elem);
this.notifyAll();
}
public synchronized int available(){
return this.elements.size();
}
}

View File

@ -0,0 +1,18 @@
package ViewTerminal;
public class InvalidFlagException extends Exception {
/**
*
*/
private static final long serialVersionUID = 1L;
public InvalidFlagException(){
super();
}
public InvalidFlagException(String message){
super(message);
}
}

View File

@ -0,0 +1,108 @@
package ViewTerminal;
public class Plane {
private String code;
private int x;
private int y;
private int z;
private int cap;
private int speed;
private boolean isDead;
public Plane(String code,int x, int y, int z, int cap, int speed){
this.code = code;
this.x = x;
this.y = y;
this.z = z;
this.cap = cap;
this.speed = speed;
this.isDead = false;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public int getZ() {
return z;
}
public void setZ(int z) {
this.z = z;
}
public int getCap() {
return cap;
}
public boolean isDead(){
return this.isDead;
}
public void setCap(int cap) {
this.cap = cap;
}
public int getSpeed() {
return speed;
}
public void setSpeed(int speed) {
this.speed = speed;
}
//Die Motherfucker
public void die(){
this.isDead = true;
}
public String getLine(int i){
switch(i){
case 0:
return "--------------------------------";
case 1:
if(this.isDead){
return "\033[4;37;41m Code: "+this.code+"\t\t\t|";
}else{
return "\033[4;37;42m Code: "+this.code+"\t\t\t|";
}
case 2:
return "\033[0m --Coords: {"+this.x+";"+this.y+";"+this.z+"} \t|";
case 3:
return "\033[0m --Cap: "+this.cap+"\t\t\t|";
case 4:
if(this.isDead){
return "\033[4;37;41m ATTENTION: avion hors ligne\t|\033[0m";
}else if(this.speed<300){
return "\033[5;37;41m --Speed: "+this.speed+"\t\t\t|\033[0m";
}else{
return "\033[0m --Speed: "+this.speed+"\t\t\t|";
}
default:
return "";
}
}
}

View File

@ -0,0 +1,98 @@
package ViewTerminal;
import java.io.IOException;
import java.net.DatagramPacket;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.HashMap;
import DatagramSocket.AsynchronousDatagramSocket;
public class PlaneContainer {
private HashMap<String,Plane> map;
private AsynchronousDatagramSocket socket;
private Printer printer;
public PlaneContainer(){
this.map = new HashMap<String,Plane>();
}
public void bindSocket(AsynchronousDatagramSocket s){
this.socket = s;
}
public void bindPrinter(Printer p){
this.printer = p;
}
public void notifyReceive() throws InvalidFlagException{
DatagramPacket packet = this.socket.synchronousReceive();
ByteBuffer buf = ByteBuffer.allocate(1);
buf.put((byte)16);
DatagramPacket ping = new DatagramPacket(buf.array(),buf.array().length,packet.getAddress(),packet.getPort());
try {
this.socket.send(ping);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
buf = ByteBuffer.wrap(packet.getData());
byte flag;
byte nbrPlane;
ArrayList<String> codes;
flag = buf.get();
nbrPlane = buf.get();
codes = new ArrayList<String>(nbrPlane);
//System.out.println("Processing "+nbrPlane+" planes");
if(flag != 1){
throw new InvalidFlagException("Flag is not a feedback flag :"+flag);
}else{
String code;
byte rawCode[] = new byte[5];
Plane plane;
for(int i = 0;i<nbrPlane;i++){
//get plane code
buf = buf.get(rawCode,0,5);
code = new String(rawCode);
plane = this.map.get(code);
codes.add(code);
//remove EOL char
buf.get();
if(plane != null){
//fill the plane
plane.setX(buf.getInt());
plane.setY(buf.getInt());
plane.setZ(buf.getInt());
plane.setCap(buf.getInt());
plane.setSpeed(buf.getInt());
}else{
plane = new Plane(code,buf.getInt(),buf.getInt(),buf.getInt(),buf.getInt(),buf.getInt());
this.map.put(code, plane);
}
}
}
//check for dead planes
for(String code : this.map.keySet()){
if(!codes.contains(code)){
this.map.get(code).die();
}
}
this.printer.notifyReceive();
}
public HashMap<String,Plane> getMap(){
return this.map;
}
}

View File

@ -0,0 +1,53 @@
package ViewTerminal;
import java.util.HashMap;
public class Printer {
private PlaneContainer container;
public Printer(){
}
public void bindContainer(PlaneContainer c){
this.container = c;
}
public void notifyReceive(){
System.out.println("\033[2J \033[H");
HashMap<String,Plane> map = this.container.getMap();
int i = 0;
String lines[] = new String[5];
for(int k = 0;k<5;k++){
lines[k] = "";
}
if(map.keySet().size() == 0){
System.out.println("\033[37;43m Aucun avion connecté au système \033[0m");
}else{
for(String code : map.keySet()){
if(i <= 1){
for(int k = 0;k<5;k++){
lines[k] += map.get(code).getLine(k);
}
i++;
}else{
for(int k = 0;k<5;k++){
System.out.println(lines[k]);
lines[k] = "";
}
for(int k = 0;k<5;k++){
lines[k] += map.get(code).getLine(k);
}
i=1;
}
}
for(int k = 0;k<5;k++){
System.out.println(lines[k]);
}
}
}
}

View File

@ -0,0 +1,102 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package ViewTerminal;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import DatagramSocket.AsynchronousDatagramSocket;
/**
*
* @author lmascaro
*/
public class ViewTerminal {
private final static int SGCA_MULTICAST_PORT = 4445;
private final static String SCGA_MULTICAST_ADDRESS = "224.0.0.2";
/**
* @param args the command line arguments
*/
public static void main(String[] args){
System.out.println("\033[2J");
/*
* Handshake
*/
int port = 0;
String addressString = "0.0.0.0";
try {
DatagramSocket socket = new DatagramSocket();
ByteBuffer buf = ByteBuffer.allocate(21);
buf.clear();
buf.put((byte)(0x01));
DatagramPacket payload = new DatagramPacket(buf.array(),buf.array().length,InetAddress.getByName(SCGA_MULTICAST_ADDRESS),SGCA_MULTICAST_PORT);
socket.send(payload);
socket.receive(payload);
buf = ByteBuffer.wrap(payload.getData());
if(buf.get() == 1){
System.out.println("--Connection request successful");
byte address[] = new byte[4];
buf = buf.get(address,0,4);
InetAddress addressObj = InetAddress.getByAddress(address);
addressString = addressObj.getHostAddress();
//emulate an unsigned short
char cast = buf.getChar();
port = (int) cast;
System.out.println("----Address : "+addressString);
System.out.println("----Port : "+port);
}
} catch ( IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return;
}
/*
* Opening final socket
*/
try {
//create all objects
AsynchronousDatagramSocket socket = new AsynchronousDatagramSocket();
PlaneContainer container = new PlaneContainer();
Printer printer = new Printer();
//bind them
socket.bindContainer(container);
container.bindPrinter(printer);
container.bindSocket(socket);
printer.bindContainer(container);
//send first packet
DatagramPacket p = new DatagramPacket(new byte[13],13,InetAddress.getByName(addressString),port);
socket.send(p);
//now we let the objects do the job
while(true){
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

BIN
viewTerm/viewTerm.jar Normal file

Binary file not shown.