void cc200_datalink_from_physical(cc200_frame_t frame, int link) { uint32_t alleged_checksum = frame.checksum; frame.checksum = 0; uint32_t actual_checksum = CNET_crc32( (void *) &frame, sizeof(frame) ); if (alleged_checksum == actual_checksum) { switch (frame.kind) { case CC200_DATA: CC200_PRINT( "data " CC200_SEQ CC200_FROM CC200_LINK, frame.sequence_number, link ); cc200_datalink_ack(frame.sequence_number, link); if ( frame.sequence_number == cc200_next_data_seq_expected[link] ) { cc200_next_data_seq_expected[link] ^= 1; cc200_network_from_datalink(frame.payload); } break; case CC200_ACK: CC200_PRINT( "ACK " CC200_SEQ CC200_FROM CC200_LINK, frame.sequence_number, link ); if ( frame.sequence_number == cc200_next_ack_seq_expected[link] ) { CC200_PRINT( "stopping timer %" PRId32 " for " CC200_LINK, cc200_link_timer_vector[link], link ); CC200_CHECK( CNET_stop_timer( cc200_link_timer_vector[link] ) ); cc200_list_node_free( cc200_list_remove( cc200_frame_queue[link], cc200_frame_queue[link]->head ) ); cc200_next_ack_seq_expected[link] ^= 1; if (cc200_frame_queue[link]->count > 0) { cc200_datalink_data_next(link); } } break; } } else { CC200_PRINT("bad frame" CC200_FROM CC200_LINK, link); } }
/* 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); }
void piece_to_flood(char *packet, size_t mtu_from_src_to_dest) { NL_PACKET *tempPacket = (NL_PACKET *) packet; size_t maxPieceLength = mtu_from_src_to_dest - PACKET_HEADER_SIZE; size_t tempLength = tempPacket->length; char *str = tempPacket->msg; NL_PACKET piecePacket; piecePacket.src = tempPacket->src; piecePacket.dest = tempPacket->dest; piecePacket.kind = tempPacket->kind; piecePacket.seqno = tempPacket->seqno; piecePacket.hopcount = tempPacket->hopcount; piecePacket.pieceStartPosition = 0; piecePacket.pieceEnd = 0; piecePacket.src_packet_length = tempPacket->src_packet_length; piecePacket.checksum = tempPacket->checksum; piecePacket.trans_time = tempPacket->trans_time; piecePacket.is_resent = tempPacket->is_resent; while (tempLength > maxPieceLength) { piecePacket.length = maxPieceLength; memcpy(piecePacket.msg, str, maxPieceLength); piecePacket.piece_checksum = CNET_crc32( (unsigned char *) (piecePacket.msg), piecePacket.length); flood((char *) &piecePacket, PACKET_SIZE(piecePacket), 0, 0); str = str + maxPieceLength; piecePacket.pieceStartPosition = piecePacket.pieceStartPosition + maxPieceLength; tempLength = tempLength - maxPieceLength; } piecePacket.pieceEnd = 1; piecePacket.length = tempLength; memcpy(piecePacket.msg, str, tempLength); piecePacket.piece_checksum = CNET_crc32( (unsigned char *) (piecePacket.msg), piecePacket.length); flood((char *) &piecePacket, PACKET_SIZE(piecePacket), 0, 0); }
void cc200_datalink_ack(cc200_byte sequence_number, int link) { CC200_PRINT( "ACK " CC200_SEQ CC200_TO CC200_LINK, sequence_number, link ); cc200_frame_t frame; frame.checksum = 0; frame.kind = CC200_ACK; frame.sequence_number = sequence_number; frame.checksum = CNET_crc32( (void *) &frame, sizeof(frame) ); cc200_physical_from_datalink(frame, link); }
void up_to_application(NL_PACKET *p, int arrived_on_link) { size_t length = p->pieceStartPosition + p->length; if (length != p->src_packet_length) return; uint32_t p_checksum = p->checksum; uint32_t checksum = CNET_crc32((unsigned char *) (p->msg), p->src_packet_length); if (p_checksum != checksum) { send_ack(p, arrived_on_link, 1); } else { // received a correct packet CHECK(CNET_write_application(p->msg, &length)); send_ack(p, arrived_on_link, 0); } }
void cc200_datalink_from_network(cc200_packet_t packet) { int link = cc200_routing_table[packet.source][packet.destination]; CC200_PRINT( "data " CC200_SEQ CC200_TO CC200_LINK, cc200_next_seq_to_send[link], link ); cc200_frame_t frame; frame.checksum = 0; frame.kind = CC200_DATA; frame.sequence_number = cc200_next_seq_to_send[link]; memcpy(&frame.payload, &packet, sizeof(packet)); frame.checksum = CNET_crc32( (void *) &frame, sizeof(frame) ); cc200_next_seq_to_send[link] ^= 1; cc200_list_insert_after( cc200_frame_queue[link], frame, cc200_frame_queue[link]->tail ); if (cc200_frame_queue[link]->count == 1) cc200_datalink_data_next(link); }
///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); }