Compare commits
No commits in common. "master" and "multicast-plane" have entirely different histories.
master
...
multicast-
47
Makefile
47
Makefile
|
@ -1,47 +0,0 @@
|
|||
|
||||
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;
|
|
@ -0,0 +1 @@
|
|||
.vscode
|
|
@ -21,13 +21,10 @@ 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/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
|
||||
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
|
||||
|
||||
|
||||
# Run full compilation
|
||||
|
@ -35,7 +32,6 @@ all: boot
|
|||
|
||||
# cleans the compiled files
|
||||
clean:
|
||||
@rm lib/network/*.o;
|
||||
@rm lib/network/**/*.o;
|
||||
@rm lib/local/*.o;
|
||||
@rm boot;
|
||||
rm boot;
|
||||
rm lib/network/**/*.o;
|
||||
rm lib/local/*.o;
|
|
@ -17,75 +17,60 @@
|
|||
* [0] Initialisation des variables
|
||||
* [1] Lancement des THREADS d'écoute
|
||||
* 1. On démarre le SERVEUR TCP d'écoute globale
|
||||
* 2. On récupère l'IP locale
|
||||
* 3. On démarre le SERVEUR UDP d'écoute globale
|
||||
* 2. 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("[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 structure\n");
|
||||
printf("** [procedureName]\n");
|
||||
printf("** {threadName}\n");
|
||||
printf("** [parent]{child}[subchild] Description\n\n\n");
|
||||
printf("**** Execution tree\n");
|
||||
|
||||
/* [0] Initialisation des variables
|
||||
=========================================================*/
|
||||
/* 1. Variables globales */
|
||||
sgca.n = 0;
|
||||
sgca.unit = (struct context_unit*) malloc( sizeof(struct context_unit) );
|
||||
struct in_addr* SERV_HOST;
|
||||
sgca.data = (struct plane*) malloc( sizeof(struct plane) );
|
||||
|
||||
/* 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 };
|
||||
/* 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 };
|
||||
|
||||
|
||||
/* [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} started\n");
|
||||
if( DEBUGMOD&THR ) printf("{tcp_listn} démarré\n");
|
||||
|
||||
/* (2) Ecoute UDP multicast */
|
||||
pthread_create(&listenManagers[1], NULL, MCAST_PUBLISH, (void*) &udp_mcast_arg);
|
||||
if( DEBUGMOD&THR ) printf("{udp_mcast} started\n");
|
||||
if( DEBUGMOD&THR ) printf("{udp_mcast} démarré\n");
|
||||
|
||||
/* (3) Ecoute UDP viewTerm */
|
||||
pthread_create(&listenManagers[2], NULL, LISTEN_UDP, (void*) &udp_vterm_arg);
|
||||
if( DEBUGMOD&THR ) printf("{udp_vterm} started\n");
|
||||
if( DEBUGMOD&THR ) printf("{udp_vterm} démarré\n");
|
||||
|
||||
/* (4) Ecoute UDP ctrlTerm */
|
||||
pthread_create(&listenManagers[3], NULL, LISTEN_UDP, (void*) &udp_cterm_arg);
|
||||
if( DEBUGMOD&THR ) printf("{udp_cterm} started\n");
|
||||
if( DEBUGMOD&THR ) printf("{udp_cterm} démarré\n");
|
||||
|
||||
|
||||
/* [2] On attends la fin de tous les THREADS
|
||||
==========================================================*/
|
||||
char i;
|
||||
for( i = 0 ; i < 4 ; i++ )
|
||||
for( char i = 0 ; i < 4 ; i++ )
|
||||
pthread_join(listenManagers[(int)i], NULL);
|
||||
|
||||
|
||||
/* [3] On libère les variables globales
|
||||
==========================================================*/
|
||||
free(sgca.unit);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
free(sgca.data);
|
||||
}
|
||||
|
||||
|
||||
|
@ -106,15 +91,12 @@ int main(int argc, char* argv[]){
|
|||
void* LISTEN_TCP(void* THREADABLE_ARGS){
|
||||
/* [0] Initialisation des variables
|
||||
==========================================================*/
|
||||
int CLIENT_SOCKET; // contiendra la socket TCP à envoyer sur un THREAD
|
||||
struct sockaddr_in clientInfo; // contiendra les infos client
|
||||
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
|
||||
int CLIENT_SOCKET; // contiendra la socket TCP à envoyer sur un THREAD
|
||||
struct sockaddr_in clientInfo; // contiendra les infos client
|
||||
socklen_t len; // taille de la socket
|
||||
int index, i; // compteurs
|
||||
struct listen_arg* arg = THREADABLE_ARGS; // Addr + Port serveur
|
||||
|
||||
ip.s_addr = arg->addr;
|
||||
|
||||
// retour de @DROP_TCP_SERVER
|
||||
int LISTENSOCK; // contiendra la socket d'écoute TCP
|
||||
|
@ -122,13 +104,12 @@ void* LISTEN_TCP(void* THREADABLE_ARGS){
|
|||
|
||||
/* [1] On démarre le SERVEUR TCP d'écoute globale
|
||||
==========================================================*/
|
||||
rtnPort = DROP_TCP_SERVER(arg->port, &LISTENSOCK);
|
||||
if( rtnPort < 0 ){
|
||||
if( DROP_TCP_SERVER(arg->port, &LISTENSOCK) < 0 ){
|
||||
|
||||
if( DEBUGMOD&SCK ) printf("{tcp_listn} Error creating listener socket\n");
|
||||
if( DEBUGMOD&SCK ) printf("{tcp_listn} Erreur création socket d'écoute\n");
|
||||
|
||||
// On ferme la SOCKET d'écoute globale
|
||||
printf("{tcp_listn} Closing listener socket!\n");
|
||||
printf("{tcp_listn} FERMETURE SOCKET D'ECOUTE TCP!\n");
|
||||
close(LISTENSOCK);
|
||||
|
||||
return NULL;
|
||||
|
@ -136,9 +117,7 @@ void* LISTEN_TCP(void* THREADABLE_ARGS){
|
|||
|
||||
|
||||
|
||||
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);
|
||||
printf("{tcp_listn} listen on %s:%d\n", arg->addr, arg->port);
|
||||
|
||||
|
||||
|
||||
|
@ -160,7 +139,7 @@ void* LISTEN_TCP(void* THREADABLE_ARGS){
|
|||
break;
|
||||
}
|
||||
|
||||
if( DEBUGMOD&SCK ) printf("{tcp_listn} %s:%d connected\n", inet_ntoa(clientInfo.sin_addr), ntohs(clientInfo.sin_port));
|
||||
if( DEBUGMOD&SCK ) printf("{tcp_listn} %s:%d connecté\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++ )
|
||||
|
@ -170,18 +149,18 @@ void* LISTEN_TCP(void* THREADABLE_ARGS){
|
|||
if( index != -1 ){
|
||||
|
||||
// Construction arguments thread
|
||||
struct handler_arg thread_args = { TCPManagers, UDPManagers, activeTCPManagers, activeUDPManagers, CLIENT_SOCKET, &sgca };
|
||||
struct handler_arg thread_args = { TCPManagers, activeTCPManagers, 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) started\n", index);
|
||||
if( DEBUGMOD&THR ) printf("{tcp_listn}{com}(%d) démarré\n", index);
|
||||
|
||||
/* 6. On signale que ce "manager" est maintenant actif */
|
||||
activeTCPManagers[index] = 1;
|
||||
|
||||
}else
|
||||
if( DEBUGMOD&THR ) printf("{tcp_listn} No available thread\n");
|
||||
if( DEBUGMOD&THR ) printf("{tcp_listn} Aucun thread libre\n");
|
||||
|
||||
}
|
||||
|
||||
|
@ -194,7 +173,7 @@ void* LISTEN_TCP(void* THREADABLE_ARGS){
|
|||
|
||||
/* [4] On ferme la SOCKET d'écoute globale
|
||||
==========================================================*/
|
||||
printf("{tcp_listn} Closing listener socket\n");
|
||||
printf("{tcp_listn} FERMETURE SOCKET D'ECOUTE TCP!\n");
|
||||
close(LISTENSOCK);
|
||||
|
||||
return NULL;
|
||||
|
@ -227,51 +206,39 @@ void* LISTEN_UDP(void* THREADABLE_ARGS){
|
|||
/* [0] Initialisation des variables
|
||||
==========================================================*/
|
||||
/* 1. On initialise les variables */
|
||||
int CLIENT_SOCKET; // contiendra la socket UDP à envoyer sur un THREAD
|
||||
struct sockaddr_in listenInfo; // contiendra les infos de la socket LISTEN
|
||||
int i, index; // compteurs
|
||||
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)
|
||||
int CLIENT_SOCKET; // contiendra la socket UDP à envoyer sur un THREAD
|
||||
struct sockaddr_in listenInfo; // contiendra les infos de la socket LISTEN
|
||||
int i, index; // compteurs
|
||||
char entity[10]; // identifiant pour debug
|
||||
int returned; // Contrôle d'exécution middleware
|
||||
struct middleware_arg marg; // paramètres pour middleware
|
||||
|
||||
|
||||
/* 2. On parse les arguments */
|
||||
struct listen_arg* arg = THREADABLE_ARGS; // Addr + Port serveur
|
||||
|
||||
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");
|
||||
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");
|
||||
|
||||
// retour de @DROP_UDP_SERVER
|
||||
int SOCKET;
|
||||
|
||||
ip.s_addr = arg->addr;
|
||||
|
||||
|
||||
/* [1] On démarre le SERVEUR UDP d'écoute globale
|
||||
==========================================================*/
|
||||
/* 1. On crée la socket */
|
||||
rtnPort = DROP_UDP_SERVER(arg->addr, arg->port, &SOCKET, &listenInfo, 1);
|
||||
if( rtnPort < 0 ){
|
||||
if( DROP_UDP_SERVER(arg->addr, arg->port, &SOCKET, &listenInfo, strcmp(arg->addr, SERV_HOST) != 0) < 0 ){
|
||||
|
||||
if( DEBUGMOD&SCK ) printf("{%s} Error creating listener socket\n", entity);
|
||||
if( DEBUGMOD&SCK ) printf("{%s} Erreur de création socket d'écoute\n", entity);
|
||||
|
||||
// On ferme la SOCKET d'écoute globale
|
||||
printf("{%s} Closing listener socket!\n", entity);
|
||||
printf("{%s} FERMETURE SOCKET D'ECOUTE UDP!\n", entity);
|
||||
close(SOCKET);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
printf("{%s} listen on %s:%d\n", entity, arg->addr, arg->port);
|
||||
|
||||
|
||||
|
||||
|
@ -289,8 +256,8 @@ void* LISTEN_UDP(void* THREADABLE_ARGS){
|
|||
if( arg->middleware != NULL ){
|
||||
|
||||
/* 1. Construction des arguments */
|
||||
marg.listenSock = SOCKET;
|
||||
marg.comSock = &CLIENT_SOCKET;
|
||||
marg.listenSock = SOCKET;
|
||||
marg.comSock = &CLIENT_SOCKET;
|
||||
strcpy(marg.entity, entity);
|
||||
|
||||
/* 2. Exécution middleware */
|
||||
|
@ -326,19 +293,18 @@ void* LISTEN_UDP(void* THREADABLE_ARGS){
|
|||
if( index != -1 ){
|
||||
|
||||
// Construction arguments thread
|
||||
|
||||
struct handler_arg thread_args = { TCPManagers, UDPManagers, activeTCPManagers, activeUDPManagers, CLIENT_SOCKET, &sgca };
|
||||
struct handler_arg thread_args = { UDPManagers, 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}{com}(%d) started\n", entity, index);
|
||||
if( DEBUGMOD&THR ) printf("{%s}{udp_com}(%d) démarré\n", entity, index);
|
||||
|
||||
/* 2.2. On signale que ce "manager" est maintenant actif */
|
||||
activeUDPManagers[index] = 1;
|
||||
|
||||
}else
|
||||
if( DEBUGMOD&THR ) printf("{%s} No available thread\n", entity);
|
||||
if( DEBUGMOD&THR ) printf("{%s} Aucun thread UDP libre!\n", entity);
|
||||
|
||||
}
|
||||
|
||||
|
@ -346,7 +312,7 @@ void* LISTEN_UDP(void* THREADABLE_ARGS){
|
|||
|
||||
/* [n] On ferme la SOCKET d'écoute globale
|
||||
==========================================================*/
|
||||
printf("{%s} Closing listener socket\n", entity);
|
||||
printf("{%s} FERMETURE SOCKET D'ECOUTE UDP!\n", entity);
|
||||
close(SOCKET);
|
||||
|
||||
return NULL;
|
||||
|
@ -376,7 +342,6 @@ 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
|
||||
|
@ -384,8 +349,6 @@ void* MCAST_PUBLISH(void* THREADABLE_ARGS){
|
|||
// retour de @UDP_SOCKET
|
||||
int SOCKET;
|
||||
|
||||
ip.s_addr = arg->addr;
|
||||
|
||||
|
||||
/* [1] On initialise la socket CLIENT UDP
|
||||
==========================================================*/
|
||||
|
@ -400,7 +363,7 @@ void* MCAST_PUBLISH(void* THREADABLE_ARGS){
|
|||
return NULL;
|
||||
}
|
||||
|
||||
printf("{udp_mcast} bound to %s:%d\n", inet_ntoa(ip), arg->port);
|
||||
printf("{udp_mcast} bound to %s:%d\n", arg->addr, arg->port);
|
||||
|
||||
|
||||
/* [2] On construit la requête à envoyer
|
||||
|
@ -408,24 +371,15 @@ void* MCAST_PUBLISH(void* THREADABLE_ARGS){
|
|||
/* 1. Initialisation du buffer */
|
||||
bzero(buffer, MAX_BUF_LEN*sizeof(char));
|
||||
|
||||
/* 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 */
|
||||
/* 2. Remplissage de la requête brute */
|
||||
request.flags = BINDHEAD_TCP;
|
||||
request.addr = htonl(servip->s_addr);
|
||||
strcpy(request.addr, SERV_HOST);
|
||||
request.port = htons(TCP_LIST);
|
||||
|
||||
/* 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) );
|
||||
/* 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));
|
||||
|
||||
|
||||
while( 1 ){
|
||||
|
@ -438,7 +392,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} Cannot publish credentials\n");
|
||||
printf("{udp_mcast} Erreur d'envoi\n");
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -449,7 +403,7 @@ void* MCAST_PUBLISH(void* THREADABLE_ARGS){
|
|||
|
||||
/* [n] On ferme la SOCKET CLIENT UDP
|
||||
==========================================================*/
|
||||
printf("{udp_mcast} Closing publisher socket\n");
|
||||
printf("{udp_mcast} FERMETURE SOCKET CLIENT UDP!\n");
|
||||
close(SOCKET);
|
||||
|
||||
return NULL;
|
|
@ -8,12 +8,10 @@
|
|||
* 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"
|
|
@ -0,0 +1,10 @@
|
|||
#!/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;
|
|
@ -0,0 +1,3 @@
|
|||
#!/bin/bash
|
||||
|
||||
echo -ne "\x3\x0\x0" | nc -u localhost 4446;
|
|
@ -0,0 +1,3 @@
|
|||
#!/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;
|
|
@ -0,0 +1,3 @@
|
|||
#!/bin/bash
|
||||
|
||||
echo -ne "\x3\x0\x0" | nc -u localhost 4445;
|
|
@ -0,0 +1,3 @@
|
|||
#!/bin/bash
|
||||
|
||||
/home/xdrm-brackets/Desktop/git.xdrm.io/sysdis-project/central-manager/boot >> $1 2>&1;
|
|
@ -5,6 +5,6 @@ Requires=network.target
|
|||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=root
|
||||
Group=root
|
||||
ExecStart=/usr/sbin/sgca
|
||||
User=xdrm-brackets
|
||||
Group=xdrm-brackets
|
||||
ExecStart=/usr/sbin/sgca /var/log/sgca
|
|
@ -4,12 +4,8 @@
|
|||
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;
|
||||
|
|
@ -17,7 +17,6 @@
|
|||
#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{
|
||||
|
@ -27,38 +26,28 @@
|
|||
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 update;
|
||||
char flags;
|
||||
struct plane udpate;
|
||||
};
|
||||
|
||||
struct term_res{
|
||||
char flags;
|
||||
char n;
|
||||
char flags;
|
||||
char n;
|
||||
struct plane* data;
|
||||
};
|
||||
|
||||
|
||||
#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)
|
||||
#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)
|
||||
|
||||
struct bind_header{
|
||||
char flags;
|
||||
in_addr_t addr;
|
||||
char addr[INET_ADDRSTRLEN];
|
||||
unsigned short port;
|
||||
};
|
||||
|
|
@ -14,16 +14,12 @@
|
|||
#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
|
|
@ -20,7 +20,6 @@
|
|||
#include <pthread.h>
|
||||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
|
||||
/* sys */
|
||||
#include <sys/types.h>
|
||||
|
@ -37,6 +36,7 @@
|
|||
#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,21 +52,13 @@
|
|||
#define maxHostLen 64
|
||||
#define maxPortLen 6
|
||||
|
||||
#define CTRL_TIMEOUT 10 // 10sec timeout (pour ctrlTerm)
|
||||
#define SOCK_TIMEOUT 4 // 4sec timeout (1+ temps refresh plane)
|
||||
#define SOCK_TIMEOUT 3 // 3sec 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 context_unit* unit; // les données des avions
|
||||
unsigned int n; // nombre d'avions
|
||||
struct plane* data; // buffer tes données avion
|
||||
};
|
||||
|
||||
struct middleware_arg{
|
||||
|
@ -76,16 +68,14 @@
|
|||
};
|
||||
|
||||
struct handler_arg{
|
||||
pthread_t* TCPManagers;
|
||||
pthread_t* UDPManagers;
|
||||
int* activeTCPManagers;
|
||||
int* activeUDPManagers;
|
||||
pthread_t* managers;
|
||||
int* activeManagers;
|
||||
int socket;
|
||||
struct context* sgca;
|
||||
};
|
||||
|
||||
struct listen_arg{
|
||||
in_addr_t addr; // socket address
|
||||
const char addr[16]; // socket address
|
||||
const unsigned short port; // socket port
|
||||
int (*middleware)(struct middleware_arg*); // middleware function
|
||||
void* (*handler)(void*); // management function (thread)
|
|
@ -0,0 +1,351 @@
|
|||
/**************************
|
||||
* 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);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -19,6 +19,5 @@
|
|||
void* manageViewTerm(void* THREADABLE_ARGS);
|
||||
void* manageCtrlTerm(void* THREADABLE_ARGS);
|
||||
|
||||
void getPlaneData(char** pBuffer, size_t* pLen, struct context* pContext);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,114 @@
|
|||
/**************************
|
||||
* 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;
|
||||
|
||||
}
|
|
@ -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);
|
||||
|
||||
|
|
@ -22,6 +22,7 @@ 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;
|
||||
|
||||
|
@ -36,6 +37,15 @@ 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
|
||||
=========================================================*/
|
||||
|
@ -51,13 +61,7 @@ int DROP_TCP_SERVER(const int pPort, int* pListenSock){
|
|||
/* [3] On publie la SOCKET
|
||||
=======================================================*/
|
||||
/* 1. Publication socket */
|
||||
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 );
|
||||
STATUS = bind(*pListenSock, (struct sockaddr*) &addr, sizeof(addr));
|
||||
|
||||
if( DEBUGMOD&SCK && DEBUGMOD&HDR ) printf(" * [drop_tcp_server] bind: %d\n", STATUS);
|
||||
|
||||
|
@ -80,6 +84,6 @@ int DROP_TCP_SERVER(const int pPort, int* pListenSock){
|
|||
|
||||
/* [n] Code succès
|
||||
=========================================================*/
|
||||
return pPort+count;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -2,11 +2,12 @@
|
|||
|
||||
|
||||
|
||||
int UDP_SOCKET(int* pSocket, in_addr_t pAddr, const int pPort, struct sockaddr_in* pInfo){
|
||||
int UDP_SOCKET(int* pSocket, const char* pAddr, const int pPort, struct sockaddr_in* pInfo){
|
||||
|
||||
/* [0] Initialisation des variables
|
||||
=========================================================*/
|
||||
*pSocket = -1;
|
||||
struct timeval timeout;
|
||||
|
||||
|
||||
/* [1] Création de la socket
|
||||
|
@ -18,6 +19,15 @@ int UDP_SOCKET(int* pSocket, in_addr_t pAddr, const int pPort, struct sockaddr_i
|
|||
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
|
||||
=========================================================*/
|
||||
|
@ -27,7 +37,7 @@ int UDP_SOCKET(int* pSocket, in_addr_t pAddr, const int pPort, struct sockaddr_i
|
|||
/* (2) On définit les infos */
|
||||
pInfo->sin_family = AF_INET;
|
||||
pInfo->sin_port = htons(pPort);
|
||||
pInfo->sin_addr.s_addr = pAddr;
|
||||
pInfo->sin_addr.s_addr = inet_addr(pAddr);
|
||||
|
||||
|
||||
/* [n] Code succès
|
|
@ -26,7 +26,7 @@
|
|||
/* Créée une socket UDP + crée le sockaddr_in pour la suite
|
||||
*
|
||||
* ==IN==
|
||||
* @pAddr<in_addr_t> Adresse du groupe multicast UDP
|
||||
* @pAddr<const char*> Adresse du groupe multicast UDP
|
||||
* @pPort<const int> Port d'écoute UDP
|
||||
*
|
||||
* ==OUT==
|
||||
|
@ -43,7 +43,7 @@
|
|||
*
|
||||
*
|
||||
*/
|
||||
int UDP_SOCKET(int* pSocket, in_addr_t pAddr, const int pPort, struct sockaddr_in* pInfo);
|
||||
int UDP_SOCKET(int* pSocket, const char* pAddr, const int pPort, struct sockaddr_in* pInfo);
|
||||
|
||||
|
||||
|
|
@ -12,15 +12,15 @@
|
|||
|
||||
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
/* [0] Initialisation des variables
|
||||
=========================================================*/
|
||||
int STATUS; // status
|
||||
struct ip_mreq mcastReq;
|
||||
*pListenSock = -1;
|
||||
struct in_addr tmp;
|
||||
struct timeval timeout;
|
||||
|
||||
|
||||
/* [1] Création de la socket
|
||||
|
@ -33,6 +33,15 @@ int DROP_UDP_SERVER(in_addr_t pAddr, const int pPort, int* pListenSock, struct s
|
|||
/* 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
|
||||
=========================================================*/
|
||||
|
@ -48,13 +57,7 @@ int DROP_UDP_SERVER(in_addr_t pAddr, const int pPort, int* pListenSock, struct s
|
|||
/* [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 );
|
||||
STATUS = bind(*pListenSock, (struct sockaddr*) pInfo, sizeof(struct sockaddr_in));
|
||||
|
||||
if( DEBUGMOD&SCK && DEBUGMOD&HDR ) printf(" * [drop_udp_server] bind: %d\n", STATUS);
|
||||
|
||||
|
@ -64,10 +67,8 @@ int DROP_UDP_SERVER(in_addr_t pAddr, const int pPort, int* pListenSock, struct s
|
|||
/* 3. Demande groupe multicast (si demandé) */
|
||||
if( pMcast ){
|
||||
|
||||
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;
|
||||
if( DEBUGMOD&SCK && DEBUGMOD&HDR ) printf(" * [drop_udp_server] join mcast group: %s\n", pAddr);
|
||||
mcastReq.imr_multiaddr.s_addr = inet_addr(pAddr);
|
||||
mcastReq.imr_interface.s_addr = htonl(INADDR_ANY);
|
||||
|
||||
if( setsockopt(*pListenSock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mcastReq, sizeof(mcastReq)) < 0 ){
|
||||
|
@ -80,6 +81,6 @@ int DROP_UDP_SERVER(in_addr_t pAddr, const int pPort, int* pListenSock, struct s
|
|||
|
||||
/* [n] Code succès
|
||||
=========================================================*/
|
||||
return pPort+count;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -20,7 +20,7 @@
|
|||
/* Créé et met un serveur UDP d'écoute MULTICAST ou CLASSIQUE
|
||||
*
|
||||
* ==IN==
|
||||
* @pAddr<in_addr_t> Adresse du groupe multicast UDP
|
||||
* @pAddr<const char*> 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(in_addr_t pAddr, const int pPort, int* pListenSock, struct sockaddr_in* pInfo, const char pMcast);
|
||||
int DROP_UDP_SERVER(const char* pAddr, const int pPort, int* pListenSock, struct sockaddr_in* pInfo, const char pMcast);
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
<?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>
|
|
@ -0,0 +1,3 @@
|
|||
Manifest-Version: 1.0
|
||||
X-COMMENT: Main-Class will be added automatically by build
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,8 @@
|
|||
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
|
|
@ -0,0 +1,73 @@
|
|||
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
|
|
@ -0,0 +1,15 @@
|
|||
<?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>
|
|
@ -13,20 +13,16 @@ 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{
|
||||
|
||||
public final static int MAX_MESSAGE_SIZE = 300;
|
||||
private 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<>();
|
||||
|
@ -40,10 +36,6 @@ 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);
|
||||
}
|
||||
|
@ -57,8 +49,8 @@ public class AsynchronousDatagramSocket implements Runnable, AutoCloseable{
|
|||
}
|
||||
}
|
||||
|
||||
public DatagramPacket synchronousReceive(){
|
||||
return this.buf.removeElement(true);
|
||||
public void synchronousReceive(DatagramPacket dp){
|
||||
dp = this.buf.removeElement(true);
|
||||
}
|
||||
|
||||
public boolean available(){
|
||||
|
@ -72,18 +64,12 @@ public class AsynchronousDatagramSocket implements Runnable, AutoCloseable{
|
|||
|
||||
@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");
|
||||
}
|
||||
DatagramPacket packet = new DatagramPacket(new byte[MAX_MESSAGE_SIZE],MAX_MESSAGE_SIZE);
|
||||
try {
|
||||
this.socket.receive(packet);
|
||||
this.buf.addElement(packet);
|
||||
} catch (IOException ex) {
|
||||
Logger.getLogger(AsynchronousDatagramSocket.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* 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();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* 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
|
||||
}
|
Binary file not shown.
|
@ -1,208 +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 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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
package ControlTerminal;
|
||||
|
||||
public class InvalidFlagException extends Exception {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public InvalidFlagException(){
|
||||
super();
|
||||
}
|
||||
|
||||
public InvalidFlagException(String message){
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,125 +0,0 @@
|
|||
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();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,119 +0,0 @@
|
|||
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;
|
||||
}
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
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)");
|
||||
}
|
||||
}
|
|
@ -1,89 +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 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");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -23,5 +23,5 @@ all: boot
|
|||
|
||||
# cleans the compiled files
|
||||
clean:
|
||||
@rm ./lib/network/**/*.o;
|
||||
@rm ./boot;
|
||||
rm boot;
|
||||
rm ./lib/network/**/*.o
|
||||
|
|
|
@ -10,11 +10,10 @@
|
|||
#include "client.h"
|
||||
|
||||
|
||||
int TCP_CONNECT(int* pSocket, const in_addr_t pAddr, const int pPort, const time_t pTimeout, struct sockaddr_in* pInfo){
|
||||
int TCP_CONNECT(int* pSocket, const char* pAddr, const int pPort, struct sockaddr_in* pInfo){
|
||||
|
||||
/* [0] Initialisation des variables
|
||||
=========================================================*/
|
||||
struct timeval timeout;
|
||||
*pSocket = -1;
|
||||
|
||||
|
||||
|
@ -27,16 +26,6 @@ int TCP_CONNECT(int* pSocket, const in_addr_t pAddr, const int pPort, const time
|
|||
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
|
||||
=========================================================*/
|
||||
|
@ -46,7 +35,7 @@ int TCP_CONNECT(int* pSocket, const in_addr_t pAddr, const int pPort, const time
|
|||
/* (2) On définit les infos */
|
||||
pInfo->sin_family = AF_INET;
|
||||
pInfo->sin_port = htons(pPort);
|
||||
pInfo->sin_addr.s_addr = pAddr;
|
||||
pInfo->sin_addr.s_addr = inet_addr(pAddr);
|
||||
|
||||
|
||||
/* [3] On se connecte au serveur
|
||||
|
|
|
@ -18,9 +18,8 @@
|
|||
/* Créée une socket TCP et la connecte + crée le sockaddr_in pour la suite
|
||||
*
|
||||
* ==IN==
|
||||
* @pAddr<const in_addr_t> Adresse du serveur TCP
|
||||
* @pPort<const int> Port du serveur TCP
|
||||
* @pTimeout<const time_t> Timeout de réception
|
||||
* @pAddr<const char*> Adresse du serveur TCP
|
||||
* @pPort<const int> Port du serveur TCP
|
||||
*
|
||||
* ==OUT==
|
||||
* @pSocket<int*> Pointeur sur le <int> à remplir => contiendra un pointeur sur la socket créée
|
||||
|
@ -35,6 +34,6 @@
|
|||
* [3] On se connecte au serveur
|
||||
*
|
||||
*/
|
||||
int TCP_CONNECT(int* pSocket, const in_addr_t pAddr, const int pPort, const time_t pTimeout, struct sockaddr_in* pInfo);
|
||||
int TCP_CONNECT(int* pSocket, const char* pAddr, const int pPort, struct sockaddr_in* pInfo);
|
||||
|
||||
#endif
|
|
@ -35,13 +35,7 @@ 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, (char*) &timeout, sizeof(struct timeval) ) < 0 ){
|
||||
close(*pListenSock);
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
if( setsockopt(*pListenSock, SOL_SOCKET, SO_SNDTIMEO, (char*) &timeout, sizeof(struct timeval) ) < 0 ){
|
||||
if( setsockopt(*pListenSock, SOL_SOCKET, SO_RCVTIMEO|SO_SNDTIMEO, (char*) &timeout, sizeof(struct timeval) ) < 0 ){
|
||||
close(*pListenSock);
|
||||
return -1;
|
||||
}
|
||||
|
@ -68,7 +62,7 @@ int DROP_MULTICAST_SERVER(const char* pAddr, const int pPort, int* pListenSock,
|
|||
/* [3] On publie la SOCKET
|
||||
=======================================================*/
|
||||
/* 1. Publication socket */
|
||||
STATUS = bind(*pListenSock, (struct sockaddr*) pInfo, sizeof(struct sockaddr_in));
|
||||
STATUS = bind(*pListenSock, (struct sockaddr*) pInfo, sizeof(struct sockaddr_in));
|
||||
|
||||
/* 2. Gestion erreur */
|
||||
if( STATUS < 0 ) return -1;
|
||||
|
|
210
plane/plane.c
210
plane/plane.c
|
@ -18,8 +18,8 @@ char numero_vol[6];
|
|||
struct coord crd;
|
||||
struct control ctrl;
|
||||
|
||||
int mcast_socket = -1;
|
||||
int commu_socket = -1;
|
||||
int mcast_socket = -1;
|
||||
int commu_socket = -1;
|
||||
char buffer[MAX_BUF_LEN] = {0};
|
||||
struct sockaddr_in sgca;
|
||||
|
||||
|
@ -31,7 +31,6 @@ 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
|
||||
=========================================================*/
|
||||
|
@ -39,13 +38,8 @@ int open_communication(){
|
|||
|
||||
/* (1) Création socket multicast client* (écoute)
|
||||
---------------------------------------------------------*/
|
||||
if( DROP_MULTICAST_SERVER(MCST_HOST, MCST_PORT, &mcast_socket, &udp) < 0 ){
|
||||
printf("/!\\ Cannot drop multicast server\n");
|
||||
if( DROP_MULTICAST_SERVER(MCST_HOST, MCST_PORT, &mcast_socket, &udp) < 0 )
|
||||
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
|
||||
|
||||
|
@ -58,39 +52,26 @@ 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.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) );
|
||||
|
||||
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) );
|
||||
// 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 TCP credentials (flags: %x, ip: %s:%d)\n", request.flags, inet_ntoa(ip), request.port);
|
||||
printf("* received bind_header{flags = %d; addr = %s; port = %d;}\n\n", request.flags, request.addr, request.port);
|
||||
|
||||
|
||||
|
||||
|
@ -103,12 +84,8 @@ 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, PAUSE, &sgca) < 0 ){
|
||||
printf("/!\\ Can't connect to TCP socket\n");
|
||||
if( TCP_CONNECT(&commu_socket, request.addr, request.port, &sgca) < 0 )
|
||||
return 0;
|
||||
}
|
||||
|
||||
printf("* Connected to TCP server\n");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -116,25 +93,12 @@ 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(char flags){
|
||||
void send_data(){
|
||||
|
||||
/* [0] Initialisation des variables
|
||||
=========================================================*/
|
||||
|
@ -142,6 +106,7 @@ void send_data(char flags){
|
|||
struct plane_data request;
|
||||
int read;
|
||||
|
||||
|
||||
/* [1] Envoi des caractéristiques
|
||||
=========================================================*/
|
||||
/* 1. Vérification socket */
|
||||
|
@ -150,29 +115,39 @@ void send_data(char flags){
|
|||
|
||||
/* 2. création objet */
|
||||
strcpy(request.code, numero_vol);
|
||||
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 );
|
||||
request.x = crd.x;
|
||||
request.y = crd.y;
|
||||
request.z = crd.z;
|
||||
request.cap = ctrl.cap;
|
||||
request.spd = ctrl.speed;
|
||||
|
||||
/* 3. Copie buffer */
|
||||
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) );
|
||||
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) );
|
||||
|
||||
read = send(commu_socket, buffer, (1+PLANE_DATA_LEN)/sizeof(char), 0);
|
||||
read = send(commu_socket, buffer, PLANE_DATA_LEN/sizeof(char) + 1, 0);
|
||||
|
||||
if( read <= 0 ){
|
||||
printf("Cannot send\n");
|
||||
printf("Erreur d'envoi\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
|
||||
|
||||
}
|
||||
|
||||
|
@ -181,10 +156,6 @@ void send_data(char flags){
|
|||
********************************/
|
||||
|
||||
// initialise aléatoirement les paramètres initiaux de l'plane
|
||||
|
||||
|
||||
|
||||
|
||||
void init_plane(){
|
||||
// initialisation aléatoire du compteur aléatoire
|
||||
time_t seed;
|
||||
|
@ -210,61 +181,28 @@ void init_plane(){
|
|||
}
|
||||
|
||||
// modifie la valeur de l'plane avec la valeur passée en paramètre
|
||||
|
||||
|
||||
|
||||
|
||||
int update_speed(int speed){
|
||||
if( speed < 0 )
|
||||
return -1;
|
||||
|
||||
if( speed > VITMAX )
|
||||
return -1;
|
||||
|
||||
ctrl.speed = speed;
|
||||
return 0;
|
||||
void update_speed(int speed){
|
||||
if (speed < 0) ctrl.speed = speed;
|
||||
}
|
||||
|
||||
// modifie le cap de l'plane avec la valeur passée en paramètre
|
||||
|
||||
|
||||
|
||||
|
||||
int update_cap(int cap){
|
||||
if( cap < 0 || cap >= 360 )
|
||||
return -1;
|
||||
|
||||
ctrl.cap = cap;
|
||||
return 0;
|
||||
void update_cap(int cap){
|
||||
if ((cap >= 0) && (cap < 360))
|
||||
ctrl.cap = cap;
|
||||
}
|
||||
|
||||
// modifie l'z de l'plane avec la valeur passée en paramètre
|
||||
|
||||
|
||||
|
||||
|
||||
int update_z(int alt){
|
||||
if( alt < 0 )
|
||||
return 01;
|
||||
|
||||
crd.z = alt;
|
||||
return 0;
|
||||
void update_z(int alt){
|
||||
if (alt < 0)
|
||||
crd.z = alt;
|
||||
}
|
||||
|
||||
// affiche les caractéristiques courantes de l'plane
|
||||
|
||||
|
||||
|
||||
|
||||
void display_data(){
|
||||
printf("| Plane %s | (%d,%d,%d) - speed: %d - cap: %d\n", numero_vol, crd.x, crd.y, crd.z, ctrl.speed, ctrl.cap);
|
||||
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);
|
||||
}
|
||||
|
||||
// recalcule la localisation de l'plane en fonction de sa speed et de son cap
|
||||
|
||||
|
||||
|
||||
|
||||
void calc_ctrl(){
|
||||
float ctrl_x, ctrl_y;
|
||||
|
||||
|
@ -296,67 +234,13 @@ 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(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);
|
||||
send_data();
|
||||
|
||||
}
|
||||
|
||||
|
@ -369,14 +253,10 @@ 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;
|
||||
}
|
|
@ -49,27 +49,14 @@
|
|||
int spd;
|
||||
};
|
||||
|
||||
#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)
|
||||
#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
|
||||
|
||||
struct bind_header{
|
||||
char flags;
|
||||
in_addr_t addr;
|
||||
char addr[INET_ADDRSTRLEN];
|
||||
unsigned short port;
|
||||
};
|
||||
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
.vscode
|
||||
*.o
|
||||
boot
|
|
@ -1,21 +0,0 @@
|
|||
#!/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;
|
|
@ -1,615 +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 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);
|
||||
|
||||
}
|
|
@ -1,155 +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
|
||||
=========================================================*/
|
||||
/* 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;
|
||||
|
||||
}
|
|
@ -1,118 +0,0 @@
|
|||
/**************************
|
||||
* 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;
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -1,74 +0,0 @@
|
|||
/**************************
|
||||
* 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
|
|
@ -1,46 +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 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();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
package ViewTerminal;
|
||||
|
||||
public class InvalidFlagException extends Exception {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public InvalidFlagException(){
|
||||
super();
|
||||
}
|
||||
|
||||
public InvalidFlagException(String message){
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,108 +0,0 @@
|
|||
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 "";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,98 +0,0 @@
|
|||
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;
|
||||
}
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
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]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,102 +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 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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
Binary file not shown.
Loading…
Reference in New Issue