#include <pthread.h> //include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> //include <string.h> #include <unistd.h> //include <errno.h> #include <ctype.h> #define SOCKET_ERR 1 #define BIND_ERR 2 #define LISTEN_ERR 3 #define ACCEPT_ERR 4 #define TH_CREATE_ERR 5 #define RECV_ERR 6 #define SEND_ERR 7 #define CLOSE_SOCK_ERR 8 #define GETHOSTN_ERR 9 #define CONNECT_ERR 10 #define SOCKET_REUSEADDR_ERR 11 #define BUF_SIZE 1500 #define PORT 4404 /*============================================================================*/ // Client HTTP donc le serveur répond par un en-tête HTTP suivi du code HTML // sinon le client ne comprendra pas ce qui se passe void envoi(int sk, const char* s, int len){ char paquet[100]; len = sprintf(paquet, "HTTP/1.1 200 OK\n" "Content-Length:%d\n" "Access-Control-Allow-Origin:*\n" "Content-type:text/html\r\n" "\r\n" "%s", len, s); if(send(sk, paquet, len, 0) == -1) print_error(SEND_ERR, errno); } /*============================================================================*/ // et si on n'envoyait que le canal rouge? void envoiUneImage(int sk){ printf("\tenvoi image\n"); char headerHTTP[100]; u8 lenH; u32 sent = 0; //len = CommonV4l2_get_image_size(&common_v4l2); lenH = sprintf(headerHTTP, "HTTP/1.1 200 OK\n" "Content-Length:%d\n" //"Content-Type:image/x-portable-graymap\n" "Content-Type:image/x-portable-pixmap", "Access-Control-Allow-Origin:*\n" // sinon ajax de plaint de ce truc "\r\n", lastframe.len); sent = send(sk, headerHTTP, lenH, 0); if(sent == -1) print_error(SEND_ERR, errno); //printf(" header %d/%d octets envoyés, ", lenH, sent); //sent = send(sk, CommonV4l2_get_image(&common_v4l2), CommonV4l2_get_image_size(&common_v4l2), 0); sent = send(sk, lastframe.pixels, lastframe.len, 0); //printf(" data %d/%d octets envoyés\n", lastframe.len, sent); if(sent == -1) print_error(SEND_ERR, errno); } /*============================================================================*/ // crée un socket listen puis accepte un client, lit et écrit SC1 commencer le scan SC0 stop le scan 200 tourner à gauche (moteur 1) 210 tourner à droite 220 tourner en haut (moteur 2) 230 tourner en bas 300 Filmer 909 Fermer le serveur void* threadReseau() { char buf[BUF_SIZE]; int len, i, sk, sks; struct sockaddr_in th_sock_addr; int th_addr_size; printf("Thread réseau\n"); //sks = lancerServeur(); // socket serveur struct sockaddr_in sAddr; if((sks = socket(AF_INET, SOCK_STREAM, 0)) == -1) print_error(SOCKET_ERR, errno); // en console CTRL-C pour stopper le serveur sinon bind() dit adress already in use // pour ne pas être forcé de faire CTRL-C, lui précise reuseaddr if (setsockopt(sks, SOL_SOCKET, SO_REUSEADDR, &(int){1}, sizeof(int)) < 0) print_error(SOCKET_REUSEADDR_ERR, errno); bzero(&sAddr, sizeof(sAddr)); sAddr.sin_family = AF_INET; sAddr.sin_port = htons(PORT); sAddr.sin_addr.s_addr = INADDR_ANY; // allow connections from any address //printf("\tbind() associate socket to specified port in sAddr\n"); if(bind(sks, (struct sockaddr*)&sAddr, sizeof(sAddr)) == -1) print_error(BIND_ERR, errno); //printf("\tlisten() listen makes a queue of 1 client request\n"); if((listen(sks, 1)) == -1) print_error(LISTEN_ERR, errno); // socket client sk = socket(AF_INET, SOCK_STREAM, 0); if(sk == -1) print_error(SOCKET_ERR, errno); // Attend qu'un client se connecte, à partir de là // il reçoit les codes du client, exécute et lui envoie une confirmation // si la connection est perdue il se remet en attente de client while(1) { printf("Waiting for client ...\n"); sk = accept(sks, (struct sockaddr*)&th_sock_addr, (int*)&th_addr_size); if(sk == -1) print_error(ACCEPT_ERR, errno); printf("\tNew client accepted\n"); while(1){ len = recv(sk, buf, BUF_SIZE, 0); if(len == -1) print_error(RECV_ERR, errno); if(len == 0) break; // connection perdue passe à l'acceptation suivante //buf[len]=0; /*printf("Message from client [%s]\n", buf); Le client web envoie une requête HTTP GET /220 HTTP/1.1 Host: 127.0.0.1:4404 Connection: keep-alive User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36 Accept: * / * Origin: null Sec-Fetch-Site: cross-site Sec-Fetch-Mode: cors Sec-Fetch-Dest: empty Accept-Encoding: gzip, deflate, br Accept-Language: fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7 suivi de 2 lignes vides inutile de parser la requête HTTP: le code commence au 5e octet donc regarde rapidement les 5e, 6e et 7e octets */ if(buf[5]=='S' && buf[6]=='C'){ if(buf[7]=='1') { printf("\tSC1 je passe en mode SCAN\n"); mode = SCAN; // quand le thread tourelle verra ça il commencera à bouger //printf("init webcam\n"); CommonV4l2_init(&common_v4l2, "/dev/video0", x_res, y_res); envoi(sk, "SC1",3); // confirmation au client que l'ordre va être exécuté } else if(buf[7]=='0') { printf("\tSC0 je stoppe le mode SCAN\n"); mode = IDLE; CommonV4l2_deinit(&common_v4l2); //éteint la webcam pour économiser la batterie envoi(sk, "SC0",3); // confirmation au client que l'ordre va être exécuté } // Ordre de déplacement SC2 if (buf[7]=='2') {AllerAGauche(10); envoi(sk, "okG",3);} else if(buf[7]=='3') {AllerADroite(10); envoi(sk, "okD",3);} else if(buf[7]=='4') {AllerEnHaut(10); envoi(sk, "okH",3);} else if(buf[7]=='5') {AllerEnBas(10); envoi(sk, "okB",3);} } else if(buf[5]=='I'){ if (buf[6]=='M' && buf[7]=='G'){ //printf("\tIMG Le client web veut une preview de la webcam\n"); // envoie la réponse HTTP header + buffer array sans header PPM /*if(mode == IDLE){ CommonV4l2_init(&common_v4l2, "/dev/video0", x_res, y_res); grabFrameFromCamera(); envoiUneImage(sk); CommonV4l2_deinit(&common_v4l2); } else*/ envoiUneImage(sk); } // Filmer avec le Nikon else if(buf[6]=='N' && buf[7]=='K'){ printf("\tIMG actionne le servomoteur qui appuie sur la télécommande bluetooth du Nikon\n"); envoi(sk, "Nik",3); ServoAppuyerSurBoutonBluetooth(); } } // le client envoie un code 909 il veut tomber l'exe serveur else if(buf[5]=='9' && buf[6]=='0' && buf[7]=='0'){ envoi(sk, "bye",3); fermer = 1; // quand le thread tourelle verra ça il sortira break; // je sors de cette communication ... } } if(fermer==1) { // ... et s'il faut terminer l'appli on ferme printf("\tOn ferme\n"); break; } printf("\tje passe à l'acceptation suivante\n"); } printf("\tClose sk\n"); if(close(sk) == -1) print_error(CLOSE_SOCK_ERR, errno); printf("\tClose sks\n"); if(close(sks) == -1) print_error(CLOSE_SOCK_ERR, errno); }
reseau.h 191 lignes, 6935 octets