Пример #1
0
/*
 * 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;
}
Пример #2
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);
  }
}
Пример #3
0
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;
    
}