int bitcoin_parallel(const unsigned int processcount) { printf("\n\nStarting bitcoin_parallel\n"); // Start, end time unsigned long start,end; // Set start time start = current_time_millis(); // TODO: Create a Blockheader object and fill it with the initial data using the getWork Method Blockheader * b_header = malloc(sizeof(Blockheader)); getWork(b_header); // TODO: Split the calculation of the hashes into several segments based on the processcount int hashes_per_process = MAX_HASHES / processcount; for (int i = 0; i < processcount; i++) { Blockheader * temp = malloc(sizeof(Blockheader)); memcpy(temp, b_header, sizeof(Blockheader)); //temp->nonce += i * 0; } // TODO: Spawn a process for each segment // TODO: If a hash has the appropriate difficulty print it on the console using print_hash // TODO: Wait until all children finish before exiting end = current_time_millis(); printf("Calculation finished after %.3fs\n", (double) (end - start) / 1000); return EXIT_FAILURE; }
int bitcoin_parallel(const unsigned int processcount) { printf("\n\nStarting bitcoin_parallel\n"); // Start, end time unsigned long start,end; // Set start time start = current_time_millis(); // TODO: Create a Blockheader object and fill it with the initial data using the getWork Method Blockheader * blockheader = malloc(sizeof(Blockheader)); getWork(blockheader); // TODO: Split the calculation of the hashes into several segments based on the processcount int segment_size = ceil((double) MAX_HASHES / processcount); unsigned long starting_nonce = toulong(blockheader->nonce); //printf("starting_nonce am anfang: %ld\n", starting_nonce); // TODO: Spawn a process for each segment int pos = 0; int * child_pids = malloc(sizeof(int) * processcount); for (int i = 0; i < processcount; i++) { child_pids[i] = 0; } for (; pos < processcount; pos++) { child_pids[pos] = fork(); if (child_pids[pos] < 0) { printf("failed forking"); return EXIT_FAILURE; } if (child_pids[pos] == 0) { break; } } if (pos < processcount) { starting_nonce += pos * segment_size; char * n = to_reversed_char_arr(starting_nonce); memcpy(&(blockheader->nonce), n, sizeof(char) * 4); calculate_hash(blockheader, segment_size); return EXIT_SUCCESS; } int status; for (int i = 0; i < processcount; i++) { wait(&status); } end = current_time_millis(); printf("Calculation finished after %.3fs\n", (double) (end - start) / 1000); return EXIT_SUCCESS; }
/* Calculates Blockhashes in a simple loop. */ int bitcoin_simple() { printf("Starting bitcoin_simple\n"); // Start, end time unsigned long start,end; // Set start time start = current_time_millis(); // Creates and retrieves the Block-Header information Blockheader * blockheader = malloc(sizeof(Blockheader)); // The getWork method fills an empty Blockheader struct with all the neccesary information needed to calcualte the Hash of a Block. getWork(blockheader); // The nonce is the value that is incremented in each run to get a different hash value char * n = malloc(sizeof(char)*4); memcpy(n,&(blockheader->nonce),sizeof(char)*4); // The values in the Blockheader are actually in reverse byte order and need to be reversed in order to increment the nonce value. byte_reversal(n,sizeof(char)*4); // Convert the 4 byte long raw data into an unsinged long unsigned long starting_nonce = n[0] << 24 | n[1] << 16 | n[2] << 8 | n[3]; // The nonce value we received in the getWork method is the actual starting nonce value. We start to calculate hashes with this initial nonce and increase it by one in each run. unsigned long nonce = starting_nonce; char * hash; // In practice it is very hard to find a valid hash, so in this exercise we will limit the amount of hashes we calculate. for(;nonce<=(starting_nonce+MAX_HASHES);nonce++) { // put current nonce in blockheader object // first, shift long back to char[4] n[0] = nonce >> 24; n[1] = nonce >> 16; n[2] = nonce >> 8; n[3] = nonce; // reverse byte order byte_reversal(n,sizeof(char)*4); // put n into blockheader blockheader->nonce[0] = n[0]; blockheader->nonce[1] = n[1]; blockheader->nonce[2] = n[2]; blockheader->nonce[3] = n[3]; // calculate the hash using the sha-256 hashing algorithm size_t size = getData(blockheader,&hash); size = sha256_digest(hash,size,&hash); // To calculate a valid hash, we need to do two hashing passes size = sha256_digest(hash,size,&hash); if(check_hash(hash,(int)size)) { printf("%ld : ", nonce); print_hash(hash,size); } } end = current_time_millis(); printf("Calculation finished after %.3fs\n", (double) (end - start) / 1000); free(blockheader); return EXIT_SUCCESS; }
// This function is used to connect to the server. It takes the socket ID and the // server's port number as input parameters. The socket ID is used to find the TCB entry. // This function sets up the TCB's server port number and a SYN segment to send to // the server using snp_sendseg(). After the SYN segment is sent, a timer is started. // If no SYNACK is received after SYNSEG_TIMEOUT timeout, then the SYN is // retransmitted. If SYNACK is received, return 1. Otherwise, if the number of SYNs // sent > SYN_MAX_RETRY, transition to CLOSED state and return -1. // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // int srt_client_connect(int sockfd, unsigned int server_port) { printf("srt_client_connect\n"); if(sockfd < 0 || sockfd > MAX_TRANSPORT_CONNECTIONS || clients[sockfd] == NULL) { printf("Error in srt_client_connect sockfd = %d max clients supported = %d\n", sockfd, MAX_TRANSPORT_CONNECTIONS); return -1; } client_tcb_t *client = clients[sockfd]; seg_t segment; bzero(&segment,sizeof(segment)); segment.header.src_port = client->client_portNum; segment.header.dest_port = client->svr_portNum = server_port; segment.header.type = SYN; segment.header.seq_num = 0; segment.header.length = 0; int trialNum = 0 ; // first trial if(snp_sendseg(mainTcpSockId,&segment) < 0){ // error check for sendseg when there is TCP socket error printf("Error in sending message in TCP layer = %d \n", mainTcpSockId); return -1; } long start_time = current_time_millis(); // timer started trialNum++; // increment trial num client->state = SYNSENT ; while(client->state == SYNSENT){ wait_for_some_time(LOOP_WAITING_TIME); long now = current_time_millis(); long diff = now - start_time ; if((diff ) > SYN_TIMEOUT_MS){ printf("TIMEOUT in connect %d for trial num = %d \n", sockfd, trialNum); if(trialNum < SYN_MAX_RETRY){ printf("resending segment \n"); if(snp_sendseg(mainTcpSockId,&segment) < 0){ // error check for sendseg when there is TCP socket error printf("ERROR in sending message sockfd = %d \n", sockfd); return -1; } start_time = (long)time(NULL); // reset timer trialNum++; }else{ printf("MAX TRIAL reached in connect segment of sock fd %d\n" ,sockfd); client->state = CLOSED; return -1; } } } printf("srt_client_connect ends \n"); fflush(stdout); return 1; // returning success it can be rechecked with state = CONNECTED }
int generate_mandelbrot_simple(const char* filename) { int return_code = EXIT_FAILURE; unsigned long start, end; // Allocate buffer for picture data pixel_data_t *data = calloc(WIDTH * HEIGHT, sizeof(pixel_data_t)); if (data) { // Create and open the output file FILE *file = fopen(filename, "wb"); if (file) { // write the header write_bitmap_header(file, WIDTH, HEIGHT); // init time measurement start = current_time_millis(); // calculate the data for the picture calc_mandelbrot(data, WIDTH, HEIGHT, 0, 0, WIDTH, HEIGHT); // write the data to the file fwrite(data, sizeof(pixel_data_t), WIDTH * HEIGHT, file); // close the file fclose(file); // print the measured time end = current_time_millis(); printf("%.2f seconds\n", (double) (end - start) / 1000); // success return_code = EXIT_SUCCESS; } else { printf("Could not create the output file: %s\n", strerror(errno)); } // free buffer free(data); } else { printf("Could not allocate memory for buffer.\n"); } return return_code; }
void send_unsent_segments(client_tcb_t *client){ pthread_mutex_lock(client->bufMutex); printf("send_unsent_segments starts \n"); while(client->sendBufunSent!=NULL && client->unAck_segNum < GBN_WINDOW){ // 1. send the segment // 2. check if it was succesfull // 3. update the sent time // 4. start the timeout thread if required which means client->unAck_segNum should be zero // 5. switch to next segment if(snp_sendseg(mainTcpSockId,(seg_t*)client->sendBufunSent)){ printf("DATA PACKET SENT sequence number %d sent to server \n",client->sendBufunSent->seg.header.seq_num); client->sendBufunSent->sentTime = current_time_millis(); client->sendBufunSent = client->sendBufunSent->next; if(client->unAck_segNum == 0) { // check printf("TIMEOUT thread create called\n"); pthread_t timeout_thread; pthread_create(&timeout_thread,NULL,sendBuf_timer, (void*)client); } client->unAck_segNum++; printf("UNACKED count = %d \n", client->unAck_segNum); }else{ printf("ERROR (send_unsent_segments) in snp_sendseg exiting TCP error \n"); exit(-1); } } pthread_mutex_unlock(client->bufMutex); printf("send_unsent_segments ends \n"); fflush(stdout); }
int bitcoin_loop(const unsigned int processcount) { printf("\n\nStarting bitcoin_loop\n"); // Start, end time unsigned long start,end; // Set start time start = current_time_millis(); Blockheader * blockheader = malloc(sizeof(Blockheader)); getWork(blockheader); // TODO: Split the calculation of the hashes into several segments based on the processcount int segment_size = ceil((double)MAX_HASHES / processcount); for (int i = 0; i < processcount; i++) { calculate_hash(blockheader, segment_size); //printf("nonce after run #%i: %ld\n", i, toulong(blockheader->nonce)); } end = current_time_millis(); printf("Calculation finished after %.3fs\n", (double) (end - start) / 1000); free(blockheader); return EXIT_SUCCESS; }
void handle_timeout_resend(client_tcb_t *client){ printf("handle_timeout_resend starts\n"); int unack_count = 0 ; segBuf_t *head = client->sendBufHead; pthread_mutex_lock(client->bufMutex); while(head && unack_count < client->unAck_segNum){ if(snp_sendseg(mainTcpSockId,(seg_t*)head)){ printf("DATA PACKET RESENT sequence number %d sent to server total UNACKED = %d \n",head->seg.header.seq_num, client->unAck_segNum ); head->sentTime = current_time_millis(); head = head->next; unack_count++; }else{ printf("ERROR (handle_timeout_resend) in snp_sendseg exiting TCP error \n"); exit(-1); } } pthread_mutex_unlock(client->bufMutex); printf("handle_timeout_resend ends\n"); }
// This thread continuously polls send buffer to trigger timeout events // It should always be running when the send buffer is not empty // If the current time - first sent-but-unAcked segment's sent time > DATA_TIMEOUT, a timeout event occurs // When timeout, resend all sent-but-unAcked segments // When the send buffer is empty, this thread terminates //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ void* sendBuf_timer(void *clienttcb) { client_tcb_t *client = (client_tcb_t *) clienttcb ; printf("TIMEOUT thread started\n"); while(1){ printf("sendBuf_timer sleeping ... \n"); wait_for_some_time(SENDBUF_POLLING_INTERVAL); printf("POLLING sendBuf_timer\n"); if(client->unAck_segNum == 0 || client->state != CONNECTED) { printf("NOTHING to send in timeout buffer hence exiting buffer thread\n"); pthread_exit(NULL); }else{ long currentTime = current_time_millis(); long diff = currentTime - client->sendBufHead->sentTime; if(diff >= DATA_TIMEOUT){ printf("TIMEOUT for sent-but-unAcked\n"); //resend all in buffer handle_timeout_resend(client); } } } return 0; }
int bitcoin_loop(const unsigned int processcount) { printf("\n\nStarting bitcoin_loop\n"); // Start, end time unsigned long start,end; // Set start time start = current_time_millis(); // TODO: Create a Blockheader object and fill it with the initial data using the getWork Method Blockheader * b_header = malloc(sizeof(Blockheader)); getWork(b_header); // TODO: Split the calculation of the hashes into several segments based on the processcount int * pids = malloc(sizeof(int) * processcount); for (int i = 0; i < processcount; i++) { if (i > 0) { if (pids[i - 1] == 0) { break; } } pids[i] = fork(); } if (pids[processcount - 1] != 0) { } int child_pid = 0; int num_process = 0; for (int i = 0; i < processcount - 1; i++) { child_pid = fork(); if (child_pid != 0) break; num_process++; } printf("%i", num_process); calc_hashes((int)floor(MAX_HASHES / processcount)); wait(child_pid); return 0; /*char * n = malloc(sizeof(char) * 4); memcpy(n, &(b_header->nonce), sizeof(char) * 4); byte_reversal(n, sizeof(char) * 4); // copy paste unsigned long starting_nonce = n[0] << 24 | n[1] << 16 | n[2] << 8 | n[3]; starting_nonce += 0; // The nonce value we received in the getWork method is the actual starting nonce value. We start to calculate hashes with this initial nonce and increase it by one in each run. unsigned long nonce = starting_nonce; char * hash; // In practice it is very hard to find a valid hash, so in this exercise we will limit the amount of hashes we calculate. for( ; nonce<=(starting_nonce + MAX_HASHES); nonce++) { // put current nonce in blockheader object // first, shift long back to char[4] n[0] = nonce >> 24; n[1] = nonce >> 16; n[2] = nonce >> 8; n[3] = nonce; // reverse byte order byte_reversal(n,sizeof(char)*4); // put n into blockheader blockheader->nonce[0] = n[0]; blockheader->nonce[1] = n[1]; blockheader->nonce[2] = n[2]; blockheader->nonce[3] = n[3]; // calculate the hash using the sha-256 hashing algorithm size_t size = getData(blockheader,&hash); size = sha256_digest(hash,size,&hash); // To calculate a valid hash, we need to do two hashing passes size = sha256_digest(hash,size,&hash); if(check_hash(hash,(int)size)) { printf("%ld : ", nonce); print_hash(hash,size); } } if(child_pid != 0) wait(child_pid); // TODO: If a hash has the appropriate difficulty (hint: check_hash) print it on the console using print_hash end = current_time_millis(); printf("Calculation finished after %.3fs\n", (double) (end - start) / 1000); return EXIT_FAILURE;*/ }
int generate_mandelbrot_loop(const char* filename) { int return_code = EXIT_FAILURE; unsigned long start, end; // Create and open the output file, write header FILE *file = fopen(filename, "wb"); if (!file) { printf("Could not create the output file: %s\n", strerror(errno)); return return_code; } // write header write_bitmap_header(file, WIDTH, HEIGHT); // close file handler fclose(file); // init time measurement start = current_time_millis(); //return -1; // Loop int i; for (i=1; i<=MAX_PROCESSES; i++) { // Slicing: Slice width, height and offsets int sliceWidth = WIDTH; int sliceHeight = HEIGHT/MAX_PROCESSES; int widthOffset = 0; int heightOffset = (i-1) * sliceHeight; // Allocate buffers for picture data pixel_data_t *data = calloc(sliceWidth * sliceHeight, sizeof(pixel_data_t)); if (data) { // Open the output file FILE *file = fopen(filename, "a+"); if (file) { // calculate the data for the picture calc_mandelbrot(data, WIDTH, HEIGHT, widthOffset, heightOffset, sliceWidth, sliceHeight); // write the data to the file fwrite(data, sizeof(pixel_data_t), sliceWidth * sliceHeight, file); // close the file fclose(file); } else { printf("Could not open the output file: %s\n", strerror(errno)); return return_code; } // free buffer free(data); } else { printf("Could not allocate memory for buffer.\n"); return return_code; } } // print the measured time end = current_time_millis(); printf("\n%.2f seconds\n", (double) (end - start) / 1000); // success return_code = EXIT_SUCCESS; return return_code; }
int generate_mandelbrot_parallel(const char* filename) { int return_code = EXIT_FAILURE; unsigned long start, end; // Create and open the output file, write header FILE *file = fopen(filename, "wb+"); if (!file) { printf("Could not create the output file: %s\n", strerror(errno)); return return_code; } // write header write_bitmap_header(file, WIDTH, HEIGHT); // store header size for later offset long headerOffset = ftell(file); // close file handler fclose(file); // init time measurement start = current_time_millis(); // set up loop and forking variables int i, status; pid_t pid = 1, wpid; for (i=0; i<=MAX_PROCESSES; i++) { if (pid>0) { // in parent process -> fork pid = fork(); } if (pid<0) { // error while forking -> exit program printf("Error while forking: %s\n", strerror(errno)); return return_code; } else if (pid==0) { // in child process -> do image generation work // Slicing: Slice the dimensions of the image into equally sized, horizontal stripes int sliceWidth = WIDTH; int sliceHeight = HEIGHT/MAX_PROCESSES; int widthOffset = 0; int heightOffset = (i-1) * sliceHeight; // Allocate buffers for picture data pixel_data_t *data = calloc(sliceWidth * sliceHeight, sizeof(pixel_data_t)); if (data) { // Open the output file FILE *file = fopen(filename, "rb+"); if (file) { // calculate the data for the picture calc_mandelbrot(data, WIDTH, HEIGHT, widthOffset, heightOffset, sliceWidth, sliceHeight); // seek right position // SizeOfPixel * NumberOfPixels * PositionOfTheCurrentSlice + HeaderSize long byteoffset = sizeof(pixel_data_t)*sliceWidth*sliceHeight*(i-1) + headerOffset; fseek(file, byteoffset, SEEK_SET); // write the data to the file fwrite(data, sizeof(pixel_data_t), sliceWidth * sliceHeight, file); // close the file fclose(file); // exit the process, return to main exit(1); } else { printf("Could not open the output file: %s\n", strerror(errno)); return return_code; } // free buffer free(data); } else { printf("Could not allocate memory for buffer.\n"); return return_code; } } } // wait for children to finish for (i=0; i<MAX_PROCESSES; i++) { wait(&status); } //re-write header in case it got overwritten - yes we know this is a bug. we don't know how to solve it. this gets around the symptoms, it's as good as we got it file = fopen(filename, "rb+"); if (!file) { printf("Could not create the output file: %s\n", strerror(errno)); return return_code; } fseek(file, 0, SEEK_SET); // write header write_bitmap_header(file, WIDTH, HEIGHT); // close file handler fclose(file); // print the measured time end = current_time_millis(); printf("\n%.2f seconds\n", (double) (end - start) / 1000); // success return_code = EXIT_SUCCESS; return return_code; }