00001 /**********************************************************************************************/ 00002 /*************************** UDP GROUP CHANNEL CLASS *************************/ 00003 /**************************** Jean FANCHON. LAAS-CNRS *************************/ 00004 /**********************************************************************************************/ 00005 00006 #include "total_order_channel.h" 00007 00008 00009 void * start_thread(void * objet) { 00010 //thread de reception 00011 ((no_prop_channel*)objet) -> read_socket(); 00012 } 00013 00014 /********************************************************************/ 00015 /******************* group administrator ****************** */ 00016 00017 group_admin:: group_admin() { 00018 00019 groupsize = 0; 00020 00021 for (int i = 0; i< MAX_MEMBER ; i++) 00022 00023 members_list[i].ident = UNDEF ; 00024 } 00025 /********************************************************************/ 00026 /******************** initialisation ********************/ 00027 00028 int group_admin::init_members_list(char * file) { 00029 00030 //initialise le tableau members_address en lisant les valeurs ds le fichier 00031 //passe en parametre 00032 //si le fichier ne peut etre ouvert, retourne -1, 0 sinon 00033 00034 FILE * f; 00035 int ident,port; 00036 char ip[15]; 00037 u_long add; 00038 int ret, nb = 0; 00039 00040 if( (f=fopen(file, "r"))==NULL ) 00041 return(-1); 00042 00043 ret = fscanf(f,"%d %s %d",&ident,&ip,&port); 00044 00045 while( ret != EOF) { 00046 00047 members_list[ident].ident = ident; 00048 add =inet_addr(ip); 00049 members_list[ident].nodeid = (int) add ; 00050 members_list[ident].port = port; 00051 nb ++; 00052 ret = fscanf(f,"%d %s %d",&ident,&ip,&port); 00053 00054 } 00055 fclose (f); 00056 groupsize = nb; 00057 00058 cout << " group_admin sz = " << groupsize << endl ; 00059 00060 return(0); 00061 00062 } 00063 00064 00065 /********************************************************************/ 00066 /******************* group modif ****************** */ 00067 00068 int group_admin::add_member( int ident, int host, int port) { 00069 00070 for( int i =0; i < MAX_MEMBER ; i++ ) { 00071 00072 if (members_list[i].ident == -1 ) { 00073 00074 members_list[i].ident = ident; 00075 00076 members_list[i].nodeid = host; 00077 00078 members_list[i].port = port; 00079 00080 groupsize ++; 00081 00082 return(0); 00083 } 00084 } 00085 return(-1); 00086 } 00087 00088 /********************************************************************/ 00089 /******************** group modif ********************/ 00090 00091 int group_admin::del_member( int ident) { 00092 00093 for( int i =0; i < MAX_MEMBER ; i++ ) { 00094 00095 if (members_list[i].ident == ident ) { 00096 00097 members_list[i].ident = -1; 00098 00099 groupsize --; 00100 00101 return(0); 00102 } 00103 } 00104 return(-1); 00105 } 00106 00107 00108 00109 /********************************************************************/ 00110 /******************** looks for host number of a member in list******************/ 00111 00112 int group_admin::host_number(int ident) { 00113 00114 int li=0, 00115 reponse; 00116 00117 while( (ident != members_list[li].ident) && (li< MAX_MEMBER) ) 00118 li++; 00119 00120 if (li == MAX_MEMBER) { 00121 return(0); 00122 } else { 00123 reponse=members_list[li].nodeid; 00124 return(reponse); 00125 } 00126 } 00127 /********************************************************************/ 00128 /******************** looks for port number of a member in list ********************/ 00129 00130 int group_admin::port_number(int ident) { 00131 00132 00133 int li=0, 00134 reponse; 00135 00136 while( (ident != members_list[li].ident) && (li<MAX_MEMBER) ) 00137 li++; 00138 00139 if (li == MAX_MEMBER ) { 00140 return(0); 00141 } else { 00142 reponse=members_list[li].port; 00143 return(reponse); 00144 } 00145 } 00146 00147 00148 /********************************************************************/ 00149 /********************************************************************/ 00150 /***************** group no property channel based on udp **************** */ 00151 00152 no_prop_channel::no_prop_channel(total_order_channel * pt, const char *ipadd, group_admin *gpt) { 00153 00154 cout << "start no prop channel 1 (from net)" << endl; 00155 00156 /********************************************************************/ 00157 /***************** initialisation *****************/ 00158 00159 my_user = pt; 00160 00161 my_group = gpt; 00162 00163 my_nodeid = (int) inet_addr(ipadd); 00164 00165 my_port = -1; 00166 00167 char *ptname; 00168 00169 ptname = getenv("HOST"); 00170 00171 strcpy( hostname, ptname); 00172 00173 /********************************************************************/ 00174 /************* initialise input socket and start reading thread ***********/ 00175 00176 int ret = pthread_create(&read_thread, 0,start_thread, (void *)this); 00177 00178 if (ret) { 00179 perror(" no-prop() "); printf(" erreur th create %d\n",ret); 00180 if (ret == ENOMEM) printf(" ENOMEM \n" ); 00181 if (ret== EINVAL) printf(" EINVAL \n" ); 00182 if (ret == EPERM) printf(" EPERM \n" ); 00183 exit(0); 00184 } 00185 } 00186 00187 00188 no_prop_channel::no_prop_channel(total_order_channel * pt, int id , char * file, group_admin *gpt) { 00189 00190 cout << "start no prop channel 0 ( from file)" << endl; 00191 00192 /********************************************************************/ 00193 /* initialisation*/ 00194 00195 my_user = pt; 00196 00197 my_group = gpt; 00198 00199 my_ident = id; 00200 00201 my_port = my_group->port_number(my_ident); 00202 00203 /************* initialise input socket and start reading thread ***********/ 00204 00205 int ret = pthread_create(&read_thread, 0,start_thread, (void *)this); 00206 00207 if (ret) { 00208 perror(" no-prop() "); printf(" erreur th create %d\n",ret); 00209 if (ret == ENOMEM) printf(" ENOMEM \n" ); 00210 if (ret== EINVAL) printf(" EINVAL \n" ); 00211 if (ret == EPERM) printf(" EPERM \n" ); 00212 exit(0); 00213 } 00214 } 00215 00216 /********************************************************************/ 00217 00218 no_prop_channel::~no_prop_channel() { 00219 00220 cout << " close socket " << endl; 00221 00222 close(sServ); 00223 } 00224 00225 /********************************************************************/ 00226 /***************** udp reading routine *****************/ 00227 00228 int no_prop_channel::read_socket() { 00229 00230 int ret , size, type, fromlen; 00231 struct sockaddr_in serveur, client; 00232 00233 00234 char message[64000]; 00235 00236 char * pt; 00237 pt = message; 00238 00239 if (my_port == -1) my_port = BASEPORT; 00240 00241 cout << "start read socket " << endl; 00242 00243 if ( (sServ=socket(AF_INET,SOCK_DGRAM,0) )<0) { 00244 //creation d'une socket UDP 00245 00246 cout << " erreur socket() start read socket " << endl; 00247 return(-1); 00248 } 00249 00250 serveur.sin_family = AF_INET; 00251 serveur.sin_port = htons(my_port); 00252 serveur.sin_addr.s_addr = htonl(INADDR_ANY); 00253 00254 //on rend la socket visible 00255 int iter = 1; 00256 00257 do { 00258 if ( bind(sServ, (struct sockaddr *)&serveur,sizeof(serveur)) == -1 ) { 00259 /*if ( errno == EADDRINUSE ) { */ 00260 00261 my_port ++; 00262 serveur.sin_port = htons(my_port); 00263 iter ++; 00264 continue; 00265 /* } 00266 00267 cout << " erreur bind() start read socket " << endl; 00268 exit(0); */ 00269 } 00270 else break; 00271 00272 } while ( iter < 10 ) ; 00273 if (iter == 10 ) { 00274 00275 cout << " erreur start read socket, " << endl; 00276 exit (2); 00277 } 00278 00279 fromlen = sizeof client; 00280 00281 for(;;) { 00282 ret =recvfrom(sServ, pt, 64000, 0, 00283 (struct sockaddr *) &client, &fromlen ); 00284 00285 if( ret == -1 ) { 00286 00287 cout << " erreur recvfrom() start read socket " << endl; 00288 return(-3); 00289 } 00290 00291 my_user->deliver(pt, ret); 00292 } 00293 00294 return(0); 00295 } 00296 00297 00298 /********************************************************************/ 00299 /************** broadcast : sendto each member's udp address **************/ 00300 00301 int no_prop_channel::broadcast(char* ch, int sz) { 00302 00303 //envoi de message a tous les membres du groupe 00304 //retourne -1 si l'hote est introuvable ou inconnu 00305 //retourne -2 si la socket ne peut etre ouverte 00306 //retourne -3 si une erreur se produit lors de l'envoi 00307 00308 int dest, test; 00309 int sock, host, port , ident ; 00310 struct sockaddr_in nom; 00311 struct hostent *hp; 00312 00313 if ( (sock=socket(AF_INET,SOCK_DGRAM,0) ) < 0 ) { 00314 //creation d'une socket UDP 00315 return(-2); 00316 } 00317 00318 for ( int i=0 ; i<MAX_MEMBER ; i++ ) { 00319 00320 dest = my_group->members_list[i].ident ; 00321 if (dest != UNDEF && my_ident != dest) { 00322 00323 //host= my_group->host_number(dest); 00324 //port= my_group->port_number(dest); 00325 00326 host= my_group->members_list[i].nodeid; 00327 port= my_group->members_list[i].port; 00328 00329 //cout << " broadcast -> " << ident << "port " << port << endl ; 00330 00331 if ( (hp=gethostbyaddr((char *)&host, sizeof (host), AF_INET))==NULL ){ 00332 close(sock); 00333 return(-1); 00334 } 00335 00336 memcpy((char *) &nom.sin_addr, (char *) hp->h_addr, hp->h_length); 00337 nom.sin_family = AF_INET; 00338 nom.sin_port = htons(port); 00339 00340 //on essaye d'envoyer les donnees au destinataire 00341 00342 if( (test = sendto(sock, ch, sz, 0, (struct sockaddr *) &nom, sizeof nom) != sz ) ) { 00343 close(sock); 00344 cout << " erreur sendto , sz = " << sz << " res = " << test << endl ; 00345 return(-3); 00346 } 00347 } 00348 } 00349 00350 close(sock); 00351 return 0; 00352 } 00353 /********************************************************************/ 00354 /******************** multicast : sendto a subset of members ********************/ 00355 00356 int no_prop_channel::multicast(int nbdest, int *dest_list, char* ch, int sz) { 00357 00358 //envoi de message aux membres de la liste 00359 //retourne -1 si l'hote est introuvable ou inconnu 00360 //retourne -2 si la socket ne peut etre ouverte 00361 //retourne -3 si une erreur se produit lors de l'envoi 00362 00363 int test; 00364 int sock, host, port; 00365 struct sockaddr_in nom; 00366 struct hostent *hp; 00367 00368 int dest; 00369 00370 if ( (sock=socket(AF_INET,SOCK_DGRAM,0) ) < 0 ) { 00371 //creation d'une socket UDP 00372 return(-2); 00373 } 00374 for ( int i=0 ; i< nbdest ; i++ ) { 00375 00376 dest = dest_list[i]; 00377 00378 host= my_group->host_number(dest); 00379 port= my_group->port_number(dest); 00380 00381 //cout << " multicast -> " << dest << endl ; 00382 00383 if ( (hp=gethostbyaddr((char *)&host, sizeof (host), AF_INET))==NULL ){ 00384 close(sock); 00385 return(-1); 00386 } 00387 00388 memcpy((char *) &nom.sin_addr, (char *) hp->h_addr, hp->h_length); 00389 nom.sin_family = AF_INET; 00390 nom.sin_port = htons(port); 00391 00392 //on essaye d'envoyer les donnees au destinataire 00393 00394 if( (test = sendto(sock, ch, sz, 0, (struct sockaddr *) &nom, sizeof nom) != sz ) ) { 00395 close(sock); 00396 cout << " erreur sendto , sz = " << sz << " res = " << test << endl ; 00397 return(-3); 00398 } 00399 } 00400 close(sock); 00401 return(0); 00402 } 00403 00404 00405 /********************************************************************/ 00406 /******************** unicast : sendto one member ********************/ 00407 00408 int no_prop_channel::unicast(int dest, char* ch, int sz) { 00409 00410 //envoi de message a un des membres du groupe 00411 //retourne -1 si l'hote est introuvable ou inconnu 00412 //retourne -2 si la socket ne peut etre ouverte 00413 //retourne -3 si une erreur se produit lors de l'envoi 00414 00415 00416 int test; 00417 int sock, host, port; 00418 struct sockaddr_in nom; 00419 struct hostent *hp; 00420 00421 if ( (sock=socket(AF_INET,SOCK_DGRAM,0) ) < 0 ) { 00422 //creation d'une socket UDP 00423 return(-2); 00424 } 00425 00426 00427 host= my_group->host_number(dest); 00428 port= my_group->port_number(dest); 00429 00430 if ( (hp=gethostbyaddr((char *)&host, sizeof (host), AF_INET))==NULL ) { 00431 close(sock); 00432 return(-1); 00433 } 00434 memcpy((char *) &nom.sin_addr, (char *) hp->h_addr, hp->h_length); 00435 nom.sin_family = AF_INET; 00436 nom.sin_port = htons(port); 00437 00438 //on essaye d'envoyer les donnees au destinataire 00439 00440 if( (test = sendto(sock, ch, sz, 0, (struct sockaddr *) &nom, sizeof nom) != sz ) ) { 00441 cout << " erreur sendto , sz = " << sz << " res = " << test << endl ; 00442 return(-3); 00443 } 00444 00445 close(sock); 00446 return 0; 00447 } 00448 00449 /********************************************************************/ 00450 /******************** initialisations ********************/ 00451 /********************envoi de demande d'inscription *****************************/ 00452 00453 int no_prop_channel::init_membership(char *file, char * ch, int sz) { 00454 00455 FILE * f; 00456 int ret, test; 00457 00458 int sock, host, port; 00459 00460 char ip[15]; 00461 struct sockaddr_in nom; 00462 struct hostent *hp; 00463 00464 if( (f=fopen(file, "r"))==NULL ) 00465 return(-1); 00466 00467 ret = fscanf(f,"%d %s %d",&test,&ip,&port); 00468 host = (int) inet_addr(ip); 00469 00470 if ( (sock=socket(AF_INET,SOCK_DGRAM,0) ) < 0 ) { 00471 //creation d'une socket UDP 00472 return(-2); 00473 } 00474 00475 if ( (hp=gethostbyaddr((char *)&host, sizeof (host), AF_INET))==NULL ) { 00476 close(sock); 00477 return(-1); 00478 } 00479 memcpy((char *) &nom.sin_addr, (char *) hp->h_addr, hp->h_length); 00480 nom.sin_family = AF_INET; 00481 nom.sin_port = htons(port); 00482 00483 //on essaye d'envoyer les donnees au destinataire 00484 00485 if( (test = sendto(sock, ch, sz, 0, (struct sockaddr *) &nom, sizeof nom) != sz ) ) { 00486 cout << " erreur sendto , sz = " << sz << " res = " << test << endl ; 00487 return(-3); 00488 } 00489 00490 if( (test = sendto(sock, ch, sz, 0, (struct sockaddr *) &nom, sizeof nom) != sz ) ) { 00491 cout << " erreur sendto , sz = " << sz << " res = " << test << endl ; 00492 return(-3); 00493 } 00494 00495 close(sock); 00496 return 0; 00497 } 00498 00499 00500 00501 /********************************************************************/ 00502 /********************* get attributes *********************/ 00503 00504 int no_prop_channel::get_mynode() { 00505 00506 return(my_nodeid); 00507 00508 } 00509 00510 int no_prop_channel::get_myport() { 00511 00512 if (my_port == -1) sleep(1) ; 00513 00514 return(my_port); 00515 00516 }