/* down_to_network() RECEIVES NEW MESSAGES FROM THE APPLICATION LAYER AND PREPARES THEM FOR TRANSMISSION TO OTHER NODES. */ static EVENT_HANDLER( down_to_network) { NL_PACKET p; p.length = sizeof(p.msg); CHECK(CNET_read_application(&p.dest, p.msg, &p.length)); CNET_disable_application(p.dest); p.src = nodeinfo.address; p.kind = NL_DATA; p.seqno = NL_nextpackettosend(p.dest); p.hopcount = 0; p.pieceNumber = 0; p.pieceEnd = 0; p.src_packet_length = (int) p.length; p.checksum = CNET_ccitt((unsigned char *) (p.msg), p.src_packet_length); p.trans_time = 0; p.is_resent = 0; //lastPacket = &p; printf( "packet generated, src = %d, des = %d, seqno = %d, send_length = %d, checksum = %d\n\n", nodeinfo.address, p.dest, p.seqno, p.length, p.checksum); flood((char *) &p, PACKET_SIZE(p), 0, 0); update_last_packet(&p); }
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); }
/* down_to_network() RECEIVES NEW MESSAGES FROM THE APPLICATION LAYER AND PREPARES THEM FOR TRANSMISSION TO OTHER NODES. */ static EVENT_HANDLER(down_to_network) { //printf("down_to_network\n"); NL_PACKET p; p.length = sizeof(p.msg); //printf("p.length = %d, MAX_MESSAGE_SIZE = %d", p.length, MAX_MESSAGE_SIZE); CHECK(CNET_read_application(&p.dest, p.msg, &p.length)); CNET_disable_application(p.dest); p.src = nodeinfo.address; p.kind = NL_DATA; //p.hopcount = 0; memset(p.traveled_hops, -1, MAXHOPS*sizeof(int)); p.traveled_hops[0] = nodeinfo.nodenumber; p.traveled_hops_count = 1; p.trans_time = 0; p.seqno = NL_nextpackettosend(p.dest); p.pieceNumber = 0; p.pieceEnd = 0; p.checksum = CNET_ccitt((unsigned char *) (p.msg), p.length); lastPacket = &p; update_last_packet(&p); printf("Packet generated at host %d, des %d\n\n", nodeinfo.address, p.dest); flood3((char *) &p, PACKET_SIZE(p), 0, 0); }
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); }
static void push_message(MSG msg, size_t msgLength){ if(queue_nitems(msg_queue) < MAX_MSG_QUEUE_SIZE){ //printf("Pushing a message for %d with length %d\n", msg.dest, msgLength); queue_add(msg_queue, &msg, msgLength); } if(queue_nitems(msg_queue) == MAX_MSG_QUEUE_SIZE){ CNET_disable_application(nodeinfo.address); } network_send(); }
static EVENT_HANDLER(application_ready){ MSG msg; size_t len = sizeof(MSG); CHECK(CNET_read_application(&msg.dest, &msg.data, &len)); queue_add(msg_queue, &msg, len + MESSAGE_HEADER_SIZE); if(queue_nitems(msg_queue) == MAX_MSG_QUEUE_SIZE){ CHECK(CNET_disable_application(ALLNODES)); app_enabled = false; } }
static EVENT_HANDLER(application_ready) { CnetAddr destaddr; lastlength = sizeof(MSG); CHECK(CNET_read_application(&destaddr, (char *)lastmsg, &lastlength)); CNET_disable_application(ALLNODES); transmit_frame(lastmsg, DATA, lastlength, nextframetosend); nextframetosend = 1-nextframetosend; }
/* down_to_network() RECEIVES NEW MESSAGES FROM THE APPLICATION LAYER AND PREPARES THEM FOR TRANSMISSION TO OTHER NODES. */ static EVENT_HANDLER( down_to_network) { NL_PACKET p; NL_PACKET test; p.length = sizeof(p.msg); CHECK(CNET_read_application(&p.dest, p.msg, &p.length)); CNET_disable_application(p.dest); p.src = nodeinfo.address; p.kind = NL_DATA; p.seqno = NL_nextpackettosend(p.dest); p.hopcount = 0; p.pieceStartPosition = 0; p.pieceEnd = 0; p.src_packet_length = (int) p.length; p.checksum = CNET_crc32((unsigned char *) (p.msg), p.src_packet_length); p.piece_checksum = CNET_crc32((unsigned char *) (p.msg), p.src_packet_length); p.trans_time = 0; p.is_resent = 0; test.src = nodeinfo.address; test.dest = p.dest; test.kind = NL_TEST; test.hopcount = 0; test.seqno = 0; test.min_mtu = INT_MAX; test.length = 0; test.pieceStartPosition = 0; test.src_packet_length = PACKET_HEADER_SIZE; test.checksum = 0; test.piece_checksum = 0; test.trans_time = 0; test.is_resent = 0; NL_updatelastsendtest(&test); update_last_packet(&p); flood_test((char *) &test, PACKET_HEADER_SIZE, 0, 0); //TODO: please inform the mtu from src to dest by using pathfinder packet //size_t mtu_from_src_to_dest = 96; //piece_to_flood((char *) &p, mtu_from_src_to_dest); }
///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; } }
static void datalink_down(FRAME frame, int inLink, int outLink) { // FRAME IS BEING FORWARDED if ( outLink != 0 ) { // MORE ROOM TO SEND SO TRANSMIT FRAME if (numInWindow[outLink - 1] < MAX_SEQ) { transmit_ack(inLink, frame.seq); inc(&frameExpected[inLink - 1]); frame.seq = nextFrameToSend[outLink - 1]; // STORE FRAME IN THE OUTGOING WINDOW window[outLink - 1][nextFrameToSend[outLink - 1]] = frame; numInWindow[outLink - 1] += 1; // TRANSMIT THE FRAME OUT frame.link = outLink; transmit_frame(frame); inc(&nextFrameToSend[outLink - 1]); } // NOT ENOUGH ROOM IN WINDOW TO SEND else { if (numInBuffer[outLink - 1] < MAX_SEQ + 1) { transmit_ack(inLink, frame.seq); inc(&frameExpected[inLink - 1]); // STORE FRAME IN THE BUFFER buffer[outLink - 1][bufferBounds[outLink - 1][1]] = frame; numInBuffer[outLink - 1] += 1; inc(&bufferBounds[outLink - 1][1]); printf("\t\t\t\t\tADDED TO BUFFER\n"); } else { // IF WINDOW AND BUFFER BOTH FULL, CAN'T DO ANYTHING. DROP printf("\t\t\t\t\tBUFFER FULL, FRAME DROPPED\n"); } } // IF THE WINDOW IS CURRENTLY FULL if (numInWindow[outLink - 1] >= MAX_SEQ) { // DISABLE GENERATION OF NEW MESSAGES WHILE WINDOW IS FULL for ( int ii = 0; ii < NUM_NODES; ii++ ) { // ONLY DISABLE MESSAGES FOR DESTINATION ROUTED THROUGH outLink if ( routingTable[nodeinfo.nodenumber][ii] == outLink ) { CNET_disable_application( ii ); printf("\t\t\t\t\tDISABLED APPLICATION\n"); CNET_set_LED( outLink-1, "red" ); } } } } else { // MORE ROOM TO SEND SO TRANSMIT FRAME if (numInWindow[inLink - 1] < MAX_SEQ) { // GET SEQUENCE NUMBER, STORE FRAME IN WINDOW, INC WINDOW NUMBER frame.seq = nextFrameToSend[inLink - 1]; window[inLink - 1][nextFrameToSend[inLink - 1]] = frame; numInWindow[inLink - 1] += 1; // CALL DLL TO TRANSMIT FRAME frame.link = inLink; transmit_frame(frame); inc(&nextFrameToSend[inLink - 1]); } // NOT ENOUGH ROOM IN WINDOW TO SEND else { // ADD FRAME TO THE BUFFER WAITING TO SEND OUT buffer[inLink - 1][bufferBounds[inLink - 1][1]] = frame; numInBuffer[inLink - 1] += 1; inc(&bufferBounds[inLink - 1][1]); // PRINT DESTINATION OF MESSAGE, LINK, INDEX IN BUFFER printf("\nADDED TO BUFFER\n"); printf("DEST:\t%s\n", nodenames[frame.destNode]); printf("LINK:\t%d\n", inLink); printf("INDEX:\t%d\n", bufferBounds[inLink - 1][1] - 1); } // IF THE WINDOW IS CURRENTLY FULL if (numInWindow[inLink - 1] >= MAX_SEQ) { // ONLY DISABLE MESSAGES FOR DESTINATION ROUTED THROUGH outLink for ( int ii = 0; ii < NUM_NODES; ii++ ) { if ( routingTable[nodeinfo.nodenumber][ii] == inLink ) { CNET_disable_application( ii ); printf("DISABLE APPLICATION FOR %s\n", nodenames[ii] ); CNET_set_LED( inLink-1 , "red" ); } } } } }
///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); }