static void Read_message() { static char mess[MAX_MESSLEN]; char sender[MAX_GROUP_NAME]; char target_groups[MAX_MEMBERS][MAX_GROUP_NAME]; membership_info memb_info; vs_set_info vssets[MAX_VSSETS]; unsigned int my_vsset_index; int num_vs_sets; char members[MAX_MEMBERS][MAX_GROUP_NAME]; int num_groups; int service_type; int16 mess_type; int endian_mismatch; int i,j; int ret; service_type = 0; ret = SP_receive( Mbox, &service_type, sender, 100, &num_groups, target_groups, &mess_type, &endian_mismatch, sizeof(mess), mess ); printf("\n============================\n"); if( ret < 0 ) { if ( (ret == GROUPS_TOO_SHORT) || (ret == BUFFER_TOO_SHORT) ) { service_type = DROP_RECV; printf("\n========Buffers or Groups too Short=======\n"); ret = SP_receive( Mbox, &service_type, sender, MAX_MEMBERS, &num_groups, target_groups, &mess_type, &endian_mismatch, sizeof(mess), mess ); } } if (ret < 0 ) { if( ! To_exit ) { SP_error( ret ); printf("\n============================\n"); printf("\nBye.\n"); } exit( 0 ); } if( Is_regular_mess( service_type ) ) { mess[ret] = 0; if ( Is_unreliable_mess( service_type ) ) printf("received UNRELIABLE "); else if( Is_reliable_mess( service_type ) ) printf("received RELIABLE "); else if( Is_fifo_mess( service_type ) ) printf("received FIFO "); else if( Is_causal_mess( service_type ) ) printf("received CAUSAL "); else if( Is_agreed_mess( service_type ) ) printf("received AGREED "); else if( Is_safe_mess( service_type ) ) printf("received SAFE "); printf("message from %s, of type %d, (endian %d) to %d groups \n(%d bytes): %s\n", sender, mess_type, endian_mismatch, num_groups, ret, mess ); }else if( Is_membership_mess( service_type ) ) { ret = SP_get_memb_info( mess, service_type, &memb_info ); if (ret < 0) { printf("BUG: membership message does not have valid body\n"); SP_error( ret ); exit( 1 ); } if ( Is_reg_memb_mess( service_type ) ) { printf("Received REGULAR membership for group %s with %d members, where I am member %d:\n", sender, num_groups, mess_type ); for( i=0; i < num_groups; i++ ) printf("\t%s\n", &target_groups[i][0] ); printf("grp id is %d %d %d\n",memb_info.gid.id[0], memb_info.gid.id[1], memb_info.gid.id[2] ); if( Is_caused_join_mess( service_type ) ) { printf("Due to the JOIN of %s\n", memb_info.changed_member ); }else if( Is_caused_leave_mess( service_type ) ){ printf("Due to the LEAVE of %s\n", memb_info.changed_member ); }else if( Is_caused_disconnect_mess( service_type ) ){ printf("Due to the DISCONNECT of %s\n", memb_info.changed_member ); }else if( Is_caused_network_mess( service_type ) ){ printf("Due to NETWORK change with %u VS sets\n", memb_info.num_vs_sets); num_vs_sets = SP_get_vs_sets_info( mess, &vssets[0], MAX_VSSETS, &my_vsset_index ); if (num_vs_sets < 0) { printf("BUG: membership message has more then %d vs sets. Recompile with larger MAX_VSSETS\n", MAX_VSSETS); SP_error( num_vs_sets ); exit( 1 ); } for( i = 0; i < num_vs_sets; i++ ) { printf("%s VS set %d has %u members:\n", (i == my_vsset_index) ? ("LOCAL") : ("OTHER"), i, vssets[i].num_members ); ret = SP_get_vs_set_members(mess, &vssets[i], members, MAX_MEMBERS); if (ret < 0) { printf("VS Set has more then %d members. Recompile with larger MAX_MEMBERS\n", MAX_MEMBERS); SP_error( ret ); exit( 1 ); } for( j = 0; j < vssets[i].num_members; j++ ) printf("\t%s\n", members[j] ); } } }else if( Is_transition_mess( service_type ) ) { printf("received TRANSITIONAL membership for group %s\n", sender ); }else if( Is_caused_leave_mess( service_type ) ){ printf("received membership message that left group %s\n", sender ); }else printf("received incorrecty membership message of type 0x%x\n", service_type ); } else if ( Is_reject_mess( service_type ) ) { printf("REJECTED message from %s, of servicetype 0x%x messtype %d, (endian %d) to %d groups \n(%d bytes): %s\n", sender, service_type, mess_type, endian_mismatch, num_groups, ret, mess ); }else printf("received message of unknown message type 0x%x with ret %d\n", service_type, ret); printf("\n"); printf("User> "); fflush(stdout); }
int main( int argc, char *argv[] ) { int ret; int service_type, num_groups; char sender[MAX_GROUP_NAME]; int16 mess_type; int dummy_endian_mismatch; int joined_members; int sender_index; int i,j; Usage( argc, argv ); if (Num_members == 0) { /* connecting to the relevant Spread daemon, no need for group info */ printf("flooder: connecting to %s\n", Spread_name ); ret = SP_connect( Spread_name, User, 0, 0, &Mbox, Private_group ) ; } else { /* connecting to the relevant Spread daemon, DO need group info */ printf("flooder: connecting to %s with group membership\n", Spread_name ); ret = SP_connect( Spread_name, User, 0, 1, &Mbox, Private_group ) ; } if(ret < 0) { SP_error( ret ); exit(1) ; } /* * Joining the process group. * * Note that this is not necessary in order to multicast the * messages, but only to demonstrate end-to-end behaviour. */ if( Read_only ) { printf("flooder: Only receiving messages\n"); SP_join( Mbox, "flooder" ); }else if( Write_only ) { printf("flooder: starting multicast of %d messages, %d bytes each (self discarding).\n", Num_messages, Num_bytes); }else{ SP_join( Mbox, "flooder" ); printf("flooder: starting multicast of %d messages, %d bytes each.\n", Num_messages, Num_bytes); } /* Wait for all members to join */ joined_members = 0; while( joined_members < Num_members) { service_type = 0; ret = SP_receive( Mbox, &service_type, sender, FLOODER_MAX_GROUPS, &num_groups, ret_groups, &mess_type, &dummy_endian_mismatch, sizeof(recv_mess), recv_mess ); if( ret < 0 ) { if ( (ret == GROUPS_TOO_SHORT) || (ret == BUFFER_TOO_SHORT) ) { printf("\n========Buffers or Groups too Short=======\n"); printf("Should NOT happen in wait for members! Program quitting\n"); exit(1); } } if( Is_regular_mess( service_type ) ) { mess[ret] = 0; if ( Is_unreliable_mess( service_type ) ) printf("received UNRELIABLE "); else if( Is_reliable_mess( service_type ) ) printf("received RELIABLE "); else if( Is_fifo_mess( service_type ) ) printf("received FIFO "); else if( Is_causal_mess( service_type ) ) printf("received CAUSAL "); else if( Is_agreed_mess( service_type ) ) printf("received AGREED "); else if( Is_safe_mess( service_type ) ) printf("received SAFE "); printf("message during wait for members, from %s, of type %d, (endian %d) to %d groups \n(%d bytes): %s\n", sender, mess_type, dummy_endian_mismatch, num_groups, ret, recv_mess ); }else if( Is_membership_mess( service_type ) ) { if ( Is_reg_memb_mess( service_type ) ) { printf("Received REGULAR membership for group %s with %d members, where I am member %d:\n", sender, num_groups, mess_type ); for( i=0; i < num_groups; i++ ) printf("\t%s\n", &ret_groups[i][0] ); /* update count of joined members */ joined_members = num_groups; }else if( Is_transition_mess( service_type ) ) { printf("received TRANSITIONAL membership for group %s\n", sender ); }else if( Is_caused_leave_mess( service_type ) ){ printf("received membership message that left group %s\n", sender ); }else printf("received incorrecty membership message of type 0x%x\n", service_type ); } else if ( Is_reject_mess( service_type ) ) { printf("REJECTED message from %s, of servicetype 0x%x messtype %d, (endian %d) to %d groups \n(%d bytes): %s\n", sender, service_type, mess_type, dummy_endian_mismatch, num_groups, ret, recv_mess ); }else printf("received message of unknown message type 0x%x with ret %d\n", service_type, ret); } /* joined_members < Num_members */ /* Update My_Counter_index field based on location of my name in last membership message */ if (Num_members) { My_Counter_index = mess_type; memcpy(&mess[0], &My_Counter_index, sizeof(int)); } for( i=1; i <= Num_messages; i++ ) { /* multicast a message unless Read_only */ if( !Read_only ) { if (Num_members) { ret = SP_multicast( Mbox, FIFO_MESS, "flooder", 0, Num_bytes, mess ); Send_Counter++; } else { ret = SP_multicast( Mbox, RELIABLE_MESS, "flooder", 0, Num_bytes, mess ); } if( ret != Num_bytes ) { if( ret < 0 ) { SP_error( ret ); exit(1); } printf("sent a different message %d -> %d\n", Num_bytes, ret ); } } /* receive a message (Read_only) or one of my messages */ if( Read_only || ( i > 200 && !Write_only ) ) { int notdone; do{ service_type = 0; ret = SP_receive( Mbox, &service_type, sender, FLOODER_MAX_GROUPS, &num_groups, ret_groups, &mess_type, &dummy_endian_mismatch, sizeof(recv_mess), recv_mess ); if( ret < 0 ) { if ( (ret == GROUPS_TOO_SHORT) || (ret == BUFFER_TOO_SHORT) ) { service_type = DROP_RECV; printf("\n========Buffers or Groups too Short=======\n"); ret = SP_receive( Mbox, &service_type, sender, FLOODER_MAX_GROUPS, &num_groups, ret_groups, &mess_type, &dummy_endian_mismatch, sizeof(recv_mess), recv_mess ); } } if( ret < 0 ) { SP_error( ret ); exit(1); } if (Num_members) { /* update counters of received messages */ memcpy(&sender_index, &recv_mess[0], sizeof(int)); Recv_Counters[sender_index]++; /* printf("DEBUG: updated counter %d to value %d\n", sender_index, Recv_Counters[sender_index]); */ if (Recv_Counters[sender_index] == (Lowest_Recv_Counter + 1)) { /* Update Lowest_Recv_Counter */ Lowest_Recv_Counter = INT_MAX; for (j=0; j < Num_members; j++) { if (Recv_Counters[j] == 0) continue; if (Recv_Counters[j] < Lowest_Recv_Counter) Lowest_Recv_Counter = Recv_Counters[j]; } if (Lowest_Recv_Counter == INT_MAX) Lowest_Recv_Counter = 0; } /* Read loop is done if we send messages and we have received all * other senders messages upto 100 less then our current send count */ notdone = ( Lowest_Recv_Counter < (Send_Counter - 200) && !Read_only ); } else { notdone = (strcmp( sender, Private_group ) != 0 && !Read_only); } } while( notdone ); } /* report some progress... */ if( i%1000 == 0 ) printf("flooder: completed %6d messages of %d bytes\n",i, ret); } printf("flooder: completed multicast of %d messages, %d bytes each.\n", Num_messages, Num_bytes); return 0; }