/* * Write PCR register. (This is internal function) * It returns PCR register and size in 1/2/4 bytes. * The offset should not exceed 0xFFFF and must be aligned with size */ static int pch_pcr_write(u8 pid, u16 offset, u32 size, u32 data) { if ((offset & (size - 1)) != 0) { printk(BIOS_DEBUG, "PchPcrWrite error. Invalid Offset: %x Size: %x", offset, size); return -1; } /* Write the PCR register with provided data * Then read back PCR register to prevent from back to back write. */ switch (size) { case 4: write32(pcr_reg_address(pid, offset), (u32) data); break; case 2: write16(pcr_reg_address(pid, offset), (u16) data); break; case 1: write8(pcr_reg_address(pid, offset), (u8) data); break; default: return -1; } /* Ensure the writes complete. */ complete_write(); return 0; }
static void complete(iocp_result_t *result, bool success, DWORD num_transferred) { result->iocpd->ops_in_progress--; DWORD status = success ? 0 : GetLastError(); switch (result->type) { case IOCP_ACCEPT: complete_accept((accept_result_t *) result, status); break; case IOCP_CONNECT: complete_connect((connect_result_t *) result, status); break; case IOCP_WRITE: complete_write((write_result_t *) result, num_transferred, status); break; case IOCP_READ: complete_read((read_result_t *) result, num_transferred, status); break; default: assert(false); } }
void* handle_connection(void* client_connection_info) { int new_listening_socket = socket(AF_INET, SOCK_DGRAM, 0); int block_num = 0; FILE *fp; struct connection_info *conn_info = client_connection_info; unsigned short opcode = conn_info->opcode; strcpy(filename, conn_info->file); struct sockaddr_in client = conn_info->client; char buffer[BUFFER_LENGTH]; // temp storage of packets received int fromlen; if (opcode == OPCODE_READ) { block_num++; // In contrast to WRQ, block number begins at 1 and not 0 char *file_contents_buffer; // Buffer used to store contents of file size_t file_size; // Size of the file // don't need a mutex when reading from files fp = fopen(filename, "rb"); // open file for reading fseek(fp, 0, SEEK_END); file_size = ftell(fp); // get the size of the file rewind(fp); // set our filestream back to the top of the file instead of the bottom file_contents_buffer = malloc(file_size * (sizeof(char))); // allocate buffer size to hold contents of file fread(file_contents_buffer, sizeof(char), file_size, fp); // read the contents of the file into the buffer fclose(fp); int payload_length = MAX_PAYLOAD_LENGTH; if (file_size < MAX_PAYLOAD_LENGTH) // Always check the size of the file in case the file is small enough to transfer just one packet with reduced size { payload_length = file_size; } char packet[4+payload_length]; // 516 bytes (4 bytes for opcode and blocknum + payload) is the bzero(packet, 4+payload_length); set_opcode(packet, OPCODE_DATA); // default for data packets, but our file size might be small enough forless set_block_num(packet, block_num); memcpy(packet+4, file_contents_buffer, payload_length); // Create our first packet of data sendto(new_listening_socket, packet, sizeof(packet), 0, &client, sizeof(client)); // Send our first data packet // Keep receiving requests while keeping track of block number int new_msg_len; int offset = 1; int retransmit_attempts = 0; int sent_last_packet = 0; int dont_exit = 1; while(dont_exit) { unsigned short op_code; unsigned short block; bzero(buffer, BUFFER_LENGTH); // Set all contents of the buffer to contain 0s new_msg_len = recvfrom(new_listening_socket,buffer,BUFFER_LENGTH,0,(struct sockaddr *)&client,(socklen_t *)&fromlen); if (new_msg_len < 0) { continue; } op_code = ntohs(*(unsigned short int*)&buffer); block = buffer[2] << 8 | buffer[3]; if (op_code == OPCODE_ERROR) { fprintf(stderr,"Error received, exiting.\n"); close(new_listening_socket); dont_exit = 0; } else if (op_code == OPCODE_ACK) { // we are receiving the proper ack packet, proceed transmitting data normally if (block == block_num && !sent_last_packet) { retransmit_attempts = 0; block_num++; if (file_size-offset*payload_length < payload_length) { payload_length = file_size-offset*payload_length; } char data_packet[4+payload_length]; // Only create a data packet as large as needed to contain the remaining file data set_opcode(data_packet, OPCODE_DATA); set_block_num(data_packet, block_num); memcpy(data_packet+4, file_contents_buffer+offset*MAX_PAYLOAD_LENGTH, payload_length); sendto(new_listening_socket, data_packet, sizeof(data_packet), 0, &client, sizeof(client)); // We have sent our last packet if (sizeof(data_packet) < 516) { sent_last_packet = 1; } offset++; } // a packet was lost somewhere, retransmit last packet else if ((block != block_num) && (retransmit_attempts < 5) && !sent_last_packet) { offset--; if (file_size-offset*payload_length < payload_length) { payload_length = file_size-offset*payload_length; } char data_packet[4+payload_length]; // Only create a data packet as large as needed to contain the remaining file data set_opcode(data_packet, OPCODE_DATA); set_block_num(data_packet, block_num); memcpy(data_packet+4, file_contents_buffer+offset*MAX_PAYLOAD_LENGTH, payload_length); sendto(new_listening_socket, data_packet, sizeof(data_packet), 0, &client, sizeof(client)); offset++; retransmit_attempts++; } // We've transmitted the same packet 5 times and are timing out, or we've sent our last packet else { fprintf(stderr,"Thread %d exiting.\n", pthread_self()); close(new_listening_socket); fclose(fp); dont_exit = 0; } } } } else if (opcode == OPCODE_WRITE) { char temp_filename[80]; // arbitrarily large filename to specify filename+directory strcpy(temp_filename, "temp"); // add temp directory to empty string strcat(temp_filename, filename); // concatenate temp directory with unique filename // This is a temporary file for writing to while receiving packets, so as to // only display the final file when all data has been written pthread_mutex_lock(&temp_file_mutex); // Lock the temp file from any other thread fp = fopen(temp_filename, "wb"); char packet[MAX_PAYLOAD_LENGTH]; set_opcode(packet, OPCODE_ACK); set_block_num(packet, block_num); // We've already confirmed we just received a WRQ and that the file doesn't exist already // Send an ACK packet // sendto without binding first will bind to random port, allowing for concurrency sendto(new_listening_socket, packet, sizeof(packet), 0, &client, sizeof(client)); block_num++; // Keep receiving requests while keeping track of block number int new_msg_len; int dont_exit = 1; while(dont_exit) { unsigned short op_code; unsigned short block; bzero(buffer, BUFFER_LENGTH); // Set all contents of the buffer to contain 0s new_msg_len = recvfrom(new_listening_socket,buffer,BUFFER_LENGTH,0,(struct sockaddr *)&client,(socklen_t *)&fromlen); if (new_msg_len < 0) { continue; } op_code = ntohs(*(unsigned short int*)&buffer); block = buffer[2] << 8 | buffer[3]; // Concatenate upper and lower halves of the block into one short if (op_code == OPCODE_ERROR) { fprintf(stderr,"Error received, exiting.\n"); close(new_listening_socket); fclose(fp); pthread_mutex_unlock(&temp_file_mutex); dont_exit = 0; } else if (op_code == OPCODE_DATA) { set_opcode(packet, OPCODE_ACK); set_block_num(packet, block_num); char payload[new_msg_len-HEADER_SIZE]; // Source, size per element in bytes, # of elements, filestream memcpy(payload, buffer+HEADER_SIZE, sizeof(payload)); fwrite(payload, 1, sizeof(payload), fp); sendto(new_listening_socket, packet, sizeof(packet), 0, &client, sizeof(client)); block_num++; } // Last packet received, child process should exit if (new_msg_len < MAX_PAYLOAD_LENGTH) { close(fp); pthread_mutex_unlock(&temp_file_mutex); // Transfer contents of temp file into correct file // Do this by looping through the temp file and copying into destination file complete_write(filename, temp_filename); close(new_listening_socket); dont_exit = 0; } } } return 0; }