From 1a98172fcaf177cc765e9dcbe7370eef63e3e338 Mon Sep 17 00:00:00 2001 From: xdrm-brackets Date: Fri, 28 Apr 2017 14:54:02 +0200 Subject: [PATCH] [done] ctrlTerm plane update procedure (v0.1) to be tested by SdS --- central-manager/central-manager.c | 51 +++-- central-manager/lib/data.h | 11 +- central-manager/lib/header.h | 8 +- central-manager/lib/local/handler.c | 270 ++++++++++++++--------- central-manager/lib/local/middleware.c | 12 +- central-manager/lib/network/common.c | 56 +++-- central-manager/lib/network/common.h | 35 +++ central-manager/lib/network/tcp/server.c | 10 - central-manager/lib/network/udp/client.c | 10 - central-manager/lib/network/udp/server.c | 10 - plane/lib/network/tcp/client.c | 13 +- plane/lib/network/tcp/client.h | 5 +- plane/lib/network/udp/server.c | 8 +- plane/plane.c | 140 +++++++++--- plane/plane.h | 11 + 15 files changed, 446 insertions(+), 204 deletions(-) diff --git a/central-manager/central-manager.c b/central-manager/central-manager.c index bca358b..b41f2fa 100644 --- a/central-manager/central-manager.c +++ b/central-manager/central-manager.c @@ -34,8 +34,9 @@ int main(int argc, char* argv[]){ /* [0] Initialisation des variables =========================================================*/ /* 1. Variables globales */ - sgca.n = 0; - sgca.data = (struct plane*) malloc( sizeof(struct plane) ); + sgca.n = 0; + sgca.data = (struct plane*) malloc( sizeof(struct plane) ); + sgca.socket = (int*) malloc( sizeof(int) ); struct in_addr* SERV_HOST; /* 2. On récupère l'IP locale' */ @@ -58,19 +59,19 @@ int main(int argc, char* argv[]){ =========================================================*/ /* (1) Ecoute TCP */ pthread_create(&listenManagers[0], NULL, LISTEN_TCP, (void*) &tcp_listn_arg); - if( DEBUGMOD&THR ) printf("{tcp_listn} démarré\n"); + if( DEBUGMOD&THR ) printf("{tcp_listn} started\n"); /* (2) Ecoute UDP multicast */ pthread_create(&listenManagers[1], NULL, MCAST_PUBLISH, (void*) &udp_mcast_arg); - if( DEBUGMOD&THR ) printf("{udp_mcast} démarré\n"); + if( DEBUGMOD&THR ) printf("{udp_mcast} started\n"); /* (3) Ecoute UDP viewTerm */ pthread_create(&listenManagers[2], NULL, LISTEN_UDP, (void*) &udp_vterm_arg); - if( DEBUGMOD&THR ) printf("{udp_vterm} démarré\n"); + if( DEBUGMOD&THR ) printf("{udp_vterm} started\n"); /* (4) Ecoute UDP ctrlTerm */ pthread_create(&listenManagers[3], NULL, LISTEN_UDP, (void*) &udp_cterm_arg); - if( DEBUGMOD&THR ) printf("{udp_cterm} démarré\n"); + if( DEBUGMOD&THR ) printf("{udp_cterm} started\n"); /* [2] On attends la fin de tous les THREADS @@ -82,6 +83,7 @@ int main(int argc, char* argv[]){ /* [3] On libère les variables globales ==========================================================*/ free(sgca.data); + free(sgca.socket); return EXIT_SUCCESS; } @@ -121,10 +123,10 @@ void* LISTEN_TCP(void* THREADABLE_ARGS){ ==========================================================*/ if( DROP_TCP_SERVER(arg->port, &LISTENSOCK) < 0 ){ - if( DEBUGMOD&SCK ) printf("{tcp_listn} Erreur création socket d'écoute\n"); + if( DEBUGMOD&SCK ) printf("{tcp_listn} Error creating listener socket\n"); // On ferme la SOCKET d'écoute globale - printf("{tcp_listn} FERMETURE SOCKET D'ECOUTE TCP!\n"); + printf("{tcp_listn} Closing listener socket!\n"); close(LISTENSOCK); return NULL; @@ -154,7 +156,7 @@ void* LISTEN_TCP(void* THREADABLE_ARGS){ break; } - if( DEBUGMOD&SCK ) printf("{tcp_listn} %s:%d connecté\n", inet_ntoa(clientInfo.sin_addr), ntohs(clientInfo.sin_port)); + if( DEBUGMOD&SCK ) printf("{tcp_listn} %s:%d connected\n", inet_ntoa(clientInfo.sin_addr), ntohs(clientInfo.sin_port)); /* 4. On cherche un "manager" libre (inactif) */ for( i = 0 ; i < MAX_TCP_THR ; i++ ) @@ -169,13 +171,13 @@ void* LISTEN_TCP(void* THREADABLE_ARGS){ /* 5. On lance un thread pour le traitement de ce client */ pthread_create(&TCPManagers[index], NULL, arg->handler, (void*) &thread_args); - if( DEBUGMOD&THR ) printf("{tcp_listn}{com}(%d) démarré\n", index); + if( DEBUGMOD&THR ) printf("{tcp_listn}{com}(%d) started\n", index); /* 6. On signale que ce "manager" est maintenant actif */ activeTCPManagers[index] = 1; }else - if( DEBUGMOD&THR ) printf("{tcp_listn} Aucun thread libre\n"); + if( DEBUGMOD&THR ) printf("{tcp_listn} No available thread\n"); } @@ -188,7 +190,7 @@ void* LISTEN_TCP(void* THREADABLE_ARGS){ /* [4] On ferme la SOCKET d'écoute globale ==========================================================*/ - printf("{tcp_listn} FERMETURE SOCKET D'ECOUTE TCP!\n"); + printf("{tcp_listn} Closing listener socket\n"); close(LISTENSOCK); return NULL; @@ -244,17 +246,22 @@ void* LISTEN_UDP(void* THREADABLE_ARGS){ /* [1] On démarre le SERVEUR UDP d'écoute globale ==========================================================*/ + /* 1. On crée la socket */ if( DROP_UDP_SERVER(arg->addr, arg->port, &SOCKET, &listenInfo, 1) < 0 ){ - if( DEBUGMOD&SCK ) printf("{%s} Erreur de création socket d'écoute\n", entity); + if( DEBUGMOD&SCK ) printf("{%s} Error creating listener socket\n", entity); // On ferme la SOCKET d'écoute globale - printf("{%s} FERMETURE SOCKET D'ECOUTE UDP!\n", entity); + printf("{%s} Closing listener socket!\n", entity); close(SOCKET); return NULL; } + /* 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), arg->port); @@ -273,8 +280,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 */ @@ -315,13 +322,13 @@ void* LISTEN_UDP(void* THREADABLE_ARGS){ /* 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) démarré\n", entity, index); + if( DEBUGMOD&THR ) printf("{%s}{com}(%d) started\n", entity, index); /* 2.2. On signale que ce "manager" est maintenant actif */ activeUDPManagers[index] = 1; }else - if( DEBUGMOD&THR ) printf("{%s} Aucun thread UDP libre!\n", entity); + if( DEBUGMOD&THR ) printf("{%s} No available thread\n", entity); } @@ -329,7 +336,7 @@ void* LISTEN_UDP(void* THREADABLE_ARGS){ /* [n] On ferme la SOCKET d'écoute globale ==========================================================*/ - printf("{%s} FERMETURE SOCKET D'ECOUTE UDP!\n", entity); + printf("{%s} Closing listener socket\n", entity); close(SOCKET); return NULL; @@ -395,7 +402,7 @@ void* MCAST_PUBLISH(void* THREADABLE_ARGS){ 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} FERMETURE SOCKET CLIENT UDP!\n"); + printf("{udp_mcast} Closing publisher socket!\n"); close(SOCKET); return NULL; } @@ -421,7 +428,7 @@ void* MCAST_PUBLISH(void* THREADABLE_ARGS){ /* [4] On envoie les information de la socket TCP =========================================================*/ if( sendto(SOCKET, buffer, BINDHDR_LEN / sizeof(char) + 1, 0, (struct sockaddr*) &targetInfo, sizeof(struct sockaddr_in)) < 0 ){ - printf("{udp_mcast} Erreur d'envoi\n"); + printf("{udp_mcast} Cannot publish credentials\n"); break; } @@ -432,7 +439,7 @@ void* MCAST_PUBLISH(void* THREADABLE_ARGS){ /* [n] On ferme la SOCKET CLIENT UDP ==========================================================*/ - printf("{udp_mcast} FERMETURE SOCKET CLIENT UDP!\n"); + printf("{udp_mcast} Closing publisher socket\n"); close(SOCKET); return NULL; diff --git a/central-manager/lib/data.h b/central-manager/lib/data.h index d990f58..b5d5171 100644 --- a/central-manager/lib/data.h +++ b/central-manager/lib/data.h @@ -29,9 +29,18 @@ char online; }; + struct plane_update{ + char flags; + int z; + int cap; + int spd; + char done; + }; + + #define TERMREQ_LEN ( sizeof(char)+PLANE_LEN ) struct term_req{ char flags; - struct plane udpate; + struct plane update; }; struct term_res{ diff --git a/central-manager/lib/header.h b/central-manager/lib/header.h index bce3ec0..8fa7143 100644 --- a/central-manager/lib/header.h +++ b/central-manager/lib/header.h @@ -51,13 +51,15 @@ #define maxHostLen 64 #define maxPortLen 6 - #define SOCK_TIMEOUT 3 // 3sec timeout (1+ temps refresh plane) + #define SOCK_TIMEOUT 4 // 4sec timeout (1+ temps refresh plane) #define PUBL_TIMEOUT 2 // 2sec entre chaque publication sur multicast UDP (pour avions) struct context{ - unsigned int n; // nombre d'avions - struct plane* data; // buffer tes données avion + unsigned int n; // nombre d'avions + int* socket; // sockets associées aux avions + struct plane* data; // buffer tes données avion + struct plane_update* request; // Stack des requêtes de modifications }; struct middleware_arg{ diff --git a/central-manager/lib/local/handler.c b/central-manager/lib/local/handler.c index 41a77e3..64f3a95 100644 --- a/central-manager/lib/local/handler.c +++ b/central-manager/lib/local/handler.c @@ -37,10 +37,10 @@ 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) + 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 */ @@ -61,6 +61,8 @@ void* managePlane(void* THREADABLE_ARGS){ } + pindex = -1; // on ne connait pas encore l'avion + while( 1 ){ /* (2) Récupération de la requête @@ -102,67 +104,40 @@ void* managePlane(void* THREADABLE_ARGS){ /* (3) Gestion de la requête -> enregistrement ---------------------------------------------------------*/ - pindex = -1; + /* 1. On cherche le rang de l'avion si on l'a pas déja */ + if( pindex <= -1 ){ - /* 1. On regarde si l'avion existe */ - for( i = 0 ; i < arg->sgca->n ; i++ ){ + /* 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->data[i].code, data.code) == 0 ){ + pindex = i; + break; + } - // 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 ){ + /* 3. Création si n'existe pas */ + if( pindex <= -1 ){ - // On ajoute une entrée à data - pindex = arg->sgca->n; + // On ajoute une entrée à data + socket + pindex = arg->sgca->n; arg->sgca->n++; - arg->sgca->data = (struct plane*) realloc(arg->sgca->data, sizeof(struct plane)*arg->sgca->n + 1); + arg->sgca->data = (struct plane*) realloc(arg->sgca->data, sizeof(struct plane)*arg->sgca->n + 1); + arg->sgca->socket = (int*) realloc(arg->sgca->socket, sizeof(struct plane)*arg->sgca->n + 1); + arg->sgca->socket[pindex] = SOCKET; printf("{tcp_com}(%d) plane '%s' (#%d) created\n", index, data.code, pindex); } - /* 3. On copie les constantes */ + /* 4. On copie/met à jour les valeurs */ memcpy(&arg->sgca->data[pindex], &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->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 = htonl(arg->sgca->data[pindex].x); - data.y = htonl(arg->sgca->data[pindex].y); - data.z = htonl(arg->sgca->data[pindex].z); - data.cap = htonl(arg->sgca->data[pindex].cap); - data.spd = htonl(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); - - - } @@ -170,6 +145,7 @@ void* managePlane(void* THREADABLE_ARGS){ =========================================================*/ /* 1. On notifie le crash */ arg->sgca->data[pindex].online = 0; + arg->sgca->socket[pindex] = -1; @@ -182,7 +158,7 @@ void* managePlane(void* THREADABLE_ARGS){ /* [7] Fermeture de la connection (SOCKET) =========================================================*/ - printf("{tcp_com}(%d) Fermeture de la socket de communication!\n", index); + printf("{tcp_com}(%d) Closing communication socket\n", index); close(SOCKET); @@ -194,7 +170,7 @@ void* managePlane(void* THREADABLE_ARGS){ arg->activeManagers[index] = 0; /* 2. On arrête le THREAD */ - if( DEBUGMOD&THR ) printf("{tcp_com}(%d) libéré\n", index); + if( DEBUGMOD&THR ) printf("{tcp_com}(%d) freed\n", index); pthread_exit(NULL); } @@ -233,7 +209,7 @@ void* manageViewTerm(void* THREADABLE_ARGS){ int count, last, sent, nb; // compteurs d'envoi int i, index = -1; // Compteurs globaux char buffer[MAX_BUF_LEN]; // Buffer d'envoi - struct term_res request; // Requête + struct term_res response; // Requête /* 2. On récupère les arguments */ struct handler_arg* arg = THREADABLE_ARGS; @@ -242,7 +218,7 @@ void* manageViewTerm(void* THREADABLE_ARGS){ for( i = 0 ; i < MAX_UDP_THR ; i++ ) if( arg->managers[i] == pthread_self() ){ index = i; break; } - printf("{udp_vterm}{com}(%d) starting terminal routine\n", index); + printf("{udp_vterm}{com}(%d) starting terminal routine (rate: %d sec)\n", index, PUBL_TIMEOUT); /* 4. Attente d'un client */ @@ -252,32 +228,34 @@ void* manageViewTerm(void* THREADABLE_ARGS){ loop = 0; } + if( loop ) printf("{udp_cterm}{com}(%d) Terminal connected\n", index); + while( loop ){ /* [2] Récupération des données =========================================================*/ /* 1. On initialise les variables utiles */ - request.flags = TERMREQ_FBK; - nb = arg->sgca->n; - request.n = 0; // nombre d'avions online + response.flags = TERMREQ_FBK; + nb = arg->sgca->n; + response.n = 0; // nombre d'avions online - free(request.data); - request.data = malloc( nb * sizeof(struct plane) + 1 ); + free(response.data); + 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(&request.data[i].code, &arg->sgca->data[i].code, sizeof(char)*6); - request.data[i].x = htonl( arg->sgca->data[i].x ); - request.data[i].y = htonl( arg->sgca->data[i].y ); - request.data[i].z = htonl( arg->sgca->data[i].z ); - request.data[i].cap = htonl( arg->sgca->data[i].cap ); - request.data[i].spd = htonl( arg->sgca->data[i].spd ); - request.data[i].online = arg->sgca->data[i].online; + memcpy(&response.data[i].code, &arg->sgca->data[i].code, sizeof(char)*6); + response.data[i].x = htonl( arg->sgca->data[i].x ); + response.data[i].y = htonl( arg->sgca->data[i].y ); + response.data[i].z = htonl( arg->sgca->data[i].z ); + response.data[i].cap = htonl( arg->sgca->data[i].cap ); + response.data[i].spd = htonl( arg->sgca->data[i].spd ); + response.data[i].online = arg->sgca->data[i].online; // Incrément du compte si online - request.n += request.data[i].online; + response.n += response.data[i].online; } @@ -288,22 +266,22 @@ void* manageViewTerm(void* THREADABLE_ARGS){ bzero(buffer, MAX_BUF_LEN*sizeof(char)); /* 2. Copie des données globales */ - count = 0; last = sizeof(char); memcpy(buffer+count, &request.flags, last); - count += last; last = sizeof(char); memcpy(buffer+count, &request.n, last); + count = 0; last = sizeof(char); memcpy(buffer+count, &response.flags, last); + count += last; last = sizeof(char); memcpy(buffer+count, &response.n, last); /* 3. Copie des données des avions */ for( i = 0 ; i < nb ; i++ ){ // Ignore les avions offline - if( !request.data[i].online ) + if( !response.data[i].online ) continue; - count += last; last = sizeof(char)*6; memcpy(buffer+count, &request.data[i].code, last); - count += last; last = sizeof(int); memcpy(buffer+count, &request.data[i].x, last); - count += last; last = sizeof(int); memcpy(buffer+count, &request.data[i].y, last); - count += last; last = sizeof(int); memcpy(buffer+count, &request.data[i].z, last); - count += last; last = sizeof(int); memcpy(buffer+count, &request.data[i].cap, last); - count += last; last = sizeof(int); memcpy(buffer+count, &request.data[i].spd, last); + count += last; last = sizeof(char)*6; memcpy(buffer+count, &response.data[i].code, last); + count += last; last = sizeof(int); memcpy(buffer+count, &response.data[i].x, last); + count += last; last = sizeof(int); memcpy(buffer+count, &response.data[i].y, last); + count += last; last = sizeof(int); memcpy(buffer+count, &response.data[i].z, last); + count += last; last = sizeof(int); memcpy(buffer+count, &response.data[i].cap, last); + count += last; last = sizeof(int); memcpy(buffer+count, &response.data[i].spd, last); } count += last; @@ -333,13 +311,16 @@ void* manageViewTerm(void* THREADABLE_ARGS){ /* [n] Arrêt du THREAD ============================================================================*/ - - /* 2. On met à jour "activeManagers" */ + /* 1. On met à jour "activeManagers" */ if( index != -1 ) arg->activeManagers[index] = 0; + /* 2. On ferme la socket */ + close(arg->socket); + + /* 3. On arrête le THREAD */ - if( DEBUGMOD&THR ) printf("{udp_vterm}{com}(%d) libéré\n", index); + if( DEBUGMOD&THR ) printf("{udp_vterm}{com}(%d) freed\n", index); pthread_exit(NULL); } @@ -372,60 +353,149 @@ void* manageCtrlTerm(void* THREADABLE_ARGS){ /* [1] Initialisation des variables =========================================================*/ - int read; // compteur + /* 1. Initialisation des variables */ struct sockaddr_in clientInfo; - socklen_t len; - char request[MAX_BUF_LEN]; // Requête - // char response[MAX_BUF_LEN]; // Réponse + socklen_t len; + char loop = 1; + int count, last, sent, nb; // compteurs d'envoi + int i, index = -1; // Compteurs globaux + int pindex; // index of the current plane + char buffer[MAX_BUF_LEN]; // Buffer d'envoi + struct term_req request; // Requête /* 2. On récupère les arguments */ struct handler_arg* arg = THREADABLE_ARGS; + /* 3. On récupère le rang dans les "managers" */ + for( i = 0 ; i < MAX_UDP_THR ; i++ ) + if( arg->managers[i] == pthread_self() ){ index = i; break; } + + printf("{udp_cterm}{com}(%d) starting terminal routine (rate: %d sec)\n", index, PUBL_TIMEOUT); + + /* 4. Attente d'un client */ + len = sizeof(struct sockaddr_in); + if( recvfrom(arg->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; + } + + if( loop ) printf("{udp_cterm}{com}(%d) Terminal connected\n", index); - do{ + while( loop ){ + + pindex = -1; - 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); + bzero(buffer, sizeof(char)*MAX_BUF_LEN); + count = recvfrom(arg->socket, buffer, 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 ) + if( count < TERMREQ_LEN ){ + if( DEBUGMOD&BUF ) printf("{udp_cterm}{com}(%d) Error receiving request\n", index); continue; + } /* 3. On désérialise la requête*/ - printf("{udp_x-term}{udp_com} TERMINAL Request(%d bytes) : '%s'\n", read, request); + 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 ); + // indian-switch + request.update.cap = ntohl(request.update.cap); + request.update.spd = ntohl(request.update.spd); + + printf("{udp_cterm}{com}(%d) { flags: %d; plane: #%s { z=%d; cap=%d; speed=%d} }\n", index, request.flags, request.update.code, request.update.z, request.update.cap, request.update.spd); + /* [3] Gestion de la requête =========================================================*/ + /* 1. On vérifie qu'il y a bien un update demandé */ + if( !( request.flags&TERMREQ_ALT || request.flags&TERMREQ_CAP || request.flags&TERMREQ_SPD ) ){ + printf("{udp_cterm}{com}(%d) No update requested, passing\n", index); + continue; + } + + /* 2. On regarde si on trouve l'avion */ + for( i = 0 ; i < arg->sgca->n ; i++ ){ + + // Si l'avion existe -> on passe à la suite + if( strcmp(arg->sgca->data[i].code, request.update.code) == 0 ){ + pindex = i; + break; + } + + } + + /* 3. Si on a pas trouvé l'avion ou qu'il est déconnecté, on passe */ + if( pindex <= -1 || arg->sgca->socket[pindex] <= -1 ){ + printf("{udp_cterm}{com}(%d) Plane unknown or unreachable, passing\n", index); + continue; + } + + /* 4. On transfère la requête à l'avion */ + bzero(buffer, sizeof(char)*MAX_BUF_LEN); + // indian-switch + request.update.z = htonl(request.update.z); + request.update.cap = htonl(request.update.cap); + request.update.spd = htonl(request.update.spd); + 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 ); + + if( send(arg->sgca->socket[pindex], buffer, count/sizeof(char)+1, 0) <= 0 ){ + printf("{udp_cterm}{com}(%d) Cannot send request to plane\n", index); + continue; + } - /* [4] Envoi reponse + /* [4] Gestion de la réponse de l'avion =========================================================*/ - strcpy(request+strlen(request), "-bla\0"); - send(arg->socket, request, strlen(request), 0); + /* 1. Réception */ + bzero(buffer, sizeof(char)*MAX_BUF_LEN); + if( recv(arg->sgca->socket[pindex], buffer, MAX_BUF_LEN, 0) <= 0 ){ + printf("{udp_cterm}{com}(%d) Cannot get response from plane\n", index); + continue; + } + + /* 2. Gestion de la validation de l'update */ + if( !(buffer[0]&TERMREQ_ALT) && request.flags&TERMREQ_ALT ) + request.flags -= TERMREQ_ALT; + + if( !(buffer[0]&TERMREQ_CAP) && request.flags&TERMREQ_CAP ) + request.flags -= TERMREQ_CAP; + + if( !(buffer[0]&TERMREQ_SPD) && request.flags&TERMREQ_SPD ) + request.flags -= TERMREQ_SPD; + + /* [5] Réponse au terminal + =========================================================*/ + if( send(arg->socket, buffer, sizeof(char)*2, 0) < 0 ) + printf("{udp_cterm}{com}(%d) Cannot answer to terminal\n", index); - }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" */ + /* 1. On met à jour "activeManagers" */ if( index != -1 ) arg->activeManagers[index] = 0; + /* 2. On ferme la socket */ + close(arg->socket); + /* 3. On arrête le THREAD */ - if( DEBUGMOD&THR ) printf("{udp_x-term}{udp_com}(%d) libéré\n", index); + if( DEBUGMOD&THR ) printf("{udp_cterm}{com}(%d) freed\n", index); pthread_exit(NULL); } diff --git a/central-manager/lib/local/middleware.c b/central-manager/lib/local/middleware.c index 5b8bb67..5bc94c5 100644 --- a/central-manager/lib/local/middleware.c +++ b/central-manager/lib/local/middleware.c @@ -55,7 +55,7 @@ int multicastTerminal(struct middleware_arg* arg){ memcpy(&request.port, buffer+sizeof(char)+sizeof(in_addr_t), sizeof(unsigned short)); request.addr = ntohl(request.addr); ip.s_addr = request.addr; - 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); + 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) ){ @@ -86,13 +86,15 @@ int multicastTerminal(struct middleware_arg* arg){ /* 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} Erreur de création de la socket COM\n", arg->entity); + 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) */ + setTimeout(*arg->comSock, SOCK_TIMEOUT, TIMEOUT_RECV|TIMEOUT_SEND); /* (2) Récupération port random @@ -101,7 +103,7 @@ int multicastTerminal(struct middleware_arg* arg){ 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); + 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); @@ -127,11 +129,11 @@ int multicastTerminal(struct middleware_arg* arg){ /* 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); + printf("{%s} Cannot answer to client\n", arg->entity); return -2; } - 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)); + 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; diff --git a/central-manager/lib/network/common.c b/central-manager/lib/network/common.c index 42592ef..cd4a158 100644 --- a/central-manager/lib/network/common.c +++ b/central-manager/lib/network/common.c @@ -12,19 +12,6 @@ - -/* 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(){ /* [0] Initialisation des variables =========================================================*/ @@ -65,4 +52,47 @@ struct in_addr* GET_LOCAL_IP(){ =========================================================*/ 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; } \ No newline at end of file diff --git a/central-manager/lib/network/common.h b/central-manager/lib/network/common.h index 256590f..3a3e7dc 100644 --- a/central-manager/lib/network/common.h +++ b/central-manager/lib/network/common.h @@ -15,7 +15,42 @@ #include + /* 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 Socket à modifier + * pSec Valeur en seconde du timeout + * pFlags 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); + + #endif \ No newline at end of file diff --git a/central-manager/lib/network/tcp/server.c b/central-manager/lib/network/tcp/server.c index bebe92d..d7389fd 100644 --- a/central-manager/lib/network/tcp/server.c +++ b/central-manager/lib/network/tcp/server.c @@ -22,7 +22,6 @@ int DROP_TCP_SERVER(const int pPort, int* pListenSock){ =========================================================*/ static struct sockaddr_in addr; // contiendra les infos du serveur int STATUS; // status - struct timeval timeout; *pListenSock = -1; @@ -37,15 +36,6 @@ int DROP_TCP_SERVER(const int pPort, int* pListenSock){ /* 2. Gestion erreur */ if( *pListenSock < 0 ) return -1; - /* 3. Timeout */ - timeout.tv_sec = SOCK_TIMEOUT; - timeout.tv_usec = 0; - - if( setsockopt(*pListenSock, SOL_SOCKET, SO_RCVTIMEO|SO_SNDTIMEO, (char*) &timeout, sizeof(struct timeval) ) < 0 ){ - close(*pListenSock); - return -1; - } - /* [2] On définit les infos de la socket =========================================================*/ diff --git a/central-manager/lib/network/udp/client.c b/central-manager/lib/network/udp/client.c index a8974b5..3e5eef4 100644 --- a/central-manager/lib/network/udp/client.c +++ b/central-manager/lib/network/udp/client.c @@ -7,7 +7,6 @@ int UDP_SOCKET(int* pSocket, in_addr_t pAddr, const int pPort, struct sockaddr_i /* [0] Initialisation des variables =========================================================*/ *pSocket = -1; - struct timeval timeout; /* [1] Création de la socket @@ -19,15 +18,6 @@ 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 =========================================================*/ diff --git a/central-manager/lib/network/udp/server.c b/central-manager/lib/network/udp/server.c index 22d56ac..a712b59 100644 --- a/central-manager/lib/network/udp/server.c +++ b/central-manager/lib/network/udp/server.c @@ -20,7 +20,6 @@ int DROP_UDP_SERVER(in_addr_t pAddr, const int pPort, int* pListenSock, struct s int STATUS; // status struct ip_mreq mcastReq; *pListenSock = -1; - struct timeval timeout; struct in_addr tmp; @@ -34,15 +33,6 @@ 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 =========================================================*/ diff --git a/plane/lib/network/tcp/client.c b/plane/lib/network/tcp/client.c index db9f1f0..6622e70 100644 --- a/plane/lib/network/tcp/client.c +++ b/plane/lib/network/tcp/client.c @@ -10,10 +10,11 @@ #include "client.h" -int TCP_CONNECT(int* pSocket, const in_addr_t pAddr, const int pPort, struct sockaddr_in* pInfo){ +int TCP_CONNECT(int* pSocket, const in_addr_t pAddr, const int pPort, const time_t pTimeout, struct sockaddr_in* pInfo){ /* [0] Initialisation des variables =========================================================*/ + struct timeval timeout; *pSocket = -1; @@ -26,6 +27,16 @@ int TCP_CONNECT(int* pSocket, const in_addr_t pAddr, const int pPort, struct soc 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 =========================================================*/ diff --git a/plane/lib/network/tcp/client.h b/plane/lib/network/tcp/client.h index bdd5cc9..a0e7928 100644 --- a/plane/lib/network/tcp/client.h +++ b/plane/lib/network/tcp/client.h @@ -19,7 +19,8 @@ * * ==IN== * @pAddr Adresse du serveur TCP - * @pPort Port du serveur TCP + * @pPort Port du serveur TCP + * @pTimeout Timeout de réception * * ==OUT== * @pSocket Pointeur sur le à remplir => contiendra un pointeur sur la socket créée @@ -34,6 +35,6 @@ * [3] On se connecte au serveur * */ - int TCP_CONNECT(int* pSocket, const in_addr_t pAddr, const int pPort, struct sockaddr_in* pInfo); + int TCP_CONNECT(int* pSocket, const in_addr_t pAddr, const int pPort, const time_t pTimeout, struct sockaddr_in* pInfo); #endif \ No newline at end of file diff --git a/plane/lib/network/udp/server.c b/plane/lib/network/udp/server.c index c7e9185..cbe2c9e 100644 --- a/plane/lib/network/udp/server.c +++ b/plane/lib/network/udp/server.c @@ -35,7 +35,13 @@ int DROP_MULTICAST_SERVER(const char* pAddr, const int pPort, int* pListenSock, timeout.tv_sec = SOCK_TIMEOUT; timeout.tv_usec = 0; - if( setsockopt(*pListenSock, SOL_SOCKET, SO_RCVTIMEO|SO_SNDTIMEO, (char*) &timeout, sizeof(struct timeval) ) < 0 ){ + if( setsockopt(*pListenSock, SOL_SOCKET, SO_RCVTIMEO, (char*) &timeout, sizeof(struct timeval) ) < 0 ){ + close(*pListenSock); + return -1; + + } + + if( setsockopt(*pListenSock, SOL_SOCKET, SO_SNDTIMEO, (char*) &timeout, sizeof(struct timeval) ) < 0 ){ close(*pListenSock); return -1; } diff --git a/plane/plane.c b/plane/plane.c index 49cf9d3..ede0edc 100644 --- a/plane/plane.c +++ b/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; @@ -70,7 +70,6 @@ int open_communication(){ memcpy(&request.port, buffer+sizeof(char)+sizeof(in_addr_t), sizeof(unsigned short) ); // on indian-switch - printf("received : %x\n", request.addr); request.addr = ntohl(request.addr); request.port = ntohs(request.port); ip.s_addr = request.addr; @@ -83,7 +82,7 @@ int open_communication(){ // printf("* hex("); for( int i = 0 ; i < BINDHDR_LEN/sizeof(char) ; i++ ) printf("\\x%02X", buffer[i]); printf(")\n"); - printf("* received bind_header{flags = %d; addr = %x/%s; port = %d;}\n\n", request.flags, request.addr, inet_ntoa(ip), request.port); + printf("* received bind_header{flags = %d; addr = %x/'%s'; port = %d;}\n\n", request.flags, request.addr, inet_ntoa(ip), request.port); @@ -96,7 +95,7 @@ int open_communication(){ /* (1) Création socket TCP + connection ---------------------------------------------------------*/ /* 1. Création socket TCP + connection serveur */ - if( TCP_CONNECT(&commu_socket, request.addr, request.port, &sgca) < 0 ) + if( TCP_CONNECT(&commu_socket, request.addr, request.port, PAUSE, &sgca) < 0 ) return 0; return 1; @@ -105,11 +104,19 @@ int open_communication(){ + + + + void close_communication(){ // fonction à implémenter qui permet de fermer la communication // avec le gestionnaire de vols } + + + + void send_data(){ /* [0] Initialisation des variables @@ -145,21 +152,11 @@ void send_data(){ read = send(commu_socket, buffer, PLANE_DATA_LEN/sizeof(char) + 1, 0); if( read <= 0 ){ - printf("Erreur d'envoi\n"); + printf("Cannot send\n"); return; } // printf("* hex("); for( int i = 0 ; i < PLANE_DATA_LEN/sizeof(char) ; i++ ) printf("\\x%02X", buffer[i]); printf(")\n"); - /* 4. Récupération réponse */ - read = recv(commu_socket, buffer, MAX_BUF_LEN, 0); - - if( read < 0 ){ - printf("Erreur de réception\n"); - return; - } - - /* 5. Gestion mise à jour */ - //TODO: update_cap etc avec flags } @@ -168,6 +165,10 @@ void send_data(){ ********************************/ // initialise aléatoirement les paramètres initiaux de l'plane + + + + void init_plane(){ // initialisation aléatoire du compteur aléatoire time_t seed; @@ -193,28 +194,61 @@ void init_plane(){ } // modifie la valeur de l'plane avec la valeur passée en paramètre -void update_speed(int speed){ - if (speed < 0) ctrl.speed = speed; + + + + +int update_speed(int speed){ + if( speed < 0 ) + return -1; + + if( speed > VITMAX ) + return -1; + + ctrl.speed = speed; + return 0; } // modifie le cap de l'plane avec la valeur passée en paramètre -void update_cap(int cap){ - if ((cap >= 0) && (cap < 360)) - ctrl.cap = cap; + + + + +int update_cap(int cap){ + if( cap < 0 || cap >= 360 ) + return -1; + + ctrl.cap = cap; + return 0; } // modifie l'z de l'plane avec la valeur passée en paramètre -void update_z(int alt){ - if (alt < 0) - crd.z = alt; + + + + +int update_z(int alt){ + if( alt < 0 ) + return 01; + + crd.z = alt; + return 0; } // affiche les caractéristiques courantes de l'plane + + + + void display_data(){ - printf("Avion %6s -> localisation : (%d,%d), altitude : %d, vitesse : %d, cap : %d\n", numero_vol, crd.x, crd.y, crd.z, ctrl.speed, ctrl.cap); + printf("| Plane %s |\n * position(%d,%d, %d)\n * speed: %d\n * cap: %d\n\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; @@ -246,13 +280,66 @@ 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}; while( 1 ){ calc_ctrl(); send_data(); - sleep(PAUSE); + + /* [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 <= 0 || received < (sizeof(char)+3*sizeof(int)) ) + continue; + + + /* [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_z(request.spd) == -1 ) + request.flags -= REQ_SPD; + + if( request.flags&REQ_CAP ) + if( update_z(request.cap) == -1 ) + request.flags -= REQ_CAP; + + + /* [3] Gestion de la réponse + =========================================================*/ + /* 1. On prépare la réponse */ + bzero(buffer, sizeof(char)*MAX_BUF_LEN); + memcpy(buffer, &request.flags, sizeof(char)); + + /* 2. Envoi de la réponse */ + send(commu_socket, buffer, sizeof(char)*2, 0); } @@ -266,6 +353,7 @@ int main(){ // on quitte si on arrive à pas contacter le gestionnaire de vols if( !open_communication() ){ + printf("Cannot connect to SGCA.\n"); exit(1); } diff --git a/plane/plane.h b/plane/plane.h index 8e35ca9..7a6228d 100644 --- a/plane/plane.h +++ b/plane/plane.h @@ -49,6 +49,17 @@ int spd; }; + #define REQ_CAP 0x02 + #define REQ_SPD 0x04 + #define REQ_ALT 0x08 + + 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)