static void set_timer(FRAME frame) { CnetTimerID timerID; CnetTime timeout; int link = frame.link; int seqNum = frame.seq; // CALCULATE TIMEOUT VALUE BASED ON BANDWIDTH + PROP DELAY timeout = FRAME_SIZE(frame)*((CnetTime)MAGIC_NUM / linkinfo[link].bandwidth); timeout += linkinfo[link].propagationdelay; // START SPECIFIC TIMER FOR CORRECT LINK. EVERY LINK USES A SEPERATE // TIMER QUEUE switch (link) { case 1: timerID = CNET_start_timer(EV_TIMER1, T_MOD * timeout, (CnetData)seqNum); break; case 2: timerID = CNET_start_timer(EV_TIMER2, T_MOD * timeout, (CnetData)seqNum); break; case 3: timerID = CNET_start_timer(EV_TIMER3, T_MOD * timeout, (CnetData)seqNum); break; case 4: timerID = CNET_start_timer(EV_TIMER4, T_MOD * timeout, (CnetData)seqNum); break; } // STORE TIMER ID IN THE TIMER ARRAY FOR LATER REFERENCE timers[link - 1][seqNum] = timerID; }
///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); }
//----------------------------------------------------------------------------- // flush a queue void flush_datalink_queue(CnetEvent ev, CnetTimerID t1, CnetData data) { int current_link = (int) data; if (queue_nitems(output_queues[current_link]) > 0) { // take a first datalink frame size_t containter_len; DTG_CONTAINER * dtg_container = queue_remove(output_queues[current_link], &containter_len); // write datalink frame to the link DL_FRAME frame; size_t datagram_length = dtg_container->len; frame.checksum = dtg_container->checksum; memcpy(&frame.data, dtg_container->data, datagram_length); size_t frame_length = datagram_length + DL_FRAME_HEADER_SIZE; int link = dtg_container->link; CHECK(CNET_write_physical(link, (char *)&frame, &frame_length)); //compute timeout for the link double bandwidth = linkinfo[link].bandwidth; CnetTime timeout = 1+8000005.0*(frame_length / bandwidth); datalink_timers[link] = CNET_start_timer(EV_DATALINK_FLUSH, timeout, current_link); free(dtg_container); } else { datalink_timers[current_link] = NULLTIMER; } }
static void transmit_frame(){ if(strcmp(nodeinfo.nodename,"Dehradun")==0 && flag_sen == 1 && count < 1000 ){ char *frame=(char *)malloc(64*sizeof(char)); size_t length=64; int i=0; if(SN==0){ sprintf(frame, "%dmessage %d is %s",SN, count+1, messages[0]); } else{ sprintf(frame, "%dmessage %d is %s",SN, count+1, messages[1]); } printf("\nsending %u bytes of ' %s ': ", length, frame); for(i=1;i<9;i++){ check[i]=frame[i]; } CHECK(CNET_write_physical(1, frame, &length)); id=CNET_start_timer(EV_TIMER1,3600,0); flag_sen=0; } else if(strcmp(nodeinfo.nodename,"KGP")==0 && flag_rec == 1){ char *ack=(char *)malloc(48*sizeof(char)); size_t length=48; sprintf(ack, "%d",RN); CHECK(CNET_write_physical(1, ack, &length)); flag_rec =0; printf("\n Acknowledgement send "); } }
//----------------------------------------------------------------------------- // send a route request void send_route_request(CnetAddr destaddr) { if (pending_route_requests[destaddr] == NULLTIMER) { ROUTE_PACKET req_packet; req_packet.type = RREQ; req_packet.source = nodeinfo.address; req_packet.dest = destaddr; req_packet.hop_count = 0; req_packet.total_delay = 0; req_packet.req_id = route_req_id; req_packet.min_mtu = 0; route_req_id++; uint16_t request_size = ROUTE_PACKET_SIZE(req_packet); DATAGRAM r_packet = alloc_datagram(__ROUTING__, nodeinfo.address, destaddr, (char*) &req_packet, request_size); // start timer for pending route request pending_route_requests[destaddr] = CNET_start_timer(EV_ROUTE_PENDING_TIMER, ROUTE_REQUEST_TIMEOUT, destaddr); route_notified[destaddr] = 0; // insert into local history table insert_local_history(req_packet.source,req_packet.dest, req_packet.req_id); broadcast_packet(r_packet, -1); } }
static EVENT_HANDLER(ready_app) { CnetAddr dest; int num_unack = next_frame - last_ack_recv; if(num_unack==(MAXSEQ+1)/2){ timer_wait = CNET_start_timer(EV_TIMER1, TIMEOUT, 0); CNET_disable_application(ALLNODES); return; } if(num_unack<0){ num_unack=MAXSEQ; } // if(trans_frame_state[next_frame%((MAXSEQ+1)/2)] == ACK_WAIT) // { // timer_wait = CNET_start_timer(EV_TIMER1, TIMEOUT, 0); // CNET_disable_application(ALLNODES); // return; // } trans_frame_state[next_frame] = ACK_WAIT; size_t length = MAX_MESSAGE_SIZE; CHECK(CNET_read_application(&dest, (char*) last_msg, &length)); frame_send(last_msg, length, next_frame); next_frame = (next_frame + 1) % (MAXSEQ + 1); }
static void down_to_transport(CnetEvent ev, CnetTimer timer, CnetData data) { /* our packet */ TR_PACKET p; /* destination address to pass to network layer */ CnetAddr temp; p.length = sizeof(p.msg); CHECK(CNET_read_application(&temp, p.msg, &p.length)); CNET_disable_application(temp); /* establish sequence number */ unsigned long seq = getSequence(temp); if( seq == -1) { addAddress(temp,0); p.sequence_number = 0; } else { unsigned long newseq = seq + p.length; setSequence(temp,newseq); p.sequence_number = newseq; } p.checksum = checksum_crc32( ((char*)&p)+sizeof(unsigned int) , TR_PACKET_SIZE(p) - sizeof(unsigned int)); down_to_network( (char*)&p , TR_PACKET_SIZE(p) , temp); /* enqueuePacket((char*)&p, TR_PACKET_SIZE(p), temp); */ CNET_start_timer(EV_TIMER1, 1000, (CnetData)1); }
void cc200_datalink_data_next(int link) { CnetTime timeout = sizeof(cc200_frame_t) * 8000000 / linkinfo[link].bandwidth + linkinfo[link].propagationdelay; timeout *= 3; CC200_CHECK0( cc200_link_timer_vector[link] = CNET_start_timer( cc200_link_event_vector[link], timeout, link ) ); CC200_PRINT( "starting timer %" PRId32 " for " CC200_LINK " at %" PRId64 " us", cc200_link_timer_vector[link], link, timeout ); cc200_physical_from_datalink( cc200_frame_queue[link]->head->data, link ); }
static void transmit_frame(MSG *msg, FRAMEKIND kind, size_t length, int seqno) { FRAME f; int link = 1; f.kind = kind; f.seq = seqno; f.checksum = 0; f.len = length; switch (kind) { case ACK : CHECK(CNET_set_wlancolour(link, "blue")); break; case DATA: { CnetTime timeout; CHECK(CNET_set_wlancolour(link, "red")); memcpy(&f.msg, (char *)msg, length); timeout = (FRAME_SIZE(f)*(CnetTime)8000000 / linkinfo[link].bandwidth + linkinfo[link].propagationdelay); timeout = 300000; lasttimer = CNET_start_timer(EV_TIMER1, 3 * timeout, 0); break; } } length = FRAME_SIZE(f); f.checksum = CNET_ccitt((unsigned char *)&f, length); CHECK(CNET_write_physical_reliable(link, (char *)&f, &length)); }
static EVENT_HANDLER(transmit) { WLAN_FRAME frame; int link = 1; // POPULATE A NEW FRAME do { frame.header.dest = CNET_rand() % NNODES; } while(frame.header.dest == nodeinfo.nodenumber); frame.header.src = nodeinfo.nodenumber; frame.header.prevpos = positions[nodeinfo.nodenumber]; // me! sprintf(frame.payload, "hello from %d", nodeinfo.nodenumber); frame.header.length = strlen(frame.payload) + 1; // send nul-byte too // TRANSMIT THE FRAME size_t len = sizeof(WLAN_HEADER) + frame.header.length; CHECK(CNET_write_physical_reliable(link, &frame, &len)); ++stats[0]; if(verbose) { fprintf(stdout, "\n%s: transmitting '%s' to %d\n", nodeinfo.nodename, frame.payload, frame.header.dest); } // SCHEDULE OUR NEXT TRANSMISSION CNET_start_timer(EV_TIMER1, TX_NEXT, 0); }
static EVENT_HANDLER(talking) { if(am_walking() == false) { size_t len = sizeof(int); fprintf(stdout,"%d: transmitting\n", nodeinfo.nodenumber); CHECK( CNET_write_physical_reliable(1, (char *)&nodeinfo.nodenumber, &len)); } CNET_start_timer(EV_TALKING, TALK_FREQUENCY, data); }
///Worker Method ///Called to send a nl_packet to an associated access point. ///If this device is not associated, we abort and manage association instead ///as there is nowhere to transmit the packet to. static int transmit(struct nl_packet *packet) { fprintf(stdout, "\tTransmitting.\n"); // Create a 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); uint16_t packet_length = sizeof(*packet); if(packet->type == NULL_FRAME) { fprintf(stderr, "\t%s is attempting to send a null packet!\n",nodeinfo.nodename); exit(0); } if(isAss == false) { fprintf(stdout, "\tWhoops! %s is not associated!\n\t Starting Probe\n", nodeinfo.nodename); // CHECK(CNET_disable_application(ALLNODES)); probe_timer = CNET_start_timer(EV_TIMER1, 100, 0); return 0; } else { fprintf(stdout, "\tAssociation is true, sending frame.\n"); fprintf(stdout, "\n packet src:%i dest:%i\n",packet->src, packet->dest); if(packet->dest > 133) exit(0); dll_wifi_write(dll_states[1], wifi_dest, (char *)packet, packet_length); if(packet->type == NL_DATA ) { CHECK(CNET_disable_application(ALLNODES)); printf(" DATA transmitted, seq=%d\n", packet->seq); data_timeout = CNET_start_timer(EV_TIMER2, CNET_rand() * 50000 + 500000, 0); /// one second wait time } return 1; } }
void setup_routing_table(){ if(!table_changed){ cleanup_and_start_app(); return; } //printf("Setting up the routing table\n"); table_changed = false; DATAGRAM dg; dg.source = dg.dest = nodeinfo.address; dg.fragOffset_nnSrc = dg.flagOffset_nnVia = nodeinfo.nodenumber; getCurrTime(&dg.timestamp); push_dg_for_routing(dg, n); n -= 2; CNET_start_timer(EV_TIMER9, 2000000, 0); }
static void timeout_test(CnetEvent ev, CnetTimerID timer, CnetData data) { CnetTime test_timeout; printf("======================\n"); printf("timeout_check!\n"); printf("======================\n"); int i; for (i = 0; i < NL_gettablesize(); i++) { if (NL_getminmtubyid(i) == 0) { flood_test((char *) NL_getlastsendtest(NL_getdestbyid(i)), PACKET_HEADER_SIZE, 0, 0); printf("resend last test dest = %d\n", NL_getdestbyid(i)); } } //printf("\n"); test_timeout = 75000; last_test_timeout_timer = CNET_start_timer(EV_TIMER3, test_timeout, 0); }
//----------------------------------------------------------------------------- // write a frame to the link void write_datalink(int link, char *datagram, uint32_t length) { DTG_CONTAINER container; container.len = length; container.link = link; container.checksum = CNET_ccitt((unsigned char *) datagram, (size_t)length); size_t datagram_length = length; memcpy(&container.data, datagram, datagram_length); // check if timer is null to avoid polling if (datalink_timers[link] == NULLTIMER) { CnetTime timeout_flush = 1; datalink_timers[link] = CNET_start_timer(EV_DATALINK_FLUSH, timeout_flush, link); } output_max[link] = max(output_max[link], queue_nitems(output_queues[link])); // add to the link queue if(queue_nitems(output_queues[link]) < 5000) { size_t container_length = DTG_CONTAINER_SIZE(container); queue_add(output_queues[link], &container, container_length); } }
void start_talking(void) { talk_tid = CNET_start_timer(EV_TALKING, 1000000, 0); }
static EVENT_HANDLER(walker) { static double dx = 0.0; static double dy = 0.0; static double newx = 0.0; static double newy = 0.0; static int nsteps = 0; CnetPosition now; CnetTime movenext; // IF PAUSED, WE NEED TO CHOOSE A NEW DESTINATION AND WALKING SPEED if(paused) { CnetPosition newdest; CHECK(CNET_get_position(&now, NULL)); // CHOOSE A NEW DESTINATION THAT DOESN'T REQUIRE WALKING THROUGH A WALL! do { int newspeed; double dist; newdest = now; do { choose_position(&newdest, MAX_WALK_DIST); } while(through_an_object(now, newdest)); dx = newdest.x - now.x; dy = newdest.y - now.y; dist = sqrt(dx*dx + dy*dy); // only walking in 2D newspeed = CNET_rand() % MAX_SPEED + 1; nsteps = dist / newspeed; } while(nsteps < 3); // ensure we'll take at least 3 steps //draw_walk(&now, &newdest); // CALCULATE MOVEMENTS PER STEP dx = (dx / nsteps); dy = (dy / nsteps); newx = now.x; newy = now.y; paused = false; // and off we go.... } // WE'RE WALKING; DO WE STILL HAVE SOME STEPS TO TAKE? if(nsteps > 0) { newx += dx; newy += dy; now.x = newx; now.y = newy; now.z = 0; CHECK(CNET_set_position(now)); paused = false; --nsteps; movenext = WALK_FREQUENCY; } // WE'VE FINISHED WALKING, SO WE PAUSE HERE FOR A WHILE else { paused = true; nsteps = 0; movenext = (CNET_rand() % (MAX_PAUSE-MIN_PAUSE) + MIN_PAUSE) * 1000000; } // RESCHEDULE THIS WALKING EVENT tid = CNET_start_timer(EV_WALKING, movenext, data); }
void start_walking(void) { CNET_stop_timer(tid); tid = CNET_start_timer(EV_WALKING, WALK_FREQUENCY, 0); }
void start_association(void) { ass_tid = CNET_start_timer(EV_ASSOCIATE, 1000000, 0); }
void start_timeout(void) { timeout_tid = CNET_start_timer(EV_TIMEOUT, 2000000, 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); }