Blame view

Librairies/Exemple/Network/libnet.c 8.85 KB
0ae69087   pfrison   Ajout des fichiers
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
  #include <sys/types.h>
  #include <sys/socket.h>
  #include <netdb.h>
  #include <errno.h>
  #include <stdlib.h>
  #include <netinet/udp.h>
  #include <netinet/in.h>
  #include <netinet/ip.h>
  #include <string.h>
  #include <stdio.h>
  #include <arpa/inet.h>
  #include <unistd.h>
  #include <stdint.h>
  
  #define MAX_TCP_CONNEXION 10
  #define BUFFER_SIZE 1024
  
  //Fonction permettant d'envoyer en broadcast un message 
  void sendUDPBroadcast(unsigned char *message, int taille_message, int port) {
      int broadcast_enable = 1;
      //Option broadcast ON
      int s = socket(AF_INET, SOCK_DGRAM, 0);
      //Création de la socket : s = file descriptor de la socket, AF_INET (socket internet), SOCK_DGRAM (datagramme, UDP, sans connexion)
      if(s < 0){
          //Test de la valeur de retour de la socket
          perror("sendUDPBroadcast.socket");
          exit(-1); 
      }
      if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &broadcast_enable, sizeof(broadcast_enable)) < 0) {
          //Mise option broadcast à la socket
          perror("sendUDPBroadcast.setsockopt");
          exit(-1);
      }
      
      struct sockaddr_in broadcast_address;
      memset(&broadcast_address, 0, sizeof(broadcast_address));
      broadcast_address.sin_family = AF_INET;
      broadcast_address.sin_port = htons(port);
      broadcast_address.sin_addr.s_addr = INADDR_BROADCAST; //255.255.255.255
      
      //Envoie du message grâce à la socket
      if(sendto(s, message, taille_message, 0, (struct sockaddr *) &broadcast_address,
              sizeof(broadcast_address)) < 0 ) {
          perror("sendUDPBroadcast.sendto");
          exit(-1);
      }
  }
  
  
  void sendUDPUnicast(char *address, unsigned char *message, int taille_message, int port) {
      int s = socket(AF_INET, SOCK_DGRAM, 0);
      //Création de la socket : s = file descriptor de la socket, AF_INET (socket internet), SOCK_DGRAM (datagramme, UDP, sans connexion)
      if(s < 0){
          //Test de la valeur de retour de la socket
          perror("sendUDPUnicast.socket");
          exit(-1); 
      }
      struct sockaddr_in unicast_address;
      //Creation structure adresse de destination
      memset(&unicast_address, 0, sizeof(unicast_address));
      //Mise à zéro de la structure d'adresse
      unicast_address.sin_family = AF_INET;
      unicast_address.sin_port = htons(port);
      //Mise du port en ordre du réseau (big endian)
      unicast_address.sin_addr.s_addr = inet_addr(address);
      if(sendto(s, message, taille_message, 0, (struct sockaddr *) &unicast_address, sizeof(unicast_address)) < 0 ) {
          perror("sendUDPUnicast.sendto");
          exit(-1);
      }
  }
  
  // Retourne l'adresse ip d'une connexion active
  static int socketVersNomUDP(struct sockaddr *padresse, char *nom){
      void *ip;
      int taille_nom;
      if(padresse->sa_family == AF_INET){
          struct sockaddr_in *ipv4 = (struct sockaddr_in *) padresse;
          ip = (void *) &ipv4->sin_addr;
          taille_nom = INET_ADDRSTRLEN;
      }
      if(padresse->sa_family == AF_INET6){
          struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *) padresse;
          ip = (void *)&ipv6->sin6_addr;
          taille_nom = INET6_ADDRSTRLEN;
      }
      char nom_deco[20];
      inet_ntop(padresse->sa_family, ip, nom_deco, taille_nom);
      sprintf(nom, "%s", nom_deco + 7);
      return 0;
  }
  static int socketVersNomTCP(int s, char *nom){
      struct sockaddr_storage adresse;
      struct sockaddr *padresse = (struct sockaddr *) &adresse;
      socklen_t taille = sizeof adresse;
      int statut;
  
      /* Recupere l'adresse de la socket distante */
      statut = getpeername(s, padresse, &taille);
      if(statut<0){
          perror("socketVersNom.getpeername");
          return -1;
      }
  
      /* Recupere le nom de la machine */
      return socketVersNomUDP(padresse, nom);
  }
  
  // Fonction permettant de créer le serveur TCP
  int initialisationServeurTCP(char *service){
      struct addrinfo precisions, *resultat, *origine;
      int statut;
      int s;
  
      /* Construction de la structure adresse */
      memset(&precisions, 0, sizeof precisions);
      precisions.ai_family = AF_UNSPEC;
      precisions.ai_socktype = SOCK_STREAM;
      precisions.ai_flags = AI_PASSIVE;
      statut = getaddrinfo(NULL, service, &precisions, &origine);
      if(statut < 0){ 
          perror("initialisationSocketUDP.getaddrinfo");
          exit(EXIT_FAILURE); 
      }
      struct addrinfo *p;
      for(p = origine, resultat = origine; p != NULL; p = p->ai_next) {
          if(p->ai_family == AF_INET6){ 
              resultat = p; 
              break;
          }
      }
  
      /* Creation d'une socket */
      s = socket(resultat->ai_family, resultat->ai_socktype, resultat->ai_protocol);
      if(s < 0){
          perror("initialisationSocketUDP.socket");
          exit(EXIT_FAILURE);
      }
  
      /* Options utiles */
      int vrai = 1;
      if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &vrai, sizeof(vrai))<0) {
          perror("initialisationServeurUDPgenerique.setsockopt (REUSEADDR)");
          exit(-1);
      }
  
      /* Specification de l'adresse de la socket */
      statut = bind(s, resultat->ai_addr, resultat->ai_addrlen);
      if(statut<0) {
          perror("initialisationServeurUDP.bind");
          exit(-1);
      }
  
      /* Liberation de la structure d'informations */
      freeaddrinfo(origine);
  
      /* Taille de la queue d'attente */
      statut = listen(s, MAX_TCP_CONNEXION);
      if(statut < 0)
          return -1;
      return s;
  }
  
  // Accepte toutes les connexions au serveur TCP et execute la fonction en argument
  int boucleServeurTCP(int socket, void (*traitement)(int, char *)){
      while(1){
  	    // accept connection
          struct sockaddr ip_src;
          socklen_t ip_len = sizeof(struct sockaddr);
          int socket_dialogue = accept(socket, &ip_src, &ip_len);
          if(socket_dialogue < 0){
              perror("boucleServeur.accept");
              return -1;
          }
  
  	    // get ip addr
          char char_ip[20];
          int status = socketVersNomTCP(socket_dialogue, char_ip);
          if(status < 0)
              perror("socketVersNom");
  
  	    // callback function
          traitement(socket_dialogue, char_ip);
      }
      return 0;
  }
  
  // Creation d'un serveur UDP
  int initialisationServeurUDP(char *service){
      struct addrinfo precisions, *resultat, *origine;
      int statut;
      int s;
  
      /* Construction de la structure adresse */
      memset(&precisions, 0, sizeof precisions);
      precisions.ai_family = AF_UNSPEC;
      precisions.ai_socktype = SOCK_DGRAM;
      precisions.ai_flags = AI_PASSIVE;
      statut = getaddrinfo(NULL, service, &precisions, &origine);
      if(statut < 0){ perror("initialisationSocketUDP.getaddrinfo"); exit(EXIT_FAILURE); }
  
      struct addrinfo *p;
      for(p=origine, resultat=origine; p!=NULL; p=p->ai_next)
      if(p->ai_family == AF_INET6){ resultat=p; break; }
  
      /* Creation d'une socket */
      s = socket(resultat->ai_family, resultat->ai_socktype, resultat->ai_protocol);
      if(s<0){ perror("initialisationSocketUDP.socket"); exit(EXIT_FAILURE); }
  
      /* Options utiles */
      int vrai = 1;
      if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &vrai, sizeof(vrai)) < 0){
          perror("initialisationServeurUDPgenerique.setsockopt (REUSEADDR)");
          exit(-1);
      }
  
      /* Specification de l'adresse de la socket */
      statut = bind(s, resultat->ai_addr, resultat->ai_addrlen);
      if(statut < 0) { perror("initialisationServeurUDP.bind"); exit(-1); }
  
      /* Liberation de la structure d'informations */
      freeaddrinfo(origine);
  
      return s;
  }
  
  // Reception des messages UDP et execute la fonction passee en argument
  int boucleServeurUDP(int s, void (*traitement)(unsigned char *, int, char *)){
      while(1){
          struct sockaddr_storage adresse;
          struct sockaddr *padresse = (struct sockaddr *) &adresse;
          socklen_t taille = sizeof(adresse);
          unsigned char message[BUFFER_SIZE];
  
          int nboctets = recvfrom(s, message, BUFFER_SIZE, 0, (struct sockaddr *) padresse, &taille);
          if(nboctets < 0) return -1;
  
          /* Recupere le nom de la machine */
          char char_ip[20];
          int status = socketVersNomUDP(padresse, char_ip);
          if(status < 0)
              perror("socketVersNom");
  
          traitement(message, nboctets, char_ip);
      }
      return 0;
  }
  
  // Initialise un client TCP
  int openTCPClient(char *hote, int port) {
      int s;
      struct sockaddr_in adresse;
      socklen_t taille = sizeof adresse;
      
      // creation socket
      s = socket(PF_INET, SOCK_STREAM, 0);
      if(s<0){ perror("connexionServeur.socket"); exit(-1); }
      
      // connexion
      memset(&adresse, 0, sizeof(adresse));
      adresse.sin_family=AF_INET;
      adresse.sin_port = htons(port);
      adresse.sin_addr.s_addr = inet_addr(hote);
      if(connect(s,(struct sockaddr *)&adresse, taille)<0) return -1;
      return s;
  }
  
  // Envoie un message TCP sur une connexion active
  void sendTCP(int socket, char *message, int length_message){
      if(length_message <= 0)
          return;
      write(socket, message, length_message);
  }
  
  // Recois un message TCP sur une connexion active
  int receiveTCP(int socket, char *message, int max_length){
      return read(socket, message, max_length);
  }