/* send an ack for the given message and message ID */ static void send_ack (int sock, struct allnet_header * hp, unsigned char * message_ack, int send_resend_request, char * contact, keyset kset) { if ((hp->transport & ALLNET_TRANSPORT_ACK_REQ) == 0) { printf ("packet not requesting an ack, no ack sent\n"); return; } int size; struct allnet_header * ackp = create_ack (hp, message_ack, NULL, ADDRESS_BITS, &size); if (ackp == NULL) return; /* also save in the (very likely) event that we receive our own ack */ currently_sent_ack = (currently_sent_ack + 1) % NUM_ACKS; memcpy (recently_sent_acks [currently_sent_ack], message_ack, MESSAGE_ID_SIZE); #ifdef DEBUG_PRINT print_packet ((char *) ackp, size, "sending ack", 1); #endif /* DEBUG_PRINT */ send_pipe_message_free (sock, (char *) ackp, size, ALLNET_PRIORITY_LOCAL); /* after sending the ack, see if we can get any outstanding * messages from the peer */ if (send_resend_request) request_and_resend (sock, contact, kset); }
/** * Repondre a une requete Initiate * @param sock Socket du joueur ayant envoye une demande de connexion * @param the_players Liste des joueurs * @param recv_frame Trame Initiate recue * @return Resultat de l'echange (cf. fonction respond pour plus d'informations) */ Result* respond_initiate(int sock, Players the_players, Frame frame) { /* Compteur persistant de joueurs connectes */ static uint16_t nb_connected_players = 0; /* Resultat de l'echange */ Result* result = NULL; /* Acquittement de la requete, negatif par defaut */ Frame ack_frame = create_ack(0); /* Verification de la requete du client */ int format_check = ERROR; int constraint_check = ERROR; constraint_check = check_initiate_constraint(sock, nb_connected_players, the_players); format_check = check_initiate_format(frame); /* Traitement de la requete */ if(constraint_check == SUCCESS && format_check == SUCCESS) { /* Verification du nom d'application et de la version du protocole */ if(check_appname(frame->data[0]->string.content) == SUCCESS && check_version(frame->data[1]->string.content) == SUCCESS) { /* Creation du resultat de l'echange */ result = malloc(sizeof(Result)); result->type = Initiate; result->content = NULL; /* Connexion du nouveau joueur */ the_players->player[nb_connected_players]->sock = sock; the_players->player[nb_connected_players]->is_connected = 1; nb_connected_players++; free_frame(ack_frame); ack_frame = create_ack(1); } } /* Envoi de l'acquittement */ send_frame(sock, ack_frame); return result; }
void process_frames(){ if(queue_nitems(receiver) == 0){ return; } size_t len = 0; FRAME *f = queue_peek(receiver, &len); int source_nodenumber = find_nodenumber(f->payload.source); if(node_buffer[source_nodenumber].busy){ free(f); return; } node_buffer[source_nodenumber].busy = true; f = queue_remove(receiver, &len); //printf("Received frames for message #%d Expecting %d\n", f->payload.mesg_seq_no, node_buffer[source_nodenumber].mesg_seq_no_to_receive); //If ack has not been received at the sender side and an old frame from an old message has been received if(f->payload.mesg_seq_no < node_buffer[source_nodenumber].mesg_seq_no_to_receive){ //printf("Message received is old, dropped :-( Message #%d\n", f->payload.mesg_seq_no); node_buffer[source_nodenumber].busy = false; free(f); process_frames(); return; } if(f->payload.mesg_seq_no > node_buffer[source_nodenumber].mesg_seq_no_to_receive){ queue_add(receiver, f, len); //printf("Message received is new, pushed back ;-) Message #%d\n", f->payload.mesg_seq_no); node_buffer[source_nodenumber].busy = false; free(f); //process_frames(); return; } int seq_no = f->payload.A; char seq_str[5]; sprintf(seq_str, "%d", seq_no); if(seq_no == node_buffer[source_nodenumber].next_seq_number_to_add){ //send ack here create_ack(f->payload); // add to the incomplete data object //printf("Frame appending %d with length %d | MSG #%d\n",seq_no, f->payload.len, f->payload.mesg_seq_no); memcpy(&node_buffer[source_nodenumber].incomplete_data[0] + node_buffer[source_nodenumber].bytes_added, &f->payload.data[0], f->payload.len); node_buffer[source_nodenumber].bytes_added += f->payload.len; node_buffer[source_nodenumber].next_seq_number_to_add++; while(true){ int next_seq = node_buffer[source_nodenumber].next_seq_number_to_add; char next_seq_str[5]; sprintf(next_seq_str, "%d", next_seq); size_t plen; PACKET *pkt = hashtable_find(node_buffer[source_nodenumber].ooo_packets, next_seq_str, &plen); if(plen == 0) break; //printf("In While loop:Next frame %d found in HT\n",next_seq); pkt = hashtable_remove(node_buffer[source_nodenumber].ooo_packets, next_seq_str, &plen); create_ack(*pkt); memcpy(&node_buffer[source_nodenumber].incomplete_data[0] + node_buffer[source_nodenumber].bytes_added, &pkt->data, pkt->len); node_buffer[source_nodenumber].bytes_added += pkt->len; node_buffer[source_nodenumber].next_seq_number_to_add++; } // check for the last packet if(f->payload.flag_offset == 1) { //printf("\t\t\t\t\t\tBytes in reconstructed message is %d and is sent by %d\n",node_buffer[source_nodenumber].bytes_added, source_nodenumber); CHECK(CNET_write_application((char*)&node_buffer[source_nodenumber].incomplete_data[0], &node_buffer[source_nodenumber].bytes_added)); node_buffer[source_nodenumber].next_seq_number_to_add = 0; memset(node_buffer[source_nodenumber].incomplete_data, '\0', MAX_MESSAGE_SIZE); hashtable_free(node_buffer[source_nodenumber].ooo_packets); // Overriding default bucket size of 1023 node_buffer[source_nodenumber].ooo_packets = hashtable_new(256); printf("\t\t\t\t\t\tSuccessfully Written to Application. Bytes in the reconstructed message #%d are %d sent by %d.\n", f->payload.mesg_seq_no, node_buffer[source_nodenumber].bytes_added, source_nodenumber); node_buffer[source_nodenumber].bytes_added = 0; node_buffer[source_nodenumber].mesg_seq_no_to_receive++; //= f->payload.mesg_seq_no; } } else { size_t plen; hashtable_find(node_buffer[source_nodenumber].ooo_packets, seq_str, &plen); if(plen == 0){ hashtable_add(node_buffer[source_nodenumber].ooo_packets, seq_str, &f->payload, len - sizeof(uint32_t)); } } node_buffer[source_nodenumber].busy = false; process_frames(); free(f); }