static EVENT_HANDLER(physical_ready) { FRAME f; size_t len; int link, checksum; len = sizeof(FRAME); CHECK(CNET_read_physical(&link, (char *)&f, &len)); checksum = f.checksum; f.checksum = 0; if(CNET_ccitt((unsigned char *)&f, len) != checksum) { return; // bad checksum, ignore frame } switch (f.kind) { case ACK : if(f.seq == ackexpected) { CNET_stop_timer(lasttimer); ackexpected = 1-ackexpected; CNET_enable_application(ALLNODES); } break; case DATA : if(f.seq == frameexpected) { len = f.len; CHECK(CNET_write_application((char *)&f.msg, &len)); frameexpected = 1-frameexpected; } transmit_frame(NULL, ACK, 0, f.seq); break; } }
void reboot_node(CnetEvent ev, CnetTimerID timer, CnetData data) { // SET EVENT HANDLERS CHECK(CNET_set_handler( EV_APPLICATIONREADY, transport_down, 0)); CHECK(CNET_set_handler( EV_PHYSICALREADY, datalink_up, 0)); CHECK(CNET_set_handler( EV_TIMER1, timeout_link_1, 0)); CHECK(CNET_set_handler( EV_TIMER2, timeout_link_2, 0)); CHECK(CNET_set_handler( EV_TIMER3, timeout_link_3, 0)); CHECK(CNET_set_handler( EV_TIMER4, timeout_link_4, 0)); CHECK(CNET_set_handler( EV_DRAWFRAME, draw_frame, 0)); // INITIALISE TIMER ARRAY TO NULL TIMERS for ( int ii = 0; ii < MAX_LINKS; ii++ ) for ( int jj = 0; jj < MAX_SEQ + 1; jj++ ) timers[ii][jj] = NULLTIMER; // ENABLE ALL NODES TO SEND TO ALL OTHER NODES CHECK(CNET_enable_application(ALLNODES)); // SET LEDS FOR LINKS TO ALL GREEN INITIALLY for ( int jj = 0; jj < nodeinfo.nlinks; jj++ ) CNET_set_LED( jj, "green" ); // SET LEDS FOR NON-USED LIGHTS TO ALL BLACK INITIALLY for ( int kk = nodeinfo.nlinks; kk < CNET_NLEDS; kk++ ) CNET_set_LED( kk, "black" ); }
void reboot_node(CnetEvent event){ check = (char *)malloc(9*sizeof(char)); CHECK(CNET_set_handler(EV_APPLICATIONREADY,application_ready, 0)); CHECK(CNET_set_handler(EV_PHYSICALREADY,frame_arrived, 0)); CHECK(CNET_set_handler(EV_TIMER1,resend_frame, 0)); CNET_enable_application(ALLNODES); }
///Initializes the mobile node and prepares it for operation. ///Called when this mobile node is booted up. void reboot_mobile() { // We require each node to have a different stream of random numbers. CNET_srand(nodeinfo.time_of_day.sec + nodeinfo.nodenumber); // Provide the required event handlers. CHECK(CNET_set_handler(EV_PHYSICALREADY, physical_ready, 0)); CHECK(CNET_set_handler(EV_APPLICATIONREADY, application_ready, 0)); // Initialize mobility. init_walking(); start_walking(); // Prepare to talk via our wireless connection. CHECK(CNET_set_wlan_model(my_WLAN_model)); // Setup our data link layer instances. dll_states = calloc(nodeinfo.nlinks + 1, sizeof(struct dll_wifi_state *)); for (int link = 1; link <= nodeinfo.nlinks; ++link) { if (linkinfo[link].linktype == LT_WLAN) { dll_states[link] = dll_wifi_new_state(link, up_from_dll, false /* is_ds */); } } isAss = false; timeAPset = false; //CNET TIMEOUT TIMER CHECK(CNET_set_handler( EV_TIMER2, timeouts, 0)); //CNET PROBE TIMER CHECK(CNET_set_handler(EV_TIMER1, probe, 0)); CHECK(CNET_set_handler(EV_TIMER3, probe, 0)); // Start cnet's default application layer. CHECK(CNET_enable_application(ALLNODES)); printf("reboot_mobile() complete.\n"); printf("\t(%s) My address: %" PRId32 ".\n",nodeinfo.nodename, nodeinfo.address); probe_timer = CNET_start_timer(EV_TIMER1, PROBE_START, 0); toSend = (struct nl_packet *)malloc(sizeof(struct nl_packet)); CNET_start_timer(EV_TIMER1, 0, 0); }
void cleanup_and_start_app(){ int other_nodes = nodes_discovered(); printf("%d Nodes Discovered for Address %d(nodenum=%d) \n",other_nodes,nodeinfo.address, nodeinfo.nodenumber); for(int i=0; i<= other_nodes; i++){ if(i != nodeinfo.nodenumber) printf("#%d : Dest address : %d | Via address : %d | MTU : %d | Cost : %ld \n", i, table[i].dest, table[i].via, linkinfo[table[i].link].mtu, table[i].cost); } printf("Routing successfully completed! Application started.\n"); RoutingStage = false; CNET_enable_application(ALLNODES); setup_nl(); setup_dll(); }
static bool extract_message(MSG *msg, int *length){ size_t len; if(queue_nitems(msg_queue) == 0) return false; msg_ptr = (MSG*)(queue_remove(msg_queue, &len)); msg->dest = msg_ptr->dest; memcpy(&msg->data[0], &msg_ptr->data[0], len - MESSAGE_HEADER_SIZE); printf("AL : Message to be sent to %d | size %d\n", msg->dest, len - MESSAGE_HEADER_SIZE); if(!app_enabled && queue_nitems(msg_queue) < MAX_MSG_QUEUE_SIZE/2){ CHECK(CNET_enable_application(ALLNODES)); app_enabled = true; } *length = len - MESSAGE_HEADER_SIZE; return true; }
void reboot_node(CnetEvent ev, CnetTimer timer, CnetData data) { if(nodeinfo.nlinks > 32) { fprintf(stderr,"selective flooding will not work here\n"); exit(1); } CHECK(CNET_set_handler(EV_APPLICATIONREADY, down_to_transport, 0)); CHECK(CNET_set_handler(EV_PHYSICALREADY, up_to_datalink, 0)); CHECK(CNET_set_handler(EV_DEBUG1, show_table, 0)); CHECK(CNET_set_debug_string( EV_DEBUG1, "NL info")); init_DLL(); init_NL(); CNET_enable_application(ALLNODES); /* added a timer to sending stuff from queue */ CNET_set_handler(EV_TIMER1, fire_queue, 0); }
static EVENT_HANDLER(ready_physical) { if(nodetype != RECEIVER) { ACK_FRAME f; int link; size_t length; length = sizeof(ACK_FRAME); CHECK(CNET_read_physical(&link, (char*) &f, &length)); uint16_t check = f.check; f.check = 0; if(CNET_ccitt((unsigned char*) &f, sizeof(ACK_FRAME)) != check) return; if(f.sequence <= 0) { // SREJ FRAME printf("\t\t\t\tSREJ received, sequence=%d\n", -f.sequence); f.sequence = -f.sequence; CNET_stop_timer(timer); trans_frame_state[f.sequence] = ACK_WAIT; frame_send(&(t_window[f.sequence].message), t_window[f.sequence].length, f.sequence); } else { // RECVREADY FRAME printf("\t\t\t\tACK received, sequence=%d\n", f.sequence); int i; for(i = (last_ack_recv + 1)%(MAXSEQ + 1); i != f.sequence - 1; i = (i + 1) % (MAXSEQ + 1)) trans_frame_state[i] = ACK_RECEIVED; last_ack_recv = f.sequence - 1; trans_frame_state[f.sequence-1] = ACK_RECEIVED; CNET_stop_timer(timer_wait); if(packets_sent >= 10000) { if(time_end == 0) time_end = nodeinfo.time_of_day.sec; } else { packets_sent++; CNET_enable_application(ALLNODES); } } } else { FRAME_DATA f; size_t length; int link; int checksum; length = sizeof(FRAME_DATA); CHECK(CNET_read_physical(&link, (char*) &f, &length)); checksum = f.checksum; f.checksum = 0; if(CNET_ccitt((unsigned char*) &f, CHECK_BYTES) != checksum) { // bad checksum, ignore frame printf("\t\t\t\tBAD checksum - frame ignored\n"); ack_send(last_ack_sent + 1, SREJ); printf("Requesting to send frame %d\n",last_ack_sent+1); return; } recv_frame_status[f.sequence] = RECEIVED; printf("\t\t\t\tDATA received, sequence=%d\n", f.sequence); int i; for(i = (last_ack_sent + 1) % (MAXSEQ + 1); i != f.sequence; i = (i + 1) % (MAXSEQ + 1)) { if(recv_frame_status[i] != RECEIVED) break; } if(i == f.sequence) ack_send(f.sequence + 1, RECVREADY); } }
/* up_to_network() IS CALLED FROM THE DATA LINK LAYER (BELOW) TO ACCEPT A PACKET FOR THIS NODE, OR TO RE-ROUTE IT TO THE INTENDED DESTINATION. */ int up_to_network(char *packet, size_t length, int arrived_on_link) { NL_PACKET *p = (NL_PACKET *) packet; if(p->src == nodeinfo.address){ printf ("drop a packet at %d, src = %d, des = %d, seqno = %d\n", nodeinfo.address, p->src, p->dest, p->seqno); return 0; } //printf("up to network at %d (from %d to %d)\n", nodeinfo.address, p->src, p->dest); ++p->hopcount; /* took 1 hop to get here */ mtu = linkinfo[arrived_on_link].mtu; p->trans_time += ((CnetTime)8000 * 1000 * mtu / linkinfo[arrived_on_link].bandwidth + linkinfo[arrived_on_link].propagationdelay)*100/mtu; ////("me = %d, dest = %d =======\n", nodeinfo.address, p->dest); /* IS THIS PACKET IS FOR ME? */ if (p->dest == nodeinfo.address) { switch (p->kind) { case NL_DATA: if (p->seqno == NL_packetexpected(p->src)) { length = p->length; memcpy(rb[p->src], (char *) p->msg, length); rb[p->src] = rb[p->src] + length; //packet_length[p->src] += length; if (p->pieceEnd) { CnetAddr tmpaddr; length = p->pieceNumber * (linkinfo[arrived_on_link].mtu - PACKET_HEADER_SIZE) + p->length; //length = packet_length[p->src]; //packet_length[p->src] = 0; int p_checksum = p->checksum; int checksum = CNET_ccitt( (unsigned char *) (receiveBuffer[p->src]), p->src_packet_length); if(p->is_resent){ printf("%d received a resent packet, src = %d, des = %d, seqno = %d, send_length = %d,receive_length = %d \n", nodeinfo.address, p->src, p->dest, p->seqno, p->src_packet_length, length); }else{ printf("%d received a packet, src = %d, des = %d, seqno = %d, send_length = %d,receive_length = %d \n", nodeinfo.address, p->src, p->dest, p->seqno, p->src_packet_length, length); } printf("last_piece_trans_time = %d, hopcount = %d\n", p->trans_time, p->hopcount); printf("src_checksum = %d calc_checksum = %d, ", p_checksum, checksum); if (p_checksum != checksum) { /***************************send back error ack**************/ printf("error packet\n\n"); NL_savehopcount(p->src, p->trans_time, arrived_on_link); tmpaddr = p->src; /* swap src and dest addresses */ p->src = p->dest; p->dest = tmpaddr; if(p->is_resent == 1) p->kind = NL_ERR_ACK_RESENT; else p->kind = NL_ERR_ACK; p->hopcount = 0; p->pieceNumber = 0; p->pieceEnd = 0; p->length = 0; p->src_packet_length = 0; p->checksum = 0; p->trans_time = 0; flood3(packet, PACKET_HEADER_SIZE, arrived_on_link, 0); rb[p->src] = &receiveBuffer[p->src][0]; //printf("\n"); return 0; /***************************end******************************/ } /* if (CNET_write_application(receiveBuffer[p->src], &length) == -1) { //source node should send this msg again //printf("===\ncnet_errno = %d\n===\n", cnet_errno); //printf("error count: %d\n", ++ err_count); if (cnet_errno == ER_CORRUPTFRAME) { printf("corrupt packet\n"); //printf("\nWarning: frame corrupted\n==\n"); } else if (cnet_errno == ER_MISSINGMSG) { printf("unordered packet\n"); //printf("\nWarning: frame missed\n\n"); } else if(cnet_errno == ER_BADSIZE){ printf("loss packet\n"); } } */ CHECK(CNET_write_application(receiveBuffer[p->src], &length)); printf("correct packet\n", p->dest, p->seqno, p->src); rb[p->src] = &receiveBuffer[p->src][0]; inc_NL_packetexpected(p->src); NL_savehopcount(p->src, p->trans_time, arrived_on_link); tmpaddr = p->src; /* swap src and dest addresses */ p->src = p->dest; p->dest = tmpaddr; p->kind = NL_ACK; p->hopcount = 0; p->pieceNumber = 0; p->pieceEnd = 0; p->length = 0; p->src_packet_length = 0; p->checksum = 0; p->trans_time = 0; p->is_resent = 0; flood3(packet, PACKET_HEADER_SIZE, arrived_on_link, 0); printf("\n"); } } break; case NL_ACK: if (p->seqno == NL_ackexpected(p->src)) { ////("ACK come!\n"); inc_NL_ackexpected(p->src); NL_savehopcount(p->src, p->trans_time, arrived_on_link); NL_set_has_resent(p->src, 0); CHECK(CNET_enable_application(p->src)); } break; case NL_ERR_ACK: printf("NL_ERR_ACK!\n"); if (p->seqno == NL_ackexpected(p->src)){ if(NL_get_has_resent(p->src) == 0) { NL_savehopcount(p->src, p->trans_time, arrived_on_link); NL_PACKET * packettoresend = get_last_packet(p->src); printf("src = %d, des = %d, seqno = %d, send_length = %d, checksum = %d\n", packettoresend->src, packettoresend->dest, packettoresend->seqno, packettoresend->length, packettoresend->checksum); printf("resend it\n"); int len = PACKET_HEADER_SIZE + packettoresend->length; packettoresend->is_resent = 1; NL_set_has_resent(p->src, 1); NL_inc_resent_times(p->src); // for debug flood3((char *) packettoresend, len, 0, 0); } else{ printf("this packet has already been resent, dont resent it again\n"); } } else{ printf("this packet has already been correct received, dont resent it again\n"); } printf("\n"); break; case NL_ERR_ACK_RESENT: printf("NL_ERR_ACK_RESENT!\n"); if (p->seqno == NL_ackexpected(p->src)) { NL_savehopcount(p->src, p->trans_time, arrived_on_link); NL_PACKET * packettoresend = get_last_packet(p->src); printf("resend a resent packet, src = %d, des = %d, seqno = %d, send_length = %d, checksum = %d\n", packettoresend->src, packettoresend->dest, packettoresend->seqno, packettoresend->length, packettoresend->checksum); printf("this packet has been resent %d times before this time\n", NL_get_resent_times(p->src)); //for debug NL_inc_resent_times(p->src); // for debug int len = PACKET_HEADER_SIZE + packettoresend->length; packettoresend->is_resent = 1; flood3((char *) packettoresend, len, 0, 0); } else{ printf("this packet has already been correct received, dont resent it again\n"); } printf("\n"); break; default: //("it's nothing!====================\n"); break; } } /* THIS PACKET IS FOR SOMEONE ELSE */ else { // //("hopcount = %d\n", p->hopcount); // //("MAXHOPS = %d\n", MAXHOPS); if (p->hopcount < MAXHOPS) { /* if not too many hops... */ ////("other's frame!\n"); //("piece for another node arrives\n"); length = p->length; memcpy(rb[p->src], (char *) p->msg, length); rb[p->src] = rb[p->src] + length; //packet_length[p->src] += length; if (p->pieceEnd) { //printf("last piece for another node arrives\n"); length = p->pieceNumber * (linkinfo[arrived_on_link].mtu - PACKET_HEADER_SIZE) + p->length; //length = packet_length[p->src]; //packet_length[p->src] = 0; NL_savehopcount(p->src, p->trans_time, arrived_on_link); NL_PACKET wholePacket; wholePacket.src = p->src; wholePacket.dest = p->dest; wholePacket.kind = p->kind; wholePacket.seqno = p->seqno; wholePacket.hopcount = p->hopcount; wholePacket.pieceNumber = 0; wholePacket.pieceEnd = 0; wholePacket.length = length; wholePacket.src_packet_length = p->src_packet_length; wholePacket.checksum = p->checksum; wholePacket.trans_time = p->trans_time; wholePacket.is_resent = p->is_resent; memcpy(wholePacket.msg, receiveBuffer[p->src], length); // //("contents of msg forwarding is \n %s\n", receiveBuffer[p->src]); flood3((char *) &wholePacket, PACKET_SIZE(wholePacket), 0, arrived_on_link); rb[p->src] = &receiveBuffer[p->src][0]; } } else { /* silently drop */; //free(&p->msg); //free(p); } } return (0); }
/* up_to_network() IS CALLED FROM THE DATA LINK LAYER (BELOW) TO ACCEPT A PACKET FOR THIS NODE, OR TO RE-ROUTE IT TO THE INTENDED DESTINATION. */ int up_to_network(char *packet, size_t length, int arrived_on_link) { NL_PACKET *p = (NL_PACKET *) packet; if (p->src == nodeinfo.address) { printf( "drop a packet at %d, src = %d, des = %d, seqno = %d, length = %d\n\n", nodeinfo.address, p->src, p->dest, p->seqno, p->length); return 0; } ++p->hopcount; /* took 1 hop to get here */ mtu = linkinfo[arrived_on_link].mtu; p->trans_time += ((CnetTime) 8000 * 1000 * mtu / linkinfo[arrived_on_link].bandwidth + linkinfo[arrived_on_link].propagationdelay) * 100 / mtu; size_t maxsize = mtu - PACKET_HEADER_SIZE; if (p->length > maxsize || p->length < (size_t) 0) { //fprintf(stdout, "p->length = %d, max size = %d\n", (int)(p->length), (int) maxsize); return 0; } CnetAddr tempaddr; /* IS THIS PACKET IS FOR ME? */ if (p->dest == nodeinfo.address) { switch (p->kind) { case NL_TEST: if (NL_gettesthascome(p->src)) break; printf("test packet come!\n"); NL_savehopcount(p->src, p->hopcount, arrived_on_link); NL_updateminmtu(p->src, p->min_mtu, arrived_on_link); NL_inctesthascome(p->src); tempaddr = p->src; p->src = p->dest; p->dest = tempaddr; p->kind = NL_TEST_ACK; p->hopcount = 0; p->length = 0; flood_test(packet, PACKET_HEADER_SIZE, arrived_on_link, 0); break; case NL_TEST_ACK: printf("test packet ack come!\n"); NL_savehopcount(p->src, p->hopcount, arrived_on_link); NL_updateminmtu(p->src, p->min_mtu, arrived_on_link); break; case NL_DATA: if (p->seqno == NL_packetexpected(p->src)) { if (RB_save_msg_link(rb, p, arrived_on_link) == 2) { /* all pieces are arrived now get the whole msg from buffer and write it in applicaiton layer */ RB_copy_whole_msg_link(rb, p, arrived_on_link); CHECK(CNET_write_application((char*) p->msg, &p->src_packet_length)); send_ack(p, arrived_on_link, 0); return 0; } else if (p->pieceEnd || p->is_resent) { /* last piece arrives, now check the missing frame position */ // check which piece is missing and require to resend this piece //TODO: check which piece is missing //TODO: and require to resend this piece } } break; case NL_ACK: if (p->seqno == NL_ackexpected(p->src)) { printf("ACK come!\n"); inc_NL_ackexpected(p->src); NL_savehopcount(p->src, p->trans_time, arrived_on_link); NL_set_has_resent(p->src, 0); NL_update_lastackexpected(p->src); CHECK(CNET_enable_application(p->src)); } else if (p->seqno < NL_ackexpected(p->src)) { printf("outdated ACK come!\n"); } break; case NL_ERR_ACK: printf("NL_ERR_ACK!\n"); if (p->seqno == NL_ackexpected(p->src)) { if (NL_get_has_resent(p->src) == 0) { NL_savehopcount(p->src, p->trans_time, arrived_on_link); NL_PACKET * packettoresend = get_last_packet(p->src); printf( "src = %d, des = %d, seqno = %d, send_length = %d, checksum = %d\n", packettoresend->src, packettoresend->dest, packettoresend->seqno, packettoresend->length, packettoresend->checksum); printf("resend it\n"); int len = PACKET_HEADER_SIZE + packettoresend->length; packettoresend->is_resent = 1; NL_set_has_resent(p->src, 1); flood((char *) packettoresend, len, 0, 0); } else { printf( "this packet has already been resent, dont resent it again\n"); } } else { printf( "this packet has already been correct received, dont resent it again\n"); } break; case NL_ERR_ACK_RESENT: printf("NL_ERR_ACK_RESENT!\n"); if (p->seqno == NL_ackexpected(p->src)) { NL_savehopcount(p->src, p->trans_time, arrived_on_link); NL_PACKET * packettoresend = get_last_packet(p->src); printf( "resend a resent packet, src = %d, des = %d, seqno = %d, send_length = %d, checksum = %d\n", packettoresend->src, packettoresend->dest, packettoresend->seqno, packettoresend->length, packettoresend->checksum); int len = PACKET_HEADER_SIZE + packettoresend->length; packettoresend->is_resent = 1; flood((char *) packettoresend, len, 0, 0); } else { printf( "this packet has already been correct received, dont resent it again\n"); } break; default: printf("it's nothing!====================\n"); break; } } /* THIS PACKET IS FOR SOMEONE ELSE */ else { if (p->kind == NL_TEST) { CnetAddr tmp; NL_PACKET temp_p; if (p->hopcount < MAXHOPS) { NL_savehopcount(p->src, p->hopcount, arrived_on_link); NL_updateminmtu(p->src, p->min_mtu, arrived_on_link); temp_p.src = p->src; temp_p.dest = p->dest; temp_p.min_mtu = p->min_mtu; temp_p.hopcount = p->hopcount; /* retransmit on best links *except* the one on which it arrived */ if (NL_minmtu(temp_p.dest) != 0 && NL_minmtu(temp_p.dest) != -1) { if (temp_p.min_mtu > NL_minmtu(temp_p.dest)) { temp_p.min_mtu = NL_minmtu(temp_p.dest); } //temp_p.hopcount = NL_gethopcount(temp_p.src) + NL_gethopcount( // temp_p.dest); temp_p.hopcount = NL_gethopcount(temp_p.dest); tmp = temp_p.dest; temp_p.dest = temp_p.src; temp_p.src = tmp; temp_p.kind = NL_TEST_ACK; temp_p.length = 0; printf("send query result of %d to %d, min_mtu = %d\n", temp_p.src, temp_p.dest, temp_p.min_mtu); flood_test((char *) &temp_p, PACKET_HEADER_SIZE, arrived_on_link, 0); } } } else if (p->hopcount < MAXHOPS) { /* if not too many hops... */ NL_savehopcount(p->src, p->hopcount, arrived_on_link);//TODO: pay attention for this line, shall we need it? /* retransmit on best links *except* the one on which it arrived */ flood(packet, length, 0, arrived_on_link); } } return 0; }
static void ack_received(FRAME frame, int link) { FRAME tempFrame; int first, second, third, fourth; // PRINT ACKOWLEDGEMENT MESSAGE printf("\n\t\t\t\t\tACK RECEIVED\n"); printf("\t\t\t\t\tIN LINK:%d\n", link); printf("\t\t\t\t\tSEQ NO:\t%d\n", frame.seq); // ENSURE ACK NUMBER IS BETWEEN ACK EXPECTED AND NEXT FRAME TO SEND if (between(ackExpected[link - 1], frame.seq, nextFrameToSend[link - 1])) { // LOOP UNTIL ACKEXPECTED IS ONE MORE THAN THE SEQNUM OF THE ACK while (between(ackExpected[link - 1], frame.seq, nextFrameToSend[link - 1])) { // STOP THE TIMER FOR THAT FRAME TO PREVENT A TIMEOUT CNET_stop_timer(timers[link - 1][ackExpected[link - 1]]); // INCREMENT ACKEXPECTED AND DECREASE NUMBER IN WINDOW inc(&ackExpected[link - 1]); numInWindow[link - 1] -= 1; } } else { // ERRORS SHOULD ALL BE CAUGHT BEFORE THIS // STILL CHECK REGARDLESS, AS A FAILSAFE printf("\n\t\t\t\t\tERROR: OUTSIDE WINDOW BOUNDS\n"); } // ENSURE WINDOW SIZE IS VALID AND BUFFER IS NOT EMPTY while (numInWindow[link - 1] < MAX_SEQ && numInBuffer[link - 1] > 0) { // ADD FRAMES FROM THE BUFFER TO THE WINDOW printf("\t\t\t\t\tSENDING FRAME FROM BUFFER\n"); // REMOVE FRAME FROM THE FRONT OF THE BUFFER tempFrame = buffer[link - 1][bufferBounds[link - 1][0]]; inc(&bufferBounds[link - 1][0]); numInBuffer[link - 1] -= 1; // STORE THE FRAME FROM THE BUFFER IN THE WINDOW tempFrame.seq = nextFrameToSend[link - 1]; window[link - 1][nextFrameToSend[link - 1]] = tempFrame; numInWindow[link - 1] += 1; // TRANSMIT THE FRAME FROM THE BUFFER (NOW IN THE WINDOW) tempFrame.link = get_route(tempFrame.destNode); transmit_frame(tempFrame); inc(&nextFrameToSend[link - 1]); } // IF ALL LINK WINDOWS NOT FULL AND ALL BUFFER'S EMPTY // THIS KEEPS EFFICIECNY AS HIGH AS POSSIBLE first = ( numInBuffer[0] == 0 ) && ( numInWindow[0] < MAX_SEQ ); second = ( numInBuffer[1] == 0 ) && ( numInWindow[1] < MAX_SEQ ); third = ( numInBuffer[2] == 0 ) && ( numInWindow[2] < MAX_SEQ ); fourth = ( numInBuffer[3] == 0 ) && ( numInWindow[3] < MAX_SEQ ); // REENABLE APPLICATION LAYER TO GENERATE MESSAGES AGAIN if ( first && second && third && fourth ) { CHECK(CNET_enable_application(ALLNODES)); for ( int ii = 0; ii < nodeinfo.nlinks; ii++ ) CNET_set_LED(ii, "green" ); } print_buffers(link); }
/* up_to_network() IS CALLED FROM THE DATA LINK LAYER (BELOW) TO ACCEPT A PACKET FOR THIS NODE, OR TO RE-ROUTE IT TO THE INTENDED DESTINATION. */ int up_to_network(char *packet, size_t length, int arrived_on_link) { printf("up to network at hop %s \n", nodeinfo.nodename); NL_PACKET *p = (NL_PACKET *) packet; //if(p->traveled_hops_count < 1 || p->traveled_hops_count > MAXHOPS) //return 0; //++p->hopcount; /* took 1 hop to get here */ if(p->traveled_hops_count > 0 && p->traveled_hops_count<= MAXHOPS){ is_traveled_hop = 0; for(i=0; i<p->traveled_hops_count; ++i){ if(p->traveled_hops[i] == nodeinfo.nodenumber){ is_traveled_hop = 1; break; } } if(is_traveled_hop != 1){ printf("seqno %d pieceNumber %d src %d des %d current_hop %d\n", p->seqno, p->pieceNumber, p->src, p->dest, nodeinfo.address); printf("p->traveled_hops_count %d\n", p->traveled_hops_count); p->traveled_hops[p->traveled_hops_count++] = nodeinfo.nodenumber; mtu = linkinfo[arrived_on_link].mtu; p->trans_time += ((CnetTime)8000000 * mtu / linkinfo[arrived_on_link].bandwidth + linkinfo[arrived_on_link].propagationdelay)/mtu; //p->trans_time += linkinfo[arrived_on_link].costperframe; } else{ printf("seqno %d pieceNumber %d src %d des %d current_hop %d. This hop has been traveled\n", p->seqno, p->pieceNumber, p->src, p->dest, nodeinfo.address); printf("\n"); /*free(&p->traveled_hops); free(&p->msg); free(p); */ return 0; } } /* IS THIS PACKET IS FOR ME? */ if (p->dest == nodeinfo.address) { switch (p->kind) { case NL_DATA: if (p->seqno == NL_packetexpected(p->src)) { length = p->length; memcpy(rb[p->src], (char *) p->msg, length); rb[p->src] = rb[p->src] + length; packet_length[p->src] += length; printf("This piece traveled %d hops\n", p->traveled_hops_count); if (p->pieceEnd) { CnetAddr tmpaddr; //length = p->pieceNumber * (linkinfo[arrived_on_link].mtu // - PACKET_HEADER_SIZE) + p->length; length = packet_length[p->src]; int p_checksum = p->checksum; int checksum = CNET_ccitt( (unsigned char *) (receiveBuffer[p->src]), (int) length); if (p_checksum != checksum) { /***************************send back error ack**************/ //NL_savehopcount(p->src, p->hopcount, arrived_on_link); NL_savehopcount(p->src, p->trans_time, arrived_on_link); tmpaddr = p->src; /* swap src and dest addresses */ p->src = p->dest; p->dest = tmpaddr; p->kind = NL_ERR_ACK; //p->hopcount = 0; p->traveled_hops_count = 0; memset(p->traveled_hops, -1, MAXHOPS*sizeof(int)); p->trans_time = 0; p->length = 0; flood3(packet, PACKET_HEADER_SIZE, arrived_on_link, 0); return 0; /***************************end******************************/ } if (CNET_write_application(receiveBuffer[p->src], &length) == -1) { //source node should send this msg again if (cnet_errno == ER_CORRUPTFRAME) { printf("Warning: host %d received a corrupt packet (seqno = %d) from %d\n", nodeinfo.address, p->seqno, p->src); } else if (cnet_errno == ER_MISSINGMSG) { printf("Warning: host %d received a unordered packet (seqno = %d) from %d\n", nodeinfo.address, p->seqno, p->src); }else if (cnet_errno == ER_BADSIZE){ printf("Warning: host %d received a loss packet (seqno = %d) from %d\n", nodeinfo.address, p->seqno, p->src); } } else { printf("host %d received a correct packet (seqno = %d) from %d\n", nodeinfo.address, p->seqno, p->src); } rb[p->src] = &receiveBuffer[p->src][0]; packet_length[p->src] = 0; inc_NL_packetexpected(p->src); //NL_savehopcount(p->src, p->hopcount, arrived_on_link); NL_savehopcount(p->src, p->trans_time, arrived_on_link); //send a NL_ACK back to source host tmpaddr = p->src; /* swap src and dest addresses */ p->src = p->dest; p->dest = tmpaddr; p->kind = NL_ACK; //p->hopcount = 0; p->traveled_hops_count = 0; memset(p->traveled_hops, -1, MAXHOPS*sizeof(int)); p->trans_time = 0; p->length = 0; packet_length[p->src] = 0; //printf("right frame! up to app\n"); flood3(packet, PACKET_HEADER_SIZE, arrived_on_link, 0); //printf("send ack\n"); } } break; case NL_ACK: if (p->seqno == NL_ackexpected(p->src)) { //printf("ACK come!\n"); inc_NL_ackexpected(p->src); //NL_savehopcount(p->src, p->hopcount, arrived_on_link); NL_savehopcount(p->src, p->trans_time, arrived_on_link); CHECK(CNET_enable_application(p->src)); } break; case NL_ERR_ACK: printf("ERROR ACK!\n"); if (p->seqno == NL_ackexpected(p->src)) { //NL_savehopcount(p->src, p->hopcount, arrived_on_link); NL_savehopcount(p->src, p->trans_time, arrived_on_link); printf("packet %d (to %d) error!\n", p->seqno, p->src); NL_PACKET * packettoresend = get_last_packet(p->src); printf("length = %d seq = %d\n", packettoresend->length, packettoresend->seqno); int a = packettoresend->checksum; int b = CNET_ccitt((unsigned char *) (packettoresend->msg), (int) (packettoresend->length)); if (a == b) { printf("ok!\n"); } else printf("wrong!\n"); int len = PACKET_HEADER_SIZE + packettoresend->length; flood3((char *) packettoresend, len, 0, 0); } break; default: ; //printf("it's nothing!====================\n"); } } /* THIS PACKET IS FOR SOMEONE ELSE */ else { // printf("hopcount = %d\n", p->hopcount); // printf("MAXHOPS = %d\n", MAXHOPS); //if (p->hopcount < MAXHOPS) { /* if not too many hops... */ //printf("other's frame!\n"); //printf("piece for another node arrives\n"); length = p->length; memcpy(rb[p->src], (char *) p->msg, length); rb[p->src] = rb[p->src] + length; packet_length[p->src] += length; if (p->pieceEnd) { //printf("last piece for another node arrives\n"); //length = p->pieceNumber * (linkinfo[arrived_on_link].mtu // - PACKET_HEADER_SIZE) + p->length; length = packet_length[p->src]; //NL_savehopcount(p->src, p->hopcount, arrived_on_link); NL_savehopcount(p->src, p->trans_time, arrived_on_link); NL_PACKET wholePacket; wholePacket.src = p->src; wholePacket.dest = p->dest; wholePacket.kind = p->kind; wholePacket.seqno = p->seqno; //wholePacket.hopcount = p->hopcount; wholePacket.trans_time = p->trans_time; wholePacket.traveled_hops_count = p->traveled_hops_count; memcpy(wholePacket.traveled_hops,p->traveled_hops, MAXHOPS); wholePacket.pieceEnd = 0; wholePacket.pieceNumber = 0; wholePacket.length = length; packet_length[p->src] = 0; memcpy(wholePacket.msg, receiveBuffer[p->src], length); flood3((char *) &wholePacket, PACKET_SIZE(wholePacket), 0, arrived_on_link); rb[p->src] = &receiveBuffer[p->src][0]; } //} else // printf("drop\n"); /* silently drop */; } printf("\n"); return (0); }
///Worker Method ///Called when we receive data from one of our data link layers. ///Handles association with AP's and propagation of frames to other layers. static void up_from_dll(int link, const char *data, size_t length) { //fprintf(stdout, "\t%s: Received frame from dll on link\n", nodeinfo.nodename); if (length > sizeof(struct nl_packet)) { printf("\t%s: %zu is larger than a nl_packet! ignoring.\n",nodeinfo.nodename, length); return; } //Treat this frame as a network layer packet. struct nl_packet packet; memset(&packet, 0, sizeof(packet)); memcpy(&packet, data, length); fprintf(stdout, "\tPacket dest %i: \n\t %s's src: %i\n", packet.dest, nodeinfo.nodename, nodeinfo.address); fprintf(stdout, "\t%s: Received frame from dll on link %d\n\tfrom node %" PRId32 " for node %" PRId32 ".\n",nodeinfo.nodename, link, packet.src, packet.dest); uint32_t checksum = packet.checksum; packet.checksum = 0; fprintf(stdout,"\t%s has received a nl_packet of type ",nodeinfo.nodename); printFRAMEKIND(packet.type); fprintf(stdout,"\n"); if (CNET_crc32((unsigned char *)&packet, sizeof(packet)) != checksum) { fprintf(stdout, "\tChecksum failed.\n"); //return; } if (packet.dest != nodeinfo.address) { fprintf(stdout, "\tThat's not for me.\n"); fprintf(stdout, "\tPacket dest %i: \n\t %s's src: %i\n", packet.dest, nodeinfo.nodename, nodeinfo.address); fprintf(stdout, "\tPacket src %i: \n", packet.src); return; } // Check if we've seen this packet rece ntly. for (size_t i = 0; i < PACKET_MEMORY_LENGTH; ++i) { if (seen_checksums[i] == checksum) { fprintf(stdout, "\tI seem to have seen this recently.\n"); return; } } // Remember the checksum of this packet. seen_checksums[next_seen_checksum++] = checksum; next_seen_checksum %= PACKET_MEMORY_LENGTH; fprintf(stdout,"\t%s has received a nl_packet of type ",nodeinfo.nodename); printFRAMEKIND(packet.type); fprintf(stdout,"\n"); struct nl_packet assRequest; switch (packet.type) { case NL_DATA : fprintf(stdout, "\nDATA FRAME FOR %i @ %i, seq=%d \n", packet.dest, nodeinfo.address, packet.seq); if(packet.seq == frameexpected) { fprintf(stdout, "\tDATA Up to the application layer!\n"); size_t payload_length = packet.length; CHECK(CNET_write_application(packet.data, &payload_length)); frameexpected = 1 - frameexpected; } else { fprintf(stdout, "\tignored...\n"); } struct nl_packet ackPacket = (struct nl_packet){ .src = nodeinfo.address, .dest = packet.src, .length = NL_MAXDATA, .type = NL_ACK }; memcpy(ackPacket.data,nodeinfo.nodename,sizeof(nodeinfo.nodename)); ackPacket.seq = packet.seq; ackPacket.checksum = CNET_crc32((unsigned char *)&ackPacket, sizeof(ackPacket)); fprintf(stdout, "\tTransmitting an acknowledgement packet, seq = %i!*********************\n", ackPacket.seq); fprintf(stdout, "\n ackpacket src:%i dest:%i\n",ackPacket.src, ackPacket.dest); if(ackPacket.dest > 133) exit(0); transmit(&ackPacket); break; case NL_ACK : //CANCEL THE TIMEOUT FUNCTION AS WE HAVE RECEIVED THE ACKNOWLEEDGEMENT EXPECTED //If it has the expected sequence number if(packet.seq == ackexpected) { printf("\t\t\t\t**************ACK received, seq=%d\n", packet.seq); CHECK(CNET_stop_timer(data_timeout)); ackexpected = 1-ackexpected; CHECK(CNET_enable_application(ALLNODES)); } break; case NL_ASSREQ : if(timeAPset == false) { if(isAss == false) { fprintf(stdout, "\n%s is now associated with ap link %i\n", nodeinfo.nodename,packet.src); CHECK(CNET_stop_timer(probe_timer)); assRequest.type = NL_ASSREQ; assRequest.dest = packet.src; assRequest.src = nodeinfo.address; assRequest.length = NL_MAXDATA; assRequest.checksum = CNET_crc32((unsigned char *)&assRequest, sizeof(assRequest)); fprintf(stdout, "\ttoSend is of frame type "); printFRAMEKIND(toSend->type); fprintf(stdout, "\n"); fprintf(stdout, "\n%s Is ASSOCIATED!**********\n",nodeinfo.nodename); if(assRequest.dest > 133) exit(0); //DOING THINGS timeAPset = true; isAss = true; transmit(&assRequest); CHECK(CNET_enable_application(ALLNODES)); } else { fprintf(stderr, "HOLY CRAP BATMAN! I'M REASSOCIATING!\n"); //exit(EXIT_FAILURE);; isAss = true; CHECK(CNET_stop_timer(probe_timer)); } timeAPset = nodeinfo.time_of_day.sec; } break; default : fprintf(stdout, "\tFollowing default\n"); exit(0); // Send this packet to the application layer. fprintf(stdout, "\tUp to the application layer!\n"); size_t payload_length = packet.length; CHECK(CNET_write_application(packet.data, &payload_length)); break; } } ///Event Handler ///Called when this mobile node's application layer has generated a new message. ///Proceeds to transmit the generated message. static EVENT_HANDLER(application_ready) { fprintf(stdout, "\t%s's application later ready, creating new message.\n\t Max data: %i, Type: %" PRId32".\n",nodeinfo.nodename, NL_MAXDATA, NL_DATA); toSend->src = nodeinfo.address; toSend->length = NL_MAXDATA; toSend->type = NL_DATA; toSend->seq = nextframetosend; printf( " THE NEXT FRAME TO SEND IS %i\n", nextframetosend); struct nl_packet temp = (struct nl_packet){ .src = nodeinfo.address, .length = NL_MAXDATA, }; //update toSend CHECK(CNET_read_application(&temp.dest, temp.data, &temp.length)); memcpy(&(toSend->dest),&temp.dest,sizeof(temp.dest)); memcpy(&(toSend->data), &temp.data, temp.length); toSend->length = temp.length; fprintf(stdout, "\ntoSend dest:%i\n", toSend->dest); fprintf(stdout, "\tAppready: toSend is of frame type "); printFRAMEKIND(toSend->type); fprintf(stdout, "\n"); toSend->checksum = CNET_crc32((unsigned char *)&toSend, sizeof(toSend)); fprintf(stdout, "\t%s: Generated message for % " PRId32 ",\n\t attempting to transmit\n",nodeinfo.nodename, toSend->dest); CHECK(CNET_disable_application(ALLNODES)); transmit(toSend); if(toSend->type != NL_DATA) { fprintf(stderr, "\t%s toSend is not DATA!\n",nodeinfo.nodename); exit(0); } // CNET_start_timer(EV_TIMER2, 1, 0); nextframetosend = 1-nextframetosend; fprintf(stdout, "\tPacket transmitted successfully.\n"); } ///Event Handler ///Creates a new probe packet and sends it to transmit for propagation. ///This packet is used to discover access points and find an appropriate one ///for association. ///It then starts a timer to ensure that if there is no response, an additional ///probe is sent after a period of time. ///The timer is stopped once an acknowledgement is received and the mobile device ///is considered 'associated' with an access point. static EVENT_HANDLER(probe) { probe_timer = CNET_start_timer(EV_TIMER3, 5000000, 0); fprintf(stdout, "\n%s Probing...\n", nodeinfo.nodename); struct nl_packet packet = (struct nl_packet){ .src = nodeinfo.address, .length = NL_MAXDATA, }; memcpy(packet.data,nodeinfo.nodename,sizeof(nodeinfo.nodename)); packet.type = NL_PROBE; packet.checksum = CNET_crc32((unsigned char *)&packet, sizeof(packet)); //create broadcast address CnetNICaddr wifi_dest; CHECK(CNET_parse_nicaddr(wifi_dest, "ff:ff:ff:ff:ff:ff")); uint16_t packet_length = NL_PACKET_LENGTH(packet); CHECK(CNET_disable_application(ALLNODES)); dll_wifi_write(dll_states[1], wifi_dest, (char *)&packet, packet_length); } static EVENT_HANDLER(timeouts) { printf("timeout, seq=%d\n", ackexpected); transmit(toSend); }
void network_send(){ if(queue_nitems(msg_queue) == 0){ CNET_start_timer(EV_TIMER0, 100000, 0); return; // do nothing } //Fragment each message into a small unit and send along the link designated by the routing table size_t len = 0; next = queue_peek(msg_queue, &len); CnetAddr dest = next->dest; int dest_number = find_nodenumber(dest); //get link to send from the routing table int currLink = find_link(dest); //printf("Link to send is : %d\n", currLink); if(queue_nitems(links[currLink].sender) > 0){ //free(next); //printf("Some items in SENDER queue!\n"); CNET_start_timer(EV_TIMER0, 100000, 0); return; // do nothing } //Remove the topmost message from the queue next = queue_remove(msg_queue, &len); links[currLink].msg_in_sender_Q = node_buffer[dest_number].mesg_seq_no_to_generate; //printf("Message is to be processed! To be sent to %d from %d and size %d and message number is %d\n", dest, nodeinfo.address, len, mesg_seq_no); //printf("Creating frames for message #%d\n", mesg_seq_no); int int_len = len - MESSAGE_HEADER_SIZE; char *data_ptr; data_ptr = &next->data[0]; //printf("Message is to be processed! To be sent to %d from %d and size %d and message is %s.\n", dest, nodeinfo.address, len, data); //Enable application is message queue grows too small if(queue_nitems(msg_queue) < MAX_MSG_QUEUE_SIZE/2){ application_enabled = true; CNET_enable_application(ALLNODES); } size_t frame_len = table[dest_number].min_mtu - FRAME_HEADER_SIZE; // removing the length occupied by the destination address in the MESSAGE //printf("Min mtu - FRAME_HEADER_SIZE is : %d Initial message size was %d, after removing dest part it is %d\n", frame_len, len, int_len); //queue packets up int seqno; for(seqno = 0; int_len > 0; seqno++){ FRAME f; memset(&f.payload.data[0], '\0', MAX_MESSAGE_SIZE); f.payload.kind = DL_DATA; f.payload.source = nodeinfo.address; f.payload.dest = dest; f.payload.mesg_seq_no = node_buffer[dest_number].mesg_seq_no_to_generate; f.payload.len = (int_len < frame_len) ? int_len : frame_len; f.payload.flag_offset = (int_len <= frame_len) ? 1 : 0; getcurrtime(&f.payload.timestamp); f.payload.A = seqno; memcpy(&f.payload.data[0], data_ptr, f.payload.len); //printf("Length of frame to send is : %d and the payload is %s (before adding to queue)\n", strlen(f.payload.data) + FRAME_HEADER_SIZE, f.payload.data); f.checksum = 0; f.checksum = CNET_ccitt((unsigned char *)&f, (int)(f.payload.len) + FRAME_HEADER_SIZE); len = f.payload.len + FRAME_HEADER_SIZE; queue_add(links[currLink].sender, &f, len); int_len = int_len - frame_len; data_ptr = data_ptr + frame_len; } printf("Message read from application layer destined for address %d | size %d | msg #%d | # frames %d \n", dest, len - MESSAGE_HEADER_SIZE, node_buffer[dest_number].mesg_seq_no_to_generate, seqno); //printf("Created %d frames\n", seqno); node_buffer[dest_number].mesg_seq_no_to_generate++; for(int i = 0; i < seqno; i++) links[currLink].ack_received[i] = false; schedule_and_send(currLink); CNET_start_timer(EV_TIMER0, 100000, 0); }
/* up_to_network() IS CALLED FROM THE DATA LINK LAYER (BELOW) TO ACCEPT A PACKET FOR THIS NODE, OR TO RE-ROUTE IT TO THE INTENDED DESTINATION. */ int up_to_network(char *packet, size_t length, int arrived_on_link) { //printf("up to network at hop %d\n", nodeinfo.address); NL_PACKET *p = (NL_PACKET *) packet; if (p->src == nodeinfo.address) { printf("drop a packet at %d, src = %d, des = %d, seqno = %d\n\n", nodeinfo.address, p->src, p->dest, p->seqno); return 0; } //printf("up to network at %d (from %d to %d)\n", nodeinfo.address, p->src, p->dest); ++p->hopcount; /* took 1 hop to get here */ mtu = linkinfo[arrived_on_link].mtu; p->trans_time += ((CnetTime) 8000 * 1000 * mtu / linkinfo[arrived_on_link].bandwidth + linkinfo[arrived_on_link].propagationdelay) * 100 / mtu; /* IS THIS PACKET IS FOR ME? */ if (p->dest == nodeinfo.address) { switch (p->kind) { case NL_DATA: if (p->seqno == NL_packetexpected(p->src)) { //length = p->length; //memcpy(rb[p->src], (char *) p->msg, length); //rb[p->src] = rb[p->src] + length; //packet_length[p->src] += length; RB_save_msg_link(p, arrived_on_link); if (p->pieceEnd) { RB_copy_whole_msg_link(p, arrived_on_link); up_to_application(p, arrived_on_link); return 0; } } break; case NL_ACK: if (p->seqno == NL_ackexpected(p->src)) { ////("ACK come!\n"); inc_NL_ackexpected(p->src); NL_savehopcount(p->src, p->trans_time, arrived_on_link); NL_set_has_resent(p->src, 0); CHECK(CNET_enable_application(p->src)); } break; case NL_ERR_ACK: printf("NL_ERR_ACK!\n"); if (p->seqno == NL_ackexpected(p->src)) { if (NL_get_has_resent(p->src) == 0) { NL_savehopcount(p->src, p->trans_time, arrived_on_link); NL_PACKET * packettoresend = get_last_packet(p->src); printf( "src = %d, des = %d, seqno = %d, send_length = %d, checksum = %d\n", packettoresend->src, packettoresend->dest, packettoresend->seqno, packettoresend->length, packettoresend->checksum); printf("resend it\n"); int len = PACKET_HEADER_SIZE + packettoresend->length; packettoresend->is_resent = 1; NL_set_has_resent(p->src, 1); //NL_inc_resent_times(p->src); // for debug flood((char *) packettoresend, len, 0, 0); } else { printf( "this packet has already been resent, dont resent it again\n"); } } else { printf( "this packet has already been correct received, dont resent it again\n"); } printf("\n"); break; case NL_ERR_ACK_RESENT: printf("NL_ERR_ACK_RESENT!\n"); if (p->seqno == NL_ackexpected(p->src)) { NL_savehopcount(p->src, p->trans_time, arrived_on_link); NL_PACKET * packettoresend = get_last_packet(p->src); printf( "resend a resent packet, src = %d, des = %d, seqno = %d, send_length = %d, checksum = %d\n", packettoresend->src, packettoresend->dest, packettoresend->seqno, packettoresend->length, packettoresend->checksum); //printf("this packet has been resent %d times before this time\n", NL_get_resent_times(p->src)); //for debug //NL_inc_resent_times(p->src); // for debug int len = PACKET_HEADER_SIZE + packettoresend->length; packettoresend->is_resent = 1; flood((char *) packettoresend, len, 0, 0); } else { printf( "this packet has already been correct received, dont resent it again\n"); } printf("\n"); break; default: //("it's nothing!====================\n"); break; } } /* THIS PACKET IS FOR SOMEONE ELSE */ else { if (p->hopcount < MAXHOPS) { /* if not too many hops... */ //length = p->length; //memcpy(rb[p->src], (char *) p->msg, length); //rb[p->src] = rb[p->src] + length; if(p->kind != NL_DATA){ route_packet(p, arrived_on_link); } else{ RB_save_msg_link(p, arrived_on_link); printf("finish new rb save msg\n"); if (p->pieceEnd){ RB_copy_whole_msg_link(p, arrived_on_link); printf("finish copy whole msg\n"); printf("p->length after copy = %d\n", p->length); route_packet(p, arrived_on_link); } } } else {/* silently drop */; } } return 0; }