struct list_node *list_check_node(const struct list_node *node, const char *abortstr) { const struct list_node *p, *n; int count = 0; for (p = node, n = node->next; n != node; p = n, n = n->next) { count++; if (n->prev != p) return corrupt(abortstr, node, n, count); } /* Check prev on head node. */ if (node->prev != p) return corrupt(abortstr, node, node, 0); return (struct list_node *)node; }
void fpage( char_data* ch, const char *text ) { char buf [ MAX_STRING_LENGTH ]; if( ch == NULL || ch->link == NULL ) return; format( buf, text ); strcat( buf, "\r\n" ); corrupt( buf, MAX_STRING_LENGTH, "Fpage" ); page( ch, buf ); }
/* * wts_salvage -- * Salvage testing. */ void wts_salvage(void) { int ret; /* Some data-sources don't support salvage. */ if (DATASOURCE("helium") || DATASOURCE("kvsbdb")) return; if (g.c_salvage == 0) return; /* * Save a copy of the interesting files so we can replay the salvage * step as necessary. */ if ((ret = system(g.home_salvage_copy)) != 0) die(ret, "salvage copy step failed"); /* Salvage, then verify. */ wts_open(g.home, 1, &g.wts_conn); salvage(); wts_verify("post-salvage verify"); wts_close(); /* * If no records were deleted, dump and compare against Berkeley DB. * (The problem with deleting records is salvage restores deleted * records if a page splits leaving a deleted record on one side of * the split, so we cannot depend on correctness in that case.) */ if (g.c_delete_pct == 0) wts_dump("salvage", SINGLETHREADED); /* Corrupt the file randomly, salvage, then verify. */ if (corrupt()) { wts_open(g.home, 1, &g.wts_conn); salvage(); wts_verify("post-corrupt-salvage verify"); wts_close(); } }
// Listens for an ack, returning the ack number. Returns -99 if timeout int listen_for_ack(int sockfd) { int recvlen; int ack_number = -99; struct packet receive; if (is_readable(sockfd)) { recvlen = recvfrom(sockfd, &receive, sizeof(receive), 0, NULL, NULL); if (should_lose_packet()) { if (receive.type == TYPE_ACK) printf("Simulated loss of ack # %d\n", receive.seq); else printf("Simulated loss of packet type %d. (Was expecting ACK).\n", receive.type); return -99; } if (should_corrupt_packet()) { if (receive.type == TYPE_ACK) printf("Simulated corruption of ack # %d\n", receive.seq); else printf("Simulated corruption of packet type %d. (Was expecting ACK).\n", receive.type); return -99; } if (corrupt(&receive)) { printf("Received actual corrupt packet\n"); return -99; } } else { return -99; } if (recvlen < 0) error("ERROR receiving ack from client"); if (receive.type != TYPE_ACK) { fprintf(stderr, "Expected ACK, received type %d", receive.type); return -99; } ack_number = receive.seq; printf("Received ack %d.\n", ack_number); return ack_number; }
int main(void) { struct sockaddr_in si_other; int s, slen=sizeof(si_other); char file_name[30]; char server[12]; int read_ret; char prog_mode; char intentional_corruption; int file_length_left; int file_length; int bytes_written = 0; int packet_count; int r,c,i,j; int random; char **data_storage; int sequence; int prev_sequence; FILE* fp; WSADATA wsa; //packet sent preceding the data containing information to initiate the file transfer struct data_packet send_data; struct data_packet receive_data; struct data_packet ACK0; struct data_packet ACK1; struct header_packet header; //initalize ACK0 memset(ACK0.data,'+',DATALEN); ACK0.sequence_number = 0; ACK0.packet_number = -1; ACK0.checksum = checksum((char*)&ACK0,sizeof(ACK0)); //initalize ACK1 memset(ACK0.data,'+',DATALEN); ACK1.sequence_number = 1; ACK1.packet_number = -1; ACK1.checksum = checksum((char*)&ACK1,sizeof(ACK1)); //Initialise winsock printf("\nInitialising Winsock..."); if (WSAStartup(MAKEWORD(2,2),&wsa) != 0) { printf("Failed. Error Code : %d",WSAGetLastError()); exit(EXIT_FAILURE); } printf("Initialised.\n"); //create socket if ( (s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == SOCKET_ERROR) { printf("socket() failed with error code : %d" , WSAGetLastError()); exit(EXIT_FAILURE); } printf("For localhost enter: 127.0.0.1 \n"); printf("Enter Server IP Address: "); scanf("%s", &server); //setup address structure memset((char *) &si_other, 0, sizeof(si_other)); si_other.sin_family = AF_INET; si_other.sin_port = htons(PORT); si_other.sin_addr.S_un.S_addr = inet_addr(server); //start communication while(1) { bytes_written = 0; packet_count = 0; sequence = 0; prev_sequence = 1; printf("Do you want to send a file? <y/n>: "); scanf(" %c", &prog_mode); printf("Do you want intentional data corruption? <y/n>: "); scanf(" %c", &intentional_corruption); if (intentional_corruption == 'y'){ printf("Options: \nACK packet bit-error = A\nData packet bit-error = B \n"); printf("Please enter your selection <A/B>: "); scanf(" %c", &intentional_corruption); } //client will receive a file if(prog_mode == 'n'){ printf("Enter file name to read on server : "); scanf("%s",header.file_name); printf("Enter file name to write on client : "); scanf("%s",file_name); fp = fopen(file_name,"wb"); //make first packet (header_packet) requesting file to be sent header.file_size = 0; header.mode = 'n'; header.packet_number = packet_count; header.intentional_corruption = intentional_corruption; header.checksum = checksum((char*)&header,sizeof(header)); printf("\n HEADER INFORMATION \n"); printf("packet number = %i \n",header.packet_number); //mode dictates whether the server should send or receive printf("mode = %c \n",header.mode); printf("File name = %s \n\n",header.file_name); //send header packet asking to send file send_packet((char*)&header,sizeof(struct header_packet),s,&si_other,slen); //wait for ACK for header printf("waiting for ACK from server \n"); receive_packet((char*)&receive_data,sizeof(struct data_packet),s,&si_other,slen); //in case of corrupt header packet or corrupt ACK while(corrupt(receive_data)||isACK(receive_data,prev_sequence)){ //resend the header packet send_packet((char*)&header,sizeof(struct header_packet),s,&si_other,slen); //look for new ACK from the server receive_packet((char*)&receive_data,sizeof(struct data_packet),s,&si_other,slen); } //notification for successful recepit of ACK if(isACK(receive_data,sequence) == 1){ printf("received ACK for header packet from server \n"); }else{ printf("ERROR: UNKNOWN DATA RECEIVED \n"); } //wait for return header packet from server indicating the file size printf("Waiting for header packet from client...\n"); //get header packet from socket receive_packet((char*)&header,sizeof(struct header_packet),s,&si_other,slen); //if header packet is corrupt send the previous sequence number ACK while(corrupt_h(header) == 1){ //resend the prev_sequence ACK packet send_packet((char*)&ACK1,sizeof(struct data_packet),s,&si_other,slen); //get a new header packet receive_packet((char*)&header,sizeof(struct header_packet),s,&si_other,slen); } //send ack printf("sending header acknowledgement \n"); send_packet((char*)&ACK0,sizeof(struct data_packet),s,&si_other,slen); printf("\n HEADER INFORMATION \n"); printf("packet number = %i \n",header.packet_number); printf("mode = %c \n",header.mode); printf("File size = %i \n",header.file_size); //Allocate array to hold data for packet reordering r = ((header.file_size-(header.file_size%(DATALEN)))/(DATALEN)); if((header.file_size%DATALEN)!=0){ r++; } c = DATALEN; data_storage = (char **)malloc(r * sizeof(char*)); for (i=0; i<r; i++){ data_storage[i] = (char *)malloc(c * sizeof(char)); } //initalize array for (i = 0; i < r; i++) for (j = 0; j < c; j++) data_storage[i][j] = '+'; printf("Waiting for data...\n"); fflush(stdout); //try to receive some data, stop when you recieve all the data which the file contains while(bytes_written < header.file_size){ //clear out the buffer each time to eliminate extraneous data on the last packet memset(receive_data.data,0xFF, DATALEN); //listen for packet and store into data_packet struct receive_packet((char*)&receive_data,sizeof(struct data_packet),s,&si_other,slen); //intentionally corrupt data packet if user selected if(header.intentional_corruption == 'B'){ random = rand() % 10; //randomly choose data packets and invalidate the sequence number if(random == 7){ receive_data.sequence_number = 49; } } //if data is corrupt or has the wrong sequence number while(corrupt(receive_data)||receive_data.sequence_number == prev_sequence){ //resend the prev_sequence ACK packet if(prev_sequence == 0){ send_packet((char*)&ACK0,sizeof(struct data_packet),s,&si_other,slen); }else{ send_packet((char*)&ACK1,sizeof(struct data_packet),s,&si_other,slen); } //look for new data from client receive_packet((char*)&receive_data,sizeof(struct data_packet),s,&si_other,slen); } //If the correct sequence data packet was sucessfully received if(receive_data.sequence_number == sequence){ printf("received data%i from client \n", sequence); }else{ printf("ERROR: UNKNOWN DATA RECEIVED \n"); } //send the ACK packet to the client if(sequence == 0){ printf("Sending ACK0 to client \n"); send_packet((char*)&ACK0,sizeof(struct data_packet),s,&si_other,slen); }else{ printf("Sending ACK1 to client \n"); send_packet((char*)&ACK1,sizeof(struct data_packet),s,&si_other,slen); } //copy data received into array to reorder packets memcpy(data_storage[receive_data.packet_number-1], receive_data.data, (DATALEN)); printf("packet number = %i \n", receive_data.packet_number); //print the data received data and origin printf("\n\n\nReceived packet from %s:%d \n", inet_ntoa(si_other.sin_addr), ntohs(si_other.sin_port)); printf("Data: %s\n\n\n" , receive_data.data); bytes_written = bytes_written + DATALEN; prev_sequence=sequence; sequence++; //when sequence number 1 is done go back to sequence number 0 if(sequence > 1){ sequence = 0; } } bytes_written = 0; //copy data into file in the correct order until the file is the correct size while(bytes_written != header.file_size){ //copy array for(i=0; i<r; i++){ bytes_written = bytes_written + DATALEN; printf("Writing Packet#: %i \n", i+1); if(bytes_written < header.file_size){ fwrite(data_storage[i],1,DATALEN,fp); printf("bytes_written: %i \n",bytes_written); //special case for the last packet which isen't DATALEN bytes long }else{ bytes_written = bytes_written - (DATALEN); printf("bytes_written: %i \n",bytes_written); fwrite(data_storage[i],1,(header.file_size - bytes_written),fp); printf("PARTIAL PACKET WRITE \n"); printf("Wrote: %i \n",(header.file_size - bytes_written)); bytes_written += (header.file_size - bytes_written); } } } printf("Receive Done. \n"); printf("header File size = %i \n",header.file_size); printf("End of Transmission \n"); fclose(fp); //free data storage array for (i=0; i<r; i++){ free(data_storage[i]); } free(data_storage); } //client will send a file if(prog_mode == 'y'){ // get file name to be sent from user printf("Enter file name to read on client : "); scanf("%s",file_name); printf("Enter file name to write on server : "); scanf("%s",header.file_name); fp = fopen(file_name,"rb"); if (fp == NULL){ printf("Invalid file name \n"); exit(EXIT_FAILURE); } //find length of the file fseek(fp, 0L, SEEK_END); file_length = ftell(fp); file_length_left = file_length; rewind(fp); //make first packet (header_packet) containing file length header.file_size = file_length; header.mode = 'y'; header.packet_number = packet_count; header.intentional_corruption = intentional_corruption; header.checksum = checksum((char*)&header, sizeof(header)); printf("\n HEADER INFORMATION \n"); printf("packet number = %i \n",header.packet_number); //mode dictates whether the server should send or receive printf("mode = %c \n",header.mode); printf("File size = %i \n\n",header.file_size); //send header packet send_packet((char*)&header,sizeof(struct header_packet),s,&si_other,slen); //wait for ACK for header printf("waiting for ACK from server \n"); receive_packet((char*)&receive_data,sizeof(struct data_packet),s,&si_other,slen); //in case of corrupt header packet or corrupt ACK while(corrupt(receive_data)||isACK(receive_data,prev_sequence)){ //resend the header packet send_packet((char*)&header,sizeof(struct header_packet),s,&si_other,slen); //look for new ACK from the server receive_packet((char*)&receive_data,sizeof(struct data_packet),s,&si_other,slen); } //notification for successful recepit of ACK if(isACK(receive_data,sequence) == 1){ printf("received ACK for header packet from server \n"); }else{ printf("ERROR: UNKNOWN DATA RECEIVED \n"); } //break up message into chunks for UDP packets while(file_length_left > 0){ packet_count++; memset(send_data.data,'\0', DATALEN); send_data.packet_number = packet_count; read_ret=fread(send_data.data, 1, (DATALEN), fp); if(read_ret != DATALEN && file_length_left>DATALEN){ printf("\n ERROR, did not read DATALEN \n"); printf("read_ret = %i \n", read_ret); } //insert sequence number send_data.sequence_number = sequence; //compute and store checksum into packet send_data.checksum = checksum((char*)&send_data, sizeof(send_data)); file_length_left = file_length_left - (DATALEN); printf("packet number = %i \n",send_data.packet_number); if(file_length_left > 0){ printf("file length left: %i \n", file_length_left); }else{ printf("file length left: 0 \n"); } //send the data_packet struct to the server send_packet((char*)&send_data,sizeof(struct data_packet),s,&si_other,slen); //look for ACK from the server printf("waiting for ACK%i from server \n", sequence); receive_packet((char*)&receive_data,sizeof(struct data_packet),s,&si_other,slen); //intentionally corrupt the received ACK packet if user selected if(intentional_corruption == 'A'){ random = rand() % 10; //randomly choose ACK packets and invalidate the sequence number if(random == 7){ receive_data.sequence_number = 69; } } //if the ACK packet is corrupted or wrong sequence ACK is received while(corrupt(receive_data)||isACK(receive_data,prev_sequence)){ printf("Resending Data packet \n"); //resend the data packet send_packet((char*)&send_data,sizeof(struct data_packet),s,&si_other,slen); //look for new ACK from the server printf("waiting for ACK%i from server \n", sequence); receive_packet((char*)&receive_data,sizeof(struct data_packet),s,&si_other,slen); } //If the correct ACK was sucessfully received if(isACK(receive_data,sequence) == 1){ printf("received ACK%i from server \n", sequence); }else{ printf("ERROR: UNKNOWN DATA RECEIVED \n"); } prev_sequence=sequence; sequence++; //when sequence number 1 is done go back to sequence number 0 if(sequence > 1){ sequence = 0; } } fclose(fp); } } closesocket(s); WSACleanup(); return 0; }
int main(int argc, char *argv[]) { int sockfd, newsockfd, portno, recvlen; struct sockaddr_in serv_addr, cli_addr; socklen_t clilen = sizeof(cli_addr); struct packet receive; FILE * f; char * filename; int i; int cwndsize; struct packet *packets; // initialize random number generator srand(time(NULL)); if (argc == 2) { portno = atoi(argv[1]); cwndsize = 1; lossprob = 0; corruptprob = 0; } else if (argc < 5) { fprintf(stderr,"usage: %s <port number> <CWnd size> <loss probability> <corruption probability>\n", argv[0]); exit(1); } else { portno = atoi(argv[1]); cwndsize = atoi(argv[2]); lossprob = atof(argv[3]); corruptprob = atof(argv[4]); } printf("CWnd size: %d\nProbLoss: %f\nProbCorrupt: %f\nServer listing on port %d...\n\n", cwndsize, lossprob, corruptprob, portno); // create UDP socket sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (sockfd < 0) error("ERROR opening socket"); // fill in address info memset((char *) &serv_addr, 0, sizeof(serv_addr)); //reset memory serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = INADDR_ANY; serv_addr.sin_port = htons(portno); // bind socket to IP address and port number if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) error("ERROR on binding"); // scan for requests from client while (1) { // receieve request from client recvlen = recvfrom(sockfd, &receive, sizeof(receive), 0, (struct sockaddr *) &cli_addr, &clilen); if (should_lose_packet()) { if (receive.type == TYPE_REQUEST) printf("Simulated loss of request packet\n"); else printf("Simulated loss of unexpected packet\n"); continue; } if (should_corrupt_packet()) { if (receive.type == TYPE_REQUEST) printf("Simulated corruption of request packet\n"); else printf("Simulated corruption of unexpected packet\n"); continue; } if (corrupt(&receive)) { printf("Received actual corrupt packet\n"); continue; } if (recvlen < 0) error("ERROR receiving data from client"); printf("Received request (%d bytes) for %s\n", receive.length, receive.data); // open file if (receive.type == TYPE_REQUEST) { f = fopen(receive.data, "r"); if (f == NULL) error("ERROR opening file"); } else { fprintf(stderr, "Packet not of type request\n"); continue; } packets = prepare_packets(f); rdt_send_packets(packets, sockfd, cli_addr, clilen, cwndsize); free(packets); printf("Finished sending file. Listening for new request...\n\n"); } // never reached if we never break out of the loop but whatever close(sockfd); return 0; }
/// \brief Corrupt a buffer with random errors. /// This is used only for testing to make sure we can cleanly /// handle corruption of the packets. /// /// @param factor A divisor to adjust how many errors are created. /// /// @return nothing int Buffer::corrupt() { return corrupt(10); }
MemBlock* MemoryPool::alloc(const size_t length) throw (OOM_EXCEPTION) { MutexLockGuard guard(mutex, "MemoryPool::alloc"); // If this is a small block, look for it there if (length <= threshold) { unsigned int slot = length / roundingSize; MemBlock* block; if (threadShared) { while (block = freeObjects[slot]) { if (freeObjects[slot].compareExchange(block, block->next)) { #ifdef MEM_DEBUG if (slot != block->length / roundingSize) corrupt("length trashed for block in slot"); #endif return block; } } } else { block = freeObjects[slot]; if (block) { freeObjects[slot] = (MemBlock*) block->pool; #ifdef MEM_DEBUG if (slot != block->length / roundingSize) corrupt("length trashed for block in slot"); #endif return block; } } // See if some other hunk has unallocated space to use MemSmallHunk* hunk; for (hunk = smallHunks; hunk; hunk = hunk->nextHunk) { if (length <= hunk->spaceRemaining) { MemBlock* block = (MemBlock*) hunk->memory; hunk->memory += length; hunk->spaceRemaining -= length; block->length = length; return block; } } // No good so far. Time for a new hunk hunk = (MemSmallHunk*) allocRaw(minAllocation); hunk->length = minAllocation - 16; hunk->nextHunk = smallHunks; smallHunks = hunk; size_t l = ROUNDUP(sizeof(MemSmallHunk), sizeof(double)); block = (MemBlock*) ((UCHAR*) hunk + l); hunk->spaceRemaining = minAllocation - length - l; hunk->memory = (UCHAR*) block + length; block->length = length; return block; } /* * OK, we've got a "big block" on on hands. To maximize confusing, the indicated * length of a free big block is the length of MemHeader plus body, explicitly * excluding the MemFreeBlock and MemBigHeader fields. [MemHeader::length] <---- MemBlock ----> *--------------*----------*---------* | MemBigHeader | MemHeader | Body | *--------------*----------*---------* <---- MemBigObject -----> *--------------*----------*---------------* | MemBigHeader | MemHeader | MemFreeBlock | *--------------*----------*---------------* <--------------- MemFreeBlock ----------> */ MemFreeBlock* freeBlock; for (freeBlock = freeBlocks.nextLarger; freeBlock != &freeBlocks; freeBlock = freeBlock->nextLarger) { if (freeBlock->memHeader.length >= length) { remove(freeBlock); MemBlock* block = (MemBlock*) &freeBlock->memHeader; // Compute length (MemHeader + body) for new free block unsigned int tail = block->length - length; // If there isn't room to split off a new free block, allocate the whole thing if (tail < sizeof(MemFreeBlock)) { block->pool = this; return block; } // Otherwise, chop up the block MemBigObject* newBlock = freeBlock; freeBlock = (MemFreeBlock*) ((UCHAR*) block + length); freeBlock->memHeader.length = tail - sizeof(MemBigObject); block->length = length; block->pool = this; if (freeBlock->next = newBlock->next) freeBlock->next->prior = freeBlock; newBlock->next = freeBlock; freeBlock->prior = newBlock; freeBlock->memHeader.pool = NULL; // indicate block is free insert(freeBlock); return block; } } // Didn't find existing space -- allocate new hunk size_t hunkLength = sizeof(MemBigHunk) + sizeof(MemBigHeader) + length; size_t freeSpace = 0; // If the hunk size is sufficient below minAllocation, allocate extra space if (hunkLength + sizeof(MemBigObject) + threshold < minAllocation) { hunkLength = minAllocation; //freeSpace = hunkLength - 2 * sizeof(MemBigObject) - length; freeSpace = hunkLength - sizeof(MemBigHunk) - 2 * sizeof(MemBigHeader) - length; } // Allocate the new hunk MemBigHunk* hunk = (MemBigHunk*) allocRaw(hunkLength); hunk->nextHunk = bigHunks; bigHunks = hunk; hunk->length = hunkLength; // Create the new block MemBigObject* newBlock = (MemBigObject*) &hunk->blocks; newBlock->prior = NULL; newBlock->next = NULL; MemBlock* block = (MemBlock*) &newBlock->memHeader; block->pool = this; block->length = length; // If there is space left over, create a free block if (freeSpace) { freeBlock = (MemFreeBlock*) ((UCHAR*) block + length); freeBlock->memHeader.length = freeSpace; freeBlock->memHeader.pool = NULL; freeBlock->next = NULL; freeBlock->prior = newBlock; newBlock->next = freeBlock; insert(freeBlock); } return block; }
TEST(RecordIOTest, Randomized) { SCOPED_TRACE(to<std::string>("Random seed is ", FLAGS_random_seed)); std::mt19937 rnd(FLAGS_random_seed); size_t recordCount = std::uniform_int_distribution<uint32_t>(30, 300)(rnd); std::uniform_int_distribution<uint32_t> recordSizeDist(1, 3 << 16); std::uniform_int_distribution<uint32_t> charDist(0, 255); std::uniform_int_distribution<uint32_t> junkDist(0, 1 << 20); // corrupt 1/5 of all records std::uniform_int_distribution<uint32_t> corruptDist(0, 4); std::vector<std::pair<fbstring, off_t>> records; std::vector<off_t> corruptPositions; records.reserve(recordCount); TemporaryFile file; fbstring record; // Recreate the writer multiple times so we test that we create a // continuous stream for (size_t i = 0; i < 3; ++i) { RecordIOWriter writer(File(file.fd())); for (size_t j = 0; j < recordCount; ++j) { off_t beginPos = writer.filePos(); record.clear(); size_t recordSize = recordSizeDist(rnd); record.reserve(recordSize); for (size_t k = 0; k < recordSize; ++k) { record.push_back(charDist(rnd)); } writer.write(iobufs({record})); bool corrupt = (corruptDist(rnd) == 0); if (corrupt) { // Corrupt one random byte in the record (including header) std::uniform_int_distribution<uint32_t> corruptByteDist( 0, recordSize + recordio_helpers::headerSize() - 1); off_t corruptRel = corruptByteDist(rnd); VLOG(1) << "n=" << records.size() << " bpos=" << beginPos << " rsize=" << record.size() << " corrupt rel=" << corruptRel << " abs=" << beginPos + corruptRel; corruptPositions.push_back(beginPos + corruptRel); } else { VLOG(2) << "n=" << records.size() << " bpos=" << beginPos << " rsize=" << record.size() << " good"; records.emplace_back(std::move(record), beginPos); } } VLOG(1) << "n=" << records.size() << " close abs=" << writer.filePos(); } for (auto& pos : corruptPositions) { corrupt(file.fd(), pos); } { size_t i = 0; RecordIOReader reader(File(file.fd())); for (auto& r : reader) { SCOPED_TRACE(i); ASSERT_LT(i, records.size()); EXPECT_EQ(records[i].first, sp(r.first)); EXPECT_EQ(records[i].second, r.second); ++i; } EXPECT_EQ(records.size(), i); } }
int main() { SOCKET s; struct sockaddr_in server, si_other; int slen; WSADATA wsa; int read_ret; int file_length_left; int file_length; int random; int bytes_written = 0; int packet_count = 0; int r,c,i,j; int sequence; int prev_sequence; char **data_storage; FILE* fp; struct data_packet receive_data; struct data_packet send_data; struct data_packet ACK0; struct data_packet ACK1; struct header_packet header; //initalize ACK0 memset(ACK0.data,'+',DATALEN); ACK0.sequence_number = 0; ACK0.packet_number = -1; ACK0.checksum = data_CSI(ACK0); //initalize ACK1 memset(ACK1.data,'+',DATALEN); ACK1.sequence_number = 1; ACK1.packet_number = -1; ACK1.checksum = data_CSI(ACK1); // ACK1.checksum = checksumAndInvert((char*)&ACK1,sizeof(ACK1)); slen = sizeof(si_other) ; //Initialise winsock printf("\nInitialising Winsock..."); if (WSAStartup(MAKEWORD(2,2),&wsa) != 0) { printf("Failed. Error Code : %d",WSAGetLastError()); exit(EXIT_FAILURE); } printf("Initialised.\n"); //Create a socket if((s = socket(AF_INET , SOCK_DGRAM , IPPROTO_UDP)) == INVALID_SOCKET) { printf("Could not create socket : %d" , WSAGetLastError()); } printf("Socket created.\n"); //Prepare the sockaddr_in structure server.sin_family = AF_INET; server.sin_addr.s_addr = INADDR_ANY; server.sin_port = htons( PORT ); //Bind if( bind(s ,(struct sockaddr *)&server , sizeof(server)) == SOCKET_ERROR) { printf("Bind failed with error code : %d" , WSAGetLastError()); exit(EXIT_FAILURE); } puts("Bind done \n"); //keep listening for data while(1){ bytes_written = 0; packet_count = 0; sequence = 0; prev_sequence = 1; //look for header packet from client to determine send/receive printf("Waiting for header packet from client...\n"); //wait for header packet receive_packet((char*)&header,sizeof(struct header_packet),s,&si_other,slen); printf("\n HEADER INFORMATION \n"); printf("packet number = %i \n",header.packet_number); //mode dictates whether the server should send or receive printf("mode = %c \n",header.mode); printf("File name = %s \n\n",header.file_name); printf("Computed = %d Checksum = %u\n", header_CSI(header), header.checksum); //if header packet is corrupt send the previous sequence number ACK while(corrupt_h(header) == 1){ //resend the prev_sequence ACK packet send_packet((char*)&ACK1,sizeof(struct data_packet),s,&si_other,slen); //get a new header packet receive_packet((char*)&header,sizeof(struct header_packet),s,&si_other,slen); } //send ack printf("sending header acknowledgement \n"); send_packet((char*)&ACK0,sizeof(struct data_packet),s,&si_other,slen); printf("\n HEADER INFORMATION \n"); printf("packet number = %i \n",header.packet_number); //mode dictates whether the server should send or receive printf("mode = %c \n",header.mode); printf("File size = %i \n",header.file_size); //Server will be sending a file if(header.mode == 'n'){ // get file name to be sent from header packet fp = fopen(header.file_name,"rb"); if (fp == NULL) { printf("Invalid file name \n"); exit(EXIT_FAILURE); } //find length of the file fseek(fp, 0L, SEEK_END); file_length = ftell(fp); file_length_left = file_length; rewind(fp); //make another packet in response to client's (header_packet) to transmit necessary data for file transfer header.file_size = file_length; header.mode = 'n'; header.packet_number = packet_count; header.checksum = header_CSI(header); printf("\n HEADER INFORMATION \n"); printf("packet number = %i \n",header.packet_number); //mode dictates whether the server should send or receive printf("mode = %c \n",header.mode); printf("File size = %i \n\n",header.file_size); //send header packet send_packet((char*)&header,sizeof(struct header_packet),s,&si_other,slen); //wait for ACK for header printf("waiting for ACK from client \n"); receive_packet((char*)&receive_data,sizeof(struct data_packet),s,&si_other,slen); //in case of corrupt header packet or corrupt/wrong ACK while(corrupt(receive_data)||isACK(receive_data,prev_sequence)){ //resend the header packet send_packet((char*)&header,sizeof(struct header_packet),s,&si_other,slen); //look for new ACK from the server receive_packet((char*)&receive_data,sizeof(struct data_packet),s,&si_other,slen); } //notification for successful recepit of ACK if(isACK(receive_data,sequence) == 1){ printf("received ACK for header packet from client \n"); }else{ printf("ERROR: UNKNOWN DATA RECEIVED \n"); } while(file_length_left > 0){ memset(send_data.data,'\0', DATALEN); packet_count++; send_data.packet_number = packet_count; read_ret=fread(send_data.data, 1, DATALEN, fp); if(read_ret != DATALEN && file_length_left>DATALEN){ printf("\n ERROR, did not write DATALEN \n"); } file_length_left = file_length_left - (DATALEN); printf("packet number = %i \n",send_data.packet_number); if(file_length_left > 0){ printf("file length left: %i \n", file_length_left); }else{ printf("file length left: 0 \n"); } //insert sequence number send_data.sequence_number = sequence; //compute and store checksum into packet send_data.checksum = data_CSI(send_data); //send the data packet send_packet((char*)&send_data,sizeof(struct data_packet),s,&si_other,slen); //look for ACK from the server printf("waiting for ACK%i from server \n", sequence); receive_packet((char*)&receive_data,sizeof(struct data_packet),s,&si_other,slen); //intentionally corrupt the received ACK packet if user selected if(header.intentional_corruption == 'A'){ random = rand() % 10; //randomly choose ACK packets and invalidate the sequence number if(random == 7){ receive_data.sequence_number = 49; } } //if the packet is corrupted or wrong sequence ACK is received while(corrupt(receive_data)||isACK(receive_data,prev_sequence)){ printf("CORRUPT OR WRONG SEQUENCE ACK PACKET RECEIVED \n"); printf("Resending Data packet \n \n"); //resend the data packet send_packet((char*)&send_data,sizeof(struct data_packet),s,&si_other,slen); //look for new ACK from the server printf("waiting for ACK%i from server \n", sequence); receive_packet((char*)&receive_data,sizeof(struct data_packet),s,&si_other,slen); } //If the correct ACK was sucessfully received if(isACK(receive_data,sequence) == 1){ printf("received ACK%i from client \n", sequence); }else{ printf("ERROR: UNKNOWN DATA RECEIVED \n"); } prev_sequence=sequence; sequence++; //when sequence number 1 is done go back to sequence number 0 if(sequence > 1){ sequence = 0; } } } //server will receive a file if(header.mode == 'y'){ //Allocate array to hold data for packet reordering //calculate rows and columns of array r = ((header.file_size-(header.file_size%(DATALEN)))/(DATALEN)); if((header.file_size%DATALEN)!=0){ r++; } c = DATALEN; data_storage = (char **)malloc(r * sizeof(char*)); for (i=0; i<r; i++){ data_storage[i] = (char *)malloc(c * sizeof(char)); } //initalize array for (i = 0; i < r; i++) for (j = 0; j < c; j++) data_storage[i][j] = '+'; fp = fopen(header.file_name,"wb"); printf("Waiting for data...\n"); fflush(stdout); //try to receive some data, stop when you recieve all the data which the file contains while(bytes_written < header.file_size){ //clear out the buffer each time to eliminate extraneous data on the last packet memset(receive_data.data,0xFF, DATALEN); //look for data from client receive_packet((char*)&receive_data,sizeof(struct data_packet),s,&si_other,slen); //intentionally corrupt data packet if user selected if(header.intentional_corruption == 'B'){ random = rand() % 10; //randomly choose data packets and invalidate the sequence number if(random == 7){ receive_data.sequence_number = 49; } } //if data is corrupt or has the previous sequence number while(corrupt(receive_data)||receive_data.sequence_number == prev_sequence){ //resend the prev_sequence ACK packet printf("CORRUPT OR WRONG SEQUENCE DATA PACKET RECEIVED \n"); printf("RESENDING PREVIOUS ACK \n\n"); if(prev_sequence == 0){ send_packet((char*)&ACK0,sizeof(struct data_packet),s,&si_other,slen); }else{ send_packet((char*)&ACK1,sizeof(struct data_packet),s,&si_other,slen); } //look for new data from client receive_packet((char*)&receive_data,sizeof(struct data_packet),s,&si_other,slen); } //If the correct sequence data packet was sucessfully received if(receive_data.sequence_number == sequence){ printf("received data%i from client \n", sequence); }else{ printf("ERROR: UNKNOWN DATA RECEIVED \n"); } //send the ACK packet to the client if(sequence == 0){ printf("Sending ACK0 to client \n"); send_packet((char*)&ACK0,sizeof(struct data_packet),s,&si_other,slen); }else{ printf("Sending ACK1 to client \n"); send_packet((char*)&ACK1,sizeof(struct data_packet),s,&si_other,slen); } //copy data received into array to reorder packets memcpy(data_storage[receive_data.packet_number-1], receive_data.data, (DATALEN)); printf("packet_number = %i \n", receive_data.packet_number); //print the data received and origin printf("\n\n\nReceived packet from %s:%d \n", inet_ntoa(si_other.sin_addr), ntohs(si_other.sin_port)); printf("Data: %s\n\n\n" , receive_data.data); bytes_written = bytes_written + DATALEN; prev_sequence=sequence; sequence++; //when sequence number 1 is done go back to sequence number 0 if(sequence > 1){ sequence = 0; } } bytes_written = 0; while(bytes_written != header.file_size){ //copy array into file for(i=0; i<r; i++){ bytes_written = bytes_written + DATALEN; printf("Writing Packet#: %i \n", i+1); if(bytes_written < header.file_size){ fwrite(data_storage[i],1,DATALEN,fp); printf("bytes_written: %i \n",bytes_written); }else{ bytes_written = bytes_written - (DATALEN); printf("bytes_written: %i \n",bytes_written); fwrite(data_storage[i],1,(header.file_size - bytes_written),fp); printf("PARTIAL PACKET WRITE \n"); printf("Wrote: %i \n",(header.file_size - bytes_written)); bytes_written += (header.file_size - bytes_written); } } } printf("Receive Done. \n"); printf("header File size = %i \n",header.file_size); printf("End of Transmission \n"); fclose(fp); //free data storage array for (i=0; i<r; i++){ free(data_storage[i]); } free(data_storage); } if(header.mode != 'y' && header.mode != 'n'){ printf("HEADER ERROR, invalid mode! \n"); return 0; } } closesocket(s); WSACleanup(); return 0; }
int main() { SOCKET s; struct sockaddr_in server, si_other; int slen; WSADATA wsa; int read_ret; int file_length_left; int file_length; int random; int sequence; int bytes_written = 0; int packet_count = 0; int r,c,i,j; char **data_storage; int GBN_lower; int GBN_upper; struct data_packet* send_packets; FILE* fp; int* timers; int timeout_indicator; int corrupt_status; int no_ACK_indicator; int dropped_count; int start_time; struct data_packet receive_data; struct data_packet send_data; struct data_packet ACK; struct header_packet header; int recv_status; //initalize ACK memset(ACK.data,'+',DATALEN); ACK.packet_number = 0; ACK.checksum = data_CSI(ACK); slen = sizeof(si_other) ; //Initialise winsock printf("\nInitialising Winsock..."); if (WSAStartup(MAKEWORD(2,2),&wsa) != 0) { printf("Failed. Error Code : %d",WSAGetLastError()); exit(EXIT_FAILURE); } printf("Initialised.\n"); //Create a socket if((s = socket(AF_INET , SOCK_DGRAM , IPPROTO_UDP)) == INVALID_SOCKET) { printf("Could not create socket : %d" , WSAGetLastError()); } printf("Socket created.\n"); //Prepare the sockaddr_in structure server.sin_family = AF_INET; server.sin_addr.s_addr = INADDR_ANY; server.sin_port = htons( PORT ); //Bind if( bind(s ,(struct sockaddr *)&server , sizeof(server)) == SOCKET_ERROR) { printf("Bind failed with error code : %d" , WSAGetLastError()); exit(EXIT_FAILURE); } puts("Bind done \n"); //keep listening for data while(1){ if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout_0, sizeof(timeout_0)) == SOCKET_ERROR) { printf("setsockopt() failed with error code : %d" , WSAGetLastError()); } timeout_indicator = 0; bytes_written = 0; packet_count = 0; sequence = 0; //look for header packet from client to determine send/receive printf("Waiting for header packet from client...\n"); //wait for header packet receive_packet((char*)&header,sizeof(struct header_packet),s,&si_other,slen); printf("\n HEADER INFORMATION \n"); printf("packet number = %i \n",header.packet_number); //mode dictates whether the server should send or receive printf("mode = %c \n",header.mode); printf("File name = %s \n\n",header.file_name); //if header packet is corrupt do nothing and wait for sender to resend while(corrupt_h(header) == 1){ //get a new header packet receive_packet((char*)&header,sizeof(struct header_packet),s,&si_other,slen); } //send ack printf("sending header acknowledgement \n"); ACK.packet_number = packet_count; ACK.checksum = data_CSI(ACK); send_packet((char*)&ACK,sizeof(struct data_packet),s,&si_other,slen); printf("\n HEADER INFORMATION \n"); printf("packet number = %i \n",header.packet_number); //mode dictates whether the server should send or receive printf("mode = %c \n",header.mode); printf("File size = %i \n",header.file_size); //Server will be sending a file if(header.mode == 'n'){ start_time = clock(); //set socket timeout if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout_1, sizeof(timeout_1)) == SOCKET_ERROR) { printf("setsockopt() failed with error code : %d" , WSAGetLastError()); } // get file name to be sent from header packet fp = fopen(header.file_name,"rb"); if (fp == NULL) { printf("Invalid file name \n"); exit(EXIT_FAILURE); } //find length of the file fseek(fp, 0L, SEEK_END); file_length = ftell(fp); file_length_left = file_length; rewind(fp); //make another packet in response to client's (header_packet) to transmit necessary data for file transfer header.file_size = file_length; header.mode = 'n'; header.packet_number = packet_count; header.checksum = header_CSI(header); printf("\n HEADER INFORMATION \n"); printf("packet number = %i \n",header.packet_number); //mode dictates whether the server should send or receive printf("mode = %c \n",header.mode); printf("File size = %i \n\n",header.file_size); do { //send header packet send_packet((char*)&header,sizeof(struct header_packet),s,&si_other,slen); //wait for ACK for header printf("looking for ACK from client \n"); //in case of corrupt header packet or corrupt/wrong ACK } while(receive_packet((char*)&receive_data,sizeof(struct data_packet),s,&si_other,slen) == -1 || corrupt(receive_data) || !isACK(receive_data,packet_count)); //notification for successful recepit of ACK if(isACK(receive_data,packet_count) == 1){ printf("received ACK for header packet from client \n"); }else{ printf("ERROR: UNKNOWN DATA RECEIVED \n"); } //calculate number of spaces in array needed to hold all the data packets r = ((header.file_size-(header.file_size%(DATALEN)))/(DATALEN)); if((header.file_size%DATALEN)!=0){ r++; } //make array to hold all the data packets send_packets = (struct data_packet*)malloc(r * sizeof(struct data_packet)); timers = (int*)malloc(r * sizeof(int)); GBN_lower = 0; while(file_length_left > 0){ packet_count++; memset(send_data.data,'\0', DATALEN); send_data.packet_number = packet_count; read_ret=fread(send_data.data, 1, DATALEN, fp); if(read_ret != DATALEN && file_length_left>DATALEN){ printf("\n ERROR, did not write DATALEN \n"); } //compute and store checksum into packet send_data.checksum = data_CSI(send_data); file_length_left = file_length_left - (DATALEN); printf("packet number = %i \n",send_data.packet_number); if(file_length_left > 0){ printf("file length left: %i \n", file_length_left); }else{ printf("file length left: 0 \n"); } send_packets[GBN_lower] = send_data; GBN_lower++; } packet_count = 1; //send all the data packets while( receive_data.packet_number != r ){ if(packet_count == 1){ GBN_lower = 1; GBN_upper = header.window; printf("Initalized...GBN_lower = %i and GBN_upper = %i \n", GBN_lower, GBN_upper); } while(packet_count <= GBN_upper){ send_data = send_packets[packet_count - 1]; printf("Sending Packet %i \n", packet_count); //send the data_packet struct to the server send_packet((char*)&send_data,sizeof(struct data_packet),s,&si_other,slen); timers[packet_count - 1] = (int)clock(); packet_count++; } //check to see if any of the timers have expired for(i=GBN_lower; i<=GBN_upper; i++){ if( (clock() - timers[i-1]) > header.timer*CLOCKS_PER_SEC ){ printf("TIMEOUT DETECTED on packet %i, time = %f \n", i,(float)(clock() - timers[i-1])/(float)CLOCKS_PER_SEC); timeout_indicator = 1; } } //if the ACK packet is corrupted throw packet away and get new one from socket //if the timer for a certain ACK expires resend whole window if(timeout_indicator == 1){ printf("TIMEOUT DETECTED: RESENDING WINDOW\n"); packet_count = GBN_lower; while(packet_count <= GBN_upper){ send_data = send_packets[packet_count - 1]; printf("Timeout: Sending Packet %i \n", packet_count); //send the data_packet struct to the server send_packet((char*)&send_data,sizeof(struct data_packet),s,&si_other,slen); timers[packet_count - 1] = (int)clock(); packet_count++; } } timeout_indicator = 0; recv_status=0; i=0; //pull as many ACKs off of the socket as possible and process while(recv_status != -1){ //look for ACK from the server recv_status = receive_packet((char*)&receive_data,sizeof(struct data_packet),s,&si_other,slen); //intentionally corrupt the received ACK packet if user selected if(header.intentional_corruption == 'A'){ random = rand() % 100; //randomly choose ACK packets and invalidate the sequence number if(random <= header.corruption && receive_data.packet_number != GBN_upper){ receive_data.packet_number = 0; } } if(recv_status == -1 && i == 0 && corrupt_status < 2 && no_ACK_indicator < 1 ){ printf("received no ACK from the server \n"); no_ACK_indicator++; } if(recv_status > 0){ printf("received ACK%i from server \n", receive_data.packet_number); } if(corrupt(receive_data)){ if(corrupt_status == 0){ printf("CORRUPT ACK PACKET RECEIVED \n"); printf("corrupt = %i, sequence = %i \n", corrupt(receive_data), receive_data.packet_number); printf("Threw away, looking for new ACK packet \n"); } corrupt_status++; } //ACK all packets equal to and less than the ACK# (cumulative ACK) //and don't slide the window longer than the bytes in the file if( receive_data.packet_number >= GBN_lower && GBN_upper < r){ GBN_lower = receive_data.packet_number+1; GBN_upper = GBN_lower+(header.window-1); if(GBN_upper > r){ GBN_upper = r; } printf(" GBN_lower = %i, GBN_upper = %i \n", GBN_lower, GBN_upper); corrupt_status = 0; no_ACK_indicator = 0; dropped_count = 0; } i++; } if(corrupt_status < 2 && no_ACK_indicator < 1) printf("\n\n\n\n"); } free(timers); free(send_packets); printf("The transfer took %f seconds \n", (float)(clock()-start_time)/(float)CLOCKS_PER_SEC); } //server will receive a file if(header.mode == 'y'){ //set socket timeout to zero if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout_0, sizeof(timeout_0)) == SOCKET_ERROR) { printf("setsockopt() failed with error code : %d" , WSAGetLastError()); } //Allocate array to hold data for packet reordering //calculate rows and columns of array r = ((header.file_size-(header.file_size%(DATALEN)))/(DATALEN)); if((header.file_size%DATALEN)!=0){ r++; } c = DATALEN; data_storage = (char **)malloc(r * sizeof(char*)); for (i=0; i<r; i++){ data_storage[i] = (char *)malloc(c * sizeof(char)); } //initalize array for (i = 0; i < r; i++) for (j = 0; j < c; j++) data_storage[i][j] = '+'; fp = fopen(header.file_name,"wb"); printf("Waiting for data...\n"); fflush(stdout); //try to receive some data, stop when you recieve all the data which the file contains while(bytes_written < header.file_size){ sequence++; //clear out the buffer each time to eliminate extraneous data on the last packet memset(receive_data.data,0xFF, DATALEN); //look for data from client receive_packet((char*)&receive_data,sizeof(struct data_packet),s,&si_other,slen); //intentionally corrupt data packet if user selected if(header.intentional_corruption == 'B'){ random = rand() % 100; //randomly choose data packets and invalidate the sequence number if(random <= header.corruption){ receive_data.packet_number = 0; } } //if data is corrupt or has some sequence number other than expected resend previous ACK while(corrupt(receive_data)||receive_data.packet_number != sequence){ printf("CORRUPT OR WRONG SEQUENCE DATA PACKET RECEIVED, packet = %i, sequence = %i \n",receive_data.packet_number,sequence); printf("RESENDING ACK FOR LAST PACKET \n\n"); ACK.packet_number = sequence-1; ACK.checksum = data_CSI(ACK); printf("Sending ACK %i to client \n", sequence-1); send_packet((char*)&ACK,sizeof(struct data_packet),s,&si_other,slen); //look for new data from client receive_packet((char*)&receive_data,sizeof(struct data_packet),s,&si_other,slen); } //If the correct sequence data packet was sucessfully received if(receive_data.packet_number == sequence){ printf("received data%i from client \n", sequence); }else{ printf("ERROR: UNKNOWN DATA RECEIVED \n"); } //send the ACK packet to the client ACK.packet_number = sequence; ACK.checksum = data_CSI(ACK); printf("Sending ACK %i to client \n", sequence); send_packet((char*)&ACK,sizeof(struct data_packet),s,&si_other,slen); //copy data received into array to reorder packets memcpy(data_storage[receive_data.packet_number-1], receive_data.data, (DATALEN)); printf("packet_number = %i \n", receive_data.packet_number); //print the data received and origin printf("\n\n\nReceived packet from %s:%d \n", inet_ntoa(si_other.sin_addr), ntohs(si_other.sin_port)); printf("Data: %s\n\n\n" , receive_data.data); bytes_written = bytes_written + DATALEN; } bytes_written = 0; while(bytes_written != header.file_size){ //copy array into file for(i=0; i<r; i++){ bytes_written = bytes_written + DATALEN; printf("Writing Packet#: %i \n", i+1); if(bytes_written < header.file_size){ fwrite(data_storage[i],1,DATALEN,fp); printf("bytes_written: %i \n",bytes_written); }else{ bytes_written = bytes_written - (DATALEN); printf("bytes_written: %i \n",bytes_written); fwrite(data_storage[i],1,(header.file_size - bytes_written),fp); printf("PARTIAL PACKET WRITE \n"); printf("Wrote: %i \n",(header.file_size - bytes_written)); bytes_written += (header.file_size - bytes_written); } } } printf("Receive Done. \n"); printf("header File size = %i \n",header.file_size); printf("End of Transmission \n"); fclose(fp); //free data storage array for (i=0; i<r; i++){ free(data_storage[i]); } free(data_storage); } if(header.mode != 'y' && header.mode != 'n'){ printf("HEADER ERROR, invalid mode! \n"); return 0; } } closesocket(s); WSACleanup(); return 0; }