383 lines
9.8 KiB
C
383 lines
9.8 KiB
C
/**************************
|
|
* Plane *
|
|
***************************
|
|
* Designed & Developed by *
|
|
* Adrien Marquès *
|
|
* <xdrm-brackets> *
|
|
***************************
|
|
* doowap31@gmail.com *
|
|
**************************/
|
|
#include "plane.h"
|
|
|
|
|
|
|
|
|
|
// numéro de vol de l'plane : code sur 5 caractères
|
|
char numero_vol[6];
|
|
|
|
struct coord crd;
|
|
struct control ctrl;
|
|
|
|
int mcast_socket = -1;
|
|
int commu_socket = -1;
|
|
char buffer[MAX_BUF_LEN] = {0};
|
|
struct sockaddr_in sgca;
|
|
|
|
|
|
|
|
int open_communication(){
|
|
/* 0. Initialisation des variables */
|
|
struct sockaddr_in udp; // données des sockets
|
|
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
|
|
=========================================================*/
|
|
|
|
|
|
/* (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");
|
|
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
|
|
|
|
|
|
/* (2) Attente réponse SGCA -> adresse+port TCP
|
|
---------------------------------------------------------*/
|
|
/* 1. Attente réponse */
|
|
status = recv(mcast_socket, buffer, MAX_BUF_LEN, 0);
|
|
|
|
/* 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) );
|
|
|
|
// 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);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* [2] Socket communication TCP
|
|
=========================================================*/
|
|
|
|
/* (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");
|
|
return 0;
|
|
}
|
|
|
|
printf("* Connected to TCP server\n");
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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){
|
|
|
|
/* [0] Initialisation des variables
|
|
=========================================================*/
|
|
char buffer[MAX_BUF_LEN] = {0};
|
|
struct plane_data request;
|
|
int read;
|
|
|
|
/* [1] Envoi des caractéristiques
|
|
=========================================================*/
|
|
/* 1. Vérification socket */
|
|
if( commu_socket < 0 )
|
|
return;
|
|
|
|
/* 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 );
|
|
|
|
/* 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) );
|
|
|
|
read = send(commu_socket, buffer, (1+PLANE_DATA_LEN)/sizeof(char), 0);
|
|
|
|
if( read <= 0 ){
|
|
printf("Cannot send\n");
|
|
return;
|
|
}
|
|
// printf("* hex("); for( int i = 0 ; i < PLANE_DATA_LEN/sizeof(char) ; i++ ) printf("\\x%02X", buffer[i]); printf(")\n");
|
|
|
|
|
|
}
|
|
|
|
/********************************
|
|
*** Fonctions gérant le déplacement de l'plane : ne pas modifier
|
|
********************************/
|
|
|
|
// initialise aléatoirement les paramètres initiaux de l'plane
|
|
|
|
|
|
|
|
|
|
void init_plane(){
|
|
// initialisation aléatoire du compteur aléatoire
|
|
time_t seed;
|
|
time( &seed);
|
|
srandom(seed);
|
|
|
|
// intialisation des paramètres de l'plane
|
|
crd.x = 1000 + random() % 1000;
|
|
crd.y = 1000 + random() % 1000;
|
|
crd.z = 900 + random() % 100;
|
|
|
|
ctrl.cap = random() % 360;
|
|
ctrl.speed = 600 + random() % 200;
|
|
|
|
// initialisation du numero de l'plane : chaine de 5 caractères
|
|
// formée de 2 lettres puis 3 chiffres
|
|
numero_vol[0] = (random() % 26) + 'A';
|
|
numero_vol[1] = (random() % 26) + 'A';
|
|
numero_vol[2] = (random() % 10) + '0';
|
|
numero_vol[3] = (random() % 10) + '0';
|
|
numero_vol[4] = (random() % 10) + '0';
|
|
numero_vol[5] = 0;
|
|
}
|
|
|
|
// 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;
|
|
}
|
|
|
|
// 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;
|
|
}
|
|
|
|
// 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;
|
|
}
|
|
|
|
// 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);
|
|
}
|
|
|
|
// recalcule la localisation de l'plane en fonction de sa speed et de son cap
|
|
|
|
|
|
|
|
|
|
void calc_ctrl(){
|
|
float ctrl_x, ctrl_y;
|
|
|
|
if (ctrl.speed < VITMIN){
|
|
close_communication();
|
|
exit(2);
|
|
}
|
|
if (crd.z == 0){
|
|
close_communication();
|
|
exit(3);
|
|
}
|
|
|
|
ctrl_x = cos(ctrl.cap * 2 * M_PI / 360) * ctrl.speed * 10 / VITMIN;
|
|
ctrl_y = sin(ctrl.cap * 2 * M_PI / 360) * ctrl.speed * 10 / VITMIN;
|
|
|
|
// on se déplace d'au moins une case quels que soient le cap et la speed
|
|
// sauf si cap est un des angles droit
|
|
if ((ctrl_x > 0) && (ctrl_x < 1)) ctrl_x = 1;
|
|
if ((ctrl_x < 0) && (ctrl_x > -1)) ctrl_x = -1;
|
|
|
|
if ((ctrl_y > 0) && (ctrl_y < 1)) ctrl_y = 1;
|
|
if ((ctrl_y < 0) && (ctrl_y > -1)) ctrl_y = -1;
|
|
|
|
|
|
crd.x = crd.x + (int)ctrl_x;
|
|
crd.y = crd.y + (int)ctrl_y;
|
|
|
|
display_data();
|
|
}
|
|
|
|
// 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 ){
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
int main(){
|
|
// on initialise le plane
|
|
init_plane();
|
|
|
|
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;
|
|
}
|